Prześlij okno dialogowe interfejsu użytkownika jQuery na <Enter>

131

Mam okno dialogowe interfejsu użytkownika jQuery z formularzem. Chciałbym zasymulować kliknięcie jednego z przycisków okna dialogowego, aby nie trzeba było do niego używać myszy ani klawisza. Innymi słowy, chcę, aby działało jak zwykłe okno dialogowe GUI, w którym symuluje naciśnięcie przycisku „OK”.

Zakładam, że może to być prosta opcja w oknie dialogowym, ale nie mogę jej znaleźć w dokumentacji interfejsu użytkownika jQuery . Mogłem powiązać każde wejście formularza za pomocą keyup (), ale nie wiedziałem, czy istnieje prostszy / czystszy sposób. Dzięki.

CMB
źródło
Jeśli chcesz uniknąć korzystania z formularza i chcesz kodu wielokrotnego użytku, podałem dobrą odpowiedź tutaj: stackoverflow.com/a/9628800/329367
Darren

Odpowiedzi:

153

Nie wiem, czy istnieje opcja w widżecie jQuery UI , ale możesz po prostu powiązać keypresszdarzenie z elementem div zawierającym twoje okno dialogowe ...

$('#DialogTag').keypress(function(e) {
    if (e.keyCode == $.ui.keyCode.ENTER) {
          //Close dialog and/or submit here...
    }
});

To będzie działać bez względu na to, który element jest aktywny w twoim oknie dialogowym, co może, ale nie musi, być dobrą rzeczą w zależności od tego, czego chcesz.

Jeśli chcesz, aby była to funkcja domyślna, możesz dodać ten fragment kodu:

// jqueryui defaults
$.extend($.ui.dialog.prototype.options, { 
    create: function() {
        var $this = $(this);

        // focus first button and bind enter to it
        $this.parent().find('.ui-dialog-buttonpane button:first').focus();
        $this.keypress(function(e) {
            if( e.keyCode == $.ui.keyCode.ENTER ) {
                $this.parent().find('.ui-dialog-buttonpane button:first').click();
                return false;
            }
        });
    } 
});

Oto bardziej szczegółowy widok tego, jak by to wyglądało:

$( "#dialog-form" ).dialog({
  buttons: { … },
  open: function() {
    $("#dialog-form").keypress(function(e) {
      if (e.keyCode == $.ui.keyCode.ENTER) {
        $(this).parent().find("button:eq(0)").trigger("click");
      }
    });
  };
});
Casey Williams
źródło
2
Nieważne, znalazłem to: dodaj „open” do okna dialogowego (np. Close, modal, bgiframe itp.) I podłącz tam obsługę klucza.
Milan Babuškov
5
W przypadku Webkit (Safari / Chrome) działa to tylko wtedy, gdy zrobię „keydown” zamiast „keyup”. Nie jestem pewien, czy to ostatnia zmiana, czy też ma znaczenie, że moja strona ma również prawdziwy formularz. Mimo to dziękuję za wskazówkę!
Nicholas Piasecki
12
Zamiast if (e.keyCode == 13) możesz zrobić, jeśli (e.keyCode === $ .ui.keyCode.ENTER), aby zwiększyć czytelność.
A. Murray,
2
Głosowałem na tę odpowiedź. Chociaż jest krótkie i zgrabne, w przeglądarce Firefox 7.0.1 spowoduje to również uruchomienie przycisku „OK”, jeśli użytkownik wybierze coś z rozwijanej listy autouzupełniania, np. Poprzednio wprowadzony adres e-mail.
cburgmer
2
To zły pomysł, aby wiązać się z wydarzeniami w „open:”. Spowoduje to ponowne wiązanie za każdym razem, gdy zostanie otwarte okno dialogowe, co oznacza, że ​​jeśli okno zostanie otwarte dwukrotnie, procedura obsługi zdarzenia zostanie wywołana dwukrotnie.
Elezar
67

Podsumowałem powyższe odpowiedzi i dodałem ważne rzeczy

$(document).delegate('.ui-dialog', 'keyup', function(e) {
        var target = e.target;
        var tagName = target.tagName.toLowerCase();

        tagName = (tagName === 'input' && target.type === 'button') 
          ? 'button' 
          : tagName;

        isClickableTag = tagName !== 'textarea' && 
          tagName !== 'select' && 
          tagName !== 'button';

        if (e.which === $.ui.keyCode.ENTER && isClickableTag) {
            $(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');

            return false;
        }
    });

Zalety:

  1. Disallow enter na niezgodnym elementów, takich jak textarea, select, buttonlub wejść z przyciskiem typu, wyobrazić kliknięcie użytkownik wchodzi na textareai dostać formularz przedłożony zamiast się nowy wiersz!
  2. Wiązanie jest wykonywane raz, unikaj używania wywołania zwrotnego w oknie dialogowym `` otwórz '' w celu powiązania klawisza enter, aby uniknąć ponownego wiązania tej samej funkcji za każdym razem, gdy okno dialogowe jest `` otwierane ''
  3. Unikaj zmiany istniejącego kodu, jak sugerują niektóre powyższe odpowiedzi
  4. Użyj „delegata” zamiast przestarzałego „na żywo” i unikaj używania nowej metody „on”, aby umożliwić pracę ze starszymi wersjami jquery
  5. Ponieważ używamy delegata, oznacza to, że powyższy kod można napisać nawet przed zainicjowaniem okna dialogowego. możesz również umieścić go w tagu head nawet bez$(document).ready
  6. Ponadto delegat będzie wiązał tylko jedną procedurę documentobsługi z każdym oknem dialogowym i nie będzie wiązał jej z każdym oknem dialogowym, jak w powyższym kodzie, dla większej wydajności
  7. Działa nawet z dynamicznie generowanymi oknami dialogowymi, takimi jak $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Pracował z ie 7/8/9!
  9. Unikaj używania wolnego selektora :first
  10. Unikaj hacków, takich jak w odpowiedziach tutaj, do tworzenia ukrytego przycisku przesyłania

Niedogodności:

  1. Uruchom pierwszy przycisk jako domyślny, możesz wybrać inny przycisk z eq()lub wywołać funkcję wewnątrz instrukcji if
  2. Wszystkie okna dialogowe będą zachowywać się tak samo, możesz je filtrować, ustawiając selektor bardziej precyzyjnie, np. „#Dialog” zamiast '.ui-dialog'

Wiem, że pytanie jest stare, ale miałem taką samą potrzebę, więc podzieliłem się rozwiązaniem, z którego korzystałem.

Basemm
źródło
4
Fakt, że nie jest to akceptowana odpowiedź i nie ma większej liczby głosów, sprawia, że ​​jestem smutny, bardzo pouczający i nie dodaje ciągle prowadzących. +1
Chris O'Kelly
1
doskonała odpowiedź, posiadanie otwartego wywołania zwrotnego w celu dodania wiązań jest czymś, czego chcesz uniknąć
Jay Rizzi.
1
dla mnie to działa, gdy zdarzenie jest keydown i
usuwam
1
Musiałem też przejść na „keydown”, aby to działało (testowane na OS X 10.8.4, Chrome 29 i Firefox 23).
natebeaty
1
Ponieważ jest to starsza odpowiedź, warto zauważyć, że .delegate()została uznana za przestarzałą w jQuery 3.0, więc .on()(dostępna od wersji 1.7) jest prawdopodobnie właściwą drogą do zrobienia w tym momencie.
jinglesthula
13
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();

Świetnie współpracuje z najnowszą wersją interfejsu użytkownika JQuery (1.8.1). Możesz także użyć: first zamiast: last w zależności od tego, który przycisk chcesz ustawić jako domyślny.

To rozwiązanie, w porównaniu do wybranego powyżej, ma tę zaletę, że pokazuje, który przycisk jest domyślny dla użytkownika. Użytkownik może również wybrać klawisz TAB między przyciskami, a naciśnięcie klawisza ENTER spowoduje kliknięcie przycisku, który jest aktualnie aktywny.

Twoje zdrowie.

Mario Awad
źródło
A co, jeśli twoje okno dialogowe ma jedno lub więcej pól do wprowadzania tekstu? Chcę, aby ENTER wysłał okno logowania, gdy użytkownik znajduje się w polach nazwy użytkownika i hasła.
David Harkness
1
@David, jeśli używasz przycisków okna dialogowego jQuery, po prostu ukryj zwykły przycisk przesyłania danych wejściowych w formularzu. na przykład. widoczność: ukryta;
Damo,
6

Prosty, ale skuteczny sposób, aby to działało bardziej ogólnie:

$.fn.dlg = function(options) {
    return this.each(function() {
             $(this).dialog(options);
             $(this).keyup(function(e){
                  if (e.keyCode == 13) {                
                       $('.ui-dialog').find('button:first').trigger('click');
                  }
             });
    });
}

Następnie podczas tworzenia nowego okna dialogowego możesz to zrobić:

$('#a-dialog').mydlg({...options...})

I używaj go jak normalnego okna dialogowego jquery:

$('#a-dialog').dialog('close')

Istnieją sposoby, aby to poprawić, aby działało w bardziej szczególnych przypadkach. Z powyższym kodem automatycznie wybierze pierwszy przycisk w oknie dialogowym jako przycisk uruchamiany po naciśnięciu klawisza Enter. Zakłada również, że w danym momencie jest tylko jedno aktywne okno dialogowe, co może nie mieć miejsca. Ale masz pomysł.

Uwaga: Jak wspomniano powyżej, przycisk, który jest naciskany na enter, zależy od konfiguracji. Tak więc w niektórych przypadkach możesz chcieć użyć: first selector w metodzie .find, aw innych możesz użyć: last selector.

Karim
źródło
Myślę, że powinno tam być .first () jak w $ ('. Ui-dialog'). Find ('button'). First (). Trigger ('click'); W przeciwnym razie klikniesz wszystkie przyciski okna dialogowego, jeśli jest więcej niż jeden.
JustinStolle
@thejh - nie, dołącza procedurę obsługi zdarzenia keyup do każdego okna dialogowego, ale tylko okno dialogowe zawierające element z fokusem po naciśnięciu klawisza otrzyma zdarzenie.
David Harkness
6

Zamiast nasłuchiwać kluczowych kodów, takich jak w tej odpowiedzi (których nie mogłem wykonać), możesz powiązać zdarzenie przesyłania formularza w oknie dialogowym, a następnie zrobić to:

$("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();

Tak więc całość wyglądałaby tak

$("#my_form").dialog({
  open: function(){
    //Clear out any old bindings
    $("#my_form").unbind('submit');
    $("#my_form").submit(function(){
      //simulate click on create button
      $("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();
      return false;
    });
  },
  buttons: {
    'Create': function() {
      //Do something
    },
    'Cancel': function() {
      $(this).dialog('close');
    }
  }
});

Zwróć uwagę, że różne przeglądarki inaczej obsługują klawisz Enter, a niektóre nie zawsze wykonują przesyłanie przy wejściu.

Oprogramowanie Salida
źródło
Wydaje się, że to najbardziej elegancka odpowiedź.
Dan
To nie działa, gdy mam trzy lub więcej danych wejściowych w tym samym oknie dialogowym. Nie wiem dlaczego.
programad
6

Bena Claytona jest najładniejszym i najkrótszym i można go umieścić na górze strony indeksu, zanim jakiekolwiek okna dialogowe jquery zostaną zainicjowane. Chciałbym jednak zaznaczyć, że format „.live” został wycofany. Preferowaną akcją jest teraz „.on”. Jeśli chcesz, aby „.on” działało jak „.live”, musisz użyć delegowanych zdarzeń, aby dołączyć procedurę obsługi zdarzeń. Jeszcze kilka innych rzeczy ...

  1. Wolę użyć metody ui.keycode.ENTER, aby przetestować klucz enter, ponieważ nie musisz pamiętać rzeczywistego kodu klucza.

  2. Użycie „$ ('. Ui-dialog-buttonpane button: first', $ (this))” dla selektora kliknięcia powoduje, że cała metoda jest ogólna.

  3. Chcesz dodać „return false”; aby zapobiec domyślnemu i zatrzymać propagację.

W tym przypadku...

$('body').on('keypress', '.ui-dialog', function(event) { 
    if (event.keyCode === $.ui.keyCode.ENTER) { 
        $('.ui-dialog-buttonpane button:first', $(this)).click();
        return false;
    }
});
Nelson M.
źródło
4

Nie znam prostszego, ale zwykle śledziłbyś, który przycisk ma bieżący fokus. Jeśli fokus zostanie zmieniony na inny element sterujący, „fokus przycisku” pozostanie na przycisku, który miał fokus jako ostatni. Zwykle „fokus przycisku” rozpoczyna się od przycisku domyślnego. Przejście do innego przycisku zmieniłoby „fokus przycisku”. Trzeba by zdecydować, czy przejście do innego elementu formularza spowoduje ponowne zresetowanie „fokusa przycisku” do przycisku domyślnego. Prawdopodobnie będziesz także potrzebować wizualnego wskaźnika innego niż domyślny przeglądarka, aby wskazać przycisk z fokusem, ponieważ traci on rzeczywisty fokus w oknie.

Po wyłączeniu i zaimplementowaniu logiki fokusa przycisku, prawdopodobnie dodałbym obsługę klawisza do samego okna dialogowego i kazałbym wywołać akcję skojarzoną z aktualnie „aktywnym” przyciskiem.

EDYCJA : Zakładam, że chcesz mieć możliwość naciśnięcia klawisza Enter za każdym razem, gdy wypełniasz elementy formularza, a pierwszeństwo ma akcja przycisku „bieżąca”. Jeśli chcesz tylko tego zachowania, gdy przycisk jest faktycznie skupiony, moja odpowiedź jest zbyt skomplikowana.

tvanfosson
źródło
3

Znalazłem to rozwiązanie, działa na IE8, Chrome 23.0 i Firefox 16.0

Opiera się na komentarzu Roberta Schmidta.

$("#id_dialog").dialog({
    buttons: [{
        text: "Accept",
        click: function() {
            // My function
        },
        id: 'dialog_accept_button'
    }]
}).keyup(function(e) {
    if (e.keyCode == $.ui.keyCode.ENTER)
        $('#dialog_accept_button').click();
});

Mam nadzieję, że to pomoże każdemu.

Pablo Oña
źródło
Dzięki! To zaoszczędziło mi dużo czasu! :)
Rahul Desai
3

Czasami zapominamy o fundamentach tego, co przeglądarka już obsługuje:

<input type="submit" style="visibility:hidden" />

Spowoduje to przesłanie ENTERklucza do formularza.

Seifu
źródło
2

Tak zrobiłem ...;) Mam nadzieję, że komuś to pomoże ..

$(window).keypress(function(e) {
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
        $(".ui-dialog:visible").find('.ui-dialog-buttonpane').find('button:first').click();
        return false;
    }
});
Stanislav Vychegzhanin
źródło
2

Powinno to zadziałać, aby wywołać kliknięcie modułu obsługi kliknięcia przycisku. W tym przykładzie założono, że już skonfigurowałeś formularz w oknie dialogowym do używania wtyczki jquery.validate. ale można je łatwo dostosować.

open: function(e,ui) {
    $(this).keyup(function(e) {
        if (e.keyCode == 13) {
           $('.ui-dialog-buttonpane button:last').trigger('click');
        }
    });
},
buttons: {
    "Submit Form" : function() {
            var isValid = $('#yourFormsID').valid();
            // if valid do ajax call
            if(isValid){
               //do  your ajax call here. with serialize form or something...

            }
}
brązowy
źródło
1

Zdaję sobie sprawę, że odpowiedzi jest już wiele, ale naturalnie uważam, że moje rozwiązanie jest najładniejsze i możliwie najkrótsze. Ma tę zaletę, że działa w przypadku wszystkich dialogów utworzonych w dowolnym momencie w przyszłości.

$(".ui-dialog").live("keyup", function(e) {
    if (e.keyCode === 13) {
        $('.ok-button', $(this) ).first().click();
    }
});
Ben Clayton
źródło
1
Hej, dzięki za aktualizację, tylko małe pytanie, co to jest „.ok-button”? czy jest to klasa, którą musisz zastosować na domyślnym przycisku, który chcesz kliknąć enter?
UID
Przepraszam, jeśli znajdziesz pytanie sily .. m zbyt nowy w JS / jQuery
UID
@BenClayton: Ta odpowiedź mogłaby zostać ulepszona, gdybyś umieścił ją w kontekście okna dialogowego jQueryUI.
Bądź miły dla nowych użytkowników,
1

Oto co zrobiłem:

myForm.dialog({
  "ok": function(){
    ...blah...
  }
  Cancel: function(){
    ...blah...
  }
}).keyup(function(e){
  if( e.keyCode == 13 ){
   $(this).parent().find('button:nth-child(1)').trigger("click");
  }
});

W tym przypadku myForm jest obiektem jQuery zawierającym html formularza (uwaga, nie ma tam żadnych tagów "form" ... jeśli je umieścisz, cały ekran odświeży się po naciśnięciu "enter").

Każde naciśnięcie klawisza „enter” z poziomu formularza będzie równoznaczne z kliknięciem przycisku „ok”.

Pozwala to również uniknąć problemu z otwieraniem formularza z już podświetlonym przyciskiem „ok”. Chociaż byłoby to dobre w przypadku formularzy bez pól, jeśli chcesz, aby użytkownik wypełnił pewne rzeczy, prawdopodobnie chcesz, aby pierwsze pole zostało podświetlone.

Tyler
źródło
To najbardziej logiczne rozwiązanie. Nawet lepiej, jeśli zadeklarujesz swój przycisk z identyfikatorem i przekażesz selektor do funkcji find (), ale tak czy inaczej działa. +1
Vincent
1

gotowe i gotowe

  $('#login input').keyup(function(e) {
      if (e.keyCode == 13) {
          $('#login form').submit();
      }
   }
kevin
źródło
0

jeśli znasz selektor elementu przycisku:

$('#dialogBox').dialog('open');
$('#okButton').focus();

Powinien załatwić sprawę za Ciebie. Spowoduje to zaznaczenie przycisku ok, a enter „kliknie” go, jak można się spodziewać. Jest to ta sama technika, która jest używana w natywnych oknach dialogowych interfejsu użytkownika.

piaskowy247
źródło
0
   $("#LogOn").dialog({
       modal: true,
       autoOpen: false,
       title: 'Please Log On',
       width: 370,
       height: 260,
       buttons: { "Log On": function () { alert('Hello world'); } },
       open: function() { $(this).parents('.ui-dialog-buttonpane button:eq(0)').focus();}
   });
LeCram
źródło
0

Znalazłem dość proste rozwiązanie tego problemu:

var d = $('<div title="My dialog form"><input /></div>').dialog(
    buttons: [{
        text: "Ok",
        click: function(){
            // do something
            alert('it works');
        },
        className: 'dialog_default_button'
    }]
});

$(d).find('input').keypress(function(e){
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
        e.preventDefault();
        $('.dialog_default_button').click();
    }
});
Robert Schmidt
źródło
0
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()

To zadziałało świetnie dla mnie.

Piotr
źródło
Dobrze byłoby dołączyć odwołanie do $ ('# DialogID'). Dialog () jako argument do zastosowania. W przeciwnym razie $ (this) .close () nie będzie miało poprawnego kontekstu wewnątrz TheButton.
Dave,
0

Żadne z tych rozwiązań nie wydawało mi się działać w IE9. Skończyło się na tym ...

$('#my-dialog').dialog({
    ...
    open: function () {
        $(this).parent()
               .find("button:eq(0)")
               .focus()
               .keyup(function (e) {
                   if (e.keyCode == $.ui.keyCode.ENTER) {
                       $(this).trigger("click");
                   };
               });
    }
});
Paul Martin
źródło
0

Poniżej body jest używane, ponieważ okno dialogowe DIV zostało dodane do ciała, więc body nasłuchuje teraz zdarzenia klawiatury. Testowano na IE8,9,10, Mojila, Chrome.

open: function() {
$('body').keypress(function (e) { 
     if (e.keyCode == 13) {   
     $(this).parent().find(".ui-dialog-buttonpane button:eq(0)").trigger("click");
     return false; 
     }
  }); 
}
LoopCoder
źródło
0

Ponieważ nie mam wystarczającej reputacji, aby publikować komentarze.

$(document).delegate('.ui-dialog', 'keyup', function(e) {
  var tagName = e.target.tagName.toLowerCase();

  tagName = (tagName === 'input' && e.target.type === 'button') ? 'button' : tagName;

  if (e.which === $.ui.keyCode.ENTER && tagName !== 'textarea' && tagName !== 'select' && tagName !== 'button') {
      $(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');
    return false;
  } else if (e.which === $.ui.keyCode.ESCAPE) {
      $(this).close();
  }
});

Zmodyfikowana odpowiedź Basemma # 35 również dodaj Escape, aby zamknąć okno dialogowe.

Liam Mitchell
źródło
-1

Działa dobrze, dziękuję !!!

open: function () { debugger; $("#dialogDiv").keypress(function (e) { if (e.keyCode == 13) { $(this).parent().find("#btnLoginSubmit").trigger("click"); } }); },

Durgaprasad Katari
źródło
hmm ... coś nowego (w porównaniu do wcześniejszych odpowiedzi) w Twoim poście?
kleopatra
-1

Nadaj swoim przyciskom klasy i wybierz je w zwykły sposób:

$('#DialogTag').dialog({
  closeOnEscape: true,
  buttons: [
    {
      text: 'Cancel',
      class: 'myCancelButton',
      click: function() {
        // Close dialog fct
      }
    },
    {
      text: 'Ok',
      class: 'myOKButton',
      click: function() {
        // OK fct
      }
    }
  ],
  open: function() {

    $(document).keyup(function(event) {

      if (event.keyCode === 13) {
        $('.myOKButton').click();
      }

    });

  }
});
yPhil
źródło