15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('uber', function() { 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Options for how web history should be handled. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var HISTORY_STATE_OPTION = { 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PUSH: 1, // Push a new history state. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REPLACE: 2, // Replace the current history state. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NONE: 3, // Ignore this history state change. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We cache a reference to the #navigation frame here so we don't need to grab 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it from the DOM on each scroll. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {Node} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var navFrame; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * A queue of method invocations on one of the iframes; if the iframe has not 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * loaded by the time there is a method to invoke, delay the invocation until 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * it is ready. 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @type {Object} 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @private 29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var queuedInvokes = {}; 31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles page initialization. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function onLoad(e) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame = $('navigation'); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.dataset.width = navFrame.offsetWidth; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Select a page based on the page-URL. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var params = resolvePageInfo(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) showPage(params.id, HISTORY_STATE_OPTION.NONE, params.path); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.addEventListener('message', handleWindowMessage); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.setTimeout(function() { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document.documentElement.classList.remove('loading'); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 0); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HACK(dbeam): This makes the assumption that any second part to a path 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will result in needing background navigation. We shortcut it to avoid 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flicker on load. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HACK(csilv): Search URLs aren't overlays, special case them. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params.id == 'settings' && params.path && 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.path.indexOf('search') != 0) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backgroundNavigation(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ensureNonSelectedFrameContainersAreHidden(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Find page information from window.location. If the location doesn't 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * point to one of our pages, return default parameters. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Object} An object containing the following parameters: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * id - The 'id' of the page. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * path - A path into the page, including search and hash. Optional. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function resolvePageInfo() { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var params = {}; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var path = window.location.pathname; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (path.length > 1) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Split the path into id and the remaining path. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path = path.slice(1); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = path.indexOf('/'); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != -1) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.id = path.slice(0, index); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.path = path.slice(index + 1); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.id = path; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var container = $(params.id); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (container) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The id is valid. Add the hash and search parts of the URL to path. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.path = (params.path || '') + window.location.search + 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window.location.hash; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The target sub-page does not exist, discard the params we generated. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.id = undefined; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.path = undefined; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have a valid page, get a default. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!params.id) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.id = getDefaultIframe().id; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return params; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handler for window.onpopstate. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The history event. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function onPopHistoryState(e) { 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Use the URL to determine which page to route to. 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) var params = resolvePageInfo(); 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // If the page isn't the current page, load it fresh. Even if the page is 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // already loaded, it may have state not reflected in the URL, such as the 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // history page's "Remove selected items" overlay. http://crbug.com/377386 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (getRequiredElement(params.id) !== getSelectedIframe()) 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) showPage(params.id, HISTORY_STATE_OPTION.NONE, params.path); 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Either way, send the state down to it. 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // 11546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Note: This assumes that the state and path parameters for every page 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // under this origin are compatible. All of the downstream pages which 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // navigate use pushState and replaceState. 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) invokeMethodOnPage(params.id, 'popState', 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) {state: e.state, path: '/' + params.path}); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Object} The default iframe container. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getDefaultIframe() { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return $(loadTimeData.getString('helpHost')); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Object} The currently selected iframe container. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getSelectedIframe() { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return document.querySelector('.iframe-container.selected'); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles postMessage calls from the iframes of the contained pages. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The pages request functionality from this object by passing an object of 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the following form: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * { method : "methodToInvoke", 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * params : {...} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * |method| is required, while |params| is optional. Extra parameters required 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * by a method must be specified by that method's documentation. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The posted object. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function handleWindowMessage(e) { 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) e = /** @type{!MessageEvent.<!{method: string, params: *}>} */(e); 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (e.data.method === 'beginInterceptingEvents') { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backgroundNavigation(); 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (e.data.method === 'stopInterceptingEvents') { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) foregroundNavigation(); 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (e.data.method === 'ready') { 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) pageReady(e.origin); 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (e.data.method === 'updateHistory') { 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) updateHistory(e.origin, e.data.params.state, e.data.params.path, 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) e.data.params.replace); 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (e.data.method === 'setTitle') { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTitle(e.origin, e.data.params.title); 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (e.data.method === 'showPage') { 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) showPage(e.data.params.pageId, 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HISTORY_STATE_OPTION.PUSH, 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) e.data.params.path); 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (e.data.method === 'navigationControlsLoaded') { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onNavigationControlsLoaded(); 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (e.data.method === 'adjustToScroll') { 1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) adjustToScroll(/** @type {number} */(e.data.params)); 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (e.data.method === 'mouseWheel') { 1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) forwardMouseWheel(/** @type {Object} */(e.data.params)); 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.error('Received unexpected message', e.data); 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sends the navigation iframe to the background. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function backgroundNavigation() { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.classList.add('background'); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.firstChild.tabIndex = -1; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.firstChild.setAttribute('aria-hidden', true); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Retrieves the navigation iframe from the background. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function foregroundNavigation() { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.classList.remove('background'); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.firstChild.tabIndex = 0; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.firstChild.removeAttribute('aria-hidden'); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Enables or disables animated transitions when changing content while 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * horizontally scrolled. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} enabled True if enabled, else false to disable. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function setContentChanging(enabled) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.classList[enabled ? 'add' : 'remove']('changing-content'); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isRTL()) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow, 2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 'setContentChanging', enabled); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Get an iframe based on the origin of a received post message. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} origin The origin of a post message. 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * @return {!Element} The frame associated to |origin| or null. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function getIframeFromOrigin(origin) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(origin.substr(-1) != '/', 'invalid origin given'); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var query = '.iframe-container > iframe[src^="' + origin + '/"]'; 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) var element = document.querySelector(query); 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) assert(element); 2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return /** @type {!Element} */(element); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Changes the path past the page title (i.e. chrome://chrome/settings/(.*)). 226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} state The page's state object for the navigation. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} path The new /path/ to be set after the page name. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} historyOption The type of history modification to make. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) function changePathTo(state, path, historyOption) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!path || path.substr(-1) != '/', 'invalid path given'); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var histFunc; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (historyOption == HISTORY_STATE_OPTION.PUSH) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histFunc = window.history.pushState; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (historyOption == HISTORY_STATE_OPTION.REPLACE) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histFunc = window.history.replaceState; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(histFunc, 'invalid historyOption given ' + historyOption); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var pageId = getSelectedIframe().id; 24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) var args = [state, '', '/' + pageId + '/' + (path || '')]; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) histFunc.apply(window.history, args); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Adds or replaces the current history entry based on a navigation from the 248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * source iframe. 249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} origin The origin of the source iframe. 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object} state The source iframe's state object. 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} path The new "path" (e.g. "/createProfile"). 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {boolean} replace Whether to replace the current history entry. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) function updateHistory(origin, state, path, replace) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!path || path[0] != '/', 'invalid path sent from ' + origin); 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var historyOption = 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) replace ? HISTORY_STATE_OPTION.REPLACE : HISTORY_STATE_OPTION.PUSH; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only update the currently displayed path if this is the visible frame. 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var container = getIframeFromOrigin(origin).parentNode; 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (container == getSelectedIframe()) 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) changePathTo(state, path, historyOption); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sets the title of the page. 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} origin The origin of the source iframe. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} title The title of the page. 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function setTitle(origin, title) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cache the title for the client iframe, i.e., the iframe setting the 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // title. querySelector returns the actual iframe element, so use parentNode 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to get back to the container. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var container = getIframeFromOrigin(origin).parentNode; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container.dataset.title = title; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only update the currently displayed title if this is the visible frame. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (container == getSelectedIframe()) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document.title = title; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Invokes a method on a subpage. If the subpage has not signaled readiness, 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * queue the message for when it does. 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} pageId Should match an id of one of the iframe containers. 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} method The name of the method to invoke. 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {Object=} opt_params Optional property page of parameters to pass to 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * the invoked method. 288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) function invokeMethodOnPage(pageId, method, opt_params) { 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var frame = $(pageId).querySelector('iframe'); 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!frame || !frame.dataset.ready) { 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) queuedInvokes[pageId] = (queuedInvokes[pageId] || []); 293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) queuedInvokes[pageId].push([method, opt_params]); 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uber.invokeMethodOnWindow(frame.contentWindow, method, opt_params); 296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Called in response to a page declaring readiness. Calls any deferred method 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * invocations from invokeMethodOnPage. 302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * @param {string} origin The origin of the source iframe. 303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) */ 304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) function pageReady(origin) { 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var frame = getIframeFromOrigin(origin); 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var container = frame.parentNode; 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frame.dataset.ready = true; 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var queue = queuedInvokes[container.id] || []; 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) queuedInvokes[container.id] = undefined; 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (var i = 0; i < queue.length; i++) { 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uber.invokeMethodOnWindow(frame.contentWindow, queue[i][0], queue[i][1]); 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) /** 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) * Selects and navigates a subpage. This is called from uber-frame. 317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * @param {string} pageId Should match an id of one of the iframe containers. 3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) * @param {number} historyOption Indicates whether we should push or replace 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * browser history. 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {string} path A sub-page path. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function showPage(pageId, historyOption, path) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var container = $(pageId); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lazy load of iframe contents. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var sourceUrl = container.dataset.url + (path || ''); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var frame = container.querySelector('iframe'); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame = container.ownerDocument.createElement('iframe'); 330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch frame.name = pageId; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container.appendChild(frame); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame.src = sourceUrl; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's no particularly good way to know what the current URL of the 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content frame is as we don't have access to its contentWindow's 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // location, so just replace every time until necessary to do otherwise. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame.contentWindow.location.replace(sourceUrl); 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frame.dataset.ready = false; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the last selected container is already showing, ignore the rest. 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) var lastSelected = document.querySelector('.iframe-container.selected'); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lastSelected === container) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (lastSelected) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastSelected.classList.remove('selected'); 348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Setting aria-hidden hides the container from assistive technology 349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // immediately. The 'hidden' attribute is set after the transition 350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // finishes - that ensures it's not possible to accidentally focus 351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // an element in an unselected container. 352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) lastSelected.setAttribute('aria-hidden', 'true'); 353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Containers that aren't selected have to be hidden so that their 356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // content isn't focusable. 357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) container.hidden = false; 358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) container.setAttribute('aria-hidden', 'false'); 359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Trigger a layout after making it visible and before setting 361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // the class to 'selected', so that it animates in. 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** @suppress {uselessCode} */ 363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) container.offsetTop; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container.classList.add('selected'); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setContentChanging(true); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adjustToScroll(0); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var selectedFrame = getSelectedIframe().querySelector('iframe'); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uber.invokeMethodOnWindow(selectedFrame.contentWindow, 'frameSelected'); 37134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) selectedFrame.contentWindow.focus(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (historyOption != HISTORY_STATE_OPTION.NONE) 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) changePathTo({}, path, historyOption); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (container.dataset.title) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document.title = container.dataset.title; 3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) assert('favicon' in container.dataset); 3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) var dataset = /** @type {{favicon: string}} */(container.dataset); 3816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) $('favicon').href = 'chrome://theme/' + dataset.favicon; 3826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) $('favicon2x').href = 'chrome://theme/' + dataset.favicon + '@2x'; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateNavigationControls(); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function onNavigationControlsLoaded() { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateNavigationControls(); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sends a message to uber-frame to update the appearance of the nav controls. 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * It should be called whenever the selected iframe changes. 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function updateNavigationControls() { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var iframe = getSelectedIframe(); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'changeSelection', {pageId: iframe.id}); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Forwarded scroll offset from a content frame's scroll handler. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} scrollOffset The scroll offset from the content frame. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function adjustToScroll(scrollOffset) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: The scroll is reset to 0 and easing turned on every time a user 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // switches frames. If we receive a non-zero value it has to have come from 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a real user scroll, so we disable easing when this happens. 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scrollOffset != 0) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setContentChanging(false); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isRTL()) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uber.invokeMethodOnWindow(navFrame.firstChild.contentWindow, 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'adjustToScroll', 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scrollOffset); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var navWidth = Math.max(0, +navFrame.dataset.width + scrollOffset); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.style.width = navWidth + 'px'; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) navFrame.style.webkitTransform = 'translateX(' + -scrollOffset + 'px)'; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Forward scroll wheel events to subpages. 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Object} params Relevant parameters of wheel event. 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function forwardMouseWheel(params) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var iframe = getSelectedIframe().querySelector('iframe'); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uber.invokeMethodOnWindow(iframe.contentWindow, 'mouseWheel', params); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) /** 433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * Make sure that iframe containers that are not selected are 434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * hidden, so that elements in those frames aren't part of the 435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * focus order. Containers that are unselected later get hidden 436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * when the transition ends. We also set the aria-hidden attribute 437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * because that hides the container from assistive technology 438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) * immediately, rather than only after the transition ends. 439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) */ 440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) function ensureNonSelectedFrameContainersAreHidden() { 441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) var containers = document.querySelectorAll('.iframe-container'); 442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (var i = 0; i < containers.length; i++) { 443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) var container = containers[i]; 444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!container.classList.contains('selected')) { 445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) container.hidden = true; 446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) container.setAttribute('aria-hidden', 'true'); 447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) container.addEventListener('webkitTransitionEnd', function(event) { 449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!event.target.classList.contains('selected')) 450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) event.target.hidden = true; 451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) }); 452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onLoad: onLoad, 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onPopHistoryState: onPopHistoryState 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)window.addEventListener('popstate', uber.onPopHistoryState); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)document.addEventListener('DOMContentLoaded', uber.onLoad); 463