From: Alexander Ebert Date: Wed, 24 Oct 2012 01:58:25 +0000 (+0200) Subject: Added keyboard-based navigation within dropdowns X-Git-Tag: 2.0.0_Beta_1~838 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=9a130ab4f15f2b6a1a6a88415e665c4c9c795b68;p=GitHub%2FWoltLab%2FWCF.git Added keyboard-based navigation within dropdowns Currently not all dropdowns properly support this, as they override the _createListItem() method which is responsible for counting the amount of selectable items. See #797 --- diff --git a/wcfsetup/install/files/acp/js/WCF.ACP.js b/wcfsetup/install/files/acp/js/WCF.ACP.js index fee364e95a..c30e8398e6 100644 --- a/wcfsetup/install/files/acp/js/WCF.ACP.js +++ b/wcfsetup/install/files/acp/js/WCF.ACP.js @@ -1004,6 +1004,23 @@ WCF.ACP.Search = WCF.Search.Base.extend({ var $item = resultList.items[$i]; $('
  • ' + $item.title + '
  • ').appendTo(this._list); + + this._itemCount++; } + }, + + /** + * @see WCF.Search.Base._highlightSelectedElement() + */ + _highlightSelectedElement: function() { + this._list.find('li').removeClass('dropdownNavigationItem'); + this._list.find('li:not(.dropdownDivider):not(.dropdownText)').eq(this._itemIndex).addClass('dropdownNavigationItem'); + }, + + /** + * @see WCF.Search.Base._selectElement() + */ + _selectElement: function(event) { + window.location = this._list.find('li.dropdownNavigationItem > a').attr('href'); } }); diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 1d4a45edbb..0d4cc98ff2 100755 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -4321,6 +4321,18 @@ WCF.Search.Base = Class.extend({ */ _excludedSearchValues: [], + /** + * count of available results + * @var integer + */ + _itemCount: 0, + + /** + * item index, -1 if none is selected + * @var integer + */ + _itemIndex: -1, + /** * result list * @var jQuery @@ -4382,6 +4394,9 @@ WCF.Search.Base = Class.extend({ this._commaSeperated = (commaSeperated) ? true : false; this._oldSearchString = [ ]; + this._itemCount = 0; + this._itemIndex = -1; + this._proxy = new WCF.Action.Proxy({ success: $.proxy(this._success, this) }); @@ -4397,6 +4412,28 @@ WCF.Search.Base = Class.extend({ * @param object event */ _keyUp: function(event) { + // handle arrow keys and return key + switch (event.which) { + case 37: // arrow-left + case 39: // arrow-right + return; + break; + + case 38: // arrow up + this._selectPreviousItem(); + return; + break; + + case 40: // arrow down + this._selectNextItem(); + return; + break; + + case 13: // return key + return this._selectElement(event); + break; + } + var $content = this._getSearchString(event); if ($content === '') { this._clearList(true); @@ -4422,6 +4459,63 @@ WCF.Search.Base = Class.extend({ } }, + /** + * Selects the next item in list. + */ + _selectNextItem: function() { + if (this._itemCount === 0) { + return; + } + + // remove previous marking + this._itemIndex++; + if (this._itemIndex === this._itemCount) { + this._itemIndex = 0; + } + + this._highlightSelectedElement(); + }, + + /** + * Selects the previous item in list. + */ + _selectPreviousItem: function() { + if (this._itemCount === 0) { + return; + } + + this._itemIndex--; + if (this._itemIndex === -1) { + this._itemIndex = this._itemCount - 1; + } + + this._highlightSelectedElement(); + }, + + /** + * Highlights the active item. + */ + _highlightSelectedElement: function() { + this._list.find('li').removeClass('dropdownNavigationItem'); + this._list.find('li:eq(' + this._itemIndex + ')').addClass('dropdownNavigationItem'); + }, + + /** + * Selects the active item by pressing the return key. + * + * @param object event + * @return boolean + */ + _selectElement: function(event) { + if (this._itemCount === 0) { + return true; + } + + this._list.find('li.dropdownNavigationItem').trigger('click'); + + return false; + }, + /** * Returns search string. * @@ -4510,6 +4604,8 @@ WCF.Search.Base = Class.extend({ var $listItem = $('
  • ' + item.label + '
  • ').appendTo(this._list); $listItem.data('objectID', item.objectID).data('label', item.label).click($.proxy(this._executeCallback, this)); + this._itemCount++; + return $listItem; }, @@ -4567,6 +4663,10 @@ WCF.Search.Base = Class.extend({ this._list.parent().removeClass('dropdownOpen').end().empty(); WCF.CloseOverlayHandler.removeCallback('WCF.Search.Base'); + + // reset item navigation + this._itemCount = 0; + this._itemIndex = -1; }, /** diff --git a/wcfsetup/install/files/style/dropdown.less b/wcfsetup/install/files/style/dropdown.less index 10cbd08cc7..c9ae506343 100644 --- a/wcfsetup/install/files/style/dropdown.less +++ b/wcfsetup/install/files/style/dropdown.less @@ -129,7 +129,8 @@ display: block; &:hover:not(.dropdownDivider):not(.dropdownList):not(.dropdownText), - &.dropdownList > li:hover:not(.dropdownDivider) { + &.dropdownList > li:hover:not(.dropdownDivider), + &.dropdownNavigationItem { background-color: @wcfDropdownHoverBackgroundColor; }