【问题标题】:Long Polling to update DOM while conserving accumulated attributes from jQuery长轮询以更新 DOM,同时保留来自 jQuery 的累积属性
【发布时间】:2014-03-04 11:29:29
【问题描述】:

编辑:一切正常;推动工作。唯一的问题是每次推送时 #load_info div 都会重置为空。我怎样才能保留div 中的原始内容,尽管在重新推送 XML 文件时内容将是其自身的更新版本。

我有一个用于长轮询 XML 文件并将其编码为 JSON 数组的 PHP 脚本。它以 JSON 作为参数从前端调用。

    $filename= dirname(__FILE__)."/people.xml";

    $lastmodif = isset( $_GET['timestamp'])? $_GET['timestamp']: 0 ;
    $currentmodif=filemtime($filename);

    while ($currentmodif <= $lastmodif) {
        usleep(10000);
        clearstatcache();
        $currentmodif =filemtime($filename);
    }

    $response = array();
    $xObj = simplexml_load_file($filename);

    // Loop for #loadMe.
    foreach($xObj as $person){
        $concat_buttons .= "<button class='mybutton' value='" . (string)$person->id . " '> " . (string)$person->fullName . "</button>";
    }

    // Loop for #toadMe.
    foreach($xObj as $person){
        $concat_info .= "<div class='div div_' data-person-id='" . (string)$person->id . "' id='" . (string)$person->id . "'><h1> " . (string)$person->job . "</h1></div>";
    }


    // Output for AJAX.
    $response['msg']                = $concat_buttons;
    $response['msg2']                = $concat_info;
    $response['timestamp']      = $currentmodif;
    echo json_encode($response);

然后我有一个用于实例化 JSON 对象 (msg2) 的 jQuery 脚本,用于将每个节点附加到名为 #load_datadiv 中。我的问题是为什么下面的 jQuery 不起作用?我的猜测是$(window).findget_person(id) 函数中不起作用和/或我的函数超出了轮询的范围。需要注意的是,在我开始尝试合并 show_person()get_person() 函数之前,PHP 和 JS 是 100% 工作的。就像在其中一样,当单击#load_button div 中的某个按钮时,它将使用id 切换一条信息视图,该value 属性与最初隐藏的.show() 匹配;然后,如果单击另一个按钮,旧信息将被 .hide() 隐藏,并且将看到新数据。这是我使用长轮询更新 DOM 元素的迂回解决方案,只需在开始时将它们全部加载,但是如果在发生新轮询时显示一条信息(vartimestamp 得到更新),那么#load_info 内部的元素将暂时从 DOM 中丢失,因此导致空的#load_info div 直到单击下一个按钮。所以我试图添加一些额外的函数来在var$person 中存储 DOM 数据,以便在轮询之后,之前显示的任何内容都会重新出现。可以更改或添加什么来让这个 jQuery 脚本按预期工作?提前致谢!

    var timestamp=null;
    function waitForMsg() {
        $.ajax({
            type: "GET",
            url: "getData.php?timestamp="+timestamp,
            async: true,
            cache: false,        
            success: function(data) {
                var json=eval('('+data+ ')');
                if (json['msg'] != "") {
                    $("#load_buttons").empty();
                    $("#load_buttons").append(json['msg']);

                    // Update any person divs that were already visible.
                    $('#load_info .person').each(function() {
                        // Grabs the ID from data-person-id set earlier.
                        var id = $(this).data('person-id');
                        show_person(id);
                    });

                }
                timestamp = json["timestamp"];
                setTimeout("waitForMsg()",1000);
            },
            error: function(XMLHttpRequest,textStatus,errorThrown) {
                setTimeout("waitForMsg()",15000);
            }                   
        });
    }

    $(document).on('click', '.mybutton', function() {
        $('#load_info').empty();
        show_person(this.value);
    });

    function show_person(id) {
        $('#person-detail-' + id).remove();
        get_person(id).appendTo('#load_info');
    }

    function get_person(id) {
        var $person = $(window).find('id:contains(id)');

        var $div = $('<div>', {
            'class': 'person',
            'data-person-id': id,
            id: id
        });

        $person.find(h1).text.appendTo($div);
        return $div;  
    }

【问题讨论】:

  • 你对$(window).find('id:contains(id)');的意图是什么?
  • @Kyle Kyle,我正在尝试使用它来创建一个变量来记录#load_info 容器内的当前元素,因此该变量可用于重新显示在下一次推送之前显示的元素;如果之前有任何显示,请发布按钮点击。

标签: javascript php jquery html json


【解决方案1】:

您在 PHP 脚本中生成 JSON 时似乎遇到了问题:

$response['msg']  = $concat;
$response['msg2'] = $concat2;

$concat$concat2 没有在任何地方定义,您的意思是改用 $concat_buttons$concat_info 吗?

$response['msg']  = $concat_buttons;
$response['msg2'] = $concat_info;

在您的 jQuery 中,您引用了 #load_info .person,但它看起来不像 PHP 构建的 div 属于 person 类,这可能是您的循环找不到它们的原因。

【讨论】:

  • 感谢您指出这一点。但是,我正在测试的实时代码没有这个错误。我重命名了问题帖子的变量,忘记重命名您指出的语句。我已经用你的修复更新了我的问题。抱歉语法错误,但根本问题仍然存在。我还重新措辞了我的问题以使其更有意义。
【解决方案2】:

我发现您的问题很难理解,但我喜欢挑战。请注意,我没有测试过任何代码,因此需要对其进行调试。

现在,据我了解,您有一堆具有这种结构的按钮:

<div id="load_buttons">
  // repeater
  <button class="mybutton" value="$person['id']">$person['fullName']</button>
  // end repeater
</div>

还有一堆具有这种结构的细节 div,最初是隐藏的:

<div id="load_info">
  // repeater
  <div class="div div_" data-person-id="$person['id']" id="$person['id']">
    <h1>$person['job']</h1>
  </div>
  // end repeater
</div>

这些应该在每次投票时更新/附加。

您想要实现的目标:单击按钮时,会显示相关信息。我会像这样完成你的成功功能:

success: function(data) {
    var json=eval('('+data+ ')');
    var $buttons;
    var $infos;
    if (json['msg'] != "") {
      addButtons($(json['msg']));
      addInfos($(json['msg2']));
    }
    timestamp = json["timestamp"];
    setTimeout("waitForMsg()",1000);
}

addButtons = function($buttons){
  // loop through the button json data
  $buttons.each(function(){
    // look to see if the button already exists
    var existing = $('[value='+$(this).attr("value")+']').length;
    if(!existing){
      // if not, add the button and assign a click handler
      $(this).appendTo('#load_buttons').click(function(){
        //hide all the children of info
        $('#load_info').children().hide();
        //show the info based on the button value
        $('#'+$(this).val).show();
      });
    }
  });
}
addInfos = function($infos){
  //loop through the info json data
  $infos.each(function(){
    // check to see if an info exists
    var existing = $('#'+$(this).attr("id")).length;
    if(!existing){
      //if not, add the info to the list and set it to hidden
      $(this).appendTo('#load_info').hide();
    }
  });
}

【讨论】:

  • 这看起来不错,但与我的尝试有很大不同,很抱歉回复晚了。我正在尝试用我的原型来实现它;我会留下另一条评论来描述我的结果。
猜你喜欢
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多