捕获按键以过滤元素

时间:2011-05-09 15:26:04

标签: javascript jquery string detection keypress

我正在使用jQuery创建一个<select>替换,用div和链接替换它。

现在,当我开始使用新的选择打开键入内容时,我想过滤

Google Translate类似,语言选择器。

你有什么建议我怎么办?

我开始使用:

$(document).bind('keypress', function(event) {
   //...
});

但我只捕获单个键,而不是整个键入的字符串。


重要:

  • 我没有<input />来检测其上的keypresskeyup事件
  • 我不想创建此<input />,因为我只想在“新选择”中使用<div><a>
  • 最近我需要使用方向键导航打开选择+输入以使用我的键盘选择选项

9 个答案:

答案 0 :(得分:2)

您可以尝试使用jQuery UI的autocomplete

答案 1 :(得分:2)

您可以通过“监听”窗口上按下的内容,然后检测按下的特定字母/字符串,搜索项目列表以及是否发现它更改其css属性或添加新的“选定”类来实现此目的ie(demo =&gt; http://jsfiddle.net/steweb/mC6tn/ ..试图按什么:)和添加后找到的东西按左或右btns,或输入):

JS :(假设您想要找到的每个元素并选择它有类'elem')

var whatYouAreSearching = $('<div class="searching-string"></div>'); //just to see what string you're typing
$(document.body).append(whatYouAreSearching);

function search(what){
    what = what.toLowerCase();
    $('.elem').removeClass('selected'); //reset everything
    $.each($('.elem'),function(index,el){
        if($(el).html().toLowerCase().indexOf(what) > -1){
            $(el).addClass('selected');
            return false; //found, 'break' the each loop
        }
    });
}

var letterPressed = [];
var timeOutResetLetters = null;

$(window).keypress(function(e) {
    clearTimeout(timeOutResetLetters); //clear timeout, important!
    timeOutResetLetters = setTimeout(function(){ //if 500 ms of inactivity, reset array of letters pressed and searching string
        letterPressed = []; 
        whatYouAreSearching.html('');
    },500);
    letterPressed.push(String.fromCharCode(e.keyCode)); //look at the comment, thanks Niclas Sahlin 
    whatYouAreSearching.html(letterPressed.join('')); //show string
    search(letterPressed.join('')); //and search string by 'joining' characters array
});

编辑添加左/右/输入键处理

$(window).keydown(function(e){ //left right handling
    var currSelected = $('.elem.selected');

    if(e.keyCode == "37"){ //left, select prev
        if(currSelected.prev() && currSelected.prev().hasClass('elem')){
            currSelected.prev().addClass('selected');
            currSelected.removeClass('selected');   
        }
    }else if(e.keyCode == "39"){ //right, select next
        if(currSelected.next() && currSelected.next().hasClass('elem')){
            currSelected.next().addClass('selected');
            currSelected.removeClass('selected');   
        }
    }else if(e.keyCode == "13"){ //enter
       $('.entered').remove();
       $(document.body).append(currSelected.clone().addClass('entered'));
    }
});

答案 2 :(得分:1)

如何做你的要求

每次在文档上触发按键事件时,请在变量(可从全局范围或闭包中访问)或在页面上的元素中记录所键入的字符(您可以选择如果您不希望用户看到它,请使用display: hidden;

然后,对下拉列表中的元素进行一次传递,并隐藏那些不包含/以您从单个击键构建的字符串开头的内容。

实际建议的是什么

使用input元素包含用户键入的键击,并让用户看到该元素。

为什么?

因为这是用户已经熟悉的交互行为。如果不使用input元素,则打开几个已使用input元素解决的新问题:

  1. 用户如何知道他们可以键入以过滤列表?输入元素是用户的明确声明:“你应该在这里输入!”
  2. 当用户按下多个键时,用户如何知道将要过滤哪个字符串?当我在Google Translate界面中快速键入“hu”时,选择“匈牙利语”,正如我所料。但是,当我慢慢输入时会发生什么?如果它足够慢,选择'Hatian Creole',然后选择'Ukranian'。
  3. 如果我输入错误并想重新开始怎么办?是否有按钮可以清除它?我需要等待过滤器自行清除多长时间?
  4. 可能肯定会创建一个新的界面元素来解决所有这些问题,如果这是你的目标,那就去做吧,但是这些事情已经存在标准。

    首先,前面提到的autocomplete小部件非常方便,而且非常灵活。

答案 3 :(得分:0)

你可以尝试这样的事情:

var _interval;

$("#textarea/field_id").bind('keypress', function(event) {
   clearTimeout(_interval);
   _interval = setTimeout(onTimeout, 1000);
});

function onTimeout(){
   var words = $("#textarea/field_id").val().split(' ');//do what you want with the string in the field
}

这将捕获整个字符串onTimeout。暂停一下,让它变得干净整洁!

答案 4 :(得分:0)

这个怎么样:

var word='';
$(document).bind('keypress', function(event) {
    //UPDATE word ACCORDING TO THE CHAR, LIKE:
    if (event.charCode >=48 && event.charCode <=57) {
        ....    ....
        ....    ....
    }
    //OR
    switch(event.charCode) {
        ....    ....
        ....    ....
    }

});

答案 5 :(得分:0)

我使用<select>标签创建了我自己的<div>版本,请在此处查看。如果我理解正确,这就是你想要的......

http://jsfiddle.net/myTPC/

它还支持退格(至少在firefox中)。

答案 6 :(得分:0)

我试图做的是:

1)得到keypressed(只有0-9,a-z和空格)并将其保存在div中 2)创建了一个LI列表(你可以使用带有a元素的div,那也没关系) 3)找到包含正在保存的文本的LI项 4)加/右/向下/向左箭头以获得列表中的下一个/上一个项目

现在,它会将所有项目保留在列表中,您也可以隐藏它们。这只是一个例子。

// EDIT

以下是首发设置:http://www.pendemo.nl/keyinputtest.html 在Firefox中,没有自动选择正文,导致您需要在检测到第二个输入之前再次单击正文/网页。在Chrome中,它会检测彼此之后按下的按键。

// EDIT2

在firefox中工作。文本现在保存在div中(您可以键入所需的字符串,并将其放置在正文中)。

// EDIT3

添加了包含一些项目的UL列表。键入一些文本将使用与键入的字符串匹配的项目过滤此列表。

// EDIT4

仅使用a-z和空格进行搜索。仍在寻找如何找到退格键的方法。由于Chrome默认添加'history.go-1'。但是Firefox会注意到退格键。 event.preventDefault()不会改变Chrome中的任何内容。

// EDIT5

添加向上+向右箭头以选择下一个和向左+向下数组以选择上一个项目。

// EDIT6

使用回车键时,当前值是警报。当然,脚本会在警报后停止。但是你可以看到价值可供你使用。

这是我到目前为止提出的代码:

var typed_string = '';

$(document).ready(function() { $('#typedtext').select(); });

$(document).bind('keypress', function(event) {
    event.preventDefault();

    if((event.which > 47 && event.which < 58) || (event.which > 96 && event.which < 123) || event.which == 32) {
        typed_string = typed_string + String.fromCharCode(event.which);
        $('#typedtext').html(typed_string);

        $('#testlist li').css('background-color', '#ffffff');
        $('#testlist li:contains('+typed_string+')').css('background-color', 'green').first().addClass('selected').css('background-color', 'red');

        $('#typedtext').select();
    }

    if(event.which == 13) {
        alert('Selected item: ' + $('.selected').html());
        $('#typedtext').select();
    }
});

$(document).keyup(function(event) {
    event.preventDefault();
    if(event.which == 38 || event.which == 37) {
        $('#testlist li').css('background-color', '#ffffff');
        $('#testlist li:contains('+typed_string+')').css('background-color', 'green');
        $('.selected').removeClass('selected').prev().css('background-color', 'red').addClass('selected');
    }

    if(event.which == 39 || event.which == 40) {
        $('#testlist li').css('background-color', '#ffffff');
        $('#testlist li:contains('+typed_string+')').css('background-color', 'green');
        $('.selected').removeClass('selected').next().css('background-color', 'red').addClass('selected');
    }
});

function clearInput() {
    typed_string = '';  
}

我正在使用这个HTML:

Press any key to save text.<br /><br />
<div id="typedtext" style="border: 1px solid #09F; padding: 5px;"></div>

<br /><br />
Let's test to filter some items from the li. (use up/down or left/right keys to select next item)
<ul id="testlist">
    <li>item</li>
    <li>test</li>
    <li>more test</li>
    <li>another item</li>
    <li>test item</li>
    <li>more item</li>
    <li>foo</li>
    <li>foo bar</li>
    <li>bar</li>
    <li>more foo</li>
</ul>

我认为您可以轻松更改HTML代码以满足您的需求。

答案 7 :(得分:0)

你不想使用输入的原因是什么,如果JS不可用你可以优雅回归选择吗?如果是这样,这可能会做你想要的,我已经使用select作为基础并从那里获取值,尽管我最终在那里输入了一个输入。

根据Neal的回答,我认为自动完成与您需要的非常相似,但如果您想以不同的方式显示结果,我会在显示过滤结果的同一示例中获得第二种方法。

此处的完整示例版本: http://jsfiddle.net/R7APm/9/

这是来自它的JS:

$opts = $('option', '#myselect');

//Grab the text from the select (could use option values instead with .val()
var values = [];
$.each($opts, function(i, opt) {
    values.push($(opt).text());
});

$div = $('<div/>');

//Autocomplete version
$input = $('<input/>').autocomplete({
    source: values
});

//Filter in div version
$wordlist = $('<div id="wordlist"/>');
$wordlist.text(values.join(", "));

$input.keyup(function() {
    matches = $.grep(values, function(el, i) {
        if (el.toLowerCase().indexOf($input.val().toLowerCase()) >= 0) {
            return true;
        } else {
            return false;
        }
    });

    $wordlist.text(matches.join(", "));
});

//Add new elements to wrapper div
$div.append($input);
$div.append($wordlist);

//Replace select with wrapper div
$('#replaceme').replaceWith($div);
$input.focus();

答案 8 :(得分:0)

如果您不想使用隐藏的下拉菜单(我仍然强烈建议),我建议您:

使用http://jsfiddle.net/aWE8b/

上的简单语言下拉菜单查看完整工作演示

该演示包含:

  • 自定义下拉列表
  • 支持的密钥:
    • 退格
    • 输入
    • 逃逸
    • 左,上
    • 向右,向下
  • 2种模式:
    • 过滤:删除不匹配的商品
    • 选择:突出显示第一个匹配的项目