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 if they will be hidden. |
50 var page = OptionsPage.registeredPages_[name]; | 57 for (var name in this.registeredPages) { |
| 58 var page = this.registeredPages[name]; |
| 59 if (name != pageName && page.willHidePage) |
| 60 page.willHidePage(); |
| 61 } |
| 62 |
| 63 // Update the visibility attribute for main pages. |
| 64 for (var name in this.registeredPages) { |
| 65 var page = this.registeredPages[name]; |
51 page.visible = name == pageName; | 66 page.visible = name == pageName; |
52 } | 67 } |
53 for (var name in OptionsPage.registeredSubPages_) { | 68 |
54 var pageInfo = OptionsPage.registeredSubPages_[name]; | 69 // Update the visibility attribute for sub-pages. |
| 70 for (var name in this.registeredSubPages) { |
| 71 var pageInfo = this.registeredSubPages[name]; |
55 var match = name == pageName; | 72 var match = name == pageName; |
56 if (match) | 73 if (match) |
57 pageInfo.parentPage.visible = true; | 74 pageInfo.parentPage.visible = true; |
58 pageInfo.page.visible = match; | 75 pageInfo.page.visible = match; |
59 } | 76 } |
| 77 |
| 78 // Notify main pages if they were shown. |
| 79 for (var name in this.registeredPages) { |
| 80 var page = this.registeredPages[name]; |
| 81 if (name == pageName && page.didShowPage) |
| 82 page.didShowPage(); |
| 83 } |
60 }; | 84 }; |
61 | 85 |
62 /** | 86 /** |
63 * Called on load. Dispatch the URL hash to the given page's handleHash | 87 * Called on load. Dispatch the URL hash to the given page's handleHash |
64 * function. | 88 * function. |
65 * @param {string} pageName The string name of the (registered) options page. | 89 * @param {string} pageName The string name of the (registered) options page. |
66 * @param {string} hash The value of the hash component of the URL. | 90 * @param {string} hash The value of the hash component of the URL. |
67 */ | 91 */ |
68 OptionsPage.handleHashForPage = function(pageName, hash) { | 92 OptionsPage.handleHashForPage = function(pageName, hash) { |
69 var page = OptionsPage.registeredPages_[pageName]; | 93 var page = this.registeredPages[pageName]; |
70 if (!page) { | 94 if (!page) { |
71 page = OptionsPage.registeredSubPages_[pageName].page; | 95 page = this.registeredSubPages[pageName].page; |
72 } | 96 } |
73 page.handleHash(hash); | 97 page.handleHash(hash); |
74 }; | 98 }; |
75 | 99 |
76 /** | 100 /** |
77 * Shows a registered Overlay page. | 101 * Shows a registered Overlay page. |
78 * @param {string} overlayName Page name. | 102 * @param {string} overlayName Page name. |
79 */ | 103 */ |
80 OptionsPage.showOverlay = function(overlayName) { | 104 OptionsPage.showOverlay = function(overlayName) { |
81 if (OptionsPage.registeredOverlayPages_[overlayName]) { | 105 if (this.registeredOverlayPages[overlayName]) { |
82 OptionsPage.registeredOverlayPages_[overlayName].visible = true; | 106 this.registeredOverlayPages[overlayName].visible = true; |
83 } | 107 } |
84 }; | 108 }; |
85 | 109 |
86 /** | 110 /** |
87 * Clears overlays (i.e. hide all overlays). | 111 * Clears overlays (i.e. hide all overlays). |
88 */ | 112 */ |
89 OptionsPage.clearOverlays = function() { | 113 OptionsPage.clearOverlays = function() { |
90 for (var name in OptionsPage.registeredOverlayPages_) { | 114 for (var name in this.registeredOverlayPages) { |
91 var page = OptionsPage.registeredOverlayPages_[name]; | 115 var page = this.registeredOverlayPages[name]; |
92 page.visible = false; | 116 page.visible = false; |
93 } | 117 } |
94 }; | 118 }; |
95 | 119 |
96 /** | 120 /** |
97 * Clears overlays if the key event is ESC. | 121 * Handle 'keydown' events. |
98 * @param {Event} e Key event. | 122 * @param {Event} e Key event. |
99 * @private | 123 * @private |
100 */ | 124 */ |
101 OptionsPage.clearOverlaysOnEsc_ = function(e) { | 125 OptionsPage.onKeyDown_ = function(e) { |
102 if (e.keyCode == 27) { // Esc | 126 if (e.keyCode == 27) { // Esc |
103 OptionsPage.clearOverlays(); | 127 this.clearOverlays(); |
104 } | 128 } |
105 }; | 129 }; |
106 | 130 |
107 /** | 131 /** |
108 * Closes any currently-open subpage. | 132 * Closes any currently-open subpage. |
109 */ | 133 */ |
110 OptionsPage.closeSubPage = function() { | 134 OptionsPage.closeSubPage = function() { |
111 for (var name in OptionsPage.registeredSubPages_) { | 135 for (var name in this.registeredSubPages) { |
112 var pageInfo = OptionsPage.registeredSubPages_[name]; | 136 var pageInfo = this.registeredSubPages[name]; |
113 if (pageInfo.page.visible) { | 137 if (pageInfo.page.visible) { |
114 pageInfo.page.visible = false; | 138 pageInfo.page.visible = false; |
115 // Since the managed pref banner lives outside the overlay, and the | 139 // Since the managed pref banner lives outside the overlay, and the |
116 // parent is not changing visibility, update the banner explicitly. | 140 // parent is not changing visibility, update the banner explicitly. |
117 pageInfo.parentPage.updateManagedBannerVisibility(); | 141 pageInfo.parentPage.updateManagedBannerVisibility(); |
118 } | 142 } |
119 } | 143 } |
120 }; | 144 }; |
121 | 145 |
122 /** | 146 /** |
(...skipping 19 matching lines...) Expand all Loading... |
142 tab.classList.add('active-tab'); | 166 tab.classList.add('active-tab'); |
143 $(tab.getAttribute('tab-contents')).classList.add('active-tab-contents'); | 167 $(tab.getAttribute('tab-contents')).classList.add('active-tab-contents'); |
144 this.activeNavTab = tab; | 168 this.activeNavTab = tab; |
145 }; | 169 }; |
146 | 170 |
147 /** | 171 /** |
148 * Registers new options page. | 172 * Registers new options page. |
149 * @param {OptionsPage} page Page to register. | 173 * @param {OptionsPage} page Page to register. |
150 */ | 174 */ |
151 OptionsPage.register = function(page) { | 175 OptionsPage.register = function(page) { |
152 OptionsPage.registeredPages_[page.name] = page; | 176 this.registeredPages[page.name] = page; |
153 // Create and add new page <li> element to navbar. | 177 // Create and add new page <li> element to navbar. |
154 var pageNav = document.createElement('li'); | 178 var pageNav = document.createElement('li'); |
155 pageNav.id = page.name + 'PageNav'; | 179 pageNav.id = page.name + 'PageNav'; |
156 pageNav.className = 'navbar-item'; | 180 pageNav.className = 'navbar-item'; |
157 pageNav.setAttribute('pageName', page.name); | 181 pageNav.setAttribute('pageName', page.name); |
158 pageNav.textContent = page.title; | 182 pageNav.textContent = page.title; |
159 pageNav.tabIndex = 0; | 183 pageNav.tabIndex = 0; |
160 pageNav.onclick = function(event) { | 184 pageNav.onclick = function(event) { |
161 OptionsPage.showPageByName(this.getAttribute('pageName')); | 185 OptionsPage.showPageByName(this.getAttribute('pageName')); |
162 }; | 186 }; |
163 pageNav.onkeypress = function(event) { | 187 pageNav.onkeypress = function(event) { |
164 // Enter or space | 188 // Enter or space |
165 if (event.keyCode == 13 || event.keyCode == 32) { | 189 if (event.keyCode == 13 || event.keyCode == 32) { |
166 OptionsPage.showPageByName(this.getAttribute('pageName')); | 190 OptionsPage.showPageByName(this.getAttribute('pageName')); |
167 } | 191 } |
168 }; | 192 }; |
169 var navbar = $('navbar'); | 193 var navbar = $('navbar'); |
170 navbar.appendChild(pageNav); | 194 navbar.appendChild(pageNav); |
171 page.tab = pageNav; | 195 page.tab = pageNav; |
172 page.initializePage(); | 196 page.initializePage(); |
173 }; | 197 }; |
174 | 198 |
175 /** | 199 /** |
176 * Registers a new Sub tab page. | 200 * Registers a new Sub tab page. |
177 * @param {OptionsPage} page Page to register. | 201 * @param {OptionsPage} page Page to register. |
178 */ | 202 */ |
179 OptionsPage.registerSubPage = function(subPage, parentPage) { | 203 OptionsPage.registerSubPage = function(subPage, parentPage) { |
180 OptionsPage.registeredSubPages_[subPage.name] = { | 204 this.registeredSubPages[subPage.name] = { |
181 page: subPage, parentPage: parentPage }; | 205 page: subPage, parentPage: parentPage }; |
182 subPage.tab = undefined; | 206 subPage.tab = undefined; |
183 subPage.isSubPageSheet = true; | 207 subPage.isSubPageSheet = true; |
184 subPage.initializePage(); | 208 subPage.initializePage(); |
185 }; | 209 }; |
186 | 210 |
187 /** | 211 /** |
188 * Registers a new Overlay page. | 212 * Registers a new Overlay page. |
189 * @param {OptionsPage} page Page to register, must be a class derived from | 213 * @param {OptionsPage} page Page to register, must be a class derived from |
190 * OptionsPage. | 214 * OptionsPage. |
191 */ | 215 */ |
192 OptionsPage.registerOverlay = function(page) { | 216 OptionsPage.registerOverlay = function(page) { |
193 OptionsPage.registeredOverlayPages_[page.name] = page; | 217 this.registeredOverlayPages[page.name] = page; |
194 page.tab = undefined; | 218 page.tab = undefined; |
195 page.isOverlay = true; | 219 page.isOverlay = true; |
196 page.initializePage(); | 220 page.initializePage(); |
197 }; | 221 }; |
198 | 222 |
199 /** | 223 /** |
200 * Callback for window.onpopstate. | 224 * Callback for window.onpopstate. |
201 * @param {Object} data State data pushed into history. | 225 * @param {Object} data State data pushed into history. |
202 */ | 226 */ |
203 OptionsPage.setState = function(data) { | 227 OptionsPage.setState = function(data) { |
204 if (data && data.pageName) { | 228 if (data && data.pageName) { |
205 OptionsPage.showPageByName(data.pageName); | 229 this.showPageByName(data.pageName); |
206 } | 230 } |
207 }; | 231 }; |
208 | 232 |
209 /** | 233 /** |
210 * Initializes the complete options page. This will cause | 234 * Initializes the complete options page. This will cause |
211 * all C++ handlers to be invoked to do final setup. | 235 * all C++ handlers to be invoked to do final setup. |
212 */ | 236 */ |
213 OptionsPage.initialize = function() { | 237 OptionsPage.initialize = function() { |
214 chrome.send('coreOptionsInitialize'); | 238 chrome.send('coreOptionsInitialize'); |
215 this.initialized_ = true; | 239 this.initialized_ = true; |
216 | 240 |
217 // Set up the overlay sheet. Clicks on the visible part of the parent page | 241 // 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. | 242 // should close the overlay, not fall through to the parent page. |
219 $('subpage-sheet-container').onclick = function(event) { | 243 $('subpage-sheet-container').onclick = function(event) { |
220 if (!$('subpage-sheet').contains(event.target)) | 244 if (!$('subpage-sheet').contains(event.target)) |
221 OptionsPage.closeSubPage(); | 245 this.closeSubPage(); |
222 event.stopPropagation(); | 246 event.stopPropagation(); |
223 } | 247 } |
224 }; | 248 }; |
225 | 249 |
226 /** | 250 /** |
227 * Re-initializes the C++ handlers if necessary. This is called if the | 251 * 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 | 252 * 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 | 253 * 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 | 254 * called, this does nothing (since it will be later, once the DOM has |
231 * finished loading). | 255 * finished loading). |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 * Sets page visibility. | 301 * Sets page visibility. |
278 */ | 302 */ |
279 set visible(visible) { | 303 set visible(visible) { |
280 if ((this.visible && visible) || (!this.visible && !visible)) | 304 if ((this.visible && visible) || (!this.visible && !visible)) |
281 return; | 305 return; |
282 | 306 |
283 if (visible) { | 307 if (visible) { |
284 this.pageDiv.classList.remove('hidden'); | 308 this.pageDiv.classList.remove('hidden'); |
285 if (this.isOverlay) { | 309 if (this.isOverlay) { |
286 $('overlay').classList.remove('hidden'); | 310 $('overlay').classList.remove('hidden'); |
287 document.addEventListener('keydown', | 311 document.addEventListener('keydown', OptionsPage.onKeyDown_); |
288 OptionsPage.clearOverlaysOnEsc_); | |
289 } else { | 312 } else { |
290 if (this.isSubPageSheet) | 313 if (this.isSubPageSheet) |
291 $('subpage-sheet-container').classList.remove('hidden'); | 314 $('subpage-sheet-container').classList.remove('hidden'); |
292 | 315 |
293 this.updateManagedBannerVisibility(); | 316 this.updateManagedBannerVisibility(); |
294 | 317 |
295 // Recent webkit change no longer allows url change from "chrome://". | 318 // Recent webkit change no longer allows url change from "chrome://". |
296 window.history.pushState({pageName: this.name}, this.title); | 319 window.history.pushState({pageName: this.name}, this.title); |
297 } | 320 } |
298 if (this.tab) { | 321 if (this.tab) { |
299 this.tab.classList.add('navbar-item-selected'); | 322 this.tab.classList.add('navbar-item-selected'); |
300 } | 323 } |
301 } else { | 324 } else { |
302 this.pageDiv.classList.add('hidden'); | 325 this.pageDiv.classList.add('hidden'); |
303 if (this.isOverlay) { | 326 if (this.isOverlay) { |
304 $('overlay').classList.add('hidden'); | 327 $('overlay').classList.add('hidden'); |
305 document.removeEventListener('keydown', | 328 document.removeEventListener('keydown', OptionsPage.onKeyDown_); |
306 OptionsPage.clearOverlaysOnEsc_); | |
307 } else if (this.isSubPageSheet) { | 329 } else if (this.isSubPageSheet) { |
308 $('subpage-sheet-container').classList.add('hidden'); | 330 $('subpage-sheet-container').classList.add('hidden'); |
309 } | 331 } |
310 if (this.tab) { | 332 if (this.tab) { |
311 this.tab.classList.remove('navbar-item-selected'); | 333 this.tab.classList.remove('navbar-item-selected'); |
312 } | 334 } |
313 } | 335 } |
314 | 336 |
315 cr.dispatchPropertyChange(this, 'visible', visible, !visible); | 337 cr.dispatchPropertyChange(this, 'visible', visible, !visible); |
316 }, | 338 }, |
317 | 339 |
318 /** | 340 /** |
319 * Handles a hash value in the URL (such as bar in | 341 * Handles a hash value in the URL (such as bar in |
320 * chrome://options/foo#bar). Called on page load. By default, this shows | 342 * 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 | 343 * an overlay that matches the hash name, but can be overriden by individual |
322 * OptionsPage subclasses to get other behavior. | 344 * OptionsPage subclasses to get other behavior. |
323 * @param {string} hash The hash value. | 345 * @param {string} hash The hash value. |
324 */ | 346 */ |
325 handleHash: function(hash) { | 347 handleHash: function(hash) { |
326 OptionsPage.showOverlay(hash); | 348 OptionsPage.showOverlay(hash); |
327 }, | 349 }, |
328 }; | 350 }; |
329 | 351 |
330 // Export | 352 // Export |
331 return { | 353 return { |
332 OptionsPage: OptionsPage | 354 OptionsPage: OptionsPage |
333 }; | 355 }; |
334 | 356 |
335 }); | 357 }); |
OLD | NEW |