From d8599bee184fda598ba037d2b2d291bb0cc24108 Mon Sep 17 00:00:00 2001 From: Santhosh Thottingal Date: Mon, 19 Nov 2012 12:25:29 +0530 Subject: [PATCH] Update jquery.uls from upstream * Bug fixes Change-Id: Ibb57ba4465ddb0878260cc23d4b7fe8a01a272a8 --- lib/jquery.uls/jquery.uls.js | 136 +++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 39 deletions(-) diff --git a/lib/jquery.uls/jquery.uls.js b/lib/jquery.uls/jquery.uls.js index de86aa0b..f27d2b0d 100644 --- a/lib/jquery.uls/jquery.uls.js +++ b/lib/jquery.uls/jquery.uls.js @@ -1,4 +1,4 @@ -/*! jquery.uls - v0.1.0 - 2012-11-11 +/*! jquery.uls - v0.1.0 - 2012-11-19 * https://github.com/wikimedia/jquery.uls * Copyright (c) 2012 Santhosh Thottingal; Licensed GPL, MIT */ @@ -512,13 +512,13 @@ You can search by language name, \ script name, ISO code of language or \ you can browse by region:\ - America, \ - Europe, \ - Middle East, \ - Africa, \ - Asia, \ - Pacific, \ - Worldwide.\ + America, \ + Europe, \ + Middle East, \ + Africa, \ + Asia, \ + Pacific, \ + Worldwide.\

\ \ \ @@ -827,11 +827,13 @@ this.$suggestion = this.$element.parents().find( '#' + this.$element.data( 'suggestion' ) ); this.$clear = this.$element.parents().find( '#'+ this.$element.data( 'clear' ) ); this.selectedLanguage = null; + this.listen(); }; var delay = ( function() { var timer = 0; + return function( callback, milliseconds ) { clearTimeout( timer ); timer = setTimeout( callback, milliseconds ); @@ -843,12 +845,15 @@ listen: function() { this.$element.on( 'keypress', $.proxy( this.keyup, this ) ) .on( 'keyup', $.proxy( this.keyup, this ) ); + if ( this.eventSupported( 'keydown' ) ) { this.$element.on( 'keydown', $.proxy( this.keyup, this ) ); } + if ( this.$clear.length ) { this.$clear.on( 'click' , $.proxy( this.clear, this ) ); } + this.toggleClear(); }, @@ -856,6 +861,7 @@ switch( e.keyCode ) { case 9: // Tab -> Autocomplete var suggestion = this.$suggestion.val(); + if ( suggestion && suggestion !== this.$element.val() ) { this.$element.val( suggestion ); e.preventDefault(); @@ -866,7 +872,9 @@ if ( !this.options.onSelect ) { break; } + var query = $.trim( this.$element.val() ).toLowerCase(); + if ( this.selectedLanguage ) { // this.selectLanguage will be populated from a matching search this.options.onSelect( this.selectedLanguage ); @@ -875,10 +883,18 @@ // but we have a matching language code. this.options.onSelect( query ); } + break; default: var that = this; + + if ( e.which < 32 ) { + // ignore any ASCII control characters + break; + } + this.selectedLanguage = null; + delay( function() { if ( !that.$element.val() ) { that.clear(); @@ -887,6 +903,7 @@ that.search(); } }, 300 ); + this.toggleClear(); } }, @@ -897,7 +914,11 @@ */ deactivate: function() { this.$element.val( '' ); - this.$element.focus(); + + if ( !$.fn.uls.Constructor.prototype.isMobile() ) { + this.$element.focus(); + } + this.toggleClear(); this.autofill(); }, @@ -907,7 +928,7 @@ */ clear: function() { this.deactivate(); - this.$element.trigger( 'seachclear' ); + this.$element.trigger( 'searchclear' ); }, /** @@ -930,25 +951,33 @@ var query = $.trim( this.$element.val() ), languages = $.uls.data.getLanguagesByScriptGroup( this.options.languages ), scriptGroup, langNum, langCode; + this.resultCount = 0; + for ( scriptGroup in languages ) { var languagesInScript = languages[scriptGroup]; + languagesInScript.sort( $.uls.data.sortByAutonym ); + for ( langNum = 0; langNum < languagesInScript.length; langNum++ ) { langCode = languagesInScript[langNum]; + if ( query === "" || this.filter( langCode, query ) ) { if ( this.resultCount === 0 ) { // Autofill the first result. this.autofill( langCode ); } + if ( query.toLowerCase() === langCode ) { this.selectedLanguage = langCode; } + this.render( langCode ); this.resultCount++; } } } + // Also do a search by search API if( !this.resultCount && this.options.searchAPI && query ) { this.searchAPI( query ); @@ -959,6 +988,7 @@ searchAPI: function( query ) { var that = this; + $.get( that.options.searchAPI, { search: query }, function( result ) { $.each( result['languagesearch'], function( code, name ) { if ( that.resultCount === 0 ) { @@ -990,15 +1020,19 @@ if ( !this.$suggestion.length ) { return; } + if ( !this.$element.val() ) { this.$suggestion.val( '' ); return; } + this.selectedLanguage = langCode; languageName = languageName || this.options.languages[langCode]; + var autonym, userInput = this.$element.val(), suggestion = userInput + languageName.substring( userInput.length, languageName.length ); + if ( suggestion.toLowerCase() !== languageName.toLowerCase() ) { // see if it was autonym match autonym = $.uls.data.getAutonym( langCode ) || ''; @@ -1008,18 +1042,22 @@ suggestion = ""; } } + // Make sure that it is a visual prefix. if ( !isVisualPrefix( userInput, suggestion ) ) { suggestion = ""; } + this.$suggestion.val( suggestion ); }, render: function( langCode ) { var $target = this.options.$target; + if ( !$target ) { return; } + $target.append( langCode, null ); }, @@ -1039,6 +1077,7 @@ // FIXME script is ISO 15924 code. We might need actual name of script. var matcher = new RegExp( "^" + this.escapeRegex( searchTerm ), 'i' ), languageName = this.options.languages[langCode]; + return matcher.test( languageName ) || matcher.test( $.uls.data.getAutonym( langCode ) ) || matcher.test( langCode ) || @@ -1063,9 +1102,11 @@ var $this = $( this ), data = $this.data( 'languagefilter' ), options = typeof option === 'object' && option; + if ( !data ) { $this.data( 'languagefilter', ( data = new LanguageFilter( this, options ) ) ); } + if ( typeof option === 'string' ) { data[option](); } @@ -1301,8 +1342,8 @@ * @licence MIT License */ -(function ( $ ) { - "use strict"; +( function ( $ ) { + 'use strict'; // Region numbers in id attributes also appear in the langdb. var template = '\ @@ -1369,7 +1410,7 @@ for ( var code in this.languages ) { if ( $.uls.data.languages[code] === undefined ) { if ( window.console && window.console.log ) { - window.console.log( "ULS: Unknown language " + code + "." ); + window.console.log( 'ULS: Unknown language ' + code + '.' ); } delete this.languages[code]; } @@ -1430,7 +1471,10 @@ } this.$menu.show(); this.shown = true; - this.$languageFilter.focus(); + + if ( !this.isMobile() ) { + this.$languageFilter.focus(); + } }, i18n: function() { @@ -1486,61 +1530,69 @@ */ listen: function() { var lcd, - that = this; + uls = this, + cancelProxy = $.proxy( uls.cancel, uls ); // Register all event listeners to the ULS here. - that.$element.on( 'click', $.proxy( that.click, that ) ); + uls.$element.on( 'click', $.proxy( uls.click, uls ) ); - that.$languageFilter.on( 'seachclear', $.proxy( that.defaultSearch, that ) ); - // Handle click on close button - this.$menu.find( "#uls-close" ).on( 'click', $.proxy( that.cancel, that ) ); + uls.$languageFilter.on( 'searchclear', $.proxy( uls.defaultSearch, uls ) ); + + // Close when clicking on the close button + uls.$menu.find( '#uls-close' ).on( 'click', cancelProxy ); + // Don't do anything if pressing on empty space in the ULS + uls.$menu.on( 'click', function ( e ) { + e.stopPropagation(); + } ); + // Close ULS if clicking elsewhere + $( document ).on( 'click', cancelProxy ); // Handle key press events on the menu - that.$menu.on('keypress', $.proxy(this.keypress, this) ) - .on('keyup', $.proxy(this.keyup, this) ); + uls.$menu.on( 'keypress', $.proxy( this.keypress, this ) ) + .on( 'keyup', $.proxy( this.keyup, this ) ); if ( this.eventSupported( 'keydown' ) ) { this.$menu.on( 'keydown', $.proxy( this.keypress, this ) ); } - lcd = that.$resultsView.lcd( { - languages: that.languages, - quickList: that.options.quickList, - clickhandler: $.proxy( that.select, that ), - lazyload: that.options.lazyload, - source: that.$languageFilter - } ).data( "lcd" ); + lcd = uls.$resultsView.lcd( { + languages: uls.languages, + quickList: uls.options.quickList, + clickhandler: $.proxy( uls.select, uls ), + lazyload: uls.options.lazyload, + source: uls.$languageFilter + } ).data( 'lcd' ); - that.$languageFilter.languagefilter( { + uls.$languageFilter.languagefilter( { $target: lcd, - languages: that.languages, + languages: uls.languages, success: function() { $( '.regionselector' ).removeClass( 'active' ); - that.success(); + uls.success(); }, noresults: function() { $( '.regionselector' ).removeClass( 'active' ); - that.noresults(); + uls.noresults(); }, - searchAPI: that.options.searchAPI, - onSelect: $.proxy( that.select, that ) + searchAPI: uls.options.searchAPI, + onSelect: $.proxy( uls.select, uls ) } ); // Create region selectors, one per region this.$menu.find( '.uls-region, .uls-region-link' ).regionselector( { $target: lcd, - languages: that.languages, + languages: uls.languages, success: function( regionfilter ) { // Deactivate search filtering - that.$languageFilter.languagefilter( 'deactivate' ); + uls.$languageFilter.languagefilter( 'deactivate' ); // If it is WW region, show the quicklist if ( regionfilter.regionGroup === 1 ) { lcd.quicklist(); } // Show 'results view' if we are in no results mode - that.success(); + uls.success(); }, noresults: function() { - that.$languageFilter.languagefilter( 'clear' ); + uls.$languageFilter.languagefilter( 'clear' ); } } ); }, @@ -1591,7 +1643,9 @@ click: function( e ) { e.stopPropagation(); e.preventDefault(); - if ( !this.shown ) { + if ( this.shown ) { + this.hide(); + } else { this.show(); } }, @@ -1604,6 +1658,10 @@ isSupported = typeof this.$element[eventName] === 'function'; } return isSupported; + }, + + isMobile: function () { + return navigator.userAgent.match( /(iPhone|iPod|iPad|Android|BlackBerry)/ ); } };