Chromium Code Reviews| 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 |