我怎样才能延迟可折叠的扩展直到其内容被提取?

时间:2013-11-03 00:08:42

标签: javascript jquery-mobile jquery jquery-mobile-collapsible

我想在我的jQM应用程序(1.3.2)中集成一个可折叠的,其工作原理如下:

  1. 开始已折叠
  2. 点击它开始从服务器获取可折叠的列表项。 可折叠关闭,加载图标可能正在旋转。
  3. 加载所有元素并刷新列表视图并准备就绪后,可折叠扩展
  4. 如果再次点击它,会立即关闭而不会延迟,并从1开始。
  5. 我最初的想法是抓住expand事件并阻止其传播。加载完成后,我取消注册我的自定义事件处理程序,将可折叠程序恢复正常,最后从JavaScript触发expand事件以打开。

    问题是这适用于第一轮,但之后无论如何都会打开折叠。考虑这个例子(也在jsfiddle中):

    <div data-role="collapsible" id="c">
      <h2>Collapse</h2> 
      <ul data-role="listview" id="lv">
        <li>You don't see me!</li>
      </ul>
    </div>
    
    <a href="#" data-role="button" onClick="$('#c').off('expand', stop)">
      Unlock the collapsible
    </a>
    
    <a href="#" data-role="button" onClick="$('#c').on('expand', stop)">
      Lock the collapsible
    </a>
    

    JavaScript的:

    var stop = function(event) {
      alert('Locked!');
      event.preventDefault();
    }
    
    // executed after the element is created ...
    $('#c').on('expand', stop)
    

    在这里,如果您在加载后单击可折叠,它将保持关闭状态(良好)。当您单击解锁时,它会打开并且不会显示任何警报(正常)。如果你再次锁定它会显示警告(好),但无论如何都会打开(坏)。

    任何人都可以告诉我我做错了什么吗?似乎有解锁的副作用,我无法看到。这里有几个类似的问题,但大多数人都很高兴只是防止扩展而不再重新开启。

    所以我的问题是:可靠地延迟可折叠扩展的最佳方法是什么?


    编辑:我添加了另一个集成listview逻辑的示例,并显示了此错误。 jsFiddle is here.我也转移到.one()以使取消注册更具可追溯性。

    新JavaScript:

    var stop_n_load = function (event) {
      alert('stop opening! (or at least try to ...)');
    
      // try to stop the expanding by stopping the event
      event.preventDefault();
    
      // Do some work that takes time and trigger expand afterwards ...
      setTimeout(function (e) {
        dd = new Date();
        $('#lv').empty();
        $('#lv').append("<li><a href='#'>Item A ("+dd+")</a></li>");
        $('#lv').append("<li><a href='#'>Item B ("+dd+")</a></li>");
        $('#lv').listview('refresh');
    
        // when done, start expanding without this handler (was register only once)
        $('#c').trigger('expand');
        // for the next collapse register stop_n_load again
        $('#c').one('collapse', reset);
      }, 2000);
    };
    
    var reset = function (event) {
      $('#c').one('expand', stop_n_load);
    };
    
    $('#c').one('expand', stop_n_load);
    

    在第一次扩展时,它按预期工作,首先更新然后打开。在第二次运行时,它无需等待即可打开,您可以稍后查看时间戳更新,以便正确调用该事件。

    .preventDefault()我似乎不明白......

3 个答案:

答案 0 :(得分:2)

当触发expand / collapse个事件时,jQM会添加几个类来显示/隐藏内容以及更新可折叠按钮/标题。

在这种情况下,event.preventDefault()不会阻止事件冒泡并阻止它们执行。因此,一旦单击标题,您需要使用event.stopImmediatePropagation()来停止expand事件。

折叠折叠后,它会有一个类ui-collapsible-collapsed,一旦展开,该类就会被删除。因此,当collapse被触发时,它会正常工作而不会中断。

$(".ui-collapsible-heading-toggle").on("click", function (e) {

    // check if collapsible is whether expanded or collapsed
    if ($(this).closest(".ui-collapsible").hasClass("ui-collapsible-collapsed")) {

        // true
        // stop "expand" event on click,tap,vclick,touchstart, etc...
        e.stopImmediatePropagation();

        // show loading msg - optional
        $.mobile.loading("show", {
            text: "Loading...Please wait",
            textVisible: true
        });

        // for demo
        // add items, expand and hide loading msg
        setTimeout(function () {                
            $("#lv").empty().append(items).listview("refresh");
            $("#c").trigger("expand");
            $.mobile.loading("hide");
        }, 1000);
    }

    // false
    // collapse normally or do something else
});
  

<强> Demo

答案 1 :(得分:1)

我对JQM并不熟悉,但在发送更多数据之前,我的第一个想法是清空列表....这似乎阻止了它的扩展。

var stop = function(event) {    
    $(this).find('.ui-listview').empty()
    event.preventDefault();

    /* do ajax and then refresh component with expand enabled */
}

$('#c').on('expand', stop);

DEMO - without ajax

答案 2 :(得分:0)

在事件系统中徘徊之后,我现在断定,如果你永远坚持下去,就设置preventDefault()。基于 charlietfl 的解决方案,我添加了代码以使视觉影响最小化,也许还有一种方法可以阻止GUI刷新20ms以使其完全不可察觉。

var stop_n_load = function (event) {
  $('#lv').empty();
  $('#lv').listview('refresh');

  setTimeout(function() {
    $('#c').trigger('collapse');
  }, 20);

  // Do some work that takes time and trigger expand afterwards ...
  setTimeout(function () {
    dd = new Date();
    $('#lv').empty();
    $('#lv').append("<li><a href='#'>Item A (" + dd + ")</a></li>");
    $('#lv').append("<li><a href='#'>Item B (" + dd + ")</a></li>");
    $('#lv').listview('refresh');

    $('#c').trigger('expand');
    $('#c').one('collapse', reset);
  }, 2000);
};

我仍在寻找一种解决方案,将事件重置为之前的状态。