From ca32f08966f1b51fcb19460f0996bb0c4048e6fe Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Sat, 3 Dec 2011 13:29:22 +0100 Subject: Update to MediaWiki 1.18.0 * also update ArchLinux skin to chagnes in MonoBook * Use only css to hide our menu bar when printing --- resources/jquery.ui/jquery.ui.autocomplete.js | 255 ++++++++++++++++++-------- 1 file changed, 178 insertions(+), 77 deletions(-) (limited to 'resources/jquery.ui/jquery.ui.autocomplete.js') diff --git a/resources/jquery.ui/jquery.ui.autocomplete.js b/resources/jquery.ui/jquery.ui.autocomplete.js index 9a12a6b0..41c13930 100644 --- a/resources/jquery.ui/jquery.ui.autocomplete.js +++ b/resources/jquery.ui/jquery.ui.autocomplete.js @@ -1,9 +1,9 @@ /* - * jQuery UI Autocomplete 1.8.2 + * jQuery UI Autocomplete 1.8.14 * - * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license * * http://docs.jquery.com/UI/Autocomplete * @@ -12,16 +12,32 @@ * jquery.ui.widget.js * jquery.ui.position.js */ -(function( $ ) { +(function( $, undefined ) { + +// used to prevent race conditions with remote data sources +var requestIndex = 0; $.widget( "ui.autocomplete", { options: { + appendTo: "body", + autoFocus: false, + delay: 300, minLength: 1, - delay: 300 + position: { + my: "left top", + at: "left bottom", + collision: "none" + }, + source: null }, + + pending: 0, + _create: function() { var self = this, - doc = this.element[ 0 ].ownerDocument; + doc = this.element[ 0 ].ownerDocument, + suppressKeyPress; + this.element .addClass( "ui-autocomplete-input" ) .attr( "autocomplete", "off" ) @@ -32,6 +48,11 @@ $.widget( "ui.autocomplete", { "aria-haspopup": "true" }) .bind( "keydown.autocomplete", function( event ) { + if ( self.options.disabled || self.element.attr( "readonly" ) ) { + return; + } + + suppressKeyPress = false; var keyCode = $.ui.keyCode; switch( event.keyCode ) { case keyCode.PAGE_UP: @@ -52,8 +73,11 @@ $.widget( "ui.autocomplete", { break; case keyCode.ENTER: case keyCode.NUMPAD_ENTER: - // when menu is open or has focus + // when menu is open and has focus if ( self.menu.active ) { + // #6055 - Opera still allows the keypress to occur + // which causes forms to submit + suppressKeyPress = true; event.preventDefault(); } //passthrough - ENTER and TAB both select the current element @@ -67,33 +91,38 @@ $.widget( "ui.autocomplete", { 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 ); + // only search if the value has changed + if ( self.term != self.element.val() ) { + self.selectedItem = null; + self.search( null, event ); + } }, self.options.delay ); break; } }) + .bind( "keypress.autocomplete", function( event ) { + if ( suppressKeyPress ) { + suppressKeyPress = false; + event.preventDefault(); + } + }) .bind( "focus.autocomplete", function() { + if ( self.options.disabled ) { + return; + } + self.selectedItem = null; self.previous = self.element.val(); }) .bind( "blur.autocomplete", function( event ) { + if ( self.options.disabled ) { + return; + } + clearTimeout( self.searching ); // clicks on the menu (or a button to trigger a search) will cause a blur event self.closing = setTimeout(function() { @@ -107,9 +136,26 @@ $.widget( "ui.autocomplete", { }; this.menu = $( "" ) .addClass( "ui-autocomplete" ) - .appendTo( "body", doc ) + .appendTo( $( this.options.appendTo || "body", doc )[0] ) // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) - .mousedown(function() { + .mousedown(function( event ) { + // clicking on the scrollbar causes focus to shift to the body + // but we can't detect a mouseup or a click immediately afterward + // so we have to track the next mousedown and close the menu if + // the user clicks somewhere outside of the autocomplete + var menuElement = self.menu.element[ 0 ]; + if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { + setTimeout(function() { + $( document ).one( 'mousedown', function( event ) { + if ( event.target !== self.element[ 0 ] && + event.target !== menuElement && + !$.ui.contains( menuElement, event.target ) ) { + self.close(); + } + }); + }, 1 ); + } + // use another timeout to make sure the blur-event-handler on the input was already triggered setTimeout(function() { clearTimeout( self.closing ); @@ -118,7 +164,7 @@ $.widget( "ui.autocomplete", { .menu({ focus: function( event, ui ) { var item = ui.item.data( "item.autocomplete" ); - if ( false !== self._trigger( "focus", null, { item: item } ) ) { + if ( false !== self._trigger( "focus", event, { 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 ); @@ -126,21 +172,37 @@ $.widget( "ui.autocomplete", { } }, 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 ); + var item = ui.item.data( "item.autocomplete" ), + previous = self.previous; + // 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; + // #6109 - IE triggers two focus events and the second + // is asynchronous, so we need to reset the previous + // term synchronously and asynchronously :-( + setTimeout(function() { + self.previous = previous; + self.selectedItem = item; + }, 1); } + + if ( false !== self._trigger( "select", event, { item: item } ) ) { + self.element.val( item.value ); + } + // reset the term after the select event + // this allows custom select handling to work properly + self.term = self.element.val(); + + self.close( event ); self.selectedItem = item; }, blur: function( event, ui ) { - if ( self.menu.element.is(":visible") ) { + // don't set the value of the text field if it's already correct + // this prevents moving the cursor unnecessarily + if ( self.menu.element.is(":visible") && + ( self.element.val() !== self.term ) ) { self.element.val( self.term ); } } @@ -166,15 +228,22 @@ $.widget( "ui.autocomplete", { $.Widget.prototype.destroy.call( this ); }, - _setOption: function( key ) { + _setOption: function( key, value ) { $.Widget.prototype._setOption.apply( this, arguments ); if ( key === "source" ) { this._initSource(); } + if ( key === "appendTo" ) { + this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) + } + if ( key === "disabled" && value && this.xhr ) { + this.xhr.abort(); + } }, _initSource: function() { - var array, + var self = this, + array, url; if ( $.isArray(this.options.source) ) { array = this.options.source; @@ -184,7 +253,25 @@ $.widget( "ui.autocomplete", { } else if ( typeof this.options.source === "string" ) { url = this.options.source; this.source = function( request, response ) { - $.getJSON( url, request, response ); + if ( self.xhr ) { + self.xhr.abort(); + } + self.xhr = $.ajax({ + url: url, + data: request, + dataType: "json", + autocompleteRequest: ++requestIndex, + success: function( data, status ) { + if ( this.autocompleteRequest === requestIndex ) { + response( data ); + } + }, + error: function() { + if ( this.autocompleteRequest === requestIndex ) { + response( [] ); + } + } + }); }; } else { this.source = this.options.source; @@ -193,12 +280,16 @@ $.widget( "ui.autocomplete", { search: function( value, event ) { value = value != null ? value : this.element.val(); + + // always save the actual value, not the one passed as an argument + this.term = this.element.val(); + if ( value.length < this.options.minLength ) { return this.close( event ); } clearTimeout( this.closing ); - if ( this._trigger("search") === false ) { + if ( this._trigger( "search", event ) === false ) { return; } @@ -206,31 +297,32 @@ $.widget( "ui.autocomplete", { }, _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.pending++; + this.element.addClass( "ui-autocomplete-loading" ); this.source( { term: value }, this.response ); }, _response: function( content ) { - if ( content.length ) { + if ( !this.options.disabled && content && content.length ) { content = this._normalize( content ); this._suggest( content ); this._trigger( "open" ); } else { this.close(); } - this.element.removeClass( "ui-autocomplete-loading" ); + this.pending--; + if ( !this.pending ) { + 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(); + this._trigger( "close", event ); } }, @@ -261,26 +353,33 @@ $.widget( "ui.autocomplete", { _suggest: function( items ) { var ul = this.menu.element - .empty() - .zIndex( this.element.zIndex() + 1 ), - menuWidth, - textWidth; + .empty() + .zIndex( this.element.zIndex() + 1 ); 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" - }); - menuWidth = ul.width( "" ).width(); - textWidth = this.element.width(); - ul.width( Math.max( menuWidth, textWidth ) ); + // size and position menu + ul.show(); + this._resizeMenu(); + ul.position( $.extend({ + of: this.element + }, this.options.position )); + + if ( this.options.autoFocus ) { + this.menu.next( new $.Event("mouseover") ); + } }, - + + _resizeMenu: function() { + var ul = this.menu.element; + ul.outerWidth( Math.max( + ul.width( "" ).outerWidth(), + this.element.outerWidth() + ) ); + }, + _renderMenu: function( ul, items ) { var self = this; $.each( items, function( index, item ) { @@ -291,7 +390,7 @@ $.widget( "ui.autocomplete", { _renderItem: function( ul, item) { return $( "
  • " ) .data( "item.autocomplete", item ) - .append( "" + item.label + "" ) + .append( $( "" ).text( item.label ) ) .appendTo( ul ); }, @@ -316,7 +415,7 @@ $.widget( "ui.autocomplete", { $.extend( $.ui.autocomplete, { escapeRegex: function( value ) { - return value.replace( /([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1" ); + return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); }, filter: function(array, term) { var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); @@ -335,9 +434,9 @@ $.extend( $.ui.autocomplete, { * 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. + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license * * http://docs.jquery.com/UI/Menu * @@ -391,12 +490,12 @@ $.widget("ui.menu", { this.deactivate(); if (this.hasScroll()) { var offset = item.offset().top - this.element.offset().top, - scroll = this.element.attr("scrollTop"), + scroll = this.element.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.element.scrollTop( scroll + offset); + } else if (offset >= elementHeight) { + this.element.scrollTop( scroll + offset - elementHeight + item.height()); } } this.active = item.eq(0) @@ -426,11 +525,11 @@ $.widget("ui.menu", { }, first: function() { - return this.active && !this.active.prev().length; + return this.active && !this.active.prevAll(".ui-menu-item").length; }, last: function() { - return this.active && !this.active.next().length; + return this.active && !this.active.nextAll(".ui-menu-item").length; }, move: function(direction, edge, event) { @@ -451,12 +550,12 @@ $.widget("ui.menu", { if (this.hasScroll()) { // TODO merge with no-scroll-else if (!this.active || this.last()) { - this.activate(event, this.element.children(":first")); + this.activate(event, this.element.children(".ui-menu-item:first")); return; } var base = this.active.offset().top, height = this.element.height(), - result = this.element.children("li").filter(function() { + result = this.element.children(".ui-menu-item").filter(function() { var close = $(this).offset().top - base - height + $(this).height(); // TODO improve approximation return close < 10 && close > -10; @@ -464,11 +563,12 @@ $.widget("ui.menu", { // TODO try to catch this earlier when scrollTop indicates the last page anyway if (!result.length) { - result = this.element.children(":last"); + result = this.element.children(".ui-menu-item:last"); } this.activate(event, result); } else { - this.activate(event, this.element.children(!this.active || this.last() ? ":first" : ":last")); + this.activate(event, this.element.children(".ui-menu-item") + .filter(!this.active || this.last() ? ":first" : ":last")); } }, @@ -477,13 +577,13 @@ $.widget("ui.menu", { if (this.hasScroll()) { // TODO merge with no-scroll-else if (!this.active || this.first()) { - this.activate(event, this.element.children(":last")); + this.activate(event, this.element.children(".ui-menu-item:last")); return; } var base = this.active.offset().top, height = this.element.height(); - result = this.element.children("li").filter(function() { + result = this.element.children(".ui-menu-item").filter(function() { var close = $(this).offset().top - base + height - $(this).height(); // TODO improve approximation return close < 10 && close > -10; @@ -491,16 +591,17 @@ $.widget("ui.menu", { // TODO try to catch this earlier when scrollTop indicates the last page anyway if (!result.length) { - result = this.element.children(":first"); + result = this.element.children(".ui-menu-item:first"); } this.activate(event, result); } else { - this.activate(event, this.element.children(!this.active || this.first() ? ":last" : ":first")); + this.activate(event, this.element.children(".ui-menu-item") + .filter(!this.active || this.first() ? ":last" : ":first")); } }, hasScroll: function() { - return this.element.height() < this.element.attr("scrollHeight"); + return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight"); }, select: function( event ) { -- cgit v1.2.3-54-g00ecf