Home | History | Annotate | Download | only in uber
      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