Update jQuery.uls to add support for up/down navigation of languages
Some localisation changes are also included. Bug: T187964 Change-Id: I7d9554c9a4e2b18c805c9ef9b916c3961ae9c32c
This commit is contained in:
@@ -138,3 +138,7 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.uls-language-option--highlighted {
|
||||
background-color: #eaeff7;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,12 @@
|
||||
|
||||
query = ( this.$element.val() || '' ).trim().toLowerCase();
|
||||
|
||||
if ( this.selectedLanguage ) {
|
||||
// Check if a language is currently highlighted, and if so select that
|
||||
// if user presses enter.
|
||||
var highlightedLanguage = this.options.lcd.getHighlightedLanguageCode();
|
||||
if ( highlightedLanguage ) {
|
||||
this.options.onSelect( highlightedLanguage, e );
|
||||
} else if ( this.selectedLanguage ) {
|
||||
// this.selectLanguage will be populated from a matching search
|
||||
this.options.onSelect( this.selectedLanguage, e );
|
||||
} else if ( this.options.languages[ query ] ) {
|
||||
@@ -115,6 +120,16 @@
|
||||
this.options.onSelect( query, e );
|
||||
}
|
||||
|
||||
break;
|
||||
case 38: // arrow up
|
||||
this.options.lcd.navigateUp();
|
||||
e.preventDefault();
|
||||
|
||||
break;
|
||||
case 40: // arrow down
|
||||
this.options.lcd.navigateDown();
|
||||
e.preventDefault();
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -163,6 +178,10 @@
|
||||
results = [],
|
||||
query = ( this.$element.val() || '' ).trim().toLowerCase();
|
||||
|
||||
// Reset the keyboard navigation index inside LanguageCategoryDisplay (lcd)
|
||||
// before re-rendering the language options
|
||||
this.options.lcd.resetNavigationIndex();
|
||||
|
||||
if ( query === '' ) {
|
||||
this.options.lcd.setGroupByRegionOverride( null );
|
||||
this.resultHandler( query, languages );
|
||||
|
||||
@@ -59,13 +59,119 @@
|
||||
this.$cachedQuicklist = null;
|
||||
this.groupByRegionOverride = null;
|
||||
|
||||
// The index of the language option that is currently visited using arrow key navigation
|
||||
// Can take values in the [0, language options list item length - 1] range for top to bottom
|
||||
// navigation, or in the [-1, -language options list item length + 1] range for bottom to
|
||||
// top navigation.
|
||||
this.navigationIndex = null;
|
||||
|
||||
this.render();
|
||||
this.listen();
|
||||
}
|
||||
|
||||
// Adapted from https://stackoverflow.com/a/41754707/903324
|
||||
function isLanguageFullyVisible( $el, $holder ) {
|
||||
var elementRect = $el.get( 0 ).getBoundingClientRect();
|
||||
var holderRect = $holder.get( 0 ).getBoundingClientRect();
|
||||
|
||||
return elementRect.top <= holderRect.top ?
|
||||
holderRect.top <= elementRect.top :
|
||||
holderRect.bottom <= elementRect.height;
|
||||
}
|
||||
|
||||
LanguageCategoryDisplay.prototype = {
|
||||
constructor: LanguageCategoryDisplay,
|
||||
|
||||
/**
|
||||
* Returns a jQuery object containing a collection of all the visible
|
||||
* language option <li> elements
|
||||
*
|
||||
* @return {jQuery}
|
||||
*/
|
||||
getLanguageOptionListItems: function () {
|
||||
return this.$element.find( '.uls-lcd-region-section:not(.hide)' ).find( 'li[data-code]' );
|
||||
},
|
||||
|
||||
/**
|
||||
* Increases the keyboard navigation index by one and applies a specific
|
||||
* class to the n-th language option <li> element (where n = navigation index)
|
||||
* Currently used as event handler for the arrow down 'keydown' event, inside
|
||||
* LanguageFilter.
|
||||
*/
|
||||
navigateDown: function () {
|
||||
var maxIndex = this.getLanguageOptionListItems().length - 1;
|
||||
// We support navigation starting both from the top and the bottom of the language list.
|
||||
// The navigation should stop when the last language option is already highlighted (for
|
||||
// top to bottom navigation). For top to bottom navigation, that happens when navigation
|
||||
// index is equal to language options list item length - 1. For bottom to top
|
||||
// navigation, that happens when navigation index is equal to -1.
|
||||
if ( this.navigationIndex === maxIndex || this.navigationIndex === -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.navigationIndex === null ) {
|
||||
this.navigationIndex = 0;
|
||||
} else {
|
||||
this.navigationIndex++;
|
||||
}
|
||||
this.highlightLanguageOption();
|
||||
},
|
||||
|
||||
/**
|
||||
* Decreases the keyboard navigation index by one and applies a specific
|
||||
* class to the n-th language option <li> element (where n = navigation index)
|
||||
* Currently used as event handler for the arrow down 'keydown' event, inside
|
||||
* LanguageFilter.
|
||||
*/
|
||||
navigateUp: function () {
|
||||
var maxIndex = this.getLanguageOptionListItems().length - 1;
|
||||
// We support navigation starting both from the top and the bottom of the language list.
|
||||
// The navigation should stop when the first language option is already highlighted (for
|
||||
// bottom to top navigation). For top to bottom navigation, that happens when navigation
|
||||
// index is equal to 0. For bottom to top navigation, that happens when navigation index
|
||||
// is equal to -languageOptionListItemsLength + 1.
|
||||
if ( this.navigationIndex === 0 || this.navigationIndex === -maxIndex ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.navigationIndex--;
|
||||
this.highlightLanguageOption();
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a specific class ("uls-language-option--highlighted") only to the n-th
|
||||
* language option <li> element (where n = navigation index)
|
||||
*/
|
||||
highlightLanguageOption: function () {
|
||||
var $listItems = this.getLanguageOptionListItems();
|
||||
$listItems.removeClass( 'uls-language-option--highlighted' );
|
||||
|
||||
var $selectedItem = $listItems.eq( this.navigationIndex );
|
||||
$selectedItem.addClass( 'uls-language-option--highlighted' );
|
||||
|
||||
// If the selected item is not visible, then scroll the container to display it
|
||||
if ( !isLanguageFullyVisible( $selectedItem, this.$element ) ) {
|
||||
$selectedItem.get( 0 ).scrollIntoView( false );
|
||||
}
|
||||
},
|
||||
|
||||
getHighlightedLanguageCode: function () {
|
||||
if ( this.navigationIndex ) {
|
||||
var $selectedItem = this.getLanguageOptionListItems().eq( this.navigationIndex );
|
||||
return $selectedItem.data( 'code' );
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the navigation index to null.
|
||||
* Currently used inside LanguageFilter search method, to reset the keyboard navigation
|
||||
*/
|
||||
resetNavigationIndex: function () {
|
||||
this.navigationIndex = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds language to the language list.
|
||||
*
|
||||
@@ -419,6 +525,18 @@
|
||||
listen: function () {
|
||||
var lcd = this;
|
||||
|
||||
this.$element.on( 'mouseenter', 'li[data-code]', function () {
|
||||
var $listItems = lcd.getLanguageOptionListItems();
|
||||
// Remove the previous option, and then highlight the current one.
|
||||
$listItems.removeClass( 'uls-language-option--highlighted' );
|
||||
var $self = $( this );
|
||||
$self.addClass( 'uls-language-option--highlighted' );
|
||||
lcd.navigationIndex = $listItems.index( $self );
|
||||
} ).on( 'mouseleave', 'li[data-code]', function () {
|
||||
$( this ).removeClass( 'uls-language-option--highlighted' );
|
||||
lcd.navigationIndex = null;
|
||||
} );
|
||||
|
||||
if ( this.options.clickhandler ) {
|
||||
this.$element.on( 'click', '.row li', function ( event ) {
|
||||
lcd.options.clickhandler.call( this, $( this ).data( 'code' ), event );
|
||||
|
||||
Reference in New Issue
Block a user