options_page.js revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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 5cr.define('options', function() { 6 ///////////////////////////////////////////////////////////////////////////// 7 // OptionsPage class: 8 9 /** 10 * Base class for options page. 11 * @constructor 12 * @param {string} name Options page name, also defines id of the div element 13 * containing the options view and the name of options page navigation bar 14 * item as name+'PageNav'. 15 * @param {string} title Options page title, used for navigation bar 16 * @extends {EventTarget} 17 */ 18 function OptionsPage(name, title, pageDivName) { 19 this.name = name; 20 this.title = title; 21 this.pageDivName = pageDivName; 22 this.pageDiv = $(this.pageDivName); 23 this.tab = null; 24 this.managed = false; 25 } 26 27 OptionsPage.registeredPages_ = {}; 28 29 /** 30 * Pages which are meant to have an entry in the nav, but 31 * not have a permanent entry. 32 */ 33 OptionsPage.registeredSubPages_ = {}; 34 35 /** 36 * Pages which are meant to behave like model dialogs. 37 */ 38 OptionsPage.registeredOverlayPages_ = {}; 39 40 /** 41 * Shows a registered page. 42 * @param {string} pageName Page name. 43 */ 44 OptionsPage.showPageByName = function(pageName) { 45 for (var name in OptionsPage.registeredPages_) { 46 var page = OptionsPage.registeredPages_[name]; 47 page.visible = name == pageName; 48 } 49 }; 50 51 /** 52 * Called on load. Dispatch the URL hash to the given page's handleHash 53 * function. 54 * @param {string} pageName The string name of the (registered) options page. 55 * @param {string} hash The value of the hash component of the URL. 56 */ 57 OptionsPage.handleHashForPage = function(pageName, hash) { 58 OptionsPage.registeredPages_[pageName].handleHash(hash); 59 }; 60 61 /** 62 * Shows a registered Overlay page. 63 * @param {string} overlayName Page name. 64 */ 65 OptionsPage.showOverlay = function(overlayName) { 66 if (OptionsPage.registeredOverlayPages_[overlayName]) { 67 OptionsPage.registeredOverlayPages_[overlayName].visible = true; 68 } 69 }; 70 71 OptionsPage.clearOverlays = function() { 72 for (var name in OptionsPage.registeredOverlayPages_) { 73 var page = OptionsPage.registeredOverlayPages_[name]; 74 page.visible = false; 75 } 76 }; 77 78 /** 79 * Shows the tab contents for the given navigation tab. 80 * @param {!Element} tab The tab that the user clicked. 81 */ 82 OptionsPage.showTab = function(tab) { 83 if (!tab.classList.contains('inactive-tab')) 84 return; 85 86 if (this.activeNavTab != null) { 87 this.activeNavTab.classList.remove('active-tab'); 88 $(this.activeNavTab.getAttribute('tab-contents')).classList. 89 remove('active-tab-contents'); 90 } 91 92 tab.classList.add('active-tab'); 93 $(tab.getAttribute('tab-contents')).classList.add('active-tab-contents'); 94 this.activeNavTab = tab; 95 } 96 97 /** 98 * Registers new options page. 99 * @param {OptionsPage} page Page to register. 100 */ 101 OptionsPage.register = function(page) { 102 OptionsPage.registeredPages_[page.name] = page; 103 // Create and add new page <li> element to navbar. 104 var pageNav = document.createElement('li'); 105 pageNav.id = page.name + 'PageNav'; 106 pageNav.className = 'navbar-item'; 107 pageNav.setAttribute('pageName', page.name); 108 pageNav.textContent = page.title; 109 pageNav.tabIndex = 0; 110 pageNav.onclick = function(event) { 111 OptionsPage.showPageByName(this.getAttribute('pageName')); 112 }; 113 pageNav.onkeypress = function(event) { 114 // Enter or space 115 if (event.keyCode == 13 || event.keyCode == 32) { 116 OptionsPage.showPageByName(this.getAttribute('pageName')); 117 } 118 }; 119 var navbar = $('navbar'); 120 navbar.appendChild(pageNav); 121 page.tab = pageNav; 122 page.initializePage(); 123 }; 124 125 /** 126 * Registers a new Sub tab page. 127 * @param {OptionsPage} page Page to register. 128 */ 129 OptionsPage.registerSubPage = function(page) { 130 OptionsPage.registeredPages_[page.name] = page; 131 var pageNav = document.createElement('li'); 132 pageNav.id = page.name + 'PageNav'; 133 pageNav.className = 'navbar-item hidden'; 134 pageNav.setAttribute('pageName', page.name); 135 pageNav.textContent = page.title; 136 var subpagesnav = $('subpagesnav'); 137 subpagesnav.appendChild(pageNav); 138 page.tab = pageNav; 139 page.initializePage(); 140 }; 141 142 /** 143 * Registers a new Overlay page. 144 * @param {OptionsPage} page Page to register, must be a class derived from 145 * OptionsPage. 146 */ 147 OptionsPage.registerOverlay = function(page) { 148 OptionsPage.registeredOverlayPages_[page.name] = page; 149 page.tab = undefined; 150 page.isOverlay = true; 151 page.initializePage(); 152 }; 153 154 /** 155 * Callback for window.onpopstate. 156 * @param {Object} data State data pushed into history. 157 */ 158 OptionsPage.setState = function(data) { 159 if (data && data.pageName) { 160 OptionsPage.showPageByName(data.pageName); 161 } 162 }; 163 164 /** 165 * Initializes the complete options page. This will cause 166 * all C++ handlers to be invoked to do final setup. 167 */ 168 OptionsPage.initialize = function() { 169 chrome.send('coreOptionsInitialize'); 170 }; 171 172 OptionsPage.prototype = { 173 __proto__: cr.EventTarget.prototype, 174 175 /** 176 * Initializes page content. 177 */ 178 initializePage: function() {}, 179 180 /** 181 * Sets managed banner visibility state. 182 */ 183 setManagedBannerVisibility: function(visible) { 184 this.managed = visible; 185 if (this.visible) { 186 $('managed-prefs-banner').style.display = visible ? 'block' : 'none'; 187 } 188 }, 189 190 /** 191 * Gets page visibility state. 192 */ 193 get visible() { 194 var page = $(this.pageDivName); 195 return page && page.ownerDocument.defaultView.getComputedStyle( 196 page).display == 'block'; 197 }, 198 199 /** 200 * Sets page visibility. 201 */ 202 set visible(visible) { 203 if ((this.visible && visible) || (!this.visible && !visible)) 204 return; 205 206 if (visible) { 207 this.pageDiv.style.display = 'block'; 208 if (this.isOverlay) { 209 var overlay = $('overlay'); 210 overlay.classList.remove('hidden'); 211 } else { 212 var banner = $('managed-prefs-banner'); 213 banner.style.display = this.managed ? 'block' : 'none'; 214 215 // Recent webkit change no longer allows url change from "chrome://". 216 window.history.pushState({pageName: this.name}, 217 this.title); 218 } 219 if (this.tab) { 220 this.tab.classList.add('navbar-item-selected'); 221 if (this.tab.parentNode && this.tab.parentNode.id == 'subpagesnav') 222 this.tab.classList.remove('hidden'); 223 } 224 } else { 225 if (this.isOverlay) { 226 var overlay = $('overlay'); 227 overlay.classList.add('hidden'); 228 } 229 this.pageDiv.style.display = 'none'; 230 if (this.tab) { 231 this.tab.classList.remove('navbar-item-selected'); 232 if (this.tab.parentNode && this.tab.parentNode.id == 'subpagesnav') 233 this.tab.classList.add('hidden'); 234 } 235 } 236 237 cr.dispatchPropertyChange(this, 'visible', visible, !visible); 238 }, 239 240 /** 241 * Handles a hash value in the URL (such as bar in 242 * chrome://options/foo#bar). Called on page load. By default, this shows 243 * an overlay that matches the hash name, but can be overriden by individual 244 * OptionsPage subclasses to get other behavior. 245 * @param {string} hash The hash value. 246 */ 247 handleHash: function(hash) { 248 OptionsPage.showOverlay(hash); 249 }, 250 }; 251 252 // Export 253 return { 254 OptionsPage: OptionsPage 255 }; 256 257}); 258