172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickcr.define('options', function() { 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ///////////////////////////////////////////////////////////////////////////// 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // OptionsPage class: 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Base class for options page. 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @constructor 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @param {string} name Options page name, also defines id of the div element 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * containing the options view and the name of options page navigation bar 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * item as name+'PageNav'. 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @param {string} title Options page title, used for navigation bar 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @extends {EventTarget} 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick function OptionsPage(name, title, pageDivName) { 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.name = name; 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.title = title; 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.pageDivName = pageDivName; 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.pageDiv = $(this.pageDivName); 233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.tab = null; 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.managed = false; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const SUBPAGE_SHEET_COUNT = 2; 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /** 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Main level option pages. 3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @protected 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OptionsPage.registeredPages = {}; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /** 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch * Pages which are meant to behave like modal dialogs. 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @protected 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OptionsPage.registeredOverlayPages = {}; 403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * Whether or not |initialize| has been called. 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @private 44201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch */ 45201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch OptionsPage.initialized_ = false; 46201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 47201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch /** 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Gets the default page (to be shown on initial load). 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.getDefaultPage = function() { 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return BrowserOptions.getInstance(); 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Shows the default page. 5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.showDefaultPage = function() { 5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.navigateToPage(this.getDefaultPage().name); 5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * "Navigates" to a page, meaning that the page will be shown and the 6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * appropriate entry is placed in the history. 6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {string} pageName Page name. 6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.navigateToPage = function(pageName) { 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.showPageByName(pageName, true); 6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch * Shows a registered page. This handles both top-level pages and sub-pages. 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @param {string} pageName Page name. 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {boolean} updateHistory True if we should update the history after 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * showing the page. 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @private 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.showPageByName = function(pageName, updateHistory) { 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Find the currently visible root-level page. 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var rootPage = null; 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (var name in this.registeredPages) { 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var page = this.registeredPages[name]; 82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (page.visible && !page.parentPage) { 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen rootPage = page; 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Find the target page. 8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var targetPage = this.registeredPages[pageName]; 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!targetPage || !targetPage.canShowPage()) { 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If it's not a page, try it as an overlay. 92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!targetPage && this.showOverlay_(pageName, rootPage)) { 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (updateHistory) 9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.updateHistoryState_(); 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen targetPage = this.getDefaultPage(); 9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen pageName = targetPage.name; 10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Determine if the root page is 'sticky', meaning that it 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // shouldn't change when showing a sub-page. This can happen for special 10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // pages like Search. 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var isRootPageLocked = 10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen rootPage && rootPage.sticky && targetPage.parentPage; 10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Notify pages if they will be hidden. 11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (var name in this.registeredPages) { 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var page = this.registeredPages[name]; 11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!page.parentPage && isRootPageLocked) 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen continue; 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (page.willHidePage && name != pageName && 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen !page.isAncestorOfPage(targetPage)) 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen page.willHidePage(); 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Update visibilities to show only the hierarchy of the target page. 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (var name in this.registeredPages) { 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var page = this.registeredPages[name]; 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!page.parentPage && isRootPageLocked) 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen continue; 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen page.visible = name == pageName || 125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (!document.documentElement.classList.contains('hide-menu') && 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen page.isAncestorOfPage(targetPage)); 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Update the history and current location. 13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (updateHistory) 13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.updateHistoryState_(); 13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Always update the page title. 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen document.title = targetPage.title; 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Notify pages if they were shown. 13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (var name in this.registeredPages) { 13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var page = this.registeredPages[name]; 13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!page.parentPage && isRootPageLocked) 14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen continue; 14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (page.didShowPage && (name == pageName || 14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen page.isAncestorOfPage(targetPage))) 14321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen page.didShowPage(); 1444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Updates the visibility and stacking order of the subpage backdrop 149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * according to which subpage is topmost and visible. 150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.updateSubpageBackdrop_ = function () { 153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var topmostPage = this.getTopmostVisibleNonOverlayPage_(); 154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var nestingLevel = topmostPage ? topmostPage.nestingLevel : 0; 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var subpageBackdrop = $('subpage-backdrop'); 157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (nestingLevel > 0) { 158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var container = $('subpage-sheet-container-' + nestingLevel); 159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen subpageBackdrop.style.zIndex = 160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen parseInt(window.getComputedStyle(container).zIndex) - 1; 161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen subpageBackdrop.hidden = false; 162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen subpageBackdrop.hidden = true; 164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Pushes the current page onto the history stack, overriding the last page 16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * if it is the generic chrome://settings/. 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @private 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.updateHistoryState_ = function() { 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var page = this.getTopmostVisiblePage(); 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var path = location.pathname; 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (path) 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen path = path.slice(1); 17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The page is already in history (the user may have clicked the same link 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // twice). Do nothing. 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (path == page.name) 18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If there is no path, the current location is chrome://settings/. 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Override this with the new page. 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var historyFunction = path ? window.history.pushState : 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen window.history.replaceState; 18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen historyFunction.call(window.history, 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen {pageName: page.name}, 18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen page.title, 18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen '/' + page.name); 19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Update tab title. 19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen document.title = page.title; 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /** 19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Shows a registered Overlay page. Does not update history. 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @param {string} overlayName Page name. 197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {OptionPage} rootPage The currently visible root-level page. 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @return {boolean} whether we showed an overlay. 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.showOverlay_ = function(overlayName, rootPage) { 20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var overlay = this.registeredOverlayPages[overlayName]; 20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!overlay || !overlay.canShowPage()) 20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ((!rootPage || !rootPage.sticky) && overlay.parentPage) 20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.showPageByName(overlay.parentPage.name, false); 20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen overlay.visible = true; 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (overlay.didShowPage) overlay.didShowPage(); 21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 21121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }; 21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Returns whether or not an overlay is visible. 21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @return {boolean} True if an overlay is visible. 21621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @private 21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 21821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OptionsPage.isOverlayVisible_ = function() { 21972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return this.getVisibleOverlay_() != null; 22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @return {boolean} True if the visible overlay should be closed. 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @private 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OptionsPage.shouldCloseOverlay_ = function() { 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var overlay = this.getVisibleOverlay_(); 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return overlay && overlay.shouldClose(); 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Returns the currently visible overlay, or null if no page is visible. 23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @return {OptionPage} The visible overlay. 23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.getVisibleOverlay_ = function() { 23621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (var name in this.registeredOverlayPages) { 23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var page = this.registeredOverlayPages[name]; 23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (page.visible) 23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return page; 2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return null; 2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 244513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch /** 24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Closes the visible overlay. Updates the history state after closing the 24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * overlay. 247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */ 24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.closeOverlay = function() { 24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var overlay = this.getVisibleOverlay_(); 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!overlay) 25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.visible = false; 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (overlay.didClosePage) overlay.didClosePage(); 25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.updateHistoryState_(); 25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Hides the visible overlay. Does not affect the history state. 26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @private 26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.hideOverlay_ = function() { 26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var overlay = this.getVisibleOverlay_(); 26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (overlay) 26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.visible = false; 2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Returns the topmost visible page (overlays excluded). 270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @return {OptionPage} The topmost visible page aside any overlay. 271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 272513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch */ 273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.getTopmostVisibleNonOverlayPage_ = function() { 27421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var topPage = null; 27521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (var name in this.registeredPages) { 27621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var page = this.registeredPages[name]; 27721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (page.visible && 27821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen (!topPage || page.nestingLevel > topPage.nestingLevel)) 27921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen topPage = page; 280513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 28221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return topPage; 28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 28421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 28521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Returns the topmost visible page, or null if no page is visible. 287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @return {OptionPage} The topmost visible page. 288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.getTopmostVisiblePage = function() { 290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Check overlays first since they're top-most if visible. 291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return this.getVisibleOverlay_() || this.getTopmostVisibleNonOverlayPage_(); 292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 29521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Closes the topmost open subpage, if any. 29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @private 29721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.closeTopSubPage_ = function() { 29921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var topPage = this.getTopmostVisiblePage(); 30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (topPage && !topPage.isOverlay && topPage.parentPage) 30121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen topPage.visible = false; 30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.updateHistoryState_(); 304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch }; 305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 306513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch /** 30721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Closes all subpages below the given level. 30821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @param {number} level The nesting level to close below. 3094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch */ 31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OptionsPage.closeSubPagesToLevel = function(level) { 31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var topPage = this.getTopmostVisiblePage(); 31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen while (topPage && topPage.nestingLevel > level) { 31321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen topPage.visible = false; 31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen topPage = topPage.parentPage; 3154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.updateHistoryState_(); 3184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch }; 3194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 3204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch /** 32121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Updates managed banner visibility state based on the topmost page. 32221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 32321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OptionsPage.updateManagedBannerVisibility = function() { 32421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var topPage = this.getTopmostVisiblePage(); 32521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (topPage) 32621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen topPage.updateManagedBannerVisibility(); 32721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }; 32821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 32921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Shows the tab contents for the given navigation tab. 3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @param {!Element} tab The tab that the user clicked. 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OptionsPage.showTab = function(tab) { 3344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Search parents until we find a tab, or the nav bar itself. This allows 3354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // tabs to have child nodes, e.g. labels in separately-styled spans. 3364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch while (tab && !tab.classList.contains('subpages-nav-tabs') && 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen !tab.classList.contains('tab')) { 3384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch tab = tab.parentNode; 3394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!tab || !tab.classList.contains('tab')) 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (this.activeNavTab != null) { 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.activeNavTab.classList.remove('active-tab'); 3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick $(this.activeNavTab.getAttribute('tab-contents')).classList. 3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick remove('active-tab-contents'); 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick tab.classList.add('active-tab'); 3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick $(tab.getAttribute('tab-contents')).classList.add('active-tab-contents'); 3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.activeNavTab = tab; 3524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch }; 3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Registers new options page. 3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @param {OptionsPage} page Page to register. 3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OptionsPage.register = function(page) { 35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen this.registeredPages[page.name] = page; 3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Create and add new page <li> element to navbar. 3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var pageNav = document.createElement('li'); 3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pageNav.id = page.name + 'PageNav'; 3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pageNav.className = 'navbar-item'; 3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pageNav.setAttribute('pageName', page.name); 36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen pageNav.textContent = page.pageDiv.querySelector('h1').textContent; 3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pageNav.tabIndex = 0; 3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pageNav.onclick = function(event) { 36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.navigateToPage(this.getAttribute('pageName')); 3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pageNav.onkeypress = function(event) { 3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Enter or space 3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (event.keyCode == 13 || event.keyCode == 32) { 37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.navigateToPage(this.getAttribute('pageName')); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var navbar = $('navbar'); 3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick navbar.appendChild(pageNav); 3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page.tab = pageNav; 3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page.initializePage(); 3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 38321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Find an enclosing section for an element if it exists. 38421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @param {Element} element Element to search. 38521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @return {OptionPage} The section element, or null. 38621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @private 3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OptionsPage.findSectionForNode_ = function(node) { 38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen while (node = node.parentNode) { 39021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (node.nodeName == 'SECTION') 39121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return node; 39221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 39321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return null; 39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }; 39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 39721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Registers a new Sub-page. 39821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @param {OptionsPage} subPage Sub-page to register. 39921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @param {OptionsPage} parentPage Associated parent page for this page. 40021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @param {Array} associatedControls Array of control elements that lead to 40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * this sub-page. The first item is typically a button in a root-level 40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * page. There may be additional buttons for nested sub-pages. 40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 40421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OptionsPage.registerSubPage = function(subPage, 40521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen parentPage, 40621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen associatedControls) { 40721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen this.registeredPages[subPage.name] = subPage; 40821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen subPage.parentPage = parentPage; 40921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (associatedControls) { 41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen subPage.associatedControls = associatedControls; 41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (associatedControls.length) { 41221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen subPage.associatedSection = 41321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen this.findSectionForNode_(associatedControls[0]); 41421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 41521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 4164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch subPage.tab = undefined; 4174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch subPage.initializePage(); 4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Registers a new Overlay page. 42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {OptionsPage} overlay Overlay to register. 42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {OptionsPage} parentPage Associated parent page for this overlay. 42421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @param {Array} associatedControls Array of control elements associated with 42521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * this page. 4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.registerOverlay = function(overlay, 42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parentPage, 42921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen associatedControls) { 43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.registeredOverlayPages[overlay.name] = overlay; 43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.parentPage = parentPage; 43221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (associatedControls) { 43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.associatedControls = associatedControls; 43421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (associatedControls.length) { 43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.associatedSection = 43621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen this.findSectionForNode_(associatedControls[0]); 43721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 43821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.tab = undefined; 44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.isOverlay = true; 44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen overlay.initializePage(); 4423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 4433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 4453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Callback for window.onpopstate. 4463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @param {Object} data State data pushed into history. 4473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 4483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OptionsPage.setState = function(data) { 4493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (data && data.pageName) { 45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // It's possible an overlay may be the last top-level page shown. 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (this.isOverlayVisible_() && 452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.registeredOverlayPages[data.pageName] == undefined) { 45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.hideOverlay_(); 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.showPageByName(data.pageName, false); 4573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 4583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 4593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Callback for window.onbeforeunload. Used to notify overlays that they will 462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * be closed. 463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OptionsPage.willClose = function() { 465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var overlay = this.getVisibleOverlay_(); 466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (overlay && overlay.didClosePage) 467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen overlay.didClosePage(); 468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 469ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 470ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 471dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Freezes/unfreezes the scroll position of given level's page container. 472dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {boolean} freeze Whether the page should be frozen. 473dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {number} level The level to freeze/unfreeze. 474dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 475dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 476dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.setPageFrozenAtLevel_ = function(freeze, level) { 477dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var container = level == 0 ? $('toplevel-page-container') 478dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : $('subpage-sheet-container-' + level); 479dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 480dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (container.classList.contains('frozen') == freeze) 481dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 483dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (freeze) { 484dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var scrollPosition = document.body.scrollTop; 485dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Lock the width, since auto width computation may change. 486dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.width = window.getComputedStyle(container).width; 487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.classList.add('frozen'); 488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.top = -scrollPosition + 'px'; 489dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.updateFrozenElementHorizontalPosition_(container); 490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var scrollPosition = - parseInt(container.style.top, 10); 492dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.classList.remove('frozen'); 493dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.top = ''; 494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.left = ''; 495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.right = ''; 496dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.width = ''; 497dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Restore the scroll position. 498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!container.hidden) 499dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen window.scroll(document.body.scrollLeft, scrollPosition); 500dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 501dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 504dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Freezes/unfreezes the scroll position of visible pages based on the current 505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * page stack. 506dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 507dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.updatePageFreezeStates = function() { 508dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var topPage = OptionsPage.getTopmostVisiblePage(); 509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!topPage) 510dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var nestingLevel = topPage.isOverlay ? 100 : topPage.nestingLevel; 512dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (var i = 0; i <= SUBPAGE_SHEET_COUNT; i++) { 513dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.setPageFrozenAtLevel_(i < nestingLevel, i); 514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 515dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 51872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Initializes the complete options page. This will cause all C++ handlers to 51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * be invoked to do final setup. 5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OptionsPage.initialize = function() { 5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chrome.send('coreOptionsInitialize'); 523201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch this.initialized_ = true; 5244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.addEventListener('scroll', this.handleScroll_.bind(this)); 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen window.addEventListener('resize', this.handleResize_.bind(this)); 52721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!document.documentElement.classList.contains('hide-menu')) { 529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Close subpages if the user clicks on the html body. Listen in the 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // capturing phase so that we can stop the click from doing anything. 531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.body.addEventListener('click', 532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.bodyMouseEventHandler_.bind(this), 533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen true); 534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We also need to cancel mousedowns on non-subpage content. 535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.body.addEventListener('mousedown', 536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.bodyMouseEventHandler_.bind(this), 537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen true); 538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var self = this; 540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Hook up the close buttons. 541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen subpageCloseButtons = document.querySelectorAll('.close-subpage'); 542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (var i = 0; i < subpageCloseButtons.length; i++) { 543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen subpageCloseButtons[i].onclick = function() { 544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen self.closeTopSubPage_(); 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 54772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Install handler for key presses. 549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.addEventListener('keydown', 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.keyDownEventHandler_.bind(this)); 551dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.addEventListener('focus', this.manageFocusChange_.bind(this), 553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen true); 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Calculate and store the horizontal locations of elements that may be 557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // frozen later. 558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var sidebarWidth = 559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen parseInt(window.getComputedStyle($('mainview')).webkitPaddingStart, 10); 560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('toplevel-page-container').horizontalOffset = sidebarWidth + 561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen parseInt(window.getComputedStyle( 562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('mainview-content')).webkitPaddingStart, 10); 563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (var level = 1; level <= SUBPAGE_SHEET_COUNT; level++) { 564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var containerId = 'subpage-sheet-container-' + level; 565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $(containerId).horizontalOffset = sidebarWidth; 566dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 567dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('subpage-backdrop').horizontalOffset = sidebarWidth; 568dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Trigger the resize handler manually to set the initial state. 569dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.handleResize_(null); 57021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }; 57121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 57221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 573dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Does a bounds check for the element on the given x, y client coordinates. 574dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {Element} e The DOM element. 575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {number} x The client X to check. 576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {number} y The client Y to check. 577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @return {boolean} True if the point falls within the element's bounds. 57821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @private 57921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 580dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.elementContainsPoint_ = function(e, x, y) { 581dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var clientRect = e.getBoundingClientRect(); 582dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return x >= clientRect.left && x <= clientRect.right && 583dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen y >= clientRect.top && y <= clientRect.bottom; 5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 586201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch /** 58772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Called when focus changes; ensures that focus doesn't move outside 58872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * the topmost subpage/overlay. 58972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {Event} e The focus change event. 59072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @private 59172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 59272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.manageFocusChange_ = function(e) { 59372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var focusableItemsRoot; 59472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var topPage = this.getTopmostVisiblePage(); 59572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!topPage) 59672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 59772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 59872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (topPage.isOverlay) { 59972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If an overlay is visible, that defines the tab loop. 60072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen focusableItemsRoot = topPage.pageDiv; 60172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 60272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If a subpage is visible, use its parent as the tab loop constraint. 60372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // (The parent is used because it contains the close button.) 60472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (topPage.nestingLevel > 0) 60572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen focusableItemsRoot = topPage.pageDiv.parentNode; 60672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 60772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 60872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (focusableItemsRoot && !focusableItemsRoot.contains(e.target)) 60972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen topPage.focusFirstElement(); 61072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 61172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 61272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 613dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Called when the page is scrolled; moves elements that are position:fixed 614dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * but should only behave as if they are fixed for vertical scrolling. 615dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {Event} e The scroll event. 616dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 617dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.handleScroll_ = function(e) { 619dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var scrollHorizontalOffset = document.body.scrollLeft; 620dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // position:fixed doesn't seem to work for horizontal scrolling in RTL mode, 621dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // so only adjust in LTR mode (where scroll values will be positive). 622dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (scrollHorizontalOffset >= 0) { 623dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('navbar-container').style.left = -scrollHorizontalOffset + 'px'; 624dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var subpageBackdrop = $('subpage-backdrop'); 625dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen subpageBackdrop.style.left = subpageBackdrop.horizontalOffset - 626dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen scrollHorizontalOffset + 'px'; 627dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.updateAllFrozenElementPositions_(); 628dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 629dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 630dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 631dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 632dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Updates all frozen pages to match the horizontal scroll position. 633dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 634dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 635dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.updateAllFrozenElementPositions_ = function() { 636dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var frozenElements = document.querySelectorAll('.frozen'); 637dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (var i = 0; i < frozenElements.length; i++) { 638dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.updateFrozenElementHorizontalPosition_(frozenElements[i]); 639dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 640dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 641dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 642dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 643dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Updates the given frozen element to match the horizontal scroll position. 644dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {HTMLElement} e The frozen element to update 645dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 646dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 647dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.updateFrozenElementHorizontalPosition_ = function(e) { 648dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (document.documentElement.dir == 'rtl') 649dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen e.style.right = e.horizontalOffset + 'px'; 650dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else 651dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen e.style.left = e.horizontalOffset - document.body.scrollLeft + 'px'; 652dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 653dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 654dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 655dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Called when the page is resized; adjusts the size of elements that depend 656dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * on the veiwport. 657dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {Event} e The resize event. 658dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 659dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 660dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.handleResize_ = function(e) { 661dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Set an explicit height equal to the viewport on all the subpage 662dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // containers shorter than the viewport. This is used instead of 663dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // min-height: 100% so that there is an explicit height for the subpages' 664dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // min-height: 100%. 665dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var viewportHeight = document.documentElement.clientHeight; 666dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var subpageContainers = 667dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen document.querySelectorAll('.subpage-sheet-container'); 668dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (var i = 0; i < subpageContainers.length; i++) { 669dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (subpageContainers[i].scrollHeight > viewportHeight) 670dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen subpageContainers[i].style.removeProperty('height'); 671dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else 672dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen subpageContainers[i].style.height = viewportHeight + 'px'; 673dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 674dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }; 675dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 676dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 67772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * A function to handle mouse events (mousedown or click) on the html body by 67872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * closing subpages and/or stopping event propagation. 67972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @return {Event} a mousedown or click event. 68072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @private 68172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 68272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.bodyMouseEventHandler_ = function(event) { 68372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Do nothing if a subpage isn't showing. 68472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var topPage = this.getTopmostVisiblePage(); 68572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!topPage || topPage.isOverlay || !topPage.parentPage) 68672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 68772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Do nothing if the client coordinates are not within the source element. 689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This situation is indicative of a Webkit bug where clicking on a 690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // radio/checkbox label span will generate an event with client coordinates 691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // of (-scrollX, -scrollY). 692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // See https://bugs.webkit.org/show_bug.cgi?id=56606 693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (event.clientX == -document.body.scrollLeft && 694ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event.clientY == -document.body.scrollTop) { 695ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 696ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 697ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 69872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Don't interfere with navbar clicks. 69972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if ($('navbar').contains(event.target)) 70072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 70172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Figure out which page the click happened in. 703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (var level = topPage.nestingLevel; level >= 0; level--) { 704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var clickIsWithinLevel = level == 0 ? true : 705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.elementContainsPoint_( 706dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('subpage-sheet-' + level), event.clientX, event.clientY); 707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 708dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!clickIsWithinLevel) 709dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 71072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 711dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Event was within the topmost page; do nothing. 712dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (topPage.nestingLevel == level) 713dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 71472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 715dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Block propgation of both clicks and mousedowns, but only close subpages 716dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // on click. 717dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (event.type == 'click') 718dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.closeSubPagesToLevel(level); 719dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen event.stopPropagation(); 720dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen event.preventDefault(); 721dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 722dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 72372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 72472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 72572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 72672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * A function to handle key press events. 72772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @return {Event} a keydown event. 72872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @private 72972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 73072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.keyDownEventHandler_ = function(event) { 73172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Close the top overlay or sub-page on esc. 73272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (event.keyCode == 27) { // Esc 733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (this.isOverlayVisible_()) { 734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (this.shouldCloseOverlay_()) 735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.closeOverlay(); 736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 73772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.closeTopSubPage_(); 738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OptionsPage.setClearPluginLSODataEnabled = function(enabled) { 743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (enabled) { 744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.documentElement.setAttribute( 745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'flashPluginSupportsClearSiteData', ''); 746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.documentElement.removeAttribute( 748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'flashPluginSupportsClearSiteData'); 74972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 75072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 75172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 75272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 753201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * Re-initializes the C++ handlers if necessary. This is called if the 754201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * handlers are torn down and recreated but the DOM may not have been (in 755201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * which case |initialize| won't be called again). If |initialize| hasn't been 756201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * called, this does nothing (since it will be later, once the DOM has 757201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch * finished loading). 758201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch */ 759201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch OptionsPage.reinitializeCore = function() { 760201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (this.initialized_) 761201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch chrome.send('coreOptionsInitialize'); 762201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 763201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 7643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OptionsPage.prototype = { 7653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick __proto__: cr.EventTarget.prototype, 7663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 76821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * The parent page of this option page, or null for top-level pages. 76921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @type {OptionsPage} 77021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 77121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen parentPage: null, 77221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 77321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 77421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * The section on the parent page that is associated with this page. 77521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Can be null. 77621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @type {Element} 77721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 77821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen associatedSection: null, 77921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 78021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 78121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * An array of controls that are associated with this page. The first 78221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * control should be located on a top-level page. 78321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @type {OptionsPage} 78421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 78521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen associatedControls: null, 78621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 78721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 7883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Initializes page content. 7893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 7903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick initializePage: function() {}, 7913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 7933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Sets managed banner visibility state. 7943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 7953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick setManagedBannerVisibility: function(visible) { 7963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.managed = visible; 7973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (this.visible) { 7984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch this.updateManagedBannerVisibility(); 7994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 8004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch }, 8014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 8024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch /** 80372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Updates managed banner visibility state. This function iterates over 80472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * all input fields of a window and if any of these is marked as managed 80572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * it triggers the managed banner to be visible. The banner can be enforced 80672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * being on through the managed flag of this class but it can not be forced 80772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * being off if managed items exist. 8084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch */ 8094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch updateManagedBannerVisibility: function() { 81072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var bannerDiv = $('managed-prefs-banner'); 81172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 81272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var hasManaged = this.managed; 81372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!hasManaged) { 81472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var inputElements = this.pageDiv.querySelectorAll('input'); 81572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (var i = 0, len = inputElements.length; i < len; i++) { 81672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (inputElements[i].managed) { 81772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen hasManaged = true; 81872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 81972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 82072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 82172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 82272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (hasManaged) { 823dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bannerDiv.hidden = false; 82472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var height = window.getComputedStyle($('managed-prefs-banner')).height; 82572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen $('subpage-backdrop').style.top = height; 8264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else { 827dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bannerDiv.hidden = true; 82872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen $('subpage-backdrop').style.top = '0'; 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 8303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }, 8313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 8323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 8333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Gets page visibility state. 8343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 8353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick get visible() { 8363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var page = $(this.pageDivName); 8373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return page && page.ownerDocument.defaultView.getComputedStyle( 8383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick page).display == 'block'; 8393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }, 8403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 8413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 8423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * Sets page visibility. 8433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 8443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick set visible(visible) { 8453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if ((this.visible && visible) || (!this.visible && !visible)) 8463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 8473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 848dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.setContainerVisibility_(visible); 8493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (visible) { 8504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch this.pageDiv.classList.remove('hidden'); 85172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 852dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (this.tab) 8533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.tab.classList.add('navbar-item-selected'); 8543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 8554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch this.pageDiv.classList.add('hidden'); 85672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 857dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (this.tab) 8583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick this.tab.classList.remove('navbar-item-selected'); 859dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 860dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 861dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.updatePageFreezeStates(); 862dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 863dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // A subpage was shown or hidden. 864dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!this.isOverlay && this.nestingLevel > 0) { 865dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OptionsPage.updateSubpageBackdrop_(); 866dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (visible) { 867dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Scroll to the top of the newly-opened subpage. 868dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen window.scroll(document.body.scrollLeft, 0) 8693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The managed prefs banner is global, so after any visibility change 87372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // update it based on the topmost page, not necessarily this page 87472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // (e.g., if an ancestor is made visible after a child). 87572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OptionsPage.updateManagedBannerVisibility(); 87672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 8773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick cr.dispatchPropertyChange(this, 'visible', visible, !visible); 8783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }, 8793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 8803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 881dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Shows or hides this page's container. 882dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {boolean} visible Whether the container should be visible or not. 883dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 884dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 885dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen setContainerVisibility_: function(visible) { 886dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var container = null; 887dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (this.isOverlay) { 888dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container = $('overlay'); 889dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 890dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var nestingLevel = this.nestingLevel; 891dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (nestingLevel > 0) 892dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container = $('subpage-sheet-container-' + nestingLevel); 893dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 894dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var isSubpage = !this.isOverlay; 895dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 896dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!container || container.hidden != visible) 897dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 898dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 899dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (visible) { 900dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.hidden = false; 901dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (isSubpage) { 902dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var computedStyle = window.getComputedStyle(container); 903dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.WebkitPaddingStart = 904dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen parseInt(computedStyle.WebkitPaddingStart, 10) + 100 + 'px'; 905dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 906dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Separate animating changes from the removal of display:none. 907dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen window.setTimeout(function() { 908dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.classList.remove('transparent'); 909dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (isSubpage) 910dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.style.WebkitPaddingStart = ''; 911dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }); 912dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 913dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var self = this; 914dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.addEventListener('webkitTransitionEnd', function f(e) { 915dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (e.propertyName != 'opacity') 916dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 917dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.removeEventListener('webkitTransitionEnd', f); 918dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen self.fadeCompleted_(container); 919dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }); 920dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.classList.add('transparent'); 921dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 922dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }, 923dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 924dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 925dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * Called when a container opacity transition finishes. 926dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @param {HTMLElement} container The container element. 927dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen * @private 928dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen */ 929dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen fadeCompleted_: function(container) { 930dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (container.classList.contains('transparent')) 931dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen container.hidden = true; 932dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }, 933dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 934dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen /** 93572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Focuses the first control on the page. 93672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 93772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen focusFirstElement: function() { 93872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Sets focus on the first interactive element in the page. 93972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var focusElement = 94072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.pageDiv.querySelector('button, input, list, select'); 94172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (focusElement) 94272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen focusElement.focus(); 94372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 94472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 94572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 94621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * The nesting level of this page. 94721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @type {number} The nesting level of this page (0 for top-level page) 94821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 94921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen get nestingLevel() { 95021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var level = 0; 95121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var parent = this.parentPage; 95221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen while (parent) { 95321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen level++; 95421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen parent = parent.parentPage; 95521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 95621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return level; 95721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }, 95821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 95921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 96021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Whether the page is considered 'sticky', such that it will 96121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * remain a top-level page even if sub-pages change. 96221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @type {boolean} True if this page is sticky. 96321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 96421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen get sticky() { 96521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 96621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }, 96721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 96821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 96921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * Checks whether this page is an ancestor of the given page in terms of 97021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * subpage nesting. 97121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @param {OptionsPage} page 97221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen * @return {boolean} True if this page is nested under |page| 97321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen */ 97421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen isAncestorOfPage: function(page) { 97521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen var parent = page.parentPage; 97621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen while (parent) { 97721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (parent == this) 97821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 97921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen parent = parent.parentPage; 98021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 98121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 98221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen }, 98321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 98421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen /** 98572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Whether it should be possible to show the page. 98672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @return {boolean} True if the page should be shown 9873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 98872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen canShowPage: function() { 98972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 9903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }, 991ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 992ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen /** 993ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Whether an overlay should be closed. Used by overlay implementation to 994ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * handle special closing behaviors. 995ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @return {boolean} True if the overlay should be closed. 996ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */ 997ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shouldClose: function() { 998ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 999ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 10003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 10013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Export 10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return { 10043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OptionsPage: OptionsPage 10053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 10063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}); 1007