简体   繁体   中英

onclick append textarea to div

I currently have an ajax call after a user presses a button on my web page..

The problem is, that after submitting, there is a slight delay (as a second ajax call needs to complete to show the DIV) to avoid a slight lag.. I was wondering if it was possible to append the content to a 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>

The above is my current code configuration. Now, this does not work as expected. It does not add the submitted content to the DIV.. here is how it's displayed through my ajax call:

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

and the call:

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

How do I append the text area to a HTML div after pressing the button so my script doesn't have to wait for a response from the newly posted status?


Update. When the button is submitted it calls the following code:

$(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'

        });
    });
});

To handle the ajax input

Sophie.

First, look at this snippet.

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

I guess this is jQuery:) This construction

$(function() { somecode(); }); 

serves to execute somecode(); when DOM is reaches "ready" state. That means - somecode() will be executed only once, on document's "ready" event, and setInterval here just binds functions execution for that event.

You should use this construction instead:

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

        somecode();

    }, 1000);
});

Second:

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

This, actually, doesn't send any response. If this is all code, then you should add

echo json_encode($Array); 

at least, to get any response.

Third:

$.ajax({  
    url: 'Ajax/AjaxStatuses.php', data: "", dataType: 'json', ....

dataType: 'json' means, that you should send a valid JSON string from server, if not - "success" function will not execute.

If this doesn't help , you should check all data flows to find place where they are broken. Use developer console in your browser to see what is going to server and from server in ajax requests to locate the problem, and then you will be able to easily fix the problem.

Also i have some advices for you to make your code more clean:

Try to make more specific selectors for things like this:

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

Just add an id (or class, if you have many buttons) attribute for corresponding input, and make that like:

$('#id').on('click', function () { ...

or

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

Also)) Try to extract things like:

<input type='hidden' name='UserID' value="<?=$_SESSION['UserID']; ?>">

out of HTML structure, if this is not inside the form or you use ajax. I see, that you use UserID in js, so better solution here will be

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

Notice, that this is just better, but not optimal ofcourse. Google for "pass variable from php to js" and choose optimal solutions:)

And the last: Try to make single SQL requests to get data from DB. For example:

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

and

"SELECT Username FROM users WHERE ID=?" 

you can replace with:

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

This will improve performens by decreasing the amount of DB requests.

Seems the $('#output') is missing . Add to your HTML :

<div id="output"></div>

You will note that there is an JavaScript error in Developer Console if it is the case.

You don't seem to read the correct data to append. You are reading from the input element, but you should be reading from the textarea.

Have a look at this, just very basic: http://jsfiddle.net/ABFV9/

So what you want is to get the submitted data from the textarea by:

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

Don't let the form submit automatically "on click" (You can remove the action field from the form attributes). Let the AJAX call happen and add $("#YourFormIdHere").submit(); as the last line of your success callback function in the ajax call (Out side your for loop here). It should work.

When you calling statusupdate queries you should return user and status encoded in JSON, then a callBack in you function JQuery allows to decode JSON and append into your div

1) in statusupdate.php

return json_encode('status:{'.$Array.'});

2) callBack in JQuery

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

3) $('#output').append('<div class="status"><span>'+User +':</span><a href="#">'+UserName+'<span><strong>'+Userstatus+'</strong></span></div>');

Are you sure you are using the right type of request between synchronous or asynchronous AJAX requests ?

  • With synchronous requests you are waiting for the reply of the server. So in some cases you might timeout and have no response.
  • With asynchronous requests you are not waiting for the reply. The response will be handle when the server reply.

Check this other post : jQuery: Performing synchronous AJAX requests

Hope that helps.

What do you need setInterval for?

Answering your question as simple as I can. To append textarea to div you need bind click event to button. If you want to do it easily you can write like this:

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

Take a look at document reaady function $(function (){}) I've declared it in the begining, and you in your setInterval declare it multiple times. You need also take a look at naming convention because your names are similar to each other and that makes the code hard to debug.

You wrote about delay. It's obvious that there is delay because these are Asynchronous methods as AJAX stands. You can always make Synchronous call, you just need to pass to $.ajax(); param async:false but I don't recommend it.

How many statuses are returned from the database?

I assume that you have correct code (combining the previous answers that have been posted here) and still the delay is present. It can be caused by the ajax call made in the setInterval - after you append the new status into the #output it's overwritten by an request that had been triggered before the click event.

To prevent that you can abort the xhr request and clear the interval function when clicking the button:

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

Here is a simple demo of that javascript (with working xhr requests) on the phpfiddle: http://phpfiddle.org/lite/code/hn0-0e1

But I'm wondering how many statuses will be fetched in each request? Wouldn't be better to store already fetched statuses in a variable and just load those that are newer than the last one we already have? Just like facebook does - when you have your wall opened it does not reload the whole wall each X seconds but just fetches statuses that have been added since previous call.

Just a quick idea:

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

So your php code should like something like this:

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

I did working demo from your code. Hope it may resolve your problem. Anyway i would recommend you spent little time to read about jQuery and JavaScript coding style.

First of all we will fix code that should update status after you click on button:

<!-- 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>

Your code that makes AJAX requests also looks not more-less fine, and was almost working. I did few changes into it:

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

You can find working examples here: http://jsfiddle.net/vmysla/XWuDf/6/

(You should change URL for AJAX requests to make them working)

There could be a number of issues here. I am going to start this answer with some debugging tips, then a list of places to check.

Some debugging tips:

  • throw some debugger; statements in your code
  • in chrome open up the developer tools and make your javascript go through that code path, eg click a button. The code will stop at debugger statements.
  • Investigate the values passed in and out of various functions. Confirm assumptions about various functions getting called and what information they are receiving.

Places to check:

  • make sure your ajax callbacks are actually being run. Your mime type from your server should be application/json. If your ajax callback isn't getting run its either a mime/response typing issue or a server failure of some sort.
  • make sure $('#output') returns something. Try opening up the chrome console and typing that in when you are paused using one of those debugger; statements. You should get back an HTML element.
  • Your updated code doesn't indicate to me that anything happens after the ajax call finishes. Is this intentional/ok? You should specify a success argument if you would like something to happen afterwards.

Pajax is easy solution to update content on page with ajax response, it will avoid lot of repeated steps, just check below links

Also consider using templates for html generation, they are beautiful and shorter way of filling html with json data

Well sorry if i've misunderstood your question, but this seems relatively easy to me. In #output, have another div that contains the statuses... like so:

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

Then, here

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

change $('#output').empty(); to $('#statuses').empty(); That way, you never remove the text area in the first place! :D

Also look at QArea's post since you've got a bunch of other errors in your syntax which has been covered there. :D If you need more help, pr if i misunderstood the question, lemme know in the comments :)

Cheers

Pranay

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM