web-dev-qa-db-de.com

keydown-Ereignis in der Dropdown-Liste

Ich versuche, eine Dropdown-Liste zu erstellen. Wenn ein Benutzer die UMSCHALTTASTE gedrückt hält, wird er in allen anderen Dropdown-Listen denselben Index auswählen.

Derzeit mache ich Folgendes:

$(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.
    }
});

Dies funktioniert nur, wenn Sie die Umschalttaste gedrückt halten, bevor Sie die Dropdown-Liste aufrufen. Wenn Sie sich in der DDL befinden und die Umschalttaste drücken, wird das Ereignis keyup/keydown nicht ausgelöst und shifted bleibt false.

Gibt es eine Möglichkeit, das keyup/keydown-Ereignis abzufangen, während eine Dropdownliste fokussiert ist?

Bearbeiten:

Sieht so aus, als könnte dies ein Problem mit Chrome sein. Versuchen Sie, Folgendes hinzuzufügen, und es funktioniert in Firefox und IE, aber nicht in Chrome:

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

Hier ist eine Geige, die nicht in Chrom funktioniert: http://jsfiddle.net/ue6xqm1q/4

18
Bryan

Ich denke, @ judgejas Antwort könnte Ihre beste Wette sein. Ich poste dies als "Antwort" anstelle eines Kommentars, weil ich meine eigene Recherche durchgeführt habe, um festzustellen, dass absolut kein Ereignis ausgelöst wird, wenn ein select-Element in Chrome geöffnet ist.

Siehe Fiddle: http://jsfiddle.net/m4tndtu4/6/

Ich habe alle möglichen Event-Handler (denke ich) an das input-Element und beide select-Elemente angehängt.

In Chrome werden viele Ereignisse ausgelöst, wenn Sie mit dem Element input arbeiten. Es werden jedoch keine Ereignisse ausgelöst, wenn Sie mit dem ersten Element select arbeiten, wenn es geöffnet ist.

Interessanterweise werden Ereignisse do in Chrome ausgelöst, wenn das Element select das Attribut multiple oder size> 1 enthält.

In Firefox werden Ereignisse für alle drei Elemente angezeigt.

Außerhalb von @ judgejas Vorschlag könnte es am besten sein, das Element select zu simulieren.

9
Rick Hitchcock

UPDATE

Warnung: Chrome (falsches) Verhalten unterscheidet sich auf verschiedenen Plattformen! In Chrome Windows wird ein Keydown-Ereignis direkt nach der Freigabe des select ausgelöst, während es unter OsX nicht der Fall ist. Dies erklärt, warum die @judgeja-Lösung für einige funktionierte, und didn ' t für mich, während ich unter OsX und nicht unter Windows gearbeitet habe.

Also habe ich eine aktualisierte Geige erstellt, um meine OsX-Lösung mit seiner Windows-Version zusammenzuführen.

http://jsfiddle.net/0fz5vcq6/5//

Auf Plattformen, auf denen der Keydown ausgelöst wird, wird die @judgeja-Lösung verwendet. Wenn dies nicht der Fall ist, wird auf ein Keyup-Ereignis ohne den vorherigen Keydown geprüft (meine vorherige Lösung). Es ist hässlich, da es nur nach dem Loslassen der Umschalttaste funktioniert, aber nur bei 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);
    });
}

Das Guthaben geht hauptsächlich an @judgeja für seine Timer-Lösung mit zusätzlichen Workarounds für den Mac (und andere Plattformen, die sich gleich verhalten).

Ich denke immer noch, die Auswahl mit etwas HTML wie http://gregfranko.com/jquery.selectBoxIt.js/ zu emulieren, ist sauberer, da sie Keydown/Keyups nicht stören sollten.

VORHERIGE LÖSUNG (nur OsX)

Die einzige Lösung, an die ich denken könnte, ist, wenn überhaupt kein Ereignis vorliegt, zu testen, ob ein Hochschalten ohne das vorherige Herunterfahren stattgefunden hat. Dies kann funktionieren, wenn Sie keine anderen Elemente haben, die sich wie die ausgewählten Elemente verhalten

http://jsfiddle.net/6jkkgx5e/

Es ist ein bisschen schwierig und schmutzig, funktioniert, sobald der Benutzer die Umschalttaste loslässt

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;
    }
});

Sollte sich auf nicht fehlerhaften Browsern normal verhalten. Wie auch immer, ich bin damit einverstanden, die Auswahlen mit etwas HTML wie http://gregfranko.com/jquery.selectBoxIt.js/ zu emulieren, könnte der sauberere Weg sein.

5
FrancescoMM

Um ehrlich zu sein, ist dies eine ziemlich hackige Lösung, aber es ist ein Mittel zum Ende, bis Sie hoffentlich etwas Besseres finden.

Da das Problem darin besteht, dass Chrome die Keydown-/Keyup-Ereignisse für die select-Elemente erst registriert, nachdem die Dropdown-Liste verschwunden ist, müssen wir dies auch tun 

a) finde heraus, wie das Ereignis ausgelöst wird (Ich habe keine Ahnung) 

oder 

b) Prüfen Sie, ob unsere Bedingungen in einer anderen Reihenfolge erfüllt wurden. 

Chrome löst das Shift-Tastendruckereignis nach dem Klicken aus, sodass wir einfach prüfen können, ob der Klick unmittelbar vor diesem Ereignis gedrückt wurde. Da sich andere Browser eher erwartungsgemäß verhalten, belassen wir auch den vorherigen Code.

Zu diesem Zweck setzen wir einen Timer für das Klickereignis. Wenn das Schichtereignis für das Select-Ereignis ausgelöst wird, sollten Sie den Timer für das Klickereignis einstellen, und wir sollten unseren Code hier ausführen, damit Chrome ihn auslöst. Wir setzen den Timer dann zurück, damit er nicht mehrmals ausgelöst wird.

NOTE: Wenn Sie die Umschalttaste unmittelbar nach dem Festlegen der Werte drücken (innerhalb des von dem angegebenen Klick festgelegten Grenzwerts), werden auch alle Werte festgelegt. Ich halte das nicht für unvernünftig, da es sich eigentlich ganz natürlich anfühlt, wenn es passiert.

Ich habe folgenden Code verwendet:

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);
    });
}

Siehe Arbeitsbeispiel hier: http://jsfiddle.net/0fz5vcq6/2/

3
James

Bryan, Sie können den folgenden Weg versuchen, dies zu tun. Ich habe auf Jsfiddle getestet, dass es auf Ihre Art funktioniert, wenn ich Ihre Frage richtig verstanden habe.

 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);
            });
        }
    });

Bitte lassen Sie mich wissen, ob es für Sie funktioniert.

1
Vinod Kumar

Hallo, das hat nicht funktioniert, weil Sie keinen Fokus darauf haben, welcher Keydown gebunden ist

versuche dies

http://jsfiddle.net/t8fsuy33/

$('select').first().focus();
1
Prozi

Überprüfen Sie die funktionierenden JS FIDDLER

Versuchen Sie das folgende Skript für Ihr Szenario

 <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>
1
Mayank

Hüpfen Sie, dass dieses Ding Ihnen helfen wird .. :)

 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;
        }
      }
    });
1
O-mkar

Zuerst. Sie sollten eine Veranstaltung auswählen, um sich zu registrieren. Registrieren Sie sich nicht, um gleichzeitig Keydown und Keydown auszuführen. Sie geben dem Browser eine harte Zeit, weil sie Ihr Endergebnis beeinflussen. Um zu verstehen, was ich meine, bearbeiten Sie einfach den Plunk und fügen ein Keyup-Ereignis hinzu. Das Endergebnis verhält sich etwas schlampig.

keyup : Ereignis wird ausgelöst, wenn eine Taste auf der Tastatur losgelassen wird.

keydown : Ereignis wird ausgelöst, wenn eine Taste auf der Tastatur gedrückt wird.

Tastendruck : Ereignis wird ausgelöst, wenn eine Taste auf der Tastatur gedrückt wird.

Sie haben ihre Unterschiede, bleiben Sie besser bei einem, ich ziehe es vor, Keydown zu verwenden, spielt einfach besser mit mir, Sie können Keyup verwenden.

Edit : Eine kurze Notiz. Das Keyup für mein Beispiel spielt nicht gut, weil es so aussieht, als würde der selectedIndex geändert, zuerst kommt es und dann das gebundene Ereignis. Beim Keydown wird zuerst das Ereignis ausgelöst, erledigt es und dann ändert sich der selectedIndex. Um mit Keyup zu spielen, muss der folgende Code geändert werden. Das bedeutet, dass der Schritt nicht erforderlich ist, wenn Sie Keyup verwenden

Ich habe eine plnkr Demo hier

Ich habe es auf IE10, Opera, Safari, Firefox und Chrome getestet. Wie zu erwarten ist, lösen Webkit-Browser das Ereignis keydown/keyup/keypress nicht aus, wenn eine Auswahlliste den Fokus hat. Grund ist mir im Moment unbekannt. In Firefox funktioniert das super. On IE arbeitet teilweise. Also, um Ihr Ziel zu erreichen, benutzerdefinierten Code zur Rettung! Ich habe gerade ein Änderungsereignis an das Dokument gebunden, ich höre auf Kewdown und Änderung. Wenn der Ereignistyp "change" ist, wird die Problemumgehung angewendet. Hier ein Code:

$(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;
          });
        }
      });
    });
1
gdyrrahitis

Ihre Syntax sieht falsch aus.

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

Chrome Hack: Sie können ein benutzerdefiniertes Ereignis für ein Dokument festlegen. Und dieses Ereignis auslösen, wenn Sie die Umschalttaste in der DDL drücken. Jquery-Auslöser können benutzerdefinierte Parameter übergeben.

1
Deep

Ich habe eine sehr einzigartige Lösung für dieses Problem speziell für Chrome gefunden. Es scheint, dass Chrome für ausgewählte Elemente außerhalb des normalen Dom verschoben wird, wenn sie den Fokus haben, sodass Sie niemals die onkey-Ereignisse (nach unten | drücken | aufwärts) erhalten, um den Schlüsselcode zu erfassen. Wenn jedoch die Größe des Auswahlfelds> 1 ist, funktioniert es. Wer jedoch ein Dropdown-Feld anstelle eines Kombinationsfelds möchte, kann dieses Problem mit diesem Code lösen. In meinem Fall habe ich versucht, zu verhindern, dass die Rücktaste zur vorherigen Browserseite zurückkehrt. 

Javascript sieht so aus:

      $(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;
          }
       }

Dann sieht HTML so aus:

<select id="coaacct" style="border:none;width:295px;" onclick="if (this.size){this.size=''}else{this.size='20'};">

Ich verwende das onclick -Ereignis, um die Größe des Auswahlfelds auf 20 zu ändern, wenn es keine Größe hat, und es wieder in nichts zu ändern, wenn es eine Größe hat. Auf diese Weise funktioniert es wie ein normales Auswahl-Dropdown-Menü. Da es jedoch bei der Auswahl der Option eine Größe von mehr als 1 hat, werden die Schlüsselcodes erkannt. Ich habe nicht gesehen, dass dies an anderer Stelle angemessen beantwortet wurde, also dachte ich, ich würde meine Lösung teilen.

0
user3520445

Wenn Sie Dinge mit einer Dropdown-Liste machen müssen, die so detailliert sind, lohnt es sich wahrscheinlich nicht, das native <select>-Element so zu verwenden, wie es ist. Allein in diesem Thread werden zahlreiche Implementierungsunterschiede erörtert, und es gibt noch viele weitere, die nicht in den Rahmen dieser Diskussion fallen, die sich aber wahrscheinlich auch auf Sie auswirken werden. Es gibt mehrere JS-Bibliotheken, die dieses Steuerelement umschließen und es auf dem mobilen Gerät belassen können (wo das native Steuerelement tatsächlich benötigt wird), es jedoch auf dem Desktop emulieren, wo das Steuerelement nicht viel tut, was in JS nicht emuliert werden kann .

0
Adam Leggett