Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: ui/webui/resources/js/cr/ui/page_manager/page_manager.js

Issue 410293004: Split OptionsPage into Page and PageManager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: s/PageTree/PageManager/, s/pageHelper/pageManager/ Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
stevenjb 2014/07/28 22:27:23 We should provide some sort of top level comment d
michaelpg 2014/07/29 01:08:31 How's this?
5 cr.define('cr.ui.pageManager', function() {
6 /** @const */ var FocusOutlineManager = cr.ui.FocusOutlineManager;
7
8 var PageManager = {
9 /**
10 * Offset of page container in pixels, to allow room for side menu.
11 * Simplified settings pages can override this if they don't use the menu.
12 * The default (155) comes from -webkit-margin-start in uber_shared.css
13 * TODO(michaelpg@): Remove dependency on uber menu (crbug.com/313244).
stevenjb 2014/07/28 22:27:23 TODO(michaelpg)
michaelpg 2014/07/29 01:08:30 Done.
14 * @private
15 */
16 horizontalOffset: 155,
17
18 /**
19 * Main level option pages. Maps lower-case page names to the respective
20 * page object.
21 * @protected
22 */
23 registeredPages: {},
24
25 /**
26 * Pages which are meant to behave like modal dialogs. Maps lower-case
27 * overlay names to the respective overlay object.
28 * @protected
29 */
30 registeredOverlayPages: {},
31
32 /**
33 * True if page is served from a dialog.
34 */
35 isDialog: false,
36
37 /**
38 * Gets the default page (to be shown on initial load).
39 */
40 getDefaultPage: function() {
41 return options.BrowserOptions.getInstance();
Dan Beam 2014/07/28 20:57:59 this should probably be abstract (e.g. just assert
michaelpg 2014/07/29 01:08:31 I'd rather not derive from PageManager, instead Op
42 },
43
44 /**
45 * Shows the default page.
46 */
47 showDefaultPage: function() {
48 this.navigateToPage(this.getDefaultPage().name);
49 },
50
51 /**
52 * "Navigates" to a page, meaning that the page will be shown and the
53 * appropriate entry is placed in the history.
54 * @param {string} pageName Page name.
55 */
56 navigateToPage: function(pageName) {
57 this.showPageByName(pageName, true);
stevenjb 2014/07/28 22:27:22 JS novice question: Could this be done by giving u
michaelpg 2014/07/29 01:08:30 Done.
58 },
59
60 /**
61 * Shows a registered page. This handles both top-level and overlay pages.
62 * @param {string} pageName Page name.
63 * @param {boolean} updateHistory True if we should update the history after
64 * showing the page.
65 * @param {Object=} opt_propertyBag An optional bag of properties including
66 * replaceState (if history state should be replaced instead of pushed).
67 * @private
Dan Beam 2014/07/28 20:58:00 this isn't private
michaelpg 2014/07/29 01:08:31 Done.
68 */
69 showPageByName: function(pageName,
70 updateHistory,
71 opt_propertyBag) {
72 // If |opt_propertyBag| is non-truthy, homogenize to object.
73 opt_propertyBag = opt_propertyBag || {};
stevenjb 2014/07/28 22:27:23 JS novice question: Is this preferable to declarin
michaelpg 2014/07/29 01:08:30 Not sure what you are asking exactly: function(fo
Dan Beam 2014/07/30 01:00:01 opt_propertyBag = opt_propertyBag || {}; simplifi
stevenjb 2014/07/30 22:36:21 Nevermind. I somehow thought you could provide def
74
75 // If a bubble is currently being shown, hide it.
76 this.hideBubble();
77
78 // Find the currently visible root-level page.
79 var rootPage = null;
80 for (var name in this.registeredPages) {
81 var page = this.registeredPages[name];
82 if (page.visible && !page.parentPage) {
83 rootPage = page;
84 break;
85 }
86 }
87
88 // Find the target page.
89 var targetPage = this.registeredPages[pageName.toLowerCase()];
90 if (!targetPage || !targetPage.canShowPage()) {
91 // If it's not a page, try it as an overlay.
92 if (!targetPage && this.showOverlay_(pageName, rootPage)) {
93 if (updateHistory)
94 this.updateHistoryState_(!!opt_propertyBag.replaceState);
95 this.updateTitle_();
96 return;
97 } else {
stevenjb 2014/07/28 22:27:23 nit: no else after return
michaelpg 2014/07/29 01:08:30 Done.
98 targetPage = this.getDefaultPage();
99 }
100 }
101
102 pageName = targetPage.name.toLowerCase();
103 var targetPageWasVisible = targetPage.visible;
104
105 // Determine if the root page is 'sticky', meaning that it
106 // shouldn't change when showing an overlay. This can happen for special
107 // pages like Search.
108 var isRootPageLocked =
109 rootPage && rootPage.sticky && targetPage.parentPage;
110
111 var allPageNames = Array.prototype.concat.call(
112 Object.keys(this.registeredPages),
113 Object.keys(this.registeredOverlayPages));
114
115 // Notify pages if they will be hidden.
116 for (var i = 0; i < allPageNames.length; ++i) {
117 var name = allPageNames[i];
118 var page = this.registeredPages[name] ||
119 this.registeredOverlayPages[name];
120 if (!page.parentPage && isRootPageLocked)
121 continue;
122 if (page.willHidePage && name != pageName &&
123 !page.isAncestorOfPage(targetPage)) {
124 page.willHidePage();
125 }
126 }
127
128 // Update visibilities to show only the hierarchy of the target page.
129 for (var i = 0; i < allPageNames.length; ++i) {
130 var name = allPageNames[i];
131 var page = this.registeredPages[name] ||
132 this.registeredOverlayPages[name];
133 if (!page.parentPage && isRootPageLocked)
134 continue;
135 page.visible = name == pageName || page.isAncestorOfPage(targetPage);
136 }
137
138 // Update the history and current location.
139 if (updateHistory)
140 this.updateHistoryState_(!!opt_propertyBag.replaceState);
141
142 // Update focus if any other control was focused on the previous page,
143 // or the previous page is not known.
144 if (document.activeElement != document.body &&
145 (!rootPage || rootPage.pageDiv.contains(document.activeElement))) {
146 targetPage.focus();
147 }
148
149 // Notify pages if they were shown.
150 for (var i = 0; i < allPageNames.length; ++i) {
151 var name = allPageNames[i];
152 var page = this.registeredPages[name] ||
153 this.registeredOverlayPages[name];
154 if (!page.parentPage && isRootPageLocked)
155 continue;
stevenjb 2014/07/28 22:27:22 nit: We use the same pattern 3 times here, maybe c
michaelpg 2014/07/29 01:08:31 Sure. But I don't want to stray too far from the o
156 if (!targetPageWasVisible && page.didShowPage &&
157 (name == pageName || page.isAncestorOfPage(targetPage))) {
158 page.didShowPage();
159 }
160 }
161
162 // Update the document title. Do this after didShowPage was called, in
163 // case a page decides to change its title.
164 this.updateTitle_();
165 },
166
167 /**
168 * Scrolls the page to the correct position (the top when opening an
169 * overaly, or the old scroll position a previously hidden overlay
170 * becomes visible).
171 * @private
172 */
173 updateScrollPosition_: function() {
174 var container = $('page-container');
175 var scrollTop = container.oldScrollTop || 0;
176 container.oldScrollTop = undefined;
177 window.scroll(scrollLeftForDocument(document), scrollTop);
178 },
179
180 /**
181 * Updates the title to title of the current page.
182 * @private
183 */
184 updateTitle_: function() {
185 var page = this.getTopmostVisiblePage();
186 // TODO(michaelpg@): Remove dependency on uber (crbug.com/313244).
Dan Beam 2014/07/28 20:58:00 same thing regarding uber deps: you should be able
stevenjb 2014/07/28 22:27:23 TODO(michaelpg)
michaelpg 2014/07/29 01:08:30 Done.
michaelpg 2014/07/29 01:08:30 Yes, setting up an observer interface was my plan.
187 uber.setTitle(page.title);
188 },
189
190 /**
191 * Pushes the current page onto the history stack, replacing the current
192 * entry if appropriate.
193 * @param {boolean} replace If true, allow no history events to be created.
194 * @param {object=} opt_params A bag of optional params, including:
195 * {boolean} ignoreHash Whether to include the hash or not.
196 * @private
197 */
198 updateHistoryState_: function(replace, opt_params) {
199 if (PageManager.isDialog)
200 return;
201
202 var page = this.getTopmostVisiblePage();
203 var path = window.location.pathname + window.location.hash;
204 if (path) {
205 // Remove trailing slash.
206 path = path.slice(1).replace(/\/(?:#|$)/, '');
207 }
208
209 // If the page is already in history (the user may have clicked the same
210 // link twice, or this is the initial load), do nothing.
211 var hash = opt_params && opt_params.ignoreHash ?
212 '' : window.location.hash;
213 var newPath = (page == this.getDefaultPage() ? '' : page.name) + hash;
214 if (path == newPath)
215 return;
216
217 // TODO(michaelpg@): Remove dependency on uber (crbug.com/313244).
stevenjb 2014/07/28 22:27:22 TODO(michaelpg)
michaelpg 2014/07/29 01:08:30 Done.
218 var historyFunction = replace ? uber.replaceState : uber.pushState;
219 historyFunction.call(uber, {}, newPath);
220 },
221
222 /**
223 * Shows a registered Overlay page. Does not update history.
224 * @param {string} overlayName Page name.
225 * @param {OptionPage} rootPage The currently visible root-level page.
226 * @return {boolean} whether we showed an overlay.
Dan Beam 2014/07/28 20:57:59 all the methods that end with _ => @private
michaelpg 2014/07/29 01:08:30 Done.
227 */
228 showOverlay_: function(overlayName, rootPage) {
229 var overlay = this.registeredOverlayPages[overlayName.toLowerCase()];
230 if (!overlay || !overlay.canShowPage())
231 return false;
232
233 // Save the currently focused element in the page for restoration later.
234 var currentPage = this.getTopmostVisiblePage();
235 if (currentPage)
236 currentPage.lastFocusedElement = document.activeElement;
237
238 if ((!rootPage || !rootPage.sticky) &&
239 overlay.parentPage &&
240 !overlay.parentPage.visible) {
241 this.showPageByName(overlay.parentPage.name, false);
242 }
243
244 if (!overlay.visible) {
245 overlay.visible = true;
246 if (overlay.didShowPage) overlay.didShowPage();
stevenjb 2014/07/28 22:27:23 nit: two lines? (Or is that a C++ only thing?)
michaelpg 2014/07/29 01:08:30 This isn't my code, but I think two lines is the c
247 }
248
249 // Change focus to the overlay if any other control was focused by
250 // keyboard before. Otherwise, no one should have focus.
251 if (document.activeElement != document.body) {
252 if (FocusOutlineManager.forDocument(document).visible) {
253 overlay.focus();
254 } else if (!overlay.pageDiv.contains(document.activeElement)) {
255 document.activeElement.blur();
256 }
257 }
258
259 if ($('search-field') && $('search-field').value == '') {
260 var section = overlay.associatedSection;
261 if (section)
262 options.BrowserOptions.scrollToSection(section);
263 }
264
265 return true;
266 },
267
268 /**
269 * Returns whether or not an overlay is visible.
270 * @return {boolean} True if an overlay is visible.
271 * @private
272 */
273 isOverlayVisible_: function() {
274 return this.getVisibleOverlay_() != null;
275 },
276
277 /**
278 * Returns the currently visible overlay, or null if no page is visible.
279 * @return {OptionPage} The visible overlay.
280 */
281 getVisibleOverlay_: function() {
282 var topmostPage = null;
283 for (var name in this.registeredOverlayPages) {
284 var page = this.registeredOverlayPages[name];
285 if (page.visible &&
286 (!topmostPage || page.nestingLevel > topmostPage.nestingLevel)) {
287 topmostPage = page;
288 }
289 }
290 return topmostPage;
291 },
292
293 /**
294 * Restores the last focused element on a given page.
295 */
296 restoreLastFocusedElement_: function() {
297 var currentPage = this.getTopmostVisiblePage();
298 if (currentPage.lastFocusedElement)
299 currentPage.lastFocusedElement.focus();
300 },
301
302 /**
303 * Closes the visible overlay. Updates the history state after closing the
304 * overlay.
305 */
306 closeOverlay: function() {
307 var overlay = this.getVisibleOverlay_();
308 if (!overlay)
309 return;
310
311 overlay.visible = false;
312
313 if (overlay.didClosePage) overlay.didClosePage();
stevenjb 2014/07/28 22:27:22 two lines?
michaelpg 2014/07/29 01:08:30 Done.
Dan Beam 2014/07/30 01:00:01 for future reference, 2 lines is more common but 1
314 this.updateHistoryState_(false, {ignoreHash: true});
315 this.updateTitle_();
316
317 this.restoreLastFocusedElement_();
318 },
319
320 /**
321 * Closes all overlays and updates the history after each closed overlay.
322 */
323 closeAllOverlays: function() {
324 while (this.isOverlayVisible_()) {
325 this.closeOverlay();
326 }
327 },
328
329 /**
330 * Cancels (closes) the overlay, due to the user pressing <Esc>.
331 */
332 cancelOverlay: function() {
333 // Blur the active element to ensure any changed pref value is saved.
334 document.activeElement.blur();
335 var overlay = this.getVisibleOverlay_();
336 // Let the overlay handle the <Esc> if it wants to.
337 if (overlay.handleCancel) {
338 overlay.handleCancel();
339 this.restoreLastFocusedElement_();
340 } else {
341 this.closeOverlay();
342 }
343 },
344
345 /**
346 * Hides the visible overlay. Does not affect the history state.
347 * @private
348 */
349 hideOverlay_: function() {
350 var overlay = this.getVisibleOverlay_();
351 if (overlay)
352 overlay.visible = false;
353 },
354
355 /**
356 * Returns the pages which are currently visible, ordered by nesting level
357 * (ascending).
358 * @return {Array.OptionPage} The pages which are currently visible, ordered
359 * by nesting level (ascending).
360 */
361 getVisiblePages_: function() {
362 var visiblePages = [];
363 for (var name in this.registeredPages) {
364 var page = this.registeredPages[name];
365 if (page.visible)
366 visiblePages[page.nestingLevel] = page;
367 }
368 return visiblePages;
369 },
370
371 /**
372 * Returns the topmost visible page (overlays excluded).
373 * @return {OptionPage} The topmost visible page aside any overlay.
374 * @private
375 */
376 getTopmostVisibleNonOverlayPage_: function() {
377 var topPage = null;
378 for (var name in this.registeredPages) {
379 var page = this.registeredPages[name];
380 if (page.visible &&
381 (!topPage || page.nestingLevel > topPage.nestingLevel))
382 topPage = page;
383 }
384
385 return topPage;
386 },
387
388 /**
389 * Returns the topmost visible page, or null if no page is visible.
390 * @return {OptionPage} The topmost visible page.
391 */
392 getTopmostVisiblePage: function() {
393 // Check overlays first since they're top-most if visible.
394 return this.getVisibleOverlay_() ||
395 this.getTopmostVisibleNonOverlayPage_();
396 },
397
398 /**
399 * Returns the currently visible bubble, or null if no bubble is visible.
400 * @return {AutoCloseBubble} The bubble currently being shown.
401 */
402 getVisibleBubble: function() {
403 var bubble = PageManager.bubble_;
404 return bubble && !bubble.hidden ? bubble : null;
405 },
406
407 /**
408 * Shows an informational bubble displaying |content| and pointing at the
409 * |target| element. If |content| has focusable elements, they join the
410 * current page's tab order as siblings of |domSibling|.
411 * @param {HTMLDivElement} content The content of the bubble.
412 * @param {HTMLElement} target The element at which the bubble points.
413 * @param {HTMLElement} domSibling The element after which the bubble is
414 * added to the DOM.
415 * @param {cr.ui.ArrowLocation} location The arrow location.
416 */
417 showBubble: function(content, target, domSibling, location) {
418 PageManager.hideBubble();
419
420 var bubble = new cr.ui.AutoCloseBubble;
421 bubble.anchorNode = target;
422 bubble.domSibling = domSibling;
423 bubble.arrowLocation = location;
424 bubble.content = content;
425 bubble.show();
426 PageManager.bubble_ = bubble;
427 },
428
429 /**
430 * Hides the currently visible bubble, if any.
431 */
432 hideBubble: function() {
433 if (PageManager.bubble_)
434 PageManager.bubble_.hide();
435 },
436
437 /**
438 * Registers new page.
439 * @param {cr.ui.page_manager.Page} page Page to register.
440 */
441 register: function(page) {
442 this.registeredPages[page.name.toLowerCase()] = page;
443 page.initializePage();
444 },
445
446 /**
447 * Find an enclosing section for an element if it exists.
448 * @param {Element} element Element to search.
449 * @return {OptionPage} The section element, or null.
450 * @private
451 */
452 findSectionForNode_: function(node) {
453 while (node = node.parentNode) {
454 if (node.nodeName == 'SECTION')
455 return node;
456 }
457 return null;
458 },
459
460 /**
461 * Registers a new Overlay page.
462 * @param {cr.ui.page_manager.Page} overlay Overlay to register.
463 * @param {cr.ui.page_manager.Page} parentPage Associated parent page for
464 * this overlay.
465 * @param {Array} associatedControls Array of control elements associated
466 * with this page.
467 */
468 registerOverlay: function(overlay,
469 parentPage,
470 associatedControls) {
471 this.registeredOverlayPages[overlay.name.toLowerCase()] = overlay;
472 overlay.parentPage = parentPage;
473 if (associatedControls) {
474 overlay.associatedControls = associatedControls;
475 if (associatedControls.length) {
476 overlay.associatedSection =
477 this.findSectionForNode_(associatedControls[0]);
478 }
479
480 // Sanity check.
481 for (var i = 0; i < associatedControls.length; ++i) {
482 assert(associatedControls[i], 'Invalid element passed.');
483 }
484 }
485
486 // Reverse the button strip for Windows and CrOS. See the documentation of
487 // reverseButtonStripIfNecessary_() for an explanation of why this is
488 // done.
489 if (cr.isWindows || cr.isChromeOS)
490 this.reverseButtonStripIfNecessary_(overlay);
491
492 overlay.tab = undefined;
493 overlay.isOverlay = true;
494 overlay.initializePage();
495 },
496
497 /**
498 * Reverses the child elements of a button strip if it hasn't already been
499 * reversed. This is necessary because WebKit does not alter the tab order
500 * for elements that are visually reversed using
501 * -webkit-box-direction: reverse, and the button order is reversed for
502 * views. See http://webk.it/62664 for more information.
503 * @param {Object} overlay The overlay containing the button strip to
504 * reverse.
505 * @private
506 */
507 reverseButtonStripIfNecessary_: function(overlay) {
508 var buttonStrips =
509 overlay.pageDiv.querySelectorAll('.button-strip:not([reversed])');
510
511 // Reverse all button-strips in the overlay.
512 for (var j = 0; j < buttonStrips.length; j++) {
513 var buttonStrip = buttonStrips[j];
514
515 var childNodes = buttonStrip.childNodes;
516 for (var i = childNodes.length - 1; i >= 0; i--)
517 buttonStrip.appendChild(childNodes[i]);
518
519 buttonStrip.setAttribute('reversed', '');
520 }
521 },
522
523 /**
524 * Returns the name of the page from the current path.
525 */
526 getPageNameFromPath: function() {
527 var path = location.pathname;
528 if (path.length <= 1)
529 return this.getDefaultPage().name;
530
531 // Skip starting slash and remove trailing slash (if any).
532 return path.slice(1).replace(/\/$/, '');
533 },
534
535 /**
536 * Callback for window.onpopstate to handle back/forward navigations.
537 * @param {string} pageName The current page name.
538 * @param {Object} data State data pushed into history.
539 */
540 setState: function(pageName, data) {
541 var currentOverlay = this.getVisibleOverlay_();
542 var lowercaseName = pageName.toLowerCase();
543 var newPage = this.registeredPages[lowercaseName] ||
544 this.registeredOverlayPages[lowercaseName] ||
545 this.getDefaultPage();
546 if (currentOverlay && !currentOverlay.isAncestorOfPage(newPage)) {
547 currentOverlay.visible = false;
548 if (currentOverlay.didClosePage) currentOverlay.didClosePage();
549 }
550 this.showPageByName(pageName, false);
551 },
552
553 /**
554 * Callback for window.onbeforeunload. Used to notify overlays that they
555 * will be closed.
556 */
557 willClose: function() {
558 var overlay = this.getVisibleOverlay_();
559 if (overlay && overlay.didClosePage)
560 overlay.didClosePage();
561 },
562
563 /**
564 * Freezes/unfreezes the scroll position of the root page container.
565 * @param {boolean} freeze Whether the page should be frozen.
566 * @private
567 */
568 setRootPageFrozen_: function(freeze) {
569 var container = $('page-container');
570 if (container.classList.contains('frozen') == freeze)
571 return;
572
573 if (freeze) {
574 // Lock the width, since auto width computation may change.
575 container.style.width = window.getComputedStyle(container).width;
576 container.oldScrollTop = scrollTopForDocument(document);
577 container.classList.add('frozen');
578 var verticalPosition =
579 container.getBoundingClientRect().top - container.oldScrollTop;
580 container.style.top = verticalPosition + 'px';
581 this.updateFrozenElementHorizontalPosition_(container);
582 } else {
583 container.classList.remove('frozen');
584 container.style.top = '';
585 container.style.left = '';
586 container.style.right = '';
587 container.style.width = '';
588 }
589 },
590
591 /**
592 * Freezes/unfreezes the scroll position of the root page based on the
593 * current page stack.
594 */
595 updateRootPageFreezeState: function() {
596 var topPage = PageManager.getTopmostVisiblePage();
597 if (topPage)
598 this.setRootPageFrozen_(topPage.isOverlay);
599 },
600
601 /**
602 * Initializes the complete page.
603 */
604 initialize: function() {
605 FocusOutlineManager.forDocument(document);
606 document.addEventListener('scroll', this.handleScroll_.bind(this));
607
608 // Trigger the scroll handler manually to set the initial state.
609 this.handleScroll_();
610
611 // Shake the dialog if the user clicks outside the dialog bounds.
612 var containers = [$('overlay-container-1'), $('overlay-container-2')];
613 for (var i = 0; i < containers.length; i++) {
614 var overlay = containers[i];
615 cr.ui.overlay.setupOverlay(overlay);
616 overlay.addEventListener('cancelOverlay',
617 PageManager.cancelOverlay.bind(PageManager));
618 }
619
620 cr.ui.overlay.globalInitialization();
621 },
622
623 /**
624 * Does a bounds check for the element on the given x, y client coordinates.
625 * @param {Element} e The DOM element.
626 * @param {number} x The client X to check.
627 * @param {number} y The client Y to check.
628 * @return {boolean} True if the point falls within the element's bounds.
629 * @private
630 */
631 elementContainsPoint_: function(e, x, y) {
632 var clientRect = e.getBoundingClientRect();
633 return x >= clientRect.left && x <= clientRect.right &&
634 y >= clientRect.top && y <= clientRect.bottom;
635 },
636
637 /**
638 * Called when the page is scrolled; moves elements that are position:fixed
639 * but should only behave as if they are fixed for vertical scrolling.
640 * @private
641 */
642 handleScroll_: function() {
643 this.updateAllFrozenElementPositions_();
644 },
645
646 /**
647 * Updates all frozen pages to match the horizontal scroll position.
648 * @private
649 */
650 updateAllFrozenElementPositions_: function() {
651 var frozenElements = document.querySelectorAll('.frozen');
652 for (var i = 0; i < frozenElements.length; i++)
653 this.updateFrozenElementHorizontalPosition_(frozenElements[i]);
654 },
655
656 /**
657 * Updates the given frozen element to match the horizontal scroll position.
658 * @param {HTMLElement} e The frozen element to update.
659 * @private
660 */
661 updateFrozenElementHorizontalPosition_: function(e) {
662 if (isRTL()) {
663 e.style.right = PageManager.horizontalOffset + 'px';
664 } else {
665 var scrollLeft = scrollLeftForDocument(document);
666 e.style.left = PageManager.horizontalOffset - scrollLeft + 'px';
667 }
668 },
669
670 /**
671 * Change the horizontal offset used to reposition elements while showing an
672 * overlay from the default.
673 */
674 setHorizontalOffset: function(value) {
675 PageManager.horizontalOffset = value;
676 },
677
678 /**
679 * Whether the page is still loading (i.e. onload hasn't finished running).
680 * @return {boolean} Whether the page is still loading.
681 */
682 isLoading: function() {
683 return document.documentElement.classList.contains('loading');
684 },
Dan Beam 2014/07/28 20:58:00 arguably these methods should be in public => prot
michaelpg 2014/07/29 01:08:31 Done. And I tried to arrange related methods toget
685 };
686
687 // Export
688 return {
689 PageManager: PageManager
690 };
691 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698