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
This commit is contained in:
Santhosh Thottingal
2012-06-25 16:46:38 +05:30
parent 4a782cbd65
commit a759f0ecbe
4 changed files with 158 additions and 61 deletions

View File

@@ -59,7 +59,7 @@ class UniversalLanguageSelectorHooks {
$languages = Language::fetchLanguageNames( $wgContLang->getCode() ); $languages = Language::fetchLanguageNames( $wgContLang->getCode() );
$languageData = htmlspecialchars( FormatJSON::encode( $languages ) ); $languageData = htmlspecialchars( FormatJSON::encode( $languages ) );
$data .= " $data .= "
<div class=\"uls-menu\"> <div class=\"uls-menu\" data-languages=\"" . $languageData . "\">
<span class=\"icon-close\"></span> <span class=\"icon-close\"></span>
<div class=\"uls-menu-header\"> <div class=\"uls-menu-header\">
<div class=\"uls-menu-header-left\"> <div class=\"uls-menu-header-left\">
@@ -67,13 +67,13 @@ class UniversalLanguageSelectorHooks {
</div> </div>
<div class=\"uls-menu-header-right\"> <div class=\"uls-menu-header-right\">
<div class='uls-worldmap'> <div class='uls-worldmap'>
<div class='uls-region' id='uls-region-1'> <div class='uls-region' id='uls-region-1' data-region='1'>
<a>North America<br>Latin America<br>South America</a> <a>North America<br>Latin America<br>South America</a>
</div> </div>
<div class='uls-region' id='uls-region-2'> <div class='uls-region' id='uls-region-2' data-region='2'>
<a>Europe<br>Middle East<br>Africa</a> <a>Europe<br>Middle East<br>Africa</a>
</div> </div>
<div class='uls-region' id='uls-region-3'> <div class='uls-region' id='uls-region-3' data-region='3'>
<a>Asia<br>Australia<br>Pacific</a> <a>Asia<br>Australia<br>Pacific</a>
</div> </div>
</div> </div>
@@ -83,7 +83,7 @@ class UniversalLanguageSelectorHooks {
<div class=\"uls-lang-selector\"> <div class=\"uls-lang-selector\">
<form action=\"#\" class=\"filterform\"> <form action=\"#\" class=\"filterform\">
<input type=\"text\" placeholder=\"Language search\" id=\"languagefilter\" <input type=\"text\" placeholder=\"Language search\" id=\"languagefilter\"
class=\"filterinput\" data-languages=\"" . $languageData . "\"> class=\"filterinput\">
<span class=\"search-button\"></span> <span class=\"search-button\"></span>
</form> </form>
<div class=\"uls-language-list\" > <div class=\"uls-language-list\" >

View File

@@ -78,11 +78,9 @@
.uls-region:hover { .uls-region:hover {
outline: 1px solid #0E90D2; outline: 1px solid #0E90D2;
background: black;
opacity: 0.4;
} }
.uls-region.active { .regionselector.active {
background: black; background: black;
opacity: 0.4; opacity: 0.4;
} }

View File

@@ -1,10 +1,11 @@
(function ( $, mw ) { (function ( $ ) {
"use strict"; "use strict";
var ULS = function( element, options ) { var ULS = function( element, options ) {
this.$element = $( element ); this.$element = $( element );
this.options = $.extend( {}, $.fn.uls.defaults, options ); this.options = $.extend( {}, $.fn.uls.defaults, options );
this.$menu = $( this.options.menu ); this.$menu = $( this.options.menu );
this.languages = this.$menu.data( 'languages' );
this.shown = false; this.shown = false;
this.render(); this.render();
this.listen(); this.listen();
@@ -36,29 +37,36 @@
render: function() { render: function() {
// Rendering stuff here // Rendering stuff here
}, },
listen: function() { setLang: function( langCode ) {
// Register all event listeners to the ULS here.
this.$element.on( 'click', $.proxy( this.click, this ) );
$( ".icon-close" ).on( 'click', $.proxy( this.click, this ) );
$( "#languagefilter" ).languagefilter( {
$target: $( 'ul.uls-language-filter-result' ),
clickhandler: function( item ) {
// TODO: dependency on MediaWiki // TODO: dependency on MediaWiki
var uri = new mw.Uri( window.location.href ); var uri = new mw.Uri( window.location.href );
uri.extend( { setlang: item.value } ); uri.extend( { setlang: langCode } );
window.location.href = uri.toString(); window.location.href = uri.toString();
} },
listen: function() {
var that = this;
// Register all event listeners to the ULS here.
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( langCode ) {
that.setLang( langCode );
},
languages: that.languages
} ); } );
$( '.uls-region' ).live( 'click', function ( e ) { // Create region selectors, one per region
var id = $( this ).attr( 'id' ); $( '.uls-region' ).regionselector( {
var active = $( this ).hasClass( 'active' ); $target: $( 'ul.uls-language-filter-result' ),
$( this ).parent().find( '.uls-region' ).removeClass( 'active' ); clickhandler: function( langCode ) {
if ( active ) { that.setLang( langCode );
$( '.uls-language-list li' ).show(); },
} else { //FIXME This is confusing: languages and source are acturally data for ULS.
$( this ).addClass( 'active' ); languages: that.languages,
$( '.uls-language-list li' ).not( '.' + id ).hide(); source: langdb,
$( '.uls-language-list li.' + id ).show(); callback: function () {
// clear the search field.
$( "#languagefilter" ).val( "" );
} }
} ); } );
// trigger a search for all languages. // trigger a search for all languages.
@@ -97,7 +105,8 @@
} else { } else {
this.hide(); this.hide();
} }
}, }
}; };
/* ULS PLUGIN DEFINITION /* ULS PLUGIN DEFINITION
@@ -121,4 +130,4 @@
$.fn.uls.Constructor = ULS; $.fn.uls.Constructor = ULS;
} )( jQuery, mediaWiki ); } )( jQuery );

View File

@@ -6,18 +6,14 @@
* the data is in the format of languagecode:languagename format. * the data is in the format of languagecode:languagename format.
* Credits: http://jqueryui.com/demos/autocomplete * Credits: http://jqueryui.com/demos/autocomplete
*/ */
jQuery( function( $ ) { (function ( $ ) {
"use strict"; "use strict";
$.widget( "ui.languagefilter", { var LanguageFilter = {
options: {
$target: null, // where to append the results
languages: null, // languages as code:name format. default values is from data-languages
clickhandler: null
},
_create: function() { _create: function() {
var self = this.element, var that = this;
options = this.options; var self = that.element,
options = that.options;
$( self ).autocomplete( { $( self ).autocomplete( {
delay: 0, delay: 0,
minLength: 0, minLength: 0,
@@ -26,7 +22,6 @@ jQuery( function( $ ) {
position: { offset: "-10000 -10000" }, position: { offset: "-10000 -10000" },
source: function( request, response ) { source: function( request, response ) {
var term = request.term; var term = request.term;
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), 'i' );
var languages = options.languages; var languages = options.languages;
if ( languages === null ) { if ( languages === null ) {
@@ -38,7 +33,7 @@ jQuery( function( $ ) {
if ( term === "" ) { if ( term === "" ) {
return { label: name, value: code }; return { label: name, value: code };
} }
if ( matcher.test( name ) ) { if ( that.filter.call( this, name, term ) ) {
return { return {
label: name.replace( label: name.replace(
new RegExp( new RegExp(
@@ -59,45 +54,140 @@ jQuery( function( $ ) {
} ); // /autocomplete } ); // /autocomplete
$( self ).data( "autocomplete" )._renderItem = function ( $target, item ) { $( self ).data( "autocomplete" )._renderItem = function ( $target, item ) {
var activeregion, classes, region, i, regionlist;
$target = options.$target; $target = options.$target;
if ( !$target ) { if ( !$target ) {
return; 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 = $( "<li>" ) var $li = $( "<li>" )
.data( "code", item.value ) .data( "code", item.value )
.addClass( classes )
.data( "item.autocomplete", item ) .data( "item.autocomplete", item )
.append( $( "<a>" ).prop( 'href', '#' ). html( item.label ) ) .append( $( "<a>" ).prop( 'href', '#' ). html( item.label ) )
.appendTo( $target ); .appendTo( $target );
activeregion = $( '.uls-region.active' ).attr( 'id' );
if ( activeregion && !$li.hasClass( activeregion ) ) {
$li.hide();
}
if ( options.clickhandler ) { if ( options.clickhandler ) {
$li.click( function() { $li.click( function() {
options.clickhandler.call( this, item ); options.clickhandler.call( this, item.value );
} ); } );
} }
return $li; return $li;
}; };
}, // End of _create }, // End of _create
destroy: function() { destroy: function() {
$.Widget.prototype.destroy.call( this ); $.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 = $( "<li>" )
.data( "code", langCode )
.append( $( "<a>" ).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 );