/*!
 * jQuery UI Mouse 1.8.23
 *
 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Mouse
 *
 * Depends:
 *	jquery.ui.widget.js
 */
(function ($, undefined) {

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

  $.widget("ui.mouse", {
    options:{
      cancel:':input,option',
      distance:1,
      delay:0
    },
    _mouseInit:function () {
      var self = this;

      this.element
        .bind('mousedown.' + this.widgetName, function (event) {
          return self._mouseDown(event);
        })
        .bind('click.' + this.widgetName, function (event) {
          if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
            $.removeData(event.target, self.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
    _mouseDestroy:function () {
      this.element.unbind('.' + this.widgetName);
      if (this._mouseMoveDelegate) {
        $(document)
          .unbind('mousemove.' + this.widgetName, this._mouseMoveDelegate)
          .unbind('mouseup.' + this.widgetName, this._mouseUpDelegate);
      }
    },

    _mouseDown:function (event) {
      // don't let more than one widget handle mouseStart
      if (mouseHandled) {
        return
      }
      ;

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

      this._mouseDownEvent = event;

      var self = 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 () {
          self.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 self._mouseMove(event);
      };
      this._mouseUpDelegate = function (event) {
        return self._mouseUp(event);
      };
      $(document)
        .bind('mousemove.' + this.widgetName, this._mouseMoveDelegate)
        .bind('mouseup.' + this.widgetName, this._mouseUpDelegate);

      event.preventDefault();

      mouseHandled = true;
      return true;
    },

    _mouseMove:function (event) {
      // IE mouseup check - mouseup happened when mouse was out of window
      if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
        return this._mouseUp(event);
      }

      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;
    },

    _mouseUp:function (event) {
      $(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);
      }

      return false;
    },

    _mouseDistanceMet:function (event) {
      return (Math.max(
        Math.abs(this._mouseDownEvent.pageX - event.pageX),
        Math.abs(this._mouseDownEvent.pageY - event.pageY)
      ) >= this.options.distance
        );
    },

    _mouseDelayMet:function (event) {
      return this.mouseDelayMet;
    },

    // These are placeholder methods, to be overriden by extending plugin
    _mouseStart:function (event) {
    },
    _mouseDrag:function (event) {
    },
    _mouseStop:function (event) {
    },
    _mouseCapture:function (event) {
      return true;
    }
  });

})(jQuery);
