From 63601400e476c6cf43d985f3e7b9864681695ed4 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Fri, 18 Jan 2013 16:46:04 +0100 Subject: Update to MediaWiki 1.20.2 this update includes: * adjusted Arch Linux skin * updated FluxBBAuthPlugin * patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024 --- resources/jquery/jquery.suggestions.js | 185 ++++++++++++++++++++++----------- 1 file changed, 122 insertions(+), 63 deletions(-) (limited to 'resources/jquery/jquery.suggestions.js') diff --git a/resources/jquery/jquery.suggestions.js b/resources/jquery/jquery.suggestions.js index 55c30010..d80680fc 100644 --- a/resources/jquery/jquery.suggestions.js +++ b/resources/jquery/jquery.suggestions.js @@ -36,20 +36,24 @@ * maxExpandFactor: Maximum suggestions box width relative to the textbox width. If set to e.g. 2, the suggestions box * will never be grown beyond 2 times the width of the textbox. * Type: Number, Range: 1 - infinity, Default: 3 - * positionFromLeft: Whether to position the suggestion box with the left attribute or the right + * expandFrom: Which direction to offset the suggestion box from. + * Values 'start' and 'end' translate to left and right respectively depending on the directionality + * of the current document, according to $( 'html' ).css( 'direction' ). + * Type: String, default: 'auto', options: 'left', 'right', 'start', 'end', 'auto'. + * positionFromLeft: Sets expandFrom=left, for backwards compatibility * Type: Boolean, Default: true * highlightInput: Whether to hightlight matched portions of the input or not * Type: Boolean, Default: false */ -( function( $ ) { +( function ( $ ) { $.suggestions = { /** * Cancel any delayed updateSuggestions() call and inform the user so * they can cancel their result fetching if they use AJAX or something */ - cancel: function( context ) { - if ( context.data.timerID != null ) { + cancel: function ( context ) { + if ( context.data.timerID !== null ) { clearTimeout( context.data.timerID ); } if ( $.isFunction( context.config.cancel ) ) { @@ -61,7 +65,7 @@ $.suggestions = { * restores the value the currently displayed suggestions are based on, rather than the value just before * highlight() overwrote it; the former is arguably slightly more sensible. */ - restore: function( context ) { + restore: function ( context ) { context.data.$textbox.val( context.data.prevText ); }, /** @@ -70,7 +74,7 @@ $.suggestions = { * function does nothing. * @param {Boolean} delayed Whether or not to delay this by the currently configured amount of time */ - update: function( context, delayed ) { + update: function ( context, delayed ) { // Only fetch if the value in the textbox changed and is not empty // if the textbox is empty then clear the result div, but leave other settings intouched function maybeFetch() { @@ -86,7 +90,7 @@ $.suggestions = { } // Cancel previous call - if ( context.data.timerID != null ) { + if ( context.data.timerID !== null ) { clearTimeout( context.data.timerID ); } if ( delayed ) { @@ -97,13 +101,13 @@ $.suggestions = { } $.suggestions.special( context ); }, - special: function( context ) { + special: function ( context ) { // Allow custom rendering - but otherwise don't do any rendering if ( typeof context.config.special.render === 'function' ) { // Wait for the browser to update the value - setTimeout( function() { + setTimeout( function () { // Render special - $special = context.data.$container.find( '.suggestions-special' ); + var $special = context.data.$container.find( '.suggestions-special' ); context.config.special.render.call( $special, context.data.$textbox.val() ); }, 1 ); } @@ -113,7 +117,8 @@ $.suggestions = { * @param property String Name of property * @param value Mixed Value to set property with */ - configure: function( context, property, value ) { + configure: function ( context, property, value ) { + var newCSS; // Validate creation using fallback values switch( property ) { case 'fetch': @@ -121,6 +126,7 @@ $.suggestions = { case 'special': case 'result': case '$region': + case 'expandFrom': context.config[property] = value; break; case 'suggestions': @@ -134,19 +140,77 @@ $.suggestions = { // Rebuild the suggestions list context.data.$container.show(); // Update the size and position of the list - var newCSS = { + newCSS = { top: context.config.$region.offset().top + context.config.$region.outerHeight(), bottom: 'auto', width: context.config.$region.outerWidth(), height: 'auto' }; - if ( context.config.positionFromLeft ) { + + // Process expandFrom, after this it is set to left or right. + context.config.expandFrom = ( function ( expandFrom ) { + var regionWidth, docWidth, regionCenter, docCenter, + docDir = $( document.documentElement ).css( 'direction' ), + $region = context.config.$region; + + // Backwards compatible + if ( context.config.positionFromLeft ) { + expandFrom = 'left'; + + // Catch invalid values, default to 'auto' + } else if ( $.inArray( expandFrom, ['left', 'right', 'start', 'end', 'auto'] ) === -1 ) { + expandFrom = 'auto'; + } + + if ( expandFrom === 'auto' ) { + if ( $region.data( 'searchsuggest-expand-dir' ) ) { + // If the markup explicitly contains a direction, use it. + expandFrom = $region.data( 'searchsuggest-expand-dir' ); + } else { + regionWidth = $region.outerWidth(); + docWidth = $( document ).width(); + if ( ( regionWidth / docWidth ) > 0.85 ) { + // If the input size takes up more than 85% of the document horizontally + // expand the suggestions to the writing direction's native end. + expandFrom = 'start'; + } else { + // Calculate the center points of the input and document + regionCenter = $region.offset().left + regionWidth / 2; + docCenter = docWidth / 2; + if ( Math.abs( regionCenter - docCenter ) / docCenter < 0.10 ) { + // If the input's center is within 10% of the document center + // use the writing direction's native end. + expandFrom = 'start'; + } else { + // Otherwise expand the input from the closest side of the page, + // towards the side of the page with the most free open space + expandFrom = regionCenter > docCenter ? 'right' : 'left'; + } + } + } + } + + if ( expandFrom === 'start' ) { + expandFrom = docDir === 'rtl' ? 'right': 'left'; + + } else if ( expandFrom === 'end' ) { + expandFrom = docDir === 'rtl' ? 'left': 'right'; + } + + return expandFrom; + + }( context.config.expandFrom ) ); + + if ( context.config.expandFrom === 'left' ) { + // Expand from left newCSS.left = context.config.$region.offset().left; newCSS.right = 'auto'; } else { + // Expand from right newCSS.left = 'auto'; newCSS.right = $( 'body' ).width() - ( context.config.$region.offset().left + context.config.$region.outerWidth() ); } + context.data.$container.css( newCSS ); var $results = context.data.$container.children( '.suggestions-results' ); $results.empty(); @@ -154,12 +218,13 @@ $.suggestions = { var $autoEllipseMe = $( [] ); var matchedText = null; for ( var i = 0; i < context.config.suggestions.length; i++ ) { + /*jshint loopfunc:true */ var text = context.config.suggestions[i]; var $result = $( '
' ) .addClass( 'suggestions-result' ) .attr( 'rel', i ) .data( 'text', context.config.suggestions[i] ) - .mousemove( function( e ) { + .mousemove( function ( e ) { context.data.selectedWithMouse = true; $.suggestions.highlight( context, $(this).closest( '.suggestions-results div' ), false @@ -220,9 +285,9 @@ $.suggestions = { * @param result to highlight: jQuery object, or 'prev' or 'next' * @param updateTextbox If true, put the suggestion in the textbox */ - highlight: function( context, result, updateTextbox ) { + highlight: function ( context, result, updateTextbox ) { var selected = context.data.$container.find( '.suggestions-result-current' ); - if ( !result.get || selected.get( 0 ) != result.get( 0 ) ) { + if ( !result.get || selected.get( 0 ) !== result.get( 0 ) ) { if ( result === 'prev' ) { if( selected.is( '.suggestions-special' ) ) { result = context.data.$container.find( '.suggestions-result:last' ); @@ -277,8 +342,8 @@ $.suggestions = { * Respond to keypress event * @param key Integer Code of key pressed */ - keypress: function( e, context, key ) { - var wasVisible = context.data.$container.is( ':visible' ), + keypress: function ( e, context, key ) { + var wasVisible = context.data.$container.is( ':visible' ), preventDefault = false; switch ( key ) { // Arrow down @@ -311,7 +376,7 @@ $.suggestions = { case 13: context.data.$container.hide(); preventDefault = wasVisible; - selected = context.data.$container.find( '.suggestions-result-current' ); + var selected = context.data.$container.find( '.suggestions-result-current' ); if ( selected.length === 0 || context.data.selectedWithMouse ) { // if nothing is selected OR if something was selected with the mouse, // cancel any current requests and submit the form @@ -340,22 +405,23 @@ $.suggestions = { } } }; -$.fn.suggestions = function() { +$.fn.suggestions = function () { // Multi-context fields - var returnValue = null; - var args = arguments; + var returnValue, + args = arguments; - $(this).each( function() { + $(this).each( function () { + var context, key; /* Construction / Loading */ - var context = $(this).data( 'suggestions-context' ); + context = $(this).data( 'suggestions-context' ); if ( context === undefined || context === null ) { context = { config: { - 'fetch' : function() {}, - 'cancel': function() {}, + 'fetch' : function () {}, + 'cancel': function () {}, 'special': {}, 'result': {}, '$region': $(this), @@ -364,7 +430,7 @@ $.fn.suggestions = function() { 'delay': 120, 'submitOnClick': false, 'maxExpandFactor': 3, - 'positionFromLeft': true, + 'expandFrom': 'auto', 'highlightInput': false } }; @@ -376,14 +442,14 @@ $.fn.suggestions = function() { if ( args.length > 0 ) { if ( typeof args[0] === 'object' ) { // Apply set of properties - for ( var key in args[0] ) { + for ( key in args[0] ) { $.suggestions.configure( context, key, args[0][key] ); } } else if ( typeof args[0] === 'string' ) { if ( args.length > 1 ) { // Set property values $.suggestions.configure( context, args[0], args[1] ); - } else if ( returnValue == null ) { + } else if ( returnValue === null || returnValue === undefined ) { // Get property values, but don't give access to internal data - returns only the first returnValue = ( args[0] in context.config ? undefined : context.config[args[0]] ); } @@ -395,45 +461,35 @@ $.fn.suggestions = function() { if ( context.data === undefined ) { context.data = { // ID of running timer - 'timerID': null, + timerID: null, + // Text in textbox when suggestions were last fetched - 'prevText': null, + prevText: null, + // Number of results visible without scrolling - 'visibleResults': 0, + visibleResults: 0, + // Suggestion the last mousedown event occured on - 'mouseDownOn': $( [] ), - '$textbox': $(this), - 'selectedWithMouse': false - }; - // Setup the css for positioning the results box - var newCSS = { - top: Math.round( context.data.$textbox.offset().top + context.data.$textbox.outerHeight() ), - width: context.data.$textbox.outerWidth(), - display: 'none' + mouseDownOn: $( [] ), + $textbox: $(this), + selectedWithMouse: false }; - if ( context.config.positionFromLeft ) { - newCSS.left = context.config.$region.offset().left; - newCSS.right = 'auto'; - } else { - newCSS.left = 'auto'; - newCSS.right = $( 'body' ).width() - ( context.config.$region.offset().left + context.config.$region.outerWidth() ); - } context.data.$container = $( '
' ) - .css( newCSS ) + .css( 'display', 'none' ) .addClass( 'suggestions' ) .append( $( '
' ).addClass( 'suggestions-results' ) // Can't use click() because the container div is hidden when the textbox loses focus. Instead, // listen for a mousedown followed by a mouseup on the same div - .mousedown( function( e ) { + .mousedown( function ( e ) { context.data.mouseDownOn = $( e.target ).closest( '.suggestions-results div' ); } ) - .mouseup( function( e ) { + .mouseup( function ( e ) { var $result = $( e.target ).closest( '.suggestions-results div' ); var $other = context.data.mouseDownOn; context.data.mouseDownOn = $( [] ); - if ( $result.get( 0 ) != $other.get( 0 ) ) { + if ( $result.get( 0 ) !== $other.get( 0 ) ) { return; } $.suggestions.highlight( context, $result, true ); @@ -448,14 +504,14 @@ $.fn.suggestions = function() { $( '
' ).addClass( 'suggestions-special' ) // Can't use click() because the container div is hidden when the textbox loses focus. Instead, // listen for a mousedown followed by a mouseup on the same div - .mousedown( function( e ) { + .mousedown( function ( e ) { context.data.mouseDownOn = $( e.target ).closest( '.suggestions-special' ); } ) - .mouseup( function( e ) { + .mouseup( function ( e ) { var $special = $( e.target ).closest( '.suggestions-special' ); var $other = context.data.mouseDownOn; context.data.mouseDownOn = $( [] ); - if ( $special.get( 0 ) != $other.get( 0 ) ) { + if ( $special.get( 0 ) !== $other.get( 0 ) ) { return; } context.data.$container.hide(); @@ -464,7 +520,7 @@ $.fn.suggestions = function() { } context.data.$textbox.focus(); } ) - .mousemove( function( e ) { + .mousemove( function ( e ) { context.data.selectedWithMouse = true; $.suggestions.highlight( context, $( e.target ).closest( '.suggestions-special' ), false @@ -472,12 +528,13 @@ $.fn.suggestions = function() { } ) ) .appendTo( $( 'body' ) ); + $(this) // Stop browser autocomplete from interfering .attr( 'autocomplete', 'off') - .keydown( function( e ) { + .keydown( function ( e ) { // Store key pressed to handle later - context.data.keypressed = ( e.keyCode === undefined ) ? e.which : e.keyCode; + context.data.keypressed = e.which; context.data.keypressedCount = 0; switch ( context.data.keypressed ) { @@ -496,18 +553,18 @@ $.fn.suggestions = function() { } } } ) - .keypress( function( e ) { + .keypress( function ( e ) { context.data.keypressedCount++; $.suggestions.keypress( e, context, context.data.keypressed ); } ) - .keyup( function( e ) { + .keyup( function ( e ) { // Some browsers won't throw keypress() for arrow keys. If we got a keydown and a keyup without a // keypress in between, solve it if ( context.data.keypressedCount === 0 ) { $.suggestions.keypress( e, context, context.data.keypressed ); } } ) - .blur( function() { + .blur( function () { // When losing focus because of a mousedown // on a suggestion, don't hide the suggestions if ( context.data.mouseDownOn.length > 0 ) { @@ -517,9 +574,11 @@ $.fn.suggestions = function() { $.suggestions.cancel( context ); } ); } + // Store the context for next time $(this).data( 'suggestions-context', context ); } ); - return returnValue !== null ? returnValue : $(this); + return returnValue !== undefined ? returnValue : $(this); }; -} )( jQuery ); \ No newline at end of file + +}( jQuery ) ); -- cgit v1.2.3-54-g00ecf