Gửi hộp thoại UI UI trên <Enter>


131

Tôi có một hộp thoại jQuery UI với một hình thức. Tôi muốn mô phỏng một lần nhấp vào một trong các nút của hộp thoại để bạn không phải sử dụng chuột hoặc tab trên nó. Nói cách khác, tôi muốn nó hoạt động như một hộp thoại GUI thông thường trong đó mô phỏng nhấn nút "OK".

Tôi cho rằng đây có thể là một tùy chọn đơn giản với hộp thoại, nhưng tôi không thể tìm thấy nó trong tài liệu UI UI . Tôi có thể liên kết từng kiểu nhập với keyup () nhưng không biết có cách nào đơn giản / gọn gàng hơn không. Cảm ơn.


Nếu bạn muốn tránh sử dụng một biểu mẫu và muốn mã có thể sử dụng lại, tôi đã cung cấp một câu trả lời tốt ở đây: stackoverflow.com/a/9628800/329367
Darren

Câu trả lời:


153

Tôi không biết nếu có một tùy chọn trong tiện ích UI UI , nhưng bạn có thể chỉ cần liên kết keypresssự kiện với div có chứa hộp thoại của bạn ...

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

Điều này sẽ chạy bất kể yếu tố nào có trọng tâm trong hộp thoại của bạn, điều này có thể hoặc không thể là một điều tốt tùy thuộc vào những gì bạn muốn.

Nếu bạn muốn làm cho chức năng này mặc định, bạn có thể thêm đoạn mã này:

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

Đây là một cái nhìn chi tiết hơn về những gì nó sẽ trông như thế nà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");
      }
    });
  };
});

2
Không bao giờ, tôi đã tìm thấy nó: thêm "mở" vào hộp thoại (như đóng, modal, bgiframe, v.v.) và móc trình xử lý keyup ở đó.
Milan Babuškov

5
Đối với Webkit (Safari / Chrome), điều này chỉ hoạt động nếu tôi thực hiện "keydown" thay vì "keyup". Không chắc chắn nếu đây là một thay đổi gần đây hoặc nếu vấn đề là trang của tôi cũng có một hình thức thực sự trên đó. Tuy nhiên, cảm ơn vì tiền boa!
Nicholas Piasecki

12
Thay vì if (e.keyCode == 13) bạn có thể làm if (e.keyCode === $ .ui.keyCode.ENTER) để tăng khả năng đọc.
A. Murray

2
Tôi đã bỏ phiếu cho câu trả lời này. Mặc dù ngắn và gọn gàng, nhưng trong Firefox 7.0.1, điều này cũng sẽ kích hoạt nút "OK" của bạn nếu người dùng chọn thứ gì đó từ hộp thả xuống tự động hoàn thành, ví dụ như địa chỉ email đã nhập trước đó.
cburgmer

2
Đó là một ý tưởng tồi để liên kết với các sự kiện trong "mở:". Điều này sẽ khiến nó khởi động lại mỗi khi hộp thoại được mở, có nghĩa là nếu hộp thoại được mở hai lần, trình xử lý sự kiện sẽ được gọi hai lần.
Elezar

67

Tôi đã tóm tắt các câu trả lời ở trên và thêm những thứ quan trọng

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

Ưu điểm:

  1. Disallow nhập key trên các yếu tố không tương thích như textarea, select, buttonhoặc đầu vào với nút loại, hãy tưởng tượng người dùng nhấp vào trên textareavà lấy mẫu gửi thay vì nhận được dòng mới!
  2. Liên kết được thực hiện một lần, tránh sử dụng hộp thoại gọi lại 'mở' để liên kết phím enter để tránh liên kết cùng chức năng lặp đi lặp lại mỗi lần hộp thoại được 'mở'
  3. Tránh thay đổi mã hiện có như một số câu trả lời ở trên gợi ý
  4. Sử dụng 'đại biểu' thay vì 'sống' không dùng nữa & tránh sử dụng phương thức 'bật' mới để cho phép làm việc với các phiên bản cũ của jquery
  5. Bởi vì chúng tôi sử dụng ủy nhiệm, điều đó có nghĩa là mã ở trên có thể được viết ngay cả trước khi khởi tạo hộp thoại. bạn cũng có thể đặt nó trong thẻ head ngay cả khi không có$(document).ready
  6. Ngoài ra, đại biểu sẽ chỉ liên kết một trình xử lý documentvà sẽ không liên kết trình xử lý với mỗi hộp thoại như trong một số mã ở trên, để hiệu quả hơn
  7. Hoạt động ngay cả với các hộp thoại được tạo động như $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Làm việc với tức là 7/8/9!
  9. Tránh sử dụng bộ chọn chậm :first
  10. Tránh sử dụng hack như trong câu trả lời ở đây để tạo nút gửi ẩn

Nhược điểm:

  1. Chạy nút đầu tiên làm nút mặc định, bạn có thể chọn nút khác với eq() hoặc gọi một hàm bên trong câu lệnh if
  2. Tất cả các hộp thoại sẽ có cùng một hành vi mà bạn có thể lọc nó bằng cách làm cho bộ chọn của bạn cụ thể hơn, ví dụ '#dialog' thay vì '.ui-dialog'

Tôi biết câu hỏi đã cũ nhưng tôi có cùng nhu cầu, vì vậy, tôi đã chia sẻ giải pháp tôi đã sử dụng.


4
Việc đây không phải là câu trả lời được chấp nhận và không có nhiều phiếu bầu khiến tôi buồn, nhiều thông tin nhất và không liên tục thêm người xử lý. +1
Chris O'Kelly

1
câu trả lời tuyệt vời, có cuộc gọi lại mở để thêm các ràng buộc là điều bạn muốn tránh
Jay Rizzi

1
đối với tôi, điều này hoạt động khi sự kiện là khóa và tôi xóa tất cả các điều kiện của tagName và xóa trình kích hoạt nhấp chuột
Isaiyavan Babu Karan

1
Tôi cũng đã phải thay đổi thành "keydown" để thực hiện công việc này (đã thử nghiệm trên OS X 10.8.4, Chrome 29 và Firefox 23).
natebeaty

1
Vì đây là một câu trả lời cũ hơn, đáng chú ý là .delegate()đã bị phản đối trong jQuery 3.0, do đó .on()(có sẵn từ 1.7) có lẽ là con đường để đi vào thời điểm này.
jinglểula

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

Nó hoạt động rất đẹp với phiên bản JQuery UI mới nhất (1.8.1). Bạn cũng có thể sử dụng: đầu tiên thay vì: cuối cùng tùy thuộc vào nút nào bạn muốn đặt làm mặc định.

Giải pháp này, so với giải pháp được chọn ở trên, có ưu điểm là hiển thị nút nào là nút mặc định cho người dùng. Người dùng cũng có thể TAB giữa các nút và nhấn ENTER sẽ nhấp vào nút hiện đang được lấy nét.

Chúc mừng.


Và nếu hộp thoại của bạn có một hoặc nhiều trường nhập văn bản thì sao? Tôi muốn ENTER gửi hộp thoại đăng nhập khi người dùng ở trong trường tên người dùng và mật khẩu.
David Harkness

1
@David nếu bạn đang sử dụng các nút Hộp thoại jQuery, thì chỉ cần ẩn nút gửi đầu vào bình thường trên biểu mẫu. ví dụ. tầm nhìn: ẩn;
Damo

6

Một cách thô sơ nhưng hiệu quả để làm cho công việc này rộng rãi hơn:

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

Sau đó, khi bạn tạo một hộp thoại mới, bạn có thể làm điều này:

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

Và sử dụng nó như một hộp thoại jquery bình thường sau đó:

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

Có nhiều cách để cải thiện điều đó để làm cho nó hoạt động trong những trường hợp đặc biệt hơn. Với đoạn mã trên, nó sẽ tự động chọn nút đầu tiên trong hộp thoại làm nút để kích hoạt khi nhấn enter. Ngoài ra, nó giả định rằng chỉ có một hộp thoại hoạt động tại bất kỳ thời điểm nào có thể không phải là trường hợp. Nhưng bạn hiểu ý rồi đấy.

Lưu ý: Như đã đề cập ở trên, nút được nhấn khi nhập phụ thuộc vào thiết lập của bạn. Vì vậy, trong một số trường hợp, bạn sẽ muốn sử dụng: bộ chọn đầu tiên trong phương thức .find và trong các trường hợp khác, bạn có thể muốn sử dụng bộ chọn: cuối cùng.


Tôi nghĩ nên có một .first () trong đó như trong $ ('. Ui-đàm thoại'). Find ('button'). First (). Trigger ('click'); Nếu không, bạn sẽ kích hoạt nhấp vào tất cả các nút của hộp thoại nếu có nhiều hơn một nút.
JustinStolle

@thejh - Không, nó gắn trình xử lý sự kiện keyup vào mọi hộp thoại, nhưng chỉ hộp thoại chứa phần tử có tiêu điểm khi nhấn phím sẽ nhận được sự kiện.
David Harkness

6

Thay vì nghe các mã khóa như trong câu trả lời này (mà tôi không thể làm việc), bạn có thể liên kết với sự kiện gửi biểu mẫu trong hộp thoại và sau đó thực hiện việc này:

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

Vì vậy, toàn bộ điều này sẽ trông như thế này

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

Lưu ý rằng các trình duyệt khác nhau xử lý khóa enter khác nhau và một số không phải lúc nào cũng thực hiện gửi khi nhập.


Đây dường như là câu trả lời tao nhã nhất.
Dan

Điều này không hoạt động khi tôi có ba hoặc nhiều đầu vào trên cùng một hộp thoại. Không biết tại sao.
chương trình

6

Ben Clayton là gọn gàng và ngắn nhất và nó có thể được đặt ở đầu trang chỉ mục của bạn trước khi bất kỳ hộp thoại jquery nào được khởi tạo. Tuy nhiên, tôi muốn chỉ ra rằng ".live" đã không được chấp nhận. Hành động ưa thích bây giờ là ".on". Nếu bạn muốn ".on" hoạt động như ".live", bạn sẽ phải sử dụng các sự kiện được ủy quyền để đính kèm trình xử lý sự kiện. Ngoài ra, một vài thứ khác ...

  1. Tôi thích sử dụng phương thức ui.keycode.ENTER để kiểm tra khóa enter vì bạn không phải nhớ mã khóa thực tế.

  2. Sử dụng nút "$ ('. Ui-hộp thoại-buttonpane: đầu tiên', $ (này))" cho bộ chọn nhấp chuột làm cho toàn bộ phương thức chung.

  3. Bạn muốn thêm "return false;" để ngăn chặn mặc định và ngừng lan truyền.

Trong trường hợp này...

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

4

Tôi không biết về đơn giản hơn, nhưng thông thường bạn sẽ theo dõi nút nào có trọng tâm hiện tại. Nếu tiêu điểm được thay đổi thành một điều khiển khác, thì "nút lấy nét" sẽ vẫn ở nút đã lấy nét sau cùng. Thông thường, "nút lấy nét" sẽ bắt đầu trên nút mặc định của bạn. Chuyển sang một nút khác sẽ thay đổi "nút lấy nét". Bạn phải quyết định xem việc điều hướng đến một thành phần biểu mẫu khác có đặt lại "nút tiêu điểm" về nút mặc định hay không. Bạn cũng có thể cần một số chỉ báo trực quan khác với mặc định của trình duyệt để chỉ ra nút tập trung vì nó mất tiêu điểm thực sự trong cửa sổ.

Khi bạn đã thực hiện logic tập trung vào nút và triển khai, thì có lẽ tôi sẽ thêm một trình xử lý khóa vào chính hộp thoại và để nó gọi hành động liên quan đến nút "tập trung" hiện tại.

EDIT : Tôi đang đưa ra giả định rằng bạn muốn có thể nhấn enter bất cứ khi nào bạn điền vào các yếu tố biểu mẫu và hành động nút "hiện tại" được ưu tiên. Nếu bạn chỉ muốn hành vi này khi nút thực sự tập trung, câu trả lời của tôi quá phức tạp.


3

Tôi đã tìm thấy giải pháp này, nó hoạt động trên IE8, Chrome 23.0 và Firefox 16.0

Nó dựa trên nhận xét của 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();
});

Tôi hy vọng nó sẽ giúp được bất cứ ai.


Cảm ơn! Điều đó giúp tôi tiết kiệm rất nhiều thời gian! :)
Rahul Desai

3

Đôi khi chúng ta quên mất nền tảng của những gì trình duyệt đã hỗ trợ:

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

Điều này sẽ gây ra ENTERchìa khóa để gửi biểu mẫu.


2

Tôi đã làm như vậy ...;) Hy vọng nó sẽ hữu ích cho ai đó ..

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

Điều này sẽ làm việc để kích hoạt nhấp chuột của trình xử lý nhấp chuột của nút. ví dụ này giả sử bạn đã thiết lập biểu mẫu trong hộp thoại để sử dụng plugin jquery.validate. nhưng có thể dễ dàng thích nghi.

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

Tôi nhận ra đã có rất nhiều câu trả lời, nhưng tôi tự nhiên nghĩ rằng giải pháp của tôi là gọn gàng nhất, và có thể là ngắn nhất. Nó có lợi thế là nó hoạt động trên bất kỳ hộp thoại nào được tạo bất kỳ lúc nào trong tương lai.

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

1
Xin chào, cảm ơn bạn đã cập nhật, chỉ là một câu hỏi nhỏ, ".ok-button" ở đây là gì? đó có phải là lớp bạn phải áp dụng trên nút mặc định mà bạn muốn nhấp bằng enter không?
UID

Xin lỗi nếu bạn tìm thấy câu hỏi sily .. m quá mới trong JS / jQuery
UID

@BenClayton: Câu trả lời này có thể được cải thiện nếu bạn đặt nó trong ngữ cảnh của Hộp thoại jQueryUI.
Michael Potter

1

Đây là những gì tôi đã làm:

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

Trong trường hợp này, myForm là một đối tượng jQuery chứa html của biểu mẫu (lưu ý, không có bất kỳ thẻ "biểu mẫu" nào trong đó ... nếu bạn đặt chúng trong toàn màn hình sẽ làm mới khi bạn nhấn "enter").

Bất cứ khi nào người dùng nhấn "enter" từ trong biểu mẫu, nó sẽ tương đương với việc nhấp vào nút "ok".

Điều này cũng tránh được vấn đề mở biểu mẫu với nút "ok" đã được tô sáng. Mặc dù điều đó sẽ tốt cho các biểu mẫu không có trường, nhưng nếu bạn cần người dùng điền vào công cụ, thì có lẽ bạn muốn trường đầu tiên được tô sáng.


Đây là giải pháp hợp lý nhất. Thậm chí tốt hơn nếu bạn khai báo nút của mình bằng id và chuyển vào bộ chọn vào find () nhưng cả hai cách đều hoạt động. +1
Vincent

1

ngay và luôn

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

0

nếu bạn biết bộ chọn thành phần nút:

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

Nên làm thủ thuật cho bạn. Điều này sẽ tập trung vào nút ok và nhập sẽ 'nhấp vào', như bạn mong đợi. Đây là kỹ thuật tương tự được sử dụng trong các hộp thoại UI gốc.


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

Tôi tìm thấy một giải pháp khá đơn giản cho vấn đề này:

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

Nó hiệu quả tuyệt vời đối với tôi..


Bạn sẽ làm tốt để bao gồm một tham chiếu đến hộp thoại $ ('# DialogID'). () Làm đối số để áp dụng. Nếu không, $ (this) .close () sẽ không có ngữ cảnh chính xác bên trong TheButton.
Dave

0

Không có giải pháp nào trong số này có vẻ hiệu quả với tôi trong IE9. Tôi đã kết thúc với điều này ..

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

Phần thân bên dưới được sử dụng vì hộp thoại DIV được thêm vào phần thân, vì vậy phần thân bây giờ lắng nghe sự kiện bàn phím. Nó đã thử nghiệm trên 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

Bởi vì tôi không có đủ danh tiếng để gửi bình luận.

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

Câu trả lời được sửa đổi bởi Basemm # 35 cũng thêm vào Escape để đóng hộp thoại.


-1

Nó hoạt động tốt Cảm ơn bạn !!!

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


hmm ... có gì mới (so với câu trả lời trước đó) trong bài viết của bạn không?
kleopatra

-1

Cung cấp cho các lớp nút của bạn và chọn chúng theo cách thông thường:

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

    });

  }
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.