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 /** | 5 /** |
6 * @fileoverview A collection of utility methods for UberPage and its contained | 6 * @fileoverview A collection of utility methods for UberPage and its contained |
7 * pages. | 7 * pages. |
8 */ | 8 */ |
9 | 9 |
10 cr.define('uber', function() { | 10 cr.define('uber', function() { |
11 | 11 |
12 /** | 12 /** |
13 * Fixed position header elements on the page to be shifted by handleScroll. | 13 * Fixed position header elements on the page to be shifted by handleScroll. |
14 * @type {NodeList} | 14 * @type {NodeList} |
15 */ | 15 */ |
16 var headerElements; | 16 var headerElements; |
17 | 17 |
18 /** | 18 /** |
19 * This should be called by uber content pages when DOM content has loaded. | 19 * This should be called by uber content pages when DOM content has loaded. |
20 */ | 20 */ |
21 function onContentFrameLoaded() { | 21 function onContentFrameLoaded() { |
22 headerElements = document.getElementsByTagName('header'); | 22 headerElements = document.getElementsByTagName('header'); |
23 document.addEventListener('scroll', handleScroll); | 23 document.addEventListener('scroll', handleScroll); |
24 | 24 |
| 25 invokeMethodOnParent('ready'); |
| 26 |
25 // Prevent the navigation from being stuck in a disabled state when a | 27 // Prevent the navigation from being stuck in a disabled state when a |
26 // content page is reloaded while an overlay is visible (crbug.com/246939). | 28 // content page is reloaded while an overlay is visible (crbug.com/246939). |
27 invokeMethodOnParent('stopInterceptingEvents'); | 29 invokeMethodOnParent('stopInterceptingEvents'); |
28 | 30 |
29 // Trigger the scroll handler to tell the navigation if our page started | 31 // Trigger the scroll handler to tell the navigation if our page started |
30 // with some scroll (happens when you use tab restore). | 32 // with some scroll (happens when you use tab restore). |
31 handleScroll(); | 33 handleScroll(); |
32 | 34 |
33 window.addEventListener('message', handleWindowMessage); | 35 window.addEventListener('message', handleWindowMessage); |
34 } | 36 } |
(...skipping 18 matching lines...) Expand all Loading... |
53 | 55 |
54 /** | 56 /** |
55 * Handles 'message' events on window. | 57 * Handles 'message' events on window. |
56 * @param {Event} e The message event. | 58 * @param {Event} e The message event. |
57 */ | 59 */ |
58 function handleWindowMessage(e) { | 60 function handleWindowMessage(e) { |
59 if (e.data.method === 'frameSelected') | 61 if (e.data.method === 'frameSelected') |
60 handleFrameSelected(); | 62 handleFrameSelected(); |
61 else if (e.data.method === 'mouseWheel') | 63 else if (e.data.method === 'mouseWheel') |
62 handleMouseWheel(e.data.params); | 64 handleMouseWheel(e.data.params); |
| 65 else if (e.data.method === 'popState') |
| 66 handlePopState(e.data.params.state, e.data.params.path); |
63 } | 67 } |
64 | 68 |
65 /** | 69 /** |
66 * This is called when a user selects this frame via the navigation bar | 70 * This is called when a user selects this frame via the navigation bar |
67 * frame (and is triggered via postMessage() from the uber page). | 71 * frame (and is triggered via postMessage() from the uber page). |
68 * @private | 72 * @private |
69 */ | 73 */ |
70 function handleFrameSelected() { | 74 function handleFrameSelected() { |
71 setScrollTopForDocument(document, 0); | 75 setScrollTopForDocument(document, 0); |
72 } | 76 } |
73 | 77 |
74 /** | 78 /** |
75 * Called when a user mouse wheels (or trackpad scrolls) over the nav frame. | 79 * Called when a user mouse wheels (or trackpad scrolls) over the nav frame. |
76 * The wheel event is forwarded here and we scroll the body. | 80 * The wheel event is forwarded here and we scroll the body. |
77 * There's no way to figure out the actual scroll amount for a given delta. | 81 * There's no way to figure out the actual scroll amount for a given delta. |
78 * It differs for every platform and even initWebKitWheelEvent takes a | 82 * It differs for every platform and even initWebKitWheelEvent takes a |
79 * pixel amount instead of a wheel delta. So we just choose something | 83 * pixel amount instead of a wheel delta. So we just choose something |
80 * reasonable and hope no one notices the difference. | 84 * reasonable and hope no one notices the difference. |
81 * @param {Object} params A structure that holds wheel deltas in X and Y. | 85 * @param {Object} params A structure that holds wheel deltas in X and Y. |
82 */ | 86 */ |
83 function handleMouseWheel(params) { | 87 function handleMouseWheel(params) { |
84 window.scrollBy(-params.deltaX * 49 / 120, -params.deltaY * 49 / 120); | 88 window.scrollBy(-params.deltaX * 49 / 120, -params.deltaY * 49 / 120); |
85 } | 89 } |
86 | 90 |
| 91 function handlePopState(state, path) { |
| 92 history.replaceState(state, '', path); |
| 93 window.dispatchEvent(new PopStateEvent('popstate', {state: state})); |
| 94 } |
| 95 |
| 96 /** |
| 97 * Returns true if this frame has a parent. |
| 98 */ |
| 99 function hasParent() { |
| 100 return window != window.parent; |
| 101 } |
| 102 |
87 /** | 103 /** |
88 * Invokes a method on the parent window (UberPage). This is a convenience | 104 * Invokes a method on the parent window (UberPage). This is a convenience |
89 * method for API calls into the uber page. | 105 * method for API calls into the uber page. |
90 * @param {string} method The name of the method to invoke. | 106 * @param {string} method The name of the method to invoke. |
91 * @param {Object=} opt_params Optional property bag of parameters to pass to | 107 * @param {Object=} opt_params Optional property bag of parameters to pass to |
92 * the invoked method. | 108 * the invoked method. |
93 * @private | 109 * @private |
94 */ | 110 */ |
95 function invokeMethodOnParent(method, opt_params) { | 111 function invokeMethodOnParent(method, opt_params) { |
96 if (window.location == window.parent.location) | 112 if (!hasParent()) |
97 return; | 113 return; |
98 | 114 |
99 invokeMethodOnWindow(window.parent, method, opt_params, 'chrome://chrome'); | 115 invokeMethodOnWindow(window.parent, method, opt_params, 'chrome://chrome'); |
100 } | 116 } |
101 | 117 |
102 /** | 118 /** |
103 * Invokes a method on the target window. | 119 * Invokes a method on the target window. |
104 * @param {string} method The name of the method to invoke. | 120 * @param {string} method The name of the method to invoke. |
105 * @param {Object=} opt_params Optional property bag of parameters to pass to | 121 * @param {Object=} opt_params Optional property bag of parameters to pass to |
106 * the invoked method. | 122 * the invoked method. |
107 * @param {string=} opt_url The origin of the target window. | 123 * @param {string=} opt_url The origin of the target window. |
108 * @private | 124 * @private |
109 */ | 125 */ |
110 function invokeMethodOnWindow(targetWindow, method, opt_params, opt_url) { | 126 function invokeMethodOnWindow(targetWindow, method, opt_params, opt_url) { |
111 var data = {method: method, params: opt_params}; | 127 var data = {method: method, params: opt_params}; |
112 targetWindow.postMessage(data, opt_url ? opt_url : '*'); | 128 targetWindow.postMessage(data, opt_url ? opt_url : '*'); |
113 } | 129 } |
114 | 130 |
| 131 /** |
| 132 * Updates the page's history state. If the page is embedded in a child, |
| 133 * forward the information to the parent for it to manage history for us. This |
| 134 * is a replacement of history.replaceState and history.pushState. |
| 135 * @param {Object} state A state object for replaceState and pushState. |
| 136 * @param {string} title The title of the page to replace. |
| 137 * @param {string} path The path the page navigated to. |
| 138 * @param {boolean} replace If true, navigate with replacement. |
| 139 * @private |
| 140 */ |
| 141 function updateHistory(state, path, replace) { |
| 142 var historyFunction = replace ? |
| 143 window.history.replaceState : |
| 144 window.history.pushState; |
| 145 |
| 146 if (hasParent()) { |
| 147 // If there's a parent, always replaceState. The parent will do the actual |
| 148 // pushState. |
| 149 historyFunction = window.history.replaceState; |
| 150 invokeMethodOnParent('updateHistory', { |
| 151 state: state, path: path, replace: replace}); |
| 152 } |
| 153 historyFunction.call(window.history, state, '', '/' + path); |
| 154 } |
| 155 |
| 156 /** |
| 157 * Sets the current title for the page. If the page is embedded in a child, |
| 158 * forward the information to the parent. This is a replacement for setting |
| 159 * document.title. |
| 160 * @param {string} title The new title for the page. |
| 161 */ |
| 162 function setTitle(title) { |
| 163 document.title = title; |
| 164 invokeMethodOnParent('setTitle', {title: title}); |
| 165 } |
| 166 |
| 167 /** |
| 168 * Pushes new history state for the page. If the page is embedded in a child, |
| 169 * forward the information to the parent; when embedded, all history entries |
| 170 * are attached to the parent. This is a replacement of history.pushState. |
| 171 * @param {Object} state A state object for replaceState and pushState. |
| 172 * @param {string} path The path the page navigated to. |
| 173 */ |
| 174 function pushState(state, path) { |
| 175 updateHistory(state, path, false); |
| 176 } |
| 177 |
| 178 /** |
| 179 * Replaces the page's history state. If the page is embedded in a child, |
| 180 * forward the information to the parent; when embedded, all history entries |
| 181 * are attached to the parent. This is a replacement of history.replaceState. |
| 182 * @param {Object} state A state object for replaceState and pushState. |
| 183 * @param {string} path The path the page navigated to. |
| 184 */ |
| 185 function replaceState(state, path) { |
| 186 updateHistory(state, path, true); |
| 187 } |
| 188 |
115 return { | 189 return { |
116 invokeMethodOnParent: invokeMethodOnParent, | 190 invokeMethodOnParent: invokeMethodOnParent, |
117 invokeMethodOnWindow: invokeMethodOnWindow, | 191 invokeMethodOnWindow: invokeMethodOnWindow, |
118 onContentFrameLoaded: onContentFrameLoaded, | 192 onContentFrameLoaded: onContentFrameLoaded, |
| 193 pushState: pushState, |
| 194 replaceState: replaceState, |
| 195 setTitle: setTitle, |
119 }; | 196 }; |
120 }); | 197 }); |
OLD | NEW |