/*!
 * jQuery UI 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
;
jQuery.ui || (function($) {

    var isFF2=$.browser.mozilla && (parseFloat($.browser.version) < 1.9);

    //Helper functions and ui object
    $.ui={
        version: "1.8rc1",

        // $.ui.plugin is deprecated.  Use the proxy pattern instead.
        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 || !instance.element[0].parentNode) {
                    return;
                }

                for (var i=0; i < set.length; i++) {
                    if (instance.options[set[i][0]]) {
                        set[i][1].apply(instance.element, args);
                    }
                }
            }
        },

        contains: function(a, b) {
            return document.compareDocumentPosition
                    ? a.compareDocumentPosition(b) & 16
                    : a !== b && a.contains(b);
        },

        hasScroll: function(el, a) {

            //If overflow is hidden, the element might have extra content, but the user wants to hide it
            if ($(el).css('overflow') == 'hidden') {
                return false;
            }

            var scroll=(a && a == 'left') ? 'scrollLeft' : 'scrollTop',
                    has=false;

            if (el[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
            el[scroll]=1;
            has=(el[scroll] > 0);
            el[scroll]=0;
            return has;
        },

        isOverAxis: function(x, reference, size) {
            //Determines when x coordinate is over "b" element axis
            return (x > reference) && (x < (reference + size));
        },

        isOver: function(y, x, top, left, height, width) {
            //Determines when x, y coordinates is over "b" element
            return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
        },

        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
        }
    };

    //jQuery plugins
    $.fn.extend({
        _focus: $.fn.focus,
        focus: function(delay, fn) {
            return typeof delay === 'number'
                    ? this.each(function() {
                var elem=this;
                setTimeout(function() {
                    $(elem).focus();
                    (fn && fn.call(elem));
                }, delay);
            })
                    : this._focus.apply(this, arguments);
        },

        enableSelection: function() {
            return this
                    .attr('unselectable', 'off')
                    .css('MozUserSelect', '')
                    .unbind('selectstart.ui');
        },

        disableSelection: function() {
            return this
                    .attr('unselectable', 'on')
                    .css('MozUserSelect', 'none')
                    .bind('selectstart.ui', function() {
                return false;
            });
        },

        scrollParent: function() {
            var scrollParent;
            if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
                scrollParent=this.parents().filter(function() {
                    return (/(relative|absolute|fixed)/).test($.curCSS(this, 'position', 1)) && (/(auto|scroll)/).test($.curCSS(this, 'overflow', 1) + $.curCSS(this, 'overflow-y', 1) + $.curCSS(this, 'overflow-x', 1));
                }).eq(0);
            } else {
                scrollParent=this.parents().filter(function() {
                    return (/(auto|scroll)/).test($.curCSS(this, 'overflow', 1) + $.curCSS(this, 'overflow-y', 1) + $.curCSS(this, 'overflow-x', 1));
                }).eq(0);
            }

            return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
        },

        zIndex: function(zIndex) {
            if (zIndex !== undefined) {
                return this.css('zIndex', zIndex);
            }

            var elem=this[0];
            while (elem && elem.style) {
                // IE returns 0 when zIndex is not specified
                // other browsers return an empty string
                // we ignore the case of nested elements with an explicit value of 0
                // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
                if (elem.style.zIndex !== '' && elem.style.zIndex !== 0) {
                    return +elem.style.zIndex;
                }
                elem=elem.parentNode;
            }

            return 0;
        }
    });


    //Additional selectors
    $.extend($.expr[':'], {
        data: function(elem, i, match) {
            return !!$.data(elem, match[3]);
        },

        focusable: function(element) {
            var nodeName=element.nodeName.toLowerCase(),
                    tabIndex=$.attr(element, 'tabindex');
            return (/input|select|textarea|button|object/.test(nodeName)
                    ? !element.disabled
                    : 'a' == nodeName || 'area' == nodeName
                    ? element.href || !isNaN(tabIndex)
                    : !isNaN(tabIndex))
                // the element and all of its ancestors must be visible
                // the browser may report that the area is hidden
                    && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
        },

        tabbable: function(element) {
            var tabIndex=$.attr(element, 'tabindex');
            return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
        }
    });

})(jQuery);
/*!
 * jQuery UI Widget 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Widget
 */
(function($) {

    var _remove=$.fn.remove;

    $.fn.remove=function(selector, keepData) {
        if (!keepData) {
            $("*", this).add(this).each(function() {
                $(this).triggerHandler("remove");
            });
        }
        return _remove.apply(this, arguments);
    };

    $.widget=function(name, base, prototype) {
        var namespace=name.split(".")[ 0 ],
                fullName;
        name=name.split(".")[ 1 ];
        fullName=namespace + "-" + name;

        if (!prototype) {
            prototype=base;
            base=$.Widget;
        }

        // create selector for plugin
        $.expr[ ":" ][ fullName ]=function(elem) {
            return !!$.data(elem, name);
        };

        $[ namespace ]=$[ namespace ] || {};
        $[ namespace ][ name ]=function(options, element) {
            // allow instantiation without initializing for simple inheritance
            if (arguments.length) {
                this._createWidget(options, element);
            }
        };

        var basePrototype=new base();
        // we need to make the options hash a property directly on the new instance
        // otherwise we'll modify the options hash on the prototype that we're
        // inheriting from
        //	$.each( basePrototype, function( key, val ) {
        //		if ( $.isPlainObject(val) ) {
        //			basePrototype[ key ] = $.extend( {}, val );
        //		}
        //	});
        basePrototype.options=$.extend({}, basePrototype.options);
        $[ namespace ][ name ].prototype=$.extend(true, basePrototype, {
            namespace: namespace,
            widgetName: name,
            widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
            widgetBaseClass: fullName
        }, prototype);

        $.widget.bridge(name, $[ namespace ][ name ]);
    };

    $.widget.bridge=function(name, object) {
        $.fn[ name ]=function(options) {
            var isMethodCall=typeof options === "string",
                    args=Array.prototype.slice.call(arguments, 1),
                    returnValue=this;

            // allow multiple hashes to be passed on init
            options=!isMethodCall && args.length ?
                    $.extend.apply(null, [ true, options ].concat(args)) :
                    options;

            // prevent calls to internal methods
            if (isMethodCall && options.substring(0, 1) === "_") {
                return returnValue;
            }

            if (isMethodCall) {
                this.each(function() {
                    var instance=$.data(this, name),
                            methodValue=instance && $.isFunction(instance[options]) ?
                                        instance[ options ].apply(instance, args) :
                                        instance;
                    if (methodValue !== instance && methodValue !== undefined) {
                        returnValue=methodValue;
                        return false;
                    }
                });
            } else {
                this.each(function() {
                    var instance=$.data(this, name);
                    if (instance) {
                        if (options) {
                            instance.option(options);
                        }
                        instance._init();
                    } else {
                        $.data(this, name, new object(options, this));
                    }
                });
            }

            return returnValue;
        };
    };

    $.Widget=function(options, element) {
        // allow instantiation without initializing for simple inheritance
        if (arguments.length) {
            this._createWidget(options, element);
        }
    };

    $.Widget.prototype={
        widgetName: "widget",
        widgetEventPrefix: "",
        options: {
            disabled: false
        },
        _createWidget: function(options, element) {
            // $.widget.bridge stores the plugin instance, but we do it anyway
            // so that it's stored even before the _create function runs
            this.element=$(element).data(this.widgetName, this);
            this.options=$.extend(true, {},
                    this.options,
                    $.metadata && $.metadata.get(element)[ this.widgetName ],
                    options);

            var self=this;
            this.element.bind("remove." + this.widgetName, function() {
                self.destroy();
            });

            this._create();
            this._init();
        },
        _create: function() {
        },
        _init: function() {
        },

        destroy: function() {
            this.element
                    .unbind("." + this.widgetName)
                    .removeData(this.widgetName);
            this.widget()
                    .unbind("." + this.widgetName)
                    .removeAttr("aria-disabled")
                    .removeClass(
                    this.widgetBaseClass + "-disabled " +
                    this.namespace + "-state-disabled");
        },

        widget: function() {
            return this.element;
        },

        option: function(key, value) {
            var options=key,
                    self=this;

            if (arguments.length === 0) {
                // don't return a reference to the internal hash
                return $.extend({}, self.options);
            }

            if (typeof key === "string") {
                if (value === undefined) {
                    return this.options[ key ];
                }
                options={};
                options[ key ]=value;
            }

            $.each(options, function(key, value) {
                self._setOption(key, value);
            });

            return self;
        },
        _setOption: function(key, value) {
            this.options[ key ]=value;

            if (key === "disabled") {
                this.widget()
                        [ value ? "addClass" : "removeClass"](
                        this.widgetBaseClass + "-disabled" + " " +
                        this.namespace + "-state-disabled")
                        .attr("aria-disabled", value);
            }

            return this;
        },

        enable: function() {
            return this._setOption("disabled", false);
        },
        disable: function() {
            return this._setOption("disabled", true);
        },

        _trigger: function(type, event, data) {
            var callback=this.options[ type ];

            event=$.Event(event);
            event.type=( type === this.widgetEventPrefix ?
                         type :
                         this.widgetEventPrefix + type ).toLowerCase();
            data=data || {};

            // copy original event properties over to the new event
            // this would happen if we could call $.event.fix instead of $.Event
            // but we don't have a way to force an event to be fixed multiple times
            if (event.originalEvent) {
                for (var i=$.event.props.length, prop; i;) {
                    prop=$.event.props[ --i ];
                    event[ prop ]=event.originalEvent[ prop ];
                }
            }

            this.element.trigger(event, data);

            return !( $.isFunction(callback) &&
                      callback.call(this.element[0], event, data) === false ||
                      event.isDefaultPrevented() );
        }
    };

})(jQuery);
/*!
 * jQuery UI Mouse 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Mouse
 *
 * Depends:
 *	jquery.ui.widget.js
 */
(function($) {

    $.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 (self._preventClickEvent) {
                    self._preventClickEvent=false;
                    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);
        },

        _mouseDown: function(event) {
            // don't let more than one widget handle mouseStart
            // TODO: figure out why we have to use originalEvent
            event.originalEvent=event.originalEvent || {};
            if (event.originalEvent.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),
                    elIsCancel=(typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(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;
                }
            }

            // 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);

            // preventDefault() is used to prevent the selection of text here -
            // however, in Safari, this causes select boxes not to be selectable
            // anymore, so this fix is needed
            ($.browser.safari || event.preventDefault());

            event.originalEvent.mouseHandled=true;
            return true;
        },

        _mouseMove: function(event) {
            // IE mouseup check - mouseup happened when mouse was out of window
            if ($.browser.msie && !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;
                this._preventClickEvent=(event.target == this._mouseDownEvent.target);
                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);
/*
 * jQuery UI Draggable 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Draggables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.draggable", $.ui.mouse, {
        options: {
            addClasses: true,
            appendTo: "parent",
            axis: false,
            connectToSortable: false,
            containment: false,
            cursor: "auto",
            cursorAt: false,
            grid: false,
            handle: false,
            helper: "original",
            iframeFix: false,
            opacity: false,
            refreshPositions: false,
            revert: false,
            revertDuration: 500,
            scope: "default",
            scroll: true,
            scrollSensitivity: 20,
            scrollSpeed: 20,
            snap: false,
            snapMode: "both",
            snapTolerance: 20,
            stack: false,
            zIndex: false
        },
        _create: function() {

            if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
                this.element[0].style.position='relative';

            (this.options.addClasses && this.element.addClass("ui-draggable"));
            (this.options.disabled && this.element.addClass("ui-draggable-disabled"));

            this._mouseInit();

        },

        destroy: function() {
            if (!this.element.data('draggable')) return;
            this.element
                    .removeData("draggable")
                    .unbind(".draggable")
                    .removeClass("ui-draggable"
                    + " ui-draggable-dragging"
                    + " ui-draggable-disabled");
            this._mouseDestroy();

            return this;
        },

        _mouseCapture: function(event) {

            var o=this.options;

            // among others, prevent a drag on a resizable-handle
            if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
                return false;

            //Quit if we're not on a valid handle
            this.handle=this._getHandle(event);
            if (!this.handle)
                return false;

            return true;

        },

        _mouseStart: function(event) {

            var o=this.options;

            //Create and append the visible helper
            this.helper=this._createHelper(event);

            //Cache the helper size
            this._cacheHelperProportions();

            //If ddmanager is used for droppables, set the global draggable
            if ($.ui.ddmanager)
                $.ui.ddmanager.current=this;

            /*
             * - Position generation -
             * This block generates everything position related - it's the core of draggables.
             */

            //Cache the margins of the original element
            this._cacheMargins();

            //Store the helper's css position
            this.cssPosition=this.helper.css("position");
            this.scrollParent=this.helper.scrollParent();

            //The element's absolute position on the page minus margins
            this.offset=this.positionAbs=this.element.offset();
            this.offset={
                top: this.offset.top - this.margins.top,
                left: this.offset.left - this.margins.left
            };

            $.extend(this.offset, {
                click: { //Where the click happened, relative to the element
                    left: event.pageX - this.offset.left,
                    top: event.pageY - this.offset.top
                },
                parent: this._getParentOffset(),
                relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
            });

            //Generate the original position
            this.originalPosition=this.position=this._generatePosition(event);
            this.originalPageX=event.pageX;
            this.originalPageY=event.pageY;

            //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
            (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));

            //Set a containment if given in the options
            if (o.containment)
                this._setContainment();

            //Call plugins and callbacks
            this._trigger("start", event);

            //Recache the helper size
            this._cacheHelperProportions();

            //Prepare the droppable offsets
            if ($.ui.ddmanager && !o.dropBehaviour)
                $.ui.ddmanager.prepareOffsets(this, event);

            this.helper.addClass("ui-draggable-dragging");
            this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
            return true;
        },

        _mouseDrag: function(event, noPropagation) {

            //Compute the helpers position
            this.position=this._generatePosition(event);
            this.positionAbs=this._convertPositionTo("absolute");

            //Call plugins and callbacks and use the resulting position if something is returned
            if (!noPropagation) {
                var ui=this._uiHash();
                this._trigger('drag', event, ui);
                this.position=ui.position;
            }

            if (!this.options.axis || this.options.axis != "y") this.helper[0].style.left=this.position.left + 'px';
            if (!this.options.axis || this.options.axis != "x") this.helper[0].style.top=this.position.top + 'px';
            if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event);

            return false;
        },

        _mouseStop: function(event) {

            //If we are using droppables, inform the manager about the drop
            var dropped=false;
            if ($.ui.ddmanager && !this.options.dropBehaviour)
                dropped=$.ui.ddmanager.drop(this, event);

            //if a drop comes from outside (a sortable)
            if (this.dropped) {
                dropped=this.dropped;
                this.dropped=false;
            }

            //if the original element is removed, don't bother to continue
            if (!this.element[0] || !this.element[0].parentNode)
                return false;

            if ((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
                var self=this;
                $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
                    self._trigger("stop", event);
                    self._clear();
                });
            } else {
                this._trigger("stop", event);
                this._clear();
            }

            return false;
        },

        _getHandle: function(event) {

            var handle=!this.options.handle || !$(this.options.handle, this.element).length ? true : false;
            $(this.options.handle, this.element)
                    .find("*")
                    .andSelf()
                    .each(function() {
                if (this == event.target) handle=true;
            });

            return handle;

        },

        _createHelper: function(event) {

            var o=this.options;
            var helper=$.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);

            if (!helper.parents('body').length)
                helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));

            if (helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
                helper.css("position", "absolute");

            return helper;

        },

        _adjustOffsetFromHelper: function(obj) {
            if (typeof obj == 'string') {
                obj=obj.split(' ');
            }
            if ($.isArray(obj)) {
                obj={left: +obj[0], top: +obj[1] || 0};
            }
            if ('left' in obj) {
                this.offset.click.left=obj.left + this.margins.left;
            }
            if ('right' in obj) {
                this.offset.click.left=this.helperProportions.width - obj.right + this.margins.left;
            }
            if ('top' in obj) {
                this.offset.click.top=obj.top + this.margins.top;
            }
            if ('bottom' in obj) {
                this.offset.click.top=this.helperProportions.height - obj.bottom + this.margins.top;
            }
        },

        _getParentOffset: function() {

            //Get the offsetParent and cache its position
            this.offsetParent=this.helper.offsetParent();
            var po=this.offsetParent.offset();

            // This is a special case where we need to modify a offset calculated on start, since the following happened:
            // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
            // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
            //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
            if (this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
                po.left+=this.scrollParent.scrollLeft();
                po.top+=this.scrollParent.scrollTop();
            }

            if ((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
                    || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
                po={ top: 0, left: 0 };

            return {
                top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
                left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
            };

        },

        _getRelativeOffset: function() {

            if (this.cssPosition == "relative") {
                var p=this.element.position();
                return {
                    top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(),
                    left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()
                };
            } else {
                return { top: 0, left: 0 };
            }

        },

        _cacheMargins: function() {
            this.margins={
                left: (parseInt(this.element.css("marginLeft"), 10) || 0),
                top: (parseInt(this.element.css("marginTop"), 10) || 0)
            };
        },

        _cacheHelperProportions: function() {
            this.helperProportions={
                width: this.helper.outerWidth(),
                height: this.helper.outerHeight()
            };
        },

        _setContainment: function() {

            var o=this.options;
            if (o.containment == 'parent') o.containment=this.helper[0].parentNode;
            if (o.containment == 'document' || o.containment == 'window') this.containment=[
                0 - this.offset.relative.left - this.offset.parent.left,
                0 - this.offset.relative.top - this.offset.parent.top,
                $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
                ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
            ];

            if (!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
                var ce=$(o.containment)[0];
                if (!ce) return;
                var co=$(o.containment).offset();
                var over=($(ce).css("overflow") != 'hidden');

                this.containment=[
                    co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left,
                    co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top,
                    co.left + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - (parseInt($(ce).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left,
                    co.top + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"), 10) || 0) - (parseInt($(ce).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top
                ];
            } else if (o.containment.constructor == Array) {
                this.containment=o.containment;
            }

        },

        _convertPositionTo: function(d, pos) {

            if (!pos) pos=this.position;
            var mod=d == "absolute" ? 1 : -1;
            var o=this.options, scroll=this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);

            return {
                top: (
                        pos.top                                                                    // The absolute mouse position
                                + this.offset.relative.top * mod                                        // Only for relative positioned nodes: Relative offset from element to offset parent
                                + this.offset.parent.top * mod                                            // The offsetParent's offset without borders (offset + border)
                                - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
                        ),
                left: (
                        pos.left                                                                // The absolute mouse position
                                + this.offset.relative.left * mod                                        // Only for relative positioned nodes: Relative offset from element to offset parent
                                + this.offset.parent.left * mod                                            // The offsetParent's offset without borders (offset + border)
                                - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
                        )
            };

        },

        _generatePosition: function(event) {

            var o=this.options, scroll=this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);

            // This is another very weird special case that only happens for relative elements:
            // 1. If the css position is relative
            // 2. and the scroll parent is the document or similar to the offset parent
            // we have to refresh the relative offset during the scroll so there are no jumps
            if (this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
                this.offset.relative=this._getRelativeOffset();
            }

            var pageX=event.pageX;
            var pageY=event.pageY;

            /*
             * - Position constraining -
             * Constrain the position to a mix of grid, containment.
             */

            if (this.originalPosition) { //If we are not dragging yet, we won't check for options

                if (this.containment) {
                    if (event.pageX - this.offset.click.left < this.containment[0]) pageX=this.containment[0] + this.offset.click.left;
                    if (event.pageY - this.offset.click.top < this.containment[1]) pageY=this.containment[1] + this.offset.click.top;
                    if (event.pageX - this.offset.click.left > this.containment[2]) pageX=this.containment[2] + this.offset.click.left;
                    if (event.pageY - this.offset.click.top > this.containment[3]) pageY=this.containment[3] + this.offset.click.top;
                }

                if (o.grid) {
                    var top=this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
                    pageY=this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

                    var left=this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
                    pageX=this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
                }

            }

            return {
                top: (
                        pageY                                                                // The absolute mouse position
                                - this.offset.click.top                                                    // Click offset (relative to the element)
                                - this.offset.relative.top                                                // Only for relative positioned nodes: Relative offset from element to offset parent
                                - this.offset.parent.top                                                // The offsetParent's offset without borders (offset + border)
                                + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
                        ),
                left: (
                        pageX                                                                // The absolute mouse position
                                - this.offset.click.left                                                // Click offset (relative to the element)
                                - this.offset.relative.left                                                // Only for relative positioned nodes: Relative offset from element to offset parent
                                - this.offset.parent.left                                                // The offsetParent's offset without borders (offset + border)
                                + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
                        )
            };

        },

        _clear: function() {
            this.helper.removeClass("ui-draggable-dragging");
            if (this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
            //if($.ui.ddmanager) $.ui.ddmanager.current = null;
            this.helper=null;
            this.cancelHelperRemoval=false;
        },

        // From now on bulk stuff - mainly helpers

        _trigger: function(type, event, ui) {
            ui=ui || this._uiHash();
            $.ui.plugin.call(this, type, [event, ui]);
            if (type == "drag") this.positionAbs=this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
            return $.Widget.prototype._trigger.call(this, type, event, ui);
        },

        plugins: {},

        _uiHash: function(event) {
            return {
                helper: this.helper,
                position: this.position,
                originalPosition: this.originalPosition,
                offset: this.positionAbs
            };
        }

    });

    $.extend($.ui.draggable, {
        version: "1.8rc1",
        eventPrefix: "drag"
    });

    $.ui.plugin.add("draggable", "connectToSortable", {
        start: function(event, ui) {

            var inst=$(this).data("draggable"), o=inst.options,
                    uiSortable=$.extend({}, ui, { item: inst.element });
            inst.sortables=[];
            $(o.connectToSortable).each(function() {
                var sortable=$.data(this, 'sortable');
                if (sortable && !sortable.options.disabled) {
                    inst.sortables.push({
                        instance: sortable,
                        shouldRevert: sortable.options.revert
                    });
                    sortable._refreshItems();	//Do a one-time refresh at start to refresh the containerCache
                    sortable._trigger("activate", event, uiSortable);
                }
            });

        },
        stop: function(event, ui) {

            //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
            var inst=$(this).data("draggable"),
                    uiSortable=$.extend({}, ui, { item: inst.element });

            $.each(inst.sortables, function() {
                if (this.instance.isOver) {

                    this.instance.isOver=0;

                    inst.cancelHelperRemoval=true; //Don't remove the helper in the draggable instance
                    this.instance.cancelHelperRemoval=false; //Remove it in the sortable instance (so sortable plugins like revert still work)

                    //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
                    if (this.shouldRevert) this.instance.options.revert=true;

                    //Trigger the stop of the sortable
                    this.instance._mouseStop(event);

                    this.instance.options.helper=this.instance.options._helper;

                    //If the helper has been the original item, restore properties in the sortable
                    if (inst.options.helper == 'original')
                        this.instance.currentItem.css({ top: 'auto', left: 'auto' });

                } else {
                    this.instance.cancelHelperRemoval=false; //Remove the helper in the sortable instance
                    this.instance._trigger("deactivate", event, uiSortable);
                }

            });

        },
        drag: function(event, ui) {

            var inst=$(this).data("draggable"), self=this;

            var checkPos=function(o) {
                var dyClick=this.offset.click.top, dxClick=this.offset.click.left;
                var helperTop=this.positionAbs.top, helperLeft=this.positionAbs.left;
                var itemHeight=o.height, itemWidth=o.width;
                var itemTop=o.top, itemLeft=o.left;

                return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
            };

            $.each(inst.sortables, function(i) {

                //Copy over some variables to allow calling the sortable's native _intersectsWith
                this.instance.positionAbs=inst.positionAbs;
                this.instance.helperProportions=inst.helperProportions;
                this.instance.offset.click=inst.offset.click;

                if (this.instance._intersectsWith(this.instance.containerCache)) {

                    //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
                    if (!this.instance.isOver) {

                        this.instance.isOver=1;
                        //Now we fake the start of dragging for the sortable instance,
                        //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
                        //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
                        this.instance.currentItem=$(self).clone().appendTo(this.instance.element).data("sortable-item", true);
                        this.instance.options._helper=this.instance.options.helper; //Store helper option to later restore it
                        this.instance.options.helper=function() {
                            return ui.helper[0];
                        };

                        event.target=this.instance.currentItem[0];
                        this.instance._mouseCapture(event, true);
                        this.instance._mouseStart(event, true, true);

                        //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
                        this.instance.offset.click.top=inst.offset.click.top;
                        this.instance.offset.click.left=inst.offset.click.left;
                        this.instance.offset.parent.left-=inst.offset.parent.left - this.instance.offset.parent.left;
                        this.instance.offset.parent.top-=inst.offset.parent.top - this.instance.offset.parent.top;

                        inst._trigger("toSortable", event);
                        inst.dropped=this.instance.element; //draggable revert needs that
                        //hack so receive/update callbacks work (mostly)
                        inst.currentItem=inst.element;
                        this.instance.fromOutside=inst;

                    }

                    //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
                    if (this.instance.currentItem) this.instance._mouseDrag(event);

                } else {

                    //If it doesn't intersect with the sortable, and it intersected before,
                    //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
                    if (this.instance.isOver) {

                        this.instance.isOver=0;
                        this.instance.cancelHelperRemoval=true;

                        //Prevent reverting on this forced stop
                        this.instance.options.revert=false;

                        // The out event needs to be triggered independently
                        this.instance._trigger('out', event, this.instance._uiHash(this.instance));

                        this.instance._mouseStop(event, true);
                        this.instance.options.helper=this.instance.options._helper;

                        //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
                        this.instance.currentItem.remove();
                        if (this.instance.placeholder) this.instance.placeholder.remove();

                        inst._trigger("fromSortable", event);
                        inst.dropped=false; //draggable revert needs that
                    }

                }
                ;

            });

        }
    });

    $.ui.plugin.add("draggable", "cursor", {
        start: function(event, ui) {
            var t=$('body'), o=$(this).data('draggable').options;
            if (t.css("cursor")) o._cursor=t.css("cursor");
            t.css("cursor", o.cursor);
        },
        stop: function(event, ui) {
            var o=$(this).data('draggable').options;
            if (o._cursor) $('body').css("cursor", o._cursor);
        }
    });

    $.ui.plugin.add("draggable", "iframeFix", {
        start: function(event, ui) {
            var o=$(this).data('draggable').options;
            $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
                $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
                        .css({
                    width: this.offsetWidth + "px", height: this.offsetHeight + "px",
                    position: "absolute", opacity: "0.001", zIndex: 1000
                })
                        .css($(this).offset())
                        .appendTo("body");
            });
        },
        stop: function(event, ui) {
            $("div.ui-draggable-iframeFix").each(function() {
                this.parentNode.removeChild(this);
            }); //Remove frame helpers
        }
    });

    $.ui.plugin.add("draggable", "opacity", {
        start: function(event, ui) {
            var t=$(ui.helper), o=$(this).data('draggable').options;
            if (t.css("opacity")) o._opacity=t.css("opacity");
            t.css('opacity', o.opacity);
        },
        stop: function(event, ui) {
            var o=$(this).data('draggable').options;
            if (o._opacity) $(ui.helper).css('opacity', o._opacity);
        }
    });

    $.ui.plugin.add("draggable", "scroll", {
        start: function(event, ui) {
            var i=$(this).data("draggable");
            if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset=i.scrollParent.offset();
        },
        drag: function(event, ui) {

            var i=$(this).data("draggable"), o=i.options, scrolled=false;

            if (i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {

                if (!o.axis || o.axis != 'x') {
                    if ((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
                        i.scrollParent[0].scrollTop=scrolled=i.scrollParent[0].scrollTop + o.scrollSpeed;
                    else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity)
                        i.scrollParent[0].scrollTop=scrolled=i.scrollParent[0].scrollTop - o.scrollSpeed;
                }

                if (!o.axis || o.axis != 'y') {
                    if ((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
                        i.scrollParent[0].scrollLeft=scrolled=i.scrollParent[0].scrollLeft + o.scrollSpeed;
                    else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity)
                        i.scrollParent[0].scrollLeft=scrolled=i.scrollParent[0].scrollLeft - o.scrollSpeed;
                }

            } else {

                if (!o.axis || o.axis != 'x') {
                    if (event.pageY - $(document).scrollTop() < o.scrollSensitivity)
                        scrolled=$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
                    else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
                        scrolled=$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
                }

                if (!o.axis || o.axis != 'y') {
                    if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
                        scrolled=$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
                    else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
                        scrolled=$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
                }

            }

            if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
                $.ui.ddmanager.prepareOffsets(i, event);

        }
    });

    $.ui.plugin.add("draggable", "snap", {
        start: function(event, ui) {

            var i=$(this).data("draggable"), o=i.options;
            i.snapElements=[];

            $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
                var $t=$(this);
                var $o=$t.offset();
                if (this != i.element[0]) i.snapElements.push({
                    item: this,
                    width: $t.outerWidth(), height: $t.outerHeight(),
                    top: $o.top, left: $o.left
                });
            });

        },
        drag: function(event, ui) {

            var inst=$(this).data("draggable"), o=inst.options;
            var d=o.snapTolerance;

            var x1=ui.offset.left, x2=x1 + inst.helperProportions.width,
                    y1=ui.offset.top, y2=y1 + inst.helperProportions.height;

            for (var i=inst.snapElements.length - 1; i >= 0; i--) {

                var l=inst.snapElements[i].left, r=l + inst.snapElements[i].width,
                        t=inst.snapElements[i].top, b=t + inst.snapElements[i].height;

                //Yes, I know, this is insane ;)
                if (!((l - d < x1 && x1 < r + d && t - d < y1 && y1 < b + d) || (l - d < x1 && x1 < r + d && t - d < y2 && y2 < b + d) || (l - d < x2 && x2 < r + d && t - d < y1 && y1 < b + d) || (l - d < x2 && x2 < r + d && t - d < y2 && y2 < b + d))) {
                    if (inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
                    inst.snapElements[i].snapping=false;
                    continue;
                }

                if (o.snapMode != 'inner') {
                    var ts=Math.abs(t - y2) <= d;
                    var bs=Math.abs(b - y1) <= d;
                    var ls=Math.abs(l - x2) <= d;
                    var rs=Math.abs(r - x1) <= d;
                    if (ts) ui.position.top=inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                    if (bs) ui.position.top=inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
                    if (ls) ui.position.left=inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
                    if (rs) ui.position.left=inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
                }

                var first=(ts || bs || ls || rs);

                if (o.snapMode != 'outer') {
                    var ts=Math.abs(t - y1) <= d;
                    var bs=Math.abs(b - y2) <= d;
                    var ls=Math.abs(l - x1) <= d;
                    var rs=Math.abs(r - x2) <= d;
                    if (ts) ui.position.top=inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
                    if (bs) ui.position.top=inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                    if (ls) ui.position.left=inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
                    if (rs) ui.position.left=inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
                }

                if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
                    (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
                inst.snapElements[i].snapping=(ts || bs || ls || rs || first);

            }
            ;

        }
    });

    $.ui.plugin.add("draggable", "stack", {
        start: function(event, ui) {

            var o=$(this).data("draggable").options;

            var group=$.makeArray($(o.stack)).sort(function(a, b) {
                return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
            });

            var min=parseInt(group[0].style.zIndex) || 0;
            $(group).each(function(i) {
                this.style.zIndex=min + i;
            });

            this[0].style.zIndex=min + group.length;

        }
    });

    $.ui.plugin.add("draggable", "zIndex", {
        start: function(event, ui) {
            var t=$(ui.helper), o=$(this).data("draggable").options;
            if (t.css("zIndex")) o._zIndex=t.css("zIndex");
            t.css('zIndex', o.zIndex);
        },
        stop: function(event, ui) {
            var o=$(this).data("draggable").options;
            if (o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
        }
    });

})(jQuery);
/*
 * jQuery UI Droppable 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Droppables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.draggable.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.droppable", {
        options: {
            accept: '*',
            activeClass: false,
            addClasses: true,
            greedy: false,
            hoverClass: false,
            scope: 'default',
            tolerance: 'intersect'
        },
        _create: function() {

            var o=this.options, accept=o.accept;
            this.isover=0;
            this.isout=1;

            this.accept=$.isFunction(accept) ? accept : function(d) {
                return d.is(accept);
            };

            //Store the droppable's proportions
            this.proportions={ width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };

            // Add the reference and positions to the manager
            $.ui.ddmanager.droppables[o.scope]=$.ui.ddmanager.droppables[o.scope] || [];
            $.ui.ddmanager.droppables[o.scope].push(this);

            (o.addClasses && this.element.addClass("ui-droppable"));

        },

        destroy: function() {
            var drop=$.ui.ddmanager.droppables[this.options.scope];
            for (var i=0; i < drop.length; i++)
                if (drop[i] == this)
                    drop.splice(i, 1);

            this.element
                    .removeClass("ui-droppable ui-droppable-disabled")
                    .removeData("droppable")
                    .unbind(".droppable");

            return this;
        },

        _setOption: function(key, value) {

            if (key == 'accept') {
                this.accept=$.isFunction(value) ? value : function(d) {
                    return d.is(value);
                };
            }
            $.Widget.prototype._setOption.apply(this, arguments);
        },

        _activate: function(event) {
            var draggable=$.ui.ddmanager.current;
            if (this.options.activeClass) this.element.addClass(this.options.activeClass);
            (draggable && this._trigger('activate', event, this.ui(draggable)));
        },

        _deactivate: function(event) {
            var draggable=$.ui.ddmanager.current;
            if (this.options.activeClass) this.element.removeClass(this.options.activeClass);
            (draggable && this._trigger('deactivate', event, this.ui(draggable)));
        },

        _over: function(event) {

            var draggable=$.ui.ddmanager.current;
            if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element

            if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) {
                if (this.options.hoverClass) this.element.addClass(this.options.hoverClass);
                this._trigger('over', event, this.ui(draggable));
            }

        },

        _out: function(event) {

            var draggable=$.ui.ddmanager.current;
            if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element

            if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) {
                if (this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
                this._trigger('out', event, this.ui(draggable));
            }

        },

        _drop: function(event, custom) {

            var draggable=custom || $.ui.ddmanager.current;
            if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element

            var childrenIntersection=false;
            this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
                var inst=$.data(this, 'droppable');
                if (
                        inst.options.greedy
                                && !inst.options.disabled
                                && inst.options.scope == draggable.options.scope
                                && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
                                && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
                        ) {
                    childrenIntersection=true;
                    return false;
                }
            });
            if (childrenIntersection) return false;

            if (this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) {
                if (this.options.activeClass) this.element.removeClass(this.options.activeClass);
                if (this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
                this._trigger('drop', event, this.ui(draggable));
                return this.element;
            }

            return false;

        },

        ui: function(c) {
            return {
                draggable: (c.currentItem || c.element),
                helper: c.helper,
                position: c.position,
                offset: c.positionAbs
            };
        }

    });

    $.extend($.ui.droppable, {
        version: "1.8rc1",
        eventPrefix: 'drop'
    });

    $.ui.intersect=function(draggable, droppable, toleranceMode) {

        if (!droppable.offset) return false;

        var x1=(draggable.positionAbs || draggable.position.absolute).left, x2=x1 + draggable.helperProportions.width,
                y1=(draggable.positionAbs || draggable.position.absolute).top, y2=y1 + draggable.helperProportions.height;
        var l=droppable.offset.left, r=l + droppable.proportions.width,
                t=droppable.offset.top, b=t + droppable.proportions.height;

        switch (toleranceMode) {
            case 'fit':
                return (l < x1 && x2 < r
                        && t < y1 && y2 < b);
                break;
            case 'intersect':
                return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
                        && x2 - (draggable.helperProportions.width / 2) < r // Left Half
                        && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
                        && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
                break;
            case 'pointer':
                var draggableLeft=((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
                        draggableTop=((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
                        isOver=$.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
                return isOver;
                break;
            case 'touch':
                return (
                        (y1 >= t && y1 <= b) || // Top edge touching
                        (y2 >= t && y2 <= b) || // Bottom edge touching
                        (y1 < t && y2 > b)        // Surrounded vertically
                        ) && (
                        (x1 >= l && x1 <= r) || // Left edge touching
                        (x2 >= l && x2 <= r) || // Right edge touching
                        (x1 < l && x2 > r)        // Surrounded horizontally
                        );
                break;
            default:
                return false;
                break;
        }

    };

    /*
     This manager tracks offsets of draggables and droppables
     */
    $.ui.ddmanager={
        current: null,
        droppables: { 'default': [] },
        prepareOffsets: function(t, event) {

            var m=$.ui.ddmanager.droppables[t.options.scope] || [];
            var type=event ? event.type : null; // workaround for #2317
            var list=(t.currentItem || t.element).find(":data(droppable)").andSelf();

            droppablesLoop: for (var i=0; i < m.length; i++) {

                if (m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0], (t.currentItem || t.element)))) continue;	//No disabled and non-accepted
                for (var j=0; j < list.length; j++) {
                    if (list[j] == m[i].element[0]) {
                        m[i].proportions.height=0;
                        continue droppablesLoop;
                    }
                }
                ; //Filter out elements in the current dragged item
                m[i].visible=m[i].element.css("display") != "none";
                if (!m[i].visible) continue; 									//If the element is not visible, continue

                m[i].offset=m[i].element.offset();
                m[i].proportions={ width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };

                if (type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables

            }

        },
        drop: function(draggable, event) {

            var dropped=false;
            $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {

                if (!this.options) return;
                if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
                    dropped=dropped || this._drop.call(this, event);

                if (!this.options.disabled && this.visible && this.accept.call(this.element[0], (draggable.currentItem || draggable.element))) {
                    this.isout=1;
                    this.isover=0;
                    this._deactivate.call(this, event);
                }

            });
            return dropped;

        },
        drag: function(draggable, event) {

            //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
            if (draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);

            //Run through all droppables and check their positions based on specific tolerance options
            $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {

                if (this.options.disabled || this.greedyChild || !this.visible) return;
                var intersects=$.ui.intersect(draggable, this, this.options.tolerance);

                var c=!intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
                if (!c) return;

                var parentInstance;
                if (this.options.greedy) {
                    var parent=this.element.parents(':data(droppable):eq(0)');
                    if (parent.length) {
                        parentInstance=$.data(parent[0], 'droppable');
                        parentInstance.greedyChild=(c == 'isover' ? 1 : 0);
                    }
                }

                // we just moved into a greedy child
                if (parentInstance && c == 'isover') {
                    parentInstance['isover']=0;
                    parentInstance['isout']=1;
                    parentInstance._out.call(parentInstance, event);
                }

                this[c]=1;
                this[c == 'isout' ? 'isover' : 'isout']=0;
                this[c == "isover" ? "_over" : "_out"].call(this, event);

                // we just moved out of a greedy child
                if (parentInstance && c == 'isout') {
                    parentInstance['isout']=0;
                    parentInstance['isover']=1;
                    parentInstance._over.call(parentInstance, event);
                }
            });

        }
    };

})(jQuery);
/*
 * jQuery UI Resizable 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Resizables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.resizable", $.ui.mouse, {
        options: {
            alsoResize: false,
            animate: false,
            animateDuration: "slow",
            animateEasing: "swing",
            aspectRatio: false,
            autoHide: false,
            containment: false,
            ghost: false,
            grid: false,
            handles: "e,s,se",
            helper: false,
            maxHeight: null,
            maxWidth: null,
            minHeight: 10,
            minWidth: 10,
            zIndex: 1000
        },
        _create: function() {

            var self=this, o=this.options;
            this.element.addClass("ui-resizable");

            $.extend(this, {
                _aspectRatio: !!(o.aspectRatio),
                aspectRatio: o.aspectRatio,
                originalElement: this.element,
                _proportionallyResizeElements: [],
                _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
            });

            //Wrap the element if it cannot hold child nodes
            if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {

                //Opera fix for relative positioning
                if (/relative/.test(this.element.css('position')) && $.browser.opera)
                    this.element.css({ position: 'relative', top: 'auto', left: 'auto' });

                //Create a wrapper element and set the wrapper to the new current internal element
                this.element.wrap(
                        $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
                            position: this.element.css('position'),
                            width: this.element.outerWidth(),
                            height: this.element.outerHeight(),
                            top: this.element.css('top'),
                            left: this.element.css('left')
                        })
                        );

                //Overwrite the original this.element
                this.element=this.element.parent().data(
                        "resizable", this.element.data('resizable')
                        );

                this.elementIsWrapper=true;

                //Move margins to the wrapper
                this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
                this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});

                //Prevent Safari textarea resize
                this.originalResizeStyle=this.originalElement.css('resize');
                this.originalElement.css('resize', 'none');

                //Push the actual element to our proportionallyResize internal array
                this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));

                // avoid IE jump (hard set the margin)
                this.originalElement.css({ margin: this.originalElement.css('margin') });

                // fix handlers offset
                this._proportionallyResize();

            }

            this.handles=o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
            if (this.handles.constructor == String) {

                if (this.handles == 'all') this.handles='n,e,s,w,se,sw,ne,nw';
                var n=this.handles.split(",");
                this.handles={};

                for (var i=0; i < n.length; i++) {

                    var handle=$.trim(n[i]), hname='ui-resizable-' + handle;
                    var axis=$('<div class="ui-resizable-handle ' + hname + '"></div>');

                    // increase zIndex of sw, se, ne, nw axis
                    //TODO : this modifies original option
                    if (/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });

                    //TODO : What's going on here?
                    if ('se' == handle) {
                        axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
                    }
                    ;

                    //Insert into internal handles object and append to element
                    this.handles[handle]='.ui-resizable-' + handle;
                    this.element.append(axis);
                }

            }

            this._renderAxis=function(target) {

                target=target || this.element;

                for (var i in this.handles) {

                    if (this.handles[i].constructor == String)
                        this.handles[i]=$(this.handles[i], this.element).show();

                    //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
                    if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {

                        var axis=$(this.handles[i], this.element), padWrapper=0;

                        //Checking the correct pad and border
                        padWrapper=/sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();

                        //The padding type i have to apply...
                        var padPos=[ 'padding',
                            /ne|nw|n/.test(i) ? 'Top' :
                            /se|sw|s/.test(i) ? 'Bottom' :
                            /^e$/.test(i) ? 'Right' : 'Left' ].join("");

                        target.css(padPos, padWrapper);

                        this._proportionallyResize();

                    }

                    //TODO: What's that good for? There's not anything to be executed left
                    if (!$(this.handles[i]).length)
                        continue;

                }
            };

            //TODO: make renderAxis a prototype function
            this._renderAxis(this.element);

            this._handles=$('.ui-resizable-handle', this.element)
                    .disableSelection();

            //Matching axis name
            this._handles.mouseover(function() {
                if (!self.resizing) {
                    if (this.className)
                        var axis=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
                    //Axis, default = se
                    self.axis=axis && axis[1] ? axis[1] : 'se';
                }
            });

            //If we want to auto hide the elements
            if (o.autoHide) {
                this._handles.hide();
                $(this.element)
                        .addClass("ui-resizable-autohide")
                        .hover(function() {
                    $(this).removeClass("ui-resizable-autohide");
                    self._handles.show();
                },
                        function() {
                            if (!self.resizing) {
                                $(this).addClass("ui-resizable-autohide");
                                self._handles.hide();
                            }
                        });
            }

            //Initialize the mouse interaction
            this._mouseInit();

        },

        destroy: function() {

            this._mouseDestroy();

            var _destroy=function(exp) {
                $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
                        .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
            };

            //TODO: Unwrap at same DOM position
            if (this.elementIsWrapper) {
                _destroy(this.element);
                var wrapper=this.element;
                wrapper.parent().append(
                        this.originalElement.css({
                            position: wrapper.css('position'),
                            width: wrapper.outerWidth(),
                            height: wrapper.outerHeight(),
                            top: wrapper.css('top'),
                            left: wrapper.css('left')
                        })
                        ).end().remove();
            }

            this.originalElement.css('resize', this.originalResizeStyle);
            _destroy(this.originalElement);

            return this;
        },

        _mouseCapture: function(event) {
            var handle=false;
            for (var i in this.handles) {
                if ($(this.handles[i])[0] == event.target) {
                    handle=true;
                }
            }

            return !this.options.disabled && handle;
        },

        _mouseStart: function(event) {

            var o=this.options, iniPos=this.element.position(), el=this.element;

            this.resizing=true;
            this.documentScroll={ top: $(document).scrollTop(), left: $(document).scrollLeft() };

            // bugfix for http://dev.jquery.com/ticket/1749
            if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
                el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
            }

            //Opera fixing relative position
            if ($.browser.opera && (/relative/).test(el.css('position')))
                el.css({ position: 'relative', top: 'auto', left: 'auto' });

            this._renderProxy();

            var curleft=num(this.helper.css('left')), curtop=num(this.helper.css('top'));

            if (o.containment) {
                curleft+=$(o.containment).scrollLeft() || 0;
                curtop+=$(o.containment).scrollTop() || 0;
            }

            //Store needed variables
            this.offset=this.helper.offset();
            this.position={ left: curleft, top: curtop };
            this.size=this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
            this.originalSize=this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
            this.originalPosition={ left: curleft, top: curtop };
            this.sizeDiff={ width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
            this.originalMousePosition={ left: event.pageX, top: event.pageY };

            //Aspect Ratio
            this.aspectRatio=(typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);

            var cursor=$('.ui-resizable-' + this.axis).css('cursor');
            $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);

            el.addClass("ui-resizable-resizing");
            this._propagate("start", event);
            return true;
        },

        _mouseDrag: function(event) {

            //Increase performance, avoid regex
            var el=this.helper, o=this.options, props={},
                    self=this, smp=this.originalMousePosition, a=this.axis;

            var dx=(event.pageX - smp.left) || 0, dy=(event.pageY - smp.top) || 0;
            var trigger=this._change[a];
            if (!trigger) return false;

            // Calculate the attrs that will be change
            var data=trigger.apply(this, [event, dx, dy]), ie6=$.browser.msie && $.browser.version < 7, csdif=this.sizeDiff;

            if (this._aspectRatio || event.shiftKey)
                data=this._updateRatio(data, event);

            data=this._respectSize(data, event);

            // plugins callbacks need to be called first
            this._propagate("resize", event);

            el.css({
                top: this.position.top + "px", left: this.position.left + "px",
                width: this.size.width + "px", height: this.size.height + "px"
            });

            if (!this._helper && this._proportionallyResizeElements.length)
                this._proportionallyResize();

            this._updateCache(data);

            // calling the user callback at the end
            this._trigger('resize', event, this.ui());

            return false;
        },

        _mouseStop: function(event) {

            this.resizing=false;
            var o=this.options, self=this;

            if (this._helper) {
                var pr=this._proportionallyResizeElements, ista=pr.length && (/textarea/i).test(pr[0].nodeName),
                        soffseth=ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
                        soffsetw=ista ? 0 : self.sizeDiff.width;

                var s={ width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
                        left=(parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
                        top=(parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;

                if (!o.animate)
                    this.element.css($.extend(s, { top: top, left: left }));

                self.helper.height(self.size.height);
                self.helper.width(self.size.width);

                if (this._helper && !o.animate) this._proportionallyResize();
            }

            $('body').css('cursor', 'auto');

            this.element.removeClass("ui-resizable-resizing");

            this._propagate("stop", event);

            if (this._helper) this.helper.remove();
            return false;

        },

        _updateCache: function(data) {
            var o=this.options;
            this.offset=this.helper.offset();
            if (isNumber(data.left)) this.position.left=data.left;
            if (isNumber(data.top)) this.position.top=data.top;
            if (isNumber(data.height)) this.size.height=data.height;
            if (isNumber(data.width)) this.size.width=data.width;
        },

        _updateRatio: function(data, event) {

            var o=this.options, cpos=this.position, csize=this.size, a=this.axis;

            if (data.height) data.width=(csize.height * this.aspectRatio);
            else if (data.width) data.height=(csize.width / this.aspectRatio);

            if (a == 'sw') {
                data.left=cpos.left + (csize.width - data.width);
                data.top=null;
            }
            if (a == 'nw') {
                data.top=cpos.top + (csize.height - data.height);
                data.left=cpos.left + (csize.width - data.width);
            }

            return data;
        },

        _respectSize: function(data, event) {

            var el=this.helper, o=this.options, pRatio=this._aspectRatio || event.shiftKey, a=this.axis,
                    ismaxw=isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh=isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
                    isminw=isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh=isNumber(data.height) && o.minHeight && (o.minHeight > data.height);

            if (isminw) data.width=o.minWidth;
            if (isminh) data.height=o.minHeight;
            if (ismaxw) data.width=o.maxWidth;
            if (ismaxh) data.height=o.maxHeight;

            var dw=this.originalPosition.left + this.originalSize.width, dh=this.position.top + this.size.height;
            var cw=/sw|nw|w/.test(a), ch=/nw|ne|n/.test(a);

            if (isminw && cw) data.left=dw - o.minWidth;
            if (ismaxw && cw) data.left=dw - o.maxWidth;
            if (isminh && ch)    data.top=dh - o.minHeight;
            if (ismaxh && ch)    data.top=dh - o.maxHeight;

            // fixing jump error on top/left - bug #2330
            var isNotwh=!data.width && !data.height;
            if (isNotwh && !data.left && data.top) data.top=null;
            else if (isNotwh && !data.top && data.left) data.left=null;

            return data;
        },

        _proportionallyResize: function() {

            var o=this.options;
            if (!this._proportionallyResizeElements.length) return;
            var element=this.helper || this.element;

            for (var i=0; i < this._proportionallyResizeElements.length; i++) {

                var prel=this._proportionallyResizeElements[i];

                if (!this.borderDif) {
                    var b=[prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
                            p=[prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];

                    this.borderDif=$.map(b, function(v, i) {
                        var border=parseInt(v, 10) || 0, padding=parseInt(p[i], 10) || 0;
                        return border + padding;
                    });
                }

                if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
                    continue;

                prel.css({
                    height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
                    width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
                });

            }
            ;

        },

        _renderProxy: function() {

            var el=this.element, o=this.options;
            this.elementOffset=el.offset();

            if (this._helper) {

                this.helper=this.helper || $('<div style="overflow:hidden;"></div>');

                // fix ie6 offset TODO: This seems broken
                var ie6=$.browser.msie && $.browser.version < 7, ie6offset=(ie6 ? 1 : 0),
                        pxyoffset=( ie6 ? 2 : -1 );

                this.helper.addClass(this._helper).css({
                    width: this.element.outerWidth() + pxyoffset,
                    height: this.element.outerHeight() + pxyoffset,
                    position: 'absolute',
                    left: this.elementOffset.left - ie6offset + 'px',
                    top: this.elementOffset.top - ie6offset + 'px',
                    zIndex: ++o.zIndex //TODO: Don't modify option
                });

                this.helper
                        .appendTo("body")
                        .disableSelection();

            } else {
                this.helper=this.element;
            }

        },

        _change: {
            e: function(event, dx, dy) {
                return { width: this.originalSize.width + dx };
            },
            w: function(event, dx, dy) {
                var o=this.options, cs=this.originalSize, sp=this.originalPosition;
                return { left: sp.left + dx, width: cs.width - dx };
            },
            n: function(event, dx, dy) {
                var o=this.options, cs=this.originalSize, sp=this.originalPosition;
                return { top: sp.top + dy, height: cs.height - dy };
            },
            s: function(event, dx, dy) {
                return { height: this.originalSize.height + dy };
            },
            se: function(event, dx, dy) {
                return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
            },
            sw: function(event, dx, dy) {
                return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
            },
            ne: function(event, dx, dy) {
                return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
            },
            nw: function(event, dx, dy) {
                return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
            }
        },

        _propagate: function(n, event) {
            $.ui.plugin.call(this, n, [event, this.ui()]);
            (n != "resize" && this._trigger(n, event, this.ui()));
        },

        plugins: {},

        ui: function() {
            return {
                originalElement: this.originalElement,
                element: this.element,
                helper: this.helper,
                position: this.position,
                size: this.size,
                originalSize: this.originalSize,
                originalPosition: this.originalPosition
            };
        }

    });

    $.extend($.ui.resizable, {
        version: "1.8rc1",
        eventPrefix: "resize"
    });

    /*
     * Resizable Extensions
     */

    $.ui.plugin.add("resizable", "alsoResize", {

        start: function(event, ui) {

            var self=$(this).data("resizable"), o=self.options;

            var _store=function(exp) {
                $(exp).each(function() {
                    $(this).data("resizable-alsoresize", {
                        width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
                        left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
                    });
                });
            };

            if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
                if (o.alsoResize.length) {
                    o.alsoResize=o.alsoResize[0];
                    _store(o.alsoResize);
                }
                else {
                    $.each(o.alsoResize, function(exp, c) {
                        _store(exp);
                    });
                }
            } else {
                _store(o.alsoResize);
            }
        },

        resize: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options, os=self.originalSize, op=self.originalPosition;

            var delta={
                height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
                top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
            },

                    _alsoResize=function(exp, c) {
                        $(exp).each(function() {
                            var el=$(this), start=$(this).data("resizable-alsoresize"), style={}, css=c && c.length ? c : ['width', 'height', 'top', 'left'];

                            $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
                                var sum=(start[prop] || 0) + (delta[prop] || 0);
                                if (sum && sum >= 0)
                                    style[prop]=sum || null;
                            });

                            //Opera fixing relative position
                            if (/relative/.test(el.css('position')) && $.browser.opera) {
                                self._revertToRelativePosition=true;
                                el.css({ position: 'absolute', top: 'auto', left: 'auto' });
                            }

                            el.css(style);
                        });
                    };

            if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
                $.each(o.alsoResize, function(exp, c) {
                    _alsoResize(exp, c);
                });
            } else {
                _alsoResize(o.alsoResize);
            }
        },

        stop: function(event, ui) {
            var self=$(this).data("resizable");

            //Opera fixing relative position
            if (self._revertToRelativePosition && $.browser.opera) {
                self._revertToRelativePosition=false;
                el.css({ position: 'relative' });
            }

            $(this).removeData("resizable-alsoresize-start");
        }
    });

    $.ui.plugin.add("resizable", "animate", {

        stop: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options;

            var pr=self._proportionallyResizeElements, ista=pr.length && (/textarea/i).test(pr[0].nodeName),
                    soffseth=ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
                    soffsetw=ista ? 0 : self.sizeDiff.width;

            var style={ width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
                    left=(parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
                    top=(parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;

            self.element.animate(
                    $.extend(style, top && left ? { top: top, left: left } : {}), {
                duration: o.animateDuration,
                easing: o.animateEasing,
                step: function() {

                    var data={
                        width: parseInt(self.element.css('width'), 10),
                        height: parseInt(self.element.css('height'), 10),
                        top: parseInt(self.element.css('top'), 10),
                        left: parseInt(self.element.css('left'), 10)
                    };

                    if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });

                    // propagating resize, and updating values for each animation step
                    self._updateCache(data);
                    self._propagate("resize", event);

                }
            }
                    );
        }

    });

    $.ui.plugin.add("resizable", "containment", {

        start: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options, el=self.element;
            var oc=o.containment,    ce=(oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
            if (!ce) return;

            self.containerElement=$(ce);

            if (/document/.test(oc) || oc == document) {
                self.containerOffset={ left: 0, top: 0 };
                self.containerPosition={ left: 0, top: 0 };

                self.parentData={
                    element: $(document), left: 0, top: 0,
                    width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
                };
            }

            // i'm a node, so compute top, left, right, bottom
            else {
                var element=$(ce), p=[];
                $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) {
                    p[i]=num(element.css("padding" + name));
                });

                self.containerOffset=element.offset();
                self.containerPosition=element.position();
                self.containerSize={ height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };

                var co=self.containerOffset, ch=self.containerSize.height,    cw=self.containerSize.width,
                        width=($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height=($.ui.hasScroll(ce) ? ce.scrollHeight : ch);

                self.parentData={
                    element: ce, left: co.left, top: co.top, width: width, height: height
                };
            }
        },

        resize: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options,
                    ps=self.containerSize, co=self.containerOffset, cs=self.size, cp=self.position,
                    pRatio=self._aspectRatio || event.shiftKey, cop={ top:0, left:0 }, ce=self.containerElement;

            if (ce[0] != document && (/static/).test(ce.css('position'))) cop=co;

            if (cp.left < (self._helper ? co.left : 0)) {
                self.size.width=self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
                if (pRatio) self.size.height=self.size.width / o.aspectRatio;
                self.position.left=o.helper ? co.left : 0;
            }

            if (cp.top < (self._helper ? co.top : 0)) {
                self.size.height=self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
                if (pRatio) self.size.width=self.size.height * o.aspectRatio;
                self.position.top=self._helper ? co.top : 0;
            }

            self.offset.left=self.parentData.left + self.position.left;
            self.offset.top=self.parentData.top + self.position.top;

            var woset=Math.abs((self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width),
                    hoset=Math.abs((self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height);

            var isParent=self.containerElement.get(0) == self.element.parent().get(0),
                    isOffsetRelative=/relative|absolute/.test(self.containerElement.css('position'));

            if (isParent && isOffsetRelative) woset-=self.parentData.left;

            if (woset + self.size.width >= self.parentData.width) {
                self.size.width=self.parentData.width - woset;
                if (pRatio) self.size.height=self.size.width / self.aspectRatio;
            }

            if (hoset + self.size.height >= self.parentData.height) {
                self.size.height=self.parentData.height - hoset;
                if (pRatio) self.size.width=self.size.height * self.aspectRatio;
            }
        },

        stop: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options, cp=self.position,
                    co=self.containerOffset, cop=self.containerPosition, ce=self.containerElement;

            var helper=$(self.helper), ho=helper.offset(), w=helper.outerWidth() - self.sizeDiff.width, h=helper.outerHeight() - self.sizeDiff.height;

            if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
                $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });

            if (self._helper && !o.animate && (/static/).test(ce.css('position')))
                $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });

        }
    });

    $.ui.plugin.add("resizable", "ghost", {

        start: function(event, ui) {

            var self=$(this).data("resizable"), o=self.options, cs=self.size;

            self.ghost=self.originalElement.clone();
            self.ghost
                    .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
                    .addClass('ui-resizable-ghost')
                    .addClass(typeof o.ghost == 'string' ? o.ghost : '');

            self.ghost.appendTo(self.helper);

        },

        resize: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options;
            if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
        },

        stop: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options;
            if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
        }

    });

    $.ui.plugin.add("resizable", "grid", {

        resize: function(event, ui) {
            var self=$(this).data("resizable"), o=self.options, cs=self.size, os=self.originalSize, op=self.originalPosition, a=self.axis, ratio=o._aspectRatio || event.shiftKey;
            o.grid=typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
            var ox=Math.round((cs.width - os.width) / (o.grid[0] || 1)) * (o.grid[0] || 1), oy=Math.round((cs.height - os.height) / (o.grid[1] || 1)) * (o.grid[1] || 1);

            if (/^(se|s|e)$/.test(a)) {
                self.size.width=os.width + ox;
                self.size.height=os.height + oy;
            }
            else if (/^(ne)$/.test(a)) {
                self.size.width=os.width + ox;
                self.size.height=os.height + oy;
                self.position.top=op.top - oy;
            }
            else if (/^(sw)$/.test(a)) {
                self.size.width=os.width + ox;
                self.size.height=os.height + oy;
                self.position.left=op.left - ox;
            }
            else {
                self.size.width=os.width + ox;
                self.size.height=os.height + oy;
                self.position.top=op.top - oy;
                self.position.left=op.left - ox;
            }
        }

    });

    var num=function(v) {
        return parseInt(v, 10) || 0;
    };

    var isNumber=function(value) {
        return !isNaN(parseInt(value, 10));
    };

})(jQuery);
/*
 * jQuery UI Selectable 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Selectables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.selectable", $.ui.mouse, {
        options: {
            appendTo: 'body',
            autoRefresh: true,
            distance: 0,
            filter: '*',
            tolerance: 'touch'
        },
        _create: function() {
            var self=this;

            this.element.addClass("ui-selectable");

            this.dragged=false;

            // cache selectee children based on filter
            var selectees;
            this.refresh=function() {
                selectees=$(self.options.filter, self.element[0]);
                selectees.each(function() {
                    var $this=$(this);
                    var pos=$this.offset();
                    $.data(this, "selectable-item", {
                        element: this,
                        $element: $this,
                        left: pos.left,
                        top: pos.top,
                        right: pos.left + $this.outerWidth(),
                        bottom: pos.top + $this.outerHeight(),
                        startselected: false,
                        selected: $this.hasClass('ui-selected'),
                        selecting: $this.hasClass('ui-selecting'),
                        unselecting: $this.hasClass('ui-unselecting')
                    });
                });
            };
            this.refresh();

            this.selectees=selectees.addClass("ui-selectee");

            this._mouseInit();

            this.helper=$(document.createElement('div'))
                    .css({border:'1px dotted black'})
                    .addClass("ui-selectable-helper");
        },

        destroy: function() {
            this.selectees
                    .removeClass("ui-selectee")
                    .removeData("selectable-item");
            this.element
                    .removeClass("ui-selectable ui-selectable-disabled")
                    .removeData("selectable")
                    .unbind(".selectable");
            this._mouseDestroy();

            return this;
        },

        _mouseStart: function(event) {
            var self=this;

            this.opos=[event.pageX, event.pageY];

            if (this.options.disabled)
                return;

            var options=this.options;

            this.selectees=$(options.filter, this.element[0]);

            this._trigger("start", event);

            $(options.appendTo).append(this.helper);
            // position helper (lasso)
            this.helper.css({
                "z-index": 100,
                "position": "absolute",
                "left": event.clientX,
                "top": event.clientY,
                "width": 0,
                "height": 0
            });

            if (options.autoRefresh) {
                this.refresh();
            }

            this.selectees.filter('.ui-selected').each(function() {
                var selectee=$.data(this, "selectable-item");
                selectee.startselected=true;
                if (!event.metaKey) {
                    selectee.$element.removeClass('ui-selected');
                    selectee.selected=false;
                    selectee.$element.addClass('ui-unselecting');
                    selectee.unselecting=true;
                    // selectable UNSELECTING callback
                    self._trigger("unselecting", event, {
                        unselecting: selectee.element
                    });
                }
            });

            $(event.target).parents().andSelf().each(function() {
                var selectee=$.data(this, "selectable-item");
                if (selectee) {
                    selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');
                    selectee.unselecting=false;
                    selectee.selecting=true;
                    selectee.selected=true;
                    // selectable SELECTING callback
                    self._trigger("selecting", event, {
                        selecting: selectee.element
                    });
                    return false;
                }
            });

        },

        _mouseDrag: function(event) {
            var self=this;
            this.dragged=true;

            if (this.options.disabled)
                return;

            var options=this.options;

            var x1=this.opos[0], y1=this.opos[1], x2=event.pageX, y2=event.pageY;
            if (x1 > x2) {
                var tmp=x2;
                x2=x1;
                x1=tmp;
            }
            if (y1 > y2) {
                var tmp=y2;
                y2=y1;
                y1=tmp;
            }
            this.helper.css({left: x1, top: y1, width: x2 - x1, height: y2 - y1});

            this.selectees.each(function() {
                var selectee=$.data(this, "selectable-item");
                //prevent helper from being selected if appendTo: selectable
                if (!selectee || selectee.element == self.element[0])
                    return;
                var hit=false;
                if (options.tolerance == 'touch') {
                    hit=( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
                } else if (options.tolerance == 'fit') {
                    hit=(selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
                }

                if (hit) {
                    // SELECT
                    if (selectee.selected) {
                        selectee.$element.removeClass('ui-selected');
                        selectee.selected=false;
                    }
                    if (selectee.unselecting) {
                        selectee.$element.removeClass('ui-unselecting');
                        selectee.unselecting=false;
                    }
                    if (!selectee.selecting) {
                        selectee.$element.addClass('ui-selecting');
                        selectee.selecting=true;
                        // selectable SELECTING callback
                        self._trigger("selecting", event, {
                            selecting: selectee.element
                        });
                    }
                } else {
                    // UNSELECT
                    if (selectee.selecting) {
                        if (event.metaKey && selectee.startselected) {
                            selectee.$element.removeClass('ui-selecting');
                            selectee.selecting=false;
                            selectee.$element.addClass('ui-selected');
                            selectee.selected=true;
                        } else {
                            selectee.$element.removeClass('ui-selecting');
                            selectee.selecting=false;
                            if (selectee.startselected) {
                                selectee.$element.addClass('ui-unselecting');
                                selectee.unselecting=true;
                            }
                            // selectable UNSELECTING callback
                            self._trigger("unselecting", event, {
                                unselecting: selectee.element
                            });
                        }
                    }
                    if (selectee.selected) {
                        if (!event.metaKey && !selectee.startselected) {
                            selectee.$element.removeClass('ui-selected');
                            selectee.selected=false;

                            selectee.$element.addClass('ui-unselecting');
                            selectee.unselecting=true;
                            // selectable UNSELECTING callback
                            self._trigger("unselecting", event, {
                                unselecting: selectee.element
                            });
                        }
                    }
                }
            });

            return false;
        },

        _mouseStop: function(event) {
            var self=this;

            this.dragged=false;

            var options=this.options;

            $('.ui-unselecting', this.element[0]).each(function() {
                var selectee=$.data(this, "selectable-item");
                selectee.$element.removeClass('ui-unselecting');
                selectee.unselecting=false;
                selectee.startselected=false;
                self._trigger("unselected", event, {
                    unselected: selectee.element
                });
            });
            $('.ui-selecting', this.element[0]).each(function() {
                var selectee=$.data(this, "selectable-item");
                selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
                selectee.selecting=false;
                selectee.selected=true;
                selectee.startselected=true;
                self._trigger("selected", event, {
                    selected: selectee.element
                });
            });
            this._trigger("stop", event);

            this.helper.remove();

            return false;
        }

    });

    $.extend($.ui.selectable, {
        version: "1.8rc1"
    });

})(jQuery);
/*
 * jQuery UI Sortable 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Sortables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.sortable", $.ui.mouse, {
        options: {
            appendTo: "parent",
            axis: false,
            connectWith: false,
            containment: false,
            cursor: 'auto',
            cursorAt: false,
            dropOnEmpty: true,
            forcePlaceholderSize: false,
            forceHelperSize: false,
            grid: false,
            handle: false,
            helper: "original",
            items: '> *',
            opacity: false,
            placeholder: false,
            revert: false,
            scroll: true,
            scrollSensitivity: 20,
            scrollSpeed: 20,
            scope: "default",
            tolerance: "intersect",
            zIndex: 1000
        },
        _create: function() {

            var o=this.options;
            this.containerCache={};
            this.element.addClass("ui-sortable");

            //Get the items
            this.refresh();

            //Let's determine if the items are floating
            this.floating=this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false;

            //Let's determine the parent's offset
            this.offset=this.element.offset();

            //Initialize mouse events for interaction
            this._mouseInit();

        },

        destroy: function() {
            this.element
                    .removeClass("ui-sortable ui-sortable-disabled")
                    .removeData("sortable")
                    .unbind(".sortable");
            this._mouseDestroy();

            for (var i=this.items.length - 1; i >= 0; i--)
                this.items[i].item.removeData("sortable-item");

            return this;
        },

        _mouseCapture: function(event, overrideHandle) {

            if (this.reverting) {
                return false;
            }

            if (this.options.disabled || this.options.type == 'static') return false;

            //We have to refresh the items data once first
            this._refreshItems(event);

            //Find out if the clicked node (or one of its parents) is a actual item in this.items
            var currentItem=null, self=this, nodes=$(event.target).parents().each(function() {
                if ($.data(this, 'sortable-item') == self) {
                    currentItem=$(this);
                    return false;
                }
            });
            if ($.data(event.target, 'sortable-item') == self) currentItem=$(event.target);

            if (!currentItem) return false;
            if (this.options.handle && !overrideHandle) {
                var validHandle=false;

                $(this.options.handle, currentItem).find("*").andSelf().each(function() {
                    if (this == event.target) validHandle=true;
                });
                if (!validHandle) return false;
            }

            this.currentItem=currentItem;
            this._removeCurrentsFromItems();
            return true;

        },

        _mouseStart: function(event, overrideHandle, noActivation) {

            var o=this.options, self=this;
            this.currentContainer=this;

            //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
            this.refreshPositions();

            //Create and append the visible helper
            this.helper=this._createHelper(event);

            //Cache the helper size
            this._cacheHelperProportions();

            /*
             * - Position generation -
             * This block generates everything position related - it's the core of draggables.
             */

            //Cache the margins of the original element
            this._cacheMargins();

            //Get the next scrolling parent
            this.scrollParent=this.helper.scrollParent();

            //The element's absolute position on the page minus margins
            this.offset=this.currentItem.offset();
            this.offset={
                top: this.offset.top - this.margins.top,
                left: this.offset.left - this.margins.left
            };

            // Only after we got the offset, we can change the helper's position to absolute
            // TODO: Still need to figure out a way to make relative sorting possible
            this.helper.css("position", "absolute");
            this.cssPosition=this.helper.css("position");

            $.extend(this.offset, {
                click: { //Where the click happened, relative to the element
                    left: event.pageX - this.offset.left,
                    top: event.pageY - this.offset.top
                },
                parent: this._getParentOffset(),
                relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
            });

            //Generate the original position
            this.originalPosition=this._generatePosition(event);
            this.originalPageX=event.pageX;
            this.originalPageY=event.pageY;

            //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
            (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));

            //Cache the former DOM position
            this.domPosition={ prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };

            //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
            if (this.helper[0] != this.currentItem[0]) {
                this.currentItem.hide();
            }

            //Create the placeholder
            this._createPlaceholder();

            //Set a containment if given in the options
            if (o.containment)
                this._setContainment();

            if (o.cursor) { // cursor option
                if ($('body').css("cursor")) this._storedCursor=$('body').css("cursor");
                $('body').css("cursor", o.cursor);
            }

            if (o.opacity) { // opacity option
                if (this.helper.css("opacity")) this._storedOpacity=this.helper.css("opacity");
                this.helper.css("opacity", o.opacity);
            }

            if (o.zIndex) { // zIndex option
                if (this.helper.css("zIndex")) this._storedZIndex=this.helper.css("zIndex");
                this.helper.css("zIndex", o.zIndex);
            }

            //Prepare scrolling
            if (this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
                this.overflowOffset=this.scrollParent.offset();

            //Call callbacks
            this._trigger("start", event, this._uiHash());

            //Recache the helper size
            if (!this._preserveHelperProportions)
                this._cacheHelperProportions();


            //Post 'activate' events to possible containers
            if (!noActivation) {
                for (var i=this.containers.length - 1; i >= 0; i--) {
                    this.containers[i]._trigger("activate", event, self._uiHash(this));
                }
            }

            //Prepare possible droppables
            if ($.ui.ddmanager)
                $.ui.ddmanager.current=this;

            if ($.ui.ddmanager && !o.dropBehaviour)
                $.ui.ddmanager.prepareOffsets(this, event);

            this.dragging=true;

            this.helper.addClass("ui-sortable-helper");
            this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
            return true;

        },

        _mouseDrag: function(event) {

            //Compute the helpers position
            this.position=this._generatePosition(event);
            this.positionAbs=this._convertPositionTo("absolute");

            if (!this.lastPositionAbs) {
                this.lastPositionAbs=this.positionAbs;
            }

            //Do scrolling
            if (this.options.scroll) {
                var o=this.options, scrolled=false;
                if (this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {

                    if ((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
                        this.scrollParent[0].scrollTop=scrolled=this.scrollParent[0].scrollTop + o.scrollSpeed;
                    else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity)
                        this.scrollParent[0].scrollTop=scrolled=this.scrollParent[0].scrollTop - o.scrollSpeed;

                    if ((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
                        this.scrollParent[0].scrollLeft=scrolled=this.scrollParent[0].scrollLeft + o.scrollSpeed;
                    else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity)
                        this.scrollParent[0].scrollLeft=scrolled=this.scrollParent[0].scrollLeft - o.scrollSpeed;

                } else {

                    if (event.pageY - $(document).scrollTop() < o.scrollSensitivity)
                        scrolled=$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
                    else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
                        scrolled=$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);

                    if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
                        scrolled=$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
                    else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
                        scrolled=$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);

                }

                if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
                    $.ui.ddmanager.prepareOffsets(this, event);
            }

            //Regenerate the absolute position used for position checks
            this.positionAbs=this._convertPositionTo("absolute");

            //Set the helper position
            if (!this.options.axis || this.options.axis != "y") this.helper[0].style.left=this.position.left + 'px';
            if (!this.options.axis || this.options.axis != "x") this.helper[0].style.top=this.position.top + 'px';

            //Rearrange
            for (var i=this.items.length - 1; i >= 0; i--) {

                //Cache variables and intersection, continue if no intersection
                var item=this.items[i], itemElement=item.item[0], intersection=this._intersectsWithPointer(item);
                if (!intersection) continue;

                if (itemElement != this.currentItem[0] //cannot intersect with itself
                        && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
                        && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
                        && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
                //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
                        ) {

                    this.direction=intersection == 1 ? "down" : "up";

                    if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
                        this._rearrange(event, item);
                    } else {
                        break;
                    }

                    this._trigger("change", event, this._uiHash());
                    break;
                }
            }

            //Post events to containers
            this._contactContainers(event);

            //Interconnect with droppables
            if ($.ui.ddmanager) $.ui.ddmanager.drag(this, event);

            //Call callbacks
            this._trigger('sort', event, this._uiHash());

            this.lastPositionAbs=this.positionAbs;
            return false;

        },

        _mouseStop: function(event, noPropagation) {

            if (!event) return;

            //If we are using droppables, inform the manager about the drop
            if ($.ui.ddmanager && !this.options.dropBehaviour)
                $.ui.ddmanager.drop(this, event);

            if (this.options.revert) {
                var self=this;
                var cur=self.placeholder.offset();

                self.reverting=true;

                $(this.helper).animate({
                    left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
                    top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
                }, parseInt(this.options.revert, 10) || 500, function() {
                    self._clear(event);
                });
            } else {
                this._clear(event, noPropagation);
            }

            return false;

        },

        cancel: function() {

            var self=this;

            if (this.dragging) {

                this._mouseUp();

                if (this.options.helper == "original")
                    this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
                else
                    this.currentItem.show();

                //Post deactivating events to containers
                for (var i=this.containers.length - 1; i >= 0; i--) {
                    this.containers[i]._trigger("deactivate", null, self._uiHash(this));
                    if (this.containers[i].containerCache.over) {
                        this.containers[i]._trigger("out", null, self._uiHash(this));
                        this.containers[i].containerCache.over=0;
                    }
                }

            }

            //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds CRUD events from the original node!
            if (this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
            if (this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();

            $.extend(this, {
                helper: null,
                dragging: false,
                reverting: false,
                _noFinalSort: null
            });

            if (this.domPosition.prev) {
                $(this.domPosition.prev).after(this.currentItem);
            } else {
                $(this.domPosition.parent).prepend(this.currentItem);
            }

            return this;

        },

        serialize: function(o) {

            var items=this._getItemsAsjQuery(o && o.connected);
            var str=[];
            o=o || {};

            $(items).each(function() {
                var res=($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
                if (res) str.push((o.key || res[1] + '[]') + '=' + (o.key && o.expression ? res[1] : res[2]));
            });

            return str.join('&');

        },

        toArray: function(o) {

            var items=this._getItemsAsjQuery(o && o.connected);
            var ret=[];
            o=o || {};

            items.each(function() {
                ret.push($(o.item || this).attr(o.attribute || 'id') || '');
            });
            return ret;

        },

        /* Be careful with the following core functions */
        _intersectsWith: function(item) {

            var x1=this.positionAbs.left,
                    x2=x1 + this.helperProportions.width,
                    y1=this.positionAbs.top,
                    y2=y1 + this.helperProportions.height;

            var l=item.left,
                    r=l + item.width,
                    t=item.top,
                    b=t + item.height;

            var dyClick=this.offset.click.top,
                    dxClick=this.offset.click.left;

            var isOverElement=(y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;

            if (this.options.tolerance == "pointer"
                    || this.options.forcePointerForContainers
                    || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
                    ) {
                return isOverElement;
            } else {

                return (l < x1 + (this.helperProportions.width / 2) // Right Half
                        && x2 - (this.helperProportions.width / 2) < r // Left Half
                        && t < y1 + (this.helperProportions.height / 2) // Bottom Half
                        && y2 - (this.helperProportions.height / 2) < b ); // Top Half

            }
        },

        _intersectsWithPointer: function(item) {

            var isOverElementHeight=$.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
                    isOverElementWidth=$.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
                    isOverElement=isOverElementHeight && isOverElementWidth,
                    verticalDirection=this._getDragVerticalDirection(),
                    horizontalDirection=this._getDragHorizontalDirection();

            if (!isOverElement)
                return false;

            return this.floating ?
                   ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
                    : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );

        },

        _intersectsWithSides: function(item) {

            var isOverBottomHalf=$.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height / 2), item.height),
                    isOverRightHalf=$.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width / 2), item.width),
                    verticalDirection=this._getDragVerticalDirection(),
                    horizontalDirection=this._getDragHorizontalDirection();

            if (this.floating && horizontalDirection) {
                return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
            } else {
                return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
            }

        },

        _getDragVerticalDirection: function() {
            var delta=this.positionAbs.top - this.lastPositionAbs.top;
            return delta != 0 && (delta > 0 ? "down" : "up");
        },

        _getDragHorizontalDirection: function() {
            var delta=this.positionAbs.left - this.lastPositionAbs.left;
            return delta != 0 && (delta > 0 ? "right" : "left");
        },

        refresh: function(event) {
            this._refreshItems(event);
            this.refreshPositions();
            return this;
        },

        _connectWith: function() {
            var options=this.options;
            return options.connectWith.constructor == String
                    ? [options.connectWith]
                    : options.connectWith;
        },

        _getItemsAsjQuery: function(connected) {

            var self=this;
            var items=[];
            var queries=[];
            var connectWith=this._connectWith();

            if (connectWith && connected) {
                for (var i=connectWith.length - 1; i >= 0; i--) {
                    var cur=$(connectWith[i]);
                    for (var j=cur.length - 1; j >= 0; j--) {
                        var inst=$.data(cur[j], 'sortable');
                        if (inst && inst != this && !inst.options.disabled) {
                            queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
                        }
                    }
                    ;
                }
                ;
            }

            queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);

            for (var i=queries.length - 1; i >= 0; i--) {
                queries[i][0].each(function() {
                    items.push(this);
                });
            }
            ;

            return $(items);

        },

        _removeCurrentsFromItems: function() {

            var list=this.currentItem.find(":data(sortable-item)");

            for (var i=0; i < this.items.length; i++) {

                for (var j=0; j < list.length; j++) {
                    if (list[j] == this.items[i].item[0])
                        this.items.splice(i, 1);
                }
                ;

            }
            ;

        },

        _refreshItems: function(event) {

            this.items=[];
            this.containers=[this];
            var items=this.items;
            var self=this;
            var queries=[
                [$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]
            ];
            var connectWith=this._connectWith();

            if (connectWith) {
                for (var i=connectWith.length - 1; i >= 0; i--) {
                    var cur=$(connectWith[i]);
                    for (var j=cur.length - 1; j >= 0; j--) {
                        var inst=$.data(cur[j], 'sortable');
                        if (inst && inst != this && !inst.options.disabled) {
                            queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
                            this.containers.push(inst);
                        }
                    }
                    ;
                }
                ;
            }

            for (var i=queries.length - 1; i >= 0; i--) {
                var targetData=queries[i][1];
                var _queries=queries[i][0];

                for (var j=0, queriesLength=_queries.length; j < queriesLength; j++) {
                    var item=$(_queries[j]);

                    item.data('sortable-item', targetData); // Data for target checking (mouse manager)

                    items.push({
                        item: item,
                        instance: targetData,
                        width: 0, height: 0,
                        left: 0, top: 0
                    });
                }
                ;
            }
            ;

        },

        refreshPositions: function(fast) {

            //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
            if (this.offsetParent && this.helper) {
                this.offset.parent=this._getParentOffset();
            }

            for (var i=this.items.length - 1; i >= 0; i--) {
                var item=this.items[i];

                var t=this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;

                if (!fast) {
                    item.width=t.outerWidth();
                    item.height=t.outerHeight();
                }

                var p=t.offset();
                item.left=p.left;
                item.top=p.top;
            }
            ;

            if (this.options.custom && this.options.custom.refreshContainers) {
                this.options.custom.refreshContainers.call(this);
            } else {
                for (var i=this.containers.length - 1; i >= 0; i--) {
                    var p=this.containers[i].element.offset();
                    this.containers[i].containerCache.left=p.left;
                    this.containers[i].containerCache.top=p.top;
                    this.containers[i].containerCache.width=this.containers[i].element.outerWidth();
                    this.containers[i].containerCache.height=this.containers[i].element.outerHeight();
                }
                ;
            }

            return this;
        },

        _createPlaceholder: function(that) {

            var self=that || this, o=self.options;

            if (!o.placeholder || o.placeholder.constructor == String) {
                var className=o.placeholder;
                o.placeholder={
                    element: function() {

                        var el=$(document.createElement(self.currentItem[0].nodeName))
                                .addClass(className || self.currentItem[0].className + " ui-sortable-placeholder")
                                .removeClass("ui-sortable-helper")[0];

                        if (!className)
                            el.style.visibility="hidden";

                        return el;
                    },
                    update: function(container, p) {

                        // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
                        // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
                        if (className && !o.forcePlaceholderSize) return;

                        //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
                        if (!p.height()) {
                            p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop') || 0, 10) - parseInt(self.currentItem.css('paddingBottom') || 0, 10));
                        }
                        ;
                        if (!p.width()) {
                            p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft') || 0, 10) - parseInt(self.currentItem.css('paddingRight') || 0, 10));
                        }
                        ;
                    }
                };
            }

            //Create the placeholder
            self.placeholder=$(o.placeholder.element.call(self.element, self.currentItem));

            //Append it after the actual current item
            self.currentItem.after(self.placeholder);

            //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
            o.placeholder.update(self, self.placeholder);

        },

        _contactContainers: function(event) {

            // get innermost container that intersects with item
            var innermostContainer=null, innermostIndex=null;


            for (var i=this.containers.length - 1; i >= 0; i--) {

                // never consider a container that's located within the item itself
                if ($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
                    continue;

                if (this._intersectsWith(this.containers[i].containerCache)) {

                    // if we've already found a container and it's more "inner" than this, then continue
                    if (innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
                        continue;

                    innermostContainer=this.containers[i];
                    innermostIndex=i;

                } else {
                    // container doesn't intersect. trigger "out" event if necessary
                    if (this.containers[i].containerCache.over) {
                        this.containers[i]._trigger("out", event, this._uiHash(this));
                        this.containers[i].containerCache.over=0;
                    }
                }

            }

            // if no intersecting containers found, return
            if (!innermostContainer) return;

            // move the item into the container if it's not there already
            if (this.currentContainer != this.containers[innermostIndex]) {

                //When entering a new container, we will find the item with the least distance and append our item near it
                var dist=10000;
                var itemWithLeastDistance=null;
                var base=this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
                for (var j=this.items.length - 1; j >= 0; j--) {
                    if (!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
                    var cur=this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
                    if (Math.abs(cur - base) < dist) {
                        dist=Math.abs(cur - base);
                        itemWithLeastDistance=this.items[j];
                    }
                }

                if (!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
                    return;

                this.currentContainer=this.containers[innermostIndex];
                itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
                this._trigger("change", event, this._uiHash());
                this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));

                //Update the placeholder
                this.options.placeholder.update(this.currentContainer, this.placeholder);

            }

            this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
            this.containers[innermostIndex].containerCache.over=1;

        },

        _createHelper: function(event) {

            var o=this.options;
            var helper=$.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);

            if (!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
                $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);

            if (helper[0] == this.currentItem[0])
                this._storedCSS={ width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };

            if (helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
            if (helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());

            return helper;

        },

        _adjustOffsetFromHelper: function(obj) {
            if (typeof obj == 'string') {
                obj=obj.split(' ');
            }
            if ($.isArray(obj)) {
                obj={left: +obj[0], top: +obj[1] || 0};
            }
            if ('left' in obj) {
                this.offset.click.left=obj.left + this.margins.left;
            }
            if ('right' in obj) {
                this.offset.click.left=this.helperProportions.width - obj.right + this.margins.left;
            }
            if ('top' in obj) {
                this.offset.click.top=obj.top + this.margins.top;
            }
            if ('bottom' in obj) {
                this.offset.click.top=this.helperProportions.height - obj.bottom + this.margins.top;
            }
        },

        _getParentOffset: function() {


            //Get the offsetParent and cache its position
            this.offsetParent=this.helper.offsetParent();
            var po=this.offsetParent.offset();

            // This is a special case where we need to modify a offset calculated on start, since the following happened:
            // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
            // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
            //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
            if (this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
                po.left+=this.scrollParent.scrollLeft();
                po.top+=this.scrollParent.scrollTop();
            }

            if ((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
                    || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
                po={ top: 0, left: 0 };

            return {
                top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
                left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
            };

        },

        _getRelativeOffset: function() {

            if (this.cssPosition == "relative") {
                var p=this.currentItem.position();
                return {
                    top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(),
                    left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()
                };
            } else {
                return { top: 0, left: 0 };
            }

        },

        _cacheMargins: function() {
            this.margins={
                left: (parseInt(this.currentItem.css("marginLeft"), 10) || 0),
                top: (parseInt(this.currentItem.css("marginTop"), 10) || 0)
            };
        },

        _cacheHelperProportions: function() {
            this.helperProportions={
                width: this.helper.outerWidth(),
                height: this.helper.outerHeight()
            };
        },

        _setContainment: function() {

            var o=this.options;
            if (o.containment == 'parent') o.containment=this.helper[0].parentNode;
            if (o.containment == 'document' || o.containment == 'window') this.containment=[
                0 - this.offset.relative.left - this.offset.parent.left,
                0 - this.offset.relative.top - this.offset.parent.top,
                $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
                ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
            ];

            if (!(/^(document|window|parent)$/).test(o.containment)) {
                var ce=$(o.containment)[0];
                var co=$(o.containment).offset();
                var over=($(ce).css("overflow") != 'hidden');

                this.containment=[
                    co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left,
                    co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top,
                    co.left + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - (parseInt($(ce).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left,
                    co.top + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"), 10) || 0) - (parseInt($(ce).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top
                ];
            }

        },

        _convertPositionTo: function(d, pos) {

            if (!pos) pos=this.position;
            var mod=d == "absolute" ? 1 : -1;
            var o=this.options, scroll=this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);

            return {
                top: (
                        pos.top                                                                    // The absolute mouse position
                                + this.offset.relative.top * mod                                        // Only for relative positioned nodes: Relative offset from element to offset parent
                                + this.offset.parent.top * mod                                            // The offsetParent's offset without borders (offset + border)
                                - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
                        ),
                left: (
                        pos.left                                                                // The absolute mouse position
                                + this.offset.relative.left * mod                                        // Only for relative positioned nodes: Relative offset from element to offset parent
                                + this.offset.parent.left * mod                                            // The offsetParent's offset without borders (offset + border)
                                - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
                        )
            };

        },

        _generatePosition: function(event) {

            var o=this.options, scroll=this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode=(/(html|body)/i).test(scroll[0].tagName);

            // This is another very weird special case that only happens for relative elements:
            // 1. If the css position is relative
            // 2. and the scroll parent is the document or similar to the offset parent
            // we have to refresh the relative offset during the scroll so there are no jumps
            if (this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
                this.offset.relative=this._getRelativeOffset();
            }

            var pageX=event.pageX;
            var pageY=event.pageY;

            /*
             * - Position constraining -
             * Constrain the position to a mix of grid, containment.
             */

            if (this.originalPosition) { //If we are not dragging yet, we won't check for options

                if (this.containment) {
                    if (event.pageX - this.offset.click.left < this.containment[0]) pageX=this.containment[0] + this.offset.click.left;
                    if (event.pageY - this.offset.click.top < this.containment[1]) pageY=this.containment[1] + this.offset.click.top;
                    if (event.pageX - this.offset.click.left > this.containment[2]) pageX=this.containment[2] + this.offset.click.left;
                    if (event.pageY - this.offset.click.top > this.containment[3]) pageY=this.containment[3] + this.offset.click.top;
                }

                if (o.grid) {
                    var top=this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
                    pageY=this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

                    var left=this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
                    pageX=this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
                }

            }

            return {
                top: (
                        pageY                                                                // The absolute mouse position
                                - this.offset.click.top                                                    // Click offset (relative to the element)
                                - this.offset.relative.top                                                // Only for relative positioned nodes: Relative offset from element to offset parent
                                - this.offset.parent.top                                                // The offsetParent's offset without borders (offset + border)
                                + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
                        ),
                left: (
                        pageX                                                                // The absolute mouse position
                                - this.offset.click.left                                                // Click offset (relative to the element)
                                - this.offset.relative.left                                                // Only for relative positioned nodes: Relative offset from element to offset parent
                                - this.offset.parent.left                                                // The offsetParent's offset without borders (offset + border)
                                + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
                        )
            };

        },

        _rearrange: function(event, i, a, hardRefresh) {

            a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));

            //Various things done here to improve the performance:
            // 1. we create a setTimeout, that calls refreshPositions
            // 2. on the instance, we have a counter variable, that get's higher after every append
            // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
            // 4. this lets only the last addition to the timeout stack through
            this.counter=this.counter ? ++this.counter : 1;
            var self=this, counter=this.counter;

            window.setTimeout(function() {
                if (counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
            }, 0);

        },

        _clear: function(event, noPropagation) {

            this.reverting=false;
            // We delay all events that have to be triggered to after the point where the placeholder has been removed and
            // everything else normalized again
            var delayedTriggers=[], self=this;

            // We first have to update the dom position of the actual currentItem
            // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
            if (!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
            this._noFinalSort=null;

            if (this.helper[0] == this.currentItem[0]) {
                for (var i in this._storedCSS) {
                    if (this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i]='';
                }
                this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
            } else {
                this.currentItem.show();
            }

            if (this.fromOutside && !noPropagation) delayedTriggers.push(function(event) {
                this._trigger("receive", event, this._uiHash(this.fromOutside));
            });
            if ((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) {
                this._trigger("update", event, this._uiHash());
            }); //Trigger update callback if the DOM position has changed
            if (!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
                if (!noPropagation) delayedTriggers.push(function(event) {
                    this._trigger("remove", event, this._uiHash());
                });
                for (var i=this.containers.length - 1; i >= 0; i--) {
                    if ($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
                        delayedTriggers.push((function(c) {
                            return function(event) {
                                c._trigger("receive", event, this._uiHash(this));
                            };
                        }).call(this, this.containers[i]));
                        delayedTriggers.push((function(c) {
                            return function(event) {
                                c._trigger("update", event, this._uiHash(this));
                            };
                        }).call(this, this.containers[i]));
                    }
                }
                ;
            }
            ;

            //Post events to containers
            for (var i=this.containers.length - 1; i >= 0; i--) {
                if (!noPropagation) delayedTriggers.push((function(c) {
                    return function(event) {
                        c._trigger("deactivate", event, this._uiHash(this));
                    };
                }).call(this, this.containers[i]));
                if (this.containers[i].containerCache.over) {
                    delayedTriggers.push((function(c) {
                        return function(event) {
                            c._trigger("out", event, this._uiHash(this));
                        };
                    }).call(this, this.containers[i]));
                    this.containers[i].containerCache.over=0;
                }
            }

            //Do what was originally in plugins
            if (this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
            if (this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
            if (this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index

            this.dragging=false;
            if (this.cancelHelperRemoval) {
                if (!noPropagation) {
                    this._trigger("beforeStop", event, this._uiHash());
                    for (var i=0; i < delayedTriggers.length; i++) {
                        delayedTriggers[i].call(this, event);
                    }
                    ; //Trigger all delayed events
                    this._trigger("stop", event, this._uiHash());
                }
                return false;
            }

            if (!noPropagation) this._trigger("beforeStop", event, this._uiHash());

            //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds CRUD events from the original node!
            this.placeholder[0].parentNode.removeChild(this.placeholder[0]);

            if (this.helper[0] != this.currentItem[0]) this.helper.remove();
            this.helper=null;

            if (!noPropagation) {
                for (var i=0; i < delayedTriggers.length; i++) {
                    delayedTriggers[i].call(this, event);
                }
                ; //Trigger all delayed events
                this._trigger("stop", event, this._uiHash());
            }

            this.fromOutside=false;
            return true;

        },

        _trigger: function() {
            if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
                this.cancel();
            }
        },

        _uiHash: function(inst) {
            var self=inst || this;
            return {
                helper: self.helper,
                placeholder: self.placeholder || $([]),
                position: self.position,
                originalPosition: self.originalPosition,
                offset: self.positionAbs,
                item: self.currentItem,
                sender: inst ? inst.element : null
            };
        }

    });

    $.extend($.ui.sortable, {
        version: "1.8rc1",
        eventPrefix: "sort"
    });

})(jQuery);
/*
 * jQuery UI Effects 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/
 */
;
jQuery.effects || (function($) {

    $.effects={};


    /******************************************************************************/
    /****************************** COLOR ANIMATIONS ******************************/
    /******************************************************************************/

    // override the animation for color styles
    $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
        'borderRightColor', 'borderTopColor', 'color', 'outlineColor'],
            function(i, attr) {
                $.fx.step[attr]=function(fx) {
                    if (!fx.colorInit) {
                        fx.start=getColor(fx.elem, attr);
                        fx.end=getRGB(fx.end);
                        fx.colorInit=true;
                    }

                    fx.elem.style[attr]='rgb(' +
                                        Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
                                        Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
                                        Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
                };
            });

    // Color Conversion functions from highlightFade
    // By Blair Mitchelmore
    // http://jquery.offput.ca/highlightFade/

    // Parse strings looking for color tuples [255,255,255]
    function getRGB(color) {
        var result;

        // Check if we're already dealing with an array of colors
        if (color && color.constructor == Array && color.length == 3)
            return color;

        // Look for rgb(num,num,num)
        if (result=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
            return [parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10)];

        // Look for rgb(num%,num%,num%)
        if (result=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
            return [parseFloat(result[1]) * 2.55, parseFloat(result[2]) * 2.55, parseFloat(result[3]) * 2.55];

        // Look for #a0b1c2
        if (result=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
            return [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)];

        // Look for #fff
        if (result=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
            return [parseInt(result[1] + result[1], 16), parseInt(result[2] + result[2], 16), parseInt(result[3] + result[3], 16)];

        // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
        if (result=/rgba\(0, 0, 0, 0\)/.exec(color))
            return colors['transparent'];

        // Otherwise, we're most likely dealing with a named color
        return colors[$.trim(color).toLowerCase()];
    }

    function getColor(elem, attr) {
        var color;

        do {
            color=$.curCSS(elem, attr);

            // Keep going until we find an element that has color, or we hit the body
            if (color != '' && color != 'transparent' || $.nodeName(elem, "body"))
                break;

            attr="backgroundColor";
        } while (elem=elem.parentNode);

        return getRGB(color);
    }

    ;

    // Some named colors to work with
    // From Interface by Stefan Petre
    // http://interface.eyecon.ro/

    var colors={
        aqua:[0,255,255],
        azure:[240,255,255],
        beige:[245,245,220],
        black:[0,0,0],
        blue:[0,0,255],
        brown:[165,42,42],
        cyan:[0,255,255],
        darkblue:[0,0,139],
        darkcyan:[0,139,139],
        darkgrey:[169,169,169],
        darkgreen:[0,100,0],
        darkkhaki:[189,183,107],
        darkmagenta:[139,0,139],
        darkolivegreen:[85,107,47],
        darkorange:[255,140,0],
        darkorchid:[153,50,204],
        darkred:[139,0,0],
        darksalmon:[233,150,122],
        darkviolet:[148,0,211],
        fuchsia:[255,0,255],
        gold:[255,215,0],
        green:[0,128,0],
        indigo:[75,0,130],
        khaki:[240,230,140],
        lightblue:[173,216,230],
        lightcyan:[224,255,255],
        lightgreen:[144,238,144],
        lightgrey:[211,211,211],
        lightpink:[255,182,193],
        lightyellow:[255,255,224],
        lime:[0,255,0],
        magenta:[255,0,255],
        maroon:[128,0,0],
        navy:[0,0,128],
        olive:[128,128,0],
        orange:[255,165,0],
        pink:[255,192,203],
        purple:[128,0,128],
        violet:[128,0,128],
        red:[255,0,0],
        silver:[192,192,192],
        white:[255,255,255],
        yellow:[255,255,0],
        transparent: [255,255,255]
    };


    /******************************************************************************/
    /****************************** CLASS ANIMATIONS ******************************/
    /******************************************************************************/

    var classAnimationActions=['add', 'remove', 'toggle'],
            shorthandStyles={
                border: 1,
                borderBottom: 1,
                borderColor: 1,
                borderLeft: 1,
                borderRight: 1,
                borderTop: 1,
                borderWidth: 1,
                margin: 1,
                padding: 1
            };

    function getElementStyles() {
        var style=document.defaultView
                ? document.defaultView.getComputedStyle(this, null)
                : this.currentStyle,
                newStyle={},
                key,
                camelCase;

        // webkit enumerates style porperties
        if (style && style.length && style[0] && style[style[0]]) {
            var len=style.length;
            while (len--) {
                key=style[len];
                if (typeof style[key] == 'string') {
                    camelCase=key.replace(/\-(\w)/g, function(all, letter) {
                        return letter.toUpperCase();
                    });
                    newStyle[camelCase]=style[key];
                }
            }
        } else {
            for (key in style) {
                if (typeof style[key] === 'string') {
                    newStyle[key]=style[key];
                }
            }
        }

        return newStyle;
    }

    function filterStyles(styles) {
        var name, value;
        for (name in styles) {
            value=styles[name];
            if (
            // ignore null and undefined values
                    value == null ||
                        // ignore functions (when does this occur?)
                    $.isFunction(value) ||
                        // shorthand styles that need to be expanded
                    name in shorthandStyles ||
                        // ignore scrollbars (break in IE)
                    (/scrollbar/).test(name) ||

                        // only colors or values that can be converted to numbers
                    (!(/color/i).test(name) && isNaN(parseFloat(value)))
                    ) {
                delete styles[name];
            }
        }

        return styles;
    }

    function styleDifference(oldStyle, newStyle) {
        var diff={ _: 0 }, // http://dev.jquery.com/ticket/5459
                name;

        for (name in newStyle) {
            if (oldStyle[name] != newStyle[name]) {
                diff[name]=newStyle[name];
            }
        }

        return diff;
    }

    $.effects.animateClass=function(value, duration, easing, callback) {
        if ($.isFunction(easing)) {
            callback=easing;
            easing=null;
        }

        return this.each(function() {

            var that=$(this),
                    originalStyleAttr=that.attr('style') || ' ',
                    originalStyle=filterStyles(getElementStyles.call(this)),
                    newStyle,
                    className=that.attr('className');

            $.each(classAnimationActions, function(i, action) {
                if (value[action]) {
                    that[action + 'Class'](value[action]);
                }
            });
            newStyle=filterStyles(getElementStyles.call(this));
            that.attr('className', className);

            that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
                $.each(classAnimationActions, function(i, action) {
                    if (value[action]) {
                        that[action + 'Class'](value[action]);
                    }
                });
                // work around bug in IE by clearing the cssText before setting it
                if (typeof that.attr('style') == 'object') {
                    that.attr('style').cssText='';
                    that.attr('style').cssText=originalStyleAttr;
                } else {
                    that.attr('style', originalStyleAttr);
                }
                if (callback) {
                    callback.apply(this, arguments);
                }
            });
        });
    };

    $.fn.extend({
        _addClass: $.fn.addClass,
        addClass: function(classNames, speed, easing, callback) {
            return speed ? $.effects.animateClass.apply(this, [
                { add: classNames },
                speed,
                easing,
                callback
            ]) : this._addClass(classNames);
        },

        _removeClass: $.fn.removeClass,
        removeClass: function(classNames, speed, easing, callback) {
            return speed ? $.effects.animateClass.apply(this, [
                { remove: classNames },
                speed,
                easing,
                callback
            ]) : this._removeClass(classNames);
        },

        _toggleClass: $.fn.toggleClass,
        toggleClass: function(classNames, force, speed, easing, callback) {
            if (typeof force == "boolean" || force === undefined) {
                if (!speed) {
                    // without speed parameter;
                    return this._toggleClass(classNames, force);
                } else {
                    return $.effects.animateClass.apply(this, [(force ? {add:classNames} : {remove:classNames}),speed,easing,callback]);
                }
            } else {
                // without switch parameter;
                return $.effects.animateClass.apply(this, [
                    { toggle: classNames },
                    force,
                    speed,
                    easing
                ]);
            }
        },

        switchClass: function(remove, add, speed, easing, callback) {
            return $.effects.animateClass.apply(this, [
                { add: add, remove: remove },
                speed,
                easing,
                callback
            ]);
        }
    });


    /******************************************************************************/
    /*********************************** EFFECTS **********************************/
    /******************************************************************************/

    $.extend($.effects, {
        version: "1.8rc1",

        // Saves a set of properties in a data storage
        save: function(element, set) {
            for (var i=0; i < set.length; i++) {
                if (set[i] !== null) element.data("ec.storage." + set[i], element[0].style[set[i]]);
            }
        },

        // Restores a set of previously saved properties from a data storage
        restore: function(element, set) {
            for (var i=0; i < set.length; i++) {
                if (set[i] !== null) element.css(set[i], element.data("ec.storage." + set[i]));
            }
        },

        setMode: function(el, mode) {
            if (mode == 'toggle') mode=el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
            return mode;
        },

        getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
            // this should be a little more flexible in the future to handle a string & hash
            var y, x;
            switch (origin[0]) {
                case 'top': y=0; break;
                case 'middle': y=0.5; break;
                case 'bottom': y=1; break;
                default: y=origin[0] / original.height;
            }
            ;
            switch (origin[1]) {
                case 'left': x=0; break;
                case 'center': x=0.5; break;
                case 'right': x=1; break;
                default: x=origin[1] / original.width;
            }
            ;
            return {x: x, y: y};
        },

        // Wraps the element around a wrapper that copies position properties
        createWrapper: function(element) {

            // if the element is already wrapped, return it
            if (element.parent().is('.ui-effects-wrapper')) {
                return element.parent();
            }

            // wrap the element
            var props={
                width: element.outerWidth(true),
                height: element.outerHeight(true),
                'float': element.css('float')
            },
                    wrapper=$('<div></div>')
                            .addClass('ui-effects-wrapper')
                            .css({
                        fontSize: '100%',
                        background: 'transparent',
                        border: 'none',
                        margin: 0,
                        padding: 0
                    });

            element.wrap(wrapper);

            // transfer positioning properties to the wrapper
            if (element.css('position') == 'static') {
                wrapper.css({ position: 'relative' });
                element.css({ position: 'relative' });
            } else {
                $.extend(props, {
                    position: element.css('position'),
                    zIndex: element.css('z-index')
                });
                $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
                    props[pos]=element.css(pos);
                    if (isNaN(parseInt(props[pos], 10))) {
                        props[pos]='auto';
                    }
                });
                element.css({position: 'relative', top: 0, left: 0 });
            }

            return wrapper.css(props).show();
        },

        removeWrapper: function(element) {
            if (element.parent().is('.ui-effects-wrapper'))
                return element.parent().replaceWith(element);
            return element;
        },

        setTransition: function(element, list, factor, value) {
            value=value || {};
            $.each(list, function(i, x) {
                unit=element.cssUnit(x);
                if (unit[0] > 0) value[x]=unit[0] * factor + unit[1];
            });
            return value;
        }
    });


    function _normalizeArguments(effect, options, speed, callback) {
        // shift params for method overloading
        if (typeof effect == 'object') {
            callback=options;
            speed=null;
            options=effect;
            effect=options.effect;
        }
        if ($.isFunction(options)) {
            callback=options;
            speed=null;
            options={};
        }
        if (typeof options == 'number') {
            callback=speed;
            speed=options;
            options={};
        }

        options=options || {};

        speed=speed || options.duration;
        speed=$.fx.off ? 0 : typeof speed == 'number'
                ? speed : $.fx.speeds[speed] || $.fx.speeds._default;

        callback=callback || options.complete;

        return [effect, options, speed, callback];
    }

    $.fn.extend({
        effect: function(effect, options, speed, callback) {
            var args=_normalizeArguments.apply(this, arguments),
                // TODO: make effects takes actual parameters instead of a hash
                    args2={
                        options: args[1],
                        duration: args[2],
                        callback: args[3]
                    },
                    effectMethod=$.effects[effect];

            return effectMethod && !$.fx.off ? effectMethod.call(this, args2) : this;
        },

        _show: $.fn.show,
        show: function(speed) {
            if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
                return this._show.apply(this, arguments);
            } else {
                var args=_normalizeArguments.apply(this, arguments);
                args[1].mode='show';
                return this.effect.apply(this, args);
            }
        },

        _hide: $.fn.hide,
        hide: function(speed) {
            if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
                return this._hide.apply(this, arguments);
            } else {
                var args=_normalizeArguments.apply(this, arguments);
                args[1].mode='hide';
                return this.effect.apply(this, args);
            }
        },

        // jQuery core overloads toggle and create _toggle
        __toggle: $.fn.toggle,
        toggle: function(speed) {
            if (!speed || typeof speed == 'number' || $.fx.speeds[speed] ||
                typeof speed == 'boolean' || $.isFunction(speed)) {
                return this.__toggle.apply(this, arguments);
            } else {
                var args=_normalizeArguments.apply(this, arguments);
                args[1].mode='toggle';
                return this.effect.apply(this, args);
            }
        },

        // helper functions
        cssUnit: function(key) {
            var style=this.css(key), val=[];
            $.each(['em','px','%','pt'], function(i, unit) {
                if (style.indexOf(unit) > 0)
                    val=[parseFloat(style), unit];
            });
            return val;
        }
    });


    /******************************************************************************/
    /*********************************** EASING ***********************************/
    /******************************************************************************/

    /*
     * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
     *
     * Uses the built in easing capabilities added In jQuery 1.1
     * to offer multiple easing options
     *
     * TERMS OF USE - jQuery Easing
     *
     * Open source under the BSD License.
     *
     * Copyright 2008 George McGinley Smith
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * Redistributions of source code must retain the above copyright notice, this list of
     * conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright notice, this list
     * of conditions and the following disclaimer in the documentation and/or other materials
     * provided with the distribution.
     *
     * Neither the name of the author nor the names of contributors may be used to endorse
     * or promote products derived from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
     * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     * OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */

    // t: current time, b: begInnIng value, c: change In value, d: duration
    $.easing.jswing=$.easing.swing;

    $.extend($.easing,
    {
        def: 'easeOutQuad',
        swing: function (x, t, b, c, d) {
            //alert($.easing.default);
            return $.easing[$.easing.def](x, t, b, c, d);
        },
        easeInQuad: function (x, t, b, c, d) {
            return c * (t/=d) * t + b;
        },
        easeOutQuad: function (x, t, b, c, d) {
            return -c * (t/=d) * (t - 2) + b;
        },
        easeInOutQuad: function (x, t, b, c, d) {
            if ((t/=d / 2) < 1) return c / 2 * t * t + b;
            return -c / 2 * ((--t) * (t - 2) - 1) + b;
        },
        easeInCubic: function (x, t, b, c, d) {
            return c * (t/=d) * t * t + b;
        },
        easeOutCubic: function (x, t, b, c, d) {
            return c * ((t=t / d - 1) * t * t + 1) + b;
        },
        easeInOutCubic: function (x, t, b, c, d) {
            if ((t/=d / 2) < 1) return c / 2 * t * t * t + b;
            return c / 2 * ((t-=2) * t * t + 2) + b;
        },
        easeInQuart: function (x, t, b, c, d) {
            return c * (t/=d) * t * t * t + b;
        },
        easeOutQuart: function (x, t, b, c, d) {
            return -c * ((t=t / d - 1) * t * t * t - 1) + b;
        },
        easeInOutQuart: function (x, t, b, c, d) {
            if ((t/=d / 2) < 1) return c / 2 * t * t * t * t + b;
            return -c / 2 * ((t-=2) * t * t * t - 2) + b;
        },
        easeInQuint: function (x, t, b, c, d) {
            return c * (t/=d) * t * t * t * t + b;
        },
        easeOutQuint: function (x, t, b, c, d) {
            return c * ((t=t / d - 1) * t * t * t * t + 1) + b;
        },
        easeInOutQuint: function (x, t, b, c, d) {
            if ((t/=d / 2) < 1) return c / 2 * t * t * t * t * t + b;
            return c / 2 * ((t-=2) * t * t * t * t + 2) + b;
        },
        easeInSine: function (x, t, b, c, d) {
            return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
        },
        easeOutSine: function (x, t, b, c, d) {
            return c * Math.sin(t / d * (Math.PI / 2)) + b;
        },
        easeInOutSine: function (x, t, b, c, d) {
            return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
        },
        easeInExpo: function (x, t, b, c, d) {
            return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
        },
        easeOutExpo: function (x, t, b, c, d) {
            return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
        },
        easeInOutExpo: function (x, t, b, c, d) {
            if (t == 0) return b;
            if (t == d) return b + c;
            if ((t/=d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
            return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
        },
        easeInCirc: function (x, t, b, c, d) {
            return -c * (Math.sqrt(1 - (t/=d) * t) - 1) + b;
        },
        easeOutCirc: function (x, t, b, c, d) {
            return c * Math.sqrt(1 - (t=t / d - 1) * t) + b;
        },
        easeInOutCirc: function (x, t, b, c, d) {
            if ((t/=d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
            return c / 2 * (Math.sqrt(1 - (t-=2) * t) + 1) + b;
        },
        easeInElastic: function (x, t, b, c, d) {
            var s=1.70158;
            var p=0;
            var a=c;
            if (t == 0) return b;
            if ((t/=d) == 1) return b + c;
            if (!p) p=d * .3;
            if (a < Math.abs(c)) {
                a=c;
                var s=p / 4;
            }
            else var s=p / (2 * Math.PI) * Math.asin(c / a);
            return -(a * Math.pow(2, 10 * (t-=1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
        },
        easeOutElastic: function (x, t, b, c, d) {
            var s=1.70158;
            var p=0;
            var a=c;
            if (t == 0) return b;
            if ((t/=d) == 1) return b + c;
            if (!p) p=d * .3;
            if (a < Math.abs(c)) {
                a=c;
                var s=p / 4;
            }
            else var s=p / (2 * Math.PI) * Math.asin(c / a);
            return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
        },
        easeInOutElastic: function (x, t, b, c, d) {
            var s=1.70158;
            var p=0;
            var a=c;
            if (t == 0) return b;
            if ((t/=d / 2) == 2) return b + c;
            if (!p) p=d * (.3 * 1.5);
            if (a < Math.abs(c)) {
                a=c;
                var s=p / 4;
            }
            else var s=p / (2 * Math.PI) * Math.asin(c / a);
            if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t-=1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
            return a * Math.pow(2, -10 * (t-=1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
        },
        easeInBack: function (x, t, b, c, d, s) {
            if (s == undefined) s=1.70158;
            return c * (t/=d) * t * ((s + 1) * t - s) + b;
        },
        easeOutBack: function (x, t, b, c, d, s) {
            if (s == undefined) s=1.70158;
            return c * ((t=t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
        },
        easeInOutBack: function (x, t, b, c, d, s) {
            if (s == undefined) s=1.70158;
            if ((t/=d / 2) < 1) return c / 2 * (t * t * (((s*=(1.525)) + 1) * t - s)) + b;
            return c / 2 * ((t-=2) * t * (((s*=(1.525)) + 1) * t + s) + 2) + b;
        },
        easeInBounce: function (x, t, b, c, d) {
            return c - $.easing.easeOutBounce(x, d - t, 0, c, d) + b;
        },
        easeOutBounce: function (x, t, b, c, d) {
            if ((t/=d) < (1 / 2.75)) {
                return c * (7.5625 * t * t) + b;
            } else if (t < (2 / 2.75)) {
                return c * (7.5625 * (t-=(1.5 / 2.75)) * t + .75) + b;
            } else if (t < (2.5 / 2.75)) {
                return c * (7.5625 * (t-=(2.25 / 2.75)) * t + .9375) + b;
            } else {
                return c * (7.5625 * (t-=(2.625 / 2.75)) * t + .984375) + b;
            }
        },
        easeInOutBounce: function (x, t, b, c, d) {
            if (t < d / 2) return $.easing.easeInBounce(x, t * 2, 0, c, d) * .5 + b;
            return $.easing.easeOutBounce(x, t * 2 - d, 0, c, d) * .5 + c * .5 + b;
        }
    });

    /*
     *
     * TERMS OF USE - EASING EQUATIONS
     *
     * Open source under the BSD License.
     *
     * Copyright 2001 Robert Penner
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * Redistributions of source code must retain the above copyright notice, this list of
     * conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright notice, this list
     * of conditions and the following disclaimer in the documentation and/or other materials
     * provided with the distribution.
     *
     * Neither the name of the author nor the names of contributors may be used to endorse
     * or promote products derived from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
     * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     * OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */

})(jQuery);
/*
 * jQuery UI Accordion 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Accordion
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.accordion", {
        options: {
            active: 0,
            animated: 'slide',
            autoHeight: true,
            clearStyle: false,
            collapsible: false,
            event: "click",
            fillSpace: false,
            header: "> li > :first-child,> :not(li):even",
            icons: {
                header: "ui-icon-triangle-1-e",
                headerSelected: "ui-icon-triangle-1-s"
            },
            navigation: false,
            navigationFilter: function() {
                return this.href.toLowerCase() == location.href.toLowerCase();
            }
        },
        _create: function() {

            var o=this.options, self=this;
            this.running=0;

            this.element.addClass("ui-accordion ui-widget ui-helper-reset");

            // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix
            if (this.element[0].nodeName == "UL") {
                this.element.children("li").addClass("ui-accordion-li-fix");
            }

            this.headers=this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
                    .bind("mouseenter.accordion", function() {
                $(this).addClass('ui-state-hover');
            })
                    .bind("mouseleave.accordion", function() {
                $(this).removeClass('ui-state-hover');
            })
                    .bind("focus.accordion", function() {
                $(this).addClass('ui-state-focus');
            })
                    .bind("blur.accordion", function() {
                $(this).removeClass('ui-state-focus');
            });

            this.headers
                    .next()
                    .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");

            if (o.navigation) {
                var current=this.element.find("a").filter(o.navigationFilter);
                if (current.length) {
                    var header=current.closest(".ui-accordion-header");
                    if (header.length) {
                        // anchor within header
                        this.active=header;
                    } else {
                        // anchor within content
                        this.active=current.closest(".ui-accordion-content").prev();
                    }
                }
            }

            this.active=this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
            this.active.next().addClass('ui-accordion-content-active');

            //Append icon elements
            this._createIcons();

            // IE7-/Win - Extra vertical space in lists fixed
            if ($.browser.msie) {
                this.element.find('a').css('zoom', '1');
            }

            this.resize();

            //ARIA
            this.element.attr('role', 'tablist');

            this.headers
                    .attr('role', 'tab')
                    .bind('keydown', function(event) {
                return self._keydown(event);
            })
                    .next()
                    .attr('role', 'tabpanel');

            this.headers
                    .not(this.active || "")
                    .attr('aria-expanded', 'false')
                    .attr("tabIndex", "-1")
                    .next()
                    .hide();

            // make sure at least one header is in the tab order
            if (!this.active.length) {
                this.headers.eq(0).attr('tabIndex', '0');
            } else {
                this.active
                        .attr('aria-expanded', 'true')
                        .attr('tabIndex', '0');
            }

            // only need links in taborder for Safari
            if (!$.browser.safari)
                this.headers.find('a').attr('tabIndex', '-1');

            if (o.event) {
                this.headers.bind((o.event) + ".accordion", function(event) {
                    self._clickHandler.call(self, event, this);
                    event.preventDefault();
                });
            }

        },

        _createIcons: function() {
            var o=this.options;
            if (o.icons) {
                $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
                this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
                this.element.addClass("ui-accordion-icons");
            }
        },

        _destroyIcons: function() {
            this.headers.children(".ui-icon").remove();
            this.element.removeClass("ui-accordion-icons");
        },

        destroy: function() {
            var o=this.options;

            this.element
                    .removeClass("ui-accordion ui-widget ui-helper-reset")
                    .removeAttr("role")
                    .unbind('.accordion')
                    .removeData('accordion');

            this.headers
                    .unbind(".accordion")
                    .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
                    .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");

            this.headers.find("a").removeAttr("tabindex");
            this._destroyIcons();
            var contents=this.headers.next().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");
            if (o.autoHeight || o.fillHeight) {
                contents.css("height", "");
            }

            return this;
        },

        _setOption: function(key, value) {
            $.Widget.prototype._setOption.apply(this, arguments);

            if (key == "active") {
                this.activate(value);
            }
            if (key == "icons") {
                this._destroyIcons();
                if (value) {
                    this._createIcons();
                }
            }

        },

        _keydown: function(event) {

            var o=this.options, keyCode=$.ui.keyCode;

            if (o.disabled || event.altKey || event.ctrlKey)
                return;

            var length=this.headers.length;
            var currentIndex=this.headers.index(event.target);
            var toFocus=false;

            switch (event.keyCode) {
                case keyCode.RIGHT:
                case keyCode.DOWN:
                    toFocus=this.headers[(currentIndex + 1) % length];
                    break;
                case keyCode.LEFT:
                case keyCode.UP:
                    toFocus=this.headers[(currentIndex - 1 + length) % length];
                    break;
                case keyCode.SPACE:
                case keyCode.ENTER:
                    this._clickHandler({ target: event.target }, event.target);
                    event.preventDefault();
            }

            if (toFocus) {
                $(event.target).attr('tabIndex', '-1');
                $(toFocus).attr('tabIndex', '0');
                toFocus.focus();
                return false;
            }

            return true;

        },

        resize: function() {

            var o=this.options, maxHeight;

            if (o.fillSpace) {

                if ($.browser.msie) {
                    var defOverflow=this.element.parent().css('overflow');
                    this.element.parent().css('overflow', 'hidden');
                }
                maxHeight=this.element.parent().height();
                if ($.browser.msie) {
                    this.element.parent().css('overflow', defOverflow);
                }

                this.headers.each(function() {
                    maxHeight-=$(this).outerHeight(true);
                });

                this.headers.next().each(function() {
                    $(this).height(Math.max(0, maxHeight - $(this).innerHeight() + $(this).height()));
                }).css('overflow', 'auto');

            } else if (o.autoHeight) {
                maxHeight=0;
                this.headers.next().each(function() {
                    maxHeight=Math.max(maxHeight, $(this).height());
                }).height(maxHeight);
            }

            return this;
        },

        activate: function(index) {
            // TODO this gets called on init, changing the option without an explicit call for that
            this.options.active=index;
            // call clickHandler with custom event
            var active=this._findActive(index)[0];
            this._clickHandler({ target: active }, active);

            return this;
        },

        _findActive: function(selector) {
            return selector
                    ? typeof selector == "number"
                    ? this.headers.filter(":eq(" + selector + ")")
                    : this.headers.not(this.headers.not(selector))
                    : selector === false
                    ? $([])
                    : this.headers.filter(":eq(0)");
        },

        // TODO isn't event.target enough? why the seperate target argument?
        _clickHandler: function(event, target) {

            var o=this.options;
            if (o.disabled)
                return;

            // called only when using activate(false) to close all parts programmatically
            if (!event.target) {
                if (!o.collapsible)
                    return;
                this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
                        .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
                this.active.next().addClass('ui-accordion-content-active');
                var toHide=this.active.next(),
                        data={
                            options: o,
                            newHeader: $([]),
                            oldHeader: o.active,
                            newContent: $([]),
                            oldContent: toHide
                        },
                        toShow=(this.active=$([]));
                this._toggle(toShow, toHide, data);
                return;
            }

            // get the click target
            var clicked=$(event.currentTarget || target);
            var clickedIsActive=clicked[0] == this.active[0];

            // TODO the option is changed, is that correct?
            // TODO if it is correct, shouldn't that happen after determining that the click is valid?
            o.active=o.collapsible && clickedIsActive ? false : $('.ui-accordion-header', this.element).index(clicked);

            // if animations are still active, or the active header is the target, ignore click
            if (this.running || (!o.collapsible && clickedIsActive)) {
                return;
            }

            // switch classes
            this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
                    .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
            if (!clickedIsActive) {
                clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
                        .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
                clicked.next().addClass('ui-accordion-content-active');
            }

            // find elements to show and hide
            var toShow=clicked.next(),
                    toHide=this.active.next(),
                    data={
                        options: o,
                        newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
                        oldHeader: this.active,
                        newContent: clickedIsActive && o.collapsible ? $([]) : toShow.find('> *'),
                        oldContent: toHide.find('> *')
                    },
                    down=this.headers.index(this.active[0]) > this.headers.index(clicked[0]);

            this.active=clickedIsActive ? $([]) : clicked;
            this._toggle(toShow, toHide, data, clickedIsActive, down);

            return;

        },

        _toggle: function(toShow, toHide, data, clickedIsActive, down) {

            var o=this.options, self=this;

            this.toShow=toShow;
            this.toHide=toHide;
            this.data=data;

            var complete=function() {
                if (!self) return;
                return self._completed.apply(self, arguments);
            };

            // trigger changestart event
            this._trigger("changestart", null, this.data);

            // count elements to animate
            this.running=toHide.size() === 0 ? toShow.size() : toHide.size();

            if (o.animated) {

                var animOptions={};

                if (o.collapsible && clickedIsActive) {
                    animOptions={
                        toShow: $([]),
                        toHide: toHide,
                        complete: complete,
                        down: down,
                        autoHeight: o.autoHeight || o.fillSpace
                    };
                } else {
                    animOptions={
                        toShow: toShow,
                        toHide: toHide,
                        complete: complete,
                        down: down,
                        autoHeight: o.autoHeight || o.fillSpace
                    };
                }

                if (!o.proxied) {
                    o.proxied=o.animated;
                }

                if (!o.proxiedDuration) {
                    o.proxiedDuration=o.duration;
                }

                o.animated=$.isFunction(o.proxied) ?
                           o.proxied(animOptions) : o.proxied;

                o.duration=$.isFunction(o.proxiedDuration) ?
                           o.proxiedDuration(animOptions) : o.proxiedDuration;

                var animations=$.ui.accordion.animations,
                        duration=o.duration,
                        easing=o.animated;

                if (easing && !animations[easing] && !$.easing[easing]) {
                    easing='slide';
                }
                if (!animations[easing]) {
                    animations[easing]=function(options) {
                        this.slide(options, {
                            easing: easing,
                            duration: duration || 700
                        });
                    };
                }

                animations[easing](animOptions);

            } else {

                if (o.collapsible && clickedIsActive) {
                    toShow.toggle();
                } else {
                    toHide.hide();
                    toShow.show();
                }

                complete(true);

            }

            // TODO assert that the blur and focus triggers are really necessary, remove otherwise
            toHide.prev().attr('aria-expanded', 'false').attr("tabIndex", "-1").blur();
            toShow.prev().attr('aria-expanded', 'true').attr("tabIndex", "0").focus();

        },

        _completed: function(cancel) {

            var o=this.options;

            this.running=cancel ? 0 : --this.running;
            if (this.running) return;

            if (o.clearStyle) {
                this.toShow.add(this.toHide).css({
                    height: "",
                    overflow: ""
                });
            }

            // other classes are removed before the animation; this one needs to stay until completed
            this.toHide.removeClass("ui-accordion-content-active");

            this._trigger('change', null, this.data);
        }

    });


    $.extend($.ui.accordion, {
        version: "1.8rc1",
        animations: {
            slide: function(options, additions) {
                options=$.extend({
                    easing: "swing",
                    duration: 300
                }, options, additions);
                if (!options.toHide.size()) {
                    options.toShow.animate({height: "show"}, options);
                    return;
                }
                if (!options.toShow.size()) {
                    options.toHide.animate({height: "hide"}, options);
                    return;
                }
                var overflow=options.toShow.css('overflow'),
                        percentDone=0,
                        showProps={},
                        hideProps={},
                        fxAttrs=[ "height", "paddingTop", "paddingBottom" ],
                        originalWidth;
                // fix width before calculating height of hidden element
                var s=options.toShow;
                originalWidth=s[0].style.width;
                s.width(parseInt(s.parent().width(), 10) - parseInt(s.css("paddingLeft"), 10) - parseInt(s.css("paddingRight"), 10) - (parseInt(s.css("borderLeftWidth"), 10) || 0) - (parseInt(s.css("borderRightWidth"), 10) || 0));

                $.each(fxAttrs, function(i, prop) {
                    hideProps[prop]='hide';

                    var parts=('' + $.css(options.toShow[0], prop)).match(/^([\d+-.]+)(.*)$/);
                    showProps[prop]={
                        value: parts[1],
                        unit: parts[2] || 'px'
                    };
                });
                options.toShow.css({ height: 0, overflow: 'hidden' }).show();
                options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps, {
                    step: function(now, settings) {
                        // only calculate the percent when animating height
                        // IE gets very inconsistent results when animating elements
                        // with small values, which is common for padding
                        if (settings.prop == 'height') {
                            percentDone=( settings.end - settings.start === 0 ) ? 0 :
                                        (settings.now - settings.start) / (settings.end - settings.start);
                        }

                        options.toShow[0].style[settings.prop]=
                        (percentDone * showProps[settings.prop].value) + showProps[settings.prop].unit;
                    },
                    duration: options.duration,
                    easing: options.easing,
                    complete: function() {
                        if (!options.autoHeight) {
                            options.toShow.css("height", "");
                        }
                        options.toShow.css("width", originalWidth);
                        options.toShow.css({overflow: overflow});
                        options.complete();
                    }
                });
            },
            bounceslide: function(options) {
                this.slide(options, {
                    easing: options.down ? "easeOutBounce" : "swing",
                    duration: options.down ? 1000 : 200
                });
            }
        }
    });

})(jQuery);
/*
 * jQuery UI Autocomplete 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Autocomplete
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.autocomplete", {
        options: {
            minLength: 1,
            delay: 300
        },
        _create: function() {
            var self=this;
            this.element
                    .addClass("ui-autocomplete")
                    .attr("autocomplete", "off")
                // TODO verify these actually work as intended
                    .attr({
                role: "textbox",
                "aria-autocomplete": "list",
                "aria-haspopup": "true"
            })
                    .bind("keydown.autocomplete", function(event) {
                var keyCode=$.ui.keyCode;
                switch (event.keyCode) {
                    case keyCode.PAGE_UP:
                        self._move("previousPage", event);
                        break;
                    case keyCode.PAGE_DOWN:
                        self._move("nextPage", event);
                        break;
                    case keyCode.UP:
                        self._move("previous", event);
                        // prevent moving cursor to beginning of text field in some browsers
                        event.preventDefault();
                        break;
                    case keyCode.DOWN:
                        self._move("next", event);
                        // prevent moving cursor to end of text field in some browsers
                        event.preventDefault();
                        break;
                    case keyCode.ENTER:
                        // when menu is open or has focus
                        if (self.menu && self.menu.active) {
                            event.preventDefault();
                        }
                    case keyCode.TAB:
                        if (!self.menu || !self.menu.active) {
                            return;
                        }
                        self.menu.select();
                        break;
                    case keyCode.ESCAPE:
                        self.element.val(self.term);
                        self.close(event);
                        break;
                    case 16:
                    case 17:
                    case 18:
                        // ignore metakeys (shift, ctrl, alt)
                        break;
                    default:
                        // keypress is triggered before the input value is changed
                        clearTimeout(self.searching);
                        self.searching=setTimeout(function() {
                            self.search(null, event);
                        }, self.options.delay);
                        break;
                }
            })
                    .bind("focus.autocomplete", function() {
                self.previous=self.element.val();
            })
                    .bind("blur.autocomplete", function(event) {
                clearTimeout(self.searching);
                // clicks on the menu (or a button to trigger a search) will cause a blur event
                // TODO try to implement this without a timeout, see clearTimeout in search()
                self.closing=setTimeout(function() {
                    self.close(event);
                }, 150);
            });
            this._initSource();
            this.response=function() {
                return self._response.apply(self, arguments);
            };
        },

        destroy: function() {
            this.element
                    .removeClass("ui-autocomplete ui-widget ui-widget-content ui-corner-all")
                    .removeAttr("autocomplete")
                    .removeAttr("role")
                    .removeAttr("aria-autocomplete")
                    .removeAttr("aria-haspopup");
            if (this.menu) {
                this.menu.element.remove();
            }
            $.Widget.prototype.destroy.call(this);
        },

        _setOption: function(key) {
            $.Widget.prototype._setOption.apply(this, arguments);
            if (key == "source") {
                this._initSource();
            }
        },

        _initSource: function() {
            if ($.isArray(this.options.source)) {
                var array=this.options.source;
                this.source=function(request, response) {
                    // escape regex characters
                    var matcher=new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
                    response($.grep(array, function(value) {
                        return matcher.test(value.value || value.label || value);
                    }));
                };
            } else if (typeof this.options.source == "string") {
                var url=this.options.source;
                this.source=function(request, response) {
                    $.getJSON(url, request, response);
                };
            } else {
                this.source=this.options.source;
            }
        },

        search: function(value, event) {
            value=value != null ? value : this.element.val();
            if (value.length < this.options.minLength) {
                return this.close(event);
            }

            clearTimeout(this.closing);
            if (this._trigger("search") === false) {
                return;
            }

            return this._search(value);
        },

        _search: function(value) {
            this.term=this.element
                    .addClass("ui-autocomplete-loading")
                // always save the actual value, not the one passed as an argument
                    .val();

            this.source({ term: value }, this.response);
        },

        _response: function(content) {
            if (content.length) {
                content=this._normalize(content);
                this._trigger("open");
                this._suggest(content);
            } else {
                this.close();
            }
            this.element.removeClass("ui-autocomplete-loading");
        },

        close: function(event) {
            clearTimeout(this.closing);
            if (this.menu) {
                this._trigger("close", event);
                this.menu.element.remove();
                this.menu=null;
            }
            if (this.previous != this.element.val()) {
                this._trigger("change", event);
            }
        },

        _normalize: function(items) {
            // assume all items have the right format when the first item is complete
            if (items.length && items[0].label && items[0].value) {
                return items;
            }
            return $.map(items, function(item) {
                if (typeof item == "string") {
                    return {
                        label: item,
                        value: item
                    };
                }
                return $.extend({
                    label: item.label || item.value,
                    value: item.value || item.label
                }, item);
            });
        },

        _suggest: function(items) {
            if (this.menu) {
                this.menu.element.remove();
            }
            var self=this,
                    ul=$("<ul></ul>"),
                    parent=this.element.parent();

            $.each(items, function(index, item) {
                $("<li></li>")
                        .data("item.autocomplete", item)
                        .append("<a>" + item.label + "</a>")
                        .appendTo(ul);
            });
            this.menu=ul
                    .addClass("ui-autocomplete-menu")
                    .appendTo(parent)
                    .menu({
                focus: function(event, ui) {
                    var item=ui.item.data("item.autocomplete");
                    if (false !== self._trigger("focus", null, { item: item })) {
                        // use value to match what will end up in the input
                        self.element.val(item.value);
                    }
                },
                selected: function(event, ui) {
                    var item=ui.item.data("item.autocomplete");
                    if (false !== self._trigger("select", event, { item: item })) {
                        self.element.val(item.value);
                    }
                    self.close(event);
                    self.previous=self.element.val();
                    // only trigger when focus was lost (click on menu)
                    if (self.element[0] != document.activeElement) {
                        self.element.focus();
                    }
                }
            })
                    .zIndex(this.element.zIndex() + 1)
                // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
                    .css({ top: 0, left: 0 })
                    .position({
                my: "left top",
                at: "left bottom",
                of: this.element
            })
                    .data("menu");
            if (ul.width() <= this.element.width()) {
                ul.width(this.element.width());
            }
            if ($.fn.bgiframe) {
                ul.bgiframe();
            }
        },

        _move: function(direction, event) {
            if (!this.menu) {
                this.search(null, event);
                return;
            }
            if (this.menu.first() && /^previous/.test(direction) ||
                this.menu.last() && /^next/.test(direction)) {
                this.element.val(this.term);
                this.menu.deactivate();
                return;
            }
            this.menu[ direction ]();
        },

        widget: function() {
            // return empty jQuery object when menu isn't initialized yet
            return this.menu ? this.menu.element : $([]);
        }
    });

    $.extend($.ui.autocomplete, {
        escapeRegex: function(value) {
            return value.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1");
        }
    });

})(jQuery);

/*
 * jQuery UI Menu (not officially released)
 * 
 * This widget isn't yet finished and the API is subject to change. We plan to finish
 * it for the next release. You're welcome to give it a try anyway and give us feedback,
 * as long as you're okay with migrating your code later on. We can help with that, too.
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Menu
 *
 * Depends:
 *	jquery.ui.core.js
 *  jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.menu", {
        _create: function() {
            var self=this;
            this.element
                    .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
                    .attr({
                role: "menu",
                "aria-activedescendant": "ui-active-menuitem"
            })
                    .click(function(e) {
                // temporary
                e.preventDefault();
                self.select();
            });
            var items=this.element.children("li")
                    .addClass("ui-menu-item")
                    .attr("role", "menuitem");

            items.children("a")
                    .addClass("ui-corner-all")
                    .attr("tabindex", -1)
                // mouseenter doesn't work with event delegation
                    .mouseenter(function() {
                self.activate($(this).parent());
            });
        },

        activate: function(item) {
            this.deactivate();
            this.active=item.eq(0)
                    .children("a")
                    .addClass("ui-state-hover")
                    .attr("id", "ui-active-menuitem")
                    .end();
            this._trigger("focus", null, { item: item });
            if (this.hasScroll()) {
                var offset=item.offset().top - this.element.offset().top,
                        scroll=this.element.attr("scrollTop"),
                        elementHeight=this.element.height();
                if (offset < 0) {
                    this.element.attr("scrollTop", scroll + offset);
                } else if (offset > elementHeight) {
                    this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
                }
            }
        },

        deactivate: function() {
            if (!this.active) {
                return;
            }

            this.active.children("a")
                    .removeClass("ui-state-hover")
                    .removeAttr("id");
            this.active=null;
        },

        next: function() {
            this.move("next", "li:first");
        },

        previous: function() {
            this.move("prev", "li:last");
        },

        first: function() {
            return this.active && !this.active.prev().length;
        },

        last: function() {
            return this.active && !this.active.next().length;
        },

        move: function(direction, edge) {
            if (!this.active) {
                this.activate(this.element.children(edge));
                return;
            }
            var next=this.active[direction]();
            if (next.length) {
                this.activate(next);
            } else {
                this.activate(this.element.children(edge));
            }
        },

        // TODO merge with previousPage
        nextPage: function() {
            if (this.hasScroll()) {
                // TODO merge with no-scroll-else
                if (!this.active || this.last()) {
                    this.activate(this.element.children(":first"));
                    return;
                }
                var base=this.active.offset().top,
                        height=this.element.height(),
                        result=this.element.children("li").filter(function() {
                            var close=$(this).offset().top - base - height + $(this).height();
                            // TODO improve approximation
                            return close < 10 && close > -10;
                        });

                // TODO try to catch this earlier when scrollTop indicates the last page anyway
                if (!result.length) {
                    result=this.element.children(":last");
                }
                this.activate(result);
            } else {
                this.activate(this.element.children(!this.active || this.last() ? ":first" : ":last"));
            }
        },

        // TODO merge with nextPage
        previousPage: function() {
            if (this.hasScroll()) {
                // TODO merge with no-scroll-else
                if (!this.active || this.first()) {
                    this.activate(this.element.children(":last"));
                    return;
                }

                var base=this.active.offset().top,
                        height=this.element.height();
                result=this.element.children("li").filter(function() {
                    var close=$(this).offset().top - base + height - $(this).height();
                    // TODO improve approximation
                    return close < 10 && close > -10;
                });

                // TODO try to catch this earlier when scrollTop indicates the last page anyway
                if (!result.length) {
                    result=this.element.children(":first");
                }
                this.activate(result);
            } else {
                this.activate(this.element.children(!this.active || this.first() ? ":last" : ":first"));
            }
        },

        hasScroll: function() {
            return this.element.height() < this.element.attr("scrollHeight");
        },

        select: function() {
            this._trigger("selected", null, { item: this.active });
        }
    });

})(jQuery);
/*
 * jQuery UI Button 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Button
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function($) {

    var lastActive,
            baseClasses="ui-button ui-widget ui-state-default ui-corner-all",
            otherClasses="ui-state-hover ui-state-active " +
                         "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only";

    $.widget("ui.button", {
        options: {
            text: true,
            label: null,
            icons: {
                primary: null,
                secondary: null
            }
        },
        _create: function() {
            this._determineButtonType();
            this.hasTitle=!!this.buttonElement.attr("title");

            var self=this,
                    options=this.options,
                    toggleButton=this.type === "checkbox" || this.type === "radio",
                    hoverClass="ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
                    focusClass="ui-state-focus";

            if (options.label === null) {
                options.label=this.buttonElement.html();
            }

            this.buttonElement
                    .addClass(baseClasses)
                    .attr("role", "button")
                    .bind("mouseenter.button", function() {
                if (options.disabled) {
                    return;
                }
                $(this).addClass("ui-state-hover");
                if (this === lastActive) {
                    $(this).addClass("ui-state-active");
                }
            })
                    .bind("mouseleave.button", function() {
                if (options.disabled) {
                    return;
                }
                $(this).removeClass(hoverClass);
            })
                    .bind("focus.button", function() {
                // no need to check disabled, focus won't be triggered anyway
                $(this).addClass(focusClass);
            })
                    .bind("blur.button", function() {
                $(this).removeClass(focusClass);
            });

            if (this.type === "checkbox") {
                this.buttonElement.bind("click.button", function() {
                    if (options.disabled) {
                        return;
                    }
                    $(this).toggleClass("ui-state-active");
                    self.element
                            .attr("checked", !self.element[0].checked)
                            .click();
                    self.buttonElement.attr("aria-pressed", self.element[0].checked);
                });
            } else if (this.type === "radio") {
                this.buttonElement.bind("click.button", function() {
                    if (options.disabled) {
                        return;
                    }
                    $(this).addClass("ui-state-active");
                    self.element
                            .attr("checked", true)
                            .click();
                    self.buttonElement.attr("aria-pressed", true);

                    var radio=self.element[ 0 ],
                            name=radio.name,
                            form=radio.form,
                            radios;
                    if (name) {
                        if (form) {
                            radios=$(form).find("[name=" + name + "]");
                        } else {
                            radios=$("[name=" + name + "]", radio.ownerDocument)
                                    .filter(function() {
                                return !this.form;
                            });
                        }
                        radios
                                .not(radio)
                                .map(function() {
                            return $(this).button("widget")[ 0 ];
                        })
                                .removeClass("ui-state-active")
                                .attr("aria-pressed", false);
                    }
                });
            } else {
                this.buttonElement
                        .bind("mousedown.button", function() {
                    if (options.disabled) {
                        return;
                    }
                    $(this).addClass("ui-state-active");
                    lastActive=this;
                    $(document).one("mouseup", function() {
                        lastActive=null;
                    });
                })
                        .bind("mouseup.button", function() {
                    if (options.disabled) {
                        return;
                    }
                    $(this).removeClass("ui-state-active");
                })
                        .bind("keydown.button", function(event) {
                    if (event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER) {
                        $(this).addClass("ui-state-active");
                    }
                })
                        .bind("keyup.button", function() {
                    $(this).removeClass("ui-state-active");
                });
                if (this.buttonElement.is("a")) {
                    this.buttonElement.keyup(function(event) {
                        if (event.keyCode == $.ui.keyCode.SPACE) {
                            // TODO pass through original event correctly (just as 2nd argument doesn't work)
                            $(this).trigger("click");
                        }
                    })
                }
            }

            this._resetButton();
        },

        _determineButtonType: function() {
            this.type=this.element.is(":checkbox")
                    ? "checkbox"
                    : this.element.is(":radio")
                    ? "radio"
                    : this.element.is("input")
                    ? "input"
                    : "button";

            if (this.type === "checkbox" || this.type === "radio") {
                this.buttonElement=$("[for=" + this.element.attr("id") + "]");
                this.element.hide();

                var checked=this.element.is(":checked");
                if (checked) {
                    this.buttonElement.addClass("ui-state-active");
                }
                this.buttonElement.attr("aria-pressed", checked)
            } else {
                this.buttonElement=this.element;
            }
        },

        widget: function() {
            return this.buttonElement;
        },

        destroy: function() {
            this.buttonElement
                    .removeClass(baseClasses + " " + otherClasses)
                    .removeAttr("role")
                    .removeAttr("aria-pressed")
                    .html(this.buttonElement.find(".ui-button-text").html());

            if (!this.hasTitle) {
                this.buttonElement.removeAttr("title");
            }

            if (this.type === "checkbox" || this.type === "radio") {
                this.element.show();
            }

            $.Widget.prototype.destroy.call(this);
        },

        _setOption: function(key, value) {
            $.Widget.prototype._setOption.apply(this, arguments);
            this._resetButton();
        },

        _resetButton: function() {
            if (this.type === "input") {
                if (this.options.label) {
                    this.element.val(this.options.label);
                }
                return;
            }
            var buttonElement=this.buttonElement,
                    buttonText=$("<span></span>")
                            .addClass("ui-button-text")
                            .html(this.options.label)
                            .appendTo(buttonElement.empty())
                            .text();

            var icons=this.options.icons,
                    multipleIcons=icons.primary && icons.secondary;
            if (icons.primary || icons.secondary) {
                buttonElement.addClass("ui-button-text-icon" +
                                       ( multipleIcons ? "s" : "" ));
                if (icons.primary) {
                    buttonElement.prepend("<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>");
                }
                if (icons.secondary) {
                    buttonElement.append("<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>");
                }
                if (!this.options.text) {
                    buttonElement
                            .addClass(multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only")
                            .removeClass("ui-button-text-icons ui-button-text-icon");
                    if (!this.hasTitle) {
                        buttonElement.attr("title", buttonText);
                    }
                }
            } else {
                buttonElement.addClass("ui-button-text-only");
            }
        }
    });

    $.widget("ui.buttonset", {
        _create: function() {
            this.element.addClass("ui-button-set");
            this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, .ui-button")
                    .button()
                    .map(function() {
                return $(this).button("widget")[ 0 ];
            })
                    .removeClass("ui-corner-all")
                    .filter(":first")
                    .addClass("ui-corner-left")
                    .end()
                    .filter(":last")
                    .addClass("ui-corner-right")
                    .end()
                    .end();
        },

        _setOption: function(key, value) {
            if (key === "disabled") {
                this.buttons.button("option", key, value);
            }

            $.Widget.prototype._setOption.apply(this, arguments);
        },

        destroy: function() {
            this.element.removeClass("ui-button-set");
            this.buttons
                    .button("destroy")
                    .removeClass("ui-corner-left ui-corner-right");

            $.Widget.prototype.destroy.call(this);
        }
    });


})(jQuery);
/*
 * jQuery UI Datepicker 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Datepicker
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */

(function($) { // hide the namespace

    $.extend($.ui, { datepicker: { version: "1.8rc1" } });

    var PROP_NAME='datepicker';
    var dpuuid=new Date().getTime();

    /* Date picker manager.
     Use the singleton instance of this class, $.datepicker, to interact with the date picker.
     Settings for (groups of) date pickers are maintained in an instance object,
     allowing multiple different settings on the same page. */

    function Datepicker() {
        this.debug=false; // Change this to true to start debugging
        this._curInst=null; // The current instance in use
        this._keyEvent=false; // If the last event was a key event
        this._disabledInputs=[]; // List of date picker inputs that have been disabled
        this._datepickerShowing=false; // True if the popup picker is showing , false if not
        this._inDialog=false; // True if showing within a "dialog", false if not
        this._mainDivId='ui-datepicker-div'; // The ID of the main datepicker division
        this._inlineClass='ui-datepicker-inline'; // The name of the inline marker class
        this._appendClass='ui-datepicker-append'; // The name of the append marker class
        this._triggerClass='ui-datepicker-trigger'; // The name of the trigger marker class
        this._dialogClass='ui-datepicker-dialog'; // The name of the dialog marker class
        this._disableClass='ui-datepicker-disabled'; // The name of the disabled covering marker class
        this._unselectableClass='ui-datepicker-unselectable'; // The name of the unselectable cell marker class
        this._currentClass='ui-datepicker-current-day'; // The name of the current day marker class
        this._dayOverClass='ui-datepicker-days-cell-over'; // The name of the day hover marker class
        this.regional=[]; // Available regional settings, indexed by language code
        this.regional['']={ // Default regional settings
            closeText: 'Done', // Display text for close link
            prevText: 'Prev', // Display text for previous month link
            nextText: 'Next', // Display text for next month link
            currentText: 'Today', // Display text for current month link
            monthNames: ['January','February','March','April','May','June',
                'July','August','September','October','November','December'], // Names of months for drop-down and formatting
            monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
            dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
            dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
            dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
            weekHeader: 'Wk', // Column header for week of the year
            dateFormat: 'mm/dd/yy', // See format options on parseDate
            firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
            isRTL: false, // True if right-to-left language, false if left-to-right
            showMonthAfterYear: false, // True if the year select precedes month, false for month then year
            yearSuffix: '' // Additional text to append to the year in the month headers
        };
        this._defaults={ // Global defaults for all the date picker instances
            showOn: 'focus', // 'focus' for popup on focus,
            // 'button' for trigger button, or 'both' for either
            showAnim: 'show', // Name of jQuery animation for popup
            showOptions: {}, // Options for enhanced animations
            defaultDate: null, // Used when field is blank: actual date,
            // +/-number for offset from today, null for today
            appendText: '', // Display text following the input box, e.g. showing the format
            buttonText: '...', // Text for trigger button
            buttonImage: '', // URL for trigger button image
            buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
            hideIfNoPrevNext: false, // True to hide next/previous month links
            // if not applicable, false to just disable them
            navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
            gotoCurrent: false, // True if today link goes back to current selection instead
            changeMonth: false, // True if month can be selected directly, false if only prev/next
            changeYear: false, // True if year can be selected directly, false if only prev/next
            yearRange: 'c-10:c+10', // Range of years to display in drop-down,
            // either relative to today's year (-nn:+nn), relative to currently displayed year
            // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
            showOtherMonths: false, // True to show dates in other months, false to leave blank
            selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
            showWeek: false, // True to show week of the year, false to not show it
            calculateWeek: this.iso8601Week, // How to calculate the week of the year,
            // takes a Date and returns the number of the week for it
            shortYearCutoff: '+10', // Short year values < this are in the current century,
            // > this are in the previous century,
            // string value starting with '+' for current year + value
            minDate: null, // The earliest selectable date, or null for no limit
            maxDate: null, // The latest selectable date, or null for no limit
            duration: '_default', // Duration of display/closure
            beforeShowDay: null, // Function that takes a date and returns an array with
            // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
            // [2] = cell title (optional), e.g. $.datepicker.noWeekends
            beforeShow: null, // Function that takes an input field and
            // returns a set of custom settings for the date picker
            onSelect: null, // Define a callback function when a date is selected
            onChangeMonthYear: null, // Define a callback function when the month or year is changed
            onClose: null, // Define a callback function when the datepicker is closed
            numberOfMonths: 1, // Number of months to show at a time
            showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
            stepMonths: 1, // Number of months to step back/forward
            stepBigMonths: 12, // Number of months to step back/forward for the big links
            altField: '', // Selector for an alternate field to store selected dates into
            altFormat: '', // The date format to use for the alternate field
            constrainInput: true, // The input is constrained by the current date format
            showButtonPanel: false, // True to show button panel, false to not show it
            autoSize: false // True to size the input for the date format, false to leave as is
        };
        $.extend(this._defaults, this.regional['']);
        this.dpDiv=$('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
    }

    $.extend(Datepicker.prototype, {
        /* Class name added to elements to indicate already configured with a date picker. */
        markerClassName: 'hasDatepicker',

        /* Debug logging (if enabled). */
        log: function () {
            if (this.debug)
                console.log.apply('', arguments);
        },

        // TODO rename to "widget" when switching to widget factory
        _widgetDatepicker: function() {
            return this.dpDiv;
        },

        /* Override the default settings for all instances of the date picker.
         @param  settings  object - the new settings to use as defaults (anonymous object)
         @return the manager object */
        setDefaults: function(settings) {
            extendRemove(this._defaults, settings || {});
            return this;
        },

        /* Attach the date picker to a jQuery selection.
         @param  target    element - the target input field or division or span
         @param  settings  object - the new settings to use for this date picker instance (anonymous) */
        _attachDatepicker: function(target, settings) {
            // check for settings on the control itself - in namespace 'date:'
            var inlineSettings=null;
            for (var attrName in this._defaults) {
                var attrValue=target.getAttribute('date:' + attrName);
                if (attrValue) {
                    inlineSettings=inlineSettings || {};
                    try {
                        inlineSettings[attrName]=eval(attrValue);
                    } catch (err) {
                        inlineSettings[attrName]=attrValue;
                    }
                }
            }
            var nodeName=target.nodeName.toLowerCase();
            var inline=(nodeName == 'div' || nodeName == 'span');
            if (!target.id)
                target.id='dp' + (++this.uuid);
            var inst=this._newInst($(target), inline);
            inst.settings=$.extend({}, settings || {}, inlineSettings || {});
            if (nodeName == 'input') {
                this._connectDatepicker(target, inst);
            } else if (inline) {
                this._inlineDatepicker(target, inst);
            }
        },

        /* Create a new instance object. */
        _newInst: function(target, inline) {
            var id=target[0].id.replace(/([^A-Za-z0-9_])/g, '\\\\$1'); // escape jQuery meta chars
            return {id: id, input: target, // associated target
                selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
                drawMonth: 0, drawYear: 0, // month being drawn
                inline: inline, // is datepicker inline or not
                dpDiv: (!inline ? this.dpDiv : // presentation div
                        $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
        },

        /* Attach the date picker to an input field. */
        _connectDatepicker: function(target, inst) {
            var input=$(target);
            inst.append=$([]);
            inst.trigger=$([]);
            if (input.hasClass(this.markerClassName))
                return;
            this._attachments(input, inst);
            input.addClass(this.markerClassName).keydown(this._doKeyDown).
                    keypress(this._doKeyPress).keyup(this._doKeyUp).
                    bind("setData.datepicker", function(event, key, value) {
                inst.settings[key]=value;
            }).bind("getData.datepicker", function(event, key) {
                return this._get(inst, key);
            });
            this._autoSize(inst);
            $.data(target, PROP_NAME, inst);
        },

        /* Make attachments based on settings. */
        _attachments: function(input, inst) {
            var appendText=this._get(inst, 'appendText');
            var isRTL=this._get(inst, 'isRTL');
            if (inst.append)
                inst.append.remove();
            if (appendText) {
                inst.append=$('<span class="' + this._appendClass + '">' + appendText + '</span>');
                input[isRTL ? 'before' : 'after'](inst.append);
            }
            input.unbind('focus', this._showDatepicker);
            if (inst.trigger)
                inst.trigger.remove();
            var showOn=this._get(inst, 'showOn');
            if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
                input.focus(this._showDatepicker);
            if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
                var buttonText=this._get(inst, 'buttonText');
                var buttonImage=this._get(inst, 'buttonImage');
                inst.trigger=$(this._get(inst, 'buttonImageOnly') ?
                               $('<img/>').addClass(this._triggerClass).
                                       attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
                               $('<button type="button"></button>').addClass(this._triggerClass).
                                       html(buttonImage == '' ? buttonText : $('<img/>').attr(
                               { src:buttonImage, alt:buttonText, title:buttonText })));
                input[isRTL ? 'before' : 'after'](inst.trigger);
                inst.trigger.click(function() {
                    if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
                        $.datepicker._hideDatepicker();
                    else
                        $.datepicker._showDatepicker(input[0]);
                    return false;
                });
            }
        },

        /* Apply the maximum length for the date format. */
        _autoSize: function(inst) {
            if (this._get(inst, 'autoSize') && !inst.inline) {
                var date=new Date(2009, 12 - 1, 20); // Ensure double digits
                var dateFormat=this._get(inst, 'dateFormat');
                if (dateFormat.match(/[DM]/)) {
                    var findMax=function(names) {
                        var max=0;
                        var maxI=0;
                        for (var i=0; i < names.length; i++) {
                            if (names[i].length > max) {
                                max=names[i].length;
                                maxI=i;
                            }
                        }
                        return maxI;
                    };
                    date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
                                                           'monthNames' : 'monthNamesShort'))));
                    date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
                                                          'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
                }
                inst.input.attr('size', this._formatDate(inst, date).length);
            }
        },

        /* Attach an inline date picker to a div. */
        _inlineDatepicker: function(target, inst) {
            var divSpan=$(target);
            if (divSpan.hasClass(this.markerClassName))
                return;
            divSpan.addClass(this.markerClassName).append(inst.dpDiv).
                    bind("setData.datepicker", function(event, key, value) {
                inst.settings[key]=value;
            }).bind("getData.datepicker", function(event, key) {
                return this._get(inst, key);
            });
            $.data(target, PROP_NAME, inst);
            this._setDate(inst, this._getDefaultDate(inst), true);
            this._updateDatepicker(inst);
            this._updateAlternate(inst);
        },

        /* Pop-up the date picker in a "dialog" box.
         @param  input     element - ignored
         @param  date      string or Date - the initial date to display
         @param  onSelect  function - the function to call when a date is selected
         @param  settings  object - update the dialog date picker instance's settings (anonymous object)
         @param  pos       int[2] - coordinates for the dialog's position within the screen or
         event - with x/y coordinates or
         leave empty for default (screen centre)
         @return the manager object */
        _dialogDatepicker: function(input, date, onSelect, settings, pos) {
            var inst=this._dialogInst; // internal instance
            if (!inst) {
                var id='dp' + (++this.uuid);
                this._dialogInput=$('<input type="text" id="' + id +
                                    '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
                this._dialogInput.keydown(this._doKeyDown);
                $('body').append(this._dialogInput);
                inst=this._dialogInst=this._newInst(this._dialogInput, false);
                inst.settings={};
                $.data(this._dialogInput[0], PROP_NAME, inst);
            }
            extendRemove(inst.settings, settings || {});
            date=(date && date.constructor == Date ? this._formatDate(inst, date) : date);
            this._dialogInput.val(date);

            this._pos=(pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
            if (!this._pos) {
                var browserWidth=document.documentElement.clientWidth;
                var browserHeight=document.documentElement.clientHeight;
                var scrollX=document.documentElement.scrollLeft || document.body.scrollLeft;
                var scrollY=document.documentElement.scrollTop || document.body.scrollTop;
                this._pos=// should use actual width/height below
                [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
            }

            // move input on screen for focus, but hidden behind dialog
            this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
            inst.settings.onSelect=onSelect;
            this._inDialog=true;
            this.dpDiv.addClass(this._dialogClass);
            this._showDatepicker(this._dialogInput[0]);
            if ($.blockUI)
                $.blockUI(this.dpDiv);
            $.data(this._dialogInput[0], PROP_NAME, inst);
            return this;
        },

        /* Detach a datepicker from its control.
         @param  target    element - the target input field or division or span */
        _destroyDatepicker: function(target) {
            var $target=$(target);
            var inst=$.data(target, PROP_NAME);
            if (!$target.hasClass(this.markerClassName)) {
                return;
            }
            var nodeName=target.nodeName.toLowerCase();
            $.removeData(target, PROP_NAME);
            if (nodeName == 'input') {
                inst.append.remove();
                inst.trigger.remove();
                $target.removeClass(this.markerClassName).
                        unbind('focus', this._showDatepicker).
                        unbind('keydown', this._doKeyDown).
                        unbind('keypress', this._doKeyPress).
                        unbind('keyup', this._doKeyUp);
            } else if (nodeName == 'div' || nodeName == 'span')
                $target.removeClass(this.markerClassName).empty();
        },

        /* Enable the date picker to a jQuery selection.
         @param  target    element - the target input field or division or span */
        _enableDatepicker: function(target) {
            var $target=$(target);
            var inst=$.data(target, PROP_NAME);
            if (!$target.hasClass(this.markerClassName)) {
                return;
            }
            var nodeName=target.nodeName.toLowerCase();
            if (nodeName == 'input') {
                target.disabled=false;
                inst.trigger.filter('button').
                        each(function() {
                    this.disabled=false;
                }).end().
                        filter('img').css({opacity: '1.0', cursor: ''});
            }
            else if (nodeName == 'div' || nodeName == 'span') {
                var inline=$target.children('.' + this._inlineClass);
                inline.children().removeClass('ui-state-disabled');
            }
            this._disabledInputs=$.map(this._disabledInputs,
                    function(value) {
                        return (value == target ? null : value);
                    }); // delete entry
        },

        /* Disable the date picker to a jQuery selection.
         @param  target    element - the target input field or division or span */
        _disableDatepicker: function(target) {
            var $target=$(target);
            var inst=$.data(target, PROP_NAME);
            if (!$target.hasClass(this.markerClassName)) {
                return;
            }
            var nodeName=target.nodeName.toLowerCase();
            if (nodeName == 'input') {
                target.disabled=true;
                inst.trigger.filter('button').
                        each(function() {
                    this.disabled=true;
                }).end().
                        filter('img').css({opacity: '0.5', cursor: 'default'});
            }
            else if (nodeName == 'div' || nodeName == 'span') {
                var inline=$target.children('.' + this._inlineClass);
                inline.children().addClass('ui-state-disabled');
            }
            this._disabledInputs=$.map(this._disabledInputs,
                    function(value) {
                        return (value == target ? null : value);
                    }); // delete entry
            this._disabledInputs[this._disabledInputs.length]=target;
        },

        /* Is the first field in a jQuery collection disabled as a datepicker?
         @param  target    element - the target input field or division or span
         @return boolean - true if disabled, false if enabled */
        _isDisabledDatepicker: function(target) {
            if (!target) {
                return false;
            }
            for (var i=0; i < this._disabledInputs.length; i++) {
                if (this._disabledInputs[i] == target)
                    return true;
            }
            return false;
        },

        /* Retrieve the instance data for the target control.
         @param  target  element - the target input field or division or span
         @return  object - the associated instance data
         @throws  error if a jQuery problem getting data */
        _getInst: function(target) {
            try {
                return $.data(target, PROP_NAME);
            }
            catch (err) {
                throw 'Missing instance data for this datepicker';
            }
        },

        /* Update or retrieve the settings for a date picker attached to an input field or division.
         @param  target  element - the target input field or division or span
         @param  name    object - the new settings to update or
         string - the name of the setting to change or retrieve,
         when retrieving also 'all' for all instance settings or
         'defaults' for all global defaults
         @param  value   any - the new value for the setting
         (omit if above is an object or to retrieve a value) */
        _optionDatepicker: function(target, name, value) {
            var inst=this._getInst(target);
            if (arguments.length == 2 && typeof name == 'string') {
                return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
                        (inst ? (name == 'all' ? $.extend({}, inst.settings) :
                                 this._get(inst, name)) : null));
            }
            var settings=name || {};
            if (typeof name == 'string') {
                settings={};
                settings[name]=value;
            }
            if (inst) {
                if (this._curInst == inst) {
                    this._hideDatepicker();
                }
                var date=this._getDateDatepicker(target, true);
                extendRemove(inst.settings, settings);
                this._attachments($(target), inst);
                this._autoSize(inst);
                this._setDateDatepicker(target, date);
                this._updateDatepicker(inst);
            }
        },

        // change method deprecated
        _changeDatepicker: function(target, name, value) {
            this._optionDatepicker(target, name, value);
        },

        /* Redraw the date picker attached to an input field or division.
         @param  target  element - the target input field or division or span */
        _refreshDatepicker: function(target) {
            var inst=this._getInst(target);
            if (inst) {
                this._updateDatepicker(inst);
            }
        },

        /* Set the dates for a jQuery selection.
         @param  target   element - the target input field or division or span
         @param  date     Date - the new date */
        _setDateDatepicker: function(target, date) {
            var inst=this._getInst(target);
            if (inst) {
                this._setDate(inst, date);
                this._updateDatepicker(inst);
                this._updateAlternate(inst);
            }
        },

        /* Get the date(s) for the first entry in a jQuery selection.
         @param  target     element - the target input field or division or span
         @param  noDefault  boolean - true if no default date is to be used
         @return Date - the current date */
        _getDateDatepicker: function(target, noDefault) {
            var inst=this._getInst(target);
            if (inst && !inst.inline)
                this._setDateFromField(inst, noDefault);
            return (inst ? this._getDate(inst) : null);
        },

        /* Handle keystrokes. */
        _doKeyDown: function(event) {
            var inst=$.datepicker._getInst(event.target);
            var handled=true;
            var isRTL=inst.dpDiv.is('.ui-datepicker-rtl');
            inst._keyEvent=true;
            if ($.datepicker._datepickerShowing)
                switch (event.keyCode) {
                    case 9: $.datepicker._hideDatepicker();
                        handled=false;
                        break; // hide on tab out
                    case 13: var sel=$('td.' + $.datepicker._dayOverClass, inst.dpDiv).
                            add($('td.' + $.datepicker._currentClass, inst.dpDiv));
                        if (sel[0])
                            $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
                        else
                            $.datepicker._hideDatepicker();
                        return false; // don't submit the form
                        break; // select the value on enter
                    case 27: $.datepicker._hideDatepicker();
                        break; // hide on escape
                    case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                                                                     -$.datepicker._get(inst, 'stepBigMonths') :
                                                                     -$.datepicker._get(inst, 'stepMonths')), 'M');
                        break; // previous month/year on page up/+ ctrl
                    case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                                                                     +$.datepicker._get(inst, 'stepBigMonths') :
                                                                     +$.datepicker._get(inst, 'stepMonths')), 'M');
                        break; // next month/year on page down/+ ctrl
                    case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
                        handled=event.ctrlKey || event.metaKey;
                        break; // clear on ctrl or command +end
                    case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
                        handled=event.ctrlKey || event.metaKey;
                        break; // current on ctrl or command +home
                    case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
                        handled=event.ctrlKey || event.metaKey;
                        // -1 day on ctrl or command +left
                        if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                                                                                                -$.datepicker._get(inst, 'stepBigMonths') :
                                                                                                -$.datepicker._get(inst, 'stepMonths')), 'M');
                        // next month/year on alt +left on Mac
                        break;
                    case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
                        handled=event.ctrlKey || event.metaKey;
                        break; // -1 week on ctrl or command +up
                    case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
                        handled=event.ctrlKey || event.metaKey;
                        // +1 day on ctrl or command +right
                        if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
                                                                                                +$.datepicker._get(inst, 'stepBigMonths') :
                                                                                                +$.datepicker._get(inst, 'stepMonths')), 'M');
                        // next month/year on alt +right
                        break;
                    case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
                        handled=event.ctrlKey || event.metaKey;
                        break; // +1 week on ctrl or command +down
                    default: handled=false;
                }
            else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
                $.datepicker._showDatepicker(this);
            else {
                handled=false;
            }
            if (handled) {
                event.preventDefault();
                event.stopPropagation();
            }
        },

        /* Filter entered characters - based on date format. */
        _doKeyPress: function(event) {
            var inst=$.datepicker._getInst(event.target);
            if ($.datepicker._get(inst, 'constrainInput')) {
                var chars=$.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
                var chr=String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
                return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
            }
        },

        /* Synchronise manual entry and field/alternate field. */
        _doKeyUp: function(event) {
            var inst=$.datepicker._getInst(event.target);
            if (inst.input.val() != inst.lastVal) {
                try {
                    var date=$.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
                            (inst.input ? inst.input.val() : null),
                            $.datepicker._getFormatConfig(inst));
                    if (date) { // only if valid
                        $.datepicker._setDateFromField(inst);
                        $.datepicker._updateAlternate(inst);
                        $.datepicker._updateDatepicker(inst);
                    }
                }
                catch (event) {
                    $.datepicker.log(event);
                }
            }
            return true;
        },

        /* Pop-up the date picker for a given input field.
         @param  input  element - the input field attached to the date picker or
         event - if triggered by focus */
        _showDatepicker: function(input) {
            input=input.target || input;
            if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
                input=$('input', input.parentNode)[0];
            if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
                return;
            var inst=$.datepicker._getInst(input);
            if ($.datepicker._curInst && $.datepicker._curInst != inst) {
                $.datepicker._curInst.dpDiv.stop(true, true);
            }
            var beforeShow=$.datepicker._get(inst, 'beforeShow');
            extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
            $.datepicker._lastInput=input;
            $.datepicker._setDateFromField(inst);
            if ($.datepicker._inDialog) // hide cursor
                input.value='';
            if (!$.datepicker._pos) { // position below input
                $.datepicker._pos=$.datepicker._findPos(input);
                $.datepicker._pos[1]+=input.offsetHeight; // add the height
            }
            var isFixed=false;
            $(input).parents().each(function() {
                isFixed|=$(this).css('position') == 'fixed';
                return !isFixed;
            });
            if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
                $.datepicker._pos[0]-=document.documentElement.scrollLeft;
                $.datepicker._pos[1]-=document.documentElement.scrollTop;
            }
            var offset={left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
            $.datepicker._pos=null;
            // determine sizing offscreen
            inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
            $.datepicker._updateDatepicker(inst);
            // fix width for dynamic number of date pickers
            // and adjust position before showing
            offset=$.datepicker._checkOffset(inst, offset, isFixed);
            inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
                                       'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
                left: offset.left + 'px', top: offset.top + 'px'});
            if (!inst.inline) {
                var showAnim=$.datepicker._get(inst, 'showAnim');
                var duration=$.datepicker._get(inst, 'duration');
                var postProcess=function() {
                    $.datepicker._datepickerShowing=true;
                    var borders=$.datepicker._getBorders(inst.dpDiv);
                    inst.dpDiv.find('iframe.ui-datepicker-cover').// IE6- only
                            css({left: -borders[0], top: -borders[1],
                        width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
                };
                if ($.effects && $.effects[showAnim])
                    inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
                else
                    inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
                if (!showAnim)
                    postProcess();
                if (inst.input.is(':visible') && !inst.input.is(':disabled'))
                    inst.input[0].focus();
                $.datepicker._curInst=inst;
            }
        },

        /* Generate the date picker content. */
        _updateDatepicker: function(inst) {
            var self=this;
            var borders=$.datepicker._getBorders(inst.dpDiv);
            inst.dpDiv.empty().append(this._generateHTML(inst))
                    .find('iframe.ui-datepicker-cover')// IE6- only
                    .css({left: -borders[0], top: -borders[1],
                width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
                    .end()
                    .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
                    .bind('mouseout', function() {
                $(this).removeClass('ui-state-hover');
                if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
                if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
            })
                    .bind('mouseover', function() {
                if (!self._isDisabledDatepicker(inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
                    $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
                    $(this).addClass('ui-state-hover');
                    if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
                    if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
                }
            })
                    .end()
                    .find('.' + this._dayOverClass + ' a')
                    .trigger('mouseover')
                    .end();
            var numMonths=this._getNumberOfMonths(inst);
            var cols=numMonths[1];
            var width=17;
            if (cols > 1)
                inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
            else
                inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
            inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
                       'Class']('ui-datepicker-multi');
            inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
                       'Class']('ui-datepicker-rtl');
            if (inst == $.datepicker._curInst && inst.input &&
                inst.input.is(':visible') && !inst.input.is(':disabled'))
                $(inst.input[0]).focus();
        },

        /* Retrieve the size of left and top borders for an element.
         @param  elem  (jQuery object) the element of interest
         @return  (number[2]) the left and top borders */
        _getBorders: function(elem) {
            var convert=function(value) {
                return {thin: 1, medium: 2, thick: 3}[value] || value;
            };
            return [parseFloat(convert(elem.css('border-left-width'))),
                parseFloat(convert(elem.css('border-top-width')))];
        },

        /* Check positioning to remain on screen. */
        _checkOffset: function(inst, offset, isFixed) {
            var dpWidth=inst.dpDiv.outerWidth();
            var dpHeight=inst.dpDiv.outerHeight();
            var inputWidth=inst.input ? inst.input.outerWidth() : 0;
            var inputHeight=inst.input ? inst.input.outerHeight() : 0;
            var viewWidth=document.documentElement.clientWidth + $(document).scrollLeft();
            var viewHeight=document.documentElement.clientHeight + $(document).scrollTop();

            offset.left-=(this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
            offset.left-=(isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
            offset.top-=(isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;

            // now check if datepicker is showing outside window viewport - move to a better place if so.
            offset.left-=Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
                                               Math.abs(offset.left + dpWidth - viewWidth) : 0);
            offset.top-=Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
                                             Math.abs(offset.top + dpHeight + inputHeight * 2 - viewHeight) : 0);

            return offset;
        },

        /* Find an object's position on the screen. */
        _findPos: function(obj) {
            var inst=this._getInst(obj);
            var isRTL=this._get(inst, 'isRTL');
            while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
                obj=obj[isRTL ? 'previousSibling' : 'nextSibling'];
            }
            var position=$(obj).offset();
            return [position.left, position.top];
        },

        /* Hide the date picker from view.
         @param  input  element - the input field attached to the date picker */
        _hideDatepicker: function(input) {
            var inst=this._curInst;
            if (!inst || (input && inst != $.data(input, PROP_NAME)))
                return;
            if (this._datepickerShowing) {
                var showAnim=this._get(inst, 'showAnim');
                var duration=this._get(inst, 'duration');
                var postProcess=function() {
                    $.datepicker._tidyDialog(inst);
                    this._curInst=null;
                };
                if ($.effects && $.effects[showAnim])
                    inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
                else
                    inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
                                (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
                if (!showAnim)
                    postProcess();
                var onClose=this._get(inst, 'onClose');
                if (onClose)
                    onClose.apply((inst.input ? inst.input[0] : null),
                            [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
                this._datepickerShowing=false;
                this._lastInput=null;
                if (this._inDialog) {
                    this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
                    if ($.blockUI) {
                        $.unblockUI();
                        $('body').append(this.dpDiv);
                    }
                }
                this._inDialog=false;
            }
        },

        /* Tidy up after a dialog display. */
        _tidyDialog: function(inst) {
            inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
        },

        /* Close date picker if clicked elsewhere. */
        _checkExternalClick: function(event) {
            if (!$.datepicker._curInst)
                return;
            var $target=$(event.target);
            if ($target[0].id != $.datepicker._mainDivId &&
                $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
                !$target.hasClass($.datepicker.markerClassName) &&
                !$target.hasClass($.datepicker._triggerClass) &&
                $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
                $.datepicker._hideDatepicker();
        },

        /* Adjust one of the date sub-fields. */
        _adjustDate: function(id, offset, period) {
            var target=$(id);
            var inst=this._getInst(target[0]);
            if (this._isDisabledDatepicker(target[0])) {
                return;
            }
            this._adjustInstDate(inst, offset +
                                       (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
                    period);
            this._updateDatepicker(inst);
        },

        /* Action for current link. */
        _gotoToday: function(id) {
            var target=$(id);
            var inst=this._getInst(target[0]);
            if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
                inst.selectedDay=inst.currentDay;
                inst.drawMonth=inst.selectedMonth=inst.currentMonth;
                inst.drawYear=inst.selectedYear=inst.currentYear;
            }
            else {
                var date=new Date();
                inst.selectedDay=date.getDate();
                inst.drawMonth=inst.selectedMonth=date.getMonth();
                inst.drawYear=inst.selectedYear=date.getFullYear();
            }
            this._notifyChange(inst);
            this._adjustDate(target);
        },

        /* Action for selecting a new month/year. */
        _selectMonthYear: function(id, select, period) {
            var target=$(id);
            var inst=this._getInst(target[0]);
            inst._selectingMonthYear=false;
            inst['selected' + (period == 'M' ? 'Month' : 'Year')]=
            inst['draw' + (period == 'M' ? 'Month' : 'Year')]=
            parseInt(select.options[select.selectedIndex].value, 10);
            this._notifyChange(inst);
            this._adjustDate(target);
        },

        /* Restore input focus after not changing month/year. */
        _clickMonthYear: function(id) {
            var target=$(id);
            var inst=this._getInst(target[0]);
            if (inst.input && inst._selectingMonthYear && !$.browser.msie)
                inst.input[0].focus();
            inst._selectingMonthYear=!inst._selectingMonthYear;
        },

        /* Action for selecting a day. */
        _selectDay: function(id, month, year, td) {
            var target=$(id);
            if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
                return;
            }
            var inst=this._getInst(target[0]);
            inst.selectedDay=inst.currentDay=$('a', td).html();
            inst.selectedMonth=inst.currentMonth=month;
            inst.selectedYear=inst.currentYear=year;
            this._selectDate(id, this._formatDate(inst,
                    inst.currentDay, inst.currentMonth, inst.currentYear));
        },

        /* Erase the input field and hide the date picker. */
        _clearDate: function(id) {
            var target=$(id);
            var inst=this._getInst(target[0]);
            this._selectDate(target, '');
        },

        /* Update the input field with the selected date. */
        _selectDate: function(id, dateStr) {
            var target=$(id);
            var inst=this._getInst(target[0]);
            dateStr=(dateStr != null ? dateStr : this._formatDate(inst));
            if (inst.input)
                inst.input.val(dateStr);
            this._updateAlternate(inst);
            var onSelect=this._get(inst, 'onSelect');
            if (onSelect)
                onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
            else if (inst.input)
                inst.input.trigger('change'); // fire the change event
            if (inst.inline)
                this._updateDatepicker(inst);
            else {
                this._hideDatepicker();
                this._lastInput=inst.input[0];
                if (typeof(inst.input[0]) != 'object')
                    inst.input[0].focus(); // restore focus
                this._lastInput=null;
            }
        },

        /* Update any alternate field to synchronise with the main field. */
        _updateAlternate: function(inst) {
            var altField=this._get(inst, 'altField');
            if (altField) { // update alternate field too
                var altFormat=this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
                var date=this._getDate(inst);
                var dateStr=this.formatDate(altFormat, date, this._getFormatConfig(inst));
                $(altField).each(function() {
                    $(this).val(dateStr);
                });
            }
        },

        /* Set as beforeShowDay function to prevent selection of weekends.
         @param  date  Date - the date to customise
         @return [boolean, string] - is this date selectable?, what is its CSS class? */
        noWeekends: function(date) {
            var day=date.getDay();
            return [(day > 0 && day < 6), ''];
        },

        /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
         @param  date  Date - the date to get the week for
         @return  number - the number of the week within the year that contains this date */
        iso8601Week: function(date) {
            var checkDate=new Date(date.getTime());
            // Find Thursday of this week starting on Monday
            checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
            var time=checkDate.getTime();
            checkDate.setMonth(0); // Compare with Jan 1
            checkDate.setDate(1);
            return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
        },

        /* Parse a string value into a date object.
         See formatDate below for the possible formats.

         @param  format    string - the expected format of the date
         @param  value     string - the date in the above format
         @param  settings  Object - attributes include:
         shortYearCutoff  number - the cutoff year for determining the century (optional)
         dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
         dayNames         string[7] - names of the days from Sunday (optional)
         monthNamesShort  string[12] - abbreviated names of the months (optional)
         monthNames       string[12] - names of the months (optional)
         @return  Date - the extracted date value or null if value is blank */
        parseDate: function (format, value, settings) {
            if (format == null || value == null)
                throw 'Invalid arguments';
            value=(typeof value == 'object' ? value.toString() : value + '');
            if (value == '')
                return null;
            var shortYearCutoff=(settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
            var dayNamesShort=(settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
            var dayNames=(settings ? settings.dayNames : null) || this._defaults.dayNames;
            var monthNamesShort=(settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
            var monthNames=(settings ? settings.monthNames : null) || this._defaults.monthNames;
            var year=-1;
            var month=-1;
            var day=-1;
            var doy=-1;
            var literal=false;
            // Check whether a format character is doubled
            var lookAhead=function(match) {
                var matches=(iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
                if (matches)
                    iFormat++;
                return matches;
            };
            // Extract a number from the string value
            var getNumber=function(match) {
                lookAhead(match);
                var size=(match == '@' ? 14 : (match == '!' ? 20 :
                                               (match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
                var digits=new RegExp('^\\d{1,' + size + '}');
                var num=value.substring(iValue).match(digits);
                if (!num)
                    throw 'Missing number at position ' + iValue;
                iValue+=num[0].length;
                return parseInt(num[0], 10);
            };
            // Extract a name from the string value and convert to an index
            var getName=function(match, shortNames, longNames) {
                var names=(lookAhead(match) ? longNames : shortNames);
                for (var i=0; i < names.length; i++) {
                    if (value.substr(iValue, names[i].length) == names[i]) {
                        iValue+=names[i].length;
                        return i + 1;
                    }
                }
                throw 'Unknown name at position ' + iValue;
            };
            // Confirm that a literal character matches the string value
            var checkLiteral=function() {
                if (value.charAt(iValue) != format.charAt(iFormat))
                    throw 'Unexpected literal at position ' + iValue;
                iValue++;
            };
            var iValue=0;
            for (var iFormat=0; iFormat < format.length; iFormat++) {
                if (literal)
                    if (format.charAt(iFormat) == "'" && !lookAhead("'"))
                        literal=false;
                    else
                        checkLiteral();
                else
                    switch (format.charAt(iFormat)) {
                        case 'd':
                            day=getNumber('d');
                            break;
                        case 'D':
                            getName('D', dayNamesShort, dayNames);
                            break;
                        case 'o':
                            doy=getNumber('o');
                            break;
                        case 'm':
                            month=getNumber('m');
                            break;
                        case 'M':
                            month=getName('M', monthNamesShort, monthNames);
                            break;
                        case 'y':
                            year=getNumber('y');
                            break;
                        case '@':
                            var date=new Date(getNumber('@'));
                            year=date.getFullYear();
                            month=date.getMonth() + 1;
                            day=date.getDate();
                            break;
                        case '!':
                            var date=new Date((getNumber('!') - this._ticksTo1970) / 10000);
                            year=date.getFullYear();
                            month=date.getMonth() + 1;
                            day=date.getDate();
                            break;
                        case "'":
                            if (lookAhead("'"))
                                checkLiteral();
                            else
                                literal=true;
                            break;
                        default:
                            checkLiteral();
                    }
            }
            if (year == -1)
                year=new Date().getFullYear();
            else if (year < 100)
                year+=new Date().getFullYear() - new Date().getFullYear() % 100 +
                      (year <= shortYearCutoff ? 0 : -100);
            if (doy > -1) {
                month=1;
                day=doy;
                do {
                    var dim=this._getDaysInMonth(year, month - 1);
                    if (day <= dim)
                        break;
                    month++;
                    day-=dim;
                } while (true);
            }
            var date=this._daylightSavingAdjust(new Date(year, month - 1, day));
            if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
                throw 'Invalid date'; // E.g. 31/02/*
            return date;
        },

        /* Standard date formats. */
        ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
        COOKIE: 'D, dd M yy',
        ISO_8601: 'yy-mm-dd',
        RFC_822: 'D, d M y',
        RFC_850: 'DD, dd-M-y',
        RFC_1036: 'D, d M y',
        RFC_1123: 'D, d M yy',
        RFC_2822: 'D, d M yy',
        RSS: 'D, d M y', // RFC 822
        TICKS: '!',
        TIMESTAMP: '@',
        W3C: 'yy-mm-dd', // ISO 8601

        _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
                        Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),

        /* Format a date object into a string value.
         The format can be combinations of the following:
         d  - day of month (no leading zero)
         dd - day of month (two digit)
         o  - day of year (no leading zeros)
         oo - day of year (three digit)
         D  - day name short
         DD - day name long
         m  - month of year (no leading zero)
         mm - month of year (two digit)
         M  - month name short
         MM - month name long
         y  - year (two digit)
         yy - year (four digit)
         @ - Unix timestamp (ms since 01/01/1970)
         ! - Windows ticks (100ns since 01/01/0001)
         '...' - literal text
         '' - single quote

         @param  format    string - the desired format of the date
         @param  date      Date - the date value to format
         @param  settings  Object - attributes include:
         dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
         dayNames         string[7] - names of the days from Sunday (optional)
         monthNamesShort  string[12] - abbreviated names of the months (optional)
         monthNames       string[12] - names of the months (optional)
         @return  string - the date in the above format */
        formatDate: function (format, date, settings) {
            if (!date)
                return '';
            var dayNamesShort=(settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
            var dayNames=(settings ? settings.dayNames : null) || this._defaults.dayNames;
            var monthNamesShort=(settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
            var monthNames=(settings ? settings.monthNames : null) || this._defaults.monthNames;
            // Check whether a format character is doubled
            var lookAhead=function(match) {
                var matches=(iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
                if (matches)
                    iFormat++;
                return matches;
            };
            // Format a number, with leading zero if necessary
            var formatNumber=function(match, value, len) {
                var num='' + value;
                if (lookAhead(match))
                    while (num.length < len)
                        num='0' + num;
                return num;
            };
            // Format a name, short or long as requested
            var formatName=function(match, value, shortNames, longNames) {
                return (lookAhead(match) ? longNames[value] : shortNames[value]);
            };
            var output='';
            var literal=false;
            if (date)
                for (var iFormat=0; iFormat < format.length; iFormat++) {
                    if (literal)
                        if (format.charAt(iFormat) == "'" && !lookAhead("'"))
                            literal=false;
                        else
                            output+=format.charAt(iFormat);
                    else
                        switch (format.charAt(iFormat)) {
                            case 'd':
                                output+=formatNumber('d', date.getDate(), 2);
                                break;
                            case 'D':
                                output+=formatName('D', date.getDay(), dayNamesShort, dayNames);
                                break;
                            case 'o':
                                output+=formatNumber('o',
                                        (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
                                break;
                            case 'm':
                                output+=formatNumber('m', date.getMonth() + 1, 2);
                                break;
                            case 'M':
                                output+=formatName('M', date.getMonth(), monthNamesShort, monthNames);
                                break;
                            case 'y':
                                output+=(lookAhead('y') ? date.getFullYear() :
                                         (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
                                break;
                            case '@':
                                output+=date.getTime();
                                break;
                            case '!':
                                output+=date.getTime() * 10000 + this._ticksTo1970;
                                break;
                            case "'":
                                if (lookAhead("'"))
                                    output+="'";
                                else
                                    literal=true;
                                break;
                            default:
                                output+=format.charAt(iFormat);
                        }
                }
            return output;
        },

        /* Extract all possible characters from the date format. */
        _possibleChars: function (format) {
            var chars='';
            var literal=false;
            // Check whether a format character is doubled
            var lookAhead=function(match) {
                var matches=(iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
                if (matches)
                    iFormat++;
                return matches;
            };
            for (var iFormat=0; iFormat < format.length; iFormat++)
                if (literal)
                    if (format.charAt(iFormat) == "'" && !lookAhead("'"))
                        literal=false;
                    else
                        chars+=format.charAt(iFormat);
                else
                    switch (format.charAt(iFormat)) {
                        case 'd': case 'm': case 'y': case '@':
                        chars+='0123456789';
                        break;
                        case 'D': case 'M':
                        return null; // Accept anything
                        case "'":
                            if (lookAhead("'"))
                                chars+="'";
                            else
                                literal=true;
                            break;
                        default:
                            chars+=format.charAt(iFormat);
                    }
            return chars;
        },

        /* Get a setting value, defaulting if necessary. */
        _get: function(inst, name) {
            return inst.settings[name] !== undefined ?
                   inst.settings[name] : this._defaults[name];
        },

        /* Parse existing date and initialise date picker. */
        _setDateFromField: function(inst, noDefault) {
            var dateFormat=this._get(inst, 'dateFormat');
            inst.lastVal=inst.input ? inst.input.val() : null;
            var dates=inst.lastVal;
            var date, defaultDate;
            date=defaultDate=this._getDefaultDate(inst);
            var settings=this._getFormatConfig(inst);
            try {
                date=this.parseDate(dateFormat, dates, settings) || defaultDate;
            } catch (event) {
                this.log(event);
                dates=(noDefault ? '' : dates);
            }
            inst.selectedDay=date.getDate();
            inst.drawMonth=inst.selectedMonth=date.getMonth();
            inst.drawYear=inst.selectedYear=date.getFullYear();
            inst.currentDay=(dates ? date.getDate() : 0);
            inst.currentMonth=(dates ? date.getMonth() : 0);
            inst.currentYear=(dates ? date.getFullYear() : 0);
            this._adjustInstDate(inst);
        },

        /* Retrieve the default date shown on opening. */
        _getDefaultDate: function(inst) {
            return this._restrictMinMax(inst,
                    this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
        },

        /* A date may be specified as an exact value or a relative one. */
        _determineDate: function(inst, date, defaultDate) {
            var offsetNumeric=function(offset) {
                var date=new Date();
                date.setDate(date.getDate() + offset);
                return date;
            };
            var offsetString=function(offset) {
                try {
                    return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
                            offset, $.datepicker._getFormatConfig(inst));
                }
                catch (e) {
                    // Ignore
                }
                var date=(offset.toLowerCase().match(/^c/) ?
                          $.datepicker._getDate(inst) : null) || new Date();
                var year=date.getFullYear();
                var month=date.getMonth();
                var day=date.getDate();
                var pattern=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
                var matches=pattern.exec(offset);
                while (matches) {
                    switch (matches[2] || 'd') {
                        case 'd' : case 'D' :
                        day+=parseInt(matches[1], 10); break;
                        case 'w' : case 'W' :
                        day+=parseInt(matches[1], 10) * 7; break;
                        case 'm' : case 'M' :
                        month+=parseInt(matches[1], 10);
                        day=Math.min(day, $.datepicker._getDaysInMonth(year, month));
                        break;
                        case 'y': case 'Y' :
                        year+=parseInt(matches[1], 10);
                        day=Math.min(day, $.datepicker._getDaysInMonth(year, month));
                        break;
                    }
                    matches=pattern.exec(offset);
                }
                return new Date(year, month, day);
            };
            date=(date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
                                                (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
            date=(date && date.toString() == 'Invalid Date' ? defaultDate : date);
            if (date) {
                date.setHours(0);
                date.setMinutes(0);
                date.setSeconds(0);
                date.setMilliseconds(0);
            }
            return this._daylightSavingAdjust(date);
        },

        /* Handle switch to/from daylight saving.
         Hours may be non-zero on daylight saving cut-over:
         > 12 when midnight changeover, but then cannot generate
         midnight datetime, so jump to 1AM, otherwise reset.
         @param  date  (Date) the date to check
         @return  (Date) the corrected date */
        _daylightSavingAdjust: function(date) {
            if (!date) return null;
            date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
            return date;
        },

        /* Set the date(s) directly. */
        _setDate: function(inst, date, noChange) {
            var clear=!(date);
            var origMonth=inst.selectedMonth;
            var origYear=inst.selectedYear;
            date=this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
            inst.selectedDay=inst.currentDay=date.getDate();
            inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();
            inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();
            if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
                this._notifyChange(inst);
            this._adjustInstDate(inst);
            if (inst.input) {
                inst.input.val(clear ? '' : this._formatDate(inst));
            }
        },

        /* Retrieve the date(s) directly. */
        _getDate: function(inst) {
            var startDate=(!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
                           this._daylightSavingAdjust(new Date(
                                   inst.currentYear, inst.currentMonth, inst.currentDay)));
            return startDate;
        },

        /* Generate the HTML for the current state of the date picker. */
        _generateHTML: function(inst) {
            var today=new Date();
            today=this._daylightSavingAdjust(
                    new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
            var isRTL=this._get(inst, 'isRTL');
            var showButtonPanel=this._get(inst, 'showButtonPanel');
            var hideIfNoPrevNext=this._get(inst, 'hideIfNoPrevNext');
            var navigationAsDateFormat=this._get(inst, 'navigationAsDateFormat');
            var numMonths=this._getNumberOfMonths(inst);
            var showCurrentAtPos=this._get(inst, 'showCurrentAtPos');
            var stepMonths=this._get(inst, 'stepMonths');
            var isMultiMonth=(numMonths[0] != 1 || numMonths[1] != 1);
            var currentDate=this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
                                                        new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
            var minDate=this._getMinMaxDate(inst, 'min');
            var maxDate=this._getMinMaxDate(inst, 'max');
            var drawMonth=inst.drawMonth - showCurrentAtPos;
            var drawYear=inst.drawYear;
            if (drawMonth < 0) {
                drawMonth+=12;
                drawYear--;
            }
            if (maxDate) {
                var maxDraw=this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
                        maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
                maxDraw=(minDate && maxDraw < minDate ? minDate : maxDraw);
                while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
                    drawMonth--;
                    if (drawMonth < 0) {
                        drawMonth=11;
                        drawYear--;
                    }
                }
            }
            inst.drawMonth=drawMonth;
            inst.drawYear=drawYear;
            var prevText=this._get(inst, 'prevText');
            prevText=(!navigationAsDateFormat ? prevText : this.formatDate(prevText,
                    this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
                    this._getFormatConfig(inst)));
            var prev=(this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
                      '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
                      '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
                      ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
                      (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
            var nextText=this._get(inst, 'nextText');
            nextText=(!navigationAsDateFormat ? nextText : this.formatDate(nextText,
                    this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
                    this._getFormatConfig(inst)));
            var next=(this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
                      '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
                      '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
                      ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
                      (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
            var currentText=this._get(inst, 'currentText');
            var gotoDate=(this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
            currentText=(!navigationAsDateFormat ? currentText :
                         this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
            var controls=(!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
                                         '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
            var buttonPanel=(showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
                                                (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
                                                                                   '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
                                                                                   '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
            var firstDay=parseInt(this._get(inst, 'firstDay'), 10);
            firstDay=(isNaN(firstDay) ? 0 : firstDay);
            var showWeek=this._get(inst, 'showWeek');
            var dayNames=this._get(inst, 'dayNames');
            var dayNamesShort=this._get(inst, 'dayNamesShort');
            var dayNamesMin=this._get(inst, 'dayNamesMin');
            var monthNames=this._get(inst, 'monthNames');
            var monthNamesShort=this._get(inst, 'monthNamesShort');
            var beforeShowDay=this._get(inst, 'beforeShowDay');
            var showOtherMonths=this._get(inst, 'showOtherMonths');
            var selectOtherMonths=this._get(inst, 'selectOtherMonths');
            var calculateWeek=this._get(inst, 'calculateWeek') || this.iso8601Week;
            var defaultDate=this._getDefaultDate(inst);
            var html='';
            for (var row=0; row < numMonths[0]; row++) {
                var group='';
                for (var col=0; col < numMonths[1]; col++) {
                    var selectedDate=this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
                    var cornerClass=' ui-corner-all';
                    var calender='';
                    if (isMultiMonth) {
                        calender+='<div class="ui-datepicker-group';
                        if (numMonths[1] > 1)
                            switch (col) {
                                case 0: calender+=' ui-datepicker-group-first';
                                    cornerClass=' ui-corner-' + (isRTL ? 'right' : 'left'); break;
                                case numMonths[1] - 1: calender+=' ui-datepicker-group-last';
                                    cornerClass=' ui-corner-' + (isRTL ? 'left' : 'right'); break;
                                default: calender+=' ui-datepicker-group-middle'; cornerClass=''; break;
                            }
                        calender+='">';
                    }
                    calender+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
                              (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
                              (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
                              this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
                                      row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
                              '</div><table class="ui-datepicker-calendar"><thead>' +
                              '<tr>';
                    var thead=(showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
                    for (var dow=0; dow < 7; dow++) { // days of the week
                        var day=(dow + firstDay) % 7;
                        thead+='<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
                               '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
                    }
                    calender+=thead + '</tr></thead><tbody>';
                    var daysInMonth=this._getDaysInMonth(drawYear, drawMonth);
                    if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
                        inst.selectedDay=Math.min(inst.selectedDay, daysInMonth);
                    var leadDays=(this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
                    var numRows=(isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
                    var printDate=this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
                    for (var dRow=0; dRow < numRows; dRow++) { // create date picker rows
                        calender+='<tr>';
                        var tbody=(!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
                                                    this._get(inst, 'calculateWeek')(printDate) + '</td>');
                        for (var dow=0; dow < 7; dow++) { // create date picker days
                            var daySettings=(beforeShowDay ?
                                             beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
                            var otherMonth=(printDate.getMonth() != drawMonth);
                            var unselectable=(otherMonth && !selectOtherMonths) || !daySettings[0] ||
                                             (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
                            tbody+='<td class="' +
                                   ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
                                   (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
                                   ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
                                    (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
                                       // or defaultDate is current printedDate and defaultDate is selectedDate
                                    ' ' + this._dayOverClass : '') + // highlight selected day
                                   (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled' : '') + // highlight unselectable days
                                   (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
                                                                          (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
                                                                          (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
                                   ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
                                   (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
                                                        inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
                                   (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
                                    (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
                                                                                                                          (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
                                                                                                                          (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
                                                                                                                          (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
                                                                                                                          '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
                            printDate.setDate(printDate.getDate() + 1);
                            printDate=this._daylightSavingAdjust(printDate);
                        }
                        calender+=tbody + '</tr>';
                    }
                    drawMonth++;
                    if (drawMonth > 11) {
                        drawMonth=0;
                        drawYear++;
                    }
                    calender+='</tbody></table>' + (isMultiMonth ? '</div>' +
                                                                   ((numMonths[0] > 0 && col == numMonths[1] - 1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
                    group+=calender;
                }
                html+=group;
            }
            html+=buttonPanel + ($.browser.msie && parseInt($.browser.version, 10) < 7 && !inst.inline ?
                                 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
            inst._keyEvent=false;
            return html;
        },

        /* Generate the month and year header. */
        _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
                                           secondary, monthNames, monthNamesShort) {
            var changeMonth=this._get(inst, 'changeMonth');
            var changeYear=this._get(inst, 'changeYear');
            var showMonthAfterYear=this._get(inst, 'showMonthAfterYear');
            var html='<div class="ui-datepicker-title">';
            var monthHtml='';
            // month selection
            if (secondary || !changeMonth)
                monthHtml+='<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
            else {
                var inMinYear=(minDate && minDate.getFullYear() == drawYear);
                var inMaxYear=(maxDate && maxDate.getFullYear() == drawYear);
                monthHtml+='<select class="ui-datepicker-month" ' +
                           'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
                           'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
                           '>';
                for (var month=0; month < 12; month++) {
                    if ((!inMinYear || month >= minDate.getMonth()) &&
                        (!inMaxYear || month <= maxDate.getMonth()))
                        monthHtml+='<option value="' + month + '"' +
                                   (month == drawMonth ? ' selected="selected"' : '') +
                                   '>' + monthNamesShort[month] + '</option>';
                }
                monthHtml+='</select>';
            }
            if (!showMonthAfterYear)
                html+=monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
            // year selection
            if (secondary || !changeYear)
                html+='<span class="ui-datepicker-year">' + drawYear + '</span>';
            else {
                // determine range of years to display
                var years=this._get(inst, 'yearRange').split(':');
                var thisYear=new Date().getFullYear();
                var determineYear=function(value) {
                    var year=(value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
                              (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
                               parseInt(value, 10)));
                    return (isNaN(year) ? thisYear : year);
                };
                var year=determineYear(years[0]);
                var endYear=Math.max(year, determineYear(years[1] || ''));
                year=(minDate ? Math.max(year, minDate.getFullYear()) : year);
                endYear=(maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
                html+='<select class="ui-datepicker-year" ' +
                      'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
                      'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
                      '>';
                for (; year <= endYear; year++) {
                    html+='<option value="' + year + '"' +
                          (year == drawYear ? ' selected="selected"' : '') +
                          '>' + year + '</option>';
                }
                html+='</select>';
            }
            html+=this._get(inst, 'yearSuffix');
            if (showMonthAfterYear)
                html+=((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '') + monthHtml;
            html+='</div>'; // Close datepicker_header
            return html;
        },

        /* Adjust one of the date sub-fields. */
        _adjustInstDate: function(inst, offset, period) {
            var year=inst.drawYear + (period == 'Y' ? offset : 0);
            var month=inst.drawMonth + (period == 'M' ? offset : 0);
            var day=Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
                    (period == 'D' ? offset : 0);
            var date=this._restrictMinMax(inst,
                    this._daylightSavingAdjust(new Date(year, month, day)));
            inst.selectedDay=date.getDate();
            inst.drawMonth=inst.selectedMonth=date.getMonth();
            inst.drawYear=inst.selectedYear=date.getFullYear();
            if (period == 'M' || period == 'Y')
                this._notifyChange(inst);
        },

        /* Ensure a date is within any min/max bounds. */
        _restrictMinMax: function(inst, date) {
            var minDate=this._getMinMaxDate(inst, 'min');
            var maxDate=this._getMinMaxDate(inst, 'max');
            date=(minDate && date < minDate ? minDate : date);
            date=(maxDate && date > maxDate ? maxDate : date);
            return date;
        },

        /* Notify change of month/year. */
        _notifyChange: function(inst) {
            var onChange=this._get(inst, 'onChangeMonthYear');
            if (onChange)
                onChange.apply((inst.input ? inst.input[0] : null),
                        [inst.selectedYear, inst.selectedMonth + 1, inst]);
        },

        /* Determine the number of months to show. */
        _getNumberOfMonths: function(inst) {
            var numMonths=this._get(inst, 'numberOfMonths');
            return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
        },

        /* Determine the current maximum date - ensure no time components are set. */
        _getMinMaxDate: function(inst, minMax) {
            return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
        },

        /* Find the number of days in a given month. */
        _getDaysInMonth: function(year, month) {
            return 32 - new Date(year, month, 32).getDate();
        },

        /* Find the day of the week of the first of a month. */
        _getFirstDayOfMonth: function(year, month) {
            return new Date(year, month, 1).getDay();
        },

        /* Determines if we should allow a "next/prev" month display change. */
        _canAdjustMonth: function(inst, offset, curYear, curMonth) {
            var numMonths=this._getNumberOfMonths(inst);
            var date=this._daylightSavingAdjust(new Date(curYear,
                    curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
            if (offset < 0)
                date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
            return this._isInRange(inst, date);
        },

        /* Is the given date in the accepted range? */
        _isInRange: function(inst, date) {
            var minDate=this._getMinMaxDate(inst, 'min');
            var maxDate=this._getMinMaxDate(inst, 'max');
            return ((!minDate || date.getTime() >= minDate.getTime()) &&
                    (!maxDate || date.getTime() <= maxDate.getTime()));
        },

        /* Provide the configuration settings for formatting/parsing. */
        _getFormatConfig: function(inst) {
            var shortYearCutoff=this._get(inst, 'shortYearCutoff');
            shortYearCutoff=(typeof shortYearCutoff != 'string' ? shortYearCutoff :
                             new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
            return {shortYearCutoff: shortYearCutoff,
                dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
                monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
        },

        /* Format the given date for display. */
        _formatDate: function(inst, day, month, year) {
            if (!day) {
                inst.currentDay=inst.selectedDay;
                inst.currentMonth=inst.selectedMonth;
                inst.currentYear=inst.selectedYear;
            }
            var date=(day ? (typeof day == 'object' ? day :
                             this._daylightSavingAdjust(new Date(year, month, day))) :
                      this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
            return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
        }
    });

    /* jQuery extend now ignores nulls! */
    function extendRemove(target, props) {
        $.extend(target, props);
        for (var name in props)
            if (props[name] == null || props[name] == undefined)
                target[name]=props[name];
        return target;
    }

    ;

    /* Determine whether an object is an array. */
    function isArray(a) {
        return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
                      (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
    }

    ;

    /* Invoke the datepicker functionality.
     @param  options  string - a command, optionally followed by additional parameters or
     Object - settings for attaching new datepicker functionality
     @return  jQuery object */
    $.fn.datepicker=function(options) {

        /* Initialise the date picker. */
        if (!$.datepicker.initialized) {
            $(document).mousedown($.datepicker._checkExternalClick).
                    find('body').append($.datepicker.dpDiv);
            $.datepicker.initialized=true;
        }

        var otherArgs=Array.prototype.slice.call(arguments, 1);
        if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
            return $.datepicker['_' + options + 'Datepicker'].
                    apply($.datepicker, [this[0]].concat(otherArgs));
        if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
            return $.datepicker['_' + options + 'Datepicker'].
                    apply($.datepicker, [this[0]].concat(otherArgs));
        return this.each(function() {
            typeof options == 'string' ?
            $.datepicker['_' + options + 'Datepicker'].
                    apply($.datepicker, [this].concat(otherArgs)) :
            $.datepicker._attachDatepicker(this, options);
        });
    };

    $.datepicker=new Datepicker(); // singleton instance
    $.datepicker.initialized=false;
    $.datepicker.uuid=new Date().getTime();
    $.datepicker.version="1.8rc1";

    // Workaround for #4055
    // Add another global to avoid noConflict issues with inline event handlers
    window['DP_jQuery_' + dpuuid]=$;

})(jQuery);
/*
 * jQuery UI Dialog 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Dialog
 *
 * Depends:
 *  jquery.ui.button.js
 *	jquery.ui.core.js
 *	jquery.ui.draggable.js
 *	jquery.ui.mouse.js
 *	jquery.ui.position.js
 *	jquery.ui.resizable.js
 *	jquery.ui.widget.js
 */
(function($) {

    var uiDialogClasses=
            'ui-dialog ' +
            'ui-widget ' +
            'ui-widget-content ' +
            'ui-corner-all ';

    $.widget("ui.dialog", {
        options: {
            autoOpen: true,
            buttons: {},
            closeOnEscape: true,
            closeText: 'close',
            dialogClass: '',
            draggable: true,
            hide: null,
            height: 'auto',
            maxHeight: false,
            maxWidth: false,
            minHeight: 150,
            minWidth: 150,
            modal: false,
            position: 'center',
            resizable: true,
            show: null,
            stack: true,
            title: '',
            width: 300,
            zIndex: 1000
        },
        _create: function() {
            this.originalTitle=this.element.attr('title');

            var self=this,
                    options=self.options,

                    title=options.title || self.originalTitle || '&#160;',
                    titleId=$.ui.dialog.getTitleId(self.element),

                    uiDialog=(self.uiDialog=$('<div></div>'))
                            .appendTo(document.body)
                            .hide()
                            .addClass(uiDialogClasses + options.dialogClass)
                            .css({
                        zIndex: options.zIndex
                    })
                        // setting tabIndex makes the div focusable
                        // setting outline to 0 prevents a border on focus in Mozilla
                            .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
                        (options.closeOnEscape && event.keyCode
                                && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
                    })
                            .attr({
                        role: 'dialog',
                        'aria-labelledby': titleId
                    })
                            .mousedown(function(event) {
                        self.moveToTop(false, event);
                    }),

                    uiDialogContent=self.element
                            .show()
                            .removeAttr('title')
                            .addClass(
                            'ui-dialog-content ' +
                            'ui-widget-content')
                            .appendTo(uiDialog),

                    uiDialogTitlebar=(self.uiDialogTitlebar=$('<div></div>'))
                            .addClass(
                            'ui-dialog-titlebar ' +
                            'ui-widget-header ' +
                            'ui-corner-all ' +
                            'ui-helper-clearfix'
                            )
                            .prependTo(uiDialog),

                    uiDialogTitlebarClose=$('<a href="#"></a>')
                            .addClass(
                            'ui-dialog-titlebar-close ' +
                            'ui-corner-all'
                            )
                            .attr('role', 'button')
                            .hover(
                            function() {
                                uiDialogTitlebarClose.addClass('ui-state-hover');
                            },
                            function() {
                                uiDialogTitlebarClose.removeClass('ui-state-hover');
                            }
                            )
                            .focus(function() {
                        uiDialogTitlebarClose.addClass('ui-state-focus');
                    })
                            .blur(function() {
                        uiDialogTitlebarClose.removeClass('ui-state-focus');
                    })
                            .mousedown(function(ev) {
                        ev.stopPropagation();
                    })
                            .click(function(event) {
                        self.close(event);
                        return false;
                    })
                            .appendTo(uiDialogTitlebar),

                    uiDialogTitlebarCloseText=(self.uiDialogTitlebarCloseText=$('<span></span>'))
                            .addClass(
                            'ui-icon ' +
                            'ui-icon-closethick'
                            )
                            .text(options.closeText)
                            .appendTo(uiDialogTitlebarClose),

                    uiDialogTitle=$('<span></span>')
                            .addClass('ui-dialog-title')
                            .attr('id', titleId)
                            .html(title)
                            .prependTo(uiDialogTitlebar);

            //handling of deprecated beforeclose (vs beforeClose) option
            //Ticket #4669 http://dev.jqueryui.com/ticket/4669
            //TODO: remove in 1.9pre
            if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
                options.beforeClose=options.beforeclose;
            }

            uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();

            (options.draggable && $.fn.draggable && self._makeDraggable());
            (options.resizable && $.fn.resizable && self._makeResizable());

            self._createButtons(options.buttons);
            self._isOpen=false;

            ($.fn.bgiframe && uiDialog.bgiframe());
        },
        _init: function() {
            if (this.options.autoOpen) {
                this.open();
            }
        },

        destroy: function() {
            var self=this;

            (self.overlay && self.overlay.destroy());
            self.uiDialog.hide();
            self.element
                    .unbind('.dialog')
                    .removeData('dialog')
                    .removeClass('ui-dialog-content ui-widget-content')
                    .hide().appendTo('body');
            self.uiDialog.remove();

            (self.originalTitle && self.element.attr('title', self.originalTitle));

            return self;
        },

        widget: function() {
            return this.uiDialog;
        },

        close: function(event) {
            var self=this;

            if (false === self._trigger('beforeClose', event)) {
                return;
            }

            (self.overlay && self.overlay.destroy());
            self.uiDialog.unbind('keypress.ui-dialog');

            (self.options.hide
                    ? self.uiDialog.hide(self.options.hide, function() {
                self._trigger('close', event);
            })
                    : self.uiDialog.hide() && self._trigger('close', event));

            $.ui.dialog.overlay.resize();

            self._isOpen=false;

            // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
            if (self.options.modal) {
                var maxZ=0;
                $('.ui-dialog').each(function() {
                    if (this != self.uiDialog[0]) {
                        maxZ=Math.max(maxZ, $(this).css('z-index'));
                    }
                });
                $.ui.dialog.maxZ=maxZ;
            }

            return self;
        },

        isOpen: function() {
            return this._isOpen;
        },

        // the force parameter allows us to move modal dialogs to their correct
        // position on open
        moveToTop: function(force, event) {
            var self=this,
                    options=self.options;

            if ((options.modal && !force)
                    || (!options.stack && !options.modal)) {
                return self._trigger('focus', event);
            }

            if (options.zIndex > $.ui.dialog.maxZ) {
                $.ui.dialog.maxZ=options.zIndex;
            }
            (self.overlay && self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ=++$.ui.dialog.maxZ));

            //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
            //  http://ui.jquery.com/bugs/ticket/3193
            var saveScroll={ scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
            self.uiDialog.css('z-index', ++$.ui.dialog.maxZ);
            self.element.attr(saveScroll);
            self._trigger('focus', event);

            return self;
        },

        open: function() {
            if (this._isOpen) {
                return;
            }

            var self=this,
                    options=self.options,
                    uiDialog=self.uiDialog;

            self.overlay=options.modal ? new $.ui.dialog.overlay(self) : null;
            (uiDialog.next().length && uiDialog.appendTo('body'));
            self._size();
            self._position(options.position);
            uiDialog.show(options.show);
            self.moveToTop(true);

            // prevent tabbing out of modal dialogs
            (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) {
                if (event.keyCode != $.ui.keyCode.TAB) {
                    return;
                }

                var tabbables=$(':tabbable', this),
                        first=tabbables.filter(':first'),
                        last=tabbables.filter(':last');

                if (event.target == last[0] && !event.shiftKey) {
                    first.focus(1);
                    return false;
                } else if (event.target == first[0] && event.shiftKey) {
                    last.focus(1);
                    return false;
                }
            }));

            // set focus to the first tabbable element in the content area or the first button
            // if there are no tabbable elements, set focus on the dialog itself
            $([])
                    .add(uiDialog.find('.ui-dialog-content :tabbable:first'))
                    .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first'))
                    .add(uiDialog)
                    .filter(':first')
                    .focus();

            self._trigger('open');
            self._isOpen=true;

            return self;
        },

        _createButtons: function(buttons) {
            var self=this,
                    hasButtons=false,
                    uiDialogButtonPane=$('<div></div>')
                            .addClass(
                            'ui-dialog-buttonpane ' +
                            'ui-widget-content ' +
                            'ui-helper-clearfix'
                            );

            // if we already have a button pane, remove it
            self.uiDialog.find('.ui-dialog-buttonpane').remove();

            (typeof buttons == 'object' && buttons !== null &&
             $.each(buttons, function() {
                 return !(hasButtons=true);
             }));
            if (hasButtons) {
                $.each(buttons, function(name, fn) {
                    var button=$('<button type="button"></button>')
                            .text(name)
                            .click(function() {
                        fn.apply(self.element[0], arguments);
                    })
                            .appendTo(uiDialogButtonPane);
                    ($.fn.button && button.button());
                });
                uiDialogButtonPane.appendTo(self.uiDialog);
            }
        },

        _makeDraggable: function() {
            var self=this,
                    options=self.options,
                    doc=$(document),
                    heightBeforeDrag;

            self.uiDialog.draggable({
                cancel: '.ui-dialog-content',
                handle: '.ui-dialog-titlebar',
                containment: 'document',
                start: function(event) {
                    heightBeforeDrag=options.height;
                    $(this).height($(this).height()).addClass("ui-dialog-dragging");
                    self._trigger('dragStart', event);
                },
                drag: function(event) {
                    self._trigger('drag', event);
                },
                stop: function(event, ui) {
                    options.position=[ui.position.left - doc.scrollLeft(),
                        ui.position.top - doc.scrollTop()];
                    $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
                    self._trigger('dragStop', event);
                    $.ui.dialog.overlay.resize();
                }
            });
        },

        _makeResizable: function(handles) {
            handles=(handles === undefined ? this.options.resizable : handles);
            var self=this,
                    options=self.options,
                // .ui-resizable has position: relative defined in the stylesheet
                // but dialogs have to use absolute or fixed positioning
                    position=self.uiDialog.css('position'),
                    resizeHandles=typeof handles == 'string'
                            ? handles
                            : 'n,e,s,w,se,sw,ne,nw';

            self.uiDialog.resizable({
                cancel: '.ui-dialog-content',
                containment: 'document',
                alsoResize: self.element,
                maxWidth: options.maxWidth,
                maxHeight: options.maxHeight,
                minWidth: options.minWidth,
                minHeight: self._minHeight(),
                handles: resizeHandles,
                start: function(event) {
                    $(this).addClass("ui-dialog-resizing");
                    self._trigger('resizeStart', event);
                },
                resize: function(event) {
                    self._trigger('resize', event);
                },
                stop: function(event) {
                    $(this).removeClass("ui-dialog-resizing");
                    options.height=$(this).height();
                    options.width=$(this).width();
                    self._trigger('resizeStop', event);
                    $.ui.dialog.overlay.resize();
                }
            })
                    .css('position', position)
                    .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
        },

        _minHeight: function() {
            var options=this.options;

            return (options.height == 'auto'
                    ? options.minHeight
                    : Math.min(options.minHeight, options.height));
        },

        _position: function(position) {
            var myAt=[],
                    offset=[0, 0];

            position=position || $.ui.dialog.prototype.options.position;

            // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
            //		if (typeof position == 'string' || $.isArray(position)) {
            //			myAt = $.isArray(position) ? position : position.split(' ');

            if (typeof position == 'string' || (typeof position == 'object' && '0' in position)) {
                myAt=position.split ? position.split(' ') : [position[0], position[1]];
                if (myAt.length == 1) {
                    myAt[1]=myAt[0];
                }

                $.each(['left', 'top'], function(i, offsetPosition) {
                    if (+myAt[i] == myAt[i]) {
                        offset[i]=myAt[i];
                        myAt[i]=offsetPosition;
                    }
                });
            } else if (typeof position == 'object') {
                if ('left' in position) {
                    myAt[0]='left';
                    offset[0]=position.left;
                } else if ('right' in position) {
                    myAt[0]='right';
                    offset[0]=-position.right;
                }

                if ('top' in position) {
                    myAt[1]='top';
                    offset[1]=position.top;
                } else if ('bottom' in position) {
                    myAt[1]='bottom';
                    offset[1]=-position.bottom;
                }
            }

            // need to show the dialog to get the actual offset in the position plugin
            var isVisible=this.uiDialog.is(':visible');
            if (!isVisible) {
                this.uiDialog.show();
            }
            this.uiDialog
                // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
                    .css({ top: 0, left: 0 })
                    .position({
                my: myAt.join(' '),
                at: myAt.join(' '),
                offset: offset.join(' '),
                of: window,
                collision: 'fit'
            });
            if (!isVisible) {
                this.uiDialog.hide();
            }
        },

        _setOption: function(key, value) {
            var self=this,
                    uiDialog=self.uiDialog,
                    isResizable=uiDialog.is(':data(resizable)'),
                    resize=false;

            switch (key) {
                //handling of deprecated beforeclose (vs beforeClose) option
                //Ticket #4669 http://dev.jqueryui.com/ticket/4669
                //TODO: remove in 1.9pre
                case "beforeclose":
                    key="beforeClose";
                    break;
                case "buttons":
                    self._createButtons(value);
                    break;
                case "closeText":
                    // convert whatever was passed in to a string, for text() to not throw up
                    self.uiDialogTitlebarCloseText.text("" + value);
                    break;
                case "dialogClass":
                    uiDialog
                            .removeClass(self.options.dialogClass)
                            .addClass(uiDialogClasses + value);
                    break;
                case "disabled":
                    (value
                            ? uiDialog.addClass('ui-dialog-disabled')
                            : uiDialog.removeClass('ui-dialog-disabled'));
                    break;
                case "draggable":
                    (value
                            ? self._makeDraggable()
                            : uiDialog.draggable('destroy'));
                    break;
                case "height":
                    resize=true;
                    break;
                case "maxHeight":
                    (isResizable && uiDialog.resizable('option', 'maxHeight', value));
                    resize=true;
                    break;
                case "maxWidth":
                    (isResizable && uiDialog.resizable('option', 'maxWidth', value));
                    resize=true;
                    break;
                case "minHeight":
                    (isResizable && uiDialog.resizable('option', 'minHeight', value));
                    resize=true;
                    break;
                case "minWidth":
                    (isResizable && uiDialog.resizable('option', 'minWidth', value));
                    resize=true;
                    break;
                case "position":
                    self._position(value);
                    break;
                case "resizable":
                    // currently resizable, becoming non-resizable
                    (isResizable && !value && uiDialog.resizable('destroy'));

                    // currently resizable, changing handles
                    (isResizable && typeof value == 'string' &&
                     uiDialog.resizable('option', 'handles', value));

                    // currently non-resizable, becoming resizable
                    (isResizable || (value !== false && self._makeResizable(value)));
                    break;
                case "title":
                    // convert whatever was passed in o a string, for html() to not throw up
                    $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
                    break;
                case "width":
                    resize=true;
                    break;
            }

            $.Widget.prototype._setOption.apply(self, arguments);
            (resize && self._size());
        },

        _size: function() {
            /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
             * divs will both have width and height set, so we need to reset them
             */
            var options=this.options;

            // reset content sizing
            this.element.css({
                height: 0,
                minHeight: 0,
                width: 'auto'
            });

            // reset wrapper sizing
            // determine the height of all the non-content elements
            var nonContentHeight=this.uiDialog.css({
                height: 'auto',
                width: options.width
            })
                    .height();

            this.element.css(options.height == 'auto'
                    ? {
                minHeight: Math.max(options.minHeight - nonContentHeight, 0),
                height: 'auto'
            }
                    : {
                height: Math.max(options.height - nonContentHeight, 0)
            });

            (this.uiDialog.is(':data(resizable)') &&
             this.uiDialog.resizable('option', 'minHeight', this._minHeight()));
        }
    });

    $.extend($.ui.dialog, {
        version: "1.8rc1",

        uuid: 0,
        maxZ: 0,

        getTitleId: function($el) {
            return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
        },

        overlay: function(dialog) {
            this.$el=$.ui.dialog.overlay.create(dialog);
        }
    });

    $.extend($.ui.dialog.overlay, {
        instances: [],
        maxZ: 0,
        events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
                function(event) {
                    return event + '.dialog-overlay';
                }).join(' '),
        create: function(dialog) {
            if (this.instances.length === 0) {
                // prevent use of anchors and inputs
                // we use a setTimeout in case the overlay is created from an
                // event that we're going to be cancelling (see #2804)
                setTimeout(function() {
                    // handle $(el).dialog().dialog('close') (see #4065)
                    if ($.ui.dialog.overlay.instances.length) {
                        $(document).bind($.ui.dialog.overlay.events, function(event) {
                            var dialogZ=$(event.target).parents('.ui-dialog').css('zIndex') || 0;
                            return (dialogZ > $.ui.dialog.overlay.maxZ);
                        });
                    }
                }, 1);

                // allow closing by pressing the escape key
                $(document).bind('keydown.dialog-overlay', function(event) {
                    (dialog.options.closeOnEscape && event.keyCode
                            && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
                });

                // handle window resize
                $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
            }

            var $el=$('<div></div>').appendTo(document.body)
                    .addClass('ui-widget-overlay').css({
                width: this.width(),
                height: this.height()
            });

            ($.fn.bgiframe && $el.bgiframe());

            this.instances.push($el);
            return $el;
        },

        destroy: function($el) {
            this.instances.splice($.inArray(this.instances, $el), 1);

            if (this.instances.length === 0) {
                $([document, window]).unbind('.dialog-overlay');
            }

            $el.remove();

            // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
            var maxZ=0;
            $.each(this.instances, function() {
                maxZ=Math.max(maxZ, this.css('z-index'));
            });
            this.maxZ=maxZ;
        },

        height: function() {
            // handle IE 6
            if ($.browser.msie && $.browser.version < 7) {
                var scrollHeight=Math.max(
                        document.documentElement.scrollHeight,
                        document.body.scrollHeight
                        );
                var offsetHeight=Math.max(
                        document.documentElement.offsetHeight,
                        document.body.offsetHeight
                        );

                if (scrollHeight < offsetHeight) {
                    return $(window).height() + 'px';
                } else {
                    return scrollHeight + 'px';
                }
                // handle "good" browsers
            } else {
                return $(document).height() + 'px';
            }
        },

        width: function() {
            // handle IE 6
            if ($.browser.msie && $.browser.version < 7) {
                var scrollWidth=Math.max(
                        document.documentElement.scrollWidth,
                        document.body.scrollWidth
                        );
                var offsetWidth=Math.max(
                        document.documentElement.offsetWidth,
                        document.body.offsetWidth
                        );

                if (scrollWidth < offsetWidth) {
                    return $(window).width() + 'px';
                } else {
                    return scrollWidth + 'px';
                }
                // handle "good" browsers
            } else {
                return $(document).width() + 'px';
            }
        },

        resize: function() {
            /* If the dialog is draggable and the user drags it past the
             * right edge of the window, the document becomes wider so we
             * need to stretch the overlay. If the user then drags the
             * dialog back to the left, the document will become narrower,
             * so we need to shrink the overlay to the appropriate size.
             * This is handled by shrinking the overlay before setting it
             * to the full document size.
             */
            var $overlays=$([]);
            $.each($.ui.dialog.overlay.instances, function() {
                $overlays=$overlays.add(this);
            });

            $overlays.css({
                width: 0,
                height: 0
            }).css({
                width: $.ui.dialog.overlay.width(),
                height: $.ui.dialog.overlay.height()
            });
        }
    });

    $.extend($.ui.dialog.overlay.prototype, {
        destroy: function() {
            $.ui.dialog.overlay.destroy(this.$el);
        }
    });

})(jQuery);
/*
 * jQuery UI Position 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Position
 */
(function($) {

    $.ui=$.ui || {};

    var horizontalPositions=/left|center|right/,
            horizontalDefault='center',
            verticalPositions=/top|center|bottom/,
            verticalDefault='center',
            _position=$.fn.position;

    $.fn.position=function(options) {
        if (!options || !options.of) {
            return _position.apply(this, arguments);
        }

        // make a copy, we don't want to modify arguments
        options=$.extend({}, options);

        var target=$(options.of),
                collision=(options.collision || 'flip').split(' '),
                offset=options.offset ? options.offset.split(' ') : [0, 0],
                targetWidth,
                targetHeight,
                basePosition;

        if (options.of.nodeType === 9) {
            targetWidth=target.width();
            targetHeight=target.height();
            basePosition={ top: 0, left: 0 };
        } else if (options.of.scrollTo && options.of.document) {
            targetWidth=target.width();
            targetHeight=target.height();
            basePosition={ top: target.scrollTop(), left: target.scrollLeft() };
        } else if (options.of.preventDefault) {
            // force left top to allow flipping
            options.at='left top';
            targetWidth=targetHeight=0;
            basePosition={ top: options.of.pageY, left: options.of.pageX };
        } else {
            targetWidth=target.outerWidth();
            targetHeight=target.outerHeight();
            basePosition=target.offset();
        }

        // force my and at to have valid horizontal and veritcal positions
        // if a value is missing or invalid, it will be converted to center
        $.each(['my', 'at'], function() {
            var pos=(options[this] || '').split(' ');
            pos=pos.length == 1
                    ? horizontalPositions.test(pos[0])
                    ? pos.concat([verticalDefault])
                    : verticalPositions.test(pos[0])
                    ? [horizontalDefault].concat(pos)
                    : [horizontalDefault, verticalDefault]
                    : pos;
            pos[0]=horizontalPositions.test(pos[0]) ? pos[0] : horizontalDefault;
            pos[1]=verticalPositions.test(pos[1]) ? pos[1] : verticalDefault;
            options[this]=pos;
        });

        // normalize collision option
        if (collision.length == 1) {
            collision[1]=collision[0];
        }

        // normalize offset option
        offset[0]=parseInt(offset[0], 10) || 0;
        if (offset.length == 1) {
            offset[1]=offset[0];
        }
        offset[1]=parseInt(offset[1], 10) || 0;

        switch (options.at[0]) {
            case 'right':
                basePosition.left+=targetWidth;
                break;
            case horizontalDefault:
                basePosition.left+=targetWidth / 2;
                break;
        }

        switch (options.at[1]) {
            case 'bottom':
                basePosition.top+=targetHeight;
                break;
            case verticalDefault:
                basePosition.top+=targetHeight / 2;
                break;
        }

        basePosition.left+=offset[0];
        basePosition.top+=offset[1];

        return this.each(function() {
            var elem=$(this),
                    elemWidth=elem.outerWidth(),
                    elemHeight=elem.outerHeight(),
                    position=$.extend({}, basePosition),
                    over,
                    myOffset,
                    atOffset;

            switch (options.my[0]) {
                case 'right':
                    position.left-=elemWidth;
                    break;
                case horizontalDefault:
                    position.left-=elemWidth / 2;
                    break;
            }

            switch (options.my[1]) {
                case 'bottom':
                    position.top-=elemHeight;
                    break;
                case verticalDefault:
                    position.top-=elemHeight / 2;
                    break;
            }

            $.each(['left', 'top'], function(i, dir) {
                ($.ui.position[collision[i]] &&
                 $.ui.position[collision[i]][dir](position, {
                     targetWidth: targetWidth,
                     targetHeight: targetHeight,
                     elemWidth: elemWidth,
                     elemHeight: elemHeight,
                     offset: offset,
                     my: options.my,
                     at: options.at
                 }));
            });

            ($.fn.bgiframe && elem.bgiframe());
            elem.offset($.extend(position, { using: options.using }));
        });
    };

    $.ui.position={
        fit: {
            left: function(position, data) {
                var over=position.left + data.elemWidth - $(window).width() - $(window).scrollLeft();
                position.left=over > 0 ? position.left - over : Math.max(0, position.left);
            },
            top: function(position, data) {
                var over=position.top + data.elemHeight - $(window).height() - $(window).scrollTop();
                position.top=over > 0 ? position.top - over : Math.max(0, position.top);
            }
        },

        flip: {
            left: function(position, data) {
                if (data.at[0] == 'center')
                    return;
                var over=position.left + data.elemWidth - $(window).width() - $(window).scrollLeft(),
                        myOffset=data.my[0] == 'left' ? -data.elemWidth : data.my[0] == 'right' ? data.elemWidth : 0,
                        offset=-2 * data.offset[0];
                position.left+=position.left < 0 ? myOffset + data.targetWidth + offset : over > 0 ? myOffset - data.targetWidth + offset : 0;
            },
            top: function(position, data) {
                if (data.at[1] == 'center')
                    return;
                var over=position.top + data.elemHeight - $(window).height() - $(window).scrollTop(),
                        myOffset=data.my[1] == 'top' ? -data.elemHeight : data.my[1] == 'bottom' ? data.elemHeight : 0,
                        atOffset=data.at[1] == 'top' ? data.targetHeight : -data.targetHeight,
                        offset=-2 * data.offset[1];
                position.top+=position.top < 0 ? myOffset + data.targetHeight + offset : over > 0 ? myOffset + atOffset + offset : 0;
            }
        }
    };

    // offset setter from jQuery 1.4
    if (!$.offset.setOffset) {
        $.offset.setOffset=function(elem, options) {
            // set position first, in-case top/left are set even on static elem
            if (/static/.test(jQuery.curCSS(elem, 'position'))) {
                elem.style.position='relative';
            }
            var curElem=jQuery(elem),
                    curOffset=curElem.offset(),
                    curTop=parseInt(jQuery.curCSS(elem, 'top', true), 10) || 0,
                    curLeft=parseInt(jQuery.curCSS(elem, 'left', true), 10) || 0,
                    props={
                        top:  (options.top - curOffset.top) + curTop,
                        left: (options.left - curOffset.left) + curLeft
                    };

            if ('using' in options) {
                options.using.call(elem, props);
            } else {
                curElem.css(props);
            }
        };

        var _offset=$.fn.offset;
        $.fn.offset=function(options) {
            var elem=this[0];
            if (!elem || !elem.ownerDocument) {
                return null;
            }
            if (options) {
                return this.each(function() {
                    $.offset.setOffset(this, options);
                });
            }
            return _offset.call(this);
        };
    }

})(jQuery);
/*
 * jQuery UI Progressbar 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Progressbar
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.progressbar", {
        options: {
            value: 0
        },
        _create: function() {

            this.element
                    .addClass("ui-progressbar"
                    + " ui-widget"
                    + " ui-widget-content"
                    + " ui-corner-all")
                    .attr({
                role: "progressbar",
                "aria-valuemin": this._valueMin(),
                "aria-valuemax": this._valueMax(),
                "aria-valuenow": this._value()
            });

            this.valueDiv=$('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);

            this._refreshValue();

        },

        destroy: function() {

            this.element
                    .removeClass("ui-progressbar"
                    + " ui-widget"
                    + " ui-widget-content"
                    + " ui-corner-all")
                    .removeAttr("role")
                    .removeAttr("aria-valuemin")
                    .removeAttr("aria-valuemax")
                    .removeAttr("aria-valuenow")
                    .removeData("progressbar")
                    .unbind(".progressbar");

            this.valueDiv.remove();

            $.Widget.prototype.destroy.apply(this, arguments);

            return this;
        },

        value: function(newValue) {
            if (newValue === undefined) {
                return this._value();
            }

            this._setOption('value', newValue);
            return this;
        },

        _setOption: function(key, value) {

            switch (key) {
                case 'value':
                    this.options.value=value;
                    this._refreshValue();
                    this._trigger('change', null, {});
                    break;
            }

            $.Widget.prototype._setOption.apply(this, arguments);

        },

        _value: function() {
            var val=this.options.value;
            // normalize invalid value
            if (typeof val != "number")
                val=0;
            if (val < this._valueMin()) val=this._valueMin();
            if (val > this._valueMax()) val=this._valueMax();

            return val;

        },

        _valueMin: function() {
            var valueMin=0;
            return valueMin;
        },

        _valueMax: function() {
            var valueMax=100;
            return valueMax;
        },

        _refreshValue: function() {
            var value=this.value();
            this.valueDiv[value == this._valueMax() ? 'addClass' : 'removeClass']("ui-corner-right");
            this.valueDiv.width(value + '%');
            this.element.attr("aria-valuenow", value);
        }

    });

    $.extend($.ui.progressbar, {
        version: "1.8rc1"
    });

})(jQuery);
/*
 * jQuery UI Slider 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */

(function($) {

    // number of pages in a slider
    // (how many times can you page up/down to go through the whole range)
    var numPages=5;

    $.widget("ui.slider", $.ui.mouse, {
        options: {
            animate: false,
            distance: 0,
            max: 100,
            min: 0,
            orientation: 'horizontal',
            range: false,
            step: 1,
            value: 0,
            values: null
        },
        _create: function() {

            var self=this, o=this.options;
            this._keySliding=false;
            this._animateOff=true;
            this._handleIndex=null;
            this._detectOrientation();
            this._mouseInit();

            this.element
                    .addClass("ui-slider"
                    + " ui-slider-" + this.orientation
                    + " ui-widget"
                    + " ui-widget-content"
                    + " ui-corner-all");

            if (o.disabled) {
                this.element.addClass('ui-slider-disabled ui-disabled');
            }

            this.range=$([]);

            if (o.range) {

                if (o.range === true) {
                    this.range=$('<div></div>');
                    if (!o.values) o.values=[this._valueMin(), this._valueMin()];
                    if (o.values.length && o.values.length != 2) {
                        o.values=[o.values[0], o.values[0]];
                    }
                } else {
                    this.range=$('<div></div>');
                }

                this.range
                        .appendTo(this.element)
                        .addClass("ui-slider-range");

                if (o.range == "min" || o.range == "max") {
                    this.range.addClass("ui-slider-range-" + o.range);
                }

                // note: this isn't the most fittingly semantic framework class for this element,
                // but worked best visually with a variety of themes
                this.range.addClass("ui-widget-header");

            }

            if ($(".ui-slider-handle", this.element).length == 0)
                $('<a href="#"></a>')
                        .appendTo(this.element)
                        .addClass("ui-slider-handle");

            if (o.values && o.values.length) {
                while ($(".ui-slider-handle", this.element).length < o.values.length)
                    $('<a href="#"></a>')
                            .appendTo(this.element)
                            .addClass("ui-slider-handle");
            }

            this.handles=$(".ui-slider-handle", this.element)
                    .addClass("ui-state-default"
                    + " ui-corner-all");

            this.handle=this.handles.eq(0);

            this.handles.add(this.range).filter("a")
                    .click(function(event) {
                event.preventDefault();
            })
                    .hover(function() {
                if (!o.disabled) {
                    $(this).addClass('ui-state-hover');
                }
            }, function() {
                $(this).removeClass('ui-state-hover');
            })
                    .focus(function() {
                if (!o.disabled) {
                    $(".ui-slider .ui-state-focus").removeClass('ui-state-focus');
                    $(this).addClass('ui-state-focus');
                } else {
                    $(this).blur();
                }
            })
                    .blur(function() {
                $(this).removeClass('ui-state-focus');
            });

            this.handles.each(function(i) {
                $(this).data("index.ui-slider-handle", i);
            });

            this.handles.keydown(function(event) {

                var ret=true;

                var index=$(this).data("index.ui-slider-handle");

                if (self.options.disabled)
                    return;

                switch (event.keyCode) {
                    case $.ui.keyCode.HOME:
                    case $.ui.keyCode.END:
                    case $.ui.keyCode.PAGE_UP:
                    case $.ui.keyCode.PAGE_DOWN:
                    case $.ui.keyCode.UP:
                    case $.ui.keyCode.RIGHT:
                    case $.ui.keyCode.DOWN:
                    case $.ui.keyCode.LEFT:
                        ret=false;
                        if (!self._keySliding) {
                            self._keySliding=true;
                            $(this).addClass("ui-state-active");
                            self._start(event, index);
                        }
                        break;
                }

                var curVal, newVal, step=self._step();
                if (self.options.values && self.options.values.length) {
                    curVal=newVal=self.values(index);
                } else {
                    curVal=newVal=self.value();
                }

                switch (event.keyCode) {
                    case $.ui.keyCode.HOME:
                        newVal=self._valueMin();
                        break;
                    case $.ui.keyCode.END:
                        newVal=self._valueMax();
                        break;
                    case $.ui.keyCode.PAGE_UP:
                        newVal=curVal + ((self._valueMax() - self._valueMin()) / numPages);
                        break;
                    case $.ui.keyCode.PAGE_DOWN:
                        newVal=curVal - ((self._valueMax() - self._valueMin()) / numPages);
                        break;
                    case $.ui.keyCode.UP:
                    case $.ui.keyCode.RIGHT:
                        if (curVal == self._valueMax()) return;
                        newVal=curVal + step;
                        break;
                    case $.ui.keyCode.DOWN:
                    case $.ui.keyCode.LEFT:
                        if (curVal == self._valueMin()) return;
                        newVal=curVal - step;
                        break;
                }

                self._slide(event, index, newVal);

                return ret;

            }).keyup(function(event) {

                var index=$(this).data("index.ui-slider-handle");

                if (self._keySliding) {
                    self._stop(event, index);
                    self._change(event, index);
                    self._keySliding=false;
                    $(this).removeClass("ui-state-active");
                }

            });

            this._refreshValue();

            this._animateOff=false;

        },

        destroy: function() {

            this.handles.remove();
            this.range.remove();

            this.element
                    .removeClass("ui-slider"
                    + " ui-slider-horizontal"
                    + " ui-slider-vertical"
                    + " ui-slider-disabled"
                    + " ui-widget"
                    + " ui-widget-content"
                    + " ui-corner-all")
                    .removeData("slider")
                    .unbind(".slider");

            this._mouseDestroy();

            return this;
        },

        _mouseCapture: function(event) {

            var o=this.options;

            if (o.disabled)
                return false;

            this.elementSize={
                width: this.element.outerWidth(),
                height: this.element.outerHeight()
            };
            this.elementOffset=this.element.offset();

            var position={ x: event.pageX, y: event.pageY };
            var normValue=this._normValueFromMouse(position);

            var distance=this._valueMax() - this._valueMin() + 1, closestHandle;
            var self=this, index;
            this.handles.each(function(i) {
                var thisDistance=Math.abs(normValue - self.values(i));
                if (distance > thisDistance) {
                    distance=thisDistance;
                    closestHandle=$(this);
                    index=i;
                }
            });

            // workaround for bug #3736 (if both handles of a range are at 0,
            // the first is always used as the one with least distance,
            // and moving it is obviously prevented by preventing negative ranges)
            if (o.range == true && this.values(1) == o.min) {
                closestHandle=$(this.handles[++index]);
            }

            this._start(event, index);

            self._handleIndex=index;

            closestHandle
                    .addClass("ui-state-active")
                    .focus();

            var offset=closestHandle.offset();
            var mouseOverHandle=!$(event.target).parents().andSelf().is('.ui-slider-handle');
            this._clickOffset=mouseOverHandle ? { left: 0, top: 0 } : {
                left: event.pageX - offset.left - (closestHandle.width() / 2),
                top: event.pageY - offset.top
                        - (closestHandle.height() / 2)
                        - (parseInt(closestHandle.css('borderTopWidth'), 10) || 0)
                        - (parseInt(closestHandle.css('borderBottomWidth'), 10) || 0)
                        + (parseInt(closestHandle.css('marginTop'), 10) || 0)
            };

            normValue=this._normValueFromMouse(position);
            this._slide(event, index, normValue);
            this._animateOff=true;
            return true;

        },

        _mouseStart: function(event) {
            return true;
        },

        _mouseDrag: function(event) {

            var position={ x: event.pageX, y: event.pageY };
            var normValue=this._normValueFromMouse(position);

            this._slide(event, this._handleIndex, normValue);

            return false;

        },

        _mouseStop: function(event) {

            this.handles.removeClass("ui-state-active");
            this._stop(event, this._handleIndex);
            this._change(event, this._handleIndex);
            this._handleIndex=null;
            this._clickOffset=null;

            this._animateOff=false;
            return false;

        },

        _detectOrientation: function() {
            this.orientation=this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';
        },

        _normValueFromMouse: function(position) {

            var pixelTotal, pixelMouse;
            if ('horizontal' == this.orientation) {
                pixelTotal=this.elementSize.width;
                pixelMouse=position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);
            } else {
                pixelTotal=this.elementSize.height;
                pixelMouse=position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);
            }

            var percentMouse=(pixelMouse / pixelTotal);
            if (percentMouse > 1) percentMouse=1;
            if (percentMouse < 0) percentMouse=0;
            if ('vertical' == this.orientation)
                percentMouse=1 - percentMouse;

            var valueTotal=this._valueMax() - this._valueMin(),
                    valueMouse=percentMouse * valueTotal,
                    valueMouseModStep=valueMouse % this.options.step,
                    normValue=this._valueMin() + valueMouse - valueMouseModStep;

            if (valueMouseModStep > (this.options.step / 2))
                normValue+=this.options.step;

            // Since JavaScript has problems with large floats, round
            // the final value to 5 digits after the decimal point (see #4124)
            return parseFloat(normValue.toFixed(5));

        },

        _start: function(event, index) {
            var uiHash={
                handle: this.handles[index],
                value: this.value()
            };
            if (this.options.values && this.options.values.length) {
                uiHash.value=this.values(index);
                uiHash.values=this.values();
            }
            this._trigger("start", event, uiHash);
        },

        _slide: function(event, index, newVal) {

            var handle=this.handles[index];

            if (this.options.values && this.options.values.length) {

                var otherVal=this.values(index ? 0 : 1);

                if ((this.options.values.length == 2 && this.options.range === true) &&
                    ((index == 0 && newVal > otherVal) || (index == 1 && newVal < otherVal))) {
                    newVal=otherVal;
                }

                if (newVal != this.values(index)) {
                    var newValues=this.values();
                    newValues[index]=newVal;
                    // A slide can be canceled by returning false from the slide callback
                    var allowed=this._trigger("slide", event, {
                        handle: this.handles[index],
                        value: newVal,
                        values: newValues
                    });
                    var otherVal=this.values(index ? 0 : 1);
                    if (allowed !== false) {
                        this.values(index, newVal, true);
                    }
                }

            } else {

                if (newVal != this.value()) {
                    // A slide can be canceled by returning false from the slide callback
                    var allowed=this._trigger("slide", event, {
                        handle: this.handles[index],
                        value: newVal
                    });
                    if (allowed !== false) {
                        this.value(newVal);
                    }

                }

            }

        },

        _stop: function(event, index) {
            var uiHash={
                handle: this.handles[index],
                value: this.value()
            };
            if (this.options.values && this.options.values.length) {
                uiHash.value=this.values(index);
                uiHash.values=this.values();
            }
            this._trigger("stop", event, uiHash);
        },

        _change: function(event, index) {
            var uiHash={
                handle: this.handles[index],
                value: this.value()
            };
            if (this.options.values && this.options.values.length) {
                uiHash.value=this.values(index);
                uiHash.values=this.values();
            }
            this._trigger("change", event, uiHash);
        },

        value: function(newValue) {

            if (arguments.length) {
                this.options.value=this._trimValue(newValue);
                this._refreshValue();
                this._change(null, 0);
            }

            return this._value();

        },

        values: function(index, newValue) {

            if (arguments.length > 1) {
                this.options.values[index]=this._trimValue(newValue);
                this._refreshValue();
                this._change(null, index);
            }

            if (arguments.length) {
                if ($.isArray(arguments[0])) {
                    var vals=this.options.values, newValues=arguments[0];
                    for (var i=0, l=vals.length; i < l; i++) {
                        vals[i]=this._trimValue(newValues[i]);
                        this._change(null, i);
                    }
                    this._refreshValue();
                } else {
                    if (this.options.values && this.options.values.length) {
                        return this._values(index);
                    } else {
                        return this.value();
                    }
                }
            } else {
                return this._values();
            }

        },

        _setOption: function(key, value) {

            $.Widget.prototype._setOption.apply(this, arguments);

            switch (key) {
                case 'disabled':
                    if (value) {
                        this.handles.filter(".ui-state-focus").blur();
                        this.handles.removeClass("ui-state-hover");
                        this.handles.attr("disabled", "disabled");
                        this.element.addClass("ui-disabled");
                    } else {
                        this.handles.removeAttr("disabled");
                        this.element.removeClass("ui-disabled");
                    }
                case 'orientation':

                    this._detectOrientation();

                    this.element
                            .removeClass("ui-slider-horizontal ui-slider-vertical")
                            .addClass("ui-slider-" + this.orientation);
                    this._refreshValue();
                    break;
                case 'value':
                    this._animateOff=true;
                    this._refreshValue();
                    this._animateOff=false;
                    break;
                case 'values':
                    this._animateOff=true;
                    this._refreshValue();
                    this._animateOff=false;
                    break;
            }

        },

        _step: function() {
            var step=this.options.step;
            return step;
        },

        _value: function() {
            //internal value getter
            // _value() returns value trimmed by min and max
            var val=this.options.value;
            val=this._trimValue(val);

            return val;
        },

        _values: function(index) {
            //internal values getter
            // _values() returns array of values trimmed by min and max
            // _values(index) returns single value trimmed by min and max

            if (arguments.length) {
                var val=this.options.values[index];
                val=this._trimValue(val);

                return val;
            } else {
                // .slice() creates a copy of the array
                // this copy gets trimmed by min and max and then returned
                var vals=this.options.values.slice();
                for (var i=0, l=vals.length; i < l; i++) {
                    vals[i]=this._trimValue(vals[i]);
                }

                return vals;
            }

        },

        _trimValue: function(val) {
            if (val < this._valueMin()) val=this._valueMin();
            if (val > this._valueMax()) val=this._valueMax();

            return val;
        },

        _valueMin: function() {
            var valueMin=this.options.min;
            return valueMin;
        },

        _valueMax: function() {
            var valueMax=this.options.max;
            return valueMax;
        },

        _refreshValue: function() {

            var oRange=this.options.range, o=this.options, self=this;
            var animate=(!this._animateOff) ? o.animate : false;

            if (this.options.values && this.options.values.length) {
                var vp0, vp1;
                this.handles.each(function(i, j) {
                    var valPercent=(self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
                    var _set={};
                    _set[self.orientation == 'horizontal' ? 'left' : 'bottom']=valPercent + '%';
                    $(this).stop(1, 1)[animate ? 'animate' : 'css'](_set, o.animate);
                    if (self.options.range === true) {
                        if (self.orientation == 'horizontal') {
                            (i == 0) && self.range.stop(1, 1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);
                            (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
                        } else {
                            (i == 0) && self.range.stop(1, 1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);
                            (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
                        }
                    }
                    lastValPercent=valPercent;
                });
            } else {
                var value=this.value(),
                        valueMin=this._valueMin(),
                        valueMax=this._valueMax(),
                        valPercent=valueMax != valueMin
                                ? (value - valueMin) / (valueMax - valueMin) * 100
                                : 0;
                var _set={};
                _set[self.orientation == 'horizontal' ? 'left' : 'bottom']=valPercent + '%';
                this.handle.stop(1, 1)[animate ? 'animate' : 'css'](_set, o.animate);

                (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1, 1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate);
                (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
                (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1, 1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate);
                (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
            }

        }

    });

    $.extend($.ui.slider, {
        version: "1.8rc1",
        eventPrefix: "slide"
    });

})(jQuery);
/*
 * jQuery UI Tabs 1.8rc1
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Tabs
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function($) {

    var tabId=0;

    $.widget("ui.tabs", {
        options: {
            add: null,
            ajaxOptions: null,
            cache: false,
            cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
            collapsible: false,
            disable: null,
            disabled: [],
            enable: null,
            event: 'click',
            fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
            idPrefix: 'ui-tabs-',
            load: null,
            panelTemplate: '<div></div>',
            remove: null,
            select: null,
            show: null,
            spinner: '<em>Loading&#8230;</em>',
            tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
        },
        _create: function() {
            this._tabify(true);
        },

        _setOption: function(key, value) {
            if (key == 'selected') {
                if (this.options.collapsible && value == this.options.selected) {
                    return;
                }
                this.select(value);
            }
            else {
                this.options[key]=value;
                this._tabify();
            }
        },

        _tabId: function(a) {
            return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
                   this.options.idPrefix + (++tabId);
        },

        _sanitizeSelector: function(hash) {
            return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
        },

        _cookie: function() {
            var cookie=this.cookie || (this.cookie=this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
            return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
        },

        _ui: function(tab, panel) {
            return {
                tab: tab,
                panel: panel,
                index: this.anchors.index(tab)
            };
        },

        _cleanup: function() {
            // restore all former loading tabs labels
            this.lis.filter('.ui-state-processing').removeClass('ui-state-processing')
                    .find('span:data(label.tabs)')
                    .each(function() {
                var el=$(this);
                el.html(el.data('label.tabs')).removeData('label.tabs');
            });
        },

        _tabify: function(init) {

            this.list=this.element.find('ol,ul').eq(0);
            this.lis=$('li:has(a[href])', this.list);
            this.anchors=this.lis.map(function() {
                return $('a', this)[0];
            });
            this.panels=$([]);

            var self=this, o=this.options;

            var fragmentId=/^#.+/; // Safari 2 reports '#' for an empty hash
            this.anchors.each(function(i, a) {
                var href=$(a).attr('href');

                // For dynamically created HTML that contains a hash as href IE < 8 expands
                // such href to the full page url with hash and then misinterprets tab as ajax.
                // Same consideration applies for an added tab with a fragment identifier
                // since a[href=#fragment-identifier] does unexpectedly not match.
                // Thus normalize href attribute...
                var hrefBase=href.split('#')[0], baseEl;
                if (hrefBase && (hrefBase === location.toString().split('#')[0] ||
                                 (baseEl=$('base')[0]) && hrefBase === baseEl.href)) {
                    href=a.hash;
                    a.href=href;
                }

                // inline tab
                if (fragmentId.test(href)) {
                    self.panels=self.panels.add(self._sanitizeSelector(href));
                }

                // remote tab
                else if (href != '#') { // prevent loading the page itself if href is just "#"
                    $.data(a, 'href.tabs', href); // required for restore on destroy

                    // TODO until #3808 is fixed strip fragment identifier from url
                    // (IE fails to load from such url)
                    $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data

                    var id=self._tabId(a);
                    a.href='#' + id;
                    var $panel=$('#' + id);
                    if (!$panel.length) {
                        $panel=$(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
                                .insertAfter(self.panels[i - 1] || self.list);
                        $panel.data('destroy.tabs', true);
                    }
                    self.panels=self.panels.add($panel);
                }

                // invalid tab href
                else {
                    o.disabled.push(i);
                }
            });

            // initialization from scratch
            if (init) {

                // attach necessary classes for styling
                this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
                this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
                this.lis.addClass('ui-state-default ui-corner-top');
                this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');

                // Selected tab
                // use "selected" option or try to retrieve:
                // 1. from fragment identifier in url
                // 2. from cookie
                // 3. from selected class attribute on <li>
                if (o.selected === undefined) {
                    if (location.hash) {
                        this.anchors.each(function(i, a) {
                            if (a.hash == location.hash) {
                                o.selected=i;
                                return false; // break
                            }
                        });
                    }
                    if (typeof o.selected != 'number' && o.cookie) {
                        o.selected=parseInt(self._cookie(), 10);
                    }
                    if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) {
                        o.selected=this.lis.index(this.lis.filter('.ui-tabs-selected'));
                    }
                    o.selected=o.selected || this.lis.length ? 0 : -1;
                }
                else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release
                    o.selected=-1;
                }

                // sanity check - default to first tab...
                o.selected=((o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0) ? o.selected : 0;

                // Take disabling tabs via class attribute from HTML
                // into account and update option properly.
                // A selected tab cannot become disabled.
                o.disabled=$.unique(o.disabled.concat(
                        $.map(this.lis.filter('.ui-state-disabled'),
                                function(n, i) {
                                    return self.lis.index(n);
                                })
                        )).sort();

                if ($.inArray(o.selected, o.disabled) != -1) {
                    o.disabled.splice($.inArray(o.selected, o.disabled), 1);
                }

                // highlight selected tab
                this.panels.addClass('ui-tabs-hide');
                this.lis.removeClass('ui-tabs-selected ui-state-active');
                if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list
                    this.panels.eq(o.selected).removeClass('ui-tabs-hide');
                    this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active');

                    // seems to be expected behavior that the show callback is fired
                    self.element.queue("tabs", function() {
                        self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected]));
                    });

                    this.load(o.selected);
                }

                // clean up to avoid memory leaks in certain versions of IE 6
                $(window).bind('unload', function() {
                    self.lis.add(self.anchors).unbind('.tabs');
                    self.lis=self.anchors=self.panels=null;
                });

            }
            // update selected after add/remove
            else {
                o.selected=this.lis.index(this.lis.filter('.ui-tabs-selected'));
            }

            // update collapsible
            this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible');

            // set or update cookie after init and add/remove respectively
            if (o.cookie) {
                this._cookie(o.selected, o.cookie);
            }

            // disable tabs
            for (var i=0, li; (li=this.lis[i]); i++) {
                $(li)[$.inArray(i, o.disabled) != -1 &&
                      !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');
            }

            // reset cache if switching from cached to not cached
            if (o.cache === false) {
                this.anchors.removeData('cache.tabs');
            }

            // remove all handlers before, tabify may run on existing tabs after add or option change
            this.lis.add(this.anchors).unbind('.tabs');

            if (o.event != 'mouseover') {
                var addState=function(state, el) {
                    if (el.is(':not(.ui-state-disabled)')) {
                        el.addClass('ui-state-' + state);
                    }
                };
                var removeState=function(state, el) {
                    el.removeClass('ui-state-' + state);
                };
                this.lis.bind('mouseover.tabs', function() {
                    addState('hover', $(this));
                });
                this.lis.bind('mouseout.tabs', function() {
                    removeState('hover', $(this));
                });
                this.anchors.bind('focus.tabs', function() {
                    addState('focus', $(this).closest('li'));
                });
                this.anchors.bind('blur.tabs', function() {
                    removeState('focus', $(this).closest('li'));
                });
            }

            // set up animations
            var hideFx, showFx;
            if (o.fx) {
                if ($.isArray(o.fx)) {
                    hideFx=o.fx[0];
                    showFx=o.fx[1];
                }
                else {
                    hideFx=showFx=o.fx;
                }
            }

            // Reset certain styles left over from animation
            // and prevent IE's ClearType bug...
            function resetStyle($el, fx) {
                $el.css({ display: '' });
                if (!$.support.opacity && fx.opacity) {
                    $el[0].style.removeAttribute('filter');
                }
            }

            // Show a tab...
            var showTab=showFx ?
                        function(clicked, $show) {
                            $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
                            $show.hide().removeClass('ui-tabs-hide')// avoid flicker that way
                                    .animate(showFx, showFx.duration || 'normal', function() {
                                resetStyle($show, showFx);
                                self._trigger('show', null, self._ui(clicked, $show[0]));
                            });
                        } :
                        function(clicked, $show) {
                            $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
                            $show.removeClass('ui-tabs-hide');
                            self._trigger('show', null, self._ui(clicked, $show[0]));
                        };

            // Hide a tab, $show is optional...
            var hideTab=hideFx ?
                        function(clicked, $hide) {
                            $hide.animate(hideFx, hideFx.duration || 'normal', function() {
                                self.lis.removeClass('ui-tabs-selected ui-state-active');
                                $hide.addClass('ui-tabs-hide');
                                resetStyle($hide, hideFx);
                                self.element.dequeue("tabs");
                            });
                        } :
                        function(clicked, $hide, $show) {
                            self.lis.removeClass('ui-tabs-selected ui-state-active');
                            $hide.addClass('ui-tabs-hide');
                            self.element.dequeue("tabs");
                        };

            // attach tab event handler, unbind to avoid duplicates from former tabifying...
            this.anchors.bind(o.event + '.tabs', function() {
                var el=this, $li=$(this).closest('li'), $hide=self.panels.filter(':not(.ui-tabs-hide)'),
                        $show=$(self._sanitizeSelector(this.hash));

                // If tab is already selected and not collapsible or tab disabled or
                // or is already loading or click callback returns false stop here.
                // Check if click handler returns false last so that it is not executed
                // for a disabled or loading tab!
                if (($li.hasClass('ui-tabs-selected') && !o.collapsible) ||
                    $li.hasClass('ui-state-disabled') ||
                    $li.hasClass('ui-state-processing') ||
                    self._trigger('select', null, self._ui(this, $show[0])) === false) {
                    this.blur();
                    return false;
                }

                o.selected=self.anchors.index(this);

                self.abort();

                // if tab may be closed
                if (o.collapsible) {
                    if ($li.hasClass('ui-tabs-selected')) {
                        o.selected=-1;

                        if (o.cookie) {
                            self._cookie(o.selected, o.cookie);
                        }

                        self.element.queue("tabs", function() {
                            hideTab(el, $hide);
                        }).dequeue("tabs");

                        this.blur();
                        return false;
                    }
                    else if (!$hide.length) {
                        if (o.cookie) {
                            self._cookie(o.selected, o.cookie);
                        }

                        self.element.queue("tabs", function() {
                            showTab(el, $show);
                        });

                        self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171

                        this.blur();
                        return false;
                    }
                }

                if (o.cookie) {
                    self._cookie(o.selected, o.cookie);
                }

                // show new tab
                if ($show.length) {
                    if ($hide.length) {
                        self.element.queue("tabs", function() {
                            hideTab(el, $hide);
                        });
                    }
                    self.element.queue("tabs", function() {
                        showTab(el, $show);
                    });

                    self.load(self.anchors.index(this));
                }
                else {
                    throw 'jQuery UI Tabs: Mismatching fragment identifier.';
                }

                // Prevent IE from keeping other link focussed when using the back button
                // and remove dotted border from clicked link. This is controlled via CSS
                // in modern browsers; blur() removes focus from address bar in Firefox
                // which can become a usability and annoying problem with tabs('rotate').
                if ($.browser.msie) {
                    this.blur();
                }

            });

            // disable click in any case
            this.anchors.bind('click.tabs', function() {
                return false;
            });

        },

        destroy: function() {
            var o=this.options;

            this.abort();

            this.element.unbind('.tabs')
                    .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
                    .removeData('tabs');

            this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');

            this.anchors.each(function() {
                var href=$.data(this, 'href.tabs');
                if (href) {
                    this.href=href;
                }
                var $this=$(this).unbind('.tabs');
                $.each(['href', 'load', 'cache'], function(i, prefix) {
                    $this.removeData(prefix + '.tabs');
                });
            });

            this.lis.unbind('.tabs').add(this.panels).each(function() {
                if ($.data(this, 'destroy.tabs')) {
                    $(this).remove();
                }
                else {
                    $(this).removeClass([
                        'ui-state-default',
                        'ui-corner-top',
                        'ui-tabs-selected',
                        'ui-state-active',
                        'ui-state-hover',
                        'ui-state-focus',
                        'ui-state-disabled',
                        'ui-tabs-panel',
                        'ui-widget-content',
                        'ui-corner-bottom',
                        'ui-tabs-hide'
                    ].join(' '));
                }
            });

            if (o.cookie) {
                this._cookie(null, o.cookie);
            }

            return this;
        },

        add: function(url, label, index) {
            if (index === undefined) {
                index=this.anchors.length; // append by default
            }

            var self=this, o=this.options,
                    $li=$(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)),
                    id=!url.indexOf('#') ? url.replace('#', '') : this._tabId($('a', $li)[0]);

            $li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);

            // try to find an existing element before creating a new one
            var $panel=$('#' + id);
            if (!$panel.length) {
                $panel=$(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
            }
            $panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');

            if (index >= this.lis.length) {
                $li.appendTo(this.list);
                $panel.appendTo(this.list[0].parentNode);
            }
            else {
                $li.insertBefore(this.lis[index]);
                $panel.insertBefore(this.panels[index]);
            }

            o.disabled=$.map(o.disabled,
                    function(n, i) {
                        return n >= index ? ++n : n;
                    });

            this._tabify();

            if (this.anchors.length == 1) { // after tabify
                o.selected=0;
                $li.addClass('ui-tabs-selected ui-state-active');
                $panel.removeClass('ui-tabs-hide');
                this.element.queue("tabs", function() {
                    self._trigger('show', null, self._ui(self.anchors[0], self.panels[0]));
                });

                this.load(0);
            }

            // callback
            this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
            return this;
        },

        remove: function(index) {
            var o=this.options, $li=this.lis.eq(index).remove(),
                    $panel=this.panels.eq(index).remove();

            // If selected tab was removed focus tab to the right or
            // in case the last tab was removed the tab to the left.
            if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) {
                this.select(index + (index + 1 < this.anchors.length ? 1 : -1));
            }

            o.disabled=$.map($.grep(o.disabled, function(n, i) {
                return n != index;
            }),
                    function(n, i) {
                        return n >= index ? --n : n;
                    });

            this._tabify();

            // callback
            this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
            return this;
        },

        enable: function(index) {
            var o=this.options;
            if ($.inArray(index, o.disabled) == -1) {
                return;
            }

            this.lis.eq(index).removeClass('ui-state-disabled');
            o.disabled=$.grep(o.disabled, function(n, i) {
                return n != index;
            });

            // callback
            this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
            return this;
        },

        disable: function(index) {
            var self=this, o=this.options;
            if (index != o.selected) { // cannot disable already selected tab
                this.lis.eq(index).addClass('ui-state-disabled');

                o.disabled.push(index);
                o.disabled.sort();

                // callback
                this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
            }

            return this;
        },

        select: function(index) {
            if (typeof index == 'string') {
                index=this.anchors.index(this.anchors.filter('[href$=' + index + ']'));
            }
            else if (index === null) { // usage of null is deprecated, TODO remove in next release
                index=-1;
            }
            if (index == -1 && this.options.collapsible) {
                index=this.options.selected;
            }

            this.anchors.eq(index).trigger(this.options.event + '.tabs');
            return this;
        },

        load: function(index) {
            var self=this, o=this.options, a=this.anchors.eq(index)[0], url=$.data(a, 'load.tabs');

            this.abort();

            // not remote or from cache
            if (!url || this.element.queue("tabs").length !== 0 && $.data(a, 'cache.tabs')) {
                this.element.dequeue("tabs");
                return;
            }

            // load remote from here on
            this.lis.eq(index).addClass('ui-state-processing');

            if (o.spinner) {
                var span=$('span', a);
                span.data('label.tabs', span.html()).html(o.spinner);
            }

            this.xhr=$.ajax($.extend({}, o.ajaxOptions, {
                url: url,
                success: function(r, s) {
                    $(self._sanitizeSelector(a.hash)).html(r);

                    // take care of tab labels
                    self._cleanup();

                    if (o.cache) {
                        $.data(a, 'cache.tabs', true); // if loaded once do not load them again
                    }

                    // callbacks
                    self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
                    try {
                        o.ajaxOptions.success(r, s);
                    }
                    catch (e) {
                    }

                    // last, so that load event is fired before show...
                    self.element.dequeue("tabs");
                }
            }));

            return this;
        },

        abort: function() {
            // stop possibly running animations
            this.element.queue([]);
            this.panels.stop(false, true);

            // "tabs" queue must not contain more than two elements,
            // which are the callbacks for the latest clicked tab...
            this.element.queue("tabs", this.element.queue("tabs").splice(-2, 2));

            // terminate pending requests from other tabs
            if (this.xhr) {
                this.xhr.abort();
                delete this.xhr;
            }

            // take care of tab labels
            this._cleanup();
            return this;
        },

        url: function(index, url) {
            this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
            return this;
        },

        length: function() {
            return this.anchors.length;
        }

    });

    $.extend($.ui.tabs, {
        version: '1.8rc1'
    });

    /*
     * Tabs Extensions
     */

    /*
     * Rotate
     */
    $.extend($.ui.tabs.prototype, {
        rotation: null,
        rotate: function(ms, continuing) {

            var self=this, o=this.options;

            var rotate=self._rotate || (self._rotate=function(e) {
                clearTimeout(self.rotation);
                self.rotation=setTimeout(function() {
                    var t=o.selected;
                    self.select(++t < self.anchors.length ? t : 0);
                }, ms);

                if (e) {
                    e.stopPropagation();
                }
            });

            var stop=self._unrotate || (self._unrotate=!continuing ?
                                                       function(e) {
                                                           if (e.clientX) { // in case of a true click
                                                               self.rotate(null);
                                                           }
                                                       } :
                                                       function(e) {
                                                           t=o.selected;
                                                           rotate();
                                                       });

            // start rotation
            if (ms) {
                this.element.bind('tabsshow', rotate);
                this.anchors.bind(o.event + '.tabs', stop);
                rotate();
            }
            // stop rotation
            else {
                clearTimeout(self.rotation);
                this.element.unbind('tabsshow', rotate);
                this.anchors.unbind(o.event + '.tabs', stop);
                delete this._rotate;
                delete this._unrotate;
            }

            return this;
        }
    });

})(jQuery);
