/*!
* jQuery UI 1.8.2
*
* 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
*/

(function($) {

    // prevent duplicate loading
    // this is only a problem because we proxy existing functions
    // and we don't want to double proxy them
    $.ui = $.ui || {};
    if ($.ui.version) {
        return;
    }

    //Helper functions and ui object
    $.extend($.ui, {
        version: "1.8.2",

        // $.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: {
            ALT: 18,
            BACKSPACE: 8,
            CAPS_LOCK: 20,
            COMMA: 188,
            COMMAND: 91,
            COMMAND_LEFT: 91, // COMMAND
            COMMAND_RIGHT: 93,
            CONTROL: 17,
            DELETE: 46,
            DOWN: 40,
            END: 35,
            ENTER: 13,
            ESCAPE: 27,
            HOME: 36,
            INSERT: 45,
            LEFT: 37,
            MENU: 93, // COMMAND_RIGHT
            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,
            WINDOWS: 91 // COMMAND
        }
    });

    //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', '');
        },

        disableSelection: function() {
            return this
            .attr('unselectable', 'on')
            .css('MozUserSelect', 'none');
        },

        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);
            }

            if (this.length) {
                var elem = $(this[0]), position, value;
                while (elem.length && elem[0] !== document) {
                    // Ignore z-index if position is set to a value where z-index is ignored by the browser
                    // This makes behavior of this function consistent across browsers
                    // WebKit always returns auto if the element is positioned
                    position = elem.css('position');
                    if (position == 'absolute' || position == 'relative' || position == 'fixed') {
                        // IE returns 0 when zIndex is not specified
                        // other browsers return a 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>
                        value = parseInt(elem.css('zIndex'));
                        if (!isNaN(value) && value != 0) {
                            return value;
                        }
                    }
                    elem = elem.parent();
                }
            }

            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.8.2
*
* 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) {
        return this.each(function() {
            if (!keepData) {
                if (!selector || $.filter(selector, [this]).length) {
                    $("*", this).add(this).each(function() {
                        $(this).triggerHandler("remove");
                    });
                }
            }
            return _remove.call($(this), selector, keepData);
        });
    };

    $.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 " +
                "ui-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" + " " +
                    "ui-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 Position 1.8.2
*
* 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,
    _offset = $.fn.offset;

    $.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(" ");
            if (pos.length === 1) {
                pos = horizontalPositions.test(pos[0]) ?
                pos.concat([verticalDefault]) :
                verticalPositions.test(pos[0]) ?
                    [horizontalDefault].concat(pos) :
                    [horizontalDefault, verticalDefault];
            }
            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;

        if (options.at[0] === "right") {
            basePosition.left += targetWidth;
        } else if (options.at[0] === horizontalDefault) {
            basePosition.left += targetWidth / 2;
        }

        if (options.at[1] === "bottom") {
            basePosition.top += targetHeight;
        } else if (options.at[1] === verticalDefault) {
            basePosition.top += targetHeight / 2;
        }

        basePosition.left += offset[0];
        basePosition.top += offset[1];

        return this.each(function() {
            var elem = $(this),
            elemWidth = elem.outerWidth(),
            elemHeight = elem.outerHeight(),
            position = $.extend({}, basePosition);

            if (options.my[0] === "right") {
                position.left -= elemWidth;
            } else if (options.my[0] === horizontalDefault) {
                position.left -= elemWidth / 2;
            }

            if (options.my[1] === "bottom") {
                position.top -= elemHeight;
            } else if (options.my[1] === verticalDefault) {
                position.top -= elemHeight / 2;
            }

            // prevent fractions (see #5280)
            position.left = parseInt(position.left);
            position.top = parseInt(position.top);

            $.each(["left", "top"], function(i, dir) {
                if ($.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
                    });
                }
            });

            if ($.fn.bgiframe) {
                elem.bgiframe();
            }
            elem.offset($.extend(position, { using: options.using }));
        });
    };

    $.ui.position = {
        fit: {
            left: function(position, data) {
                var win = $(window),
                over = position.left + data.elemWidth - win.width() - win.scrollLeft();
                position.left = over > 0 ? position.left - over : Math.max(0, position.left);
            },
            top: function(position, data) {
                var win = $(window),
                over = position.top + data.elemHeight - win.height() - win.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 win = $(window),
                over = position.left + data.elemWidth - win.width() - win.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 win = $(window),
                over = position.top + data.elemHeight - win.height() - win.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($.curCSS(elem, "position"))) {
                elem.style.position = "relative";
            }
            var curElem = $(elem),
            curOffset = curElem.offset(),
            curTop = parseInt($.curCSS(elem, "top", true), 10) || 0,
            curLeft = parseInt($.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);
            }
        };

        $.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 Autocomplete 1.8.2
*
* 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
*  jquery.ui.position.js
*/
(function($) {

    $.widget("ui.autocomplete", {
        options: {
            minLength: 1,
            delay: 300,
            offset: "0 0"
        },
        _create: function() {
            var self = this,
            doc = this.element[0].ownerDocument;
            this.element
            .addClass("ui-autocomplete-input")
            .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:
                    case keyCode.NUMPAD_ENTER:
                        // when menu is open or has focus
                        if (self.menu.active) {
                            event.preventDefault();
                        }
                        //passthrough - ENTER and TAB both select the current element
                    case keyCode.TAB:
                        if (!self.menu.active) {
                            return;
                        }
                        self.menu.select(event);
                        break;
                    case keyCode.ESCAPE:
                        self.element.val(self.term);
                        self.close(event);
                        break;
                    case keyCode.LEFT:
                    case keyCode.RIGHT:
                    case keyCode.SHIFT:
                    case keyCode.CONTROL:
                    case keyCode.ALT:
                    case keyCode.COMMAND:
                    case keyCode.COMMAND_RIGHT:
                    case keyCode.INSERT:
                    case keyCode.CAPS_LOCK:
                    case keyCode.END:
                    case keyCode.HOME:
                        // 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.selectedItem = null;
                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
                self.closing = setTimeout(function() {
                    self.close(event);
                    self._change(event);
                }, 150);
            });
            this._initSource();
            this.response = function() {
                return self._response.apply(self, arguments);
            };
            this.menu = $("<ul></ul>")
            .addClass("ui-autocomplete")
            .appendTo("body", doc)
            // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
            .mousedown(function() {
                // use another timeout to make sure the blur-event-handler on the input was already triggered
                setTimeout(function() {
                    clearTimeout(self.closing);
                }, 13);
            })
            .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, if it was a key event
                        if (/^key/.test(event.originalEvent.type)) {
                            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);
                    // only trigger when focus was lost (click on menu)
                    var previous = self.previous;
                    if (self.element[0] !== doc.activeElement) {
                        self.element.focus();
                        self.previous = previous;
                    }
                    self.selectedItem = item;
                },
                blur: function(event, ui) {
                    if (self.menu.element.is(":visible")) {
                        self.element.val(self.term);
                    }
                }
            })
            .zIndex(this.element.zIndex() + 1)
            // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
            .css({ top: 0, left: 0 })
            .hide()
            .data("menu");
            if ($.fn.bgiframe) {
                this.menu.element.bgiframe();
            }
        },

        destroy: function() {
            this.element
            .removeClass("ui-autocomplete-input")
            .removeAttr("autocomplete")
            .removeAttr("role")
            .removeAttr("aria-autocomplete")
            .removeAttr("aria-haspopup");
            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() {
            var array,
            url;
            if ($.isArray(this.options.source)) {
                array = this.options.source;
                this.source = function(request, response) {
                    response($.ui.autocomplete.filter(array, request.term));
                };
            } else if (typeof this.options.source === "string") {
                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._suggest(content);
                this._trigger("open", null, this.menu);
            } else {
                this.close();
            }
            this.element.removeClass("ui-autocomplete-loading");
        },

        close: function(event) {
            clearTimeout(this.closing);
            if (this.menu.element.is(":visible")) {
                this._trigger("close", event);
                this.menu.element.hide();
                this.menu.deactivate();
            }
        },

        _change: function(event) {
            if (this.previous !== this.element.val()) {
                this._trigger("change", event, { item: this.selectedItem });
            }
        },

        _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) {
            var ul = this.menu.element
                .empty()
                .zIndex(this.element.zIndex() + 1),
            menuWidth,
            textWidth;
            this._renderMenu(ul, items);
            // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
            this.menu.deactivate();
            this.menu.refresh();
            this.menu.element.show().position({
                my: "left top",
                at: "left bottom",
                of: this.element,
                collision: "none",
                offset: this.options.offset
            });

            // get width
            $(ul).css({
                position: 'absolute',
                width: 'auto'               // reset width so when we change textboxes on the same page, the width can be adjusted correctly
            });

            menuWidth = ul.innerWidth();
            textWidth = this.element.innerWidth();
            ul.width(Math.max(menuWidth, textWidth));
        },

        _renderMenu: function(ul, items) {
            var self = this;
            $.each(items, function(index, item) {
                self._renderItem(ul, item);
            });
        },

        _renderItem: function(ul, item) {
            return $("<li></li>")
            .data("item.autocomplete", item)
            .append("<a>" + item.label + "</a>")
            .appendTo(ul);
        },

        _move: function(direction, event) {
            if (!this.menu.element.is(":visible")) {
                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](event);
        },

        widget: function() {
            return this.menu.element;
        }
    });

    $.extend($.ui.autocomplete, {
        escapeRegex: function(value) {
            return value.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1");
        },
        filter: function(array, term) {
            var matcher = new RegExp($.ui.autocomplete.escapeRegex(term), "i");
            return $.grep(array, function(value) {
                return matcher.test(value.label || value.value || value);
            });
        }
    });

} (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: "listbox",
                "aria-activedescendant": "ui-active-menuitem"
            })
            .click(function(event) {
                if (!$(event.target).closest(".ui-menu-item a").length) {
                    return;
                }
                // temporary
                event.preventDefault();
                self.select(event);
            });
            this.refresh();
        },

        refresh: function() {
            var self = this;

            // don't refresh list items that are already adapted
            var items = this.element.children("li:not(.ui-menu-item):has(a)")
            .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(event) {
                self.activate(event, $(this).parent());
            })
            .mouseleave(function() {
                self.deactivate();
            });
        },

        activate: function(event, item) {
            this.deactivate();
            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());
                }
            }
            this.active = item.eq(0)
            .children("a")
                .addClass("ui-state-hover")
                .attr("id", "ui-active-menuitem")
            .end();
            this._trigger("focus", event, { item: item });
        },

        deactivate: function() {
            if (!this.active) { return; }

            this.active.children("a")
            .removeClass("ui-state-hover")
            .removeAttr("id");
            this._trigger("blur");
            this.active = null;
        },

        next: function(event) {
            this.move("next", ".ui-menu-item:first", event);
        },

        previous: function(event) {
            this.move("prev", ".ui-menu-item:last", event);
        },

        first: function() {
            return this.active && !this.active.prev().length;
        },

        last: function() {
            return this.active && !this.active.next().length;
        },

        move: function(direction, edge, event) {
            if (!this.active) {
                this.activate(event, this.element.children(edge));
                return;
            }
            var next = this.active[direction + "All"](".ui-menu-item").eq(0);
            if (next.length) {
                this.activate(event, next);
            } else {
                this.activate(event, this.element.children(edge));
            }
        },

        // TODO merge with previousPage
        nextPage: function(event) {
            if (this.hasScroll()) {
                // TODO merge with no-scroll-else
                if (!this.active || this.last()) {
                    this.activate(event, 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(event, result);
            } else {
                this.activate(event, this.element.children(!this.active || this.last() ? ":first" : ":last"));
            }
        },

        // TODO merge with nextPage
        previousPage: function(event) {
            if (this.hasScroll()) {
                // TODO merge with no-scroll-else
                if (!this.active || this.first()) {
                    this.activate(event, 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(event, result);
            } else {
                this.activate(event, this.element.children(!this.active || this.first() ? ":last" : ":first"));
            }
        },

        hasScroll: function() {
            return this.element.height() < this.element.attr("scrollHeight");
        },

        select: function(event) {
            this._trigger("selected", event, { item: this.active });
        }
    });

} (jQuery));

