From a759f0ecbe936684fb6de21da149763568f15163 Mon Sep 17 00:00:00 2001 From: Santhosh Thottingal Date: Mon, 25 Jun 2012 16:46:38 +0530 Subject: [PATCH] Introduce regionfilter RegionFilter is a basic jquery plugin to work with ULS to select languages based on regions. PS2: Added a css class for elements with regionfilter. Used it for visual indication of selection. Plus some clean up. Change-Id: Ib01b4077435f98665075310e285e68f8538eeb4e --- UniversalLanguageSelector.hooks.php | 10 +- resources/css/ext.uls.css | 4 +- resources/ext.uls.core.js | 51 +++++---- resources/ext.uls.languagefilter.js | 154 ++++++++++++++++++++++------ 4 files changed, 158 insertions(+), 61 deletions(-) diff --git a/UniversalLanguageSelector.hooks.php b/UniversalLanguageSelector.hooks.php index dbc71b9e..2be59ac1 100644 --- a/UniversalLanguageSelector.hooks.php +++ b/UniversalLanguageSelector.hooks.php @@ -59,7 +59,7 @@ class UniversalLanguageSelectorHooks { $languages = Language::fetchLanguageNames( $wgContLang->getCode() ); $languageData = htmlspecialchars( FormatJSON::encode( $languages ) ); $data .= " -
+
@@ -67,13 +67,13 @@ class UniversalLanguageSelectorHooks {
-
+ -
+ - @@ -83,7 +83,7 @@ class UniversalLanguageSelectorHooks {
+ class=\"filterinput\">
diff --git a/resources/css/ext.uls.css b/resources/css/ext.uls.css index ccb2deda..da1e8541 100644 --- a/resources/css/ext.uls.css +++ b/resources/css/ext.uls.css @@ -78,11 +78,9 @@ .uls-region:hover { outline: 1px solid #0E90D2; - background: black; - opacity: 0.4; } -.uls-region.active { +.regionselector.active { background: black; opacity: 0.4; } diff --git a/resources/ext.uls.core.js b/resources/ext.uls.core.js index 343903ee..4f02e7e6 100644 --- a/resources/ext.uls.core.js +++ b/resources/ext.uls.core.js @@ -1,10 +1,11 @@ -(function ( $, mw ) { +(function ( $ ) { "use strict"; var ULS = function( element, options ) { this.$element = $( element ); this.options = $.extend( {}, $.fn.uls.defaults, options ); this.$menu = $( this.options.menu ); + this.languages = this.$menu.data( 'languages' ); this.shown = false; this.render(); this.listen(); @@ -36,29 +37,36 @@ 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. - this.$element.on( 'click', $.proxy( this.click, this ) ); - $( ".icon-close" ).on( 'click', $.proxy( this.click, this ) ); + that.$element.on( 'click', $.proxy( that.click, that ) ); + $( ".icon-close" ).on( 'click', $.proxy( that.click, that ) ); $( "#languagefilter" ).languagefilter( { $target: $( 'ul.uls-language-filter-result' ), - clickhandler: function( item ) { - // TODO: dependency on MediaWiki - var uri = new mw.Uri( window.location.href ); - uri.extend( { setlang: item.value } ); - window.location.href = uri.toString(); - } + clickhandler: function( langCode ) { + that.setLang( langCode ); + }, + languages: that.languages } ); - $( '.uls-region' ).live( 'click', function ( e ) { - var id = $( this ).attr( 'id' ); - var active = $( this ).hasClass( 'active' ); - $( this ).parent().find( '.uls-region' ).removeClass( 'active' ); - if ( active ) { - $( '.uls-language-list li' ).show(); - } else { - $( this ).addClass( 'active' ); - $( '.uls-language-list li' ).not( '.' + id ).hide(); - $( '.uls-language-list li.' + id ).show(); + // 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. + languages: that.languages, + source: langdb, + callback: function () { + // clear the search field. + $( "#languagefilter" ).val( "" ); } } ); // trigger a search for all languages. @@ -97,7 +105,8 @@ } else { this.hide(); } - }, + } + }; /* ULS PLUGIN DEFINITION @@ -121,4 +130,4 @@ $.fn.uls.Constructor = ULS; -} )( jQuery, mediaWiki ); +} )( jQuery ); diff --git a/resources/ext.uls.languagefilter.js b/resources/ext.uls.languagefilter.js index 8374381a..1b9edb50 100644 --- a/resources/ext.uls.languagefilter.js +++ b/resources/ext.uls.languagefilter.js @@ -6,18 +6,14 @@ * the data is in the format of languagecode:languagename format. * Credits: http://jqueryui.com/demos/autocomplete */ -jQuery( function( $ ) { +(function ( $ ) { "use strict"; - $.widget( "ui.languagefilter", { - options: { - $target: null, // where to append the results - languages: null, // languages as code:name format. default values is from data-languages - clickhandler: null - }, + var LanguageFilter = { _create: function() { - var self = this.element, - options = this.options; + var that = this; + var self = that.element, + options = that.options; $( self ).autocomplete( { delay: 0, minLength: 0, @@ -26,7 +22,6 @@ jQuery( function( $ ) { position: { offset: "-10000 -10000" }, source: function( request, response ) { var term = request.term; - var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), 'i' ); var languages = options.languages; if ( languages === null ) { @@ -38,7 +33,7 @@ jQuery( function( $ ) { if ( term === "" ) { return { label: name, value: code }; } - if ( matcher.test( name ) ) { + if ( that.filter.call( this, name, term ) ) { return { label: name.replace( new RegExp( @@ -59,45 +54,140 @@ jQuery( function( $ ) { } ); // /autocomplete $( self ).data( "autocomplete" )._renderItem = function ( $target, item ) { - var activeregion, classes, region, i, regionlist; - $target = options.$target; if ( !$target ) { return; } - - regionlist = langdb.languages[item.value] || ["unknown", ["unknown"]]; - regionlist = regionlist[1]; - for ( i = 0; i < regionlist.length; i++ ) { - region = langdb.regiongroups[regionlist[i]] - if ( region ) { - classes = classes + " uls-region-" + region; - } - } var $li = $( "
  • " ) .data( "code", item.value ) - .addClass( classes ) .data( "item.autocomplete", item ) .append( $( "" ).prop( 'href', '#' ). html( item.label ) ) .appendTo( $target ); - activeregion = $( '.uls-region.active' ).attr( 'id' ); - if ( activeregion && !$li.hasClass( activeregion ) ) { - $li.hide(); - } - if ( options.clickhandler ) { $li.click( function() { - options.clickhandler.call( this, item ); + options.clickhandler.call( this, item.value ); } ); } return $li; - }; }, // End of _create destroy: function() { $.Widget.prototype.destroy.call( this ); + }, + + filter: function( langName, searchTerm ) { + var matcher = new RegExp( $.ui.autocomplete.escapeRegex( searchTerm ), 'i' ); + return matcher.test( langName ); + }, + + options: { + $target: null, // where to append the results + languages: null, // languages as code:name format. default values is from data-languages + clickhandler: null, } - } ); -} ); + }; + + $.widget( "ui.languagefilter", LanguageFilter ); + + + /* + * Region selector is a language selector based on regions. + * Usage: $( 'jqueryselector' ).regionselector(options); + * The attached element should have data-region attribute + * that defines the region for the selector. + */ + var RegionSelector = function( element, options ) { + this.$element = $( element ); + this.options = $.extend( {}, $.fn.regionselector.defaults, options ); + this.$element.addClass( 'regionselector' ); + this.listen(); + this.region = this.$element.data( 'region' ); + }; + + RegionSelector.prototype = { + constructor: RegionSelector, + test: function( langCode ) { + var that = this; + var languages = that.options.source.languages; + var regionGroups = that.options.source.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 + // 3. if this language is included in that region, show it + // 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; + } + } ); + return false; + }, + show: function() { + var that = this; + var languages = that.options.source.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 ) { + that.test( langCode ); + } ); + if ( that.options.callback ) { + 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 ); + } ); + } + }, + 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 ) { + return this.each( function() { + var $this = $( this ), + data = $this.data( 'regionselector' ), + options = typeof option == 'object' && option; + if ( !data ) { + $this.data( 'regionselector', ( data = new RegionSelector( this, options ) ) ); + } + if ( typeof option === 'string' ) { + data[option](); + } + } ); + }; + + $.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. + }; + + $.fn.regionselector.Constructor = RegionSelector; + + +} )( jQuery ); \ No newline at end of file