Best ajax questions in July 2011

What happens in JavaScript when an AJAX call returns while the script is executing?

24 votes

Suppose I write some JavaScript that performs an AJAX call with myCallback as a callback method to execute when the AJAX succeeds.

Suppose then that some other JavaScript method called myFunction is being invoked on my page when myCallback is invoked asynchronously.

Does one operation take precedence over the other? Do they both run at the same time? What happens?

Suppose then that some other JavaScript method called myFunction is being invoked on my page when myCallback is invoked asynchronously.

Does one operation take precedence over the other? Do they both run at the same time? What happens?

JavaScript on browsers is single-threaded (barring your using web workers, and the syntax for that is explicit). So myFunction will run until it returns — with certain caveats (keep reading). If the ajax layer completes an operation while myFunction is running (which it very well may) and needs to invoke the callback, that call gets queued. The next time your code yields, the next call in the queue will be triggered.

It might seem, then, that we never have to worry about race conditions. That's mostly true, but there are subtleties. For instance, consider this code:

var img = document.createElement('img');
img.src = /* ...the URL of the image... */;
img.onload = function() {
    // Handle the fact the image loaded
    foo();
};
doSomethingElse();
doYetAnotherThing();

Since JavaScript on browsers is single-threaded, I'm guaranteed to get the load event when the image loads, right?

Wrong.

The JavaScript code is single-threaded, but the rest of the environment probably isn't. So it can happen that, having set the img.src, the browser may see that it has a cached copy of the image it can use, and so it triggers the load event on the img between the img.src = ... line and the img.onload = ... line. Since my handler isn't attached yet, I don't get the call, because by the time I've attached my handler, the event has already fired.

But you can see the effect of queuing if we reverse those lines:

var img = document.createElement('img');
img.onload = function() {
    // Handle the fact the image loaded
    foo();
};
img.src = /* ...the URL of the image... */;
doSomethingElse();
doYetAnotherThing();

Now I'm hooking the event before setting src. If the event fires between the img.src = ... line and the doSomethingElse line (because the browser has the image in cache), the callback to my handler gets queued. doSomethingElse and doYetAnotherThing run before my handler does. Only when control passes out of my code does the queued call to my handler finally get run. The JavaScript code is single-threaded, but the environment is not.

You can also yield to the host environment in non-obvious ways. For instance, by calling alert or its breathren confirm, prompt, etc. These functions stick out like the sore thumbs they are in modern JavaScript because they aren't event driven; instead, JavaScript execution is suspended while a modal window is shown. But as bobince points out in his in-depth discussion here, that doesn't mean none of your other code will run while that modal is showing. It's still single-threaded, but the one thread is being suspended in one place (by the modal) and used to run code elsewhere in the meantime; a very fine distinction indeed. (Bob also points to some event handling — his focus example — that seems to break this rule, but it doesn't. His example calls focus, which in turn calls the event handlers, and then returns; no different from you calling your own functions.) The key thing the items that Bob points out have in common is that your code has called into something in the host environment that does goes away and does something (shows a modal dialog, fires blur and focus handlers, etc.).

(alert and its breathren in particular cause all sorts of nastiness, particularly around focus and blur, and I recommend avoiding them in favor of more modern techniques (which can also look about 18x better).)

So those are the caveats mentioned at the outset of the answer. And in particular, if myFunction calls alert, at least on Firefox the ajax completion callback will get run during the alert (it won't on most other browsers). If you're curious to try out what does and doesn't happen during alerts and such, here's a test page testing setTimeout and ajax; you could extend the tests to go further.

Is setInterval CPU intensive?

8 votes

I read somewhere that setInterval is CPU intensive. I created a script that uses setInterval and monitored the CPU usage but didn't notice a change. I want to know if there is something I missed.

What the code does is check for changes to the hash in the URL (content after #) every 100 milliseconds and if it has changed, load a page using AJAX. If it has not changed, nothing happens. Would there be any CPU issues with that.

I don't think setInterval is inherently going to cause you significant performance problems. I suspect the reputation may come from an earlier era, when CPUs were less powerful.

There are ways that you can improve the performance, however, and it's probably wise to do them:

  1. Pass a function to setInterval, rather than a string.
  2. Have as few intervals set as possible.
  3. Make the interval durations as long as possible.
  4. Have the code running each time as short and simple as possible.

Don't optimise prematurely -- don't make life difficult for yourself when there isn't a problem.

One thing, however, that you can do in your particular case is to use the onhashchange event, rather than timeouts, in browsers that support it.

Is it possible for an AJAX request to be read before the response is complete?

8 votes

I have an ajax request that takes a while to complete, but the server does output some content along the way. If I load the request simply in the browser, I can see the page slowly loading and it can be stopped at any time. Is it possible to access an incomplete ajax request before the server closes the response?

The way to accomplish this is by listening on the readyState in the the xhr object. When readyState == 3 it means new content has arrived and you can access it. The technique is referred to as Comet.

Note however that different browsers behave differently here, IE will not allow you to access it See Here and webkit browsers (Chrome/Safari) buffer 2KB of data before making it available. After accounting for that though, you can then listen for the change then act on it.

Unfortunately, jQuery does not currently support this out of the box. You can get around this as noted in Bug #8327, where they basically fall back to polling on the readyState to see if it changes. They have plans to maybe do something about it in the future, Bug #9883, but don't hold your breath.

So finally, yes it is possible, no it is not easy.

differences between doing ajax using a page method, a web service and a custom http handler

7 votes

I'm looking to create json objects in the client and then transfer these objects back to the server for processing. These are the following options I'm considering:

  • a page method

  • a web service

  • a custom http handler

I'm looking to use jquery to send the objects. The plan is to convert the json object into c# objects that in turn go into queries. During the processing, I'll need access to the users' session that's working in SQL server session mode. The pages where these calls will be running will be on https. The return objects will also be json objects. I'll consider scalability, security and performance.

I was wondering what would be the ups/downs of using each option.

Thanks for your suggestions.

This is my order of preference:

  • web service
  • httpHandler (asp.net web services are httpHandlers behind the scenes)
  • page method

Web service gives the maximum flexibility and scalability. ASP.Net web services are in fact HttpHandlers conforming to XML/SOAP standards.

Page Methods are least flexible. They best for one off communication between a piece of javascript with the aspx page. Even then, you have better ways to handle that rather than going through a page method.

Here are few benefits of using a web service:

  • Standards based
  • Provide loose coupling between systems
  • Can be scaled easily
  • Provide greater security as you can implement security at many levels (Authorization, Authentication wise)

Converting jquery code to prototype for a cross browser Ajax request in order to obtain Latest Tweets

6 votes

Converting jquery code to prototype for a cross browser Ajax request

My first post !

I had to fetch my latest tweet and so had to perform a cross browser request. The current app uses prototype, but I am somewhat familiar with jquery.

So, I began in jquery as :

$.ajax('http://twitter.com/status/user_timeline/apocalyptic_AB.json?count=1&callback=?', {
  dataType: "jsonp",
  success:function(data,text,xhqr){
    $.each(data, function(i, item) {
      console.log(item.text);
    });
  }
});

I get a warning as :

'Resource interpreted as Script but transferred with MIME type application/json.'

But, I do get to see my last tweet. Fine.

So, I decided to do the same in prototype and then try eliminating warnings, if any. But, I got nowhere near even after trying for hours.

This is what I came up with initially in prototype. I had a lot of changes/alterations that followed but none worked.

new Ajax.Request('http://twitter.com/status/user_timeline/apocalyptic_AB.json?count=1&callback=?', {
  contentType: "jsonp",
  onSuccess:function(transport){
    console.log(transport) ;
  }
});

The request succeeds but the response text is nil / " " . I get no error in Firefox but in Chrome the error is :

XMLHttpRequest cannot load http://twitter.com/status/user_timeline/apocalyptic_AB.json?count=1&callback=?. Origin http://localhost:4000 is not allowed by Access-Control-Allow-Origin.
Refused to get unsafe header "X-JSON"

Any help shall be greatly appreciated. Thank you.

Thanks Darin for getting me back onto Dandean's JSONP for prototype js.

Although I did not mention in the first place(the question was getting a bit long), I had tried using Ajax.JSONRequest from Dandean (the very link you are referring to). The request was constantly getting failed, and I didnt go further into using it as I was assuming it would be pretty straight forward getting it done in prototype too, like jquery. As I got no more answers, justifiably so, I decided to wrap my head around using Ajax.JSONRequest. The request failure was not due to a gateway timeout. It was because the request url had params callback repeated in it.

So, the request url turned out to be

GET (twitter.com/status/user_timeline/apocalyptic_AB.json?count=1&&callback=?&callba‌ck=_prototypeJSONPCallback_0) 

Thus, I defined my url without callback and it performed as desired. However, I still get a warning :

Resource interpreted as Script but transferred with MIME type application/json

Here is the equivalent prototype :

new Ajax.JSONRequest('http://twitter.com/status/user_timeline/apocalyptic_AB.json?count=1', {
    onSuccess:function(response){
    response.responseJSON.each(function(item){
        console.log(item.text);
    });

What kind of json answer starts with )]}'

5 votes

I have noticed that some json queries, particularly in google services, return a peculiar "json" which starts with a closing sequence and then it has just a array structure, specified with square braces.

What kind of ajax is this? Is there some library, js or py, parsing it?

To put a more concrete example:

>>> import json
>>> import urllib2
>>> url=urllib2.urlopen("https://plus.google.com/u/0/_/socialgraph/lookup/visible/?o=%5Bnull%2Cnull%2C%22114423404493486623226%22%5D")
>>> url.readline()
")]}'\n"
>>> url.readline()
'\n'
>>> url.readline()
'[["tsg.lac",[]\n'

and from there, a typical array follows. The full answer is thus a two line "header" and then an array, but the "header" is very puzzling and I wonder if it comes from an standard ajax library or it is just an idea of these guys.

Ah, if you use the developer tools of Chrome to look into the actual queries, you see the same. So I am induced to believe that it is an actual answer and not an artifact of the query.

Using invalid JSON at the beginning of a message is one way to defeat a combination of CSRF and a tricky attack on JavaScript's array constructor.

If that URL returned a valid, unwrapped array, then any site you visited could overload the Array function, place/inject a script reference to that Google+ URL on the page, and harvest your private/secure data when you simply loaded their page.

Google's own client-side code can strip that invalid JSON out before parsing it, because it's using a traditional XHR request which gives them access to the raw response. A remote site can only access it via script element injection and has no chance to pre-process the data before the browser parses it. The latter is similar to how JSONP works, with the Array constructor unwittingly becoming the callback function.

You'll see a similar approach on many high profile sites that return JSON arrays in response to GET requests. Facebook pads theirs with for (;;);, for example. If you try to use the CSRF attack on those Facebook APIs, the browser just enters an infinite loop on the remote site making reference to Facebook's private API. On Facebook.com, their client-side code has an opportunity to strip that off before running a JSON.parse() on it.

How can I populate a text field using primefaces ajax after validation errors occur?

5 votes

I have a form in a view which performs ajax partial processing for autocompletion and gmap localization. My backing bean instantiates an entity object "Address" and is to this object that the form's inputs are referenced:

@ManagedBean(name="mybean")
@SessionScoped
public class Mybean implements Serializable {
    private Address address;
    private String fullAddress;
    private String center = "0,0";
    ....

    public mybean() {
        address = new Address();
    }
    ...
   public void handleAddressChange() {
      String c = "";
      c = (address.getAddressLine1() != null) { c += address.getAddressLine1(); }
      c = (address.getAddressLine2() != null) { c += ", " + address.getAddressLine2(); }
      c = (address.getCity() != null) { c += ", " + address.getCity(); }
      c = (address.getState() != null) { c += ", " + address.getState(); }
      fullAddress = c;
      addMessage(new FacesMessage(FacesMessage.SEVERITY_INFO, "Full Address", fullAddress));
      try {
            geocodeAddress(fullAddress);
        } catch (MalformedURLException ex) {
            Logger.getLogger(Mybean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(Mybean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Mybean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(Mybean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SAXException ex) {
            Logger.getLogger(Mybean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (XPathExpressionException ex) {
            Logger.getLogger(Mybean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void geocodeAddress(String address)
            throws MalformedURLException, UnsupportedEncodingException,
            IOException, ParserConfigurationException, SAXException,
            XPathExpressionException {

        // prepare a URL to the geocoder
        address = Normalizer.normalize(address, Normalizer.Form.NFD);
        address = address.replaceAll("[^\\p{ASCII}]", "");

        URL url = new URL(GEOCODER_REQUEST_PREFIX_FOR_XML + "?address="
                + URLEncoder.encode(address, "UTF-8") + "&sensor=false");

        // prepare an HTTP connection to the geocoder
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        Document geocoderResultDocument = null;

        try {
            // open the connection and get results as InputSource.
            conn.connect();
            InputSource geocoderResultInputSource = new InputSource(conn.getInputStream());

            // read result and parse into XML Document
            geocoderResultDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(geocoderResultInputSource);
        } finally {
            conn.disconnect();
        }

        // prepare XPath
        XPath xpath = XPathFactory.newInstance().newXPath();

        // extract the result
        NodeList resultNodeList = null;

        // c) extract the coordinates of the first result
        resultNodeList = (NodeList) xpath.evaluate(
                "/GeocodeResponse/result[1]/geometry/location/*",
                geocoderResultDocument, XPathConstants.NODESET);
        String lat = "";
        String lng = "";
        for (int i = 0; i < resultNodeList.getLength(); ++i) {
            Node node = resultNodeList.item(i);
            if ("lat".equals(node.getNodeName())) {
                lat = node.getTextContent();
            }
            if ("lng".equals(node.getNodeName())) {
                lng = node.getTextContent();
            }
        }
        center = lat + "," + lng;
    }

Autocompletion and map ajax requests work fine before I process the whole form on submit. If validation fails, ajax still works ok except for the field fullAddress which is unable to update in the view, even when it's value is correctly set on the backing bean after the ajax request.

<h:outputLabel for="address1" value="#{label.addressLine1}"/>
<p:inputText required="true" id="address1" 
          value="#{mybean.address.addressLine1}">
  <p:ajax update="latLng,fullAddress" 
          listener="#{mybean.handleAddressChange}" 
          process="@this"/>
</p:inputText>
<p:message for="address1"/>

<h:outputLabel for="address2" value="#{label.addressLine2}"/>
<p:inputText id="address2" 
          value="#{mybean.address.addressLine2}" 
          label="#{label.addressLine2}">
  <f:validateBean disabled="#{true}" />
  <p:ajax update="latLng,fullAddress" 
          listener="#{mybean.handleAddressChange}" 
          process="address1,@this"/>
</p:inputText>
<p:message for="address2"/>

<h:outputLabel for="city" value="#{label.city}"/>
<p:inputText required="true" 
          id="city" value="#{mybean.address.city}" 
          label="#{label.city}">
  <p:ajax update="latLng,fullAddress" 
          listener="#{mybean.handleAddressChange}" 
          process="address1,address2,@this"/>
</p:inputText>
<p:message for="city"/>

<h:outputLabel for="state" value="#{label.state}"/>
<p:autoComplete id="state" value="#{mybean.address.state}" 
          completeMethod="#{mybean.completeState}" 
          selectListener="#{mybean.handleStateSelect}"
          onSelectUpdate="latLng,fullAddress,growl" 
          required="true">
  <p:ajax process="address1,address2,city,@this"/>
</p:autoComplete>
<p:message for="state"/> 

<h:outputLabel for="fullAddress" value="#{label.fullAddress}"/>
<p:inputText id="fullAddress" value="#{mybean.fullAddress}" 
          style="width: 300px;"
          label="#{label.fullAddress}"/>
<p:commandButton value="#{label.locate}" process="@this,fullAddress"
          update="growl,latLng" 
          actionListener="#{mybean.findOnMap}" 
          id="findOnMap"/>

<p:gmap id="latLng" center="#{mybean.center}" zoom="18" 
          type="ROADMAP" 
          style="width:600px;height:400px;margin-bottom:10px;" 
          model="#{mybean.mapModel}" 
          onPointClick="handlePointClick(event);" 
          pointSelectListener="#{mybean.onPointSelect}" 
          onPointSelectUpdate="growl" 
          draggable="true" 
          markerDragListener="#{mybean.onMarkerDrag}" 
          onMarkerDragUpdate="growl" widgetVar="map"/>
<p:commandButton id="register" value="#{label.register}" 
          action="#{mybean.register}" ajax="false"/>

If I refresh the page, validation error messages disappear and the ajax completes fullAddress field as expected.

Another weird behavior occurs also during validation: I have disabled bean validation for a form field, as seen on the code. This work alright until other validation errors are found, then, if I resubmit the form, jsf makes bean validation for this field!

I guess I am missing something in during the validation state but I can't figure out what's wrong with it. Does anyone knows how to debug jsf life cycle? Any ideas?

The cause of the problem can be understood by considering the following facts:

  • When validation on a JSF input component fails, the component is marked as invalid and the originally submitted value is kept in the component.

  • When validation on a JSF input component succeeds, the component is marked as valid and the originally submitted value is set to null (the converted/validated value is now set as model value).

  • When JSF renders an input component, it will first test if the originally submitted value is not null and if so, then redisplay it, else display the model value.

So, when you would like to update/re-render another input component using Ajax, you would need to make sure that the input component in question is marked as valid and the originally submitted value is set to null so that JSF will display the model value which you have set/changed programmatically.

One of the ways in your particular case is to manually collect all IDs of input components which are to be updated/re-rendered by PartialViewContext#getRenderIds() and then manually reset its state and submitted values by EditableValueHolder#resetValue().

FacesContext facesContext = FacesContext.getCurrentInstance();
PartialViewContext partialViewContext = facesContext.getPartialViewContext();
Collection<String> renderIds = partialViewContext.getRenderIds();

for (String renderId : renderIds) {
    UIComponent component = viewRoot.findComponent(renderId);
    EditableValueHolder input = (EditableValueHolder) component;
    input.resetValue();
}

You could do this inside the handleAddressChange() listener method, or inside an reuseable ActionListener implementation which you attach as <f:actionListener> to the input component which is calling the handleAddressChange() listener method.


Note that I don't guarantee whether this will work in combination with PrimeFaces. To my own experience, it works perfectly fine when using JSF2 standard <f:ajax> component, but it didn't work when using RichFaces' <a4j:xxx> components. See also the bug report which I have ever filed against this: RF-11112.


Coming back to the concrete problem, I'd imagine that this is an oversight in the JSF2 specification. It would make much more sense to us, JSF developers, when the JSF specification mandates the following:

  • When JSF needs to update/re-render an input component by an ajax request, and that input component is not included in the process/execute of the ajax request, then JSF should reset the input component's value.

$.ajax() error in jquery-1.6.2 but not in jquery-1.4.1

5 votes

I used $.ajax() to consume a local .asmx webservice. Here's my code for the call:

    $("#btnGetOne").click(function() {
        $.ajax({
            type: 'POST',
            contentType: 'application/json; charset=utf-8',
            url: 'http://localhost:53003/TestWebService.asmx/GetServant',
            data: '{ "servant_id": "' + $("#txtServantID").val() + '" }',
            dataType: 'json',
            success: function(data, textStatus, jqXHR) {
                var jsnData = $.parseJSON(data.d);
                $('#DisplayArea').html(jsnData.Servant_Name);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                alert(textStatus + ' ' + errorThrown);
            }
        });
    });

As you can see the ajax call executes when I click btnGetOne.

As in my question header, this works in jquery-1.4.1, but when I used jquery-1.6.2 I get an errorThrown saying No Transport.

Is there anything else I'm missing?

Your HTML+JS page is probably not loaded from localhost:53003, while you are trying to, using Ajax, an URL that is on domain localhost:53003.

So, it looks like you are trying to make a cross-domain request, which is forbidden -- see Same Origin Policy.


Taking a look a the documentation of jQuery.support, you might want to enable jQuery.support.cors (quoting) :

cors is equal to true if a browser can create an XMLHttpRequest object and if that XMLHttpRequest object has a withCredentials property.

To enable cross-domain requests in environments that do not support cors yet but do allow cross-domain XHR requests (windows gadget, etc), set $.support.cors = true;.


And here are a couple of links that might help :

jQuery.post() inside a jQuery.post()

5 votes

Imagine a website where the content is loaded via a menu with using jQuery .post() (or .get()).

Imagine that inside this dynamic loaded content should be another jQuery post to show some more things under the content

(all without navigating to a new file in the address bar)

Here is what i mean (but only the base frame...):

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<input type="text" name="n" id="n" placeholder="Search..." />
<button id="click1">Go</button>
<!-- the result of the search will be rendered inside this div -->
<br />
<div id="result" name="result"></div>

<script>
window.onload = (function(){
    /* attach a submit handler to the button */

    $("#click1").click(function(event) {
        $.ajax({
            url: 'test.php',
            type: 'POST',
            data: 'n: term',
              success: function(msg) {
                $( "#result" ).empty().append( msg );
              }
         });
    });
});
</script>

</body>
</html>

So, stop laughing, I know that the page only loads itself in the div and this is not working because of the same IDs... it´s not Inception here ;-)

But even if I link a completely new page to it with new IDs it is not working...

Is it possible to add a new jQuery AJAX inside an existing, already with jQuery AJAX loaded content?

I think yes, but I can´t find my mistake...

/EDIT

I think I need to give a bit more input:

test.php

<input type="text" name="n" id="n" placeholder="Search..." />
<button id="click1">Go</button>
<div id="result" name="result"></div>

<script>
window.onload = (function(){        
    $("#click1").click(function(event) {
        $.ajax({
            url: 'test2.php',
            type: 'POST',
            data: 'n: term',
              success: function(msg) {
                $( "#result" ).empty().append( msg );
              }
         });
    }); 
    $("#click2").click(function(event) {
        $.ajax({
            url: 'test3.php',
            type: 'POST',
            data: 'n2: term',
              success: function(msg) {
                $( "#result2" ).empty().append( msg );
              }
         });
    });
});
</script>

test2.php

<input type="text" name="n2" id="n2" placeholder="Search..." />
<button id="click2">Go</button>
<div id="result2" name="result2"></div>

test3.php

<?php
echo 'It´s working!';
?>

My final question: Why is it not working? Why does it not output "It´s working!" at the end?

You can put another post inside the success handler of the first post:

$("#click1").click(function(event) {
    $.ajax({
        url: 'test.php',
        type: 'POST',
        data: 'n: term',
          success: function(msg) {
            $( "#result" ).empty().append( msg );

            $.ajax({/* params here */});
          }
     });
});

Quick and Dirty Explanation of MVC3 Ajax/JS files, please :)

4 votes

I've been trying to find a decent article or snippet that explains what the difference is in JS (Validate & Ajax) files are Microsoft includes with MVC3 and I've not been able to find anything.

Would someone kindly explain the differences and how they're supposed to be use (e.g. does one piggy-back off the other, used instead for X reason, etc):

  • jquery.validate, jquery.validate.unobtrusive and MicrosoftMVCValidation
  • jquery.unobtrusive-ajax, MicrosoftAjax & MicrosoftMVCAjax

To add on to this - basically why would I use jquery.validate vs. the unobtrusive or MVC validation. Or what is their purpose in conjunction with jquery.validate, etc. Likewise for the Ajax files.

Thanks a ton in advance :)

Here are my 2 cents:

  • (jquery.validate and jquery.validate.unobtrusive) vs (MicrosoftMVCValidation)

Pick the first as it is unobtrusive meaning that HTML5 data-* attributes are generated on the input fields and validators are unobtrusively attached into separate javascript files. With Microsoft validation your final markup is no longer markup but it is markup mixed with javascript. Not only that this increases the size of your HTML pages but it makes them uglier and impossible to benefit from the browser caching capabilities of external static resources.

Depending on the project I decide whether I would use directly jQuery.validate plugin or benefit from the autogenerated HTML5 data-* attributes and let the jquery.validate.unobtrusive script do the automatic client script validation based on some DataAnnotations rules on my view models. Well, actually I don't use DataAnnotations but FluentValidation.NET but it doesn't matter to the client side as they both emit ModelMetaData. I must agree that with ASP.NET MVC 3 Microsoft made a step forward with those jquery.validate.unobtrusive scripts. But basically it will really depend on the project I am working on and the amount of control I need.

  • (jquery.unobtrusive-ajax) vs (MicrosoftAjax & MicrosoftMVCAjax)

None of the above :-) I would recommend you using pure jQuery but if you had to pick between the jquery.unobtrusive-ajax and MicrosoftAjax pick the first for the exact same reasons as the previous one. Now I should probably explain why I don't like either. I have already pointed out the complete crapiness of all Microsoft* scripts so let's not repeat it again. Even Microsoft themselves realized their mistake and starting from ASP.NET MVC 3 jQuery becomes the default library and their scripts are only included for compatibility with older applications that you might be converting, but I guess in future versions they will disappear completely. The question is why pure jQuery compared to jQuery.unobtrusive-ajax? Well, with the first I have far more control over the events of the AJAX requests. With jquery.unobtrusive-ajax for example when JSON objects are returned in the OnSuccess callback they are not automatically parsed into javascript objects you will have to do the parsing manually and that is just driving me nuts.

Ajax sent on "keyup" duplicates results when fast typing!

4 votes

This is my Ajax:

$("form[0] :text").live("keyup", function(event) {

    event.preventDefault();
    $('.result').remove();
    var serchval = $("form[0] :text").val();

    if(serchval){

        $.ajax({

            type: "POST",
            url: "<?= site_url('pages/ajax_search') ?>",
            data: {company : serchval},
            success: function(data) {

                var results = (JSON.parse(data));
                console.log(results);

                if(results[0]){
                    $.each(results, function(index) {
                        console.log(results[index].name);
                        $("#sresults").append("<div class='result'>" + results[index].name + "</div>");
                    });
                }
                else {
                    $("#sresults").append("<div class='result'>לא נמצאו חברות</div>");
                }
            }
        });
    }
});

When I type slowly (slower then a letter per second) I get the results correct, when I type faster I get 2 times the same results

example:
slow typing: res1 res2 res3
fast typing: res1 res2 res3 res1 res2 res3

Also, any advice on improving the code would be welcome!

Thats what is happening (pseudocode):

When you're typing slow:

.keyup1
.remove1
//asynchronous ajax1 request takes some time here...
.append1
.keyup2
.remove2
//asynchronous ajax2 request takes some time here...
.append2

When you're typing fast:

.keyup1
.remove1
//asynchronous ajax1 request takes some time here...
//and keyup2 happens before ajax1 is complete
.keyup2
.remove2
.append1
//asynchronous ajax2 request takes some time here...
.append2
//two results were appended _in a row_ - therefore duplicates

To solve duplicates problem, you would want to make your results removing/appending an atomic operation - using .replaceWith.

Build results HTML block first as string and then do the .replaceWith instead of .remove/.append:

var result = '';
for (i in results) {
    result += "<div class='result'>" + results[i].name + "</div>";
}

$("#sresults").replaceWith('<div id="sresults">' + result + '</div>');

Another problem (not related to duplicates) may be that older result overwrites newer which arrived earlier (because AJAX is asynchronous and server may issue responses not in the same order it receives requests).

One approach to avoid this is attaching roundtrip marker (kind of "serial number") to each request, and checking it in response:

//this is global counter, you should initialize it on page load, global scope
//it contains latest request "serial number"
var latestRequestNumber = 0;

$.ajax({
    type: "POST",
    url: "<?= site_url('pages/ajax_search') ?>",
    //now we're incrementing latestRequestNumber and sending it along with request
    data: {company : serchval, requestNumber: ++latestRequestNumber},
    success: function(data) {
        var results = (JSON.parse(data));
        //server should've put "serial number" from our request to the response (see PHP example below)
        //if response is not latest (i.e. other requests were issued already) - drop it
        if (results.requestNumber < latestRequestNumber) return;
        // ... otherwise, display results from this response ...
    }
});

On server side:

function ajax_search() {
    $response = array();

    //... fill your response with searh results here ...

    //and copy request "serial number" into it
    $response['requestNumber'] = $_REQUEST['requestNumber'];

    echo json_encode($response);
}

Another approach would be to make .ajax() requests synchronous, setting async option to false. However this may temporarily lock the browser while request is active (see docs)

And also you should definitely introduce timeout as algiecas suggests to reduce load on server (this is third issue, not related to duplicates nor to request/response order).

Detect if HTTP method (POST, GET) in jQuery.ajaxComplete()

4 votes

In a jQuery.ajaxComplete() how can I detect the HTTP method, specifically a GET or a POST?

I've tried reading the jQuery documentation and searching around and I can't seem to find much documentation of the 3 objects passed to the function handler inside

jQuery(element).ajaxComplete(function(event, request, settings) {    });

Thanks

The settings object in the AJAX callback is the settings object that was passed into the AJAX call. You can therefore look for the type property on it to see whether it was GET or POST:

jQuery(element).ajaxComplete(function(event, request, settings) {
    alert(settings.type);
});

The settings that you can retrieve in this manner are the same as those that you can set with the $.ajax constructor.

Simple key/value database

4 votes

I'm looking for a very(!) simple (server-side) key/value database which preferably has a REST API. It's used to cache some values in a javascript driven web application. Looking for a quick set up and easy ajax interaction. Any tips would be greatly appreciated!

You should check out couch db:

http://couchdb.apache.org/docs/intro.html

Sounds about what you are looking for.

Any existing solutions for dynamic forms in Django?

3 votes

I'm looking for existing solutions for building dynamic forms with Django. What I want to get is a form that looks just like a table, but when any of its cells are clicked, textbox is dynamically displayed instead of the text and then user can edit the value.

I know that's quite an abstract description but I'd really appreciate everything related: if that library/framework will reload absolutely all table to switch it from completely read-only to completely editable, that's also fine.

I'm implementing a proof of concept web application, so I'd like to avoid spending time for implementing it from scratch.

The description is unclear, I believe. Here it is:

  1. There's a list of users for instance. Just a simple table. Administrator clicks one of these users and profile is displayed:

    Login: jsmith

    Real Name: John Smith

    Group: Users

  2. Then administrator double-clicks "John Smith" and text box is loaded instead of text:

    Login: jsmith

    Real Name: [ John Smith ]

    Group: Users

    [Save] [Cancel]

  3. Administrator can now modify jsmith's real name. If Save is clicked, data is sent to server. If Cancel is clicked, data is reverted and profile is as on p.1

Update: what I want is what we have here on stackoverflow.com - write a comment (not answer) and post it. Then you can edit it without reloading the page. That's what I've been talking about before. So, I need something of that kind but extendable and Django-injectable

Sounds like what you want is a Javascript Data Grid widget. The Ext JS toolkit has a nice example, something like this:

http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/cell-editing.html

Now note this has nothing to do with Django, these things can be deployed by any web server or application server.

Of course implementing this on a Django server just means making sure your server is serving the Javascript, and that you've written any Ajax calls correctly. But thats the next step.

Asymetric and symetric key storage.

2 votes

Hi guys and thanks for reading.

I'm working on an ajax portal and I need some advice. My client wants it fairly secure but doesn't want to deal with ssl. There is no ultra sensitive data to store so I'm doing a custom "handshake" when the page initializes.

Since every session I'm dealing with 2 new sets of asymetric key and some symetric one as well, I want to know how you guys would handle these keys. This is probably going to reside on a shared host and I've read everywhere that the session file can't really be trusted in that case...

Right now I'm storing some info in the session file pointing to the right keys, which are in a database. Everything works just fine as it is (well, I think :))... Now I want to delete the keys from the database when the user session ends, so I don't end up with tables filled with useless keys.

Even if I knew it is BAD, I tried an ajax call when closing the window/browser... this is indeed BAD and inconsistent, so this option is out of the way. I also thought about a cron job to erase every key dating more than a couple of days, but it kind of feels "unfinished" to me...

My question is: I'm wondering how does ssl handles it's keys? Where are they stored while the user session lasts? How do you guys deal/would deal with this?

Thanks

EDIT

Yep, I should have known that this question would lead to that.

I know that ssl would be the best option and it is to my own regret that I have coded my application. I'll talk some more to my client about it, but I have little hopes. If he still wants to go http, I won't risk to loose the contract to proove my point and I'll have an alternative to protect its uncensitive data (login info kinda, no credit card...).

Yes, "fairly secure" is appropriate since no system is completely secure. "Fairly secure" means that a wannabe hacker who just downloaded wireshark, or watched a video on youtube to do a man in the middle attack won't be able to get in. I would say that it is already a lot better than all the multi billions gaming companies who recently been put to shame by some teenagers.

The correct answer goes to Nasko who answered part of my question and made some obvious recommendation, without being cocky at that.

SSL generates symmetric key for each handshake it completes and stores it in memory (unless the session cache is written to disk).

That said, I would suggest to avoid doing your own crypto protocol, since you are bound to make a mistake. Even the best crypto people make mistakes, so I wouldn't recommend anyone doing it for the sake of doing it.

Figure out what the problems are that your client perceives with SSL and address those. This way you use standard technology that is proven to work and your customer is happy at the end.

Array in success function undefined

2 votes

Why does this code

for(var i = 0; i < array.length; ++i) {
    array[i]["bla"] = "check";
}

work perfectly, whereas the array is here, according to firebug, undefinied:

for(var i = 0; i < array.length; ++i) {
    $.ajax({
        type: "POST",
        url: "my url",
        data: "data here",
        success: function() {
            array[i]["bla"] = "check";
        }
    });
}

How can I fix that issue?

Due to how closures work, the value of i is always going to be equal to array.length in the callback, because that's what it equals after the loop is done (after all, i < array.length is false). And that position is always undefined. You need to re-bind i inside the loop to make the current value "stick". Unfortunately the only way to do this in standard JS is to use yet another function, for instance:

for (...; i++) {
    (function(boundI) {
        // boundI is now bound to the current value of i in the current scope
        // If you want, you can call boundI just "i", but make sure you understand
        // how scopes work in JS before you do.
        $.ajax({
            ...
            success: function() {
                array[boundI]["bla"] = "check";
            }
        });
    })(i); // pass in the current value of the loop index which gets bound to boundI
}

AjaxOptions OnSuccess callback with parameter not working

1 votes

I am trying to use AjaxOptions.OnSuccess to call a javascript function and pass a parameter to it. I am able to call a basic function with no parameters without a problem, it's just the parameter passing.

Here is my JS function:

<script type="text/javascript">
    function removeRow (itemId) {

        alert(itemId);
    }
</script>

And my AjaxOptions declaration in razor:

New AjaxOptions With {.OnSuccess = "function(){removeRow(" + item.Id.ToString + ");}"}

On the client side the link appears like this:

<a data-ajax="true" data-ajax-success="function(){removeRow(3);}" href=...

Any idea what I'm doing wrong?

Thanks!

Try this:

New AjaxOptions With {.OnSuccess = String.Format("removeRow({0})", item.Id) }

Faster to display results from php or via jquery using ajax and json?

1 votes

I have a list of results Im displaying from the database using php. I query the database based on the search options the user uses and then return the results in a table layout. Im thinking about using jquery and ajax to call the php script instead so I can use something like a loading icon so they know its working instead of the page just hanging waiting for the results.

My question is, would it be faster to call the php script from jquery using ajax and have the php script get the results, build the view then return the view and have jquery just display the view from the output of the php script? Or would it be faster to request the php page from jquery/ajax, have the php script return json object of the results and just have jquery loop through it and build the view inside the jquery function instead?

This question has already been addressed: Creating HTML: PHP server-side vs. jQuery client-side

$.ajax error on mobile safari

1 votes

This is weird.

Only on mobile safari, and since last night this script....

 function login(login) 
{
        scrollTo(0,0);      
        var persistent = 'false'
            if ($('#persistent').is(':checked')){persistent = 'true';}
            if ($('#loginMsg').is(":visible")) {$('#loginMsg').hide();}
            var password = $('#password').val(); 
            var email = $('#email').val();
    $.ajax({
        type: "POST",
        url: "rpc.php",
        data: { id: email, value: password, persistent: persistent, method: "loginM"},      
        dataType: "json",
        timeout: 5000,
        success:    function(data){

        if (data.login=='true')
            {
            $('#pleaseWait').jqmShow(); 
            location.reload(true);
            }           
        else
            {   
            $("#loginMsg").show();
            $("#loginMsg").html(data.status);   
            }   
        },  
        /* error: function() {
        alert('This is taking too long. You could try again now, or wait and try again later.');*/ 

        error:function (xhr, ajaxOptions, thrownError){
                alert(xhr.status);
               alert(xhr.statusText);      
    }
});
}   
  1. alert(XMLHttpRequest.responseText); - returns me the entire script for the page
  2. alert(textStatus); - returns 'ok'
  3. alert(errorThrown); - returns '200'

When I run the script it errors immediately, doesn't wait 5 seconds. I have quarantined the script so it is by itself so other scripts don't interfere with it. Cleared the cache on the ipod.

This seems quite a common problem. One solution seems to be rebooting the sever which isn't an option.

The URL is relative. It should be absolute like : http://myserver.com/rpc.php

Why is there a Foursquare v2 API javascript authentication method?

1 votes

Browsing though the Foursquare API documentation, I noticed that when obtaining an access token with ajax there is no need for a secret key (for obvious reasons). But this makes me wonder what is even the point of having to register apps with foursquare in the first place if you can just fake being any app by using their client key. Why do they allow this?

https://developer.foursquare.com/docs/oauth.html

Your answer is in the document you referred to

Since each credential is tied to a particular URL

The point is Foursquare is looking at the URL of the requesting script for security. If there is no registration there is no URL to tie the credentials to.

I hope this makes sense