Caixa de diálogo Enviar UI do jQuery em <Enter>

131

Eu tenho uma caixa de diálogo jQuery UI com um formulário. Gostaria de simular um clique em um dos botões da caixa de diálogo para que você não precise usar o mouse ou a guia sobre ele. Em outras palavras, eu quero que ele aja como uma caixa de diálogo GUI comum, onde simule apertar o botão "OK".

Suponho que essa possa ser uma opção simples na caixa de diálogo, mas não a encontro na documentação da interface do usuário do jQuery . Eu poderia vincular cada entrada de formulário com keyup (), mas não sabia se havia uma maneira mais simples / limpa. Obrigado.

CMB
fonte
Se você deseja evitar o uso de um formulário e quer código reutilizáveis, eu tenho desde uma boa resposta aqui: stackoverflow.com/a/9628800/329367
Darren

Respostas:

153

Não sei se existe uma opção no widget da interface do usuário do jQuery , mas você pode simplesmente vincular o keypressevento à div que contém sua caixa de diálogo ...

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

Isso funcionará independentemente do elemento em foco na sua caixa de diálogo, o que pode ou não ser uma coisa boa, dependendo do que você deseja.

Se você deseja tornar isso a funcionalidade padrão, você pode adicionar este trecho de código:

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

Aqui está uma visão mais detalhada de como seria:

$( "#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
fonte
2
Deixa pra lá, eu achei: adicione "open" à caixa de diálogo (como close, modal, bgiframe etc.) e conecte o manipulador de keyup lá.
Milan Babuškov 30/08/09
5
Para o Webkit (Safari / Chrome), isso só funciona se eu fizer "keydown" em vez de "keyup". Não tenho certeza se é uma alteração recente ou se importa que minha página também tenha uma forma real. Ainda assim, obrigado pela dica!
Nicholas Piasecki
12
Em vez de if (e.keyCode == 13), você poderia fazer if (e.keyCode === $ .ui.keyCode.ENTER) para aumentar a legibilidade.
A. Murray
2
Eu votei para baixo nesta resposta. Embora seja curto e arrumado, no Firefox 7.0.1 isso também acionará o botão "OK" se o usuário selecionar algo na caixa suspensa de preenchimento automático, por exemplo, um endereço de e-mail inserido anteriormente.
cburgmer
2
É uma má ideia vincular-se a eventos em "open:". Isso fará com que ele seja religado toda vez que a caixa de diálogo for aberta, o que significa que, se a caixa de diálogo for aberta duas vezes, o manipulador de eventos será chamado duas vezes.
Elezar
67

Eu resumi as respostas acima e adicionei coisas importantes

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

Vantagens:

  1. Proibir tecla enter em elementos não compatíveis, como textarea, select, buttonou entradas com botão tipo, imagine usuário clicar entrar em textareae obter o formulário apresentado em vez de começar nova linha!
  2. A ligação é feita uma vez, evite usar o retorno de chamada 'aberto' da caixa de diálogo para ligar a tecla enter, para evitar vincular a mesma função repetidamente sempre que a caixa de diálogo for 'aberta'
  3. Evite alterar o código existente, como sugerem algumas respostas acima
  4. Use 'delegate' em vez do 'obsoleto' obsoleto e evite usar o novo método 'on' para permitir trabalhar com versões mais antigas do jquery
  5. Como usamos delegate, isso significa que o código acima pode ser escrito antes mesmo de inicializar o diálogo. você também pode colocá-lo no cabeçalho, mesmo sem$(document).ready
  6. Além disso, o delegado vinculará apenas um manipulador documente não vinculará o manipulador a cada caixa de diálogo, como em algum código acima, para maior eficiência
  7. Funciona mesmo com diálogos gerados dinamicamente, como $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Trabalhou com ie 7/8/9!
  9. Evite usar o seletor lento :first
  10. Evite usar hacks como nas respostas aqui para criar um botão de envio oculto

Desvantagens:

  1. Execute o primeiro botão como o padrão, você pode escolher outro botão com eq()ou chamar uma função dentro da instrução if
  2. Todas as caixas de diálogo terão o mesmo comportamento que você pode filtrar, tornando seu seletor mais específico, ou seja, '#dialog' em vez de '.ui-dialog'

Sei que a pergunta é antiga, mas tive a mesma necessidade, então compartilhei a solução que usei.

Basemm
fonte
4
O fato de essa não ser a resposta aceita e não ter mais votos me deixa triste, mais informativo e não adiciona manipuladores continuamente. +1
Chris O'Kelly
1
excelente resposta, tendo o retorno de chamada aberta para adicionar ligações é algo que você quer evitar
Jay Rizzi
1
para mim isso funciona quando o evento é Keydown e eu remover todas as condições de tagName e remover o clique gatilho
Isaiyavan Babu Karan
1
Eu também tive que mudar para "keydown" para fazer esse trabalho (testado no OS X 10.8.4, Chrome 29 e Firefox 23).
Netebeaty
1
Como essa é uma resposta mais antiga, vale a pena notar que ela .delegate()foi descontinuada no jQuery 3.0, portanto .on()(disponível desde 1.7) é provavelmente o caminho a seguir neste momento.
Jinglesthula
13
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();

Funciona perfeitamente com a versão mais recente da JQuery UI (1.8.1). Você também pode usar: first em vez de: last dependendo do botão que deseja definir como padrão.

Essa solução, comparada à selecionada acima, tem a vantagem de mostrar qual botão é o padrão para o usuário. O usuário também pode pressionar TAB entre os botões e pressionar ENTER para clicar no botão atualmente em foco.

Felicidades.

Mario Awad
fonte
E se a sua caixa de diálogo tiver um ou mais campos de entrada de texto? Quero que a ENTER envie a caixa de diálogo de login quando o usuário estiver nos campos de nome e senha de usuário.
David Harkness
1
@ David, se você estiver usando os botões da caixa de diálogo jQuery, oculte o botão de envio de entrada normal no formulário. por exemplo. visibilidade: oculto;
Damo
6

Uma maneira grosseira, mas eficaz, de fazer isso funcionar de maneira mais genérica:

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

Então, quando você cria uma nova caixa de diálogo, pode fazer o seguinte:

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

E use-o como um diálogo jquery normal depois:

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

Existem maneiras de melhorar isso e fazê-lo funcionar em casos mais especiais. Com o código acima, ele escolherá automaticamente o primeiro botão na caixa de diálogo como o botão a ser acionado quando pressionar Enter. Também pressupõe que existe apenas uma caixa de diálogo ativa a qualquer momento, o que pode não ser o caso. Mas você entendeu.

Nota: Como mencionado acima, o botão pressionado enter depende da sua configuração. Portanto, em alguns casos você deseja usar o seletor: first no método .find e em outros você pode usar o seletor: last.

Karim
fonte
Eu acho que deveria haver um .primeiro () lá como em $ ('. Ui-dialog'). Find ('button'). First (). Trigger ('click'); Caso contrário, você acionará o clique de todos os botões da caixa de diálogo, se houver mais de um.
JustinStolle
@thejh - Não, ele anexa um manipulador de eventos de keyup a cada caixa de diálogo, mas somente a caixa de diálogo que contém o elemento em foco quando a tecla é pressionada receberá o evento.
David Harkness
6

Em vez de escutar códigos-chave como nesta resposta (que eu não consegui trabalhar), você pode vincular ao evento de envio do formulário na caixa de diálogo e, em seguida, fazer o seguinte:

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

Então, a coisa toda ficaria assim

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

Observe que navegadores diferentes manipulam a tecla enter de maneira diferente e alguns nem sempre enviam ao entrar.

Salida Software
fonte
Esta parece ser a resposta mais elegante.
Dan
Isso não funciona quando tenho três ou mais entradas na mesma caixa de diálogo. Não sei porque.
Programad
6

O de Ben Clayton é o mais bonito e o mais curto, e pode ser colocado no topo da sua página de índice antes que qualquer caixa de diálogo jquery seja inicializada. No entanto, gostaria de salientar que ".live" foi descontinuado. A ação preferida agora é ".on". Se você deseja que ".on" funcione como ".live", será necessário usar eventos delegados para anexar o manipulador de eventos. Além disso, algumas outras coisas ...

  1. Prefiro usar o método ui.keycode.ENTER para testar a tecla enter, pois você não precisa se lembrar do código da chave real.

  2. Usar "$ ('.ii-dialog-buttonpane button: first', $ (this))" para o seletor de clique torna todo o método genérico.

  3. Você deseja adicionar "return false"; para impedir o padrão e parar a propagação.

Nesse caso...

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

Eu não sei mais simples, mas normalmente você acompanharia qual botão tem o foco atual. Se o foco for alterado para um controle diferente, o "foco do botão" permanecerá no botão que teve o foco por último. Normalmente, o "foco do botão" inicia no botão padrão. Tabular para um botão diferente alteraria o "foco do botão". Você teria que decidir se navegar para um elemento de formulário diferente redefiniria o "foco do botão" para o botão padrão novamente. Você provavelmente também precisará de algum indicador visual diferente do padrão do navegador para indicar o botão de foco, pois ele perde o foco real na janela.

Depois que a lógica de foco do botão for desativada e implementada, provavelmente adicionaria um manipulador de chaves à própria caixa de diálogo e chamaria a ação associada ao botão "focado" atualmente.

EDITAR : Estou assumindo que você deseja poder pressionar enter a qualquer momento que estiver preenchendo elementos do formulário e que a ação do botão "atual" tenha precedência. Se você deseja esse comportamento apenas quando o botão está realmente focado, minha resposta é muito complicada.

tvanfosson
fonte
3

Encontrei esta solução, funciona no IE8, Chrome 23.0 e Firefox 16.0

É baseado no comentário de 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();
});

Espero que ajude alguém.

Pablo Oña
fonte
Obrigado! Isso me salvou muito tempo! :)
Rahul Desai
3

Às vezes esquecemos o fundamental do que o navegador já suporta:

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

Isso fará com que a ENTERchave envie o formulário.

Seifu
fonte
2

Eu fiz assim ...;) Espero que seja útil para alguém ..

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

Isso deve funcionar para acionar o clique do manipulador de cliques do botão. este exemplo assume que você já configurou o formulário na caixa de diálogo para usar o plug-in jquery.validate. mas pode ser facilmente adaptado.

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

Sei que já existem muitas respostas, mas reconheço naturalmente que minha solução é a mais limpa e possivelmente a mais curta. Tem a vantagem de funcionar em qualquer caixa de diálogo criada a qualquer momento no futuro.

$(".ui-dialog").live("keyup", function(e) {
    if (e.keyCode === 13) {
        $('.ok-button', $(this) ).first().click();
    }
});
Ben Clayton
fonte
1
Ei, obrigado por atualizar, apenas uma pequena pergunta, o que é ".ok-button" aqui? é a classe que você deve aplicar no botão padrão no qual deseja clicar?
UID
Desculpe se você encontrar a pergunta sily .. m muito novo no JS / jQuery
UID
@ BenClayton: Esta resposta pode ser melhorada se você a colocar no contexto da caixa de diálogo jQueryUI.
Michael Potter
1

Aqui está o que eu fiz:

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

Nesse caso, o myForm é um objeto jQuery que contém o html do formulário (observe, não há tags "form" lá ... se você colocar as na tela inteira será atualizada quando você pressionar "enter").

Sempre que o usuário pressionar "enter" no formulário, será o equivalente a clicar no botão "ok".

Isso também evita que o formulário seja aberto com o botão "ok" já destacado. Embora isso seja bom para formulários sem campos, se você precisar que o usuário preencha itens, provavelmente desejará que o primeiro campo seja destacado.

Tyler
fonte
Essa é a solução mais lógica. Ainda melhor se você declarar seu botão com um ID e passar o seletor para o find (), mas de qualquer maneira funcionará. 1
Vincent
1

feito e feito

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

se você conhece o seletor de elemento de botão:

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

Deve fazer o truque para você. Isso focalizará o botão ok, e digite 'clique' nele, como seria de esperar. Essa é a mesma técnica usada nas caixas de diálogo nativas da interface do usuário.

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

Encontrei uma solução bastante simples para esse problema:

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

Isso funcionou muito bem para mim ..

Peter
fonte
Você faria bem em incluir uma referência a $ ('# DialogID'). Dialog () como argumento a ser aplicado. Caso contrário, $ (this) .close () não terá o contexto correto dentro do TheButton.
Dave
0

Nenhuma dessas soluções parecia funcionar para mim no IE9. Eu acabei com isso ..

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

Abaixo do corpo é usado porque a caixa de diálogo DIV foi adicionada ao corpo, então o corpo agora ouve o evento do teclado. Ele testou no 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
fonte
0

Porque não tenho reputação suficiente para postar comentários.

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

Resposta modificada por Basemm # 35 também adicione Escape para fechar a caixa de diálogo.

Liam Mitchell
fonte
-1

Funciona bem Obrigado !!!

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

Durgaprasad Katari
fonte
hmm ... algo novo (em comparação com as respostas anteriores) no seu post?
21813 kleopatra
-1

aulas aos seus botões e selecione-as da maneira usual:

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