Skip to content

Commit f08c363

Browse files
committed
Merge pull request #3 from BaylorRae/master
Made a jQuery Plugin
2 parents 747dfe6 + 8ea32dd commit f08c363

File tree

4 files changed

+247
-11
lines changed

4 files changed

+247
-11
lines changed

index.html

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
<title>Relevant Dropdown</title>
88

99
<link rel='stylesheet' href='css/style.css'>
10-
11-
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
12-
<script src="js/modernizr.custom.50983.js"></script>
13-
<script src="js/relevant-dropdown.js"></script>
1410
</head>
1511

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

7975
</datalist>
8076

77+
<p><input type="text" id="name" list="names" placeholder="Look for someone!"></p>
78+
79+
<datalist id="names">
80+
<option value="Baylor Rae'">
81+
<option value="Chris Coyier">
82+
</datalist>
83+
8184
<p><a href="https://github.com/chriscoyier/Relevant-Dropdowns">GitHub</a></p>
8285

8386
</div>
8487

88+
<script src="js/jquery.js"></script>
89+
<script src="js/modernizr.custom.50983.js"></script>
90+
<script src="js/jquery.relevant-dropdown.js"></script>
91+
<script>
92+
93+
$('#search').relevantDropdown();
94+
95+
$('#name').relevantDropdown({
96+
fadeOutSpeed: 0
97+
});
98+
99+
</script>
85100
</body>
86-
87101
</html>

js/jquery.relevant-dropdown.js

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
(function($) {
2+
3+
// Make jQuery's :contains case insensitive (like HTML5 datalist)
4+
// Changed the name to prevent overriding original functionality
5+
$.expr[':'].RD_contains = function(a, i, m) {
6+
return $(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
7+
};
8+
9+
$.fn.relevantDropdown = function(options) {
10+
11+
options = $.extend({
12+
fadeOutSpeed: 'normal', // speed to fade out the dataList Popup
13+
change: null
14+
}, options);
15+
16+
return this.each(function() {
17+
18+
var $input = $(this),
19+
list_id = $input.attr('list'),
20+
$datalist = $("#" + list_id),
21+
datalistItems = $datalist.find("option"),
22+
23+
searchPosition,
24+
scrollValue = 0;
25+
26+
// Makes sure the browser doesn't already support the list attribute
27+
// todo: I couldn't figure out how to make an opposite `if statement` without Safari acting up
28+
if( !Modernizr.input.list || (parseInt($.browser.version) > 400) ) {
29+
30+
// Insert home for new fake datalist
31+
$("<ul />", {
32+
"class": "datalist",
33+
"id" : list_id
34+
}).appendTo("body");
35+
36+
// Remove old datalist
37+
$datalist.remove();
38+
39+
// Update pointer
40+
var $datalist = $("#" + list_id);
41+
42+
// Fill new fake datalist
43+
datalistItems.each(function() {
44+
$("<li />", {
45+
"text": $(this).val()
46+
}).appendTo($datalist);
47+
});
48+
49+
// Update pointer
50+
datalistItems = $datalist.find("li");
51+
52+
// Typey type type
53+
$input
54+
.on("focus", function() {
55+
// Reset scroll
56+
$datalist.scrollTop(0);
57+
scrollValue = 0;
58+
})
59+
.on("blur", function() {
60+
61+
// If this fires immediately, it prevents click-to-select from working
62+
setTimeout(function() {
63+
$datalist.fadeOut(options.fadeOutSpeed);
64+
datalistItems.removeClass("active");
65+
}, 500);
66+
})
67+
.on("keyup focus", function(e) {
68+
searchPosition = $input.position();
69+
70+
// Build datalist
71+
$datalist
72+
.show()
73+
.css({
74+
top: searchPosition.top + $(this).outerHeight(),
75+
left: searchPosition.left,
76+
width: $input.outerWidth()
77+
});
78+
79+
datalistItems.hide();
80+
$datalist.find("li:RD_contains('" + $input.val() + "')").show();
81+
});
82+
83+
// Don't want to use :hover in CSS so doing this instead
84+
// really helps with arrow key navigation
85+
datalistItems
86+
.on("mouseenter", function() {
87+
$(this).addClass("active").siblings().removeClass("active");
88+
})
89+
.on("mouseleave", function() {
90+
$(this).removeClass("active");
91+
});
92+
93+
// Window resize
94+
$(window).resize(function() {
95+
searchPosition = $input.position();
96+
$datalist
97+
.css({
98+
top: searchPosition.top + $(this).outerHeight(),
99+
left: searchPosition.left,
100+
width: $input.outerWidth()
101+
});
102+
});
103+
104+
// Watch arrow keys for up and down
105+
$input.on("keydown", function(e) {
106+
107+
var active = $("li.active"),
108+
datalistHeight = $datalist.outerHeight(),
109+
datalistItemsHeight = datalistItems.outerHeight();
110+
111+
// up arrow
112+
if ( e.keyCode == 38 ) {
113+
if (active.length) {
114+
prevAll = active.prevAll("li:visible");
115+
if (prevAll.length > 0) {
116+
active.removeClass("active");
117+
prevAll.eq(0).addClass("active");
118+
}
119+
120+
if ( prevAll.length && prevAll.position().top < 0 && scrollValue > 0 ){
121+
$datalist.scrollTop(scrollValue-=datalistItemsHeight);
122+
}
123+
}
124+
}
125+
126+
// down arrow
127+
if ( e.keyCode == 40 ) {
128+
if (active.length) {
129+
var nextAll = active.nextAll("li:visible");
130+
if (nextAll.length > 0) {
131+
active.removeClass("active");
132+
nextAll.eq(0).addClass("active");
133+
}
134+
135+
if ( nextAll.length && (nextAll.position().top + datalistItemsHeight) >= datalistHeight ){
136+
$datalist.stop().animate({
137+
scrollTop: scrollValue += datalistItemsHeight
138+
}, 200);
139+
}
140+
} else {
141+
datalistItems.removeClass("active");
142+
$datalist.find("li:visible:first").addClass("active");
143+
}
144+
}
145+
146+
// return or tab key
147+
if ( e.keyCode == 13 || e.keyCode == 9 ) {
148+
if (active.length) {
149+
$input.val(active.text());
150+
item_selected(active.text());
151+
}
152+
$datalist.fadeOut(options.fadeOutSpeed);
153+
datalistItems.removeClass("active");
154+
}
155+
156+
// keys
157+
if ( e.keyCode != 13 && e.keyCode != 38 && e.keyCode != 40 ){
158+
// Reset active class
159+
datalistItems.removeClass("active");
160+
$datalist.find("li:visible:first").addClass("active");
161+
162+
// Reset scroll
163+
$datalist.scrollTop(0);
164+
scrollValue = 0;
165+
}
166+
167+
});
168+
169+
// When choosing from dropdown
170+
datalistItems.on("click", function() {
171+
var active = $("li.active");
172+
if (active.length) {
173+
$input.val($(this).text());
174+
}
175+
$datalist.fadeOut(options.fadeOutSpeed);
176+
datalistItems.removeClass("active");
177+
item_selected($(this).text());
178+
});
179+
180+
function item_selected(new_text) {
181+
if( typeof options.change === 'function' )
182+
options.change.call(this, new_text);
183+
}
184+
185+
} // end if
186+
});
187+
};
188+
})(jQuery);

js/relevant-dropdown.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ $(function() {
3535
});
3636

3737
// Update pointer
38-
var datalistItems = $datalist.find("li");
38+
datalistItems = $datalist.find("li");
3939

4040
// Typey type type
4141
doc

readme.markdown

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
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.
66

7-
###Usage
7+
### Usage without the Plugin
88

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

11-
```
11+
```html
1212
<input type="search" list="states" placeholder="Find U.S. State">
1313

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

2121
You'll need the scripts:
2222

23-
```
23+
```html
2424
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
2525
<script src="js/modernizr.custom.50983.js"></script>
2626
<script src="js/relevant-dropdown.js"></script>
2727
```
2828

29-
On Line 12 of the relevant-dropdown.js file you can change the ID to your own search input's ID.
29+
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.
30+
31+
### Using the Plugin
32+
33+
Markup
34+
35+
```html
36+
<input type="search" list="states" placeholder="Find U.S. State">
37+
38+
<datalist id="states">
39+
<option value="Alabama">
40+
<option value="Alaska">
41+
<!-- all states -->
42+
</datalist>
43+
```
44+
45+
Include jQuery, Modernizer and the Plugin:
46+
47+
```html
48+
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
49+
<script src="js/modernizr.custom.50983.js"></script>
50+
<script src="js/jquery.relevant-dropdown.js"></script>
51+
```
52+
53+
Using the Plugin
54+
55+
```html
56+
<script>
57+
$('#names').relevantDropdown({
58+
fadeOutSpeed: 'normal', // optional, default: 'normal'
59+
change: function(new_text) {
60+
console.log('the new value is: ', new_text);
61+
}
62+
});
63+
</script>
64+
```
3065

3166
###TODO
3267

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

0 commit comments

Comments
 (0)