﻿/*
* jQuery UI @VERSION
*
* Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI
*/
; (function ($) {

  /** jQuery core modifications and additions **/

  var _remove = $.fn.remove;
  $.fn.remove = function () {
    $("*", this).add(this).triggerHandler("remove");
    return _remove.apply(this, arguments);
  };

  function isVisible(element) {
    function checkStyles(element) {
      var style = element.style;
      return (style.display != 'none' && style.visibility != 'hidden');
    }

    var visible = checkStyles(element);

    (visible && $.each($.dir(element, 'parentNode'), function () {
      return (visible = checkStyles(this));
    }));

    return visible;
  }

  $.extend($.expr[':'], {
    data: function (a, i, m) {
      return $.data(a, m[3]);
    },

    // TODO: add support for object, area
    tabbable: function (a, i, m) {
      var nodeName = a.nodeName.toLowerCase();

      return (
      // in tab order
			a.tabIndex >= 0 &&

			( // filter node types that participate in the tab order

      // anchor tag
				('a' == nodeName && a.href) ||

      // enabled form element
				(/input|select|textarea|button/.test(nodeName) &&
					'hidden' != a.type && !a.disabled)
			) &&

      // visible on page
			isVisible(a)
		);
    }
  });

  $.keyCode = {
    BACKSPACE: 8,
    CAPS_LOCK: 20,
    COMMA: 188,
    CONTROL: 17,
    DELETE: 46,
    DOWN: 40,
    END: 35,
    ENTER: 13,
    ESCAPE: 27,
    HOME: 36,
    INSERT: 45,
    LEFT: 37,
    NUMPAD_ADD: 107,
    NUMPAD_DECIMAL: 110,
    NUMPAD_DIVIDE: 111,
    NUMPAD_ENTER: 108,
    NUMPAD_MULTIPLY: 106,
    NUMPAD_SUBTRACT: 109,
    PAGE_DOWN: 34,
    PAGE_UP: 33,
    PERIOD: 190,
    RIGHT: 39,
    SHIFT: 16,
    SPACE: 32,
    TAB: 9,
    UP: 38
  };

  // $.widget is a factory to create jQuery plugins
  // taking some boilerplate code out of the plugin code
  // created by Scott González and Jörn Zaefferer
  function getter(namespace, plugin, method, args) {
    function getMethods(type) {
      var methods = $[namespace][plugin][type] || [];
      return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
    }

    var methods = getMethods('getter');
    if (args.length == 1 && typeof args[0] == 'string') {
      methods = methods.concat(getMethods('getterSetter'));
    }
    return ($.inArray(method, methods) != -1);
  }

  $.widget = function (name, prototype) {
    var namespace = name.split(".")[0];
    name = name.split(".")[1];

    // create plugin method
    $.fn[name] = function (options) {
      var isMethodCall = (typeof options == 'string'),
			args = Array.prototype.slice.call(arguments, 1);

      // prevent calls to internal methods
      if (isMethodCall && options.substring(0, 1) == '_') {
        return this;
      }

      // handle getter methods
      if (isMethodCall && getter(namespace, name, options, args)) {
        var instance = $.data(this[0], name);
        return (instance ? instance[options].apply(instance, args)
				: undefined);
      }

      // handle initialization and non-getter methods
      return this.each(function () {
        var instance = $.data(this, name);

        // constructor
        (!instance && !isMethodCall &&
				$.data(this, name, new $[namespace][name](this, options)));

        // method call
        (instance && isMethodCall && $.isFunction(instance[options]) &&
				instance[options].apply(instance, args));
      });
    };

    // create widget constructor
    $[namespace][name] = function (element, options) {
      var self = this;

      this.widgetName = name;
      this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
      this.widgetBaseClass = namespace + '-' + name;

      this.options = $.extend({},
			$.widget.defaults,
			$[namespace][name].defaults,
			$.metadata && $.metadata.get(element)[name],
			options);

      this.element = $(element)
			.bind('setData.' + name, function (e, key, value) {
			  return self._setData(key, value);
			})
			.bind('getData.' + name, function (e, key) {
			  return self._getData(key);
			})
			.bind('remove', function () {
			  return self.destroy();
			});

      this._init();
    };

    // add widget prototype
    $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);

    // TODO: merge getter and getterSetter properties from widget prototype
    // and plugin prototype
    $[namespace][name].getterSetter = 'option';
  };

  $.widget.prototype = {
    _init: function () { },
    destroy: function () {
      this.element.removeData(this.widgetName);
    },

    option: function (key, value) {
      var options = key,
			self = this;

      if (typeof key == "string") {
        if (value === undefined) {
          return this._getData(key);
        }
        options = {};
        options[key] = value;
      }

      $.each(options, function (key, value) {
        self._setData(key, value);
      });
    },
    _getData: function (key) {
      return this.options[key];
    },
    _setData: function (key, value) {
      this.options[key] = value;

      if (key == 'disabled') {
        this.element[value ? 'addClass' : 'removeClass'](
				this.widgetBaseClass + '-disabled');
      }
    },

    enable: function () {
      this._setData('disabled', false);
    },
    disable: function () {
      this._setData('disabled', true);
    },

    _trigger: function (type, e, data) {
      var eventName = (type == this.widgetEventPrefix
			? type : this.widgetEventPrefix + type);
      e = e || $.event.fix({ type: eventName, target: this.element[0] });
      return this.element.triggerHandler(eventName, [e, data], this.options[type]);
    }
  };

  $.widget.defaults = {
    disabled: false
  };


  /** jQuery UI core **/

  $.ui = {
    plugin: {
      add: function (module, option, set) {
        var proto = $.ui[module].prototype;
        for (var i in set) {
          proto.plugins[i] = proto.plugins[i] || [];
          proto.plugins[i].push([option, set[i]]);
        }
      },
      call: function (instance, name, args) {
        var set = instance.plugins[name];
        if (!set) { return; }

        for (var i = 0; i < set.length; i++) {
          if (instance.options[set[i][0]]) {
            set[i][1].apply(instance.element, args);
          }
        }
      }
    },
    cssCache: {},
    css: function (name) {
      if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; }
      var tmp = $('<div class="ui-gen">').addClass(name).css({ position: 'absolute', top: '-5000px', left: '-5000px', display: 'block' }).appendTo('body');

      //if (!$.browser.safari)
      //tmp.appendTo('body'); 

      //Opera and Safari set width and height to 0px instead of auto
      //Safari returns rgba(0,0,0,0) when bgcolor is not set
      $.ui.cssCache[name] = !!(
			(!(/auto|default/).test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) ||
			!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
		);
      try { $('body').get(0).removeChild(tmp.get(0)); } catch (e) { }
      return $.ui.cssCache[name];
    },
    disableSelection: function (el) {
      return $(el)
			.attr('unselectable', 'on')
			.css('MozUserSelect', 'none')
			.bind('selectstart.ui', function () { return false; });
    },
    enableSelection: function (el) {
      return $(el)
			.attr('unselectable', 'off')
			.css('MozUserSelect', '')
			.unbind('selectstart.ui');
    },
    hasScroll: function (e, a) {

      //If overflow is hidden, the element might have extra content, but the user wants to hide it
      if ($(e).css('overflow') == 'hidden') { return false; }

      var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
			has = false;

      if (e[scroll] > 0) { return true; }

      // TODO: determine which cases actually cause this to happen
      // if the element doesn't have the scroll set, see if it's possible to
      // set the scroll
      e[scroll] = 1;
      has = (e[scroll] > 0);
      e[scroll] = 0;
      return has;
    }
  };


  /** Mouse Interaction Plugin **/

  $.ui.mouse = {
    _mouseInit: function () {
      var self = this;

      this.element.bind('mousedown.' + this.widgetName, function (e) {
        return self._mouseDown(e);
      });

      // Prevent text selection in IE
      if ($.browser.msie) {
        this._mouseUnselectable = this.element.attr('unselectable');
        this.element.attr('unselectable', 'on');
      }

      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);

      // Restore text selection in IE
      ($.browser.msie
			&& this.element.attr('unselectable', this._mouseUnselectable));
    },

    _mouseDown: function (e) {
      // we may have missed mouseup (out of window)
      (this._mouseStarted && this._mouseUp(e));

      this._mouseDownEvent = e;

      var self = this,
			btnIsLeft = (e.which == 1),
			elIsCancel = (typeof this.options.cancel == "string" ? $(e.target).parents().add(e.target).filter(this.options.cancel).length : false);
      if (!btnIsLeft || elIsCancel || !this._mouseCapture(e)) {
        return true;
      }

      this.mouseDelayMet = !this.options.delay;
      if (!this.mouseDelayMet) {
        this._mouseDelayTimer = setTimeout(function () {
          self.mouseDelayMet = true;
        }, this.options.delay);
      }

      if (this._mouseDistanceMet(e) && this._mouseDelayMet(e)) {
        this._mouseStarted = (this._mouseStart(e) !== false);
        if (!this._mouseStarted) {
          e.preventDefault();
          return true;
        }
      }

      // these delegates are required to keep context
      this._mouseMoveDelegate = function (e) {
        return self._mouseMove(e);
      };
      this._mouseUpDelegate = function (e) {
        return self._mouseUp(e);
      };
      $(document)
			.bind('mousemove.' + this.widgetName, this._mouseMoveDelegate)
			.bind('mouseup.' + this.widgetName, this._mouseUpDelegate);

      return false;
    },

    _mouseMove: function (e) {
      // IE mouseup check - mouseup happened when mouse was out of window
      if ($.browser.msie && !e.button) {
        return this._mouseUp(e);
      }

      if (this._mouseStarted) {
        this._mouseDrag(e);
        return false;
      }

      if (this._mouseDistanceMet(e) && this._mouseDelayMet(e)) {
        this._mouseStarted =
				(this._mouseStart(this._mouseDownEvent, e) !== false);
        (this._mouseStarted ? this._mouseDrag(e) : this._mouseUp(e));
      }

      return !this._mouseStarted;
    },

    _mouseUp: function (e) {
      $(document)
			.unbind('mousemove.' + this.widgetName, this._mouseMoveDelegate)
			.unbind('mouseup.' + this.widgetName, this._mouseUpDelegate);

      if (this._mouseStarted) {
        this._mouseStarted = false;
        this._mouseStop(e);
      }

      return false;
    },

    _mouseDistanceMet: function (e) {
      return (Math.max(
				Math.abs(this._mouseDownEvent.pageX - e.pageX),
				Math.abs(this._mouseDownEvent.pageY - e.pageY)
			) >= this.options.distance
		);
    },

    _mouseDelayMet: function (e) {
      return this.mouseDelayMet;
    },

    // These are placeholder methods, to be overriden by extending plugin
    _mouseStart: function (e) { },
    _mouseDrag: function (e) { },
    _mouseStop: function (e) { },
    _mouseCapture: function (e) { return true; }
  };

  $.ui.mouse.defaults = {
    cancel: null,
    distance: 1,
    delay: 0
  };

})(jQuery);


