Best ajax questions in May 2012

What does "return false;" do?

7 votes

I wrote a webpage where a user can enter a log entry that is stored on a database and then retrieved and printed on the page using ajax. I am still quite new to ajax and was wondering if somebody could please explain to me what does return false; do at the end of my code? and is it even necessary?

If I put the second ajax code after the return false the code does not work! can you please explain to me why?

//handles submitting the form without reloading page 
$('#FormSubmit').submit(function(e) {
    //stores the input of today's data
    var log_entry = $("#LogEntry").val();
    // prevent the form from submitting normally
    e.preventDefault();

    $.ajax({
        type: 'POST',
        url: 'behind_curtains.php',
        data: {
            logentry: log_entry
        },
        success: function() {
            alert(log_entry);
            //clears textbox after submission
            $('#LogEntry').val("");
            //presents successs text and then fades it out
            $("#entered-log-success").html("Your Entry has been entered.");
            $("#entered-log-success").show().fadeOut(3000);
        }
    });
    //prints new log entries on page upon submittion
    $.ajax({
        type: 'POST',
        url: '/wp-content/themes/childOfFanwood/traininglog_behind_curtains.php',
        data: {
            log_entries_loop: "true"
        },
        success: function(data) {
            alert(data);
            $("#log-entry-container").html("");
            $("#log-entry-container").html(data);
        }
    });
    return false;
});
​

What I'll write here is true for jQuery events,
For vanilla javascript events read @T.J. Crowder comment at the bottom of the answer


return false inside a callback prevents the default behaviour. For example, in a submit event, it doesn't submit the form.

return false also stops bubbling, so the parents of the element won't know the event occurred.

return false is equivalent to event.preventDefault() + event.stopPropagation()

And of course, all code that exists after the return xxx line won't be executed. (as with all programming languages I know)

Maybe you find this helpful:
Stop event bubbling - increases performance?


A "real" demo to explain the difference between return false and event.preventDefault():

Markup:

<div id="theDiv">
    <form id="theForm" >
        <input type="submit" value="submit"/> 
    </form>
</div>​

JavaScript:

$('#theDiv').submit(function() {
    alert('DIV!');
});
$('#theForm').submit(function(e) {
    alert('FORM!');
    e.preventDefault();
});​

Now... when the user submit the form, the first handler is the form submit, which preventDefault() -> the form won't be submitted, but the event bubbles to the div, triggering it's submit handler.

Live DEMO

Now, if the form submit's handler would cancel the bubbling with return false:

$('#theDiv').submit(function() {
    alert('DIV!');
});
$('#theForm').submit(function(event) {
    alert('FORM!');
    return false;   
    // Or:
    event.preventDefault(); 
    event.stopPropagation();
});​

The div wouldn't even know there were a form submittion.

Live DEMO


What does return false do in vanilla javascript events

return false from a DOM2 handler (addEventListener) does nothing at all (neither prevents the default nor stops bubbling; from a Microsoft DOM2-ish handler (attachEvent), it prevents the default but not bubbling; from a DOM0 handler (onclick="return ..."), it prevents the default (provided you include the return in the attribute) but not bubbling; from a jQuery event handler, it does both, because that's a jQuery thing. Details and live tests here – T.J. Crowder

When doing AJAX edit to the database, should I update the interface immediately with the new data

6 votes

I'm using inline-edit to update text in the database with AJAX. This is basically the process, pretty usual stuff:

  • text is not editable
  • I click the text, it becomes editable
  • I type the new text
  • then click to send the updated text to the database
  • then return the text to non-editable format

My question is when should I update the interface with the new data? Should I update it immediately before the ajax call, or should I wait for the update response to return from the database?

My concern:

  • If I don't update the interface immediately and wait to get the response from the database, then I've lost the asynchronous benefit that comes with ajax.
  • But if I update it immediately, then if the database response has an error, I somehow have to track the change I already made, and reverse it, which is a lot more work.

So how is this sort of thing usually done?

I think it is completely reasonable to wait for the response and update as a result of a callback. Doing so does not detract from the async approach. It is still fully async because you are not blocking the entire page or reloading it completely.

Plenty of times in apps, especially in mobile ones where the bandwidth might be limited, I will see a spinner indicating that the field is submitting. This does not hold up any other part of the app. Even stackoverflow does this when I use the mobile view. Rely on the callbacks in order to stay async and still be synced to database return values.

AJAX IRCX Client and Server

5 votes

I am currently developing an IRCX AJAX Chat based system and have a few questions regarding the Server and Client implementation; Any suggestions are welcome:

Server

Should this be implemented as a Web Service, or a Windows Form application? I have experience in developing Windows Forms based servers, however I am wondering if this would be better implemented as a Web Service and if so, why?

Client

How are Web Based Clients implemented today and what is the preferred method to implement a Web Based Client?

My solution so far are

  • ASP.NET Web Forms with an AJAX Update Panel (This seems the most viable)
  • Using jQuery connecting to the web service with a JavaScript timeout

Polling

How frequently should the server be polled for new messages? 0.5 seconds seems a bit excessive and anything between 2 or 3 seconds seems sluggish.

Thanks for your input.

I believe using ASP.NET (Sockets and an Update Panel) seems to be the best approach. Using jQuery in this context now seems a bit invalid because it would not maintain a persistent state with the Chat Server which is required for Real Time Communication.

An alternative way I found would be using a Web Sockets and Backbone.JS to deal with the data returned from the server.

http://blog.fogcreek.com/the-trello-tech-stack/

Server-side processing with pipelining

4 votes

By default this function works with $_GET. Based on this discussion I modified this function and got something like below. Now the problem is, Firebug gives error message

json.aaData is undefined @ line 99

Here is line (located at the end of code)

json.aaData.splice( 0, iRequestStart-oCache.iCacheLower ); 

PHP side responds, and this table works 100% without pipelining. But When I enable pipelining getting this error

http://screencast.com/t/GOJzPHq3kg

function fnDataTablesPipeline ( sSource, aoData, fnCallback ) {
    var iPipe = 5; /* Ajust the pipe size */

    var bNeedServer = false;
    var sEcho = fnGetKey(aoData, "sEcho");
    var iRequestStart = fnGetKey(aoData, "iDisplayStart");
    var iRequestLength = fnGetKey(aoData, "iDisplayLength");
    var iRequestEnd = iRequestStart + iRequestLength;
    oCache.iDisplayStart = iRequestStart;

    /* outside pipeline? */
    if ( oCache.iCacheLower < 0 || iRequestStart < oCache.iCacheLower || iRequestEnd > oCache.iCacheUpper )
    {
        bNeedServer = true;
    }

    /* sorting etc changed? */
    if ( oCache.lastRequest && !bNeedServer )
    {
        for( var i=0, iLen=aoData.length ; i<iLen ; i++ )
        {
            if ( aoData[i].name != "iDisplayStart" && aoData[i].name != "iDisplayLength" && aoData[i].name != "sEcho" )
            {
                if ( aoData[i].value != oCache.lastRequest[i].value )
                {
                    bNeedServer = true;
                    break;
                }
            }
        }
    }

    /* Store the request for checking next time around */
    oCache.lastRequest = aoData.slice();

    if ( bNeedServer )
    {
        if ( iRequestStart < oCache.iCacheLower )
        {
            iRequestStart = iRequestStart - (iRequestLength*(iPipe-1));
            if ( iRequestStart < 0 )
            {
                iRequestStart = 0;
            }
        }

        oCache.iCacheLower = iRequestStart;
        oCache.iCacheUpper = iRequestStart + (iRequestLength * iPipe);
        oCache.iDisplayLength = fnGetKey( aoData, "iDisplayLength" );
        fnSetKey( aoData, "iDisplayStart", iRequestStart );
        fnSetKey( aoData, "iDisplayLength", iRequestLength*iPipe );

        jQuery.post( sSource, aoData, function (data) { 
            /* Callback processing */
            oCache.lastJson = jQuery.extend(true, {}, data);

            if ( oCache.iCacheLower != oCache.iDisplayStart )
            {
                data.aaData.splice( 0, oCache.iDisplayStart-oCache.iCacheLower );
            }
            data.aaData.splice( oCache.iDisplayLength, data.aaData.length );

            fnCallback(data)
        },"json" );
    }
    else
    {
        json = jQuery.extend(true, {}, oCache.lastJson);
        json.sEcho = sEcho; /* Update the echo for each response */
        json.aaData.splice( 0, iRequestStart-oCache.iCacheLower ); // <- this line
        json.aaData.splice( iRequestLength, json.aaData.length );
        fnCallback(json);
        return;
    }
}

What am I missing? Any suggestion?

json gets its properties, inside fnDataTablesPipeline(), from oCache.lastJson but only if bNeedServer is true.

If fnDataTablesPipeline() has never been called or has been called but bNeedServer remained false, then the line oCache.lastJson = jQuery.extend(true, {}, data); will not have been executed and json.aaData.splice() will fail.

You need to handle the case that oCache.lastJson is not populated (or only partially populated) either:

  • by initialising oCache.lastJson with default properties
  • by testing for the existence of properties before trying to use them and acting accordingly,

For example:

else{
    if(oCache.lastJson.aaData) {
        json = jQuery.extend(true, {}, oCache.lastJson);
        json.sEcho = sEcho; /* Update the echo for each response */
        json.aaData.splice( 0, iRequestStart-oCache.iCacheLower );
        json.aaData.splice( iRequestLength, json.aaData.length );
        fnCallback(json);
    }
}

I can't tell whether this is 100% correct. You may need to put less inside the if clause, for example it may be appropriate to suppress only the two lines starting json.aaData.splice....

Ajax Request - Call different method on Spring Controller

4 votes

I've been having a problem regarding using AJAX with Spring MVC. I have a form which has a lot of fields, and each field retrieves data depending on the associated button that was clicked.

So, each one of my buttons needs to call an AJAX request. Each response will be displayed on the associated field.

I wonder if it is possible to call a different method in my Spring controller once I clicked on a different button?

In other words, I want to make multiple ajax requests to the same controller where each request will call a different method in that same controller.

See this example :

    // when get account detail is clicked it will call this method  
@RequestMapping(method=RequestMethod.POST)  
    public @ResponseBody String getAccountDetails(@RequestParam(value="accountid") String accountid){  

     return somefunct.getAccountDetails(accountid);  

    }  



// when get account summary is clicked it will call this method  
@RequestMapping(method=RequestMethod.POST)  
    public @ResponseBody String getAccountSummary(@RequestParam(value="accountid") String accountid){  

      return somefunct.getAccountSummary(accountid);  

    }  



/* when submit button is clicked... Form is submitted for saving*/  
@RequestMapping(method=RequestMethod.POST)  
    public String submitForm(){  
        // save here  
        return "myform";  
    };*/  

Currently, I can have only one AJAX request. How can I modify this code so that I can have different functionality for different AJAX requests?

First, consider that when you retrieve data from a server without modifying the state of that server, the commonly accepted standard is to use the HTTP GET method, not POST. Thus, for your first two methods, you are misusing the HTTP Methods.

Second, you can map individual URL patterns to a specific method using the value property of the RequestMapping annotation.

Third, the most RESTful way to represent your account details resource is to use the PathVariable annotation and include your identifying accountid in the actual path:

@RequestMapping(value="/account/{accountid}/details", method = RequestMethod.GET)
public @ResponseBody String getAccountDetails(@PathVariable(value="accountid") String accountid){  

 return somefunct.getAccountDetails(accountid);  

}  

Next, you can represent your account summary using a different URL pattern where the URL is built like a tree, where the first two parts of the path are once again "Account" and the accountid:

// when get account summary is clicked it will call this method  
@RequestMapping(value="/account/{accountid}/summary", method=RequestMethod.GET)  
public @ResponseBody String getAccountSummary(@PathVariable(value="accountid") String accountid){  

    return somefunct.getAccountSummary(accountid);  

}  

Now, your submit method, on the other hand, has side effects. This is just a fancy way of saying that the state of your server will be different at the end of this request, and any GET requests made to that resource will be different than they were prior to the change. The appropriate HTTP method to use when modifying a resource or adding a resource to a collection is the HTTP POST Method. When replacing a collection, the HTTP Method PUT is the generally accepted method of choice.

Another differentiating factor between PUT and POST is that PUT is idempotent, meaning that the same request repeated over and over again doesn't change the state on the server. If hitting the same request multiple times creates more records, then use POST.

Lastly, this request can be mapped to a URL as well. In the example below, I've assumed you are creating a new Account record and inserting a new record in the collection of accounts in the database. Thus, I've used POST. I also modified your parameter list to use PathVariable to take the accountid from the URL path, and I added a RequestBody annotation so that you can send an object in the body of the request, which could be deserialized into a Java object:

/* when submit button is clicked... Form is submitted for saving*/  
@RequestMapping(value="/account/{accountid}", method=RequestMethod.POST)  
    public String submitForm(@PathVariable String accountid, @RequestBody Account account){  
        // save here  
        return "myform";  
}

For more information on Spring MVC, please check out the Spring documentation on Spring MVC.

Having trouble with undefined !== undefined

4 votes

I'm trying to process a complete function in an ajax call. If the value is undefined, I want cast a var as an empty string. Otherwise, I would like to capture the value into a string array.

The problem is I'm entering the if statement, even when logging the value of the variable in question returns as undefined. What am I missing here?

completefunc: function (xData, Status) {
      $(xData.responseXML).SPFilterNode("z:row").each(function() {
        if(typeof $(this).attr("ows_Products") !== undefined) {
          console.log($(this).attr("ows_Products"));
          arr = $(this).attr("ows_Products").split(',');
        }
        else {
          arr = "";
        }
      });
    }

typeof returns a string value, so you'll need to compare with "undefined" as a string. E.g.,

if(typeof $(this).attr("ows_Products") !== "undefined") { ... }

Edit - more info:

If you check out the MDN page for typeof, you'll see this:

The typeof operator returns a string indicating the type of the unevaluated operand.

This is very different from returning the Type itself (which in JavaScript would probably be something like returning a constructor function like String, Array, etc.). Therefore, when using typeof, you'll always be comparing to strings like "object", "string", "undefined", etc.

how to delete database row in example below?

4 votes

I have a cancel button where the user can cancel on a file upload and it will display a cancel message. Now what I want also to happen is that when the user clicks on the Cancel button, it will look up for the file name which has been cancelled in the database and delete the database row. Problem is that it is not deleting the database row at all. How can I get this to happen. At the moment I am using the jpuery.ajax method which you can see in code below.

Below is form code:

var $fileImage = $("<form action='imageupload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='return imageClickHandler(this);' class='imageuploadform' >" + 

 "Image File: <input name='fileImage' type='file' class='fileImage' /></label><br/><br/><label class='imagelbl'>" + 

 "<input type='submit' name='submitImageBtn' class='sbtnimage' value='Upload' /></label>" + 

 "</p><p class='imagef1_cancel' align='center'><label>" + 

 "<input type='button' name='imageCancel' class='imageCancel' cancel_image_file_name='" + imagefilename + "' value='Cancel' /></label></form>"); 

Below is the cancel button function:

    $('.imagef1_cancel').eq(window.lastUploadImageIndex).find(".imageCancel").on("click", function(event) {

        var cancel_image_file_name = $(this).attr('cancel_image_file_name');

    jQuery.ajax("cancelimage.php?imagefilename=" + cancel_image_file_name)

    return stopImageUpload(2, cancel_image_file_name);

});

Finally below is the cancelimage.php script where the jquery.ajax navigates to, to supposedly be able to delete the the database row containing the file name:

 <?php

...

    //I have connected to database

    $cancel_image_file_name = $_GET["imagefilename"];

            $imagecancelsql = "DELETE FROM Image 
            WHERE ImageFile = 'ImageFiles/". mysql_real_escape_string($cancel_image_file_name)."'";

        mysql_query($imagecancelsql);

        mysql_close();


    ?>

UPDATE:

Below is what it currently shows when I echo the delete query:

Notice: Undefined index: imagefilename in /web/stud/xxx/.../cancelimage.php on line 19 DELETE FROM Image WHERE ImageFile = 'ImageFiles/'

Below is the code of the delete function where when the Delete Button is pressed, it will navigate to the deleteimage.php script and delete the database row:

function stopImageUpload(success, imagefilename){

         $('.listImage').eq(window.lastUploadImageIndex).append('<div>' + htmlEncode(imagefilename) + '<button type="button" class="deletefileimage" image_file_name="' + imagefilename + '">Remove</button><br/><hr/></div>'); 

$('.listImage').eq(window.lastUploadImageIndex).find(".deletefileimage").on("click", function(event) {
    var image_file_name = $(this).attr('image_file_name');

    jQuery.ajax("deleteimage.php?imagefilename=" + image_file_name)

    $(this).parent().remove();
});

      return true;   
}

Below is deleteimage.php script:

<?php

//connected to DB

  $image_file_name = $_GET["imagefilename"];

        $imagedeletesql = "DELETE FROM Image 
        WHERE ImageFile = 'ImageFiles/". mysql_real_escape_string($image_file_name)."'";

    mysql_query($imagedeletesql);

    mysql_close();


?>

Below is an UPDATE of what the cancel button function now looks like:

function startImageUpload(imageuploadform, imagefilename){
            $('.imagef1_cancel').eq(window.lastUploadImageIndex).find(".imageCancel").on("click", function(event) {

var cancel_image_file_name_ = $(this).attr('css');
var cancel_image_file_name = '';
var style_array = cancel_image_file_name_.split(" ");
for(i=0;i<style_array.length;i++){
    if(style_array[i].substr(0,2) == "__"){
     cancel_image_file_name = style_array[i].slice(2,style_array[i].length-2);
}

}

    jQuery.ajax("cancelimage.php?imagefilename=" + cancel_image_file_name)

    return stopImageUpload(2, cancel_image_file_name);

});       
      return true;
}

I changed the button input tag to this for cancel button:

<input type='button' name='imageCancel' class='imageCancel __"+ imagefilename + "' value='Cancel' />

Try these changes:

on form:

<input type='button' name='imageCancel' class='imageCancel __"+ imagefilename + "' value='Cancel' /></label></form>

on cancel button function:

var cancel_image_file_name_ = $(this).attr('class');
var cancel_image_file_name = '';
var style_array = cancel_image_file_name_.split(" ");
for(i=0;i<style_array.length;i++){
    if(style_array[i].substr(0,2) == "__"){
     cancel_image_file_name = style_array[i].slice(2,style_array[i].length);
}

}

Dynamically generated images, fetched using POST

4 votes

I need to dynamically load images inside a JSP. I've tried the <img src="servletUrl?p1=x&p2=y"/>, but the problem is that the URL is too long to be sent using GET.

I'm now performing a POST call. From the servlet I'm generating a pie chart image, based on the params I send. The image is not persisted, so I can't return something like "images/image1.jpg" and set that as src of the image.

So I'm returning the image as a byte array and setting the appropriate image content type.

My question is: once I have the image bytes in javascript, how do I display them in the corresponding img tag?

This is my AJAX call:

new Ajax.Request(url, {
        method: 'post',
        parameters: params,
        onComplete: function(request) {
                    alert(request.responseText);      
        }
});

I haven't try this my self but it should work. You could create an image and set its src using a dataUrl. You will have to convert the byte[] in to a base64 encoded string for this to work.

new Ajax.Request(url, {
        method: 'post',
        parameters: params,
        onComplete: function(response) {
            var img = new Image();
            img.src = "data:image/png;base64," + response;

            document.body.appendChild(img);
        }
});

Where data sort should be done ? Server or client?

4 votes

I get from a server some datas that I display using GWT on client.

GWT is not the problem here, you can replace GWT by ajax calls or you can transpose it to a real application instead of a web app.

Where the sort action should be done ? On server ? or on client using javascript, after receiving the datas and before displaying them ?

Each approach has its pros and cons:

  • If you need pagination, and don't want to download the entire data to the client, then you must perform the sorting on the server (otherwise the client can only sort the rows it currently has, which will lead to wrong results, if you re-sort by a different column)
  • Sorting on the server is faster (as in: you can sort more rows/second), but if you have to serve 10000 clients at once, this may easily invert.
  • When sorting on the client, you can re-sort without downloading the data again.

preload image with ajax

4 votes

Found this technique of using ajax to preload things at: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

window.onload = function() {
    setTimeout(function() {
        // XHR to request a JS and a CSS
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://domain.tld/preload.js');
        xhr.send('');
        xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://domain.tld/preload.css');
        xhr.send('');
        // preload image
        new Image().src = "http://domain.tld/preload.png";
    }, 1000);
};

I noticed that the 'ajax' preloading for this image isn't really ajax at all. It is the same as what I have been using for years already, just setting the url in a new image object's source and letting the browser load it into the cache.

Now imagine that there was an application where, I needed to actually cancel the preloading of the image if it took over a certain amount of time. There really is no good way to do this with just setting the image to src, unlike the xhr.abort() method which stops the loading of an actual xhr request.

Is there any reason that doing some thing like the below wouldn't preload the image just as well and allow the cancellation of the preload request?

function preload(url, timeout){
    this.canceltimeout = function(){
        clearTimeout(this.timeout);
        this.loaded = true;
        return false;
    }

    this.abort = function(){
        this.xhr.abort();
        this.aborted = true;
    }

    //creates a closure to bind the functions to the right execution scope
    this.$_bind = function(method){
        var obj = this;
        return function (e){ obj[method](e);};
    }

    //set a default of 10 second timeout
    if(timeout == null){
        timeout = 10000;
    }

    this.aborted = false;
    this.loaded = false;
    this.xhr = new XMLHttpRequest();
    this.xhr.onreadystatechange = this.$_bind('canceltimeout');
    this.xhr.open('GET', url);
    this.xhr.send('');
    this.timeout = setTimeout(this.$_bind('abort'), timeout);
}

var llama = new preload('/image.gif');
show_image();

function show_image(){
    if(llama.loaded){
        var l = new Image();
        l.src = '/image.gif';
        application.appendChild(l);
    }else if(llama.aborted){
        var l = document.createElement('p');
        l.innerHTML = 'image.gif got cancelled';
        application.appendChild(l);
    }else{
        setTimeout(show_image, 10);
    }
    return false;
}

The main drawback is that unless you have configured your webserver to provide future freshness info(an Expires, or Cache-control: max-age http header that is in the future), the web browser may make a second http request to the server when you set the image.src, or just plain actually use the image in the document. If your web server had sent freshness validation headers(last-modified, or e-tag) then the image won't be redownloaded, but the request asking the server for freshness validation will stil be made, which is wasteful and adds latency to the process.

I don't know why, but browsers really like to cache the images when you hold a reference to an Image() object.

If you watch the net panel in a web browsers debug tools, you'll most browsers make the first 2 requests, but not the 3rd. Commenting out the code in the ajax callback, ands you'll see the request made for #3

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
<script>
var f = "0.png?" + (new Date); // 0.png should not have future freshness info headers

$.get(f, function() {
    var i = new Image();
    i.src = f;
});
setTimeout(function(){
    //#3
    var i = new Image();
    i.src = f;
}, 5000);
</script>