OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 /** @const */ var FocusOutlineManager = cr.ui.FocusOutlineManager; | 6 /** @const */ var FocusOutlineManager = cr.ui.FocusOutlineManager; |
7 | 7 |
8 ///////////////////////////////////////////////////////////////////////////// | 8 ///////////////////////////////////////////////////////////////////////////// |
9 // OptionsPage class: | 9 // OptionsPage class: |
10 | 10 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 | 64 |
65 /** | 65 /** |
66 * Gets the default page (to be shown on initial load). | 66 * Gets the default page (to be shown on initial load). |
67 */ | 67 */ |
68 OptionsPage.getDefaultPage = function() { | 68 OptionsPage.getDefaultPage = function() { |
69 return BrowserOptions.getInstance(); | 69 return BrowserOptions.getInstance(); |
70 }; | 70 }; |
71 | 71 |
72 /** | 72 /** |
73 * Shows the default page. | 73 * Shows the default page. |
| 74 * @param {Object=} opt_propertyBag An optional bag of properties including |
| 75 * replaceState (if history state should be replaced instead of pushed). |
74 */ | 76 */ |
75 OptionsPage.showDefaultPage = function() { | 77 OptionsPage.showDefaultPage = function(opt_propertyBag) { |
76 this.navigateToPage(this.getDefaultPage().name); | 78 this.navigateToPage(this.getDefaultPage().name, opt_propertyBag); |
77 }; | 79 }; |
78 | 80 |
79 /** | 81 /** |
80 * "Navigates" to a page, meaning that the page will be shown and the | 82 * "Navigates" to a page, meaning that the page will be shown and the |
81 * appropriate entry is placed in the history. | 83 * appropriate entry is placed in the history. |
82 * @param {string} pageName Page name. | 84 * @param {string} pageName Page name. |
| 85 * @param {Object=} opt_propertyBag An optional bag of properties including |
| 86 * replaceState (if history state should be replaced instead of pushed). |
83 */ | 87 */ |
84 OptionsPage.navigateToPage = function(pageName) { | 88 OptionsPage.navigateToPage = function(pageName, opt_propertyBag) { |
85 this.showPageByName(pageName, true); | 89 this.showPageByName(pageName, true, opt_propertyBag); |
86 }; | 90 }; |
87 | 91 |
88 /** | 92 /** |
89 * Shows a registered page. This handles both top-level and overlay pages. | 93 * Shows a registered page. This handles both top-level and overlay pages. |
90 * @param {string} pageName Page name. | 94 * @param {string} pageName Page name. |
91 * @param {boolean} updateHistory True if we should update the history after | 95 * @param {boolean} updateHistory True if we should update the history after |
92 * showing the page. | 96 * showing the page. |
93 * @param {Object=} opt_propertyBag An optional bag of properties including | 97 * @param {Object=} opt_propertyBag An optional bag of properties including |
94 * replaceState (if history state should be replaced instead of pushed). | 98 * replaceState (if history state should be replaced instead of pushed). |
95 * @private | 99 * @private |
(...skipping 17 matching lines...) Expand all Loading... |
113 } | 117 } |
114 } | 118 } |
115 | 119 |
116 // Find the target page. | 120 // Find the target page. |
117 var targetPage = this.registeredPages[pageName.toLowerCase()]; | 121 var targetPage = this.registeredPages[pageName.toLowerCase()]; |
118 if (!targetPage || !targetPage.canShowPage()) { | 122 if (!targetPage || !targetPage.canShowPage()) { |
119 // If it's not a page, try it as an overlay. | 123 // If it's not a page, try it as an overlay. |
120 if (!targetPage && this.showOverlay_(pageName, rootPage)) { | 124 if (!targetPage && this.showOverlay_(pageName, rootPage)) { |
121 if (updateHistory) | 125 if (updateHistory) |
122 this.updateHistoryState_(!!opt_propertyBag.replaceState); | 126 this.updateHistoryState_(!!opt_propertyBag.replaceState); |
| 127 this.updateTitle_(); |
123 return; | 128 return; |
124 } else { | 129 } else { |
125 targetPage = this.getDefaultPage(); | 130 targetPage = this.getDefaultPage(); |
126 } | 131 } |
127 } | 132 } |
128 | 133 |
129 pageName = targetPage.name.toLowerCase(); | 134 pageName = targetPage.name.toLowerCase(); |
130 var targetPageWasVisible = targetPage.visible; | 135 var targetPageWasVisible = targetPage.visible; |
131 | 136 |
132 // Determine if the root page is 'sticky', meaning that it | 137 // Determine if the root page is 'sticky', meaning that it |
(...skipping 26 matching lines...) Expand all Loading... |
159 this.registeredOverlayPages[name]; | 164 this.registeredOverlayPages[name]; |
160 if (!page.parentPage && isRootPageLocked) | 165 if (!page.parentPage && isRootPageLocked) |
161 continue; | 166 continue; |
162 page.visible = name == pageName || page.isAncestorOfPage(targetPage); | 167 page.visible = name == pageName || page.isAncestorOfPage(targetPage); |
163 } | 168 } |
164 | 169 |
165 // Update the history and current location. | 170 // Update the history and current location. |
166 if (updateHistory) | 171 if (updateHistory) |
167 this.updateHistoryState_(!!opt_propertyBag.replaceState); | 172 this.updateHistoryState_(!!opt_propertyBag.replaceState); |
168 | 173 |
169 // Update tab title. | |
170 this.setTitle_(targetPage.title); | |
171 | |
172 // Update focus if any other control was focused on the previous page, | 174 // Update focus if any other control was focused on the previous page, |
173 // or the previous page is not known. | 175 // or the previous page is not known. |
174 if (document.activeElement != document.body && | 176 if (document.activeElement != document.body && |
175 (!rootPage || rootPage.pageDiv.contains(document.activeElement))) { | 177 (!rootPage || rootPage.pageDiv.contains(document.activeElement))) { |
176 targetPage.focus(); | 178 targetPage.focus(); |
177 } | 179 } |
178 | 180 |
179 // Notify pages if they were shown. | 181 // Notify pages if they were shown. |
180 for (var i = 0; i < allPageNames.length; ++i) { | 182 for (var i = 0; i < allPageNames.length; ++i) { |
181 var name = allPageNames[i]; | 183 var name = allPageNames[i]; |
182 var page = this.registeredPages[name] || | 184 var page = this.registeredPages[name] || |
183 this.registeredOverlayPages[name]; | 185 this.registeredOverlayPages[name]; |
184 if (!page.parentPage && isRootPageLocked) | 186 if (!page.parentPage && isRootPageLocked) |
185 continue; | 187 continue; |
186 if (!targetPageWasVisible && page.didShowPage && | 188 if (!targetPageWasVisible && page.didShowPage && |
187 (name == pageName || page.isAncestorOfPage(targetPage))) { | 189 (name == pageName || page.isAncestorOfPage(targetPage))) { |
188 page.didShowPage(); | 190 page.didShowPage(); |
189 } | 191 } |
190 } | 192 } |
| 193 |
| 194 // Update the document title. Do this after didShowPage was called, in case |
| 195 // a page decides to change its title. |
| 196 this.updateTitle_(); |
191 }; | 197 }; |
192 | 198 |
193 /** | 199 /** |
194 * Sets the title of the page. This is accomplished by calling into the | |
195 * parent page API. | |
196 * @param {string} title The title string. | |
197 * @private | |
198 */ | |
199 OptionsPage.setTitle_ = function(title) { | |
200 uber.invokeMethodOnParent('setTitle', {title: title}); | |
201 }; | |
202 | |
203 /** | |
204 * Scrolls the page to the correct position (the top when opening an overlay, | 200 * Scrolls the page to the correct position (the top when opening an overlay, |
205 * or the old scroll position a previously hidden overlay becomes visible). | 201 * or the old scroll position a previously hidden overlay becomes visible). |
206 * @private | 202 * @private |
207 */ | 203 */ |
208 OptionsPage.updateScrollPosition_ = function() { | 204 OptionsPage.updateScrollPosition_ = function() { |
209 var container = $('page-container'); | 205 var container = $('page-container'); |
210 var scrollTop = container.oldScrollTop || 0; | 206 var scrollTop = container.oldScrollTop || 0; |
211 container.oldScrollTop = undefined; | 207 container.oldScrollTop = undefined; |
212 window.scroll(scrollLeftForDocument(document), scrollTop); | 208 window.scroll(scrollLeftForDocument(document), scrollTop); |
213 }; | 209 }; |
214 | 210 |
215 /** | 211 /** |
216 * Pushes the current page onto the history stack, overriding the last page | 212 * Updates the title to title of the current page. |
217 * if it is the generic chrome://settings/. | 213 * @private |
| 214 */ |
| 215 OptionsPage.updateTitle_ = function() { |
| 216 var page = this.getTopmostVisiblePage(); |
| 217 uber.setTitle(page.title); |
| 218 }; |
| 219 |
| 220 /** |
| 221 * Pushes the current page onto the history stack, replacing the current entry |
| 222 * if appropriate. |
218 * @param {boolean} replace If true, allow no history events to be created. | 223 * @param {boolean} replace If true, allow no history events to be created. |
219 * @param {object=} opt_params A bag of optional params, including: | 224 * @param {object=} opt_params A bag of optional params, including: |
220 * {boolean} ignoreHash Whether to include the hash or not. | 225 * {boolean} ignoreHash Whether to include the hash or not. |
221 * @private | 226 * @private |
222 */ | 227 */ |
223 OptionsPage.updateHistoryState_ = function(replace, opt_params) { | 228 OptionsPage.updateHistoryState_ = function(replace, opt_params) { |
224 if (OptionsPage.isDialog) | 229 if (OptionsPage.isDialog) |
225 return; | 230 return; |
226 | 231 |
227 var page = this.getTopmostVisiblePage(); | 232 var page = this.getTopmostVisiblePage(); |
228 var path = window.location.pathname + window.location.hash; | 233 var path = window.location.pathname + window.location.hash; |
229 if (path) | 234 if (path) |
230 path = path.slice(1).replace(/\/(?:#|$)/, ''); // Remove trailing slash. | 235 path = path.slice(1).replace(/\/(?:#|$)/, ''); // Remove trailing slash. |
231 | 236 |
232 // Update tab title. | |
233 this.setTitle_(page.title); | |
234 | |
235 // The page is already in history (the user may have clicked the same link | 237 // The page is already in history (the user may have clicked the same link |
236 // twice). Do nothing. | 238 // twice). Do nothing. |
237 if (path == page.name && !OptionsPage.isLoading()) | 239 if (path == page.name && !OptionsPage.isLoading()) |
238 return; | 240 return; |
239 | 241 |
240 var hash = opt_params && opt_params.ignoreHash ? '' : window.location.hash; | 242 var hash = opt_params && opt_params.ignoreHash ? '' : window.location.hash; |
241 | 243 |
242 // If settings are embedded, tell the outer page to set its "path" to the | 244 var newPath = (page == this.getDefaultPage() ? '' : page.name) + hash; |
243 // inner frame's path. | 245 var historyFunction = replace ? uber.replaceState : uber.pushState; |
244 var outerPath = (page == this.getDefaultPage() ? '' : page.name) + hash; | 246 historyFunction.call(uber, {pageName: page.name}, newPath); |
245 uber.invokeMethodOnParent('setPath', {path: outerPath}); | |
246 | |
247 // If there is no path, the current location is chrome://settings/. | |
248 // Override this with the new page. | |
249 var historyFunction = path && !replace ? window.history.pushState : | |
250 window.history.replaceState; | |
251 historyFunction.call(window.history, | |
252 {pageName: page.name}, | |
253 page.title, | |
254 '/' + page.name + hash); | |
255 }; | 247 }; |
256 | 248 |
257 /** | 249 /** |
258 * Shows a registered Overlay page. Does not update history. | 250 * Shows a registered Overlay page. Does not update history. |
259 * @param {string} overlayName Page name. | 251 * @param {string} overlayName Page name. |
260 * @param {OptionPage} rootPage The currently visible root-level page. | 252 * @param {OptionPage} rootPage The currently visible root-level page. |
261 * @return {boolean} whether we showed an overlay. | 253 * @return {boolean} whether we showed an overlay. |
262 */ | 254 */ |
263 OptionsPage.showOverlay_ = function(overlayName, rootPage) { | 255 OptionsPage.showOverlay_ = function(overlayName, rootPage) { |
264 var overlay = this.registeredOverlayPages[overlayName.toLowerCase()]; | 256 var overlay = this.registeredOverlayPages[overlayName.toLowerCase()]; |
265 if (!overlay || !overlay.canShowPage()) | 257 if (!overlay || !overlay.canShowPage()) |
266 return false; | 258 return false; |
267 | 259 |
268 // Save the currently focused element in the page for restoration later. | 260 // Save the currently focused element in the page for restoration later. |
269 var currentPage = this.getTopmostVisiblePage(); | 261 var currentPage = this.getTopmostVisiblePage(); |
270 if (currentPage) | 262 if (currentPage) |
271 currentPage.lastFocusedElement = document.activeElement; | 263 currentPage.lastFocusedElement = document.activeElement; |
272 | 264 |
273 if ((!rootPage || !rootPage.sticky) && | 265 if ((!rootPage || !rootPage.sticky) && |
274 overlay.parentPage && | 266 overlay.parentPage && |
275 !overlay.parentPage.visible) { | 267 !overlay.parentPage.visible) { |
276 this.showPageByName(overlay.parentPage.name, false); | 268 this.showPageByName(overlay.parentPage.name, false); |
277 } | 269 } |
278 | 270 |
279 if (!overlay.visible) { | 271 if (!overlay.visible) { |
280 overlay.visible = true; | 272 overlay.visible = true; |
281 if (overlay.didShowPage) overlay.didShowPage(); | 273 if (overlay.didShowPage) overlay.didShowPage(); |
282 } | 274 } |
283 | 275 |
284 // Update tab title. | |
285 this.setTitle_(overlay.title); | |
286 | |
287 // Change focus to the overlay if any other control was focused by keyboard | 276 // Change focus to the overlay if any other control was focused by keyboard |
288 // before. Otherwise, no one should have focus. | 277 // before. Otherwise, no one should have focus. |
289 if (document.activeElement != document.body) { | 278 if (document.activeElement != document.body) { |
290 if (FocusOutlineManager.forDocument(document).visible) { | 279 if (FocusOutlineManager.forDocument(document).visible) { |
291 overlay.focus(); | 280 overlay.focus(); |
292 } else if (!overlay.pageDiv.contains(document.activeElement)) { | 281 } else if (!overlay.pageDiv.contains(document.activeElement)) { |
293 document.activeElement.blur(); | 282 document.activeElement.blur(); |
294 } | 283 } |
295 } | 284 } |
296 | 285 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 */ | 332 */ |
344 OptionsPage.closeOverlay = function() { | 333 OptionsPage.closeOverlay = function() { |
345 var overlay = this.getVisibleOverlay_(); | 334 var overlay = this.getVisibleOverlay_(); |
346 if (!overlay) | 335 if (!overlay) |
347 return; | 336 return; |
348 | 337 |
349 overlay.visible = false; | 338 overlay.visible = false; |
350 | 339 |
351 if (overlay.didClosePage) overlay.didClosePage(); | 340 if (overlay.didClosePage) overlay.didClosePage(); |
352 this.updateHistoryState_(false, {ignoreHash: true}); | 341 this.updateHistoryState_(false, {ignoreHash: true}); |
| 342 this.updateTitle_(); |
353 | 343 |
354 this.restoreLastFocusedElement_(); | 344 this.restoreLastFocusedElement_(); |
355 }; | 345 }; |
356 | 346 |
357 /** | 347 /** |
358 * Closes all overlays and updates the history after each closed overlay. | 348 * Closes all overlays and updates the history after each closed overlay. |
359 */ | 349 */ |
360 OptionsPage.closeAllOverlays = function() { | 350 OptionsPage.closeAllOverlays = function() { |
361 while (this.isOverlayVisible_()) { | 351 while (this.isOverlayVisible_()) { |
362 this.closeOverlay(); | 352 this.closeOverlay(); |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 canShowPage: function() { | 1009 canShowPage: function() { |
1020 return true; | 1010 return true; |
1021 }, | 1011 }, |
1022 }; | 1012 }; |
1023 | 1013 |
1024 // Export | 1014 // Export |
1025 return { | 1015 return { |
1026 OptionsPage: OptionsPage | 1016 OptionsPage: OptionsPage |
1027 }; | 1017 }; |
1028 }); | 1018 }); |
OLD | NEW |