jQuery:处理多个按键监听器?

时间:2011-01-24 15:24:45

标签: javascript jquery

我有一个页面需要同时做两件事:

  • 一直聆听来自扫描仪的输入(显示为键盘输入),并注意以正确格式输入字符串的时间。
  • 倾听关注特定下拉列表的用户,并键入一组首字母 - 当输入的一组首字母与下拉列表中项目的title属性匹配时,请关注该下拉列表。

我可以单独做这些事情中的任何一个,但不能一起做。代码:

// Listen for input when userlist is in focus. 
$("#userlist").keypress(function (e) {
    initials += String.fromCharCode(e.which).toUpperCase();
    $(this).find("option").filter(function () {
        return $(this).attr("title").toUpperCase().indexOf(initials) === 0;
    }).first().attr("selected", true);      
    // uses timer to check for time between keypresses
    return false;
});
// Listen for scanner input all the time. 
var input = '',
    r1 = /^~{1}$/,
    r2 = /^~{1}\d+$/,
    r3 = /^~{1}\d+\.$/,
    r4 = /^~{1}\d+\.\d+$/,
    r5 = /^~{1}\d+\.\d+~{1}$/;
$(window).keypress(function(e) {
    // when input matches final regex, do something  
}    

如果我同时使用两者,那么当用户专注于下拉菜单时,页面就不会“听到”来自扫描仪的输入。

如何将两者组合在一起以确保页面对扫描仪输入做出反应,即使用户专注于下拉列表也是如此?

4 个答案:

答案 0 :(得分:0)

这是因为您使用keypress对象上的侦听器覆盖窗口对象上的侦听器。我会做这样的事情:

var input = '',
r1 = /^~{1}$/,
r2 = /^~{1}\d+$/,
r3 = /^~{1}\d+\.$/,
r4 = /^~{1}\d+\.\d+$/,
r5 = /^~{1}\d+\.\d+~{1}$/;
function checkRegex(e) { /* Check */ }

// Listen for input when userlist is in focus. 
$("#userlist").keypress(function (e) {
        checkRegex(e);
    initials += String.fromCharCode(e.which).toUpperCase();
    $(this).find("option").filter(function () {
        return $(this).attr("title").toUpperCase().indexOf(initials) === 0;
    }).first().attr("selected", true);      
    // uses timer to check for time between keypresses
    return false;
});
// Listen for scanner input all the time. 
$(window).keypress(function(e) {
    checkRegex(e);
}    

答案 1 :(得分:0)

delegate不会给你必要的控制权吗?然后,您可以检查事件目标并做出相应的响应吗?

即:

$(window).delegate('keypress', function(e){
    if ($(e.target).attr('id') == 'userlist'){
        // something
    }else{
        //something else
    }
});

答案 2 :(得分:0)

您不需要两个处理程序。只需在窗口级别有一个处理程序,然后检查引发事件的元素:

$(window).keypress(function(e) {
  var $target = $(e.target);
  if ($target.is("#userlist")) {
    initials += String.fromCharCode(e.which).toUpperCase();
    $(this).find("option").filter(function () {
    return $(this).attr("title").toUpperCase().indexOf(initials) === 0;
    }).first().attr("selected", true);      
    // uses timer to check for time between keypresses
    return false;
   } else {
       // when input matches final regex, do something  
   }

});

答案 3 :(得分:0)

这可能比你想要的更复杂,但我认为这符合你的目的。

我试图以jQuery插件的方式制作它,并允许你将它附加到任何特定的对象(并且它的自定义应该覆盖通过DOM冒泡(在你的组合框的情况下)除了允许窗户等

无论如何,尝试一下,看看你的想法。如有必要,我可以进行修改,只需知道它们是什么。

工作示例: http://www.jsfiddle.net/bradchristie/xSMQd/4/

;(function($){
    $.keyListener = function(sel, options){
        // avoid scope issues by using base instead of this
        var base = this;

        // Setup jQuery DOM elements
        base.$sel = $(sel);
        base.sel = sel;
        base.keyPresses = '';
        base.validater = null;

        // add a reverse reference to the DOM object
        base.$sel.data('keyListener', base);

        // create an initialization function we can call
        base.init = function(){
            base.opts = $.extend({}, $.keyListener.defaultOptions, options);

            base.$sel.keypress(function(e){
                base.keyPresses += String.fromCharCode(e.which);

                if (base.validator != null)
                    clearTimeout(base.validator);
                if (base.keyPresses != '')
                    base.validator = setTimeout(base.validateInput, base.opts.callbackDelay);

                if (base.opts.preventDefault)
                    e.preventDefault();
                else if (base.opts.stopPropagation)
                    e.stopPropagation();
            });
        };

        base.validateInput = function(){
            var filter = base.opts.filter;
            var reCompare = (typeof(filter)=='object'
                             ? filter.constructor.toString().match(/regexp/i)!==null
                             : false);

            // exception when the input is cleared out
            var input = base.sel.constructor.toString().match(/HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement/i);
            if (input && (!base.opts.preventDefault && base.$sel.val() == ''))
                base.keyPresses = '';

            // regular expression match
            if (reCompare){
                if (base.keyPresses.match(filter))
                    base.validateSuccess();
                else
                    base.validateFailure();
            // traditional string match
            }else if (typeof(filter)=='string'){
                if (base.keyPresses==filter)
                    base.validateSuccess();
                else
                    base.validateFailure();
            }

            // reset string
            base.keyPresses = '';
        };

        base.validateSuccess = function(){
            if (typeof(base.opts.success)=='function')
                base.opts.success(base.keyPresses);
        };
        base.validateFailure = function(){
            if (typeof(base.opts.failure)=='function')
                base.opts.failure(base.keyPresses);
        };

        // run the initializer
        base.init();
    };

    $.keyListener.defaultOptions = {
        // time to wait before triggering callback
        // Give it time to accumulate the key presses and send it off
        // as a compiled package
        callbackDelay: 1000,

        // Filter to apply to the input (can be a string match or a regular expression)
        filter: /.*/,

        // functions to callback when a match has or hasn't been made
        success: function(i){},
        failure: function(i){},

        // would you like this to completely override key input?
        preventDefault: false,

        // stop it from going up the DOM tree (first object to grab the keypress
        // gets it)
        stopPropagation: true,
    };

    $.fn.extend({
        keyListener: function(options){
            // use return to allow jQuery to chain methods
            return this.each(function(){
                (new $.keyListener(this, options));
            });
        }
    });
})(jQuery);

$('#listen-scanner,#listen-combo,#listen-text').add(window).keyListener({
    filter: /^\d+$/,
    success: function(input){
        $('#output-scanner').text('Match!: '+input);
    },
    failure: function(input){
        $('#output-scanner').text('No Match: '+input);
    },
    stopPropagation: true
});

我试过的HTML:

<input type="text" id="listen-scanner" /><span id="output-scanner"></span><br />
<select id="listen-combo">
    <option value="AA">Aardvarc</option>
    <option value="AB">Abracabra</option>
    <option value="AC">Accelerate</option>
    <option value="AD">Adult</option>
</select><span id="output-combo"></span>
<textarea id="listen-text"></textarea>