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. |
(...skipping 30 matching lines...) Expand all Loading... |
41 * @private | 41 * @private |
42 */ | 42 */ |
43 OptionsPage.initialized_ = false; | 43 OptionsPage.initialized_ = false; |
44 | 44 |
45 /** | 45 /** |
46 * Shows a registered page. This handles both top-level pages and sub-pages. | 46 * Shows a registered page. This handles both top-level pages and sub-pages. |
47 * @param {string} pageName Page name. | 47 * @param {string} pageName Page name. |
48 */ | 48 */ |
49 OptionsPage.showPageByName = function(pageName) { | 49 OptionsPage.showPageByName = function(pageName) { |
50 var targetPage = this.registeredPages[pageName]; | 50 var targetPage = this.registeredPages[pageName]; |
| 51 |
| 52 // Determine if the root page is 'sticky', meaning that it |
| 53 // shouldn't change when showing a sub-page. This can happen for special |
| 54 // pages like Search. |
| 55 var rootPage = null; |
| 56 for (var name in this.registeredPages) { |
| 57 var page = this.registeredPages[name]; |
| 58 if (page.visible && !page.parentPage) { |
| 59 rootPage = page; |
| 60 break; |
| 61 } |
| 62 } |
| 63 var isRootPageLocked = |
| 64 rootPage && rootPage.sticky && targetPage.parentPage; |
| 65 |
51 // Notify pages if they will be hidden. | 66 // Notify pages if they will be hidden. |
52 for (var name in this.registeredPages) { | 67 for (var name in this.registeredPages) { |
53 var page = this.registeredPages[name]; | 68 var page = this.registeredPages[name]; |
| 69 if (!page.parentPage && isRootPageLocked) |
| 70 continue; |
54 if (page.willHidePage && name != pageName && | 71 if (page.willHidePage && name != pageName && |
55 !page.isAncestorOfPage(targetPage)) | 72 !page.isAncestorOfPage(targetPage)) |
56 page.willHidePage(); | 73 page.willHidePage(); |
57 } | 74 } |
58 | 75 |
59 // Update visibilities to show only the hierarchy of the target page. | 76 // Update visibilities to show only the hierarchy of the target page. |
60 for (var name in this.registeredPages) { | 77 for (var name in this.registeredPages) { |
61 var page = this.registeredPages[name]; | 78 var page = this.registeredPages[name]; |
| 79 if (!page.parentPage && isRootPageLocked) |
| 80 continue; |
62 page.visible = name == pageName || | 81 page.visible = name == pageName || |
63 (document.documentElement.getAttribute('hide-menu') != 'true' && | 82 (document.documentElement.getAttribute('hide-menu') != 'true' && |
64 page.isAncestorOfPage(targetPage)); | 83 page.isAncestorOfPage(targetPage)); |
65 } | 84 } |
66 | 85 |
67 // Notify pages if they were shown. | 86 // Notify pages if they were shown. |
68 for (var name in this.registeredPages) { | 87 for (var name in this.registeredPages) { |
69 var page = this.registeredPages[name]; | 88 var page = this.registeredPages[name]; |
70 if (name == pageName && page.didShowPage) | 89 if (!page.parentPage && isRootPageLocked) |
| 90 continue; |
| 91 if (page.didShowPage && (name == pageName || |
| 92 page.isAncestorOfPage(targetPage))) |
71 page.didShowPage(); | 93 page.didShowPage(); |
72 } | 94 } |
73 }; | 95 }; |
74 | 96 |
75 /** | 97 /** |
76 * Called on load. Dispatch the URL hash to the given page's handleHash | 98 * Called on load. Dispatch the URL hash to the given page's handleHash |
77 * function. | 99 * function. |
78 * @param {string} pageName The string name of the (registered) options page. | 100 * @param {string} pageName The string name of the (registered) options page. |
79 * @param {string} hash The value of the hash component of the URL. | 101 * @param {string} hash The value of the hash component of the URL. |
80 */ | 102 */ |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 OptionsPage.showPageByName(this.getAttribute('pageName')); | 230 OptionsPage.showPageByName(this.getAttribute('pageName')); |
209 } | 231 } |
210 }; | 232 }; |
211 var navbar = $('navbar'); | 233 var navbar = $('navbar'); |
212 navbar.appendChild(pageNav); | 234 navbar.appendChild(pageNav); |
213 page.tab = pageNav; | 235 page.tab = pageNav; |
214 page.initializePage(); | 236 page.initializePage(); |
215 }; | 237 }; |
216 | 238 |
217 /** | 239 /** |
218 * Registers a new Sub tab page. | 240 * Find an enclosing section for an element if it exists. |
219 * @param {OptionsPage} page Page to register. | 241 * @param {Element} element Element to search. |
| 242 * @return {OptionPage} The section element, or null. |
| 243 * @private |
220 */ | 244 */ |
221 OptionsPage.registerSubPage = function(subPage, parentPage) { | 245 OptionsPage.findSectionForNode_ = function(node) { |
| 246 while (node = node.parentNode) { |
| 247 if (node.nodeName == 'SECTION') |
| 248 return node; |
| 249 } |
| 250 return null; |
| 251 }; |
| 252 |
| 253 /** |
| 254 * Registers a new Sub-page. |
| 255 * @param {OptionsPage} subPage Sub-page to register. |
| 256 * @param {OptionsPage} parentPage Associated parent page for this page. |
| 257 * @param {Array} associatedControls Array of control elements that lead to |
| 258 * this sub-page. The first item is typically a button in a root-level |
| 259 * page. There may be additional buttons for nested sub-pages. |
| 260 */ |
| 261 OptionsPage.registerSubPage = function(subPage, |
| 262 parentPage, |
| 263 associatedControls) { |
222 this.registeredPages[subPage.name] = subPage; | 264 this.registeredPages[subPage.name] = subPage; |
223 subPage.parentPage = parentPage; | 265 subPage.parentPage = parentPage; |
| 266 if (associatedControls) { |
| 267 subPage.associatedControls = associatedControls; |
| 268 if (associatedControls.length) { |
| 269 subPage.associatedSection = |
| 270 this.findSectionForNode_(associatedControls[0]); |
| 271 } |
| 272 } |
224 subPage.tab = undefined; | 273 subPage.tab = undefined; |
225 subPage.initializePage(); | 274 subPage.initializePage(); |
226 }; | 275 }; |
227 | 276 |
228 /** | 277 /** |
229 * Registers a new Overlay page. | 278 * Registers a new Overlay page. |
230 * @param {OptionsPage} page Page to register, must be a class derived from | 279 * @param {OptionsPage} page Page to register, must be a class derived from |
231 * OptionsPage. | 280 * @param {Array} associatedControls Array of control elements associated with |
| 281 * this page. |
232 */ | 282 */ |
233 OptionsPage.registerOverlay = function(page) { | 283 OptionsPage.registerOverlay = function(page, |
| 284 associatedControls) { |
234 this.registeredOverlayPages[page.name] = page; | 285 this.registeredOverlayPages[page.name] = page; |
| 286 if (associatedControls) { |
| 287 page.associatedControls = associatedControls; |
| 288 if (associatedControls.length) { |
| 289 page.associatedSection = |
| 290 this.findSectionForNode_(associatedControls[0]); |
| 291 } |
| 292 } |
235 page.tab = undefined; | 293 page.tab = undefined; |
236 page.isOverlay = true; | 294 page.isOverlay = true; |
237 page.initializePage(); | 295 page.initializePage(); |
238 }; | 296 }; |
239 | 297 |
240 /** | 298 /** |
241 * Callback for window.onpopstate. | 299 * Callback for window.onpopstate. |
242 * @param {Object} data State data pushed into history. | 300 * @param {Object} data State data pushed into history. |
243 */ | 301 */ |
244 OptionsPage.setState = function(data) { | 302 OptionsPage.setState = function(data) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 OptionsPage.prototype = { | 372 OptionsPage.prototype = { |
315 __proto__: cr.EventTarget.prototype, | 373 __proto__: cr.EventTarget.prototype, |
316 | 374 |
317 /** | 375 /** |
318 * The parent page of this option page, or null for top-level pages. | 376 * The parent page of this option page, or null for top-level pages. |
319 * @type {OptionsPage} | 377 * @type {OptionsPage} |
320 */ | 378 */ |
321 parentPage: null, | 379 parentPage: null, |
322 | 380 |
323 /** | 381 /** |
| 382 * The section on the parent page that is associated with this page. |
| 383 * Can be null. |
| 384 * @type {Element} |
| 385 */ |
| 386 associatedSection: null, |
| 387 |
| 388 /** |
| 389 * An array of controls that are associated with this page. The first |
| 390 * control should be located on a top-level page. |
| 391 * @type {OptionsPage} |
| 392 */ |
| 393 associatedControls: null, |
| 394 |
| 395 /** |
324 * Initializes page content. | 396 * Initializes page content. |
325 */ | 397 */ |
326 initializePage: function() {}, | 398 initializePage: function() {}, |
327 | 399 |
328 /** | 400 /** |
329 * Sets managed banner visibility state. | 401 * Sets managed banner visibility state. |
330 */ | 402 */ |
331 setManagedBannerVisibility: function(visible) { | 403 setManagedBannerVisibility: function(visible) { |
332 this.managed = visible; | 404 this.managed = visible; |
333 if (this.visible) { | 405 if (this.visible) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 } | 471 } |
400 if (this.tab) { | 472 if (this.tab) { |
401 this.tab.classList.remove('navbar-item-selected'); | 473 this.tab.classList.remove('navbar-item-selected'); |
402 } | 474 } |
403 } | 475 } |
404 | 476 |
405 cr.dispatchPropertyChange(this, 'visible', visible, !visible); | 477 cr.dispatchPropertyChange(this, 'visible', visible, !visible); |
406 }, | 478 }, |
407 | 479 |
408 /** | 480 /** |
409 * Gets the nesting level of this page. | 481 * The nesting level of this page. |
410 * @return {number} The nesting level of this page (0 for top-level page) | 482 * @type {number} The nesting level of this page (0 for top-level page) |
411 */ | 483 */ |
412 get nestingLevel() { | 484 get nestingLevel() { |
413 var level = 0; | 485 var level = 0; |
414 var parent = this.parentPage; | 486 var parent = this.parentPage; |
415 while (parent) { | 487 while (parent) { |
416 level++; | 488 level++; |
417 parent = parent.parentPage; | 489 parent = parent.parentPage; |
418 } | 490 } |
419 return level; | 491 return level; |
420 }, | 492 }, |
421 | 493 |
422 /** | 494 /** |
| 495 * Whether the page is considered 'sticky', such that it will |
| 496 * remain a top-level page even if sub-pages change. |
| 497 * @type {boolean} True if this page is sticky. |
| 498 */ |
| 499 get sticky() { |
| 500 return false; |
| 501 }, |
| 502 |
| 503 /** |
423 * Checks whether this page is an ancestor of the given page in terms of | 504 * Checks whether this page is an ancestor of the given page in terms of |
424 * subpage nesting. | 505 * subpage nesting. |
425 * @param {OptionsPage} page | 506 * @param {OptionsPage} page |
426 * @return {boolean} True if this page is nested under |page| | 507 * @return {boolean} True if this page is nested under |page| |
427 */ | 508 */ |
428 isAncestorOfPage: function(page) { | 509 isAncestorOfPage: function(page) { |
429 var parent = page.parentPage; | 510 var parent = page.parentPage; |
430 while (parent) { | 511 while (parent) { |
431 if (parent == this) | 512 if (parent == this) |
432 return true; | 513 return true; |
(...skipping 13 matching lines...) Expand all Loading... |
446 OptionsPage.showOverlay(hash); | 527 OptionsPage.showOverlay(hash); |
447 }, | 528 }, |
448 }; | 529 }; |
449 | 530 |
450 // Export | 531 // Export |
451 return { | 532 return { |
452 OptionsPage: OptionsPage | 533 OptionsPage: OptionsPage |
453 }; | 534 }; |
454 | 535 |
455 }); | 536 }); |
OLD | NEW |