define(["lib/jquery", "lib/underscore", "common/util/check", "common/util/binding_list"], function( $, _, check, BindingList) { "use strict"; // scrolls of less than this many pixels will be ignored var SCROLL_THRESHOLD = 5; /** * Makes an element scrollable. * * @param {string | DOMElement | jQuery} el * Scrollable element. Can be a CSS selector, a DOM element, or a * jQuery object. * * @param {Number} [numFingers] * The number of fingers used to scroll. Defaults to 3. * * @class Represents a scrollable element. * * @property {Boolean} enabled Whether this Scrollable is enabled. * * @name Lens.Components.Scrollable */ var Scrollable = function(el, numFingers) { check(el, check.Match.Elementish); check(numFingers, check.Match.Optional(Number)); var self = {}; var enabled = true; var scrollSubscribers = BindingList(); var eventHandler = function(evt) { if(!self.enabled) { return; } var touches = evt.targetTouches; if(touches.length >= numFingers) { var startScrollY = el.scrollTop(); var startScrollX = el.scrollLeft(); // keep track of previous dx and dy so we can respect the threshold var prevDy = touches.dy; var prevDx = touches.dx; // bind to the mover handler touches.moved(function() { if(Math.abs(prevDy - touches.dy) > SCROLL_THRESHOLD) { el.scrollTop(startScrollY - touches.dy); prevDy = touches.dy; scrollSubscribers.callAll(); } if(Math.abs(prevDx - touches.dx) > SCROLL_THRESHOLD) { el.scrollLeft(startScrollX - touches.dx); prevDx = touches.dx; scrollSubscribers.callAll(); } }); evt.stopPropagation(); } }; Object.defineProperty(self, "enabled", { get: function() { return enabled; } }); /** * Enables the scrollable. Scrollables start out enabled, so you only * need to call this if you've disabled the Scrollable with `disable`. */ self.enable = function() { el = $(el); el[0].addEventListener("lens:touchstart", eventHandler, true); enabled = true; }; /** * Disables the scrollable. The scrollable will no longer move when * touched. */ self.disable = function() { el = $(el); el[0].removeEventListener("lens:touchstart", eventHandler, true); enabled = false; }; /** * Registers a function to be called whenever scrolling occurs. * * @param {Function} callback * The function to call. Gets one {@link Scrollable} as an * argument. * * @return {Binding} A Binding that allows this handler to be cleared. */ self.onScroll = function(callback) { check(callback, Function); return scrollSubscribers.add(callback); }; if(!numFingers) { numFingers = 3; } $(function(){ self.enable(); }); Object.freeze(self); return self; }; Lens._addMember(Scrollable, "Scrollable", Lens.Components); return Scrollable; });