Skip to content

Made a jQuery Plugin #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Dec 7, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
<title>Relevant Dropdown</title>

<link rel='stylesheet' href='css/style.css'>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="js/modernizr.custom.50983.js"></script>
<script src="js/relevant-dropdown.js"></script>
</head>

<body>
Expand Down Expand Up @@ -78,10 +74,28 @@ <h2>A HTML5 datalist polyfill that depends on jQuery and Modernizr.</h2>

</datalist>

<p><input type="text" id="name" list="names" placeholder="Look for someone!"></p>

<datalist id="names">
<option value="Baylor Rae'">
<option value="Chris Coyier">
</datalist>

<p><a href="https://github.com/chriscoyier/Relevant-Dropdowns">GitHub</a></p>

</div>

<script src="js/jquery.js"></script>
<script src="js/modernizr.custom.50983.js"></script>
<script src="js/jquery.relevant-dropdown.js"></script>
<script>

$('#search').relevantDropdown();

$('#name').relevantDropdown({
fadeOutSpeed: 0
});

</script>
</body>

</html>
188 changes: 188 additions & 0 deletions js/jquery.relevant-dropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
(function($) {

// Make jQuery's :contains case insensitive (like HTML5 datalist)
// Changed the name to prevent overriding original functionality
$.expr[':'].RD_contains = function(a, i, m) {
return $(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};

$.fn.relevantDropdown = function(options) {

options = $.extend({
fadeOutSpeed: 'normal', // speed to fade out the dataList Popup
change: null
}, options);

return this.each(function() {

var $input = $(this),
list_id = $input.attr('list'),
$datalist = $("#" + list_id),
datalistItems = $datalist.find("option"),

searchPosition,
scrollValue = 0;

// Makes sure the browser doesn't already support the list attribute
// todo: I couldn't figure out how to make an opposite `if statement` without Safari acting up
if( !Modernizr.input.list || (parseInt($.browser.version) > 400) ) {

// Insert home for new fake datalist
$("<ul />", {
"class": "datalist",
"id" : list_id
}).appendTo("body");

// Remove old datalist
$datalist.remove();

// Update pointer
var $datalist = $("#" + list_id);

// Fill new fake datalist
datalistItems.each(function() {
$("<li />", {
"text": $(this).val()
}).appendTo($datalist);
});

// Update pointer
datalistItems = $datalist.find("li");

// Typey type type
$input
.on("focus", function() {
// Reset scroll
$datalist.scrollTop(0);
scrollValue = 0;
})
.on("blur", function() {

// If this fires immediately, it prevents click-to-select from working
setTimeout(function() {
$datalist.fadeOut(options.fadeOutSpeed);
datalistItems.removeClass("active");
}, 500);
})
.on("keyup focus", function(e) {
searchPosition = $input.position();

// Build datalist
$datalist
.show()
.css({
top: searchPosition.top + $(this).outerHeight(),
left: searchPosition.left,
width: $input.outerWidth()
});

datalistItems.hide();
$datalist.find("li:RD_contains('" + $input.val() + "')").show();
});

// Don't want to use :hover in CSS so doing this instead
// really helps with arrow key navigation
datalistItems
.on("mouseenter", function() {
$(this).addClass("active").siblings().removeClass("active");
})
.on("mouseleave", function() {
$(this).removeClass("active");
});

// Window resize
$(window).resize(function() {
searchPosition = $input.position();
$datalist
.css({
top: searchPosition.top + $(this).outerHeight(),
left: searchPosition.left,
width: $input.outerWidth()
});
});

// Watch arrow keys for up and down
$input.on("keydown", function(e) {

var active = $("li.active"),
datalistHeight = $datalist.outerHeight(),
datalistItemsHeight = datalistItems.outerHeight();

// up arrow
if ( e.keyCode == 38 ) {
if (active.length) {
prevAll = active.prevAll("li:visible");
if (prevAll.length > 0) {
active.removeClass("active");
prevAll.eq(0).addClass("active");
}

if ( prevAll.length && prevAll.position().top < 0 && scrollValue > 0 ){
$datalist.scrollTop(scrollValue-=datalistItemsHeight);
}
}
}

// down arrow
if ( e.keyCode == 40 ) {
if (active.length) {
var nextAll = active.nextAll("li:visible");
if (nextAll.length > 0) {
active.removeClass("active");
nextAll.eq(0).addClass("active");
}

if ( nextAll.length && (nextAll.position().top + datalistItemsHeight) >= datalistHeight ){
$datalist.stop().animate({
scrollTop: scrollValue += datalistItemsHeight
}, 200);
}
} else {
datalistItems.removeClass("active");
$datalist.find("li:visible:first").addClass("active");
}
}

// return or tab key
if ( e.keyCode == 13 || e.keyCode == 9 ) {
if (active.length) {
$input.val(active.text());
item_selected(active.text());
}
$datalist.fadeOut(options.fadeOutSpeed);
datalistItems.removeClass("active");
}

// keys
if ( e.keyCode != 13 && e.keyCode != 38 && e.keyCode != 40 ){
// Reset active class
datalistItems.removeClass("active");
$datalist.find("li:visible:first").addClass("active");

// Reset scroll
$datalist.scrollTop(0);
scrollValue = 0;
}

});

// When choosing from dropdown
datalistItems.on("click", function() {
var active = $("li.active");
if (active.length) {
$input.val($(this).text());
}
$datalist.fadeOut(options.fadeOutSpeed);
datalistItems.removeClass("active");
item_selected($(this).text());
});

function item_selected(new_text) {
if( typeof options.change === 'function' )
options.change.call(this, new_text);
}

} // end if
});
};
})(jQuery);
2 changes: 1 addition & 1 deletion js/relevant-dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ $(function() {
});

// Update pointer
var datalistItems = $datalist.find("li");
datalistItems = $datalist.find("li");

// Typey type type
doc
Expand Down
44 changes: 39 additions & 5 deletions readme.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

Datalist browser support (Dec 2011) is Firefox 4+, Opera 10.6+, and IE 10. It's reasonable that you'd want WebKit support. So. This.

###Usage
### Usage without the Plugin

Markup like this. IMPORTANT, use value attribute not text.

```
```html
<input type="search" list="states" placeholder="Find U.S. State">

<datalist id="states">
Expand All @@ -20,17 +20,51 @@ Markup like this. IMPORTANT, use value attribute not text.

You'll need the scripts:

```
```html
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script src="js/modernizr.custom.50983.js"></script>
<script src="js/relevant-dropdown.js"></script>
```

On Line 12 of the relevant-dropdown.js file you can change the ID to your own search input's ID.
On Lines `[12, 42, 47, 55, 91]` of the relevant-dropdown.js file you can change the ID to your own search input's ID.

### Using the Plugin

Markup

```html
<input type="search" list="states" placeholder="Find U.S. State">

<datalist id="states">
<option value="Alabama">
<option value="Alaska">
<!-- all states -->
</datalist>
```

Include jQuery, Modernizer and the Plugin:

```html
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script src="js/modernizr.custom.50983.js"></script>
<script src="js/jquery.relevant-dropdown.js"></script>
```

Using the Plugin

```html
<script>
$('#names').relevantDropdown({
fadeOutSpeed: 'normal', // optional, default: 'normal'
change: function(new_text) {
console.log('the new value is: ', new_text);
}
});
</script>
```

###TODO

- Make better
- Plugize / work on multiple inputs
- Better IE styling
- Might be able to remove Modernizr and just test for support of list attribute in element