(function($) {
    var extensions = {
        AddMultipleToAutocomplete: function() {
            $.extend($.ui.autocomplete.prototype.options, {
                multiple: false
            });
    
            var _originalCreate = $.ui.autocomplete.prototype._create;
            $.extend($.ui.autocomplete.prototype, {
                _create: function() {
                    if (this.options.multiple) { this._makeMultiple.extendInstance.call(this); }
                    _originalCreate.apply(this, arguments);
                    if (this.options.multiple) { this._makeMultiple.bindEvents.call(this); }
                },
                _makeMultiple: {
                    bindEvents: function() {
                        var base = this;
                        this.element.bind('autocompletesearch', function() {
            				var term = base._extractValue(this.value);
            				if (term.length < base.options.minLength) { return false; }
                        });
                        this.element.bind('autocompletefocus', function() {
                            return false;
                        });
                        this.element.bind('autocompleteselect', function(e, ui) {
            				var terms = base._splitValues(this.value);
            				// remove the current input
            				terms.pop();
            				// add the selected item
            				terms.push(ui.item.value);
            				// add placeholder to get the comma-and-space at the end
            				terms.push('');
            				this.value = terms.join(', ');
            				return false;
                        });
                    },
                    extendInstance: function() {
                        var _originalInitSource = this._initSource;
                        $.extend(this, {
                            _initSource: function() {
                                _originalInitSource.apply(this, arguments);
                                var original = this.source;
                                this.source = function(request, response) {
                                    request.term = this._extractValue(request.term);
                                    original.call(this, request, response);
                                };
                            },
                            _splitValues: function(val) {
                                return val.split(/,\s*/);
                            },
                            _extractValue: function(val) {
                                return this._splitValues(val).pop();
                            }
                        });
                    }
                }
            });
        },
        AddContainerToAutocomplete: function() {
            $.extend($.ui.autocomplete.prototype.options, {
                container: 'dropdown'
            });
    
            var _originalCreate = $.ui.autocomplete.prototype._create;
            $.extend($.ui.autocomplete.prototype, {
                _create: function() {
                    var container = this.options.container;
                    if (container !== 'dropdown') {
                        this.close = function() { };
                        this._suggest = this._suggest.wrap(function(original, items) {
                            var result =  original(items);
                            this.menu.element.appendTo(container).css('position', 'static');
                            return result;
                        });
                    }
                    return _originalCreate.apply(this, arguments);
                }
            });
        },
        AddFadeToDialogDefaults: function() {
            $.extend($.ui.dialog.prototype.options, {
                show: 'fade'
            });
        },
        FixJaggedTextForIEAnimation: function() {
            var _originalAnimate = $.fn.animate;
            $.fn.animate = function(props) {
                var original = _originalAnimate.apply(this, arguments);
                if (!$.support.opacity && props.opacity) {
                    if (props.opacity == 'show' || props.opacity == 1) {
                        $(this).queue(function(next) {
                            this.style.removeAttribute('filter');
                            next();
                        });
                    }
                }
                return original;
            };
        },
        AddAnimationToProgressBar: function() {
            $.extend($.ui.progressbar.prototype.options, {
                animate: true
            });

            $.ui.progressbar.prototype._refreshValue = function() {
                var value = this.value();
        		this.valueDiv[value === this._valueMax() ? 'addClass' : 'removeClass']('ui-corner-right');
        		this.element.attr('aria-valuenow', value);
        		
                if (this.options.animate) {
                    this.valueDiv.stop(true, true).animate({ width: value + '%' }, { duration: value == 0 ? 0 : $.fx.speeds._default });
                } else {
            		this.valueDiv.width( value + "%" );
                }
            };
        },
        DoNotTriggerAutoCompleteSearchForCommandKey: function() {
            var _originalSearch = $.ui.autocomplete.prototype.search;
            $.ui.keyCode.META = 224;
            $.extend($.ui.autocomplete.prototype, {
                search: function(value, event) {
                    if (event) {
                        if (event.keyCode == $.ui.keyCode.META) { return false; }
                        return _originalSearch.apply(this, arguments);
                    } else {
                        return _originalSearch.apply(this, arguments);
                    }
                }
            });
        },
        FixIEDialogAutoWidth: function() {
            var _originalSize = $.ui.dialog.prototype._size;
            $.extend($.ui.dialog.prototype, {
                _size: function() {
                    _originalSize.apply(this, arguments);
            
                    if (this.options.width == 'auto') {
                        this.uiDialog.css({ width: 'auto', position: 'absolute' });
                    }
                },
                // Convenience function for getting buttons
                buttons: function() {
                    return this.uiDialog.find('.ui-dialog-buttonpane button');
                }
            });
        },
        AddConvenienceDialogFunctions: function() {
            $.extend($.ui.dialog, {
                save: function() { $(this).find('form').trigger('submit'); },
                close: function() { $(this).dialog('close'); }
            });
        },
        AddAutoCompleteViewMore: function() {
            var _originalSuggest = $.ui.autocomplete.prototype._suggest;
            $.extend($.ui.autocomplete.prototype, {
                _suggest: function() {
                    var original = _originalSuggest.apply(this, arguments);

                    if (this.options.viewMore) {
                        var link = $('<a/>', {
                            href: this.options.viewMore + '?term=' + this.term,
                            tabindex: -1,
                            html: 'View all search results <span class="ui-icon ui-icon-circle-arrow-e"></span>',
                            click: function() {
                                window.location.href = $(this).attr('href');
                                return false;
                            }
                        });
                        this.menu.element.append(link.wrap('<li class="ui-menu-viewmore"/>').parent());
                    }
            
                    return original;
                }
            });

            var _originalRenderItem = $.ui.autocomplete.prototype._renderItem;
            $.extend($.ui.autocomplete.prototype, {
                _renderItem: function(ul, item) {
                    var original = _originalRenderItem.apply(this, arguments);
                    if (item.header) {
                        original.addClass('ui-menu-header').addClass('ui-widget-header');
                    }
                    return original;
            	}
            });
        }
    };
    
    $.each(extensions, function(feature, method) {
        method();
    });
})(jQuery);
