jQuery UI - Đóng Hộp thoại Khi được Nhấp vào Bên ngoài


113

Tôi có Hộp thoại giao diện người dùng jQuery được hiển thị khi các phần tử cụ thể được nhấp vào. Tôi muốn đóng hộp thoại nếu nhấp chuột xảy ra ở bất kỳ nơi nào khác ngoài các phần tử kích hoạt đó hoặc chính hộp thoại.

Đây là mã để mở hộp thoại:

$(document).ready(function() {
    var $field_hint = $('<div></div>')
        .dialog({
            autoOpen: false,
            minHeight: 50,
            resizable: false,
            width: 375
        });

    $('.hint').click(function() {
        var $hint = $(this);
        $field_hint.html($hint.html());
        $field_hint.dialog('option', 'position', [162, $hint.offset().top + 25]);
        $field_hint.dialog('option', 'title', $hint.siblings('label').html());
        $field_hint.dialog('open');
    });
    /*$(document).click(function() {
        $field_hint.dialog('close');
    });*/
});

Nếu tôi bỏ ghi chú phần cuối cùng, hộp thoại sẽ không bao giờ mở. Tôi cho rằng đó là vì cùng một cú nhấp chuột mở hộp thoại đang đóng hộp thoại lại.


Lưu ý mã làm việc cuối cùng
: Đây là sử dụng plugin jQuery bên ngoài sự kiện

$(document).ready(function() {
    // dialog element to .hint
    var $field_hint = $('<div></div>')
            .dialog({
                autoOpen: false,
                minHeight: 0,
                resizable: false,
                width: 376
            })
            .bind('clickoutside', function(e) {
                $target = $(e.target);
                if (!$target.filter('.hint').length
                        && !$target.filter('.hintclickicon').length) {
                    $field_hint.dialog('close');
                }
            });

    // attach dialog element to .hint elements
    $('.hint').click(function() {
        var $hint = $(this);
        $field_hint.html('<div style="max-height: 300px;">' + $hint.html() + '</div>');
        $field_hint.dialog('option', 'position', [$hint.offset().left - 384, $hint.offset().top + 24 - $(document).scrollTop()]);
        $field_hint.dialog('option', 'title', $hint.siblings('label').html());
        $field_hint.dialog('open');
    });

    // trigger .hint dialog with an anchor tag referencing the form element
    $('.hintclickicon').click(function(e) {
        e.preventDefault();
        $($(this).get(0).hash + ' .hint').trigger('click');
    });
});

Câu trả lời:


31

Kiểm tra plugin Sự kiện bên ngoài của jQuery

Cho phép bạn làm:

$field_hint.bind('clickoutside',function(){
    $field_hint.dialog('close');
});

Tôi nhận được hành vi tương tự, trong đó gợi ý sẽ không hiển thị khi các phần tử $ ('. Hint') được nhấp vào. Những yếu tố đó nằm 'bên ngoài' hộp thoại.
Sonny

Bạn chỉ quan tâm đến nhấp chuột bên ngoài nếu hộp thoại đang mở. Vì vậy, chỉ ràng buộc nó sau khi bạn mở nó.
PetersenDidIt vào

3
Tôi đã đọc ở một nơi khác về tính năng lọc dựa trên sự kiện và cách đó đã giải quyết được vấn đề: groups.google.com/group/jquery-ui/msg/a880d99138e1e80d
Sonny

Hộp thoại được sử dụng lại nhiều lần trong tài liệu, vì vậy tôi phải có cách để hủy liên kết khi đóng hộp thoại. Tôi nghĩ rằng bộ lọc là một giải pháp đơn giản hơn.
Sonny

159

Xin lỗi để kéo điều này lên sau quá lâu nhưng tôi đã sử dụng bên dưới. Bất kỳ nhược điểm? Xem chức năng mở ...

$("#popup").dialog(
{
    height: 670,
    width: 680,
    modal: true,
    autoOpen: false,
    close: function(event, ui) { $('#wrap').show(); },
    open: function(event, ui) 
    { 
        $('.ui-widget-overlay').bind('click', function()
        { 
            $("#popup").dialog('close'); 
        }); 
    }
});

18
Trên thực tế, điều này sẽ chỉ hoạt động nếu cửa sổ giao diện người dùng là phương thức. Vâng hữu ích nếu bạn muốn đóng một hộp thoại modal
stumac85

37
Rất đẹp. Tôi chỉ thay đổi nó để này vì vậy tôi không cần phải thiết lập các tài liệu tham khảo ID một cách rõ ràng:$('.ui-widget-overlay').bind('click', function () { $(this).siblings('.ui-dialog').find('.ui-dialog-content').dialog('close'); });
James McCormack

1
Tôi thích cái này. Có trường hợp nào bạn không muốn nó modal nhưng vẫn muốn click ra ngoài để đóng không? Không có ý nghĩa với tôi (tôi đoán với phương thức, bạn mất di chuột vào các yếu tố bên ngoài / bên dưới).
Nick Spacek

3
@NickSpacek - Khi nó không phải là phương thức, tôi có thể đặt tiêu điểm cho một trường, mở hộp thoại mới, v.v. chỉ với một cú nhấp chuột. Với hộp thoại phương thức, tôi sẽ phải sử dụng hai lần nhấp: một để đóng nó và một để thực hiện hành động tiếp theo.
Sonny

1
Cảm ơn! Bạn cũng có thể tận dụng tính năng sủi bọt trực tiếp của jQuery. $ ('body'). on ('click', '.ui-widget-overlay', close);
Quảng Văn

78

Quên sử dụng một plugin khác:

Dưới đây là 3 phương pháp để đóng hộp thoại giao diện người dùng jquery khi nhấp vào bên ngoài cửa sổ bật lên:

Nếu hộp thoại là phương thức / có lớp phủ nền: http://jsfiddle.net/jasonday/6FGqN/

jQuery(document).ready(function() {
    jQuery("#dialog").dialog({
        bgiframe: true,
        autoOpen: false,
        height: 100,
        modal: true,
        open: function(){
            jQuery('.ui-widget-overlay').bind('click',function(){
                jQuery('#dialog').dialog('close');
            })
        }
    });
}); 

Nếu hộp thoại không phải là phương thức Phương pháp 1: Phương pháp 1: http://jsfiddle.net/jasonday/xpkFf/

 // Close Pop-in If the user clicks anywhere else on the page
                     jQuery('body')
                      .bind(
                       'click',
                       function(e){
                        if(
                         jQuery('#dialog').dialog('isOpen')
                         && !jQuery(e.target).is('.ui-dialog, a')
                         && !jQuery(e.target).closest('.ui-dialog').length
                        ){
                         jQuery('#dialog').dialog('close');
                        }
                       }
                      );

Hộp thoại Non-Modal Phương pháp 2: http://jsfiddle.net/jasonday/eccKr/

  $(function() {
            $( "#dialog" ).dialog({
                autoOpen: false, 
                minHeight: 100,
                width: 342,
                draggable: true,
                resizable: false,
                modal: false,
                closeText: 'Close',
                  open: function() {
                      closedialog = 1;
                      $(document).bind('click', overlayclickclose);
                  },
                  focus: function() {
                      closedialog = 0;
                  },
                  close: function() {
                      $(document).unbind('click');
                  }



        });

         $('#linkID').click(function() {
            $('#dialog').dialog('open');
            closedialog = 0;
        });

         var closedialog;

          function overlayclickclose() {
              if (closedialog) {
                  $('#dialog').dialog('close');
              }

              //set to one because click on dialog box sets to zero
              closedialog = 1;
          }


  });

2
Tuyệt quá! Tôi đã thay đổi một chút chức năng tùy chọn mở cho hộp thoại phương thức, vì vậy không cần phải đặt tên rõ ràng cho phần tử. open : function () { $('.ui-widget-overlay').on('click', function () { $(this).parents("body").find(".ui-dialog-content").dialog("close"); }); }
meridius

Lưu ý rằng cho giải pháp # 2, .là ( 'ui-thoại, a ') đã được thay đổi để .là (' ui-thoại, whateverYouClickOnToOpenTheDialog.')
personne3000

@Jason vì dấu phẩy, tôi nghĩ dòng này thực sự nói "không phải hộp thoại ui hoặc bất kỳ liên kết nào trong trang". Nếu tôi thay đổi liên kết "Hộp thoại mở" trong ví dụ của bạn thành <span>, hộp thoại sẽ bị đóng ngay sau khi mở vì sự kiện cửa sổ được kích hoạt lần cuối, đó là lý do tại sao tôi nghĩ bạn cần loại trừ mục bạn nhấp vào để mở hộp thoại. Tôi không hiểu tại sao bạn cần tham chiếu các liên kết trong hộp thoại?
personne3000

@ personne3000 - thực ra bạn đã đúng về ngữ cảnh, rằng bộ chọn đang chọn cả hai. Tôi đang cố nhớ lý do tại sao tôi lại thêm điều đó vào, vì chắc chắn tôi phải có một lý do cụ thể nào đó mà tôi không nhớ vào lúc này.
Jason

@ Jason đến mâu thuẫn tránh với nhiều hộp thoại, bạn có thể sử dụng các sự kiện namespacedclick.myNamespace
Christophe Roussy

17

Chỉ cần thêm tập lệnh toàn cục này, tập lệnh này sẽ đóng tất cả các hộp thoại phương thức chỉ cần nhấp vào bên ngoài chúng.

$(document).ready(function()
{
    $(document.body).on("click", ".ui-widget-overlay", function()
    {
        $.each($(".ui-dialog"), function()
        {
            var $dialog;
            $dialog = $(this).children(".ui-dialog-content");
            if($dialog.dialog("option", "modal"))
            {
                $dialog.dialog("close");
            }
        });
    });;
});

Tôi không sử dụng hộp thoại phương thức. Câu trả lời ở đây với nhiều phiếu bầu nhất cũng dành cho các hộp thoại phương thức.
Sonny

Khi sử dụng cùng một hộp thoại nhiều lần trên cùng một trang, đây là cách duy nhất để thực hiện vì nó sẽ chỉ hoạt động một lần nếu bạn liên kết nó trong hàm đang mở. Cảm ơn vì ý tưởng tuyệt vời này!
MaDaHoPe

đây là của tôi:$(document).on('click', '.ui-widget-overlay', function() { $('#'+$('.ui-dialog-content')[0].id).dialog('close'); });
mr5.

10
$(".ui-widget-overlay").click (function () {
    $("#dialog-id").dialog( "close" );
});

Fiddle hiển thị đoạn mã trên đang hoạt động.


Tôi sẽ xem qua nó. Cảm ơn Jen!
Sonny

8

Tôi đã phải làm hai phần. Đầu tiên trình xử lý nhấp chuột bên ngoài:

$(document).on('click', function(e){
    if ($(".ui-dialog").length) {
        if (!$(e.target).parents().filter('.ui-dialog').length) {
            $('.ui-dialog-content').dialog('close');
        }
    }
}); 

Điều này gọi dialog('close')đến ui-dialog-contentlớp chung và do đó sẽ đóng tất cả các hộp thoại nếu lần nhấp không bắt nguồn từ một lớp. Nó cũng sẽ hoạt động với các hộp thoại phương thức, vì lớp phủ không phải là một phần của .ui-dialoghộp.

Vấn đề là:

  1. Hầu hết các hộp thoại được tạo do các nhấp chuột bên ngoài hộp thoại
  2. Trình xử lý này chạy sau khi những cú nhấp chuột đó đã tạo ra một hộp thoại và chuyển đến tài liệu, vì vậy nó ngay lập tức đóng chúng.

Để khắc phục điều này, tôi phải thêm stopPropagation vào các trình xử lý nhấp chuột đó:

moreLink.on('click', function (e) {
    listBox.dialog();
    e.stopPropagation(); //Don't trigger the outside click handler
});

Điều này nghe có vẻ đơn giản hơn so với giải pháp tôi đang sử dụng. Tôi sẽ phải thử nó.
Sonny

Đây là giải pháp tôi nghĩ đến bản thân mình, nhưng tôi là một lớp lót:$('body').on('click', '.ui-widget-overlay', function () { $('#myDialog').dialog('close'); });
styfle

5

Câu hỏi này hơi cũ, nhưng trong trường hợp ai đó muốn đóng hộp thoại KHÔNG theo phương thức khi người dùng nhấp vào đâu đó, bạn có thể sử dụng câu hỏi này mà tôi đã lấy từ plugin JQuery UI Multiselect . Ưu điểm chính là nhấp chuột không bị "mất" (nếu người dùng muốn nhấp vào một liên kết hoặc một nút, hành động được thực hiện).

$myselector.dialog({
            title: "Dialog that closes when user clicks outside",
            modal:false,
            close: function(){
                        $(document).off('mousedown.mydialog');
                    },
            open: function(event, ui) { 
                    var $dialog = $(this).dialog('widget');
                    $(document).on('mousedown.mydialog', function(e) {
                        // Close when user clicks elsewhere
                        if($dialog.dialog('isOpen') && !$.contains($myselector.dialog('widget')[0], e.target)){
                            $myselector.dialog('close');
                        }            
                    });
                }                    
            });

Tôi đã phải di chuyển var $dialog = $(this).dialog('widget');bên trong xử lý sự kiện khi nhấp chuột
Stefan Haberl

1
@Melanie, tôi nghĩ giải pháp của bạn có thể áp dụng hơn những giải pháp khác. Một anh chàng tạo plugin cho 'jqui thoại' dựa trên cách tiếp cận của bạn - js tại github
resnyanskiy

5

Bạn có thể làm điều này mà không cần sử dụng bất kỳ trình cắm bổ sung nào

var $dialog= $(document.createElement("div")).appendTo(document.body);
    var dialogOverlay;

    $dialog.dialog({
        title: "Your title",
        modal: true,
        resizable: true,
        draggable: false,
        autoOpen: false,
        width: "auto",
        show: "fade",
        hide: "fade",
        open:function(){
            $dialog.dialog('widget').animate({
                width: "+=300", 
                left: "-=150"
            });

//get the last overlay in the dom
            $dialogOverlay = $(".ui-widget-overlay").last();
//remove any event handler bound to it.
            $dialogOverlay.unbind();
            $dialogOverlay.click(function(){
//close the dialog whenever the overlay is clicked.
                $dialog.dialog("close");
            });
        }
    });

Đây là hộp thoại $. Những gì chúng ta đang làm về cơ bản là lấy tiện ích lớp phủ cuối cùng bất cứ khi nào hộp thoại này được mở và liên kết trình xử lý nhấp chuột với lớp phủ đó để đóng hộp thoại $ khi bất kỳ lúc nào lớp phủ được nhấp.


Tôi nghĩ điều này tương tự với các giải pháp khác cho hộp thoại phương thức. Câu hỏi của tôi dành cho các hộp thoại không theo phương thức.
Sonny

5

không cần plugin sự kiện bên ngoài ...

chỉ cần thêm một trình xử lý sự kiện vào div .ui-widget-overlay:

jQuery(document).on('click', 'body > .ui-widget-overlay', function(){
     jQuery("#ui-dialog-selector-goes-here").dialog("close");
     return false;
});

chỉ cần đảm bảo rằng bất kỳ bộ chọn nào bạn đã sử dụng cho hộp thoại jQuery ui, cũng được gọi để đóng nó .. tức là # ui-hộp thoại-selector-go-here


Một số giải pháp để đóng hộp thoại phương thức đã được đề xuất. Hộp thoại của tôi là không theo phương thức và do đó không có lớp phủ.
Sonny

Hơn nữa, bạn chỉ cần liên kết sự kiện nhấp chuột với thẻ body hoặc trình bao bọc div và sử dụng nó làm trình kích hoạt sự kiện nhấp chuột của bạn, thay vì phương thức.
Jonathan Marzullo

Đúng. Về cơ bản đó là những gì giải pháp của tôi làm. Nó cũng phải loại trừ các nhấp chuột trong hộp thoại.
Sonny

3

Điều này không sử dụng jQuery UI, nhưng sử dụng jQuery và có thể hữu ích cho những người không sử dụng jQuery UI vì bất kỳ lý do gì. Làm như vậy:

function showDialog(){
  $('#dialog').show();
  $('*').on('click',function(e){
    $('#zoomer').hide();
  });
}

$(document).ready(function(){

  showDialog();    

});

Vì vậy, khi tôi hiển thị một hộp thoại, tôi thêm một trình xử lý nhấp chuột chỉ tìm kiếm nhấp chuột đầu tiên vào bất kỳ thứ gì.

Bây giờ, sẽ tốt hơn nếu tôi có thể làm cho nó bỏ qua các nhấp chuột vào bất kỳ thứ gì trên #dialog và nội dung của nó, nhưng khi tôi thử chuyển $ ('*') với $ (': not ("# hộp thoại, # hộp thoại *") '), nó vẫn phát hiện thấy # nhấp chuộtialog.

Dù sao, tôi đang sử dụng nó hoàn toàn cho một hộp đèn ảnh, vì vậy nó hoạt động ổn cho mục đích đó.


2

(Các) ví dụ đã cho sử dụng một hộp thoại có id '#dialog', tôi cần một giải pháp để đóng bất kỳ hộp thoại nào:

$.extend($.ui.dialog.prototype.options, {
    modal: true,
    open: function(object) {
        jQuery('.ui-widget-overlay').bind('click', function() {              
            var id = jQuery(object.target).attr('id');
            jQuery('#'+id).dialog('close');
        })
    }
});

Cảm ơn đồng nghiệp của tôi Youri Arkesteijn về đề xuất sử dụng nguyên mẫu.


2

Đây là phương pháp duy nhất phù hợp với tôi cho hộp thoại KHÔNG CHẾ ĐỘ của tôi

$(document).mousedown(function(e) {
    var clicked = $(e.target); // get the element clicked
    if (clicked.is('#dlg') || clicked.parents().is('#dlg') || clicked.is('.ui-dialog-titlebar')) {
        return; // click happened within the dialog, do nothing here
    } else { // click was outside the dialog, so close it
        $('#dlg').dialog("close");
    }
});

Tất cả tín dụng được chuyển đến Axle
Nhấp vào bên ngoài hộp thoại không theo phương thức để đóng



1

Tôi sử dụng giải pháp này dựa trên một giải pháp được đăng ở đây:

var g_divOpenDialog = null;
function _openDlg(l_d) {

  // http://stackoverflow.com/questions/2554779/jquery-ui-close-dialog-when-clicked-outside
  jQuery('body').bind(
   'click',
   function(e){
    if(
      g_divOpenDialog!=null 
      && !jQuery(e.target).is('.ui-dialog, a')
      && !jQuery(e.target).closest('.ui-dialog').length
    ){
      _closeDlg();
    }
   }
  );

  setTimeout(function() {
    g_divOpenDialog = l_d;
    g_divOpenDialog.dialog();
  }, 500);
}
function _closeDlg() {
  jQuery('body').unbind('click');
  g_divOpenDialog.dialog('close');
  g_divOpenDialog.dialog('destroy');
  g_divOpenDialog = null;
}

1

Tôi đã gặp vấn đề tương tự khi thực hiện phương thức xem trước trên một trang. Sau rất nhiều googling, tôi thấy giải pháp này rất hữu ích. Với sự kiện và mục tiêu, nó đang kiểm tra nơi nhấp chuột đã xảy ra và tùy thuộc vào nó kích hoạt hành động hoặc không làm gì.

Trang web Thư viện đoạn mã

$('#modal-background').mousedown(function(e) {
var clicked = $(e.target);  
if (clicked.is('#modal-content') || clicked.parents().is('#modal-content')) 
    return; 
} else {  
 $('#modal-background').hide();
}
});

0

Điều đó thực sự đơn giản, bạn không cần bất kỳ plugin nào, chỉ cần jquery hoặc bạn có thể làm điều đó với javascript đơn giản.

$('#dialog').on('click', function(e){
  e.stopPropagation();
});
$(document.body).on('click', function(e){
  master.hide();
});

0

Tôi không nghĩ rằng việc tìm kiếm nội dung hộp thoại bằng $ ('. Any-selector') từ toàn bộ DOM lại sáng sủa như vậy.

Thử

$('<div />').dialog({
    open: function(event, ui){
        var ins = $(this).dialog('instance');
        var overlay = ins.overlay;
        overlay.off('click').on('click', {$dialog: $(this)}, function(event){
            event.data.$dialog.dialog('close');
        });
    }
});

Bạn thực sự nhận được lớp phủ từ thể hiện hộp thoại mà nó thuộc về, mọi thứ sẽ không bao giờ sai theo cách này.


Đây là cho một hộp thoại phương thức? OP của tôi là về phi phương thức, vì vậy không có lớp phủ.
Sonny

0

Với đoạn mã sau, bạn có thể mô phỏng một cú nhấp chuột vào nút 'đóng' của hộp thoại (thay đổi chuỗi 'MY_DIALOG' cho tên hộp thoại của riêng bạn)

$("div[aria-labelledby='ui-dialog-title-MY_DIALOG'] div.ui-helper-clearfix a.ui-dialog-titlebar-close")[0].click();

0

Mã thông minh: Tôi đang sử dụng mã sau để mọi thứ vẫn rõ ràng và dễ đọc. out side body sẽ đóng hộp thoại.

$(document).ready(function () {
   $('body').on('click', '.ui-widget-overlay', closeDialogBox);
});

function closeDialogBox() {
    $('#dialog-message').dialog('close');
}

0

Tôi đã kết thúc bằng cách sử dụng mã này sẽ hoạt động trên bất kỳ hộp thoại đang mở nào trên trang, bỏ qua các nhấp chuột vào chú giải công cụ và dọn dẹp tài nguyên của hộp thoại đang đóng.


        $(document).mousedown(function(e) {
            var clicked = $(e.target); // get the element clicked
            if (clicked.is('.ui-dialog-content, .ui-dialog-titlebar, .ui-tooltip') || clicked.parents().is('.ui-dialog-content, .ui-dialog-titlebar, .ui-tooltip')) {
                return; // click happened within the dialog, do nothing here
            } else { // click was outside the dialog, so close it
                $('.ui-dialog-content').dialog("close");
                $('.ui-dialog-content').dialog("destroy");
                $('.ui-dialog-content').detach();

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