Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 cr.define('options', function() { | 5 cr.define('options', function() { |
| 6 ///////////////////////////////////////////////////////////////////////////// | 6 ///////////////////////////////////////////////////////////////////////////// |
| 7 // OptionsPage class: | 7 // OptionsPage class: |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * Base class for options page. | 10 * Base class for options page. |
| 11 * @constructor | 11 * @constructor |
| 12 * @param {string} name Options page name, also defines id of the div element | 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 | 13 * containing the options view and the name of options page navigation bar |
| 14 * item as name+'PageNav'. | 14 * item as name+'PageNav'. |
| 15 * @param {string} title Options page title, used for navigation bar | 15 * @param {string} title Options page title, used for navigation bar |
| 16 * @extends {EventTarget} | 16 * @extends {EventTarget} |
| 17 */ | 17 */ |
| 18 function OptionsPage(name, title, pageDivName) { | 18 function OptionsPage(name, title, pageDivName) { |
| 19 this.name = name; | 19 this.name = name; |
| 20 this.title = title; | 20 this.title = title; |
| 21 this.pageDivName = pageDivName; | 21 this.pageDivName = pageDivName; |
| 22 this.pageDiv = $(this.pageDivName); | 22 this.pageDiv = $(this.pageDivName); |
| 23 this.tab = null; | 23 this.tab = null; |
| 24 this.managed = false; | 24 this.managed = false; |
| 25 } | 25 } |
| 26 | 26 |
| 27 OptionsPage.registeredPages_ = {}; | 27 /** |
| 28 * Main level option pages. | |
| 29 * @protected | |
| 30 */ | |
| 31 OptionsPage.registeredPages = {}; | |
| 28 | 32 |
| 29 /** | 33 /** |
| 30 * Pages which are nested under a main page. | 34 * Pages which are nested under a main level page. |
| 35 * @protected | |
| 31 */ | 36 */ |
| 32 OptionsPage.registeredSubPages_ = {}; | 37 OptionsPage.registeredSubPages = {}; |
| 33 | 38 |
| 34 /** | 39 /** |
| 35 * Pages which are meant to behave like modal dialogs. | 40 * Pages which are meant to behave like modal dialogs. |
| 41 * @protected | |
| 36 */ | 42 */ |
| 37 OptionsPage.registeredOverlayPages_ = {}; | 43 OptionsPage.registeredOverlayPages = {}; |
| 38 | 44 |
| 39 /** | 45 /** |
| 40 * Whether or not |initialize| has been called. | 46 * Whether or not |initialize| has been called. |
| 47 * @private | |
| 41 */ | 48 */ |
| 42 OptionsPage.initialized_ = false; | 49 OptionsPage.initialized_ = false; |
| 43 | 50 |
| 44 /** | 51 /** |
| 45 * Shows a registered page. This handles both top-level pages and sub-pages. | 52 * Shows a registered page. This handles both top-level pages and sub-pages. |
| 46 * @param {string} pageName Page name. | 53 * @param {string} pageName Page name. |
| 47 */ | 54 */ |
| 48 OptionsPage.showPageByName = function(pageName) { | 55 OptionsPage.showPageByName = function(pageName) { |
| 49 for (var name in OptionsPage.registeredPages_) { | 56 // Notify main pages that they will be shown or hidden. |
| 50 var page = OptionsPage.registeredPages_[name]; | 57 for (var name in this.registeredPages) { |
| 58 var page = this.registeredPages[name]; | |
| 59 if (name == pageName) { | |
| 60 if (page.willShowPage) | |
| 61 page.willShowPage(); | |
| 62 } else { | |
| 63 if (page.willHidePage) | |
| 64 page.willHidePage(); | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 // Update the visibility attribute for main pages. | |
| 69 for (var name in this.registeredPages) { | |
| 70 var page = this.registeredPages[name]; | |
| 51 page.visible = name == pageName; | 71 page.visible = name == pageName; |
|
James Hawkins
2010/12/02 23:11:44
Can you just move this to the above for loop that
csilv
2010/12/02 23:40:21
No. The reason is that the 'willShowPage' and 'wi
James Hawkins
2010/12/03 00:02:09
Can you elucidate the problem? I'm not understand
| |
| 52 } | 72 } |
| 53 for (var name in OptionsPage.registeredSubPages_) { | 73 |
| 54 var pageInfo = OptionsPage.registeredSubPages_[name]; | 74 // Update the visibility attribute for sub-pages. |
| 75 for (var name in this.registeredSubPages) { | |
| 76 var pageInfo = this.registeredSubPages[name]; | |
| 55 var match = name == pageName; | 77 var match = name == pageName; |
| 56 if (match) | 78 if (match) |
| 57 pageInfo.parentPage.visible = true; | 79 pageInfo.parentPage.visible = true; |
| 58 pageInfo.page.visible = match; | 80 pageInfo.page.visible = match; |
| 59 } | 81 } |
| 82 | |
| 83 // Notify main pages that they were shown or hidden. | |
| 84 for (var name in this.registeredPages) { | |
| 85 var page = this.registeredPages[name]; | |
| 86 if (name == pageName) { | |
| 87 if (page.didShowPage) | |
|
James Hawkins
2010/12/02 23:11:44
Is there a way for a page to listen to class chang
csilv
2010/12/02 23:40:21
Yes, there is a mechanism for this in cr, but that
| |
| 88 page.didShowPage(); | |
| 89 } else { | |
| 90 if (page.didHidePage) | |
| 91 page.didHidePage(); | |
| 92 } | |
| 93 } | |
| 60 }; | 94 }; |
| 61 | 95 |
| 62 /** | 96 /** |
| 63 * Called on load. Dispatch the URL hash to the given page's handleHash | 97 * Called on load. Dispatch the URL hash to the given page's handleHash |
| 64 * function. | 98 * function. |
| 65 * @param {string} pageName The string name of the (registered) options page. | 99 * @param {string} pageName The string name of the (registered) options page. |
| 66 * @param {string} hash The value of the hash component of the URL. | 100 * @param {string} hash The value of the hash component of the URL. |
| 67 */ | 101 */ |
| 68 OptionsPage.handleHashForPage = function(pageName, hash) { | 102 OptionsPage.handleHashForPage = function(pageName, hash) { |
| 69 var page = OptionsPage.registeredPages_[pageName]; | 103 var page = this.registeredPages[pageName]; |
| 70 if (!page) { | 104 if (!page) { |
| 71 page = OptionsPage.registeredSubPages_[pageName].page; | 105 page = this.registeredSubPages[pageName].page; |
| 72 } | 106 } |
| 73 page.handleHash(hash); | 107 page.handleHash(hash); |
| 74 }; | 108 }; |
| 75 | 109 |
| 76 /** | 110 /** |
| 77 * Shows a registered Overlay page. | 111 * Shows a registered Overlay page. |
| 78 * @param {string} overlayName Page name. | 112 * @param {string} overlayName Page name. |
| 79 */ | 113 */ |
| 80 OptionsPage.showOverlay = function(overlayName) { | 114 OptionsPage.showOverlay = function(overlayName) { |
| 81 if (OptionsPage.registeredOverlayPages_[overlayName]) { | 115 if (this.registeredOverlayPages[overlayName]) { |
| 82 OptionsPage.registeredOverlayPages_[overlayName].visible = true; | 116 this.registeredOverlayPages[overlayName].visible = true; |
| 83 } | 117 } |
| 84 }; | 118 }; |
| 85 | 119 |
| 86 /** | 120 /** |
| 87 * Clears overlays (i.e. hide all overlays). | 121 * Clears overlays (i.e. hide all overlays). |
| 88 */ | 122 */ |
| 89 OptionsPage.clearOverlays = function() { | 123 OptionsPage.clearOverlays = function() { |
| 90 for (var name in OptionsPage.registeredOverlayPages_) { | 124 for (var name in this.registeredOverlayPages) { |
| 91 var page = OptionsPage.registeredOverlayPages_[name]; | 125 var page = this.registeredOverlayPages[name]; |
| 92 page.visible = false; | 126 page.visible = false; |
| 93 } | 127 } |
| 94 }; | 128 }; |
| 95 | 129 |
| 96 /** | 130 /** |
| 97 * Clears overlays if the key event is ESC. | 131 * Handle 'keydown' events. |
| 98 * @param {Event} e Key event. | 132 * @param {Event} e Key event. |
| 99 * @private | 133 * @private |
| 100 */ | 134 */ |
| 101 OptionsPage.clearOverlaysOnEsc_ = function(e) { | 135 OptionsPage.handleKeyDown_ = function(e) { |
|
James Hawkins
2010/12/02 23:11:44
s/handleKeyDown_/onKeyDown_/
csilv
2010/12/02 23:40:21
Done.
| |
| 102 if (e.keyCode == 27) { // Esc | 136 if (e.keyCode == 27) { // Esc |
| 103 OptionsPage.clearOverlays(); | 137 this.clearOverlays(); |
| 104 } | 138 } |
| 105 }; | 139 }; |
| 106 | 140 |
| 107 /** | 141 /** |
| 108 * Closes any currently-open subpage. | 142 * Closes any currently-open subpage. |
| 109 */ | 143 */ |
| 110 OptionsPage.closeSubPage = function() { | 144 OptionsPage.closeSubPage = function() { |
| 111 for (var name in OptionsPage.registeredSubPages_) { | 145 for (var name in this.registeredSubPages) { |
| 112 var pageInfo = OptionsPage.registeredSubPages_[name]; | 146 var pageInfo = this.registeredSubPages[name]; |
| 113 if (pageInfo.page.visible) { | 147 if (pageInfo.page.visible) { |
| 114 pageInfo.page.visible = false; | 148 pageInfo.page.visible = false; |
| 115 // Since the managed pref banner lives outside the overlay, and the | 149 // Since the managed pref banner lives outside the overlay, and the |
| 116 // parent is not changing visibility, update the banner explicitly. | 150 // parent is not changing visibility, update the banner explicitly. |
| 117 pageInfo.parentPage.updateManagedBannerVisibility(); | 151 pageInfo.parentPage.updateManagedBannerVisibility(); |
| 118 } | 152 } |
| 119 } | 153 } |
| 120 }; | 154 }; |
| 121 | 155 |
| 122 /** | 156 /** |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 142 tab.classList.add('active-tab'); | 176 tab.classList.add('active-tab'); |
| 143 $(tab.getAttribute('tab-contents')).classList.add('active-tab-contents'); | 177 $(tab.getAttribute('tab-contents')).classList.add('active-tab-contents'); |
| 144 this.activeNavTab = tab; | 178 this.activeNavTab = tab; |
| 145 }; | 179 }; |
| 146 | 180 |
| 147 /** | 181 /** |
| 148 * Registers new options page. | 182 * Registers new options page. |
| 149 * @param {OptionsPage} page Page to register. | 183 * @param {OptionsPage} page Page to register. |
| 150 */ | 184 */ |
| 151 OptionsPage.register = function(page) { | 185 OptionsPage.register = function(page) { |
| 152 OptionsPage.registeredPages_[page.name] = page; | 186 this.registeredPages[page.name] = page; |
| 153 // Create and add new page <li> element to navbar. | 187 // Create and add new page <li> element to navbar. |
| 154 var pageNav = document.createElement('li'); | 188 var pageNav = document.createElement('li'); |
| 155 pageNav.id = page.name + 'PageNav'; | 189 pageNav.id = page.name + 'PageNav'; |
| 156 pageNav.className = 'navbar-item'; | 190 pageNav.className = 'navbar-item'; |
| 157 pageNav.setAttribute('pageName', page.name); | 191 pageNav.setAttribute('pageName', page.name); |
| 158 pageNav.textContent = page.title; | 192 pageNav.textContent = page.title; |
| 159 pageNav.tabIndex = 0; | 193 pageNav.tabIndex = 0; |
| 160 pageNav.onclick = function(event) { | 194 pageNav.onclick = function(event) { |
| 161 OptionsPage.showPageByName(this.getAttribute('pageName')); | 195 OptionsPage.showPageByName(this.getAttribute('pageName')); |
| 162 }; | 196 }; |
| 163 pageNav.onkeypress = function(event) { | 197 pageNav.onkeypress = function(event) { |
| 164 // Enter or space | 198 // Enter or space |
| 165 if (event.keyCode == 13 || event.keyCode == 32) { | 199 if (event.keyCode == 13 || event.keyCode == 32) { |
| 166 OptionsPage.showPageByName(this.getAttribute('pageName')); | 200 OptionsPage.showPageByName(this.getAttribute('pageName')); |
| 167 } | 201 } |
| 168 }; | 202 }; |
| 169 var navbar = $('navbar'); | 203 var navbar = $('navbar'); |
| 170 navbar.appendChild(pageNav); | 204 navbar.appendChild(pageNav); |
| 171 page.tab = pageNav; | 205 page.tab = pageNav; |
| 172 page.initializePage(); | 206 page.initializePage(); |
| 173 }; | 207 }; |
| 174 | 208 |
| 175 /** | 209 /** |
| 176 * Registers a new Sub tab page. | 210 * Registers a new Sub tab page. |
| 177 * @param {OptionsPage} page Page to register. | 211 * @param {OptionsPage} page Page to register. |
| 178 */ | 212 */ |
| 179 OptionsPage.registerSubPage = function(subPage, parentPage) { | 213 OptionsPage.registerSubPage = function(subPage, parentPage) { |
| 180 OptionsPage.registeredSubPages_[subPage.name] = { | 214 this.registeredSubPages[subPage.name] = { |
| 181 page: subPage, parentPage: parentPage }; | 215 page: subPage, parentPage: parentPage }; |
| 182 subPage.tab = undefined; | 216 subPage.tab = undefined; |
| 183 subPage.isSubPageSheet = true; | 217 subPage.isSubPageSheet = true; |
| 184 subPage.initializePage(); | 218 subPage.initializePage(); |
| 185 }; | 219 }; |
| 186 | 220 |
| 187 /** | 221 /** |
| 188 * Registers a new Overlay page. | 222 * Registers a new Overlay page. |
| 189 * @param {OptionsPage} page Page to register, must be a class derived from | 223 * @param {OptionsPage} page Page to register, must be a class derived from |
| 190 * OptionsPage. | 224 * OptionsPage. |
| 191 */ | 225 */ |
| 192 OptionsPage.registerOverlay = function(page) { | 226 OptionsPage.registerOverlay = function(page) { |
| 193 OptionsPage.registeredOverlayPages_[page.name] = page; | 227 this.registeredOverlayPages[page.name] = page; |
| 194 page.tab = undefined; | 228 page.tab = undefined; |
| 195 page.isOverlay = true; | 229 page.isOverlay = true; |
| 196 page.initializePage(); | 230 page.initializePage(); |
| 197 }; | 231 }; |
| 198 | 232 |
| 199 /** | 233 /** |
| 200 * Callback for window.onpopstate. | 234 * Callback for window.onpopstate. |
| 201 * @param {Object} data State data pushed into history. | 235 * @param {Object} data State data pushed into history. |
| 202 */ | 236 */ |
| 203 OptionsPage.setState = function(data) { | 237 OptionsPage.setState = function(data) { |
| 204 if (data && data.pageName) { | 238 if (data && data.pageName) { |
| 205 OptionsPage.showPageByName(data.pageName); | 239 this.showPageByName(data.pageName); |
| 206 } | 240 } |
| 207 }; | 241 }; |
| 208 | 242 |
| 209 /** | 243 /** |
| 210 * Initializes the complete options page. This will cause | 244 * Initializes the complete options page. This will cause |
| 211 * all C++ handlers to be invoked to do final setup. | 245 * all C++ handlers to be invoked to do final setup. |
| 212 */ | 246 */ |
| 213 OptionsPage.initialize = function() { | 247 OptionsPage.initialize = function() { |
| 214 chrome.send('coreOptionsInitialize'); | 248 chrome.send('coreOptionsInitialize'); |
| 215 this.initialized_ = true; | 249 this.initialized_ = true; |
| 216 | 250 |
| 217 // Set up the overlay sheet. Clicks on the visible part of the parent page | 251 // Set up the overlay sheet. Clicks on the visible part of the parent page |
| 218 // should close the overlay, not fall through to the parent page. | 252 // should close the overlay, not fall through to the parent page. |
| 219 $('subpage-sheet-container').onclick = function(event) { | 253 $('subpage-sheet-container').onclick = function(event) { |
| 220 if (!$('subpage-sheet').contains(event.target)) | 254 if (!$('subpage-sheet').contains(event.target)) |
| 221 OptionsPage.closeSubPage(); | 255 this.closeSubPage(); |
| 222 event.stopPropagation(); | 256 event.stopPropagation(); |
| 223 } | 257 } |
| 224 }; | 258 }; |
| 225 | 259 |
| 226 /** | 260 /** |
| 227 * Re-initializes the C++ handlers if necessary. This is called if the | 261 * Re-initializes the C++ handlers if necessary. This is called if the |
| 228 * handlers are torn down and recreated but the DOM may not have been (in | 262 * handlers are torn down and recreated but the DOM may not have been (in |
| 229 * which case |initialize| won't be called again). If |initialize| hasn't been | 263 * which case |initialize| won't be called again). If |initialize| hasn't been |
| 230 * called, this does nothing (since it will be later, once the DOM has | 264 * called, this does nothing (since it will be later, once the DOM has |
| 231 * finished loading). | 265 * finished loading). |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 * Sets page visibility. | 311 * Sets page visibility. |
| 278 */ | 312 */ |
| 279 set visible(visible) { | 313 set visible(visible) { |
| 280 if ((this.visible && visible) || (!this.visible && !visible)) | 314 if ((this.visible && visible) || (!this.visible && !visible)) |
| 281 return; | 315 return; |
| 282 | 316 |
| 283 if (visible) { | 317 if (visible) { |
| 284 this.pageDiv.classList.remove('hidden'); | 318 this.pageDiv.classList.remove('hidden'); |
| 285 if (this.isOverlay) { | 319 if (this.isOverlay) { |
| 286 $('overlay').classList.remove('hidden'); | 320 $('overlay').classList.remove('hidden'); |
| 287 document.addEventListener('keydown', | 321 document.addEventListener('keydown', OptionsPage.handleKeyDown_); |
| 288 OptionsPage.clearOverlaysOnEsc_); | |
| 289 } else { | 322 } else { |
| 290 if (this.isSubPageSheet) | 323 if (this.isSubPageSheet) |
| 291 $('subpage-sheet-container').classList.remove('hidden'); | 324 $('subpage-sheet-container').classList.remove('hidden'); |
| 292 | 325 |
| 293 this.updateManagedBannerVisibility(); | 326 this.updateManagedBannerVisibility(); |
| 294 | 327 |
| 295 // Recent webkit change no longer allows url change from "chrome://". | 328 // Recent webkit change no longer allows url change from "chrome://". |
| 296 window.history.pushState({pageName: this.name}, this.title); | 329 window.history.pushState({pageName: this.name}, this.title); |
| 297 } | 330 } |
| 298 if (this.tab) { | 331 if (this.tab) { |
| 299 this.tab.classList.add('navbar-item-selected'); | 332 this.tab.classList.add('navbar-item-selected'); |
| 300 } | 333 } |
| 301 } else { | 334 } else { |
| 302 this.pageDiv.classList.add('hidden'); | 335 this.pageDiv.classList.add('hidden'); |
| 303 if (this.isOverlay) { | 336 if (this.isOverlay) { |
| 304 $('overlay').classList.add('hidden'); | 337 $('overlay').classList.add('hidden'); |
| 305 document.removeEventListener('keydown', | 338 document.removeEventListener('keydown', OptionsPage.handleKeyDown_); |
| 306 OptionsPage.clearOverlaysOnEsc_); | |
| 307 } else if (this.isSubPageSheet) { | 339 } else if (this.isSubPageSheet) { |
| 308 $('subpage-sheet-container').classList.add('hidden'); | 340 $('subpage-sheet-container').classList.add('hidden'); |
| 309 } | 341 } |
| 310 if (this.tab) { | 342 if (this.tab) { |
| 311 this.tab.classList.remove('navbar-item-selected'); | 343 this.tab.classList.remove('navbar-item-selected'); |
| 312 } | 344 } |
| 313 } | 345 } |
| 314 | 346 |
| 315 cr.dispatchPropertyChange(this, 'visible', visible, !visible); | 347 cr.dispatchPropertyChange(this, 'visible', visible, !visible); |
| 316 }, | 348 }, |
| 317 | 349 |
| 318 /** | 350 /** |
| 319 * Handles a hash value in the URL (such as bar in | 351 * Handles a hash value in the URL (such as bar in |
| 320 * chrome://options/foo#bar). Called on page load. By default, this shows | 352 * chrome://options/foo#bar). Called on page load. By default, this shows |
| 321 * an overlay that matches the hash name, but can be overriden by individual | 353 * an overlay that matches the hash name, but can be overriden by individual |
| 322 * OptionsPage subclasses to get other behavior. | 354 * OptionsPage subclasses to get other behavior. |
| 323 * @param {string} hash The hash value. | 355 * @param {string} hash The hash value. |
| 324 */ | 356 */ |
| 325 handleHash: function(hash) { | 357 handleHash: function(hash) { |
| 326 OptionsPage.showOverlay(hash); | 358 OptionsPage.showOverlay(hash); |
| 327 }, | 359 }, |
| 328 }; | 360 }; |
| 329 | 361 |
| 330 // Export | 362 // Export |
| 331 return { | 363 return { |
| 332 OptionsPage: OptionsPage | 364 OptionsPage: OptionsPage |
| 333 }; | 365 }; |
| 334 | 366 |
| 335 }); | 367 }); |
| OLD | NEW |