Надішліть діалог інтерфейсу jQuery на <Enter>


131

У мене є діалогове вікно інтерфейсу jQuery з формою. Я хотів би імітувати клацання однією з кнопок діалогового вікна, щоб вам не потрібно було користуватися мишкою або вкладкою. Іншими словами, я хочу, щоб це діяло як звичайне діалогове вікно графічного інтерфейсу, де імітується натискання кнопки "ОК".

Я припускаю, що це може бути простий варіант із діалоговим вікном, але я не можу його знайти в документації на jQuery UI . Я міг би зв’язати кожне введення форми за допомогою keyup (), але не знав, чи є простіший / чистіший спосіб. Дякую.


Якщо ви не хочете використовувати форму та хочете повторно використовувати код, я надав хорошу відповідь тут: stackoverflow.com/a/9628800/329367
Даррен

Відповіді:


153

Я не знаю, чи є варіант у віджеті інтерфейсу jQuery UI , але ви можете просто прив'язати keypressподію до діву, який містить діалог ...

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

Це запускається незалежно від того, який елемент має фокус у вашому діалоговому вікні, що може бути, а може і не бути хорошою справою залежно від того, що ви хочете.

Якщо ви хочете зробити цю функцію за замовчуванням, ви можете додати цей фрагмент коду:

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

Ось більш детальний вигляд того, як це виглядатиме:

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

2
Не забудьте, я знайшов це: додайте "відкрити" до діалогового вікна (як-от закрити, модально, bgiframe тощо) та підключіть там обробник клавіш.
Мілан Бабушков

5
Для Webkit (Safari / Chrome) це працює лише в тому випадку, якщо я роблю "keydown" замість "keyup". Не впевнений, що це нещодавня зміна чи важливо, що моя сторінка також має реальну форму на ній. Все-таки дякую за пораду!
Микола П’ясецький

12
Замість if (e.keyCode == 13) ви могли б зробити, якщо (e.keyCode === $ .ui.keyCode.ENTER) для збільшення читабельності.
А. Мюррей

2
Я вниз проголосував за цю відповідь. Незважаючи на те, що він короткий і акуратний, у Firefox 7.0.1 це також запустить вашу кнопку "ОК", якщо користувач вибере щось із спадного поля для автозаповнення, наприклад, раніше введену електронну адресу.
cburgmer

2
Погано зав'язувати події в "open:". Це призведе до того, що він буде відновлюватись кожного разу, коли діалогове вікно відкриється, а це означає, що якщо діалогове вікно відкриється двічі, обробник подій буде викликаний двічі.
Елезар

67

Я підсумував відповіді вище та додав важливі речі

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

Переваги:

  1. Disallow клавішу введення на несумісних елементів , таких як textarea, select, buttonабо входи з кнопкою типу, уявіть користувач , натиснувши увійти на textareaі отримати форму , подану замість отримання нового рядка!
  2. Прив’язка виконується один раз, уникайте використання діалогового "відкритого" зворотного виклику для прив'язки клавіші введення, щоб уникнути прив'язки однієї і тієї ж функції знову і знову щоразу, коли діалогове вікно відкриється
  3. Уникайте змін існуючого коду, як підказують деякі відповіді вище
  4. Використовуйте "delegate" замість застарілого "live" і уникайте використання нового методу "on", щоб дозволити роботу зі старими версіями jquery
  5. Оскільки ми використовуємо делегат, це означає, що код вище може бути записаний ще до ініціалізації діалогу. Ви також можете помістити його в тег голови навіть без$(document).ready
  6. Також делегат прив’яже лише один обробник до documentі не прив'язує обробник до кожного діалогового вікна, як у деяких кодах вище, для більшої ефективності
  7. Працює навіть з динамічно генерованими діалогами, як-от $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Працював з 7/8/9!
  9. Уникайте використання повільного селектора :first
  10. Уникайте використання хак, як у відповідях тут, щоб зробити приховану кнопку подання

Недоліки:

  1. Запустіть першу кнопку як типову, ви можете вибрати іншу кнопку з eq()або викликати функцію всередині оператора if
  2. Усі діалогові вікна матимуть однакову поведінку, ви можете відфільтрувати його, зробивши ваш вибір більш конкретним, тобто "#dialog" замість '.ui-dialog'

Я знаю, що питання давнє, але в мене була така ж потреба, тому я поділився рішенням, яким я користувався.


4
Той факт, що це не прийнята відповідь і не має більше голосів, робить мене сумним, найбільш інформативним і не додає постійно обробників. +1
Кріс О'Келлі

1
чудова відповідь: відкритий зворотний дзвінок для додавання прив’язок - те, чого ви хочете уникати
Jay Rizzi

1
для мене це працює, коли подія є натисканням клавіш, і я знімаю всі умови tagName та видаляю тригер клацання
Ісаїяван Бабу Каран

1
Я також повинен був перейти на "клавіш", щоб зробити цю роботу (протестовано на OS X 10.8.4, Chrome 29 та Firefox 23).
natebeaty

1
Оскільки це старіша відповідь, варто відзначити, що .delegate()в jQuery 3.0 застаріло, тому .on()(доступно з 1.7), мабуть, маршрут, який слід пройти в цей момент.
jinglesthula

13
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();

Це прекрасно працює з останньою версією JQuery UI (1.8.1). Ви також можете використовувати: перший замість: останній, залежно від того, яку кнопку ви хочете встановити за замовчуванням.

Це рішення, порівняно з обраним вище, має перевагу, показуючи, яка кнопка є типовою для користувача. Користувач також може клацнути TAB між кнопками, а натисканням клавіші ENTER буде натиснути кнопку, що знаходиться під фокусом.

Ура.


А що робити, якщо у діалоговому вікні є одне або більше полів для введення тексту? Я хочу, щоб ENTER надсилав діалогове вікно для входу, коли користувач знаходиться у полях імені користувача та пароля.
Девід Харкнес

1
@David, якщо ви використовуєте кнопки діалогового вікна jQuery, тоді просто захойте звичайну кнопку подання вводу у формі. напр. видимість: приховано;
Дамо

6

Грубий, але ефективний спосіб зробити цю роботу більш загальним:

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

Потім, коли ви створюєте новий діалог, ви можете зробити це:

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

І використовуйте його як звичайне діалогове вікно jquery після цього:

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

Є шляхи покращити це, щоб змусити його працювати в більш особливих випадках. З вищенаведеним кодом він автоматично вибере першу кнопку в діалоговому вікні, як кнопку, яка запускається при натисканні клавіші Enter. Також передбачається, що в будь-який момент часу існує лише один активний діалог, що може не відбутися. Але ви отримуєте ідею.

Примітка: Як було сказано вище, кнопка, яка натискається на введення, залежить від вашого налаштування. Отже, в деяких випадках ви хочете використовувати: перший селектор у .find методі, а в інших ви можете скористатися селектором: last.


Я думаю, що там має бути .first (), як у $ ('. Ui-dialog'). Find ('button'). First (). Trigger ('click'); Інакше ви натиснете всі кнопки діалогового вікна, якщо таких є більше.
JustinStolle

@thejh - Ні, він додає обробник подій клавіатури до кожного діалогового вікна, але подія отримає лише діалогове вікно, що містить елемент з фокусом при натисканні клавіші.
Девід Харкнес

6

Замість того, щоб слухати ключові коди, як у цій відповіді (на яку я не міг приступити до роботи), ви можете прив’язати до події подання форми у діалоговому вікні, а потім зробити це:

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

Отже, вся справа виглядала б так

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

Зауважте, що різні веб-переглядачі по-різному обробляють клавішу введення, а деякі не завжди виконують подачу при введенні.


Це здається найелегантнішою відповіддю.
День

Це не працює, якщо в одному діалоговому вікні є три або більше входів. Не знаю чому.
programad

6

Бен Клейтон - найновіший і найкоротший, і він може бути розміщений у верхній частині вашої індексної сторінки до того, як ініціалізуються будь-які діалоги jquery. Однак, я хотів би зазначити, що ". Live" був застарілим. Бажана дія зараз ".on". Якщо ви хочете, щоб ".on" функціонував як ".live", вам доведеться використовувати делеговані події, щоб приєднати обробник подій. Також ще кілька речей ...

  1. Я вважаю за краще використовувати метод ui.keycode.ENTER для перевірки ключа введення, оскільки вам не потрібно запам’ятовувати фактичний код ключа.

  2. Використання кнопки "$ ('. Ui-dialog-buttonpane: first", $ (this)) "для вибору клацання робить весь метод загальним.

  3. Ви хочете додати "return false;" щоб запобігти дефолту та припинити розповсюдження.

В цьому випадку...

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

4

Я не знаю про простіше, але зазвичай ви відстежуєте, яка кнопка має фокус. Якщо фокус буде змінено на інший елемент керування, то "фокусування на кнопці" залишиться на тій кнопці, у якій фокус був останнім. Зазвичай "фокусування на кнопці" розпочнеться на вашій кнопці за замовчуванням. Вкладка на іншу кнопку змінила б "фокус кнопки". Вам доведеться вирішити, чи переміщення до іншого елемента форми знову поверне "фокус кнопок" до кнопки за замовчуванням. Можливо, вам також знадобиться якийсь візуальний індикатор, окрім браузера за замовчуванням, для позначення фокусованої кнопки, оскільки вона втрачає реальний фокус у вікні.

Після того, як у вас буде вимкнена та реалізована логіка фокусування кнопок, я, ймовірно, додаю обробник ключів до самого діалогового вікна і запропонував би йому викликати дії, пов'язані з "зосередженою" на даний момент кнопкою.

EDIT : Я роблю припущення, що ви хочете мати можливість ввести вхід у будь-який час, коли ви заповнюєте елементи форми, а "поточна" дія кнопки має перевагу. Якщо ви хочете такої поведінки лише тоді, коли кнопка насправді зосереджена, моя відповідь занадто складна.


3

Я знайшов це рішення, воно працює на IE8, Chrome 23.0 та Firefox 16.0

Він заснований на коментарі Роберта Шмідта.

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

Я сподіваюся, що це допоможе комусь.


Дякую! Це врятувало мені багато часу! :)
Рахул Дезай

3

Іноді ми забуваємо основне, що браузер вже підтримує:

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

Це призведе до того, що ENTERключ надішле форму.


2

Я так зробив ...;) Сподіваюся, це комусь допоможе ..

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

2

Це має спрацювати, щоб викликати обробку клацання кнопки. Цей приклад передбачає, що ви вже налаштували форму в діалоговому вікні, щоб використовувати плагін jquery.validate. але може бути легко адаптований.

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

            }
}

1

Я усвідомлюю, що відповідей уже багато, але я вважаю, що моє рішення є найкоротшим і, можливо, найкоротшим. Він має перевагу в тому, що він працює в будь-яких діалогах, створених у будь-який час у майбутньому.

$(".ui-dialog").live("keyup", function(e) {
    if (e.keyCode === 13) {
        $('.ok-button', $(this) ).first().click();
    }
});

1
Ей, дякую за оновлення, лише невелике запитання, що тут ".ok-button"? це клас, який ви повинні застосувати за кнопкою за замовчуванням, яку ви хочете натиснути клавішею enter?
UID

Вибачте, якщо ви знайшли питання sily .. m занадто новий у JS / jQuery
UID

@BenClayton: Цю відповідь можна було б покращити, якби ви поставили її в контекст діалогу jQueryUI.
Майкл Поттер

1

Ось що я зробив:

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

У цьому випадку myForm - це об’єкт jQuery, що містить html форми (зверніть увагу, там немає жодних тегів "form" ... якщо ви помістите їх на весь екран, оновиться, якщо натиснути "Enter").

Кожного разу, коли користувач натискає "ввести" з форми, це буде еквівалентом натискання кнопки "ОК".

Це також дозволяє уникнути проблеми відкритості форми з уже виділеною кнопкою "ОК". Хоча це було б добре для форм без полів, якщо вам потрібен користувач для заповнення матеріалів, ви, ймовірно, хочете виділити перше поле.


Це найбільш логічне рішення. Ще краще, якщо ви оголосите свою кнопку ідентифікатором і перейдете в селекторі до find (), але будь-який спосіб працює. +1
Вінсент

1

зроблено і зроблено

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

0

якщо ви знаєте перемикач елементів кнопки:

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

Слід зробити трюк для вас. Це сфокусує кнопку "Гаразд", а введення "натисне" на неї, як ви і очікували. Це та сама методика, яка використовується у діалогах інтерфейсу користувача.


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

0

Я знайшов досить просте рішення цієї проблеми:

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

0
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()

Це спрацювало для мене чудово ..


Вам було б добре включити посилання на $ ('# DialogID'). Діалог () як аргумент, який потрібно застосувати. Інакше $ (this) .close () не матиме правильного контексту всередині TheButton.
Дейв

0

Жодне з цих рішень, схоже, не працювало для мене в IE9. Я закінчився цим.

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

0

Нижче корпусу використовується, тому що діалогове вікно DIV додано на корпус, тому тіло тепер слухає події на клавіатурі. Тестовано на 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; 
     }
  }); 
}

0

Тому що мені не вистачає репутації, щоб розміщувати коментарі.

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

Модифіковану відповідь Basemm №35 також додайте в Escape, щоб закрити діалогове вікно.


-1

Це добре працює Дякую !!!

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


хм ... щось нове (порівняно з попередніми відповідями) у твоєму дописі?
Клеопатра

-1

Дайте класам клавіші та виберіть їх звичайним способом:

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

    });

  }
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.