Commit 4478df76 authored by Jacob Thornton's avatar Jacob Thornton

first pass at ultra basic autocomplete

parent 961c4794
This diff is collapsed.
This diff is collapsed.
...@@ -23,48 +23,6 @@ ...@@ -23,48 +23,6 @@
<link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png"> <link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png"> <link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
<!-- Le javascript -->
<!-- placed up here so that the inline demos can be next to their markup -->
<script src="http://code.jquery.com/jquery-1.7.min.js"></script>
<script type="text/javascript">
// NOT FINAL BY ANY MEANS, JUST MAH JANK CODE BRO
$(document).ready(function() {
$('.nav .active').click(function(e) {
e.preventDefault();
$(this).siblings().toggle();
});
});
</script>
<script src="assets/js/google-code-prettify/prettify.js"></script>
<script src="../js/bootstrap-transition.js"></script>
<script src="../js/bootstrap-alert.js"></script>
<script src="../js/bootstrap-modal.js"></script>
<script src="../js/bootstrap-dropdown.js"></script>
<script src="../js/bootstrap-scrollspy.js"></script>
<script src="../js/bootstrap-tab.js"></script>
<script src="../js/bootstrap-twipsy.js"></script>
<script src="../js/bootstrap-popover.js"></script>
<script src="../js/bootstrap-button.js"></script>
<script>
$(function () {
// twipsy demo
$("a[rel=twipsy]").twipsy({
live: true
})
//popover demo
$("a[rel=popover]")
.popover({
offset: 10
})
.click(function(e) {
e.preventDefault()
})
})
</script>
</head> </head>
<body id="bootstrap-js"> <body id="bootstrap-js">
...@@ -163,6 +121,10 @@ ...@@ -163,6 +121,10 @@
<td><a href="./javascript.html#carousel">bootstrap-carousel.js</a></td> <td><a href="./javascript.html#carousel">bootstrap-carousel.js</a></td>
<td>A plugin for rotating through elements. A merry-go-round.</td> <td>A plugin for rotating through elements. A merry-go-round.</td>
</tr> </tr>
<tr>
<td><a href="./javascript.html#typeahead">bootstrap-typeahead.js</a></td>
<td>A basic, easily extended plugin for quickly creating elegant typeaheads.</td>
</tr>
</tbody> </tbody>
</table> </table>
<h3>Is javascript necessary?</h3> <h3>Is javascript necessary?</h3>
...@@ -1151,6 +1113,54 @@ $('.myCarousel').carousel({ ...@@ -1151,6 +1113,54 @@ $('.myCarousel').carousel({
</div> </div>
</section> </section>
<!-- Typeahead
================================================== -->
<section id="typeahead">
<div class="page-header">
<h1>Typeahead <small>bootstrap-typeahead.js</small></h1>
</div>
<div class="row">
<div class="span3 columns">
<p>A basic, easily extended plugin for quickly creating elegant typeaheads.</p>
<a href="../js/bootstrap-carousel.js" target="_blank" class="btn primary">Download</a>
</div>
<div class="span9 columns">
<h3>Using bootstrap-typeahead.js</h3>
<pre class="prettyprint linenums">$('.typeahead').typeahead()</pre>
<h3>Options</h3>
<table class="bordered-table striped-table">
<thead>
<tr>
<th style="width: 100px;">Name</th>
<th style="width: 50px;">type</th>
<th style="width: 50px;">default</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td>items</td>
<td>number</td>
<td>8</td>
<td>The max number of items to display in the dropdown.</td>
</tr>
</tbody>
</table>
<h3>Markup</h3>
<p>Add data attributes to register an element with typeahead functionality.</p>
<pre class="prettyprint linenums">
&lt;input type="text" data-provide="typeahead" /&gt;
</pre>
<h3>Demo</h3>
<input type="text" data-provide="typeahead" data-items="4" data-data='["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]'>
</div>
</div>
</section>
<!-- Footer <!-- Footer
================================================== --> ================================================== -->
<footer class="footer"> <footer class="footer">
...@@ -1178,6 +1188,7 @@ $('.myCarousel').carousel({ ...@@ -1178,6 +1188,7 @@ $('.myCarousel').carousel({
<script src="../js/bootstrap-button.js"></script> <script src="../js/bootstrap-button.js"></script>
<script src="../js/bootstrap-collapse.js"></script> <script src="../js/bootstrap-collapse.js"></script>
<script src="../js/bootstrap-carousel.js"></script> <script src="../js/bootstrap-carousel.js"></script>
<script src="../js/bootstrap-typeahead.js"></script>
<script src="assets/js/application.js"></script> <script src="assets/js/application.js"></script>
<script> <script>
$(function () { $(function () {
......
...@@ -34,80 +34,102 @@ ...@@ -34,80 +34,102 @@
constructor: Typeahead constructor: Typeahead
, matcher: function(item, query) { , matcher: function (item, query) {
return ~item.indexOf(query) return ~item.indexOf(query)
} }
, select: function(event) { , select: function () {
this.$element.val($(event.target).attr('data-value')) var val = this.$menu.find('.active').attr('data-value')
this.hide() this.$element.val(val)
return this.hide()
} }
, show: function () { , show: function () {
this.shown = true var pos = $.extend({}, this.$element.offset(), {
height: this.$element[0].offsetHeight
})
this.$menu.css({
top: pos.top + pos.height
, left: pos.left
})
this.$menu.show() this.$menu.show()
this.shown = true
return this return this
} }
, hide: function () { , hide: function () {
this.shown = false
this.$menu.hide() this.$menu.hide()
this.shown = false
return this return this
} }
, lookup: function (event) { , lookup: function (event) {
var query = this.$element.val() var query = this.$element.val()
, that = this , that = this
, items
var items = this.data.filter(function (item) { if (!query) {
if (that.matcher(item, query)) { return this.shown ? this.hide() : this
return item
} }
items = this.data.filter(function (item) {
if (that.matcher(item, query)) return item
}) })
if (!items.length) { if (!items.length) {
return this.shown ? this.hide() : this return this.shown ? this.hide() : this
} }
return this.render(items).show() return this.render(items.slice(0, this.options.items)).show()
} }
, render: function(items) { , render: function (items) {
var that = this var that = this
items = $(items).map(function (i, item) { items = $(items).map(function (i, item) {
return $(that.options.item) i = $(that.options.item).attr('data-value', item)
.text(item) i.find('a').text(item)
.attr('data-value', item)[0] return i[0]
}) })
items.first().addClass('active') items.first().addClass('active')
this.$menu.html(items)
this.$menu.append(items)
return this return this
} }
, next: function (event) { , next: function (event) {
var active = this.$menu.find('.active').removeClass('active') var active = this.$menu.find('.active').removeClass('active')
, next = active.next() || $(this.$menu.find('li')[0]) , next = active.next()
if (!next.length) {
next = $(this.$menu.find('li')[0])
}
next.addClass('active') next.addClass('active')
} }
, prev: function (event) { , prev: function (event) {
var active = this.$menu.find('.active').removeClass('active') var active = this.$menu.find('.active').removeClass('active')
, next = active.prev() || this.$menu.find('li').last() , prev = active.prev()
next.addClass('active') if (!prev.length) {
prev = this.$menu.find('li').last()
}
prev.addClass('active')
} }
, keyup: function () { , keyup: function (e) {
event e.stopPropagation()
.stopPropagation() e.preventDefault()
.preventDefault()
switch(e.keyCode) {
case 40: // down arrow
case 38: // up arrow
break
switch(event.keyCode) {
case 9: // tab case 9: // tab
case 13: // enter case 13: // enter
this.select() this.select()
...@@ -120,51 +142,68 @@ ...@@ -120,51 +142,68 @@
default: default:
this.lookup() this.lookup()
} }
} }
, keypress: function (event) { , keypress: function (e) {
event.stopPropagation() e.stopPropagation()
switch(event.keyCode) {
switch(e.keyCode) {
case 9: // tab case 9: // tab
case 13: // enter case 13: // enter
case 27: // escape case 27: // escape
event.preventDefault() e.preventDefault()
break break
case 38: // up arrow case 38: // up arrow
e.preventDefault()
this.prev() this.prev()
event.preventDefault()
break break
case 40: // down arrow case 40: // down arrow
e.preventDefault()
this.next() this.next()
event.preventDefault()
break break
} }
} }
, blur: function (e) {
var that = this
e.stopPropagation()
e.preventDefault()
setTimeout(function () { that.hide() }, 150)
}
, click: function (e) {
e.stopPropagation()
e.preventDefault()
this.select()
}
, mouseenter: function (e) {
this.$menu.find('.active').removeClass('active')
$(e.currentTarget).addClass('active')
}
, listen: function () { , listen: function () {
this.$element this.$element
.on('focus', this.show) .on('blur', $.proxy(this.blur, this))
.on('blur', $.proxy(this.hide, this))
.on('keypress', $.proxy(this.keypress, this)) .on('keypress', $.proxy(this.keypress, this))
.on('keyup', this.keyup) .on('keyup', $.proxy(this.keyup, this))
.on('change', $.proxy(this.lookup, this))
if ($.browser.webkit || $.browser.msie) { if ($.browser.webkit || $.browser.msie) {
this.$element.on('keydown', this.keypress) this.$element.on('keydown', $.proxy(this.keypress, this))
} }
this.$menu this.$menu
.on('click', '* > *', $.proxy(this.select, this)) .on('click', $.proxy(this.click, this))
.on('mouseenter', function () { .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
/* remove selected class, add to mouseover */
})
} }
} }
/* TYPEAHEAD PLUGIN DEFINITION /* TYPEAHEAD PLUGIN DEFINITION
* ============================== */ * =========================== */
$.fn.typeahead = function ( option ) { $.fn.typeahead = function ( option ) {
return this.each(function () { return this.each(function () {
...@@ -177,14 +216,24 @@ ...@@ -177,14 +216,24 @@
} }
$.fn.typeahead.defaults = { $.fn.typeahead.defaults = {
data: null items: 8
, items: 8 , menu: '<ul class="typeahead dropdown-menu"></ul>'
, empty: false , item: '<li><a href="#"></a></li>'
, noresults: false
, menu: '<ul class="dropdown-menu"></ul>'
, item: '<li></li>'
} }
$.fn.typeahead.Constructor = Typeahead $.fn.typeahead.Constructor = Typeahead
/* TYPEAHEAD DATA-API
* ================== */
$(function () {
$('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
var $this = $(this)
if ($this.data('typeahead')) return
e.preventDefault()
$this.typeahead($this.data())
})
})
}( window.jQuery ) }( window.jQuery )
\ No newline at end of file
...@@ -13,11 +13,9 @@ $(function () { ...@@ -13,11 +13,9 @@ $(function () {
test("should listen to an input", function () { test("should listen to an input", function () {
var $input = $('<input />') var $input = $('<input />')
$input.typeahead() $input.typeahead()
ok($input.data('events').focus, 'has a focus event')
ok($input.data('events').blur, 'has a blur event') ok($input.data('events').blur, 'has a blur event')
ok($input.data('events').keypress, 'has a keypress event') ok($input.data('events').keypress, 'has a keypress event')
ok($input.data('events').keyup, 'has a keyup event') ok($input.data('events').keyup, 'has a keyup event')
ok($input.data('events').change, 'has a change event')
if ($.browser.webkit || $.browser.msie) { if ($.browser.webkit || $.browser.msie) {
ok($input.data('events').keydown, 'has a keydown event') ok($input.data('events').keydown, 'has a keydown event')
} else { } else {
...@@ -44,7 +42,8 @@ $(function () { ...@@ -44,7 +42,8 @@ $(function () {
}) })
, typeahead = $input.data('typeahead') , typeahead = $input.data('typeahead')
$input.val('a').change() $input.val('a')
typeahead.lookup()
ok(typeahead.$menu.is(":visible"), 'typeahead is visible') ok(typeahead.$menu.is(":visible"), 'typeahead is visible')
equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu') equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu')
...@@ -54,12 +53,14 @@ $(function () { ...@@ -54,12 +53,14 @@ $(function () {
}) })
test("should hide menu when query entered", function () { test("should hide menu when query entered", function () {
stop()
var $input = $('<input />').typeahead({ var $input = $('<input />').typeahead({
data: ['aa', 'ab', 'ac'] data: ['aa', 'ab', 'ac']
}) })
, typeahead = $input.data('typeahead') , typeahead = $input.data('typeahead')
$input.val('a').change() $input.val('a')
typeahead.lookup()
ok(typeahead.$menu.is(":visible"), 'typeahead is visible') ok(typeahead.$menu.is(":visible"), 'typeahead is visible')
equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu') equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu')
...@@ -67,7 +68,10 @@ $(function () { ...@@ -67,7 +68,10 @@ $(function () {
$input.blur() $input.blur()
setTimeout(function () {
ok(!typeahead.$menu.is(":visible"), "typeahead is no longer visible") ok(!typeahead.$menu.is(":visible"), "typeahead is no longer visible")
start()
}, 200)
typeahead.$menu.remove() typeahead.$menu.remove()
}) })
...@@ -78,7 +82,8 @@ $(function () { ...@@ -78,7 +82,8 @@ $(function () {
}) })
, typeahead = $input.data('typeahead') , typeahead = $input.data('typeahead')
$input.val('a').change() $input.val('a')
typeahead.lookup()
ok(typeahead.$menu.is(":visible"), 'typeahead is visible') ok(typeahead.$menu.is(":visible"), 'typeahead is visible')
equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu') equals(typeahead.$menu.find('li').length, 3, 'has 3 items in menu')
...@@ -110,9 +115,10 @@ $(function () { ...@@ -110,9 +115,10 @@ $(function () {
}) })
, typeahead = $input.data('typeahead') , typeahead = $input.data('typeahead')
$input.val('a').change() $input.val('a')
typeahead.lookup()
$(typeahead.$menu.find('li')[2]).trigger('click') $(typeahead.$menu.find('li')[2]).mouseover().click()
equals($input.val(), 'ac', 'input value was correctly set') equals($input.val(), 'ac', 'input value was correctly set')
ok(!typeahead.$menu.is(':visible'), 'the menu was hidden') ok(!typeahead.$menu.is(':visible'), 'the menu was hidden')
......
...@@ -68,8 +68,10 @@ ...@@ -68,8 +68,10 @@
font-weight: normal; font-weight: normal;
line-height: 18px; line-height: 18px;
color: @gray; color: @gray;
}
// Hover state // Hover state
&:hover { &.typeahead .active a, a:hover {
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
text-shadow: 0 -1px 0 rgba(0,0,0,.25); text-shadow: 0 -1px 0 rgba(0,0,0,.25);
...@@ -78,7 +80,6 @@ ...@@ -78,7 +80,6 @@
@shadow: inset 0 1px 0 rgba(0,0,0,.075), inset 0 -1px rgba(0,0,0,.075); @shadow: inset 0 1px 0 rgba(0,0,0,.075), inset 0 -1px rgba(0,0,0,.075);
.box-shadow(@shadow); .box-shadow(@shadow);
} }
}
} }
// Open state for the dropdown // Open state for the dropdown
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment