Отправить диалоговое окно jQuery UI на <Enter>

131

У меня есть диалоговое окно пользовательского интерфейса jQuery с формой. Я хотел бы смоделировать щелчок по одной из кнопок диалогового окна, чтобы вам не приходилось использовать мышь или вкладку для нее. Другими словами, я хочу, чтобы оно действовало как обычное диалоговое окно графического интерфейса пользователя, имитирующее нажатие кнопки «ОК».

Я предполагаю, что это может быть простой вариант с диалоговым окном, но я не могу найти его в документации jQuery UI . Я мог связать каждый ввод формы с помощью keyup (), но не знал, есть ли более простой / чистый способ. Спасибо.

CMB
источник
Если вы не хотите использовать форму и хотите использовать повторно используемый код, я дал здесь хороший ответ: stackoverflow.com/a/9628800/329367
Даррен,

Ответы:

153

Я не знаю, есть ли опция в виджете jQuery UI , но вы можете просто привязать keypressсобытие к div, который содержит ваш диалог ...

$('#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
Неважно, я нашел это: добавьте "open" в диалог (например, close, modal, bgiframe и т. Д.) И подключите туда обработчик keyup.
Милан Бабушков,
5
Для Webkit (Safari / Chrome) это работает, только если я нажимаю "keydown" вместо "keyup". Не уверен, что это недавнее изменение или важно, чтобы на моей странице также была настоящая форма. Тем не менее, спасибо за подсказку!
Николас Пясецкий
12
Вместо if (e.keyCode == 13) вы можете использовать if (e.keyCode === $ .ui.keyCode.ENTER) для повышения читабельности.
А. Мюррей,
2
Я проголосовал за этот ответ. Хотя это коротко и аккуратно, в Firefox 7.0.1 это также вызовет вашу кнопку «ОК», если пользователь выберет что-то из раскрывающегося списка автозаполнения, например, ранее введенный адрес электронной почты.
cburgmer
2
Привязка к событиям в "open:" - плохая идея. Это приведет к его повторной привязке каждый раз при открытии диалогового окна, что означает, что если диалоговое окно открывается дважды, обработчик событий будет вызываться дважды.
Elezar
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. Привязка выполняется один раз, избегайте использования обратного вызова диалога 'open' для привязки клавиши ввода, чтобы избежать привязки одной и той же функции снова и снова каждый раз, когда диалоговое окно 'открыто'
  3. Избегайте изменения существующего кода, как предлагают некоторые ответы выше
  4. Используйте 'делегат' вместо устаревшего 'live' и избегайте использования нового метода 'on', чтобы разрешить работу со старыми версиями jquery
  5. Поскольку мы используем делегат, это означает, что приведенный выше код может быть написан даже до инициализации диалога. вы также можете поместить его в тег заголовка даже без$(document).ready
  6. Также делегат будет связывать только один обработчик documentи не будет связывать обработчик с каждым диалогом, как в некотором коде выше, для большей эффективности.
  7. Работает даже с динамически генерируемыми диалогами, такими как $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Работал с IE 7/8/9!
  9. Избегайте использования медленного селектора :first
  10. Избегайте использования хаков, как в ответах здесь, чтобы сделать скрытую кнопку отправки

Недостатки:

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

Я знаю, что вопрос старый, но у меня была такая же потребность, поэтому я поделился решением, которое использовал.

Basemm
источник
4
Тот факт, что это не принятый ответ и не набрал больше голосов, меня огорчает, он очень информативен и не добавляет постоянно обработчиков. +1
Крис О'Келли
1
отличный ответ, наличие открытого обратного вызова для добавления привязок - это то, чего вы хотите избежать,
Джей Рицци,
1
для меня это работает, когда событие находится в нажатом состоянии, и я удаляю все условия tagName и удаляю триггер клика
Исайяван Бабу Каран
1
Мне также пришлось переключиться на «keydown», чтобы заставить эту работу работать (проверено на 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). Вы также можете использовать: first вместо: last в зависимости от того, какую кнопку вы хотите установить по умолчанию.

Это решение, по сравнению с выбранным выше, имеет то преимущество, что показывает, какая кнопка является кнопкой по умолчанию для пользователя. Пользователь также может переключаться между кнопками TAB, а нажатие ENTER щелкает по кнопке, которая в данный момент находится в фокусе.

Приветствия.

Марио Авад
источник
А что, если в вашем диалоге есть одно или несколько полей для ввода текста? Я хочу, чтобы ENTER отправляла диалоговое окно входа в систему, когда пользователь находится в полях имени пользователя и пароля.
Дэвид Харкнесс
1
@David, если вы используете кнопки диалогового окна jQuery, просто скройте обычную кнопку отправки ввода в форме. например. видимость: скрытая;
Damo
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')

Есть способы улучшить это, чтобы заставить его работать в более особых случаях. С помощью приведенного выше кода он автоматически выберет первую кнопку в диалоговом окне в качестве кнопки, запускаемой при нажатии клавиши ввода. Также предполагается, что в любой момент времени существует только один активный диалог, что может быть не так. Но Вы получаете идею.

Примечание. Как упоминалось выше, кнопка, которая нажимается при вводе, зависит от ваших настроек. Итак, в некоторых случаях вы захотите использовать селектор: first в методе .find, а в других вы можете захотеть использовать селектор: last.

Karim
источник
Я думаю, что там должен быть .first (), как в $ ('. Ui-dialog'). Find ('button'). First (). Trigger ('click'); В противном случае вы вызовете щелчок всех кнопок диалогового окна, если их больше одной.
JustinStolle
@thejh - Нет, он прикрепляет обработчик события keyup к каждому диалогу, но только диалог, который содержит элемент с фокусом при нажатии клавиши, получит событие.
Дэвид Харкнесс
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');
    }
  }
});

Обратите внимание, что разные браузеры обрабатывают ключ ввода по-разному, а некоторые не всегда отправляют при входе.

Программное обеспечение Salida
источник
Это кажется наиболее элегантным ответом.
Дэн
Это не работает, если в одном диалоговом окне есть три или более ввода. Не знаю почему.
программа
6

Ben Clayton's - самый изящный и самый короткий, и его можно разместить вверху вашей индексной страницы до того, как будут инициализированы какие-либо диалоги jquery. Однако я хотел бы отметить, что ".live" устарел. Теперь предпочтительное действие - ".on". Если вы хотите, чтобы .on функционировал как .live, вам нужно будет использовать делегированные события для присоединения обработчика событий. И еще кое-что ...

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

  2. Использование "$ ('. Ui-dialog-buttonpane button: 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

Не знаю, как проще, но обычно вы отслеживаете, какая кнопка имеет текущий фокус. Если фокус изменен на другой элемент управления, то «фокус кнопки» останется на кнопке, которая имела фокус последней. Обычно «фокус кнопки» начинается с кнопки по умолчанию. Переход к другой кнопке изменит «фокус кнопки». Вам нужно будет решить, приведет ли переход к другому элементу формы к сбросу «фокуса кнопки» снова на кнопку по умолчанию. Вам также, вероятно, понадобится какой-то визуальный индикатор, отличный от стандартного в браузере, чтобы указать кнопку с фокусом, поскольку она теряет реальный фокус в окне.

После того, как вы определили и реализовали логику фокуса кнопки, я бы, вероятно, добавил ключевой обработчик к самому диалогу и заставил бы его вызывать действие, связанное с текущей «сфокусированной» кнопкой.

РЕДАКТИРОВАТЬ : Я предполагаю, что вы хотите иметь возможность нажимать Enter в любое время, когда вы заполняете элементы формы, и чтобы «текущее» действие кнопки имело приоритет. Если вам нужно только такое поведение, когда кнопка фактически сфокусирована, мой ответ слишком сложен.

tvanfosson
источник
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ключ отправит форму.

Seifu
источник
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...

            }
}
timbrown
источник
1

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

$(".ui-dialog").live("keyup", function(e) {
    if (e.keyCode === 13) {
        $('.ok-button', $(this) ).first().click();
    }
});
Бен Клейтон
источник
1
Привет, спасибо за обновление, небольшой вопрос, что здесь ".ok-button"? это класс, который вы должны применить к кнопке по умолчанию, которую вы хотите нажать с вводом?
UID
Извините, если вы нашли вопрос sily .. м. Слишком ново в JS / jQuery
UID
@BenClayton: Этот ответ можно было бы улучшить, если бы вы поместили его в контекст jQueryUI Dialog.
Майкл Поттер,
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 формы (обратите внимание, там нет никаких тегов «формы» ... если вы поместите их на весь экран, они обновятся, когда вы нажмете «ввод»).

Всякий раз, когда пользователь нажимает «ввод» в форме, это будет эквивалентно нажатию кнопки «ОК».

Это также позволяет избежать проблемы с открытием формы с уже выделенной кнопкой «ОК». Хотя это было бы хорошо для форм без полей, если вам нужно, чтобы пользователь заполнял данные, вы, вероятно, хотите, чтобы первое поле было выделено.

Тайлер
источник
Это наиболее логичное решение. Еще лучше, если вы объявите свою кнопку с идентификатором и передадите селектор в find (), но в любом случае работает. +1
Винсент
1

сделано и сделано

  $('#login input').keyup(function(e) {
      if (e.keyCode == 13) {
          $('#login form').submit();
      }
   }
Кевин
источник
0

если вы знаете селектор элемента кнопки:

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

Должен сделать трюк для вас. Это сфокусирует кнопку ОК, и Enter «щелкнет» по ней, как и следовало ожидать. Это тот же метод, который используется в диалогах собственного пользовательского интерфейса.

sandesh247
источник
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
источник
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'). Dialog () в качестве аргумента для применения. В противном случае $ (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; 
     }
  }); 
}
LoopCoder
источник
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"); } }); },

Дургапрасад Катари
источник
хм ... что-нибудь новенькое (по сравнению с предыдущими ответами) в вашем посте?
kleopatra
-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();
      }

    });

  }
});
yPhil
источник