Path: blob/trunk/third_party/closure/goog/events/mousewheelhandler.js
2868 views
// Copyright 2006 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview This event wrapper will dispatch an event when the user uses16* the mouse wheel to scroll an element. You can get the direction by checking17* the deltaX and deltaY properties of the event.18*19* This class aims to smooth out inconsistencies between browser platforms with20* regards to mousewheel events, but we do not cover every possible21* software/hardware combination out there, some of which occasionally produce22* very large deltas in mousewheel events. If your application wants to guard23* against extremely large deltas, use the setMaxDeltaX and setMaxDeltaY APIs24* to set maximum values that make sense for your application.25*26* @author [email protected] (Erik Arvidsson)27* @see ../demos/mousewheelhandler.html28*/2930goog.provide('goog.events.MouseWheelEvent');31goog.provide('goog.events.MouseWheelHandler');32goog.provide('goog.events.MouseWheelHandler.EventType');3334goog.require('goog.dom');35goog.require('goog.events');36goog.require('goog.events.BrowserEvent');37goog.require('goog.events.EventTarget');38goog.require('goog.math');39goog.require('goog.style');40goog.require('goog.userAgent');41424344/**45* This event handler allows you to catch mouse wheel events in a consistent46* manner.47* @param {Element|Document} element The element to listen to the mouse wheel48* event on.49* @param {boolean=} opt_capture Whether to handle the mouse wheel event in50* capture phase.51* @constructor52* @extends {goog.events.EventTarget}53*/54goog.events.MouseWheelHandler = function(element, opt_capture) {55goog.events.EventTarget.call(this);5657/**58* This is the element that we will listen to the real mouse wheel events on.59* @type {Element|Document}60* @private61*/62this.element_ = element;6364var rtlElement = goog.dom.isElement(this.element_) ?65/** @type {Element} */ (this.element_) :66(this.element_ ?67/** @type {Document} */ (this.element_).body :68null);6970/**71* True if the element exists and is RTL, false otherwise.72* @type {boolean}73* @private74*/75this.isRtl_ = !!rtlElement && goog.style.isRightToLeft(rtlElement);7677var type = goog.userAgent.GECKO ? 'DOMMouseScroll' : 'mousewheel';7879/**80* The key returned from the goog.events.listen.81* @type {goog.events.Key}82* @private83*/84this.listenKey_ = goog.events.listen(this.element_, type, this, opt_capture);85};86goog.inherits(goog.events.MouseWheelHandler, goog.events.EventTarget);878889/**90* Enum type for the events fired by the mouse wheel handler.91* @enum {string}92*/93goog.events.MouseWheelHandler.EventType = {94MOUSEWHEEL: 'mousewheel'95};969798/**99* Optional maximum magnitude for x delta on each mousewheel event.100* @type {number|undefined}101* @private102*/103goog.events.MouseWheelHandler.prototype.maxDeltaX_;104105106/**107* Optional maximum magnitude for y delta on each mousewheel event.108* @type {number|undefined}109* @private110*/111goog.events.MouseWheelHandler.prototype.maxDeltaY_;112113114/**115* @param {number} maxDeltaX Maximum magnitude for x delta on each mousewheel116* event. Should be non-negative.117*/118goog.events.MouseWheelHandler.prototype.setMaxDeltaX = function(maxDeltaX) {119this.maxDeltaX_ = maxDeltaX;120};121122123/**124* @param {number} maxDeltaY Maximum magnitude for y delta on each mousewheel125* event. Should be non-negative.126*/127goog.events.MouseWheelHandler.prototype.setMaxDeltaY = function(maxDeltaY) {128this.maxDeltaY_ = maxDeltaY;129};130131132/**133* Handles the events on the element.134* @param {goog.events.BrowserEvent} e The underlying browser event.135*/136goog.events.MouseWheelHandler.prototype.handleEvent = function(e) {137var deltaX = 0;138var deltaY = 0;139var detail = 0;140var be = e.getBrowserEvent();141if (be.type == 'mousewheel') {142// In IE we get a multiple of 120; we adjust to a multiple of 3 to143// represent number of lines scrolled (like Gecko).144// Newer versions of Webkit match IE behavior, and WebKit on145// Windows also matches IE behavior.146// See bug https://bugs.webkit.org/show_bug.cgi?id=24368147var wheelDeltaScaleFactor = 40;148149detail = goog.events.MouseWheelHandler.smartScale_(150-be.wheelDelta, wheelDeltaScaleFactor);151if (goog.isDef(be.wheelDeltaX)) {152// Webkit has two properties to indicate directional scroll, and153// can scroll both directions at once.154deltaX = goog.events.MouseWheelHandler.smartScale_(155-be.wheelDeltaX, wheelDeltaScaleFactor);156deltaY = goog.events.MouseWheelHandler.smartScale_(157-be.wheelDeltaY, wheelDeltaScaleFactor);158} else {159deltaY = detail;160}161162// Historical note: Opera (pre 9.5) used to negate the detail value.163} else { // Gecko164// Gecko returns multiple of 3 (representing the number of lines scrolled)165detail = be.detail;166167// Gecko sometimes returns really big values if the user changes settings to168// scroll a whole page per scroll169if (detail > 100) {170detail = 3;171} else if (detail < -100) {172detail = -3;173}174175// Firefox 3.1 adds an axis field to the event to indicate direction of176// scroll. See https://developer.mozilla.org/en/Gecko-Specific_DOM_Events177if (goog.isDef(be.axis) && be.axis === be.HORIZONTAL_AXIS) {178deltaX = detail;179} else {180deltaY = detail;181}182}183184if (goog.isNumber(this.maxDeltaX_)) {185deltaX = goog.math.clamp(deltaX, -this.maxDeltaX_, this.maxDeltaX_);186}187if (goog.isNumber(this.maxDeltaY_)) {188deltaY = goog.math.clamp(deltaY, -this.maxDeltaY_, this.maxDeltaY_);189}190// Don't clamp 'detail', since it could be ambiguous which axis it refers to191// and because it's informally deprecated anyways.192193// For horizontal scrolling we need to flip the value for RTL grids.194if (this.isRtl_) {195deltaX = -deltaX;196}197var newEvent = new goog.events.MouseWheelEvent(detail, be, deltaX, deltaY);198this.dispatchEvent(newEvent);199};200201202/**203* Helper for scaling down a mousewheel delta by a scale factor, if appropriate.204* @param {number} mouseWheelDelta Delta from a mouse wheel event. Expected to205* be an integer.206* @param {number} scaleFactor Factor to scale the delta down by. Expected to207* be an integer.208* @return {number} Scaled-down delta value, or the original delta if the209* scaleFactor does not appear to be applicable.210* @private211*/212goog.events.MouseWheelHandler.smartScale_ = function(213mouseWheelDelta, scaleFactor) {214// The basic problem here is that in Webkit on Mac and Linux, we can get two215// very different types of mousewheel events: from continuous devices216// (touchpads, Mighty Mouse) or non-continuous devices (normal wheel mice).217//218// Non-continuous devices in Webkit get their wheel deltas scaled up to219// behave like IE. Continuous devices return much smaller unscaled values220// (which most of the time will not be cleanly divisible by the IE scale221// factor), so we should not try to normalize them down.222//223// Detailed discussion:224// https://bugs.webkit.org/show_bug.cgi?id=29601225// http://trac.webkit.org/browser/trunk/WebKit/chromium/src/mac/WebInputEventFactory.mm#L1063226if (goog.userAgent.WEBKIT && (goog.userAgent.MAC || goog.userAgent.LINUX) &&227(mouseWheelDelta % scaleFactor) != 0) {228return mouseWheelDelta;229} else {230return mouseWheelDelta / scaleFactor;231}232};233234235/** @override */236goog.events.MouseWheelHandler.prototype.disposeInternal = function() {237goog.events.MouseWheelHandler.superClass_.disposeInternal.call(this);238goog.events.unlistenByKey(this.listenKey_);239this.listenKey_ = null;240};241242243244/**245* A base class for mouse wheel events. This is used with the246* MouseWheelHandler.247*248* @param {number} detail The number of rows the user scrolled.249* @param {Event} browserEvent Browser event object.250* @param {number} deltaX The number of rows the user scrolled in the X251* direction.252* @param {number} deltaY The number of rows the user scrolled in the Y253* direction.254* @constructor255* @extends {goog.events.BrowserEvent}256* @final257*/258goog.events.MouseWheelEvent = function(detail, browserEvent, deltaX, deltaY) {259goog.events.BrowserEvent.call(this, browserEvent);260261this.type = goog.events.MouseWheelHandler.EventType.MOUSEWHEEL;262263/**264* The number of lines the user scrolled265* @type {number}266* NOTE: Informally deprecated. Use deltaX and deltaY instead, they provide267* more information.268*/269this.detail = detail;270271/**272* The number of "lines" scrolled in the X direction.273*274* Note that not all browsers provide enough information to distinguish275* horizontal and vertical scroll events, so for these unsupported browsers,276* we will always have a deltaX of 0, even if the user scrolled their mouse277* wheel or trackpad sideways.278*279* Currently supported browsers are Webkit and Firefox 3.1 or later.280*281* @type {number}282*/283this.deltaX = deltaX;284285/**286* The number of lines scrolled in the Y direction.287* @type {number}288*/289this.deltaY = deltaY;290};291goog.inherits(goog.events.MouseWheelEvent, goog.events.BrowserEvent);292293294