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('uber', function() { | 5 cr.define('uber', function() { |
6 | 6 |
7 /** | 7 /** |
8 * Handles page initialization. | 8 * Handles page initialization. |
9 */ | 9 */ |
10 function onLoad() { | 10 function onLoad() { |
11 var navigationItems = document.querySelectorAll('#navigation li'); | |
12 var iframes = document.querySelectorAll('.iframe-container'); | |
13 | |
14 for (var i = 0; i < navigationItems.length; ++i) { | |
15 var navItem = navigationItems[i]; | |
16 navItem.associatedIframe = iframes[i]; | |
17 iframes[i].associatedNavItem = navItem; | |
18 navItem.addEventListener('click', onNavItemClicked); | |
19 } | |
20 | |
21 // Update the URL if need be. | 11 // Update the URL if need be. |
22 if (window.location.pathname === '/') { | 12 if (window.location.pathname === '/') { |
23 var selectedNavItem = document.querySelector('#navigation li.selected'); | 13 var pageId = getSelectedIframe().id; |
24 var pageId = selectedNavItem.associatedIframe.id; | |
25 window.history.replaceState({pageId: pageId}, '', '/' + pageId); | 14 window.history.replaceState({pageId: pageId}, '', '/' + pageId); |
26 } | 15 } |
27 | 16 |
28 window.addEventListener('message', handleWindowMessage); | 17 window.addEventListener('message', handleWindowMessage); |
29 } | 18 } |
30 | 19 |
31 /** | 20 /** |
32 * Handles clicks on the navigation controls (switches the page and updates | |
33 * the URL). | |
34 * @param {Event} e The click event. | |
35 */ | |
36 function onNavItemClicked(e) { | |
37 if (selectPageForNavItem(e.currentTarget)) { | |
38 var pageId = e.currentTarget.associatedIframe.id; | |
39 window.history.pushState({pageId: pageId}, '', '/' + pageId); | |
40 } | |
41 } | |
42 | |
43 /** | |
44 * Selects the page for |navItem|, or does nothing if that item has already | 21 * Selects the page for |navItem|, or does nothing if that item has already |
45 * been selected. | 22 * been selected. |
46 * @param {Object} navItem The navigation control li. | 23 * @param {Object} navItem The navigation control li. |
47 * @return {boolean} True if the item became selected, false if it had already | 24 * @return {boolean} True if the item became selected, false if it had already |
48 * been selected. | 25 * been selected. |
49 */ | 26 */ |
50 function selectPageForNavItem(navItem) { | 27 function selectPageForNavItem(navItem) { |
51 // Note that |iframe| is the containing element of the underlying iframe, as | 28 // Note that |iframe| is the containing element of the underlying iframe, as |
52 // opposed to the iframe element itself. | 29 // opposed to the iframe element itself. |
53 var iframe = navItem.associatedIframe; | 30 var iframe = navItem.associatedIframe; |
54 var currentIframe = getSelectedIframe_(); | 31 var currentIframe = getSelectedIframe(); |
55 if (currentIframe == iframe) | 32 if (currentIframe == iframe) |
56 return false; | 33 return false; |
57 | 34 |
58 // Restore the cached title. | 35 // Restore the cached title. |
59 if (iframe.title) | 36 if (iframe.title) |
60 document.title = iframe.title; | 37 document.title = iframe.title; |
61 | 38 |
39 console.log('removing'); | |
Dan Beam
2012/01/20 00:59:02
remove the removing
Evan Stade
2012/01/20 03:27:07
Done.
| |
62 currentIframe.classList.remove('selected'); | 40 currentIframe.classList.remove('selected'); |
63 iframe.classList.add('selected'); | 41 iframe.classList.add('selected'); |
64 | 42 |
65 var currentNavItem = document.querySelector('li.selected'); | 43 var currentNavItem = document.querySelector('li.selected'); |
66 currentNavItem.classList.remove('selected'); | 44 currentNavItem.classList.remove('selected'); |
67 navItem.classList.add('selected'); | 45 navItem.classList.add('selected'); |
68 | 46 |
69 return true; | 47 return true; |
70 } | 48 } |
71 | 49 |
72 /** | 50 /** |
73 * Handler for window.onpopstate. | 51 * Handler for window.onpopstate. |
74 * @param {Event} e The history event. | 52 * @param {Event} e The history event. |
75 */ | 53 */ |
76 function onPopHistoryState(e) { | 54 function onPopHistoryState(e) { |
77 if (e.state && e.state.pageId) | 55 if (e.state && e.state.pageId) |
78 selectPageForNavItem($(e.state.pageId).associatedNavItem); | 56 showPage(e.state.pageId); |
79 } | 57 } |
80 | 58 |
81 /** | 59 /** |
82 * @return {Object} The currently selected iframe container. | 60 * @return {Object} The currently selected iframe container. |
83 * @private | 61 * @private |
csilv
2012/01/20 03:30:11
The naming change implies that this is no longer p
Evan Stade
2012/01/20 03:36:07
good catch, i should remove @private
| |
84 */ | 62 */ |
85 function getSelectedIframe_() { | 63 function getSelectedIframe() { |
86 return document.querySelector('.iframe-container.selected'); | 64 return document.querySelector('.iframe-container.selected'); |
87 } | 65 } |
88 | 66 |
89 /** | 67 /** |
90 * Handles postMessage calls from the iframes of the contained pages. | 68 * Handles postMessage calls from the iframes of the contained pages. |
91 * | 69 * |
92 * The pages request functionality from this object by passing an object of | 70 * The pages request functionality from this object by passing an object of |
93 * the following form: | 71 * the following form: |
94 * | 72 * |
95 * { method : "methodToInvoke", | 73 * { method : "methodToInvoke", |
96 * params : {...} | 74 * params : {...} |
97 * } | 75 * } |
98 * | 76 * |
99 * |method| is required, while |params| is optional. Extra parameters required | 77 * |method| is required, while |params| is optional. Extra parameters required |
100 * by a method must be specified by that method's documentation. | 78 * by a method must be specified by that method's documentation. |
101 * | 79 * |
102 * @param {Event} e The posted object. | 80 * @param {Event} e The posted object. |
103 */ | 81 */ |
104 function handleWindowMessage(e) { | 82 function handleWindowMessage(e) { |
105 if (e.data.method === 'showOverlay') | 83 if (e.data.method === 'beginInterceptingEvents') |
106 showOverlay_(); | 84 backgroundNavigation(); |
107 else if (e.data.method === 'hideOverlay') | 85 else if (e.data.method === 'stopInterceptingEvents') |
108 hideOverlay_(); | 86 foregroundNavigation(); |
109 else if (e.data.method === 'setTitle') | 87 else if (e.data.method === 'setTitle') |
110 setTitle_(e.origin, e.data.params); | 88 setTitle_(e.origin, e.data.params); |
89 else if (e.data.method === 'showPage') | |
90 showPage(e.data.params.pageId); | |
91 else if (e.data.method === 'navigationControlsLoaded') | |
92 onNavigationControlsLoaded(); | |
111 else | 93 else |
112 console.error('Received unexpected message: ' + e.data); | 94 console.error('Received unexpected message: ' + e.data); |
113 } | 95 } |
114 | 96 |
115 /** | 97 /** |
116 * @private | 98 * @private |
117 */ | 99 */ |
118 function showOverlay_() { | 100 function backgroundNavigation() { |
csilv
2012/01/20 03:30:11
Why remove the underscores on these two methods?
Evan Stade
2012/01/20 03:36:07
because they are not methods, they are functions
| |
119 document.querySelector('.overlay').classList.add('showing'); | 101 $('navigation').classList.add('background'); |
120 } | 102 } |
121 | 103 |
122 /** | 104 /** |
123 * @private | 105 * @private |
124 */ | 106 */ |
125 function hideOverlay_() { | 107 function foregroundNavigation() { |
126 document.querySelector('.overlay').classList.remove('showing'); | 108 $('navigation').classList.remove('background'); |
127 } | 109 } |
128 | 110 |
129 /** | 111 /** |
130 * Sets the title of the page. | 112 * Sets the title of the page. |
131 * @param {Object} origin The origin of the source iframe. | 113 * @param {Object} origin The origin of the source iframe. |
132 * @param {Object} params Must contain a |title| property. | 114 * @param {Object} params Must contain a |title| property. |
133 * @private | 115 * @private |
134 */ | 116 */ |
135 function setTitle_(origin, params) { | 117 function setTitle_(origin, params) { |
136 // |iframe.src| always contains a trailing backslash while |origin| does not | 118 // |iframe.src| always contains a trailing backslash while |origin| does not |
137 // so add the trailing source for normalization. | 119 // so add the trailing source for normalization. |
138 var query = '.iframe-container > iframe[src="' + origin + '/"]'; | 120 var query = '.iframe-container > iframe[src="' + origin + '/"]'; |
139 | 121 |
140 // Cache the title for the client iframe, i.e., the iframe setting the | 122 // Cache the title for the client iframe, i.e., the iframe setting the |
141 // title. querySelector returns the actual iframe element, so use parentNode | 123 // title. querySelector returns the actual iframe element, so use parentNode |
142 // to get back to the container. | 124 // to get back to the container. |
143 var container = document.querySelector(query).parentNode; | 125 var container = document.querySelector(query).parentNode; |
144 container.title = params.title; | 126 container.title = params.title; |
145 | 127 |
146 // Only update the currently displayed title if this is the visible frame. | 128 // Only update the currently displayed title if this is the visible frame. |
147 if (container == getSelectedIframe_()) | 129 if (container == getSelectedIframe()) |
148 document.title = params.title; | 130 document.title = params.title; |
149 } | 131 } |
150 | 132 |
133 /** | |
134 * Selects a subpage. This is called from uber-frame. | |
135 * @param {String} pageId Should matche an id of one of the iframe containers. | |
136 */ | |
137 function showPage(pageId) { | |
138 var container = $(pageId); | |
139 var lastSelected = document.querySelector('.iframe-container.selected'); | |
140 if (lastSelected === container) | |
141 return; | |
142 | |
143 console.log('removing'); | |
Dan Beam
2012/01/20 00:59:02
here too
| |
144 lastSelected.classList.remove('selected'); | |
145 container.classList.add('selected'); | |
146 document.title = container.title; | |
147 | |
148 window.history.pushState({pageId: pageId}, '', '/' + pageId); | |
149 updateNavigationControls(); | |
150 } | |
151 | |
152 function onNavigationControlsLoaded() { | |
153 updateNavigationControls(); | |
154 } | |
155 | |
156 /** | |
157 * Sends a message to uber-frame to update the appearance of the nav controls. | |
158 * It should be called whenever the selected iframe changes. | |
159 */ | |
160 function updateNavigationControls() { | |
161 var iframe = getSelectedIframe(); | |
162 uber.invokeMethodOnWindow($('navigation').firstChild.contentWindow, | |
163 'changeSelection', {pageId: iframe.id}); | |
164 } | |
165 | |
151 return { | 166 return { |
152 onLoad: onLoad, | 167 onLoad: onLoad, |
153 onPopHistoryState: onPopHistoryState | 168 onPopHistoryState: onPopHistoryState |
154 }; | 169 }; |
155 | 170 |
156 }); | 171 }); |
157 | 172 |
158 window.addEventListener('popstate', uber.onPopHistoryState); | 173 window.addEventListener('popstate', uber.onPopHistoryState); |
159 document.addEventListener('DOMContentLoaded', uber.onLoad); | 174 document.addEventListener('DOMContentLoaded', uber.onLoad); |
OLD | NEW |