API Docs for: 1.11.2-pre
Show:

File: ui-cn\mouse.js

/*!
 * jQuery UI Mouse @VERSION
 * http://jqueryui.com
 *
 * Copyright 2014 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/mouse/
 */
(function( factory ) {
	if ( typeof define === "function" && define.amd ) {

		// AMD. Register as an anonymous module.
		define([
			"jquery",
			"./widget"
		], factory );
	} else {

		// Browser globals
		factory( jQuery );
	}
}(function( $ ) {

var mouseHandled = false;
$( document ).mouseup( function() {
	mouseHandled = false;
});

/**
 * $.ui.mouse 鼠标交互<br/>
 * 与 jQuery.Widget 相似,鼠标交互的目的不是直接使用。
 * 这是一个纯粹给其他小部件继承用的基础层。该页面有添加到 jQuery.Widget 的文档,但是它包含了不能被覆盖的内部方法。
 * 公共的 API 是 _mouseStart()、_mouseDrag()、_mouseStop() 和 _mouseCapture()。
 * 
 * @class mouse
 * @module mouse
 * @requires widget
 * @constructor
 * @namespace ui
 */

return $.widget("ui.mouse", {
	version: "@VERSION",
	/**
	 * 默认的鼠标交互 options
	 * @property options
	 * @type {Object}
	 * @final
	 * @example
	 *	//初始化带有指定 cancel 选项的 mouse:
	 *	$( ".selector" ).mouse({ cancel: ".title" });
	 *	
	 *	//在初始化后,获取或设置 cancel 选项:
	 *	// getter
	 *	var cancel = $( ".selector" ).mouse( "option", "cancel" );
	 *	// setter
	 *	$( ".selector" ).mouse( "option", "cancel", ".title" );
	 * 
	 */
	options: {
		cancel: "input,textarea,button,select,option",  //防止从指定的元素上开始交互。
		distance: 1, //鼠标按下后交互开始前鼠标必须移动的距离,以像素计。该选项可用于防止点击在一个元素上时不必要的交互。
		delay: 0  //鼠标按下后直至交互开始的事件,以毫秒计。该选项可用于防止点击在一个元素上时不必要的交互。
	},
    /**
     * 初始化交互事件处理程序。这必须调用来自扩展的小部件的 _create() 方法。
     * @method  _mouseInit
     * @private
     */
	_mouseInit: function() {
		var that = this;

		this.element
			.bind("mousedown." + this.widgetName, function(event) {
				return that._mouseDown(event);
			})
			.bind("click." + this.widgetName, function(event) {
				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
					$.removeData(event.target, that.widgetName + ".preventClickEvent");
					event.stopImmediatePropagation();
					return false;
				}
			});

		this.started = false;
	},

	// TODO: make sure destroying one instance of mouse doesn't mess with
	// other instances of mouse
    /**
     * 销毁交互事件处理程序。这必须调用来自扩展的小部件的 _destroy() 方法。
     * @method  _mouseDestroy
     * @private
     */
	_mouseDestroy: function() {
		this.element.unbind("." + this.widgetName);
		if ( this._mouseMoveDelegate ) {
			this.document
				.unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
				.unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
		}
	},
    /**
     * 处理交互的开始。确认与主要的鼠标按钮关联的事件,确保 delay 与 distance 在交互启动之前得到满足。
     * 当交互已经准备开始,为要处理的扩展小部件调用 _mouseStart 方法。
     * @method  _mouseDown
     * @param event
     * @returns {boolean}
     * @private
     */
	_mouseDown: function(event) {
		// don't let more than one widget handle mouseStart
		if ( mouseHandled ) {
			return;
		}

		this._mouseMoved = false;

		// we may have missed mouseup (out of window)
		(this._mouseStarted && this._mouseUp(event));

		this._mouseDownEvent = event;

		var that = this,
			btnIsLeft = (event.which === 1),
			// event.target.nodeName works around a bug in IE 8 with
			// disabled inputs (#7620)
			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
			return true;
		}

		this.mouseDelayMet = !this.options.delay;
		if (!this.mouseDelayMet) {
			this._mouseDelayTimer = setTimeout(function() {
				that.mouseDelayMet = true;
			}, this.options.delay);
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted = (this._mouseStart(event) !== false);
			if (!this._mouseStarted) {
				event.preventDefault();
				return true;
			}
		}

		// Click event may never have fired (Gecko & Opera)
		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
			$.removeData(event.target, this.widgetName + ".preventClickEvent");
		}

		// these delegates are required to keep context
		this._mouseMoveDelegate = function(event) {
			return that._mouseMove(event);
		};
		this._mouseUpDelegate = function(event) {
			return that._mouseUp(event);
		};

		this.document
			.bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
			.bind( "mouseup." + this.widgetName, this._mouseUpDelegate );

		event.preventDefault();

		mouseHandled = true;
		return true;
	},
    /**
     * 处理交互的每个移动。为要处理的扩展小部件调用 _mouseDrag 方法。
     * @method  _mouseMove
     * @param event
     * @returns {*}
     * @private
     */
	_mouseMove: function(event) {
		// Only check for mouseups outside the document if you've moved inside the document
		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
		// fire a mousemove event if content is placed under the cursor. See #7778
		// Support: IE <9
		if ( this._mouseMoved ) {
			// IE mouseup check - mouseup happened when mouse was out of window
			if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
				return this._mouseUp(event);

			// Iframe mouseup check - mouseup occurred in another document
			} else if ( !event.which ) {
				return this._mouseUp( event );
			}
		}

		if ( event.which || event.button ) {
			this._mouseMoved = true;
		}

		if (this._mouseStarted) {
			this._mouseDrag(event);
			return event.preventDefault();
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted =
				(this._mouseStart(this._mouseDownEvent, event) !== false);
			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
		}

		return !this._mouseStarted;
	},
    /**
     * 处理交互的结束。为要处理的扩展小部件调用 _mouseStop 方法。
     * @method  _mouseUp
     * @param event
     * @returns {boolean}
     * @private
     */
	_mouseUp: function(event) {
		this.document
			.unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
			.unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );

		if (this._mouseStarted) {
			this._mouseStarted = false;

			if (event.target === this._mouseDownEvent.target) {
				$.data(event.target, this.widgetName + ".preventClickEvent", true);
			}

			this._mouseStop(event);
		}

		mouseHandled = false;
		return false;
	},
    /**
     * 决定 distance 选项是否满足当前交互。
     * @method  _mouseDistanceMet
     * @param event
     * @returns {boolean}
     * @private
     */
	_mouseDistanceMet: function(event) {
		return (Math.max(
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
			) >= this.options.distance
		);
	},
    /**
     * 决定 delay 选项是否满足当前交互。
     * @method  _mouseDelayMet
     * @returns {boolean|*|mouseDelayMet}
     * @private
     */
	_mouseDelayMet: function(/* event */) {
		return this.mouseDelayMet;
	},

	// These are placeholder methods, to be overriden by extending plugin
    /**
     * 扩展小部件应实现一个 _mouseStart() 方法,来处理交互的开始。该方法将接收与交互开始相关联的鼠标事件。
     * @method  _mouseStart
     * @private
     */
	_mouseStart: function(/* event */) {},
    /**
     * 扩展小部件应实现一个 _mouseDrag() 方法,来处理交互的每个移动。该方法将接收与鼠标移动相关联的鼠标事件。
     * @method  _mouseDrag
     * @private
     */
	_mouseDrag: function(/* event */) {},
    /**
     * 扩展小部件应实现一个 _mouseStop() 方法,来处理交互的结束。该方法将接收与交互结束相关联的鼠标事件。
     * @method  _mouseStop
     * @private
     */
	_mouseStop: function(/* event */) {},
    /**
     * 决定交互是否应该基于交互的事件目标开始。默认的实现总是返回 true。
     * @method  _mouseCapture
     * @returns {boolean}
     * @private
     */
	_mouseCapture: function(/* event */) { return true; }
});

}));