diff --git a/resources/ext.uls.core.js b/resources/ext.uls.core.js index 022a7153..3240d59c 100644 --- a/resources/ext.uls.core.js +++ b/resources/ext.uls.core.js @@ -13,6 +13,7 @@ ULS.prototype = { constructor: ULS, + show: function() { var pos = $.extend( {}, this.$element.offset(), { height: this.$element[0].offsetHeight @@ -29,20 +30,24 @@ $( 'input#languagefilter' ).focus(); return this; }, + hide: function() { this.$menu.hide(); this.shown = false; return this; }, + render: function() { // Rendering stuff here }, + setLang: function( langCode ) { // TODO: dependency on MediaWiki var uri = new mw.Uri( window.location.href ); uri.extend( { setlang: langCode } ); window.location.href = uri.toString(); }, + listen: function() { var that = this; // Register all event listeners to the ULS here. @@ -54,7 +59,7 @@ clickhandler: function( langCode ) { that.setLang( langCode ); } - }).data( "lcd" ); + } ).data( "lcd" ); $( "#languagefilter" ).languagefilter( { $target: $lcd, //$( 'ul.uls-language-filter-result' ), languages: that.languages @@ -63,7 +68,7 @@ // Create region selectors, one per region $( '.uls-region' ).regionselector( { $target: $lcd, - //FIXME This is confusing: languages and source are actually data for ULS. + // FIXME This is confusing: languages and source are actually data for ULS. languages: that.languages, callback: function () { // clear the search field. @@ -73,6 +78,7 @@ // trigger a search for all languages. $( "#languagefilter" ).languagefilter( "search" ); }, + keyup: function( e ) { switch( e.keyCode ) { case 27: // escape @@ -84,6 +90,7 @@ e.stopPropagation(); e.preventDefault(); }, + keypress: function( e ) { if ( !this.shown ) { return; @@ -96,6 +103,7 @@ } e.stopPropagation(); }, + click: function( e ) { e.stopPropagation(); e.preventDefault(); diff --git a/resources/ext.uls.data.utils.js b/resources/ext.uls.data.utils.js index 6988b07c..05cb7fb7 100644 --- a/resources/ext.uls.data.utils.js +++ b/resources/ext.uls.data.utils.js @@ -1,11 +1,11 @@ -/* +/** * @author Amir E. Aharoni - * Utilities for querying language data. + * Utility functions for querying language data. */ (function ( $ ) { "use strict"; - /* + /** * Returns the script of the language. * @param string language code * @return string @@ -14,7 +14,7 @@ return $.uls.data.languages[language][0]; }; - /* + /** * Returns the regions in which a language is spoken. * @param string language code * @return array of strings @@ -23,7 +23,7 @@ return $.uls.data.languages[language][1]; }; - /* + /** * Returns the autonym of the language. * @param string language code * @return string @@ -32,7 +32,7 @@ return $.uls.data.autonyms[language]; }; - /* + /** * Returns all languages written in script. * @param script string * @return array of strings (languages codes) @@ -41,7 +41,7 @@ return $.uls.data.languagesInScripts( [ script ] ); }; - /* + /** * Returns all languages written in the given scripts. * @param scripts array of strings * @return array of strings (languages codes) @@ -61,7 +61,7 @@ return languagesInScripts; }; - /* + /** * Returns all languages in a given region. * @param region string * @return array of strings (languages codes) @@ -70,7 +70,7 @@ return $.uls.data.languagesInRegions( [ region ] ); }; - /* + /** * Returns all languages in given regions. * @param region array of strings. * @return array of strings (languages codes) @@ -90,7 +90,16 @@ return languagesInRegions; }; - /* + /** + * Returns all languages in a region group. + * @param groupNum number. + * @return array of strings (languages codes) + */ + $.uls.data.languagesInRegionGroup = function( groupNum ) { + return $.uls.data.languagesInRegions( $.uls.data.regionsInGroup( groupNum ) ); + }; + + /** * Returns an associative array of languages in a region, * grouped by script. * @param string region code @@ -112,7 +121,84 @@ return languagesByScriptInRegion; }; - /* + /** + * Returns an associative array of languages in a region, + * grouped by script group. + * @param string region code + * @return associative array + */ + $.uls.data.languagesByScriptGroupInRegion = function( region ) { + return $.uls.data.languagesByScriptGroupInRegions( [ region ] ); + }; + + /** + * Returns an associative array of languages in several regions, + * grouped by script group. + * @param array of strings - region codes + * @return associative array + */ + $.uls.data.languagesByScriptGroupInRegions = function( regions ) { + var languagesByScriptGroupInRegions = {}; + + for ( var language in $.uls.data.languages ) { + for ( var i = 0; i < regions.length; i++ ) { + if ( $.inArray( regions[i], $.uls.data.regions( language ) ) !== -1 ) { + var scriptGroup = $.uls.data.scriptGroupOfLanguage( language ); + if ( languagesByScriptGroupInRegions[scriptGroup] === undefined ) { + languagesByScriptGroupInRegions[scriptGroup] = []; + } + languagesByScriptGroupInRegions[scriptGroup].push( language ); + break; + } + } + } + + return languagesByScriptGroupInRegions; + }; + + /** + * Returns an array of languages grouped by region group, + * region, script group and script. + * @return associative array + */ + $.uls.data.allLanguagesByRegionAndScript = function() { + var allLanguagesByRegionAndScript = {}, + region, + regionGroup; + + for ( region in $.uls.data.regiongroups ) { + regionGroup = $.uls.data.regiongroups[region]; + if ( allLanguagesByRegionAndScript[regionGroup] === undefined ) { + allLanguagesByRegionAndScript[regionGroup] = {}; + } + allLanguagesByRegionAndScript[regionGroup][region] = {}; + } + + for ( var language in $.uls.data.languages ) { + var script = $.uls.data.script( language ); + var scriptGroup = $.uls.data.groupOfScript( script ); + var regions = $.uls.data.regions( language ); + + for ( var regionNum = 0; regionNum < regions.length; regionNum++ ) { + region = regions[regionNum]; + regionGroup = $.uls.data.regiongroups[region]; + + if ( allLanguagesByRegionAndScript[regionGroup][region][scriptGroup] === undefined ) { + allLanguagesByRegionAndScript[regionGroup][region][scriptGroup] = {}; + } + + if ( allLanguagesByRegionAndScript[regionGroup][region][scriptGroup][script] === undefined ) { + allLanguagesByRegionAndScript[regionGroup][region][scriptGroup][script] = []; + } + + allLanguagesByRegionAndScript[regionGroup][region][scriptGroup][script].push( language ); + } + } + + return allLanguagesByRegionAndScript; + }; + + /** * Returns all regions in a region group. * @param number groupNum * @return array of strings @@ -129,7 +215,7 @@ return regionsInGroup; }; - /* + /** * Returns the script group of a script or 'Other' if it doesn't * belong to any group. * @param string script code @@ -145,9 +231,13 @@ return 'Other'; }; - $.uls.data.sortByScriptGroup = function( languages ) { - // FIXME sort it. - return languages; + /** + * Returns the script group of a language. + * @param string language code + * @return string script group name + */ + $.uls.data.scriptGroupOfLanguage = function( language ) { + return $.uls.data.groupOfScript( $.uls.data.script( language ) ); }; } )( jQuery ); diff --git a/resources/ext.uls.languagefilter.js b/resources/ext.uls.languagefilter.js index 646d7488..c529e19e 100644 --- a/resources/ext.uls.languagefilter.js +++ b/resources/ext.uls.languagefilter.js @@ -21,8 +21,8 @@ listen: function() { this.$element.on( 'keyup', $.proxy( this.keyup, this )); if ( $.browser.webkit || $.browser.msie ) { - this.$element.on( 'keydown', $.proxy( this.keyup, this ) ) - }; + this.$element.on( 'keydown', $.proxy( this.keyup, this ) ); + } }, keyup: function( e ) { @@ -34,23 +34,24 @@ var that = this; var languages = this.options.languages; var query = this.$element.val(); - $.each( languages, function ( code, name ) { + + $.each( languages, function ( langCode, name ) { if ( query === "" ) { - that.render(code); + that.render( langCode ); } - else if ( that.filter( code, query ) ) { - that.render(code); + else if ( that.filter( langCode, query ) ) { + that.render( langCode ); } } ) ; }, - render : function( code ) { + render: function( langCode ) { var that = this; var $target = this.options.$target; if ( !$target ) { return; } - $target.append(code); + $target.append( langCode ); }, escapeRegex: function( value ) { @@ -65,13 +66,14 @@ * c) ISO 639 code match with search string. * d) ISO 15924 code for the script match the search string. */ - filter: function( code, searchTerm ) { + filter: function( langCode, searchTerm ) { // FIXME script is ISO 15924 code. We might need actual name of script. var matcher = new RegExp( this.escapeRegex( searchTerm ), 'i' ); - return matcher.test( this.options.languages[code] ) || - matcher.test( $.uls.data.autonym( code ) ) || - matcher.test( code ) || - matcher.test( $.uls.data.script( code ) ); + + return matcher.test( this.options.languages[langCode] ) || + matcher.test( $.uls.data.autonym( langCode ) ) || + matcher.test( langCode ) || + matcher.test( $.uls.data.script( langCode ) ); } }; @@ -80,7 +82,7 @@ return this.each( function() { var $this = $( this ), data = $this.data( 'languagefilter' ), - options = typeof option == 'object' && option; + options = typeof option === 'object' && option; if ( !data ) { $this.data( 'languagefilter', ( data = new LanguageFilter( this, options ) ) ); } @@ -91,17 +93,16 @@ }; $.fn.languagefilter.defaults = { - $target: null, // where to append the results - languages: null, // languages as code:name format. default values is from data-languages - clickhandler: null, + $target: null, // Where to append the results + languages: null, // Languages as code:name format. Default values come from data.languages. + clickhandler: null }; $.fn.languagefilter.Constructor = LanguageFilter; - /* RegionSelector Plugin Definition */ - /* + /** * Region selector is a language selector based on regions. * Usage: $( 'jqueryselector' ).regionselector( options ); * The attached element should have data-regiongroup attribute @@ -117,11 +118,11 @@ RegionSelector.prototype = { constructor: RegionSelector, + test: function( langCode ) { - var that = this; - var languages = $.uls.data.languages; - var regionGroups = $.uls.data.regiongroups; - var regions = languages[langCode][1]; + var that = this, + regionGroups = $.uls.data.regiongroups, + regions = $.uls.data.regions( langCode ); // 1. loop over all regiongroups - like {EU: 2, AF: 2, AS: 3 ...} // 2. check that the region matches the active region group // 3. if this language is included in that region, show it @@ -133,11 +134,9 @@ } } ); }, - show: function() { - var that = this, - languages = $.uls.data.languages; - languages = $.uls.data.sortByScriptGroup( languages ); + show: function() { + var that = this; // Make the selected region (and it only) active $( '.regionselector' ).removeClass( 'active' ); @@ -145,29 +144,39 @@ // Repopulate the list of languages that.options.$target.empty(); - $.each( languages, function( langCode, langDef ) { - that.test( langCode ); - } ); + + var regions = $.uls.data.regionsInGroup( that.regionGroup ); + var languagesInRegion = $.uls.data.languagesByScriptGroupInRegions( regions ); + for ( var scriptGroup in languagesInRegion ) { + for ( var langNum = 0; langNum < languagesInRegion[scriptGroup].length; langNum++ ) { + that.test( languagesInRegion[scriptGroup][langNum] ); + } + } + if ( that.options.callback ) { that.options.callback.call(); } }, - render: function( langCode, region) { + + render: function( langCode, region ) { var $target = this.options.$target; if ( !$target ) { return; } $target.append( langCode, region ); }, - listen: function(){ + + listen: function() { this.$element.on( 'click', $.proxy( this.click, this ) ); }, + click: function( e ) { e.stopPropagation(); e.preventDefault(); this.show(); } }; + /* RegionSelector Plugin Definition */ $.fn.regionselector = function( option ) { @@ -175,6 +184,7 @@ var $this = $( this ), data = $this.data( 'regionselector' ), options = typeof option === 'object' && option; + if ( !data ) { $this.data( 'regionselector', ( data = new RegionSelector( this, options ) ) ); } @@ -191,5 +201,4 @@ $.fn.regionselector.Constructor = RegionSelector; - } )( jQuery ); diff --git a/resources/ext.uls.lcd.js b/resources/ext.uls.lcd.js index ea38afcc..788cb707 100644 --- a/resources/ext.uls.lcd.js +++ b/resources/ext.uls.lcd.js @@ -16,6 +16,7 @@ var that = this; this.addToRegion( langCode, regionCode ); }, + /** * Add the language to a region. * If the region parameter is given , add to that region alone @@ -27,6 +28,10 @@ var that = this, language = $.uls.data.languages[langCode]; + // TODO: This shouldn't happen. + // This currently happens with some special cases, such as qqq and + // some codes that are incorrectly used in Wikimedia projects for + // historical reasons. if ( !language ) { console.log( "Definition for " + langCode + " was not found in the language database." ); return; @@ -37,7 +42,7 @@ var regions = []; if ( region ) { regions.push( region ); - } else{ + } else { regions = $.uls.data.regions( langCode ); } @@ -49,7 +54,10 @@ .append( $( '' ).prop( 'href', '#' ).html( langName ) ); - that.getColumn( regionCode ).append( $li ); + + // Append the element to the column in the list + var column = that.getColumn( regionCode ); + column.append( $li ); if ( that.options.clickhandler ) { $li.click( function() { @@ -60,12 +68,16 @@ }, getColumn: function( regionCode ) { - var $ul = $( "div#" + regionCode ).find( 'ul:last' ); - if ( $ul.length === 0 || $ul.find( 'li' ).length >= 10) { + var $divRegionCode = $( 'div#' + regionCode ); + + var $ul = $divRegionCode.find( 'ul:last' ); + if ( $ul.length === 0 || $ul.find( 'li' ).length >= 10 ) { $ul = $( '