用于JQueryUI选项卡内的JQueryUI对话框的.on()事件绑定

时间:2012-02-01 22:57:30

标签: performance jquery-ui jquery

我有一个页面,其中包含类'对话'的链接,单击时会在JQueryUI dialog中生成。这些对话框是从页面上的其他元素创建的,并且可以包含类“add_tab”的链接,这些链接应该在单击时创建新的JQueryUI [tab](http://jqueryui.com/demos/dialog/)。这些选项卡通过Ajax加载其内容并包含相同的结构。这意味着对话框中的“add_tab”链接会创建一个新选项卡,其中包含“对话框”链接,这些链接生成包含更多“add_tab”链接的对话框,依此类推。

这是基本的HTML结构:

<div id="tabs">
  <ul>
    <li><a href="#tabs-1">tab 1</a></li>
  </ul>
  <div id="tabs-1">
    <p>This tab contains a <a href="#popup1" class="dialog" target="_new">popup</a> and a direct link to a <a href="tabs2.htm" class="add_tab">new tab</a>.</p>
    <div id="popup1" style="display:nonee;">This popup contains a link to a <a href="tabs2.htm" class="add_tab" target="_new">new tab</a>.</div>
  </div>

使用JQuery 1.7的.on() method,我在为添加的标签上的对话框中出现的'add_tab'链接正确注册点击处理程序时遇到了麻烦。我设法在新生成的选项卡中为“对话框”链接注册单击处理程序(以便它们生成对话框),但无法为那些对话框中出现的“add_tab”链接注册单击处理程序。我在http://www.kantl.be/ctb/temp/jquerytest/tabs1.htm在线提供了一个简化的测试版本。例如,遵循以下场景:

  1. http://www.kantl.be/ctb/temp/jquerytest/tabs1.htm上,点击“弹出”:这将生成一个JQueryUI对话框
  2. 在对话框中单击“li”,单击“新选项卡”:这将生成一个新的JQueryUI选项卡
  3. 在新添加的标签为'tabs2.htm'的标签中,点击'弹出':这将生成一个JQueryUI对话框
  4. 在对话框中
  5. ,单击“新选项卡”:这不会生成新的JQueryUI选项卡,而是在新窗口中打开目标

    ==&GT;这说明了此事件处理程序显然 NOT 正确注册了在新添加的选项卡中生成的对话框中出现的“add_tab”链接

  6. 在标签为'tabs2.htm'的标签中,点击'新标签':这将生成一个新的JQueryUI标签

    ==&GT;这说明了如何为直接在新添加的选项卡中出现的“add_tab”链接正确注册此事件处理程序

  7. 这是我的javascript代码:

    // these event registrations register clicks on $('a.dialog') and $('a.add_tab') to open new JQueryUI dialogs / tabs
    // note: this event registration works for all such links on the original page
    $('a.dialog').on('click', function(){
      $($(this).attr('href')).dialog(); 
      return false; 
    });
    $('a.add_tab').on('click', function(){
      $tabs.tabs( "add", $(this).attr('href'), 'added tab'); 
      $('.ui-dialog-content').each(function(){$(this).dialog('close')}) 
      return false; 
    }); 
    // tabs: upon creation, register clicks on nested $('a.dialog') and $('a.add_tab') to open new JQueryUI dialogs / tabs 
    var $tabs = $( "#tabs" ).tabs({    
      add: function(event, ui) { 
        $tabs.tabs('select', '#' + ui.panel.id); 
        $tabs.tabs($tabs.tabs('option', 'selected')) 
          .on('click', 'a.dialog', function(){ 
            $($(this).attr('href')).dialog(); 
            return false; 
          })
          // this registration doesn't seem to work for <a class="add_tab"> links occurring inside generated JQueryUI dialogs inside added JQueryUI tabs          
          .on('click', 'a.add_tab', function(){ 
            $tabs.tabs( "add", $(this).attr('href'), 'added tab'); 
            return false; 
          }); 
      }
    });
    

    几乎那里!任何人都可以帮我解决上面代码中的最后一个事件处理程序吗?非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

事件委托的想法是将事件绑定在页面上固定的上(不是动态创建的)。使用.on()方法的selector参数可以告诉应该触发事件处理程序的元素。

在您的代码中,您使用事件绑定有两种方式,例如,如果您使用.on():

  • 首先直接绑定现有元素a.dialog和a.add_tab - 这只适用于tab1上的链接,因为它们是代码执行时唯一存在的元素,没有事件代表团在这里。

  • 添加选项卡时,您正在选项卡容器$ tabs:

    上执行事件委派
    • 用于打开$tabs.on('click', 'a.dialog', function(){ ... })对话框的链接 - 这可以正常工作,因为链接a.dialog确实位于标签容器中。

    • 对于$tabs.on('click', 'a.add_tab', function(){ ... })对话框中的链接 - 这不起作用,因为在创建对话框时,插件会移动正文末尾的<div id="popup2"></body>之前1}})。因此,当您单击对话框中的a.add_tab时,它不再是选项卡容器的后代,并且不会发生事件委派。

这就是我要做的事情:

  1. 为避免重复相同的代码,请将事件处理程序声明为变量

  2. 在选项卡容器上使用事件委托来获取链接a.dialog和a.add_tab

  3. 创建新对话框时,在对话框中使用事件委托,其中包含

  4. 的a.add_tab链接

    以下是代码:

    var addTabClickHandler = function(e) {
        $tabs.tabs("add", $(this).attr('href'), 'added tab');
        $('.ui-dialog-content').each(function() {
            $(this).dialog('close')
        })
        return false;
    };
    
    var dialogOpenClickHandler = function(e) {
        $($(this).attr('href'))
            .dialog()
            .on('click', 'a.add_tab', addTabClickHandler);
        return false;
    }
    
    var $tabs = $("#tabs").tabs({
        add: function(event, ui) {
            $tabs
                .tabs('select', '#' + ui.panel.id)
                .tabs($tabs.tabs('option', 'selected'));
        }
    });
    
    $tabs
        .on('click', 'a.dialog', dialogOpenClickHandler)
        .on('click', 'a.add_tab', addTabClickHandler);
    

答案 1 :(得分:1)

与此同时,我提出了一种解决方法,只需在“tabs”容器上注册事件处理程序,并在创建时将对话框附加到“tabs”容器。因此,我的初始代码可以缩减为:

// tabs: upon creation, register clicks on nested $('a.dialog') and $('a.add_tab') to open new JQueryUI dialogs / tabs 
var $tabs = $( "#tabs" ).tabs({
  create: function(event, ui) {
    $(this)
      .on('click', 'a.dialog', function(){
        // dialog: upon creation, move the dialog to the tab to ensure delegated event registration
        $($(this).attr('href')).dialog().parent('.ui-dialog').appendTo($tabs);
        return false;
      })
      .on('click', 'a.add_tab', function(){
        $tabs.tabs( "add", $(this).attr('href'), $(this).attr('href'));
        $('.ui-dialog-content').dialog('close');
        return false;
      })
  }
});