【问题标题】:How I can I delay the expansion of a collapsible until its content is fetched?我怎样才能延迟可折叠的扩展,直到它的内容被提取?
【发布时间】:2013-11-03 00:08:42
【问题描述】:

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

  1. 它开始折叠
  2. 单击时,它开始从服务器获取可折叠的列表项。 折叠屏保持关闭状态,加载图标可能会旋转。
  3. 加载所有元素并刷新列表视图并准备就绪后,可折叠展开
  4. 如果再次点击它,它直接关闭不会延迟,从1开始。

我最初的想法是抓住expand 事件并阻止其传播。加载完成后,我取消注册自定义事件处理程序以将可折叠恢复正常,最后触发 JavaScript 中的展开事件以打开。

问题是这适用于第一轮,但之后折叠式仍然打开。考虑这个例子(也在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)

在这里,如果您在加载后单击可折叠,它会保持关闭状态(很好)。当您单击解锁时,它会打开并且不显示任何警报(好)。如果您再次锁定它,它会显示警报(好)但仍然会打开(坏)。

谁能告诉我我做错了什么?解锁似乎有我看不到的副作用。这里有几个类似的问题,但大多数人都乐于阻止扩展而不重新打开它。

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


编辑:我添加了另一个集成列表视图逻辑的示例,也显示了此错误。 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()好像有问题我不明白...

【问题讨论】:

  • 您需要同时使用return false = preventDefault()stopPropagation()。检查这个jsfiddle.net/Palestinian/yXa4W
  • 谢谢@Omar,这看起来很棒!为什么点击事件没有第二次点击时仍设置.preventDefault()的问题?您能根据您的评论做出回答吗?
  • 当collapsible展开时,ui-collapsible-collapsed类被移除,所以第二次点击正常工作。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我对 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

    【讨论】:

    • 感谢您的回答,这只是部分解决了我的问题,因为您仍然可以看到可折叠的反应(添加了下方的一些空白区域,图标更改)。 I made another fiddle with additional listview logic 结合您的想法,您应该会看到问题所在。必须有一个解决方案来直接处理事件,毕竟它在第一次点击时就可以按我想要的方式工作......
    • 我猜是浏览器/设备依赖....我和你在 windows 上使用我的开发浏览器 FF 和 Chrome 不一样
    【解决方案3】:

    在事件系统中涉足之后,我现在得出的结论是,如果您设置preventDefault(),一旦您将永远卡在它上面。基于 charlietfl 的解决方案,我添加了代码以使视觉影响最小,也许还有一种方法可以防止 GUI 在 20 毫秒内刷新以使其完全不被注意到。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 2019-06-19
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      相关资源
      最近更新 更多