我在其中一个代码中有一个搜索功能,它理想地在值列表(小数字)上执行搜索。
<li>abc</li>
<li>def</li>
...
我在底部有一个搜索按钮,我放置了一个keyup
事件侦听器来获取即时搜索。现在的问题是如何使它可导航。理想的场景搜索一些文本,按回车键,它应该打开第一个元素,否则你应该能够导航。
如果我在上面不清楚,我实际上是在要求一个与 Facebook Chat 侧边栏搜索非常相似的功能。
我在其中一个代码中有一个搜索功能,它理想地在值列表(小数字)上执行搜索。
<li>abc</li>
<li>def</li>
...
我在底部有一个搜索按钮,我放置了一个keyup
事件侦听器来获取即时搜索。现在的问题是如何使它可导航。理想的场景搜索一些文本,按回车键,它应该打开第一个元素,否则你应该能够导航。
如果我在上面不清楚,我实际上是在要求一个与 Facebook Chat 侧边栏搜索非常相似的功能。
为了没有将jQuery添加到标签列表中的OP(恭喜你),我将添加一个纯JavaScript的小型导航插件。
披露——实际逻辑的功劳归功于 Facebook 的 Eric Priestley,因为这是从他的 Javelin JS 库中提取的。
我在这里发布了指向小提琴的链接。我还从您的问题中假设您已经有了搜索解决方案,并且只是在寻找导航解决方案。
从小提琴交叉张贴。我在代码中评论了很多,所以应该是自我解释的。虽然如果您确实有疑问,请与我们联系。
HTML 可以是你想要的任何东西。为简洁起见,我添加了这个
<input id='control' type='text' placeholder='Search text here' />
<!-- List of results - hardcoded for now -->
<ul id='hardpoint' class='hidden'>
<li class='item'>Search item 1</li>
<li class='item'>Search item 2</li>
<li class='item'>Search item 3</li>
<li class='item'>Search item 4</li>
</ul>
编码
(function() {
/**
* Helper functions
*/
var bind = function( context, func, more ){
if (typeof func !== 'function') {
throw new Error ("No function supplied to bind function");
}
var bound = Array.prototype.slice.call( arguments ).slice(2);
if (func.bind) {
return func.bind.apply(func, [context].concat(bound));
}
return function() {
return func.apply(context || window, bound.concat(Array.prototype.slice.call( arguments )));
}
};
var getChildElements = function(node) {
var childNodes = Array.prototype.slice.call(node.childNodes);
childNodes = childNodes.filter(function(item) {
return item.tagName && item.nodeType && item.nodeType === 1 && item !== node;
});
return childNodes;
};
var hasClass = function(node, className) {
return ((' ' + node.className + ' ').indexOf(' ' + className + ' ') > -1);
};
var alterClass = function(node, className, add) {
var has = hasClass(node, className);
if (add && !has) {
node.className = node.className.trim() + ' ' + className;
}
else if (has && !add) {
node.className = node.className.replace(
new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), ' ');
}
};
var getIndex = function( list, element ){
var index = -1;
for (var i = 0; i < list.length; i++) {
if( list[i] === element ){
index = i;
break;
}
};
return index;
};
// Start of plugin
// Constructor
var ListNavigator = function(config) {};
// This can be moved within constructor if you so prefer
ListNavigator.prototype.init = function(config) {
// On what element do you want the controls to activate
// Pressing up down etc on this element, triggers tha navigation
this.control = document.getElementById(config.control);
// The list of results that can be navigated
this.hardpoint = document.getElementById(config.hardpoint);
// A list of items ( usually, childNodes ) of hardpoint
// Dynamically populated
this.display = getChildElements(this.hardpoint);;
// What to set the focus on initially
this.focus = -1;
// Specify a function to execute when the user chooses a result
// Keydown - Return : configured to be the choose event type now
this.choose = config.choose;
this.selector = config.selector;
};
ListNavigator.prototype.run = function() {
var controlEvents = ['focus', 'blur', 'keydown', 'input'],
mouseEvents = [ 'mouseover', 'mouseout', 'mousedown' ],
self = this,
selector = this.selector;
controlEvents.forEach(function(event) {
self.control.addEventListener(event, bind(self, self.handleEvent), false);
});
mouseEvents.forEach(function(event) {
self.hardpoint.addEventListener(event, bind(self, self.onmouse), true);
});
};
// Logic to change the focus on keydown
ListNavigator.prototype.changeFocus = function(d) {
var n = Math.min( Math.max( -1, this.focus + d ), this.display.length - 1);
if (this.focus >= 0 && this.focus < this.display.length) {
alterClass(this.display[this.focus], 'focused', false);
}
this.focus = n;
this.drawFocus();
return true;
};
// Set the focus on the targetted element
ListNavigator.prototype.drawFocus = function() {
var f = this.display[this.focus];
if (f) {
alterClass(f, 'focused', true);
}
};
// Handle mouse events
ListNavigator.prototype.onmouse = function(event) {
var target = event.target, type = event.type;
if ( hasClass( target, this.selector ) ) {
if ( type === 'mousedown' ) {
// Choose this element
this.choose(target);
}
else if ( type === 'mouseover' ) {
// Set the focus to element on which mouse is hovering on
this.focus = getIndex( this.display, target );
this.drawFocus();
}
else if ( type === 'mouseout' ){
// Reset the display to none
this.changeFocus(Number.NEGATIVE_INFINITY);
}
};
};
ListNavigator.prototype.handleEvent = function(e) {
var type = e.type;
if (type === 'blur') {
this.focused = false;
this.hide();
} else {
alterClass(this.hardpoint, 'hidden', false);
this.update(e);
}
};
ListNavigator.prototype.hide = function() {
this.changeFocus(Number.NEGATIVE_INFINITY);
this.display = [];
alterClass(this.hardpoint, 'hidden', true);
};
ListNavigator.prototype.submit = function() {
if (this.focus >= 0 && this.display[this.focus]) {
this.choose(this.display[this.focus]);
} else {
if (this.display.length) {
this.changeFocus(1);
this.choose(this.display[this.focus]);
}
}
return false;
};
ListNavigator.prototype.update = function(event) {
console.log( 'upadte' );
this.display = getChildElements(this.hardpoint);
if (event.type === 'focus') {
this.focused = true;
}
var k = event.which;
if (k && event.type == 'keydown') {
switch (k) {
case 38:
if (this.display.length && this.changeFocus(-1)) {
event.stopPropagation();
}
break;
case 40:
if (this.display.length && this.changeFocus(1)) {
event.stopPropagation();
}
break;
case 13:
if (this.display.length) {
this.hide();
event.stopPropagation();
this.submit();
}
break;
case 27:
if (this.display.length) {
this.hide();
event.stopPropagation();
}
break;
case 9:
// If the user tabs out of the field, don't refresh.
return;
}
}
};
window.ListNav = ListNavigator
})();
var nav = new ListNav();
nav.init({
control: 'control',
hardpoint: 'hardpoint',
selector: 'item',
choose: function(){
console.log( arguments );
}
});
nav.run();
<html lang="html">
<head>
<meta charset="utf-8" />
<title>Search Users</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("#searched_users_list").hide();
$("#search_user").keyup(function(){
var what_to_search = $(this).val().toLowerCase();
if(what_to_search != ''){
$("#users_list").hide();
$("#searched_users_list").show();
}else{
$("#users_list").show();
$("#searched_users_list").hide();
}
var searched_users = '';
var user_name = '';
$("#users_list").children('li:contains("'+what_to_search+'")').each(function(){
user_name = $(this).html();
searched_users += "<li>"+user_name+"</li>";
});
if(searched_users != '')
$("#searched_users_list").html(searched_users);
else
$("#searched_users_list").html('<li>No user found....</li>');
})
});
</script>
</head>
<body>
<ul id="users_list">
<li>abc</li>
<li>defa</li>
<li>ghife</li>
</ul>
<ul id="searched_users_list">
<li>No user found....</li>
</ul>
<input type="text" name="search_users" id="search_user" value="" />
</body>
</html>
It's my first post... Sorry If something is odd.
如果这是我的页面,我会将可搜索元素标记为类,<li class="searchable">abc</li>
并且我将使用 jQuery 通过选择器查找页面中的所有可搜索元素,例如$("li.searchable:contains('" + SEARCHTERM + "')")
之前我们定义 var SEARCHTERM = $("#searchbox").文本();
您可能希望对此进行一些微调(例如:contains 区分大小写),但这听起来是否方向正确?
您是否正在寻找自动完成功能...?如果是这样,您应该查看 jQuery UI 自动完成:http: //jqueryui.com/autocomplete/