Kirim dialog UI jQuery di <Enter>

131

Saya memiliki kotak dialog UI jQuery dengan formulir. Saya ingin mensimulasikan klik pada salah satu tombol dialog sehingga Anda tidak perlu menggunakan mouse atau tab untuk itu. Dengan kata lain, saya ingin itu berfungsi seperti kotak dialog GUI biasa di mana mensimulasikan menekan tombol "OK".

Saya menganggap ini mungkin opsi sederhana dengan dialog, tetapi saya tidak dapat menemukannya di dokumentasi jQuery UI . Saya bisa mengikat setiap input formulir dengan keyup () tetapi tidak tahu apakah ada cara yang lebih sederhana / bersih. Terima kasih.

CMB
sumber
Jika Anda ingin menghindari menggunakan formulir dan menginginkan kode yang dapat digunakan kembali, saya telah memberikan jawaban yang baik di sini: stackoverflow.com/a/9628800/329367
Darren

Jawaban:

153

Saya tidak tahu apakah ada opsi di widget jQuery UI , tetapi Anda bisa mengikat keypressacara ke div yang berisi dialog Anda ...

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

Ini akan berjalan tidak peduli elemen apa yang memiliki fokus dalam dialog Anda, yang mungkin atau mungkin bukan hal yang baik tergantung pada apa yang Anda inginkan.

Jika Anda ingin menjadikan ini fungsionalitas default, Anda dapat menambahkan potongan kode ini:

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

Berikut tampilan yang lebih terperinci tentang tampilannya:

$( "#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
sumber
2
Nevermind, saya menemukannya: tambahkan "buka" ke dialog (seperti tutup, modal, bgiframe, dll.) Dan kaitkan pengendali keyup di sana.
Milan Babuškov
5
Untuk Webkit (Safari / Chrome), ini hanya berfungsi jika saya melakukan "keydown" daripada "keyup". Tidak yakin apakah ini perubahan terbaru atau apakah itu penting bahwa halaman saya juga memiliki bentuk nyata di atasnya. Tetap saja, terima kasih atas tipnya!
Nicholas Piasecki
12
Alih-alih jika (e.keyCode == 13) Anda dapat melakukannya jika (e.keyCode === $ .ui.keyCode.ENTER) untuk meningkatkan keterbacaan.
A. Murray
2
Saya memilih jawaban ini. Meskipun pendek dan rapi, di Firefox 7.0.1 ini juga akan memicu tombol "OK" Anda jika pengguna memilih sesuatu dari kotak tarik-turun autocomplete, misalnya alamat email yang dimasukkan sebelumnya.
cburgmer
2
Gagasan buruk untuk mengikat acara di "buka:". Ini akan menyebabkannya mengulang setiap kali dialog dibuka, yang berarti jika dialog dibuka dua kali, event handler akan dipanggil dua kali.
Elezar
67

Saya telah merangkum jawaban di atas & menambahkan hal-hal penting

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

Keuntungan:

  1. Larang memasukkan kunci pada elemen non kompatibel seperti textarea, select, buttonatau input dengan tombol jenis, bayangkan mengklik pengguna masuk pada textareadan mendapatkan formulir yang diajukan bukannya baris baru!
  2. Ikatan dilakukan sekali, hindari menggunakan dialog 'buka' callback untuk mengikat tombol enter untuk menghindari mengikat fungsi yang sama lagi dan lagi setiap kali dialog 'terbuka'
  3. Hindari mengubah kode yang ada seperti yang disarankan beberapa jawaban di atas
  4. Gunakan 'delegasi' alih-alih 'live' yang sudah usang & hindari menggunakan metode 'on' baru untuk memungkinkan bekerja dengan versi jquery yang lebih lama
  5. Karena kami menggunakan delegate, itu berarti kode di atas dapat ditulis bahkan sebelum memulai dialog. Anda juga dapat meletakkannya di tag kepala bahkan tanpa$(document).ready
  6. Juga mendelegasikan akan mengikat hanya satu penangan ke documentdan tidak akan mengikat penangan ke setiap dialog seperti dalam beberapa kode di atas, untuk efisiensi lebih
  7. Bekerja bahkan dengan dialog yang dihasilkan secara dinamis seperti $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Bekerja dengan ie 7/8/9!
  9. Hindari menggunakan pemilih lambat :first
  10. Hindari menggunakan peretasan seperti pada jawaban di sini untuk membuat tombol kirim tersembunyi

Kekurangan:

  1. Jalankan tombol pertama sebagai yang default, Anda dapat memilih tombol lain dengan eq()atau memanggil fungsi di dalam pernyataan if
  2. Semua dialog akan memiliki perilaku yang sama Anda dapat memfilternya dengan membuat pemilih Anda lebih spesifik yaitu '# dialog' bukan '.ui-dialog'

Saya tahu pertanyaannya sudah lama tetapi saya memiliki kebutuhan yang sama, jadi, saya membagikan solusi yang saya gunakan.

Basemm
sumber
4
Fakta bahwa ini bukan jawaban yang diterima dan tidak memiliki lebih banyak suara membuat saya sedih, paling informatif dan tidak terus menambahkan penangan. +1
Chris O'Kelly
1
jawaban yang sangat baik, memiliki panggilan balik terbuka untuk menambahkan binding adalah sesuatu yang ingin Anda hindari
Jay Rizzi
1
bagi saya ini bekerja ketika acara adalah keydown dan saya menghapus semua kondisi tagName dan menghapus pemicu klik
Isaiyavan Babu Karan
1
Saya juga harus mengubah ke "keydown" untuk membuatnya bekerja (diuji pada OS X 10.8.4, Chrome 29 dan Firefox 23).
natebeaty
1
Karena ini adalah jawaban yang lebih lama, perlu dicatat bahwa .delegate()sudah tidak digunakan lagi di jQuery 3.0, jadi .on()(tersedia sejak 1.7) mungkin merupakan rute untuk pergi pada titik ini.
jinglesthula
13
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();

Ini berfungsi dengan baik dengan versi terbaru JQuery UI (1.8.1). Anda juga dapat menggunakan: pertama alih-alih: terakhir tergantung pada tombol mana yang ingin Anda tetapkan sebagai default.

Solusi ini, dibandingkan dengan yang dipilih di atas, memiliki keuntungan menunjukkan tombol mana yang merupakan default untuk pengguna. Pengguna juga dapat TAB antara tombol dan menekan ENTER akan mengklik tombol yang saat ini dalam fokus.

Bersulang.

Mario Awad
sumber
Dan bagaimana jika dialog Anda memiliki satu atau beberapa bidang entri teks? Saya ingin ENTER mengirimkan dialog login ketika pengguna berada di bidang nama pengguna dan kata sandi.
David Harkness
1
@ Hapus jika Anda menggunakan tombol Dialog jQuery, maka sembunyikan saja tombol kirim masukan normal pada formulir. misalnya. visibilitas: tersembunyi;
Damo
6

Cara kasar tetapi efektif untuk membuat ini bekerja lebih umum:

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

Kemudian ketika Anda membuat dialog baru Anda bisa melakukan ini:

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

Dan gunakan seperti dialog jquery normal setelahnya:

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

Ada cara untuk meningkatkannya agar berfungsi dalam kasus yang lebih khusus. Dengan kode di atas, ia akan secara otomatis memilih tombol pertama dalam dialog sebagai tombol untuk memicu ketika masuk ditekan. Juga diasumsikan bahwa hanya ada satu dialog aktif pada waktu tertentu yang mungkin tidak terjadi. Tetapi Anda mendapatkan idenya.

Catatan: Seperti disebutkan di atas, tombol yang ditekan saat masuk tergantung pada pengaturan Anda. Jadi, dalam beberapa kasus Anda ingin menggunakan: pemilih pertama dalam metode .find dan dalam kasus lain Anda mungkin ingin menggunakan: pemilih terakhir.

Karim
sumber
Saya pikir harus ada .first () di sana seperti dalam $ ('. Ui-dialog'). Find ('tombol'). First (). Trigger ('click'); Kalau tidak, Anda akan memicu klik semua tombol dialog jika ada lebih dari satu.
JustinStolle
@ thejh - Tidak, itu melampirkan pengendali event keyup untuk setiap dialog, tetapi hanya dialog yang berisi elemen dengan fokus ketika tombol ditekan akan menerima acara.
David Harkness
6

Daripada mendengarkan kode-kode kunci seperti dalam jawaban ini (yang saya tidak bisa mulai bekerja) Anda dapat mengikat untuk mengirimkan acara formulir dalam dialog dan kemudian lakukan ini:

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

Jadi, semuanya akan terlihat seperti ini

$("#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');
    }
  }
});

Perhatikan bahwa browser yang berbeda menangani tombol enter secara berbeda, dan beberapa tidak selalu melakukan pengiriman saat masuk.

Perangkat Lunak Salida
sumber
Ini sepertinya jawaban yang paling elegan.
Dan
Ini tidak berfungsi ketika saya memiliki tiga input atau lebih pada dialog yang sama. Tidak tahu kenapa
programad
6

Ben Clayton adalah yang paling rapi dan terpendek dan dapat ditempatkan di bagian atas halaman indeks Anda sebelum dialog jquery dimulai. Namun, saya ingin menunjukkan bahwa ".Live" telah usang. Tindakan yang disukai sekarang ".on". Jika Anda ingin ".on" berfungsi seperti ".live", Anda harus menggunakan acara yang didelegasikan untuk melampirkan pengendali acara. Juga, beberapa hal lain ...

  1. Saya lebih suka menggunakan metode ui.keycode.ENTER untuk menguji kunci enter karena Anda tidak harus mengingat kode kunci yang sebenarnya.

  2. Menggunakan "$ ('. Ui-dialog-buttonpane tombol: first', $ (this))" untuk pemilih klik membuat keseluruhan metode menjadi generik.

  3. Anda ingin menambahkan "return false;" untuk mencegah default dan menghentikan propagasi.

Pada kasus ini...

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

Saya tidak tahu tentang yang lebih sederhana, tetapi biasanya Anda akan melacak tombol mana yang memiliki fokus saat ini. Jika fokus diubah ke kontrol yang berbeda, maka "tombol fokus" akan tetap pada tombol yang terakhir fokus. Biasanya, "tombol fokus" akan mulai pada tombol default Anda. Menabrak tombol yang berbeda akan mengubah "fokus tombol". Anda harus memutuskan apakah menavigasi ke elemen formulir yang berbeda akan mengatur ulang "fokus tombol" ke tombol default lagi. Anda juga mungkin memerlukan beberapa indikator visual selain peramban bawaan untuk menunjukkan tombol fokus karena kehilangan fokus nyata di jendela.

Setelah Anda memiliki logika tombol fokus dan diimplementasikan, maka saya mungkin akan menambahkan penangan kunci untuk dialog itu sendiri dan meminta tindakan yang terkait dengan tombol "fokus" saat ini.

EDIT : Saya membuat asumsi bahwa Anda ingin dapat menekan enter kapan saja Anda mengisi elemen formulir dan memiliki tindakan tombol "saat ini" diutamakan. Jika Anda hanya menginginkan perilaku ini ketika tombol benar-benar fokus, jawaban saya terlalu rumit.

tvanfosson
sumber
3

Saya menemukan solusi ini, ini berfungsi pada IE8, Chrome 23.0 dan Firefox 16.0

Ini berdasarkan komentar Robert Schmidt.

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

Saya harap ini membantu siapa pun.

Pablo Oña
sumber
Terima kasih! Itu menyelamatkan saya banyak waktu! :)
Rahul Desai
3

Terkadang kita lupa dasar dari apa yang sudah didukung browser:

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

Ini akan menyebabkan ENTERkunci untuk mengirimkan formulir.

Seifu
sumber
2

Saya melakukan cara seperti itu ...;) Semoga ini bisa membantu seseorang ..

$(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
sumber
2

Ini seharusnya berfungsi untuk memicu klik pada handler klik tombol. contoh ini mengasumsikan Anda telah menyiapkan formulir dalam dialog untuk menggunakan plugin jquery.validate. tetapi bisa dengan mudah diadaptasi.

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...

            }
}
timbrown
sumber
1

Saya menyadari sudah ada banyak jawaban, tetapi saya rasa secara alami bahwa solusi saya adalah yang paling rapi, dan mungkin yang terpendek. Ini memiliki keuntungan bahwa ia bekerja pada dialog apa pun yang dibuat kapan saja di masa depan.

$(".ui-dialog").live("keyup", function(e) {
    if (e.keyCode === 13) {
        $('.ok-button', $(this) ).first().click();
    }
});
Ben Clayton
sumber
1
Hai terima kasih telah memperbarui, hanya pertanyaan kecil, apa itu ".ok-tombol" di sini? apakah ini kelas yang harus Anda terapkan pada tombol default yang ingin Anda klik dengan enter?
UID
Maaf jika Anda menemukan pertanyaan sily .. m terlalu baru di JS / jQuery
UID
@ BenClayton: Jawaban ini dapat ditingkatkan jika Anda meletakkannya dalam konteks Dialog jQueryUI.
Michael Potter
1

Inilah yang saya lakukan:

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

Dalam hal ini, myForm adalah objek jQuery yang berisi html formulir (perhatikan, tidak ada tag "formulir" di sana ... jika Anda meletakkannya di seluruh layar akan menyegarkan saat Anda menekan "enter").

Setiap kali pengguna menekan "masuk" dari dalam formulir itu akan sama dengan mengklik tombol "ok".

Ini juga menghindari masalah memiliki formulir terbuka dengan tombol "ok" sudah disorot. Meskipun itu bagus untuk formulir tanpa bidang, jika Anda membutuhkan pengguna untuk mengisi barang, maka Anda mungkin ingin bidang pertama disorot.

Tyler
sumber
Ini adalah solusi paling logis. Bahkan lebih baik jika Anda mendeklarasikan tombol Anda dengan id dan meneruskan pemilih ke find () tetapi cara baik berfungsi. +1
Vincent
1

dilakukan dan dilakukan

  $('#login input').keyup(function(e) {
      if (e.keyCode == 13) {
          $('#login form').submit();
      }
   }
kevin
sumber
0

jika Anda tahu pemilih elemen tombol:

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

Sebaiknya lakukan trik untuk Anda. Ini akan memfokuskan tombol ok, dan masuk akan 'mengklik' itu, seperti yang Anda harapkan. Ini adalah teknik yang sama yang digunakan dalam dialog UI asli.

sandesh247
sumber
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
sumber
0

Saya menemukan solusi yang cukup sederhana untuk masalah ini:

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
sumber
0
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()

Ini bekerja sangat baik untuk saya ..

Peter
sumber
Anda sebaiknya memasukkan referensi ke dialog $ ('# DialogID'). () Sebagai argumen untuk diterapkan. Kalau tidak, $ (this) .close () tidak akan memiliki konteks yang benar di dalam TheButton.
Dave
0

Tidak satu pun dari solusi ini yang bekerja untuk saya di IE9. Saya berakhir dengan ini ..

$('#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
sumber
0

Di bawah tubuh digunakan karena dialog DIV ditambahkan pada tubuh, jadi tubuh sekarang mendengarkan acara keyboard. Ini diuji pada 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
sumber
0

Karena saya tidak punya cukup reputasi untuk mengirim komentar.

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

Jawaban yang dimodifikasi oleh Basemm # 35 juga ditambahkan di Escape untuk menutup dialog.

Liam Mitchell
sumber
-1

Ini bekerja dengan baik Terima kasih !!!

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

Durgaprasad Katari
sumber
hmm ... ada yang baru (dibandingkan dengan jawaban sebelumnya) di pos Anda?
kleopatra
-1

Berikan kelas tombol Anda dan pilih dengan cara biasa:

$('#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
sumber