Javascript 下拉列表中的keydown事件

Javascript 下拉列表中的keydown事件,javascript,jquery,html,google-chrome,Javascript,Jquery,Html,Google Chrome,我试图创建一个下拉列表,当用户按住SHIFT键时,它将在所有其他下拉列表上选择相同的索引 目前,我正在做以下工作: $(document).on('keyup keydown', function (e) { shifted = e.shiftKey }); $(document).on('change', '.report_info select', function (e) { if (shifted) { //Code to change other drop do

我试图创建一个下拉列表,当用户按住SHIFT键时,它将在所有其他下拉列表上选择相同的索引

目前,我正在做以下工作:

$(document).on('keyup keydown', function (e) { shifted = e.shiftKey });
$(document).on('change', '.report_info select', function (e) {
    if (shifted) {
        //Code to change other drop down lists.
    }
});
只有在进入下拉列表之前按住shift键,此功能才有效。如果您在DDL内并按下shift键,则不会触发keyup/keydown事件,并且
SHIFED
将保持
false

当下拉列表处于焦点时,是否有任何方法可以捕捉到keyup/keydown事件?

编辑:

看起来这可能只是Chrome的一个问题,只是尝试添加以下内容,它在Firefox和IE中工作,但在Chrome中不工作:

$(document).on('keyup keydown', 'select', function (e) {
    shifted = e.shiftKey;
});

下面是一个在chrome中不起作用的例子:

您的语法看起来不正确

$("#target").keydown(function() {
    alert( "Handler for .keydown() called." );
});

Chrome hack:您可以为文档设置自定义事件。并在DDL内按shift键时触发此事件。Jquery触发触发器可以传递自定义参数。

检查工作状态

请针对您的场景尝试以下脚本

 <script type="text/javascript" language="javascript">
    window.shifted = false;
    $(document).on('keyup keydown', function (e) { shifted = e.shiftKey; });
    $(document).on('change', 'select.report_info', function (e) {
        var cr = $(this).val();
        if (shifted) {
            $('.report_info').each(function () {
                $(this).val(cr);
            });
        }
    });
</script>

window.shift=false;
$(document).on('keyup-keydown',函数(e){shifted=e.shiftKey;});
$(文档).on('change','select.report_info',函数(e){
var cr=$(this.val();
如果(移位){
$('.report_info')。每个(函数(){
$(此).val(cr);
});
}
});

老实说,这是一个相当粗糙的解决方案,但在你希望找到更好的解决方案之前,这是一种达到目的的手段

因为问题是chrome在dropdownlist消失之前不会在
select
元素上注册keydown/keyup事件,所以我们需要

a)找出如何激发事件(我不知道)

b)检查我们的条件是否以不同的顺序得到满足

Chrome会在点击后触发shift键按下事件,因此我们可以简单地检查点击是否在该事件发生之前被按下。由于其他浏览器的行为更符合预期,我们也将保留前面的代码

为此,我们在点击事件上设置了一个计时器,然后当select的shift事件被触发时,如果点击事件计时器也被设置了,我们应该在这里运行我们的代码,这样chrome就会触发它。然后我们重置计时器,使其不会多次触发

注意:如果您在设置值后立即按shift键(在您指定的单击限制范围内),它也将设置所有值。我不认为这是不合理的,因为当它发生时,实际上感觉很自然

我使用了以下代码:

var shifted = false;
var hackytimer = 0;

$(document).on('keyup keydown', function (e) { 
    shifted = e.shiftKey;
});

$(document).on('keyup keydown', 'select', function (e) {
    shifted = e.shiftKey;
    if(Date.now() - hackytimer <200){
        changeAllSelects($(this).val());
    }
});

$(document).on('change', '.report_info select', function (e) {
    hackytimer = Date.now();        
    if (shifted) {
        changeAllSelects($(this).val());
    }
});

function changeAllSelects(cr){
    hackytimer = 0;
    $('.report_info select').each(function () {
        $(this).val(cr);
    });
}
var=false;
var-hackytimer=0;
$(文档).on('keyup-keydown',函数(e){
移位=e.移位键;
});
$(文档).on('keyup keydown','select',函数(e){
移位=e.移位键;

if(Date.now()-hackytimer我认为@judgeja的回应可能是你最好的选择。我将此作为“答案”而不是评论发布,因为我已经做了自己的研究,以确定当Chrome中打开
select
元素时绝对不会触发任何事件

参见小提琴:

我已经将所有可能的事件处理程序(我认为)附加到
input
元素和
select
元素

在Chrome中,当使用
input
元素时,您会看到许多事件触发,但当第一个
select
元素打开时,您不会看到任何事件触发

有趣的是,如果
select
元素具有
multiple
属性或
size
>1,则会在Chrome中触发事件

在Firefox中,您将看到所有三个元素都会触发事件

在@judgeja的建议之外,您最好的选择可能是模拟
select
元素。

Bryan, 您可以尝试以下方法来实现这一点。我在JSFIDLE上进行了测试,如果我正确回答了您的问题,它将以您的方式工作

 var shifted = false;
$(document).on('keyup keydown', function (e) { shifted = e.shiftKey; });

$("select").on('keyup keydown',  function (e) {
    shifted = e.shiftKey;  
});
    $('.report_info select').on('change',  function (e) {
        var cr = $(this).val();
        if (shifted) {
            $('.report_info select').each(function () {
                $(this).val(cr);
            });
        }
    });

请让我知道它是否适用于您。

您好,这不起作用,因为没有关注您的选择,它具有向下键绑定

试试这个


更新

警告:Chrome(mis)行为在不同的平台上有所不同!在Chrome Windows中,在select被释放后会立即触发按键事件,而在OsX上则不会。这解释了为什么@judgeja解决方案对某些人有效,而对我无效,而我的解决方案对OsX有效,而不是在Windows上

因此,我创建了一个更新的fiddle,将我的OsX解决方案与他的Windows解决方案合并

在触发按键的平台上,使用@judgeja解决方案,如果未触发,则在没有上一个按键的情况下测试按键事件(我的上一个解决方案)。这很难看,因为它只在释放shift键后工作,但只在Chrome OsX上工作

var shifted = false;
var hackytimer = 0;
var lastval=null;

$(document).keydown(function(e){
    if(e.which == 16){
        if(Date.now() - hackytimer <200){
            alert("you pressed shift inside the select (Win)");
           changeAllSelects($(this).val());
       }        shifted = true;
    }
});

$(document).keyup(function(e){
    if(e.which == 16) {
        if(!shifted && lastval!=null) {

            alert("you pressed shift inside the select (OsX)");
            $('.report_info select').each(function () {
                changeAllSelects(lastval);
            });

        }
        shifted = false;
    }
});

$(document).on('change', '.report_info select', function (e) {
    hackytimer = Date.now();        
    if (shifted) {
        changeAllSelects($(this).val());
    } else {
        lastval=$(this).val();
    }
});

function changeAllSelects(cr){
    hackytimer = 0;
    $('.report_info select').each(function () {
        $(this).val(cr);
    });
}

应该在没有错误的浏览器上正常运行。无论如何,我同意用类似HTML的东西模拟选择可能是更干净的方法。

首先,你应该选择一个事件进行注册。不要同时注册到keyup和keydown。你给浏览器带来了困难,因为它们会影响你的最终结果。要明白我的意思,只需编辑t他砰地一声,添加了一个keyup事件。最终结果表现得有点马虎

keyup:在键盘上释放一个键时激发的事件

keydown:按下键盘上的键时激发的事件

按键:在键盘上按下某个键时激发的事件

他们有他们的不同,最好坚持一个,我更喜欢在这个例子中使用keydown,只是对我玩得更好,你可以使用keydup

编辑:一个简短的说明。我的示例中的keyup播放得不好,因为似乎selectedIndex中的更改首先出现,然后是绑定的事件。在keydown上,首先触发事件,完成它的工作,然后selectedIndex更改。要使用keyup播放,下面的代码需要一些修改,这意味着该步骤不是
var shifted = false;
var hackytimer = 0;
var lastval=null;

$(document).keydown(function(e){
    if(e.which == 16){
        if(Date.now() - hackytimer <200){
            alert("you pressed shift inside the select (Win)");
           changeAllSelects($(this).val());
       }        shifted = true;
    }
});

$(document).keyup(function(e){
    if(e.which == 16) {
        if(!shifted && lastval!=null) {

            alert("you pressed shift inside the select (OsX)");
            $('.report_info select').each(function () {
                changeAllSelects(lastval);
            });

        }
        shifted = false;
    }
});

$(document).on('change', '.report_info select', function (e) {
    hackytimer = Date.now();        
    if (shifted) {
        changeAllSelects($(this).val());
    } else {
        lastval=$(this).val();
    }
});

function changeAllSelects(cr){
    hackytimer = 0;
    $('.report_info select').each(function () {
        $(this).val(cr);
    });
}
var shifted = false;
var lastval=null;

$(document).keydown(function(e){
    if(e.which == 16){
        shifted = true;
    }
});

$(document).keyup(function(e){
    if(e.which == 16){
        if(!shifted && lastval!=null) {

            alert("you pressed shift inside the select");
            $('.report_info select').each(function () {
                $(this).val(lastval);
            });

        }
        shifted = false;
    }
});

$(document).on('change', '.report_info select', function (e) {
    var cr = $(this).val();
    if (shifted) {
        $('.report_info select').each(function () {
            $(this).val(cr);
        });
    } else {
        lastval=cr;
    }
});
$(document).ready(function(){
    $(document).on('keydown change', 'select', function(evt){
        var shiftKey = evt.shiftKey;
        var code = evt.keyCode || evt.which;

        //if it's a change event and i dont have any shiftKey or code
        //set the to a default value of true
        if(evt.type === 'change' && !shiftKey && !code){
          //special! only when change is fired
          shiftKey = true;
          code = true; 
        }

        //if shift key
        if(shiftKey && (code === 40 || code === 38 || code === true)){

          var target = $(evt.target);
          //if code is not true means it is not a change event, go ahead and set
          //a step value, else no step value
          var step = (code !== true) ? (code === 40) ? 1 : -1 : 0;
          var index = target[0].selectedIndex + step;

          //just to keep the lower and upper bound of the select list
          if(index < 0){
            index = 0;
          }else if(index >= target[0].length){
            index = target[0].length - 1;
          }

          //get all other select lists
          var allOtherSelects = target.closest('div').siblings('div').children('select');
          //foreach select list, set its selectedIndex
          $.each(allOtherSelects, function(i, el){
            el.selectedIndex = index;
          });
        }
      });
    });
 var onkeydown = (function (ev) {
      var key;
      var isShift;
      if (window.event) {
        key = window.event.keyCode;
        isShift = window.event.shiftKey ? true : false;
      } else {
        key = ev.which;
        isShift = ev.shiftKey ? true : false;
      }
      if ( isShift ) {
        switch (key) {
          case 16: // ignore shift key
            break;
          default:
            alert(key);
            // do stuff here?
            break;
        }
      }
    });
      $(document).ready(function() { 
          $('select').keypress(function(event) 
             { return cancelBackspace(event) });
        $('select').keydown(function(event) 
           { return cancelBackspace(event) });
       }); 

      function cancelBackspace(event) {
         if (event.keyCode == 8) {
            return false;
          }
       }