Skip to content

Commit

Permalink
Merge pull request #80 from PolymerElements/iron-menu-prefix-search
Browse files Browse the repository at this point in the history
Iron menu prefix search
  • Loading branch information
bicknellr authored Sep 24, 2016
2 parents a0c185a + dbfe282 commit 37c3afb
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 3 deletions.
32 changes: 29 additions & 3 deletions iron-menu-behavior.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
}
},

_SEARCH_RESET_TIMEOUT_MS: 1000,

hostAttributes: {
'role': 'menu',
'tabindex': '0'
Expand Down Expand Up @@ -124,16 +126,40 @@
* @param {KeyboardEvent} event A KeyboardEvent.
*/
_focusWithKeyboardEvent: function(event) {
this.cancelDebouncer('_clearSearchText');

var searchText = this._searchText || '';
var key = event.key && event.key.length == 1 ? event.key :
String.fromCharCode(event.keyCode);
searchText += key.toLocaleLowerCase();

var searchLength = searchText.length;

for (var i = 0, item; item = this.items[i]; i++) {
if (item.hasAttribute('disabled')) {
continue;
}

var attr = this.attrForItemTitle || 'textContent';
var title = item[attr] || item.getAttribute(attr);
var title = (item[attr] || item.getAttribute(attr) || '').trim();

if (!item.hasAttribute('disabled') && title &&
title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.keyCode).toLowerCase()) {
if (title.length < searchLength) {
continue;
}

if (title.slice(0, searchLength).toLocaleLowerCase() == searchText) {
this._setFocusedItem(item);
break;
}
}

this._searchText = searchText;
this.debounce('_clearSearchText', this._clearSearchText,
this._SEARCH_RESET_TIMEOUT_MS);
},

_clearSearchText: function() {
this._searchText = '';
},

/**
Expand Down
56 changes: 56 additions & 0 deletions test/iron-menu-behavior.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@
</template>
</test-fixture>

<test-fixture id="countries">
<template>
<test-menu>
<div>Ghana</div>
<div>Uganda</div>
</test-menu>
</template>
</test-fixture>

<test-fixture id="bogus-attr-for-item-title">
<template>
<test-menu attr-for-item-title="totally-doesnt-exist">
<div>Focused by default</div>
<div>I'm not entitled!</div>
</test-menu>
</template>
</test-fixture>

<script>
suite('menu a11y tests', function() {
test('menu has role="menu"', function() {
Expand Down Expand Up @@ -381,6 +399,44 @@
});
});

test('focusing on item with multi-char, quick input', function(done) {
var menu = fixture('countries');
MockInteractions.focus(menu);

// Wait for async focus
Polymer.Base.async(function() {
// Key press 'u'
MockInteractions.keyDownOn(menu, 85);

// Key press 'g'
MockInteractions.keyDownOn(menu, 71);

Polymer.Base.async(function() {
var focusedItem = Polymer.dom(menu).node.focusedItem;
assert.equal(focusedItem, menu.items[1], 'menu.items[1] is focused');
done();
});
});
});

test('focusing on item with bogus attr-for-item-title', function(done) {
var menu = fixture('bogus-attr-for-item-title');
MockInteractions.focus(menu);

// Wait for async focus
Polymer.Base.async(function() {
// Key press 'i'
MockInteractions.keyDownOn(menu, 73);

Polymer.Base.async(function() {
var focusedItem = Polymer.dom(menu).node.focusedItem;
assert.equal(focusedItem, menu.items[0], 'menu.items[0] is still focused');
done();
});
});

});

test('focusing non-item content does not auto-focus an item', function(done) {
var menu = fixture('basic');
menu.extraContent.focus();
Expand Down

0 comments on commit 37c3afb

Please sign in to comment.