(bug 38670) Provide a no results found view

Provide a view showing:
- A feedback message where the current search term is displayed.
- Suggested options: based on likely languages and languages with one
additional level of editing distance than the used in the search algorithm.
- Instructions for search and browse including links to all the sub-regions
available.

* Introduced success, noresults callbacks for language and region filters
* Region filter can be a link for a region alone.

Change-Id: I713b62911bb32e1b1427320ced767b144180c5c4
This commit is contained in:
pginer
2012-07-25 16:00:05 +02:00
committed by Santhosh Thottingal
parent 08c14dafa4
commit 5b055bdf5b
7 changed files with 131 additions and 34 deletions

View File

@@ -113,6 +113,22 @@ class UniversalLanguageSelectorHooks {
</div> </div>
</div> </div>
<div class='row uls-language-list'></div> <div class='row uls-language-list'></div>
<div class='row uls-no-results-view'>
<h2 class='ten columns end offset-by-one'>No results found for \"<span id='uls-no-found-search-term'></span>\"</h2>
<div id='uls-no-found-more'>
<div class='ten columns end offset-by-one'>
<p>You can search by language name, script name, ISO code of language or you can browse by region:
<a class='uls-region-link' data-region='NA' href='#'>America</a>,
<a class='uls-region-link' data-region='EU' href='#'>Europe</a>,
<a class='uls-region-link' data-region='ME' href='#'>Middle East</a>,
<a class='uls-region-link' data-region='AF' href='#'>Africa</a>,
<a class='uls-region-link' data-region='AS' href='#'>Asia</a>,
<a class='uls-region-link' data-region='PA' href='#'>Pacific</a> or
<a class='uls-region-link' data-region='WW' href='#'>Worldwide languages</a>.
</p>
</div>
</div>
</div>
</div>"; </div>";
return true; return true;
} }

View File

@@ -101,6 +101,21 @@
</div> </div>
</div> </div>
<div class="row uls-language-list"></div> <div class="row uls-language-list"></div>
<div class="row uls-no-results-view">
<h2 class="ten columns end offset-by-one">No results found for "<span id="uls-no-found-search-term">Esapnol</span>"</h2>
<div id="uls-no-found-more">
<div class="ten columns end offset-by-one">
<p>You can search by language name, script name, ISO code of language or you can browse by region:
<a class="uls-region-link" data-region="NA" href="#">America</a>,
<a class="uls-region-link" data-region="EU" href="#">Europe</a>,
<a class="uls-region-link" data-region="ME" href="#">Middle East</a>,
<a class="uls-region-link" data-region="AF" href="#">Africa</a>,
<a class="uls-region-link" data-region="AS" href="#">Asia</a>,
<a class="uls-region-link" data-region="PA" href="#">Pacific</a> or
<a class="uls-region-link" data-region="WW" href="#">Worldwide languages</a>.
</p>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -42,10 +42,18 @@
padding-left: 15px; padding-left: 15px;
color: #777; color: #777;
} }
.uls-menu h2 {
padding-left: 6px;
margin-top: 0px;
margin-bottom: 15px;
border-bottom: none;
color: #777;
}
.uls-menu h3 { .uls-menu h3 {
padding-left: 0px; padding-left: 0px;
margin-top: 0px; margin-top: 0px;
margin-bottom: 15px; margin-bottom: 15px;
border-bottom: none;
} }
.uls-worldmap { .uls-worldmap {
/* @embed */ /* @embed */

View File

@@ -34,15 +34,25 @@
.uls-language-block .three.columns { .uls-language-block .three.columns {
width: 22%; width: 22%;
} }
.uls-language-list-footer .three.columns { .uls-language-list-footer .three.columns {
width: 22%; width: 22%;
} }
.uls-language-block {
.uls-language-block{ width: 100%;
width:100%; }
.uls-no-results-view {
color: #777;
}
#uls-no-found-more {
font-size: 0.9em;
background: #F8F8F8;
display: inline-block;
width: 100%;
margin-top: 1.6em;
line-height: 1.6em;
} }

View File

@@ -33,6 +33,9 @@
} }
this.shown = false; this.shown = false;
this.$languageFilter = $( 'input#languagefilter' ); this.$languageFilter = $( 'input#languagefilter' );
this.$noResultsView = $( 'div.uls-no-results-view' );
this.$resultsView = $( 'div.uls-language-list' );
this.$noResultsView.hide();
this.render(); this.render();
this.listen(); this.listen();
this.ready(); this.ready();
@@ -70,8 +73,20 @@
// Rendering stuff here // Rendering stuff here
}, },
noresults: function( search ) {
this.$noResultsView.show();
// FIXME i18n
this.$noResultsView.find( 'span#uls-no-found-search-term' ).text( search );
this.$resultsView.hide();
},
success: function() {
this.$noResultsView.hide();
this.$resultsView.show();
},
listen: function() { listen: function() {
var that = this, $lcd; var that = this, lcd;
// Register all event listeners to the ULS here. // Register all event listeners to the ULS here.
that.$element.on( 'click', $.proxy( that.click, that ) ); that.$element.on( 'click', $.proxy( that.click, that ) );
@@ -85,7 +100,7 @@
this.$menu.on( 'keydown', $.proxy( this.keypress, this ) ) this.$menu.on( 'keydown', $.proxy( this.keypress, this ) )
} }
$lcd = $( 'div.uls-language-list' ).lcd( { lcd = that.$resultsView.lcd( {
languages: that.languages, languages: that.languages,
clickhandler: function( langCode ) { clickhandler: function( langCode ) {
if ( that.options.onSelect ) { if ( that.options.onSelect ) {
@@ -95,19 +110,21 @@
} ).data( "lcd" ); } ).data( "lcd" );
that.$languageFilter.languagefilter( { that.$languageFilter.languagefilter( {
$target: $lcd, //$( 'ul.uls-language-filter-result' ), $target: lcd,
languages: that.languages, languages: that.languages,
success: $.proxy( that.success, that ),
noresults: $.proxy( that.noresults, that ),
searchAPI: that.options.searchAPI searchAPI: that.options.searchAPI
} ); } );
// Create region selectors, one per region // Create region selectors, one per region
$( '.uls-region' ).regionselector( { $( '.uls-region, .uls-region-link' ).regionselector( {
$target: $lcd, $target: lcd,
// FIXME This is confusing: languages and source are actually data for ULS.
languages: that.languages, languages: that.languages,
callback: function () { success: function() {
// clear the search field. // clear the search field.
that.$languageFilter.val( "" ); that.$languageFilter.val( '' );
that.success();
} }
} ); } );

View File

@@ -30,6 +30,7 @@
this.$element = $( element ); this.$element = $( element );
this.options = $.extend( {}, $.fn.regionselector.defaults, options ); this.options = $.extend( {}, $.fn.regionselector.defaults, options );
this.$element.addClass( 'languagefilter' ); this.$element.addClass( 'languagefilter' );
this.resultCount = 0;
this.listen(); this.listen();
}; };
@@ -51,17 +52,21 @@
var query = $.trim( this.$element.val() ), var query = $.trim( this.$element.val() ),
languages = $.uls.data.languagesByScriptGroup( this.options.languages ), languages = $.uls.data.languagesByScriptGroup( this.options.languages ),
scriptGroup, langNum, langCode; scriptGroup, langNum, langCode;
this.resultCount = 0;
for ( scriptGroup in languages ) { for ( scriptGroup in languages ) {
for ( langNum = 0; langNum < languages[scriptGroup].length; langNum++ ) { for ( langNum = 0; langNum < languages[scriptGroup].length; langNum++ ) {
langCode = languages[scriptGroup][langNum]; langCode = languages[scriptGroup][langNum];
if ( query === "" || this.filter( langCode, query ) ) { if ( query === "" || this.filter( langCode, query ) ) {
this.render( langCode ); this.render( langCode );
this.resultCount++;
} }
} }
} }
// Also do a search to search API // Also do a search by search API
if( this.options.searchAPI && query){ if( this.options.searchAPI && query ) {
this.searchAPI( query ); this.searchAPI( query );
} else {
this.resultHandler( query );
} }
}, },
@@ -70,10 +75,25 @@
$.get( that.options.searchAPI, { search: query }, function( result ) { $.get( that.options.searchAPI, { search: query }, function( result ) {
$.each( result['languagesearch'], function( code, name ) { $.each( result['languagesearch'], function( code, name ) {
that.render( code, name ); that.render( code, name );
that.resultCount++;
} ); } );
that.resultHandler( query );
} ); } );
}, },
/**
* Handler method to be called once search is over.
* Based on search result call success or noresults callbacks
* @param String query
*/
resultHandler: function( query ) {
if ( this.resultCount === 0 && this.options.noresults ) {
this.options.noresults.call( this, query );
} else if ( this.options.success ) {
this.options.success( this, query, this.resultCount );
}
},
render: function( langCode, languageName ) { render: function( langCode, languageName ) {
var $target = this.options.$target; var $target = this.options.$target;
if ( !$target ) { if ( !$target ) {
@@ -122,14 +142,15 @@
$.fn.languagefilter.defaults = { $.fn.languagefilter.defaults = {
$target: null, // Where to append the results $target: null, // Where to append the results
languages: null, // Languages as code:name format. Default values come from data.languages. searchAPI: null,
clickhandler: null, languages: null, // Languages as code:name format.
searchAPI: null noresults: null, // callback for no results found case
success: null // callback if any results found.
}; };
$.fn.languagefilter.Constructor = LanguageFilter; $.fn.languagefilter.Constructor = LanguageFilter;
/* RegionSelector Plugin Definition */ /* RegionSelector plugin definition */
/** /**
* Region selector is a language selector based on regions. * Region selector is a language selector based on regions.
@@ -141,19 +162,28 @@
this.$element = $( element ); this.$element = $( element );
this.options = $.extend( {}, $.fn.regionselector.defaults, options ); this.options = $.extend( {}, $.fn.regionselector.defaults, options );
this.$element.addClass( 'regionselector' ); this.$element.addClass( 'regionselector' );
this.listen(); this.regions = [];
this.regionGroup = this.$element.data( 'regiongroup' ); this.regionGroup = this.$element.data( 'regiongroup' );
this.init();
this.listen();
}; };
RegionSelector.prototype = { RegionSelector.prototype = {
constructor: RegionSelector, constructor: RegionSelector,
init: function() {
var region = this.$element.data( 'region' );
this.regions = $.uls.data.regionsInGroup( this.regionGroup );
if ( region ) {
this.regions.push( region );
}
},
test: function( langCode ) { test: function( langCode ) {
var regions = $.uls.data.regionsInGroup( this.regionGroup ), var langRegions = $.uls.data.regions( langCode ),
langRegions = $.uls.data.regions( langCode ),
region; region;
for ( var i = 0; i < regions.length; i++ ) { for ( var i = 0; i < this.regions.length; i++ ) {
region = regions[i]; region = this.regions[i];
if ( $.inArray( region, langRegions ) >= 0 ) { if ( $.inArray( region, langRegions ) >= 0 ) {
this.render( langCode, region ); this.render( langCode, region );
return; return;
@@ -165,11 +195,12 @@
var i, regions, language, languagesByScriptGroup, scriptGroup, languages; var i, regions, language, languagesByScriptGroup, scriptGroup, languages;
// Make the selected region (and it only) active // Make the selected region (and it only) active
$( '.regionselector' ).removeClass( 'active' ); $( '.regionselector' ).removeClass( 'active' );
if( this.regionGroup ) {
// if there is a region group, make it active.
this.$element.addClass( 'active' ); this.$element.addClass( 'active' );
}
// Re-populate the list of languages // Re-populate the list of languages
this.options.$target.empty(); this.options.$target.empty();
regions = $.uls.data.regionsInGroup( this.regionGroup );
languagesByScriptGroup = $.uls.data.languagesByScriptGroup( this.options.languages ); languagesByScriptGroup = $.uls.data.languagesByScriptGroup( this.options.languages );
for ( scriptGroup in languagesByScriptGroup ) { for ( scriptGroup in languagesByScriptGroup ) {
languages = languagesByScriptGroup[scriptGroup]; languages = languagesByScriptGroup[scriptGroup];
@@ -179,8 +210,8 @@
} }
} }
if ( this.options.callback ) { if ( this.options.success ) {
this.options.callback.call(); this.options.success.call();
} }
}, },
@@ -203,7 +234,7 @@
} }
}; };
/* RegionSelector Plugin Definition */ /* RegionSelector plugin definition */
$.fn.regionselector = function( option ) { $.fn.regionselector = function( option ) {
return this.each( function() { return this.each( function() {
@@ -221,8 +252,8 @@
}; };
$.fn.regionselector.defaults = { $.fn.regionselector.defaults = {
$target: null, // Where to render the results. Must be a ul element $target: null, // Where to render the results
callback: null, // Callback - will be called after results are displayed. success: null, // callback if any results found.
languages: null languages: null
}; };