/*
 * 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);
