diff --git a/UniversalLanguageSelector.hooks.php b/UniversalLanguageSelector.hooks.php index ed6aba4c..6d620097 100644 --- a/UniversalLanguageSelector.hooks.php +++ b/UniversalLanguageSelector.hooks.php @@ -87,8 +87,6 @@ class UniversalLanguageSelectorHooks {
-
"; diff --git a/UniversalLanguageSelector.php b/UniversalLanguageSelector.php index a3fc68bf..39ceb817 100644 --- a/UniversalLanguageSelector.php +++ b/UniversalLanguageSelector.php @@ -51,6 +51,22 @@ $wgResourceModules['ext.uls.data'] = array( 'remoteExtPath' => 'UniversalLanguageSelector', ); +$wgResourceModules['ext.uls.lcd'] = array( + 'scripts' => 'resources/ext.uls.lcd.js', + 'localBasePath' => $dir, + 'remoteExtPath' => 'UniversalLanguageSelector', + 'styles' => 'resources/css/ext.uls.lcd.css', + 'dependencies' => array( + 'jquery.viewport', + ), +); + +$wgResourceModules['jquery.viewport'] = array( + 'scripts' => 'resources/jquery.viewport.js', + 'localBasePath' => $dir, + 'remoteExtPath' => 'UniversalLanguageSelector', +); + $wgResourceModules['ext.uls.core'] = array( 'scripts' => array( 'resources/ext.uls.core.js', @@ -63,6 +79,7 @@ $wgResourceModules['ext.uls.core'] = array( 'dependencies' => array( 'mediawiki.Uri', 'ext.uls.data', + 'ext.uls.lcd', ), 'position' => 'top', ); diff --git a/resources/css/ext.uls.css b/resources/css/ext.uls.css index da1e8541..d678770e 100644 --- a/resources/css/ext.uls.css +++ b/resources/css/ext.uls.css @@ -100,14 +100,6 @@ margin-top: 2%; } -.uls-language-list ul { - list-style: none; - margin-left: 0; - -moz-column-count: 3; - -webkit-column-count: 3; - column-count: 3; -} - .uls-language-list ul li { font-weight: bold; } diff --git a/resources/css/ext.uls.lcd.css b/resources/css/ext.uls.lcd.css new file mode 100644 index 00000000..91bd1d0d --- /dev/null +++ b/resources/css/ext.uls.lcd.css @@ -0,0 +1,16 @@ +.uls-lcd-region-section h3 { + color: #999999; +} + +.uls-lcd-region-section ul { + list-style: none; + margin-left: 0; + float: left; + width: 150px; + padding: 10px; + clear: right; +} + +.uls-lcd-region-section { + clear: both; +} \ No newline at end of file diff --git a/resources/ext.uls.core.js b/resources/ext.uls.core.js index a2355f24..022a7153 100644 --- a/resources/ext.uls.core.js +++ b/resources/ext.uls.core.js @@ -49,24 +49,22 @@ that.$element.on( 'click', $.proxy( that.click, that ) ); $( ".icon-close" ).on( 'click', $.proxy( that.click, that ) ); - // The search input box - $( "#languagefilter" ).languagefilter( { - $target: $( 'ul.uls-language-filter-result' ), + var $lcd = $( "div.uls-language-list" ).lcd( { + languages: that.languages, clickhandler: function( langCode ) { that.setLang( langCode ); - }, + } + }).data( "lcd" ); + $( "#languagefilter" ).languagefilter( { + $target: $lcd, //$( 'ul.uls-language-filter-result' ), languages: that.languages } ); // Create region selectors, one per region $( '.uls-region' ).regionselector( { - $target: $( 'ul.uls-language-filter-result' ), - clickhandler: function( langCode ) { - that.setLang( langCode ); - }, - //FIXME This is confusing: languages and source are acturally data for ULS. + $target: $lcd, + //FIXME This is confusing: languages and source are actually data for ULS. languages: that.languages, - source: $.uls.data, callback: function () { // clear the search field. $( "#languagefilter" ).val( "" ); @@ -75,10 +73,9 @@ // trigger a search for all languages. $( "#languagefilter" ).languagefilter( "search" ); }, - keyup : function(e) { - switch(e.keyCode) { - case 27: - // escape + keyup: function( e ) { + switch( e.keyCode ) { + case 27: // escape if (!this.shown ) { return this.hide(); } @@ -93,8 +90,7 @@ } switch( e.keyCode ) { - case 27: - // escape + case 27: // escape e.preventDefault(); break; } @@ -117,7 +113,10 @@ $.fn.uls = function( option ) { return this.each( function() { - var $this = $( this ), data = $this.data( 'uls' ), options = typeof option == 'object' && option; + var $this = $( this ), + data = $this.data( 'uls' ), + options = typeof option === 'object' && option; + if ( !data ) { $this.data( 'uls', ( data = new ULS( this, options ) ) ); } @@ -128,7 +127,7 @@ }; $.fn.uls.defaults = { - menu : '.uls-menu', + menu: '.uls-menu' }; $.fn.uls.Constructor = ULS; diff --git a/resources/ext.uls.data.utils.js b/resources/ext.uls.data.utils.js index e9781fda..6988b07c 100644 --- a/resources/ext.uls.data.utils.js +++ b/resources/ext.uls.data.utils.js @@ -5,9 +5,32 @@ (function ( $ ) { "use strict"; - // Constants - var scriptIndex = 0, - regionsIndex = 1; + /* + * Returns the script of the language. + * @param string language code + * @return string + */ + $.uls.data.script = function( language ) { + return $.uls.data.languages[language][0]; + }; + + /* + * Returns the regions in which a language is spoken. + * @param string language code + * @return array of strings + */ + $.uls.data.regions = function( language ) { + return $.uls.data.languages[language][1]; + }; + + /* + * Returns the autonym of the language. + * @param string language code + * @return string + */ + $.uls.data.autonym = function( language ) { + return $.uls.data.autonyms[language]; + }; /* * Returns all languages written in script. @@ -16,7 +39,7 @@ */ $.uls.data.languagesInScript = function( script ) { return $.uls.data.languagesInScripts( [ script ] ); - } + }; /* * Returns all languages written in the given scripts. @@ -28,7 +51,7 @@ for ( var language in $.uls.data.languages ) { for ( var i = 0; i < scripts.length; i++ ) { - if ( scripts[i] === $.uls.data.languages[language][scriptIndex] ) { + if ( scripts[i] === $.uls.data.script(language) ) { languagesInScripts.push( language ); break; } @@ -36,7 +59,7 @@ } return languagesInScripts; - } + }; /* * Returns all languages in a given region. @@ -45,7 +68,7 @@ */ $.uls.data.languagesInRegion = function( region ) { return $.uls.data.languagesInRegions( [ region ] ); - } + }; /* * Returns all languages in given regions. @@ -57,7 +80,7 @@ for ( var language in $.uls.data.languages ) { for ( var i = 0; i < regions.length; i++ ) { - if ( $.inArray( regions[i], $.uls.data.languages[language][regionsIndex] ) != -1 ) { + if ( $.inArray( regions[i], $.uls.data.regions( language ) ) !== -1 ) { languagesInRegions.push( language ); break; } @@ -65,7 +88,7 @@ } return languagesInRegions; - } + }; /* * Returns an associative array of languages in a region, @@ -77,8 +100,8 @@ var languagesByScriptInRegion = {}; for ( var language in $.uls.data.languages ) { - if ( $.inArray( region, $.uls.data.languages[language][regionsIndex] ) != -1 ) { - var script = $.uls.data.languages[language][scriptIndex]; + if ( $.inArray( region, $.uls.data.regions( language ) ) !== -1 ) { + var script = $.uls.data.script( language ); if ( languagesByScriptInRegion[script] === undefined ) { languagesByScriptInRegion[script] = []; } @@ -87,7 +110,7 @@ } return languagesByScriptInRegion; - } + }; /* * Returns all regions in a region group. @@ -104,20 +127,27 @@ } return regionsInGroup; - } + }; /* * Returns the script group of a script or 'Other' if it doesn't * belong to any group. + * @param string script code + * @return string script group name */ $.uls.data.groupOfScript = function( script ) { for ( var group in $.uls.data.scriptgroups ) { - if ( $.inArray( script, $.uls.data.scriptgroups[group] ) != -1 ) { + if ( $.inArray( script, $.uls.data.scriptgroups[group] ) !== -1 ) { return group; } } return 'Other'; - } + }; + + $.uls.data.sortByScriptGroup = function( languages ) { + // FIXME sort it. + return languages; + }; } )( jQuery ); diff --git a/resources/ext.uls.languagefilter.js b/resources/ext.uls.languagefilter.js index 9f208233..d3623039 100644 --- a/resources/ext.uls.languagefilter.js +++ b/resources/ext.uls.languagefilter.js @@ -1,9 +1,10 @@ /** * @author Santhosh Thottingal * jQuery language filter plugin - * Usage: $('inputbox').languagefilter(); + * + * Usage: $( 'inputbox' ).languagefilter(); * The values for autocompletion is from the options.languages. - * the data is in the format of languagecode:languagename format. + * The data is in the format of languagecode:languagename. */ (function ( $ ) { "use strict"; @@ -33,7 +34,7 @@ var that = this; var languages = this.options.languages; var query = this.$element.val(); - $.each( languages, function ( name, code ) { + $.each( languages, function ( code, name ) { if ( query === "" ) { that.render(code); } @@ -49,16 +50,7 @@ if ( !$target ) { return; } - var $li = $( "
  • " ) - .data( "code", code ) - .append( $( "" ).prop( 'href', '#' ). html( this.options.languages[code] || code ) ) - .appendTo( $target ); - - if ( this.options.clickhandler ) { - $li.click( function() { - that.options.clickhandler.call( this, code ); - } ); - } + $target.append(code); }, escapeRegex: function( value ) { @@ -74,13 +66,12 @@ * d) ISO 15924 code for the script match the search string. */ filter: function( code, searchTerm ) { - var languages = this.options.languages; - var langName = languages[code]; - var autonym = $.uls.data.autonyms[code]; - var script = $.uls.data.languages[code]? $.uls.data.languages[code][0]: "unknown"; // FIXME script is ISO 15924 code. We might need actual name of script. var matcher = new RegExp( this.escapeRegex( searchTerm ), 'i' ); - return matcher.test( langName ) || matcher.test( autonym ) || matcher.test( code ) || matcher.test( script ); + return matcher.test( this.options.languages[code] ) || + matcher.test( $.uls.data.autonym( code ) ) || + matcher.test( code ) || + matcher.test( $.uls.data.script( code ) ); } }; @@ -112,7 +103,7 @@ /* * Region selector is a language selector based on regions. - * Usage: $( 'jqueryselector' ).regionselector(options); + * Usage: $( 'jqueryselector' ).regionselector( options ); * The attached element should have data-region attribute * that defines the region for the selector. */ @@ -128,8 +119,8 @@ constructor: RegionSelector, test: function( langCode ) { var that = this; - var languages = that.options.source.languages; - var regionGroups = that.options.source.regiongroups; + var languages = $.uls.data.languages; + var regionGroups = $.uls.data.regiongroups; var regions = languages[langCode][1]; // 1. loop over all regions - like {EU: 2, AF: 2, AS: 3 ...} // 2. check that the region matches the active region group @@ -137,18 +128,21 @@ // 4. if none of the conditions match, the language is not shown $.each( regionGroups, function( regionGroup, groupId ) { if ( groupId === that.region && $.inArray( regionGroup, regions ) >= 0 ) { - that.render( langCode ); - return true; + that.render( langCode, regionGroup ); + return; } } ); - return false; }, show: function() { - var that = this; - var languages = that.options.source.languages; + var that = this, + languages = $.uls.data.languages; + + languages = $.uls.data.sortByScriptGroup( languages ); + // Make the selected region (and it only) active $( '.regionselector' ).removeClass( 'active' ); that.$element.addClass( 'active' ); + // Repopulate the list of languages that.options.$target.empty(); $.each( languages, function( langCode, langDef ) { @@ -158,19 +152,12 @@ that.options.callback.call(); } }, - render: function( langCode ) { - var that = this; - var langName = that.options.languages[langCode] || langCode; - var $li = $( "
  • " ) - .data( "code", langCode ) - .append( $( "" ).prop( 'href', '#' ).html( langName ) ) - .appendTo( this.options.$target ); - - if ( that.options.clickhandler ) { - $li.click( function() { - that.options.clickhandler.call( this, langCode ); - } ); + render: function( langCode, regionGroup) { + var $target = this.options.$target; + if ( !$target ) { + return; } + $target.append( langCode, regionGroup ); }, listen: function(){ this.$element.on( 'click', $.proxy( this.click, this ) ); @@ -187,7 +174,7 @@ return this.each( function() { var $this = $( this ), data = $this.data( 'regionselector' ), - options = typeof option == 'object' && option; + options = typeof option === 'object' && option; if ( !data ) { $this.data( 'regionselector', ( data = new RegionSelector( this, options ) ) ); } @@ -199,9 +186,6 @@ $.fn.regionselector.defaults = { $target: null, // Where to render the results. Must be a ul element - clickhandler: null, // Click handler to handle click events on results - source: null, // The language database - languages:null, // Language names for the current UI language callback: null // Callback - will be called after results are displayed. }; diff --git a/resources/ext.uls.lcd.js b/resources/ext.uls.lcd.js new file mode 100644 index 00000000..ed1a67c9 --- /dev/null +++ b/resources/ext.uls.lcd.js @@ -0,0 +1,111 @@ +(function( $ ) { + "use strict"; + + var LanguageCategoryDisplay = function( element, options ) { + this.$element = $( element ); + this.options = $.extend( {}, $.fn.lcd.defaults, options ); + this.$element.addClass( 'lcd' ); + this.show(); + this.listen(); + }; + + LanguageCategoryDisplay.prototype = { + constructor: LanguageCategoryDisplay, + + append: function( langCode, regionGroup ) { + var that = this; + this.addToRegion( langCode, regionGroup ); + }, + + addToRegion: function( langCode, regionGroup ) { + var that = this, + language = $.uls.data.languages[langCode]; + + if ( !language ) { + console.log( "Definition for " + langCode + " was not found in the language database." ); + return; + } + + var langName = that.options.languages[langCode]; + + var regions = $.uls.data.regions( langCode ); + for ( var i = 0; i < regions.length; i++ ) { + var regionCode = regions[i]; + + if ( regionGroup && regionCode !== regionGroup ) { + continue; + } + + var $li = $( '
  • ' ) + .data( 'code', langCode ) + .append( + $( '' ).prop( 'href', '#' ).html( langName ) + ); + that.getColumn( regionCode ).append( $li ); + if ( that.options.clickhandler ) { + $li.click( function() { + that.options.clickhandler.call( this, langCode ); + } ); + } + } + }, + + getColumn: function( regionCode ) { + var $ul = $( "div#" + regionCode ).find( 'ul:last' ); + if ( $ul.length === 0 || $ul.find( 'li' ).length >= 10) { + $ul = $( '