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 3 // found in the LICENSE file. 4 5 // This file contains the navigation controls that are visible on the left side 6 // of the uber page. It exists separately from uber.js so that it may be loaded 7 // in an iframe. Iframes can be layered on top of each other, but not mixed in 8 // with page content, so all overlapping content on uber must be framed. 9 10 <include src="../../../../ui/webui/resources/js/util.js"> 11 <include src="uber_utils.js"> 12 13 cr.define('uber_frame', function() { 14 15 /** 16 * Handles page initialization. 17 */ 18 function onLoad() { 19 var navigationItems = document.querySelectorAll('li'); 20 21 for (var i = 0; i < navigationItems.length; ++i) { 22 navigationItems[i].addEventListener('click', onNavItemClicked); 23 } 24 25 window.addEventListener('message', handleWindowMessage); 26 uber.invokeMethodOnParent('navigationControlsLoaded'); 27 28 document.documentElement.addEventListener('mousewheel', onMouseWheel); 29 cr.ui.FocusManager.disableMouseFocusOnButtons(); 30 } 31 32 /** 33 * Handles clicks on the navigation controls (switches the page and updates 34 * the URL). 35 * @param {Event} e The click event. 36 */ 37 function onNavItemClicked(e) { 38 // Though pointer-event: none; is applied to the .selected nav item, users 39 // can still tab to them and press enter/space which simulates a click. 40 if (e.target.classList.contains('selected')) 41 return; 42 43 // Extensions can override Uber content (e.g., if the user has a history 44 // extension, it should display when the 'History' navigation is clicked). 45 if (e.currentTarget.getAttribute('override') == 'yes') { 46 window.open('chrome://' + e.currentTarget.getAttribute('controls'), 47 '_blank'); 48 return; 49 } 50 51 uber.invokeMethodOnParent('showPage', 52 {pageId: e.currentTarget.getAttribute('controls')}); 53 54 setSelection(e.currentTarget); 55 } 56 57 /** 58 * Handles postMessage from chrome://chrome. 59 * @param {Event} e The post data. 60 */ 61 function handleWindowMessage(e) { 62 if (e.data.method === 'changeSelection') 63 changeSelection(e.data.params); 64 else if (e.data.method === 'adjustToScroll') 65 adjustToScroll(e.data.params); 66 else if (e.data.method === 'setContentChanging') 67 setContentChanging(e.data.params); 68 else 69 console.error('Received unexpected message', e.data); 70 } 71 72 /** 73 * Changes the selected nav control. 74 * @param {Object} params Must contain pageId. 75 */ 76 function changeSelection(params) { 77 var navItem = 78 document.querySelector('li[controls="' + params.pageId + '"]'); 79 setSelection(navItem); 80 showNavItems(); 81 } 82 83 /** 84 * @return {Element} The currently selected nav item, if any. 85 */ 86 function getSelectedNavItem() { 87 return document.querySelector('li.selected'); 88 } 89 90 /** 91 * Sets selection on the given nav item. 92 * @param {Element} newSelection The item to be selected. 93 */ 94 function setSelection(newSelection) { 95 var lastSelectedNavItem = getSelectedNavItem(); 96 if (lastSelectedNavItem !== newSelection) { 97 newSelection.classList.add('selected'); 98 if (lastSelectedNavItem) 99 lastSelectedNavItem.classList.remove('selected'); 100 } 101 } 102 103 /** 104 * Shows nav items belonging to the same group as the selected item. 105 */ 106 function showNavItems() { 107 var navItems = document.querySelectorAll('li'); 108 var selectedNavItem = getSelectedNavItem(); 109 assert(selectedNavItem); 110 111 var selectedGroup = selectedNavItem.getAttribute('group'); 112 for (var i = 0; i < navItems.length; ++i) { 113 navItems[i].hidden = navItems[i].getAttribute('group') != selectedGroup; 114 } 115 } 116 117 /** 118 * Adjusts this frame's content to scrolls from the outer frame. This is done 119 * to obscure text in RTL as a user scrolls over the content of this frame (as 120 * currently RTL scrollbars still draw on the right). 121 * @param {number} scroll document.body.scrollLeft of the content frame. 122 */ 123 function adjustToScroll(scrollLeft) { 124 assert(isRTL()); 125 document.body.style.webkitTransform = 'translateX(' + -scrollLeft + 'px)'; 126 } 127 128 /** 129 * Enable/disable an animation to ease the nav bar back into view when 130 * changing content while horizontally scrolled. 131 * @param {boolean} enabled Whether easing should be enabled. 132 */ 133 function setContentChanging(enabled) { 134 assert(isRTL()); 135 document.documentElement.classList[enabled ? 'add' : 'remove']( 136 'changing-content'); 137 } 138 139 /** 140 * Handles mouse wheels on the top level element. Forwards them to uber.js. 141 * @param {Event} e The mouse wheel event. 142 */ 143 function onMouseWheel(e) { 144 uber.invokeMethodOnParent('mouseWheel', 145 {deltaX: e.wheelDeltaX, deltaY: e.wheelDeltaY}); 146 } 147 148 /** 149 * @return {Element} The currently selected iframe container. 150 * @private 151 */ 152 function getSelectedIframe() { 153 return document.querySelector('.iframe-container.selected'); 154 } 155 156 /** 157 * Finds the <li> element whose 'controls' attribute is |controls| and sets 158 * its 'override' attribute to |override|. 159 * @param {string} controls The value of the 'controls' attribute of the 160 * element to change. 161 * @param {string} override The value to set for the 'override' attribute of 162 * that element (either 'yes' or 'no'). 163 */ 164 function setNavigationOverride(controls, override) { 165 var navItem = 166 document.querySelector('li[controls="' + controls + '"]'); 167 navItem.setAttribute('override', override); 168 } 169 170 return { 171 onLoad: onLoad, 172 setNavigationOverride: setNavigationOverride, 173 }; 174 175 }); 176 177 document.addEventListener('DOMContentLoaded', uber_frame.onLoad); 178