Well, just the navigation part.
A Pen by Justin Perry on CodePen.
<label>Search <input id="search" type="search" placeholder="Enter search term" autocomplete="off" /></label> | |
<ul class="nav-list"> | |
<li class="list__item"><a href="http://www.google.co.uk" target="_blank">Link 1</a></li> | |
<li class="list__item"><a href="http://www.google.co.uk" target="_blank">Link 2</a></li> | |
<li class="list__item"><a href="http://www.google.co.uk" target="_blank">Link 3</a></li> | |
<li class="list__item"><a href="http://www.google.co.uk" target="_blank">Link 4</a></li> | |
<li class="list__item"><a href="http://www.google.co.uk" target="_blank">Link 5</a></li> | |
<li class="list__item"><a href="http://www.google.co.uk" target="_blank">Link 6</a></li> | |
</ul> |
function NavSelector(opts){ | |
this.opts = opts; | |
this.$itemsContainer = $(opts.itemsContainer); | |
this.$items = this.$itemsContainer.find(opts.items); | |
this.itemLink = opts.itemLink; | |
this.$itemLinks = this.$items.find(opts.itemLink); | |
this.$search = $(opts.search); | |
this.onSelect = opts.onSelect || $.noop; | |
this.keys = opts.keys || { | |
up : 38, | |
down : 40, | |
select : 13, | |
esc : 27 | |
} | |
} | |
NavSelector.prototype = { | |
start : function(){ | |
var self = this; | |
$(document).on('keyup', this.opts.itemsContainer, function(e){ | |
switch(e.which){ | |
case self.keys.up: | |
self.updateIndex('up'); | |
break; | |
case self.keys.down: | |
self.updateIndex('down'); | |
console.log('down'); | |
break; | |
case self.keys.select: | |
self.selectItem(self.currentIndex); | |
break; | |
case self.keys.esc: | |
self.returnToSearch(); | |
break; | |
} | |
}); | |
}, | |
show: function(){ | |
this.$itemsContainer.addClass('is-active'); | |
}, | |
hide: function(){ | |
this.$itemsContainer.removeClass('is-active'); | |
}, | |
moveFocus: function(index){ | |
this.$items.eq(index) | |
.find(this.itemLink) | |
.addClass('is-active') | |
.focus(); | |
}, | |
updateIndex: function(dir) { | |
if( dir === 'up' && this.currentIndex ){ | |
this.currentIndex--; | |
} | |
else if( dir === 'down' && this.currentIndex < this.$items.length ){ | |
this.currentIndex++; | |
} | |
this.moveFocus(this.currentIndex); | |
}, | |
selectItem: function(index){ | |
this.onSelect(index); | |
}, | |
focusStart: function(){ | |
this.$currentItemLink = this.$items.find(this.itemLink).first(); | |
this.$currentItemLink.focus(); | |
this.currentIndex = 0; | |
}, | |
openNav: function(){ | |
this.show(); | |
this.focusStart(); | |
}, | |
returnToSearch: function(){ | |
this.hide(); | |
this.$search.focus(); | |
}, | |
init: function(){ | |
this.start(); | |
} | |
}; | |
var navSelector = new NavSelector({ | |
search : '#search', | |
itemsContainer : '.nav-list', | |
items : '.list__item', | |
itemLink : 'a' | |
}); | |
navSelector.init(); | |
$('#search').on('keyup', function(e){ | |
if( $(this).val().length >= 2 ){ | |
navSelector.openNav(); | |
} | |
}); |
@import "compass"; | |
.nav-list{ | |
border: 1px solid #ccc; | |
border-radius: 5px; | |
display: none; | |
list-style: none; | |
overflow: auto; | |
padding: 0; | |
&.is-active{ | |
display: block; | |
} | |
.list__item{ | |
a{ | |
display: block; | |
padding: 10px; | |
text-decoration: none; | |
&:focus{ | |
background-color: #888; | |
color: white; | |
} | |
&:hover{ | |
background-color: #d1d1d1; | |
} | |
} | |
} | |
} |