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)/** 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview Card slider implementation. Allows you to create interactions 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that have items that can slide left to right to reveal additional items. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Works by adding the necessary event handlers to a specific DOM structure 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * including a frame, container and cards. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - The frame defines the boundary of one item. Each card will be expanded to 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fill the width of the frame. This element is also overflow hidden so that 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the additional items left / right do not trigger horizontal scrolling. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - The container is what all the touch events are attached to. This element 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be expanded to be the width of all cards. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - The cards are the individual viewable items. There should be one card for 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * each item in the list. Only one card will be visible at a time. Two cards 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be visible while you are transitioning between cards. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This class is designed to work well on any hardware-accelerated touch device. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * It should still work on pre-hardware accelerated devices it just won't feel 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * very good. It should also work well with a mouse. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use an anonymous function to enable strict mode just for this file (which 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will be concatenated with other files when embedded in Chrome 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cr.define('cr.ui', function() { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'use strict'; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Element} frame The bounding rectangle that cards are visible in. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Element} container The surrounding element that will have event 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * listeners attached to it. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} cardWidth The width of each card should have. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function CardSlider(frame, container, cardWidth) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {!Element} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.frame_ = frame; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {!Element} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_ = container; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Array of card elements. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {!Array.<!Element>} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_ = []; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Index of currently shown card. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {number} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentCard_ = -1; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {number} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cardWidth_ = cardWidth; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {!cr.ui.TouchHandler} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touchHandler_ = new cr.ui.TouchHandler(this.container_); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The time to transition between cards when animating. Measured in ms. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {number} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @const 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CardSlider.TRANSITION_TIME_ = 200; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The minimum velocity required to transition cards if they did not drag past 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the halfway point between cards. Measured in pixels / ms. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {number} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @const 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CardSlider.TRANSITION_VELOCITY_THRESHOLD_ = 0.2; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CardSlider.prototype = { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The current left offset of the container relative to the frame. This 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * position does not include deltas from active drag operations, and 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * always aligns with a frame boundary. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {number} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) currentLeft_: 0, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Current offset relative to |currentLeft_| due to an active drag 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * operation. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {number} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deltaX_: 0, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Initialize all elements and event handlers. Must call after construction 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and before usage. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} ignoreMouseWheelEvents If true, horizontal mouse wheel 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * events will be ignored, rather than flipping between pages. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialize: function(ignoreMouseWheelEvents) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var view = this.container_.ownerDocument.defaultView; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(view.getComputedStyle(this.container_).display == '-webkit-box', 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Container should be display -webkit-box.'); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(view.getComputedStyle(this.frame_).overflow == 'hidden', 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Frame should be overflow hidden.'); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(view.getComputedStyle(this.container_).position == 'static', 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Container should be position static.'); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateCardWidths_(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelScrollAmount_ = 0; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelCardSelected_ = false; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelIsContinuous_ = false; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.scrollClearTimeout_ = null; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ignoreMouseWheelEvents) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.frame_.addEventListener('mousewheel', 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onMouseWheel_.bind(this)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.addEventListener( 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'webkitTransitionEnd', this.onWebkitTransitionEnd_.bind(this)); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also support touch events in case a touch screen happens to be 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // available. Note that this has minimal impact in the common case of 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no touch events (eg. we're mainly just adding listeners for events that 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will never trigger). 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var TouchHandler = cr.ui.TouchHandler; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.addEventListener(TouchHandler.EventType.TOUCH_START, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onTouchStart_.bind(this)); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.addEventListener(TouchHandler.EventType.DRAG_START, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onDragStart_.bind(this)); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.addEventListener(TouchHandler.EventType.DRAG_MOVE, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onDragMove_.bind(this)); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.addEventListener(TouchHandler.EventType.DRAG_END, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onDragEnd_.bind(this)); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touchHandler_.enable(/* opt_capture */ false); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use in cases where the width of the frame has changed in order to update 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the width of cards. For example should be used when orientation changes 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in full width sliders. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} newCardWidth Width all cards should have, in pixels. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize: function(newCardWidth) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newCardWidth != this.cardWidth_) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cardWidth_ = newCardWidth; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateCardWidths_(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must upate the transform on the container to show the correct card. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.transformToCurrentCard_(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sets the cards used. Can be called more than once to switch card sets. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Array.<!Element>} cards The individual viewable cards. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index Index of the card to in the new set of cards to 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * navigate to. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setCards: function(cards, index) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(index >= 0 && index < cards.length, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Invalid index in CardSlider#setCards'); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_ = cards; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateCardWidths_(); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateSelectedCardAttributes_(); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Jump to the given card index. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectCard(index, false, false, true); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Ensures that for all cards: 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - if the card is the current card, then it has 'selected-card' in its 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * classList, and is visible for accessibility 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - if the card is not the selected card, then it does not have 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'selected-card' in its classList, and is invisible for accessibility. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateSelectedCardAttributes_: function() { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i < this.cards_.length; i++) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == this.currentCard_) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_[i].classList.add('selected-card'); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_[i].removeAttribute('aria-hidden'); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_[i].classList.remove('selected-card'); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_[i].setAttribute('aria-hidden', true); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Updates the width of each card. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) updateCardWidths_: function() { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0, card; card = this.cards_[i]; i++) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) card.style.width = this.cardWidth_ + 'px'; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the index of the current card. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} index of the current card. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get currentCard() { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.currentCard_; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Allows setting the current card index. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index A new index to set the current index to. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} The new index after having been set. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set currentCard(index) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (this.currentCard_ = index); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the number of cards. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {number} number of cards. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get cardCount() { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.cards_.length; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the current card itself. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {!Element} the currently shown card. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get currentCardValue() { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.cards_[this.currentCard_]; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the frame holding the cards. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Element} The frame used to position the cards. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get frame() { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this.frame_; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle horizontal scrolls to flip between pages. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onMouseWheel_: function(e) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.wheelDeltaX == 0) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Continuous devices such as an Apple Touchpad or Apple MagicMouse will 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // send arbitrary delta values. Conversly, standard mousewheels will 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // send delta values in increments of 120. (There is of course a small 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // chance we mistake a continuous device for a non-continuous device. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unfortunately there isn't a better way to do this until real touch 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // events are available to desktop clients.) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var DISCRETE_DELTA = 120; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.wheelDeltaX % DISCRETE_DELTA) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelIsContinuous_ = true; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.mouseWheelIsContinuous_) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For continuous devices, detect a page swipe when the accumulated 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delta matches a pre-defined threshhold. After changing the page, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ignore wheel events for a short time before repeating this process. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.mouseWheelCardSelected_) return; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelScrollAmount_ += e.wheelDeltaX; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Math.abs(this.mouseWheelScrollAmount_) >= 600) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var pagesToScroll = this.mouseWheelScrollAmount_ > 0 ? 1 : -1; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isRTL()) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesToScroll *= -1; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCardIndex = this.currentCard + pagesToScroll; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCardIndex = Math.min(this.cards_.length - 1, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Math.max(0, newCardIndex)); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectCard(newCardIndex, true); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelCardSelected_ = true; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For discrete devices, consider each wheel tick a page change. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var pagesToScroll = e.wheelDeltaX / DISCRETE_DELTA; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isRTL()) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesToScroll *= -1; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCardIndex = this.currentCard + pagesToScroll; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCardIndex = Math.min(this.cards_.length - 1, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Math.max(0, newCardIndex)); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectCard(newCardIndex, true); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We got a mouse wheel event, so cancel any pending scroll wheel timeout. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.scrollClearTimeout_ != null) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearTimeout(this.scrollClearTimeout_); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't use up all the scroll, hold onto it for a little bit, but 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drop it after a delay. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.mouseWheelScrollAmount_ != 0) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.scrollClearTimeout_ = 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(this.clearMouseWheelScroll_.bind(this), 500); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Resets the amount of horizontal scroll we've seen to 0. See 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * onMouseWheel_. 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearMouseWheelScroll_: function() { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelScrollAmount_ = 0; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseWheelCardSelected_ = false; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles the ends of -webkit-transitions on -webkit-transform (animated 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * card switches). 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e The webkitTransitionEnd event. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onWebkitTransitionEnd_: function(e) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore irrelevant transitions that might bubble up. 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (e.target !== this.container_ || 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.propertyName != '-webkit-transform') { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fireChangeEndedEvent_(true); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Dispatches a simple event to tell subscribers we're done moving to the 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * newly selected card. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} wasAnimated whether or not the change was animated. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fireChangeEndedEvent_: function(wasAnimated) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var e = document.createEvent('Event'); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.initEvent('cardSlider:card_change_ended', true, true); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.cardSlider = this; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.changedTo = this.currentCard_; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.wasAnimated = wasAnimated; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.dispatchEvent(e); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add a card to the card slider at a particular index. If the card being 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * added is inserted in front of the current card, cardSlider.currentCard 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be adjusted accordingly (to current card + 1). 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Node} card A card that will be added to the card slider. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index An index at which the given |card| should be 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * inserted. Must be positive and less than the number of cards. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addCardAtIndex: function(card, index) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(card instanceof Node, '|card| isn\'t a Node'); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.assertValidIndex_(index); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_ = Array.prototype.concat.call( 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_.slice(0, index), card, this.cards_.slice(index)); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateSelectedCardAttributes_(); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.currentCard_ == -1) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentCard_ = 0; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (index <= this.currentCard_) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectCard(this.currentCard_ + 1, false, true, true); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fireAddedEvent_(card, index); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Append a card to the end of the list. 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Node} card A card to add at the end of the card slider. 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) appendCard: function(card) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(card instanceof Node, '|card| isn\'t a Node'); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.cards_.push(card); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fireAddedEvent_(card, this.cards_.length - 1); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Dispatches a simple event to tell interested subscribers that a card was 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * added to this card slider. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Node} card The recently added card. 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The position of the newly added card. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fireAddedEvent_: function(card, index) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.assertValidIndex_(index); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var e = document.createEvent('Event'); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.initEvent('cardSlider:card_added', true, true); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.addedIndex = index; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.addedCard = card; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.dispatchEvent(e); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Returns the card at a particular index. 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {number} index The index of the card to return. 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return {!Element} The card at the given index. 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) getCardAtIndex: function(index) { 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.assertValidIndex_(index); 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return this.cards_[index]; 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }, 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Removes a card by index from the card slider. If the card to be removed 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is the current card or in front of the current card, the current card 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be updated (to current card - 1). 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!Node} card A card to be removed. 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removeCard: function(card) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(card instanceof Node, '|card| isn\'t a Node'); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeCardAtIndex(this.cards_.indexOf(card)); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Removes a card by index from the card slider. If the card to be removed 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is the current card or in front of the current card, the current card 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be updated (to current card - 1). 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the tile that should be removed. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removeCardAtIndex: function(index) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.assertValidIndex_(index); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var removed = this.cards_.splice(index, 1).pop(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.cards_.length == 0) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentCard_ = -1; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (index < this.currentCard_) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectCard(this.currentCard_ - 1, false, true); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fireRemovedEvent_(removed, index); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Dispatches a cardSlider:card_removed event so interested subscribers know 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * when a card was removed from this card slider. 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Node} card The recently removed card. 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index The index of the card before it was removed. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fireRemovedEvent_: function(card, index) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var e = document.createEvent('Event'); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.initEvent('cardSlider:card_removed', true, true); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.removedCard = card; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.removedIndex = index; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.dispatchEvent(e); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This re-syncs the -webkit-transform that's used to position the frame in 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the likely event it needs to be updated by a card being inserted or 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * removed in the flow. 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) repositionFrame: function() { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.transformToCurrentCard_(); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Checks the the given |index| exists in this.cards_. 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index An index to check. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assertValidIndex_: function(index) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(index >= 0 && index < this.cards_.length); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Selects a new card, ensuring that it is a valid index, transforming the 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * view and possibly calling the change card callback. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} newCardIndex Index of card to show. 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean=} opt_animate If true will animate transition from 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * current position to new position. 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean=} opt_dontNotify If true, don't tell subscribers that 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we've changed cards. 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean=} opt_forceChange If true, ignore if the card already 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * selected. 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectCard: function(newCardIndex, 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_animate, 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_dontNotify, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opt_forceChange) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.assertValidIndex_(newCardIndex); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var previousCard = this.currentCardValue; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var isChangingCard = 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !this.cards_[newCardIndex].classList.contains('selected-card'); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (typeof opt_forceChange != 'undefined' && opt_forceChange) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isChangingCard = true; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isChangingCard) { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentCard_ = newCardIndex; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.updateSelectedCardAttributes_(); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var willTransitionHappen = this.transformToCurrentCard_(opt_animate); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isChangingCard && !opt_dontNotify) { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var event = document.createEvent('Event'); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.initEvent('cardSlider:card_changed', true, true); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.cardSlider = this; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event.wasAnimated = !!opt_animate; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.dispatchEvent(event); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We also dispatch an event on the cards themselves. 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (previousCard) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.dispatchSimpleEvent(previousCard, 'carddeselected', 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, true); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cr.dispatchSimpleEvent(this.currentCardValue, 'cardselected', 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, true); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're not changing, animated, or transitioning, fire a 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cardSlider:card_change_ended event right away. 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((!isChangingCard || !opt_animate || !willTransitionHappen) && 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !opt_dontNotify) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.fireChangeEndedEvent_(false); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Selects a card from the stack. Passes through to selectCard. 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Node} newCard The card that should be selected. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean=} opt_animate Whether to animate. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selectCardByValue: function(newCard, opt_animate) { 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var i = this.cards_.indexOf(newCard); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(i != -1); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectCard(i, opt_animate); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Centers the view on the card denoted by this.currentCard. Can either 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * animate to that card or snap to it. 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean=} opt_animate If true will animate transition from 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * current position to new position. 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} Whether or not a transformation was necessary. 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transformToCurrentCard_: function(opt_animate) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var prevLeft = this.currentLeft_; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentLeft_ = -this.cardWidth_ * 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (isRTL() ? this.cards_.length - this.currentCard - 1 : 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentCard); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there's no change, return something to let the caller know there 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // won't be a transition occuring. 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prevLeft == this.currentLeft_ && this.deltaX_ == 0) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Animate to the current card, which will either transition if the 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // current card is new, or reset the existing card if we didn't drag 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enough to change cards. 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var transition = ''; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (opt_animate) { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition = '-webkit-transform ' + CardSlider.TRANSITION_TIME_ + 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'ms ease-in-out'; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.style.WebkitTransition = transition; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.translateTo_(this.currentLeft_); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Moves the view to the specified position. 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} x Horizontal position to move to. 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) translateTo_: function(x) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use a webkitTransform to slide because this is GPU accelerated on 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome and iOS. Once Chrome does GPU acceleration on the position 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fixed-layout elements we could simply set the element's position to 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fixed and modify 'left' instead. 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.deltaX_ = x - this.currentLeft_; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.style.WebkitTransform = 'translate3d(' + x + 'px, 0, 0)'; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Touch ******************************************************************/ 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clear any transition that is in progress and enable dragging for the 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * touch. 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!cr.ui.TouchHandler.Event} e The TouchHandler event. 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onTouchStart_: function(e) { 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.style.WebkitTransition = ''; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.enableDrag = true; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Tell the TouchHandler that dragging is acceptable when the user begins by 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * scrolling horizontally and there is more than one card to slide. 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!cr.ui.TouchHandler.Event} e The TouchHandler event. 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onDragStart_: function(e) { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) e.enableDrag = this.cardCount > 1 && Math.abs(e.dragDeltaX) > 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Math.abs(e.dragDeltaY); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * On each drag move event reposition the container appropriately so the 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cards look like they are sliding. 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!cr.ui.TouchHandler.Event} e The TouchHandler event. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onDragMove_: function(e) { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var deltaX = e.dragDeltaX; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If dragging beyond the first or last card then apply a backoff so the 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dragging feels stickier than usual. 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.currentCard && deltaX > 0 || 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.currentCard == (this.cards_.length - 1) && deltaX < 0) { 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deltaX /= 2; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.translateTo_(this.currentLeft_ + deltaX); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * On drag end events we may want to transition to another card, depending 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * on the ending position of the drag and the velocity of the drag. 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {!cr.ui.TouchHandler.Event} e The TouchHandler event. 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onDragEnd_: function(e) { 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var deltaX = e.dragDeltaX; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var velocity = this.touchHandler_.getEndVelocity().x; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newX = this.currentLeft_ + deltaX; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newCardIndex = Math.round(-newX / this.cardWidth_); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newCardIndex == this.currentCard && Math.abs(velocity) > 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CardSlider.TRANSITION_VELOCITY_THRESHOLD_) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The drag wasn't far enough to change cards but the velocity was 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // high enough to transition anyways. If the velocity is to the left 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (negative) then the user wishes to go right (card + 1). 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCardIndex += velocity > 0 ? -1 : 1; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that the new card index is valid. The new card index could be 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invalid if a swipe suggests scrolling off the end of the list of 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cards. 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newCardIndex < 0) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCardIndex = 0; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (newCardIndex >= this.cardCount) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newCardIndex = this.cardCount - 1; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectCard(newCardIndex, /* animate */ true); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Cancel any current touch/slide as if we saw a touch end 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancelTouch: function() { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop listening to any current touch 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.touchHandler_.cancelTouch(); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure we're at a card bounary 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.transformToCurrentCard_(true); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return { 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CardSlider: CardSlider 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}); 681