点击事件将文本区域添加到 div 中。

12

我目前在网页上设置了一个 button,当用户按下该按钮后会发起一次ajax调用。

问题是,在提交后会有一点延迟(因为需要完成第二个ajax调用才能显示DIV),以避免出现轻微的滞后。我想知道是否可能将内容附加到DIV中:

    <textarea name='Status'> </textarea>
    <input type='hidden' name='UserID' value="<?=$_SESSION['UserID']; ?>">
    <input type='button' value='Status Update'>
  <script>
  $(function () {
    $('input').on('click', function () {
        var Status = $(this).val();
       $('#output').append(Status);
});
  </script>

以上是我的当前代码配置。现在,它没有按预期工作。它不能将提交的内容添加到DIV中...这是通过我的ajax调用显示的方式:

window.setInterval(function()
{
  $(function () 
  {
    $.ajax({                                      
        url: 'Ajax/AjaxStatuses.php', data: "", dataType: 'json',  success: function(rows)        
        {
        $('#output').empty();
            for (var i in rows)
            {
                var row = rows[i];          
                var User = row[0];
                var Status = row[1]
                    $('#output').append(''+
                    '<div class="small-3 large-2 columns "><img src="http://placehold.it/80x80&text=[img]" /></div>'+
                    '<div class="small-9 large-10 columns">'+
                        '<p><strong><a href="#">'+User+'</a>:</strong>'+Status+'</p>'+
                        '<ul class="inline-list">'+
                            '<li><a href="">Reply</a></li>'+
                            '<li><a href="">Share</a></li>'+
                        '</ul><hr>');
            } 
        } 
    });       
  });
 }, 1000);

并且这个调用:

 include "../PHP/Database.php";
    $Array = array();

        $Query = $DB->prepare("SELECT UserID, Text FROM statuses Order BY ID DESC");
        $Query->execute();
        $Query->bind_result($ID, $Text);
        $Query->store_result();
        while($Query->fetch()){
            $Second_Query = $DB->prepare("SELECT Username FROM users WHERE ID=?");
            $Second_Query->bind_param('i',$ID);
            $Second_Query->execute();
            $Second_Query->bind_result($Username);
            $Second_Query->fetch();
                $Array[] = array ($Username, $Text);
            $Second_Query->close();         
        }
        $Query->close();

如何在按下按钮后将文本区域附加到HTML div中,以便我的脚本不必等待新发布状态的响应?


更新。当按钮提交时,它调用以下代码:

$(function () {
    $('input').on('click', function () {
        var Status = $(this).val();
        $.ajax({
            url: 'Ajax/StatusUpdate.php',
            data: {
                userid: $("input[name=UserID]").val(),
                text: $("textarea[name=Status]").val(),
                Status: Status
            },
            dataType : 'json'

        });
    });
});

处理ajax输入


2
侧记:建议不要在HTML代码中混合使用单引号和双引号。 - Raptor
如果您不想等待xhr请求的响应,请在调用之前附加div。如果您选择这种方法,则应该有一个指示正在请求数据的标志。 - BingeBoy
嗨,Sophie,您的代码中有语法错误。缺少一个结束花括号:$(function(){ $('input').on('click',function(){ var Status = $(this).val(); $('#output').append(Status); } }); - Babak Bandpay
你有没有其他按钮能正常工作? - Daryl Gill
可能只是服务器错误。 - bren
显示剩余5条评论
12个回答

7

Sophie.

首先,看这段代码。

window.setInterval(function()
{
  $(function () 
  {
      ...   
  });
 }, 1000);

我猜这是jQuery :) 这段代码的意思是:

闭合一个段落标签。
$(function() { somecode(); }); 

当DOM达到“ready”状态时,用于执行somecode()。这意味着 - somecode()仅在文档的“ready”事件上执行一次,并且setInterval在此处只绑定函数执行以进行该事件。

您应该使用此结构:

$(function () 
{
    window.setInterval(function()
    {

        somecode();

    }, 1000);
});

第二点:

include "../PHP/Database.php";
 $Array = array();
        $Query = $DB->prepare("SELECT UserID, Text FROM statuses Order BY ID DESC");
        $Query->execute();
        $Query->bind_result($ID, $Text);
        $Query->store_result();
        while($Query->fetch()){
            $Second_Query = $DB->prepare("SELECT Username FROM users WHERE ID=?");
            $Second_Query->bind_param('i',$ID);
            $Second_Query->execute();
            $Second_Query->bind_result($Username);
            $Second_Query->fetch();
                $Array[] = array ($Username, $Text);
            $Second_Query->close();         
        }
        $Query->close();

这实际上不发送任何响应。如果这是所有的代码,那么你应该加上

标签。
echo json_encode($Array); 

至少,要得到任何回应。
第三点:
$.ajax({  
    url: 'Ajax/AjaxStatuses.php', data: "", dataType: 'json', ....

dataType: 'json'表示从服务器发送有效的JSON字符串,否则"success"函数将不会执行。

如果这不能帮助你,你应该检查所有的数据流以找到它们中断的地方。使用浏览器中的开发者控制台来查看ajax请求中从服务器接收到的内容以及即将发送到服务器的内容,以定位问题,然后您将能够轻松地解决问题。

另外,我有一些建议可以让您的代码更加清洁:

尝试为像这样的元素制定更具体的选择器:

$('input').on('click', function () {

只需为相应的输入添加id属性(或class属性,如果有多个按钮),并将其设置为以下内容:
$('#id').on('click', function () { ...

或者

$('.class').on('click', function () { ...

同时,尝试提取以下内容:
<input type='hidden' name='UserID' value="<?=$_SESSION['UserID']; ?>">

如果这段代码不在表单中或者你使用ajax,它将会脱离HTML结构。我看到你在js中使用了UserID,因此更好的解决方案是

<script type="text/javascript">
   var UserID = "<?=$_SESSION['UserID']; ?>";
</script>

请注意,这种方法比较好,但并不是最优的。可以在谷歌上搜索“如何从php传递变量到js”以获取更优的解决方案。

另外一个建议:尽可能使用单个SQL请求从数据库中获取数据。例如:

"SELECT UserID, Text FROM statuses Order BY ID DESC" 

并且。
"SELECT Username FROM users WHERE ID=?" 

你可以替换为:

"SELECT statuses.UserID, statuses.Text, users.Username
FROM statuses 
INNER JOIN users ON users.ID = statuses.UserID
Order BY ID DESC" 

这将通过减少数据库请求的数量来提高性能。

2
当您调用 statusupdate 查询时,应返回以 JSON 编码的用户和状态,然后在您的函数 JQuery 中使用回调函数解码 JSON 并添加到您的 div 中。
1)在 statusupdate.php 中:
return json_encode('status:{'.$Array.'});

2) JQuery中的回调函数

$.ajax{(
)}.done(function(status) {
  var status = jQuery.parseJSON(status);
  Userstatus = status.text;
  UserName = status.username;
});

3)$('#output').append('<div class="status"><span>'+用户+':</span><a href="#">'+用户名+'<span><strong>'+用户状态+'</strong></span></div>');


2

你需要setInterval做什么?

简单回答你的问题。要将textarea添加到div中,你需要将click事件绑定到按钮上。如果你想轻松实现,可以像这样编写:

<script>
$(function (){
  $("#btn_append").click(function (){
     //$("#output").html($("#mytext").val()); //overwrite text
     $("#output").append($("#mytext").val()); //append text
  });
});
</script>
<input type="button" id="btn_append" value="append" />
<textarea id="mytext"></textarea>
<div id="output"></div>

请查看document ready(文档就绪)函数$(function (){})。我已经在开头声明了它,而你在setInterval中声明了多次。你还需要注意命名规则,因为你的名称相似,这使得代码难以调试。
你提到了延迟(delay)。显然由于这些是异步方法,因为 AJAX 是这样的。你可以始终进行同步调用,只需要通过参数async:false传递给$.ajax();,但我不建议这么做。

2

数据库会返回多少状态?

我假设您已有正确的代码(将此前在这里发布的答案结合起来),但仍然存在延迟。这可能是由于 setInterval 中发出的 ajax 调用造成的 - 在将新状态附加到 #output 后,它被先前触发的请求覆盖了。

为防止这种情况,您可以在单击按钮时中止 xhr 请求并清除间隔函数:

$(function(){


    // interval reference and jQuery XHR object
    var ajaxInterval, jqxhr;

    // initialize fetching data from server
    function startPolling() {
        stopPolling();
        ajaxInterval = setInterval( function() {
            jqxhr = $.ajax({                                      
                url: location.href, 
                data: {ajax: 1}, 
                dataType: 'json',  
                type: "GET",
                success: function(result)        
                {
                    // parse result and insert into #output
                    // ...
                } 
            });     
        }, 1000);
    }

    // clear interval and abort xhr request
    function stopPolling() {
        if(ajaxInterval)
            clearInterval(ajaxInterval);
        if(jqxhr)
            jqxhr.abort();
    }


    $('input').click(function(){

        // this prevents overwriting from old ajax call
        stopPolling();

        // insert into #output our new status
        var getText=jQuery("[name='Status']").val();
        $('#output').append('<div>'+getText+'</div>');

        // post status into server
        $.ajax({                                      
            url: location.href, 
            data: {ajax: 1, status: $("[name='Status']").val()}, 
            dataType: 'json',  
            type: "POST",
            success: function(result)        
            {
                // parse result and insert into #output here
                // ...

                // restart fetching data
                startPolling();
            } 
        });     
    });

    // start fetching data
    startPolling();
});

这是一个简单的JavaScript演示(包含可工作的xhr请求)在phpfiddle上: http://phpfiddle.org/lite/code/hn0-0e1 但我想知道每个请求中会获取多少状态。存储已获取的状态并仅加载比我们已有的最后一个状态更新的状态是否更好?就像Facebook一样 - 当您打开自己的墙时,它不会每X秒重新加载整个墙,而只是获取自上次调用以来添加的状态。
这只是一个快速的想法:
$(function(){


    // interval reference and jQuery XHR object
    var ajaxInterval, jqxhr;
    var statuses = [];

    // initialize fetching data from server
    function startPolling() {
        stopPolling();
        ajaxInterval = setInterval( function() {

            // get the newest stored id
            var lastStatusId = 0;
            if(statuses.length)
                lastStatusId = statuses[0].id;

            jqxhr = $.ajax({                                      
                url: location.href, 
                data: {ajax: 1, lastStatusId: lastStatusId}, 
                dataType: 'json',  
                type: "GET",
                success: function(result)        
                {
                    if(result.updateStatuses) {
                        // prepending the latest statuses to our variable
                        statuses = result.statuses.concat(statuses);
                        // merge repaint output
                        displayStatuses();
                    }
                } 
            });     
        }, 1000);
    }

    // clear interval and abort xhr request
    function stopPolling() {
        if(ajaxInterval)
            clearInterval(ajaxInterval);
        if(jqxhr)
            jqxhr.abort();
    }


    function displayStatuses() {
        var $output = $('#output');
        $output.empty();

        // parse statuses array of objects and 
        // insert the result in the #output
        // ...
    }


    $('input').click(function(){

        // this prevents overwriting from old ajax call
        stopPolling();

        // insert into #output our new status
        var getText=jQuery("[name='Status']").val();
        $('#output').append('<div>'+getText+'</div>');

        // get the newest stored id
        var lastStatusId = 0;
        if(statuses.length)
            lastStatusId = statuses[0].id;

        // post status into server
        $.ajax({                                      
            url: location.href, 
            data: {ajax: 1, status: $("[name='Status']").val(), lastStatusId: lastStatusId}, 
            dataType: 'json',  
            type: "POST",
            success: function(result)        
            {
                if(result.updateStatuses) {
                    // prepending the latest statuses to our variable
                    statuses = result.statuses.concat(statuses);
                    // merge repaint output
                    displayStatuses();
                }

                // restart fetching data
                startPolling();
            } 
        });     
    });

    // start fetching data
    startPolling();
});

所以你的 PHP 代码应该像这样:
    $Query = $DB->prepare("SELECT Statuses.ID, Text, Username FROM statuses, users WHERE Username.ID = statuses.UserID AND statuses.ID > ? ORDER BY Statuses.ID DESC");
    $Query->bind_param('i',intval($_REQUEST['lastStatusId']));
    $Query->execute();
    $Query->bind_result($ID, $Text, $Username);
    $Query->store_result();
    $Array = array();
    while($Query->fetch()){
         $Array[] = array ('id'=>$ID,'username'=>$Username, 'text'=>$Text);
    }
    $Query->close();

    // are there any new statuses?
    $result['updateStatuses'] = false;
    if( count($Array) )
        $result['updateStatuses'] = true;

    $result['statuses'] = $Array;
    echo json_encode($Array);

2

我已经从你的代码中制作了工作演示,希望它能解决你的问题。无论如何,我建议你花点时间阅读关于jQuery和JavaScript编码风格的内容。

首先,我们将修复代码,以便在单击按钮后更新状态:

<!-- TEXTAREA that we will update --> 
<textarea name='Status'> </textarea>

<!-- I didn't saw output DIV in your code. It should be present in HTML -->
<div id='output'></div>

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

<script>

 $(function(){

   // 1. Update on click:
   $('input').on('click', function () {

       var Status = $(this).val();

       // append content to the DIV
       $('#output').append(Status);

       // save content to the TEXTAREA
       $('textarea').val(Status);
   });

 }

</script>

您的AJAX请求代码看起来也还不错,几乎能够工作。我对其进行了一些更改:

<textarea id='status' name='Status'> </textarea>
<div id='output'></div>
<input type='button' value='Status Update'>

<script id="AjaxStatusesTemplate" type="text/template">

  <div class="small-3 large-2 columns ">
    <img src="http://placehold.it/80x80&text=[img]" />
  </div>
  <div class="small-9 large-10 columns">
      <p><strong><a href="#">{{User}}</a>:</strong>{{Status}}</p>
      <ul class="inline-list">
          <li><a href="">Reply</a></li>
          <li><a href="">Share</a></li>
      </ul>
      <hr/>
   </div>

</script>

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

<script>

    // 2. Update by timer with 1 second delay: 
    function UpdateOutputWithAjaxStatuses(){
        var htmlTemplate = $('#AjaxStatusesTemplate').html();
        $.ajax({ url: 'http://your-server.com/Ajax/AjaxStatuses.php', data: '', dataType: 'json',
          success: function(rows){
            $('#output').empty();
            for (var i=0, row=rows[i]; i<rows.length;i++)
            {     
              var User = row[0];
              var Status = row[1];

              var html = htmlTemplate
                           .replace('{{User}}', User)
                           .replace('{{Status}}', Status);

              $('#output').append(html);
            } 
          },
          error: function(){
              var now = new Date();
              $('#output').html('error at '+now);
          },
          complete: function(){
            setTimeout(UpdateOutputWithAjaxStatuses, 1000);
          }
        });       
    }

    // comment next line to stop autostart for ajax request scheduler
    UpdateOutputWithAjaxStatuses();

</script>

您可以在这里找到工作示例:http://jsfiddle.net/vmysla/XWuDf/6/

(您应该更改 AJAX 请求的 URL 以使它们正常工作)


2
似乎缺少$('#output')。请将其添加到您的HTML中:
<div id="output"></div>

如果出现这种情况,您会注意到开发者控制台中存在一个JavaScript错误。

在开发者控制台中是否有JavaScript错误?$('#output')是否在jQuery加载后初始化?提示:使用document.ready - Raptor
你能再解释一下吗?$('#output') 是被初始化的,这是在我的ajax调用中要追加的内容。 - Sophie Mackeral
尝试使用 console.log($('#output')。它是否未定义?将所有 jQuery 代码用 document.ready 包围起来。 - Raptor

2

您似乎没有读取正确的数据进行追加。您正在从输入元素中读取,但应该从文本区域中读取。

看一下这个,非常基础: http://jsfiddle.net/ABFV9/

所以您想要通过以下方式从文本区域中获取提交的数据:

var getText=jQuery("[name='Status']").val();

这不会附加到我的输出。请阅读注释,我认为这与ajax刷新有关。 - Sophie Mackeral
它附加到元素#output。我觉得我在这里没有理解到什么。 - bouscher
正如我所说,我有一个使用 window.setInterval 的常量 AJAX 调用,它会附加到同一个 DIV。因此,我认为问题就出在这里。 - Sophie Mackeral
正如你在我的fiddle中所看到的,你可以通过反复调用$('#output').append来添加任意数量的内容。我想告诉你的是,在你上面的脚本中,你调用了var Status = $(this).val(); 这里的'this'指的是输入元素,它没有值,而不是文本区域。 - bouscher
我已经告诉你这还有一点延迟。请查看http://pastebin.com/PExM7wjZ以获取我的代码设置。 - Sophie Mackeral

2
不要让表格在"点击"时自动提交(您可以从表格属性中删除操作字段)。让AJAX调用发生,并在ajax调用的成功回调函数中添加$("#YourFormIdHere").submit();作为最后一行(在此处的for循环之外)。这应该能够正常工作。

这并不使用提交。HTML输入甚至不在<form>标签中,因为它是通过ajax/json进行排序的。 - Sophie Mackeral
好的,它们不需要以表格形式存在。您可以始终使用$('#<your wrapping div>').serialize();来获取所有HTML输入的帖子格式值。然后通过将serialize()的结果分配给data字段来在AJAX中发送它。 - Archer

2
您确定您在同步或异步AJAX请求之间使用了正确的请求类型吗?
  • 使用同步请求,您正在等待服务器的回复。因此,在某些情况下可能会超时并且没有响应。
  • 使用异步请求,您不必等待回复。响应将在服务器回复时处理。
请查看此其他帖子:jQuery:执行同步AJAX请求 希望这可以帮助到您。

1
抱歉,如果我误解了您的问题,但这对我来说似乎相对容易。在#output中,有另一个包含状态的div...就像这样:
<div id = "output">
    <div id="statuses">
    ...
    </div>
<textarea name='Status'> </textarea>
<input type='hidden' name='UserID' value="<?=$_SESSION['UserID']; ?>">
<input type='button' value='Status Update'>
</div>

然后,在这里。
window.setInterval(function()
{
  $(function () 
  {
    $.ajax({                                      
        url: 'Ajax/AjaxStatuses.php', data: "", dataType: 'json',  success: function(rows)        
        {
        $('#output').empty();
        for (var i in rows)
        {
            var row = rows[i];          
            var User = row[0];
            var Status = row[1]
            $('#output').append(''+
                '<div class="small-3 large-2 columns "><img src="http://placehold.it/80x80&text=[img]" /></div>'+
                '<div class="small-9 large-10 columns">'+
                    '<p><strong><a href="#">'+User+'</a>:</strong>'+Status+'</p>'+
                    '<ul class="inline-list">'+
                        '<li><a href="">Reply</a></li>'+
                        '<li><a href="">Share</a></li>'+
                    '</ul><hr>');
        } 
    } 
});       
});
}, 1000);

$('#output').empty(); 改为 $('#statuses').empty();,这样你就不会在第一次删除文本区域! :D
此外,查看 QArea 的帖子,因为您的语法中还有其他错误。 :D 如果您需要更多帮助,或者我误解了问题,请在评论中告诉我 :)
干杯
Pranay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接