From 78e9b83c6b0cb8d41fcddc89ff0684bf7daaa929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20Laxstr=C3=B6m?= Date: Fri, 20 Dec 2013 10:31:04 +0000 Subject: [PATCH] Make ULS language selector appear faster after clicking trigger * Removed unused class end. * Class uls-lcd-region-section was used in two different elements, retained it on the outer one. * Build a list of languages per region, once done render the regions at once. * Use direct dom manipulation in hot spots. * Use shorter selectors like children instead of find and dropping the tag name. * Fixed mismatch when there were no results and when the message was shown. * Less flickering by not hiding or showing regions unnecessary * Cache the common languages "quicklist" * Added itemsPerColumn as an option Reduces time used to show language selector after clicking the trigger on my machine from about 1.8s to about 380 ms (JS execution times, actual times are about the same but little bigger. The actual rendering is now less than 100ms, the rest is other setup overheard and $.fn.scrollIntoView which can take many hundreds of milliseconds. --- src/jquery.uls.languagefilter.js | 14 +- src/jquery.uls.lcd.js | 319 ++++++++++++++++++------------- 2 files changed, 195 insertions(+), 138 deletions(-) diff --git a/src/jquery.uls.languagefilter.js b/src/jquery.uls.languagefilter.js index 40b6a86..ad0f2ea 100644 --- a/src/jquery.uls.languagefilter.js +++ b/src/jquery.uls.languagefilter.js @@ -188,8 +188,9 @@ this.selectedLanguage = langCode; } - this.render( langCode ); - this.resultCount++; + if ( this.render( langCode ) ) { + this.resultCount++; + } } } } @@ -212,8 +213,9 @@ languageFilter.autofill( code, name ); } - languageFilter.render( code ); - languageFilter.resultCount++; + if ( languageFilter.render( code ) ) { + languageFilter.resultCount++; + } } ); languageFilter.resultHandler( query ); @@ -278,10 +280,10 @@ var $target = this.options.$target; if ( !$target ) { - return; + return false; } - $target.append( langCode, null ); + return $target.append( langCode ); }, escapeRegex: function( value ) { diff --git a/src/jquery.uls.lcd.js b/src/jquery.uls.lcd.js index 2ad9efb..3c9b176 100644 --- a/src/jquery.uls.lcd.js +++ b/src/jquery.uls.lcd.js @@ -26,12 +26,12 @@ /*jshint multistr:true */ noResultsTemplate = '\ -
\ -

\ +
\ +

\ No results found\

\
\ -
\ +
\

\ You can search by language name, \ script name, ISO code of language or \ @@ -53,9 +53,13 @@ this.$element = $( element ); this.options = $.extend( {}, $.fn.lcd.defaults, options ); this.$element.addClass( 'lcd' ); - this.regionDivs = {}; + this.regionLanguages = {}; + this.renderTimeout = null; + this.cachedQuicklist = null; + this.$element.append( $( noResultsTemplate ) ); - this.$noResults = this.$element.find( 'div.uls-no-results-view' ); + this.$noResults = this.$element.children( '.uls-no-results-view' ); + this.render(); this.listen(); }; @@ -63,109 +67,50 @@ LanguageCategoryDisplay.prototype = { constructor: LanguageCategoryDisplay, + /** + * Adds language to the language list. + * @param {string} langCode + * @param {string} [regionCode] + * @return {bool} Whether the language was added. + */ append: function ( langCode, regionCode ) { + var lcd = this, i, regions; + if ( !this.options.languages[langCode] ) { // Language is unknown or not in the list of languages for this context. - return; + return false; } - this.addToRegion( langCode, regionCode ); - this.$noResults.hide(); - }, - /** - * Add the language to a region. - * If the region parameter is given, add to that region alone - * Otherwise to all regions that this language belongs. - * @param langCode - * @param region Optional region - */ - addToRegion: function ( langCode, region ) { - var i, regionCode, $li, $column, lastLanguage, lastScriptGroup, currentScriptGroup, - language = this.options.languages[langCode], - langName = $.uls.data.getAutonym( langCode ) || language || langCode, - regions = []; - - if ( region ) { - regions.push( region ); + if ( regionCode ) { + regions = [regionCode]; } else { regions = $.uls.data.getRegions( langCode ); } - // World wide languages need not be repeated in all regions. + // Worldwides only displayed once if ( $.inArray( 'WW', regions ) > -1 ) { - regions = [ 'WW' ]; + regions = ['WW']; } for ( i = 0; i < regions.length; i++ ) { - regionCode = regions[i]; - - $li = $( '

  • ' ) - .data( 'code', langCode ) - .attr( { - lang: langCode, - dir: $.uls.data.getDir( langCode ) - } ) - .append( - $( '' ).attr( 'title', language ).text( langName ) - ); - - // Append the element to the column in the list - $column = this.getColumn( regionCode ); - lastLanguage = $column.find( 'li:last' ).data( 'code' ); - - if ( lastLanguage ) { - lastScriptGroup = $.uls.data.getScriptGroupOfLanguage( lastLanguage ); - currentScriptGroup = $.uls.data.getScriptGroupOfLanguage( langCode ); - - if ( lastScriptGroup !== currentScriptGroup ) { - if ( $column.find( 'li' ).length > 2 ) { - // If column already has 2 or more languages, add a new column - $column = this.getColumn( regionCode, true ); - } - } - } - - $column.append( $li ); - } - }, - - /** - * Get a column to add language. - * @param regionCode string The region code - * @param forceNew bool whether a new column must be created or not - */ - getColumn: function ( regionCode, forceNew ) { - var $divRegionCode, $rowDiv, $ul; - - forceNew = forceNew || false; - $divRegionCode = this.regionDivs[regionCode]; - $rowDiv = $divRegionCode.find( 'div.row:last' ); - $ul = $rowDiv.find( 'ul:last' ); - - // Each column can have maximum 8 languages. - if ( $ul.length === 0 || $ul.find( 'li' ).length >= 8 || forceNew ) { - $ul = $( '