Best jquery questions in July 2011

Question about multiple ready()'s

21 votes

Suppose I have:

<script src="script1.js"></script>
<script src="script2.js"></script>

Both of these scripts have ready() inside. Will the code in script2.js's ready() always execute after the first one?

Yes.

First of all, the code in script2.js will be executed after script1.js, as it comes later in the document (and the defer attribute is not set).

Furthermore, the implementation [source] of the ready function is:

ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();

    // Add the callback
    readyList.done( fn );

    return this;
},

where readyList seems to be [source] a deferred object [docs]. That means the callbacks are executed in the order they have been added to that object.

Can search engine spiders see content I add using jQuery?

20 votes

I currently have something like this

<p class="test"></p>

<script type="text/javascript">
    $(document).ready(function() {
          $(".test").html("hey");
    });
</script>

Will search engines be able to spider the "hey" text? and if yes, what method can I use to prevent that.

Despite what is being stated here in other answers and totally contrary to Google's own FAQ, a Google employee named JohnMu answered a question recently in Google Groups about how the GoogleBot came to follow a non-existent URL. (The actual URL was contained within the jQuery code itself and the GoogleBot DID try to follow it.)

jQuery causing 404 errors in Google Webmaster Tools

Google Employee explains how JavaScript and jQuery are indexed

Apparently, Google does attempt to index your JavaScript.

Quote Google's JohnMu:

"I would also recommend not explicitly disallowing crawling of the jQuery file. While we generally wouldn't index it on its own, we may need to access it to generate good Instant Previews for your site."

JohnMu later in the same thread...

"Additionally, we're constantly working on improving processing of JavaScript for web-search in general, so if you use jQuery to pull in content, and the jQuery script is disallowed for Googlebot, then we would not be able to look at that at all."

What exactly does $(document).ready guarantee?

17 votes

Running my (rather complex) JavaScript/jQuery application in Google's Chrome browser, it would appear that $(document).ready fires while some of the JavaScript files have not yet loaded.

The relevant code (simplified):

In my HTML file

<script>var httpRoot='../../../';var verifyLoad = {};</script>

<script src="../../../globalvars.js"></script>
<script src="../../../storagekeys.js"></script>
<script src="../../../geometry.js"></script>
<script src="../../../md5.js"></script>
<script src="../../../serialize.js"></script>
...
<script src="../../../main.js"></script>

As the last statement of each of the .js files except main.js:

verifyLoad.FOO = true; // where FOO is a property specific to the file

e.g.

verifyLoad.jquerySupplements = true; 

verifyLoad.serialize = true; 

In main.js:

$(document).ready(function() {
    function verifyLoadTest (scriptFileName, token) {
        if (!verifyLoad.hasOwnProperty(token)) {
            console.log(scriptFileName + ' not properly loaded'); 
        };
    };
    verifyLoadTest('globalvars.js', 'globalvars');
    verifyLoadTest('storagekeys.js', 'storagekeys');
    verifyLoadTest('geometry.js', 'geometry');
    verifyLoadTest('md5.js', 'geometry');
    verifyLoadTest('serialize.js', 'serialize');
    ...
}

Much to my amazement, I see some of these trigger. This does not match my understanding of $(document).ready. What am I missing?

The document's ready event is fired when the browser has parsed the HTML file from beginning to end and converted it into a DOM structure. It does not in any way guarantee that any other resources (e.g. stylesheets, images or, as in this case, scripts) will have loaded. It only refers to the DOM structure, and is fired irrespective of the loading status of the page's resources.

If you want to wait for resources to load, use the window's load event, which is fired only when every element on the page has finished loading.

See:

What's the right way to do $(document).ready in jQuery Mobile?

15 votes

Suppose I want to run some code once jQuery Mobile has finished rendering the UI. The mobileinit event doesn't work since it's raised before this happens. A quick Google search seems to indicate that simply using $(document).ready won't work with JQM; but I just tried it (called after mobileinit) and it worked for me: my code ran and dynamically updated elements, etc. just fine. So I'm wondering, is there some reason I shouldn't be using it (it's unreliable or messes up JQM), or is the information out there about it not working simply inaccurate? What am I missing?

Update: See here for a demonstration.

Most likely the reason you read that $(document).ready won't work with jQuery Mobile is that it does not fire each time you view a pseudo-page. That said, it still triggers as it should when the html document is loaded.

If you want to run code that triggers each time you view a pseudo-page you can use this code:

$('[data-role="page"]').live('pageshow', function () {
    //run your code here
});

NOTE: there are other hooks that you can bind to as well (pageshow, pagehide, pagebefoershow, pagebeforehide), documentation can be found here: http://jquerymobile.com/demos/1.0b1/docs/api/events.html

---------- EDIT ----------

I was thinking about this and the best analog to $(document).ready() is not binding to the "pageshow" event, it would be binding to the "pagecreate" event. $(document).ready() fires once per page load, and "pagecreate" does the same for pseudo-pages whereas "pageshow" fires each time a page is displayed.

So if a user clicked away from the home-screen and then clicked a back button to return to the home-screen, "pageshow" would fire on this second (and subsequent) "showing" of the home-screen.

Also, "pageshow" requires the user to navigate to the page to which it is bound.

CSS rules with multiple possible values (jQuery)

13 votes

The question is simple; using jQuery's css function, the computed style of a CSS attribute may be returned, but what if there are more than one style for that attribute being rendered? For example :

<div id="foo" style="text-decoration:underline;">Some underline text</div>

The instruction $('#foo').css('text-decoration'); will return underline. Now if I change it to

<div id="foo" style="text-decoration:underline;">Some underline <span id="bar" style="text-decoration:line-through;">text</span></div>

The instruction $('#bar').css('text-decoration'); will return line-through, alright.

But the actual text is also underline! How can I return both? Do I need to search all ancestors if I want to know if some text is both underline and line-through? Sounds a bit painful, no?

** Edit **

Another problem arises whith this HTML

<span style="text-decoration:underline;">some <span id="e1" style="font-weight:bold;">text</span></span>

where $('#e1').css('text-decoration'); returns none for some reason, while the text is clearly rendered with an underline.

** Disclaimer **

This question is not to debate how the UA renders an element, but if an element hierarchy applies a CSS or not. If one wants to understand text-decoration better, I suggest one would read about it. The question tries to focus on a more generalize matter. For example, it can also apply to this HTML

<div style="display:none;">Some <span id="keyword" style="text-decoration:underline;">hidden</span> text</div>

where one could want to know if the element keyword is visible or not. With the code below, this is simply done with

cssLookup($('#keyword'), 'display', 'none');   // -> true

** UPDATE **

After all the answers and comments, here is, based on Brock Adams solution :

/**
 * Lookup the given node and node's parents for the given style value. Returns boolean
 *
 * @param e     element (jQuery object)
 * @param style the style name
 * @param value the value to look for
 * @return boolean
 */  
function cssLookup(e, style, value) {
    var result = (e.css(style) == value);
    if (!result) {
        e.parents().each(function() {
            if ($(this).css(style) == value) {
                result = true;
                return false;
            }
        });
    }

    return result;
}

Thank you, everyone, for your inputs.

I don't think any browser, or the W3C, provides a good way to do this.

A complicating factor is knowing which styles cancel preceding styles (underline versus no-underline, for example).

So, we would need multiple look-up tables or human judgement to know which style actually applied.

Finally, all these methods (3 answers so far) cannot distinguish between a blank, or missing, style setting and an explicitly set none. Obviously the browser can render an explicitly set none differently than a blank or missing setting.

For human use, this code should do the trick:

function cssTree (jNode, styleName, bShowBlanks) {
    var styleArray  = [jNode.css (styleName)];

    jNode.parents ().map ( function () {
        var style   = $(this).css (styleName);

        if (bShowBlanks  ||  ! /^(none|\s*)$/i.test (style) )
            styleArray.push (style);
    } );
    return styleArray;
}

alert ( cssTree ( $("#bar"), 'text-decoration') );


See it in action at jsFiddle.

Results:

bar: line-through,underline
el: none,underline

//-- With bShowBlanks = true.
bar: line-through,underline,none,none
el: none,underline,none,none

What function acts as .SelectMany() in jQuery?

13 votes

Let me explain more:

we know that map function in jQuery acts as .Select() (as in LINQ).

$("tr").map(function() { return $(this).children().first(); }); // returns 20 tds

now the question is how can we have .SelectMany() in jQuery?

$("tr").map(function() { return $(this).children(); }); // returns 10 arrays not 20 tds!

here is my example in action: http://jsfiddle.net/8aLFQ/4/
"l2" should be 8 if we have selectMany.

[NOTE] please don't stick to this example, above code is to just show what I mean by SelectMany() otherwise it's very easy to say $("tr").children();

Hope it's clear enough.

map will flatten native arrays. Therefore, you can write:

$("tr").map(function() { return $(this).children().get(); })

You need to call .get() to return a native array rather than a jQuery object.

Proper use of jquery $(document).ready()?

12 votes

I have gotten into the habit of starting jquery coding with the ready function $(function(){...}); and putting all functions called from ready within ready.

Then I realized that some of the functions put into the ready function probably didn't need to be there.

For example, simple functions used by events in document ready could be declared outside of it:

function checkEmail(objelement){
   var emailRx = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
   return emailRx.test(objelement.val()) ? true : false;
}

Then used inside of it:

//code snippet for example

$(function(){

$("form[name='contactform']").submit(function(){
    $("input[type=text]").each(function(){
        if($(this).attr("id") == "email" && !checkEmail($(this))) { 
            $(this).prev().css("color","red");
       }
    });
});

});

I searched through many SO previous questions and couldn't seem to find an answer.

Is it better, worse, or no different to declare functions outside of ready in this manner?

If you declare them outside, all it means is that they exist in the global scope.

An advantage of this is that they can be reused outside of the document.ready function. A disadvantage is that they clutter up the global namespace (this can be avoiding by namespacing, if you want).

Personally, if I'm going to reuse them, they go outside. If they need to reference a variable or something else that will only exist within the scope of my domready handler, they go inside (usually as anonymous functions though).

Lately, I've been putting everything I can outside of the domready handler simply because the interpreter has to parse all function declarations within the domready handler before starting to execute the handler and delaying execution of your domready handler sort of defeats the purpose (regardless of how negligible that time is).

How do you step through jQuery code efficiently?

11 votes

I've just been playing with jQuery for a little while - been using YUI for awhile and while I really appreciate a lot of what the jQuery library has to offer, I'm finding it to be quite a pain to step through jQuery code in the debugger and I'm wondering if there are any tricks other than the obvious things?

Take a simple function like this:

function findFirstShortChild(parent) {
    var result = null;
    $("#" + parent + " li").each(function() {
        if ($(this).css("height") <= 10) {
            result = this;
            return(false);    // break out of each() function
        }
    });
    return(result);
}

If the function isn't working as intended and I decide I want to step through it, it is not intuitive at all. In fact, you can't really step through it at all. You would have to go through all sorts of jQuery code in a bunch of places. You can't step into the .each() loop because it isn't actually a traditional loop. I'm surprised at how unproductive I feel in the debugger compared to other libraries. So, here are my issues:

  • You can't step through line by line or you'll end up in a whole bunch of jQuery functions.
  • You can't get into the inside of the each loop without either going through a lot of jQuery stuff or setting a breakpoint and letting it hit the breakpoint.
  • You can't see what any of the intermediate values like $(this) are or why it might be getting a bogus value for the height without stepping through miles of foreign jQuery code.
  • You can't break out of the each loop like you do in a traditional loop (with break or return) because it isn't an actual loop. The loop is inside the .each() function. What looks like a loop here is just the internals of a function call.
  • What if I want to know why I'm getting a bogus height value in the loop. Is there any way to figure that out without stepping through a lot of jQuery code?

So, what am I missing here? Is it just a lot less convenient to step through this kind of code? Am I missing some magic techniques built into the jQuery framework to help with this? Or is the price you pay for using this style library that you have to completely change how you debug problems.

Is this what you have to do?

  • Assign intermediate values to local variables in a trouble spot so you can more easily inspect them without stepping through jQuery functions.
  • Move from breakpoint to breakpoint rather than stepping through things a line at a time.
  • Learn how to step into and through jQuery calls (efficiently) to answer some kinds of questions.

How do you all do it? What am I missing?

I should mention that I use Firebug in FF5 and the built-in debugger in Chrome (Chrome more often than Firebug now). And, yes I'm using the debug (non-minified) version of jQuery when debugging. So, this isn't a question about which debugger you use, but how you use the debugger to effectively step through jQuery code.

Tools

I'm using Firebug to debug jQuery code with some extensions for jQuery debugging:

FireQuery is a Firefox extension integrated with Firebug

  • jQuery expressions are intelligently presented in Firebug Console and DOM inspector
  • attached jQuery data are first class citizens
  • elements in jQuery collections are highlighted on hover
  • jQuerify: enables you to inject jQuery into any web page
  • jQuery Lint: enables you to automatically inject jQuery Lint into the page as it is loaded (great for ad-hoc code validation)

Firefinder is an add-on to Firebug, to help find HTML elements matching chosen CSS selector(s) or XPath expression. You can also auto-select elements when hovering or via the context menu.

Example

  • You can't step through line by line or you'll end up in a whole bunch of jQuery functions.
  • You can't get into the inside of the each loop without either going through a lot of jQuery stuff or setting a breakpoint and letting it hit the breakpoint.

When I want to get inside a each loop and debug step-by-step, I create a breakpoint in the function which was passed to the each function and then I debug line-by-line until I reach jQuery code. Now I'm creating a new breakpoint at the position where the jQuery code ends and I want to continue to debug.

  • You can't see what any of the intermediate values like $(this) are or why it might be getting a bogus value for the height without stepping through miles of foreign jQuery code.

Look at http://msdn.microsoft.com/en-us/scriptjunkie/ee819093. There is explained how you can watch inside this for example (section 'Scenario 2'). This article gives many tips how to debug code which uses jQuery.

  • You can't break out of the each loop like you do in a traditional loop (with break or return) because it isn't an actual loop. The loop is inside the .each() function. What looks like a loop here is just the internals of a function call.

I don't understand this issue. You can break out of the each loop with returning false. The function which was passed to the each function won't be called anymore when the function returned false one time.

  • What if I want to know why I'm getting a bogus height value in the loop. Is there any way to figure that out without stepping through a lot of jQuery code?

Maybe you'd have more information after looking into this as explained above. But sometimes it is necessary to look into jQuery code, but I don't do that very often. Of course there can be a bug in jQuery, too. :-D

Conclusion

Yes, debugging jQuery is a bit different. But I think after a small familiarization phase you will have modified your debugging style for jQuery. And moving from breakpoint to breakpoint is nothing compared to the time which was saved when using jQuery.

.

How to know when font-face has been applied

9 votes

I am currently building a corporate website for a customer that uses custom fonts extensively.

On jQuerys DOM-ready I am doing placement calculations to figure out where some pop-up menus with dynamic width and height should be placed based on their dynamic contents.

These calculations fail, since DOM-ready is fired before font-face is applied, and thus widths and heights are incorrect.

Right now (for the prototype) i am doing the calculations 500ms after DOM-ready to alleviate this problem, but this can't go into production for obvious reasons.

The problem has been observed in latest Firefox and chrome. IE 8 doesn't seem to have the problem, but then DOM-ready fires fairly late, so the delay is kind of built in I guess :)

Waiting for the load event is not an option, so my question to you is this:

Is there a reliable cross-browser way to detect when font-face has been applied?

I found a solution after wondering why IE doesn't suffer from this problem.

Firefox and chrome/safari triggers the DOMContentLoaded event before font-face is applied, thus causing the problem.

The solution is to not listen for DOMContentLoaded but instead go oldschool and listen to onreadystatechange and wait until the document.readystate === 'complete' which is always triggered after font-face is applied (as far as i can tell by my tests) - which is ofcourse what always happens in IE sine it doesn't support DOMContentLoaded.

So basically you can roll-your-own event in jQuery called fontfaceapplied - maybe it should be built in ;)

Funny fact: opera does it right and waits to trigger DOMContentLoaded until font-face is applied.

Minimizing jQuery instance vs creating more instances

8 votes

I started a series of posts on javascript / jQuery optimization and stumbled upon this interesting result.

Why is it that minimizing jQuery objects (by searching from a cached jQuery collection) can be slower then creating more instances of jQuery objects?

I was stunned to see the results of a test i prepared. I always thought that minimizing creating $ instances are slower.

This is what i am used to write, as i cache the parent (i call it "appRoot").

var appRoot = $("#appRoot");
    appRoot.find(".element1").css("color","red");
    appRoot.find(".element2").css("color","blue");

vs

    $(".element1").css("color","red");
    $(".element2").css("color","blue");

See the test results (slightly different scenario). jsperf minimize-jquery-object-creation it turns out that the cached snippet is slower then the uncached snippet.

I am trying to understand why?

You need to consider that your test contains less than 10 divs or other html elements. The reason to write code like in the first example is to make the selector faster, but with the cost of additional method calls. Normaly the selector should be the more expensive of the two by far so the the gain would outweight the loss but with a DOM this small the selector will be very cheap no matter how you write it.

People often make the misstake of not remembering that a more complex and large DOM will change the bottlenecks of the code. I think jsperf should have some kind of warning about this.

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.

Is Javascript size a performance concern after it is cached?

8 votes

I'm writing a project which will use some fairly large JS libraries including jquery UI. The project will be run within an Intranet though. So download time is not really an issue for me and most people should only have to download the libraries once since I assume they will remain in the browser's cache.

My question is about how modern browsers (IE9,FF5,etc) handle the processing of the Javascript code. I imagine at some point it is compiled, but is this done on each page load, or is the compiled code cached too. If so, is it cached even after the browser is closed?

This web app may run on some low powered portable devices so I wanted to be reasonably efficient. I wanted to combine all the javascript files into one large one that is linked to on every page of the app.

But depending on how much work the browser must do to process all the JS I'm wondering if I should split them up so not all pages must load all the JS. Obviously that's more work though.

Any thoughts or info would be appreciated. Thank you.

Yes, JavaScript size is still a performance concern if it is cached for the following reasons:

  • Most browsers don't cache the byte code that they execute. So the script must still be re-parsed on every page load. Modern browsers are doing this faster, but it still may be a concern for very large JavaScript files.
  • The code in your JavaScript files is actually executed on every page load. Even if browsers start caching byte code, they still have to re-execute the JavaScript every time the page is loaded.
  • You may get a lower cache rate than expected, for reasons beyond your control. Users may disable their cache, or visit so many sites that your files get expired from the cache quickly. You should check your logs to make sure that the ratio of page loads to JavaScript file loads is high.
  • Loading a file from cache is usually pretty fast, but it's not always trivial. It can take upwards of 200ms in some cases.

You can do a pretty quick test to get a rough idea of how long your scripts take to parse and execute like this:

<script>
  var startTime = (new Date()).getTime();
</script>
<script src="cachedFile1.js"></script>
<script src="cachedFile2.js"></script>
<!--all your scripts included this way-->
<script>
  var endTime = (new Date()).getTime();
  alert("Took " + (endTime - startTime) + " milliseconds to parse and execute");
</script>

Make sure to test on all the target browsers you support; JavaScript parse and execution time can vary wildly between different browsers. Also make sure that you test on a computer that is as slow as the ones your users will have. If you do find performance problems, you probably will need to solve them in a profiler. Minification won't help much for improving parse and execution time.

jQuery attr() fails to set attribute

7 votes

I am trying to rotate an image via svg's transform. This is the code I have:

<svg width="100" height="100"> 
   <image id="trns" transform="rotate(90,50,50)" width="100" height="100" xlink:href="logo.png"/> 
</svg>

This successfully rotates logo.png by 90 degrees when the page loads. Also, when I change 90 to a different number in firbug's HTML tab the rotation changes accordingly. But when I try to change the value with jQuery, nothing happens:

$('#trns').attr('transform', 'rotate(60, 50,50)');

What does firebug do that my attr line does not?

Working fine here (with jQuery 1.6.2): http://jsfiddle.net/niklasvh/k3Grd/

Make sure to call it once the DOM is ready:

$(function(){
 $('#trns').attr('transform', 'rotate(60,50,50)');
});

Is it better to do a large query and filter with jquery, or do more smaller queries?

7 votes

I'm writing my first website using php/mysql, and jquery. For the next part, the user will apply filters and sorts to find specific items (like an advanced search, kind of) and there will also be a search box. I want the data to reflect the change as soon as any checkbox filter is changed (currently have a test ajax call with no database query to do this that works well).

Would it be better to re-form the query string and re query the data each time a filter changes, or to make one large query and filter the results depending on the filters?

For the time being, the number of records will be low, but it's possible to grow into the thousands.

I would say build the query solely based on the data the user has selected, simply because when the data does become large and unwieldy, it would be silly to send that all to the client. It would be detrimental to performance in two main ways, if you think about it:

  1. Large data download to the client.
  2. JavaScript will need to process (sort/filter) the results and display what the user has asked for.

This is a no brainer, in my books. You will end up having to re-work your solution to scale with the size of your database, which is something you do don't want.

The server is good at handling queries and sorting and filtering through truckloads of data. That's not really something you should be doing on the client side if you have a choice.

JavaScript RegExp.test() returns false, even though it should return true

7 votes

The Prob: I get an AJAX response (JSON or plaintext with line breaks). Each item of the response should be checked via RegEx to find out whether it matches to user-definded patter or not.

Example:

Ajax Response (plain-text)

"Aldor
Aleph
Algae
Algo
Algol
Alma-0
Alphard
Altran"

User-pattern:

/^Alg/ig.test(responseItem)

RegExp Results should look like:

Aldor   // false
Aleph   // false
Algae   // true
Algo    // true
Algol   // true
Alma-0  // false
Alphard // false
Altran  // false

But each time i get different (and kinda weired) results... e.g. (/^alg/ig.test("Algo") => false)

My code:

HTML

...
<form>
  <input id="in" />
</form>
<div id="x">
  Aldor
  Aleph
  Algae
  Algo
  Algol
  Alma-0
  Alphard
  Altran
</div><button id="checker">check!</button>
...

JavaScript (jQuery 1.6.2)

$(function(){
    var $checker = $('#checker');

    $checker.click(function(ev){
        var inputFieldVal = $.trim($('#in').val());
        console.log(inputFieldVal); // Alg
        var regExpPattern = '^'+inputFieldVal,
            re = new RegExp(regExpPattern, 'igm');
        onsole.log(re); // /^Al/gim
        // Get text out of div#x
        var text = $('#x').text();
        // Trim and 'convert' to an array...
            text = $.trim(text).split('\n');
        console.log(text); // ["Aldor", "Aleph", "Algae", "Algo", "Algol", "Alma-0", "Alphard", "Altran"]

        for (var index=0, upper=text.length;index<upper;++index) {
            console.log(
               re.test(text[index]),
               text[index]
             );
        }
    });
})

Console OUTPUT:

/^Alg/ig => should match each item which starts with Alg

false "Aldor"
false "Aleph"
true "Algae"
false "Algo" //Why ? O.o
true "Algol"
false "Alma-0"
false "Alphard"
false "Altran"

/^Al/ig => should match each item because every item start with Al

true "Aldor"
false "Aleph" //Why ? O.o
true "Algae"
false "Algo" //Why ? O.o
true "Algol"
false "Alma-0" //Why ? O.o
true "Alphard"
false "Altran" //Why ? O.o

Any suggestions?

This is a common behavior that the the exec or test methods show when you deal with patterns that have the global g flag.

The RegExp object will keep track of the lastIndex where a match was found, and then on subsequent matches it will start from that lastIndex instead of starting from 0.

For example:

var re = /^a/g;
console.log(re.test("ab")); // true, lastIndex was 0
console.log(re.test("ab")); // false, lastIndex was 1

Remove the g flag from your pattern, since you are looking just for a single match (you are testing each line separately).

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

Conditional compilation turned off warning when mixing razor and javascript

5 votes

The following snippet triggers a "Conditional compilation turned off" warning in one of my views. Do you have an idea on how to fix it?

<script type="text/javascript">
    $(document).ready(function () {
        @RenderSection("JQueryDocumentReady",false)
    });
</script>

I tried to insert a semicolon at the end of the render section statement but it didn't help.

Thank you.

NOTE: Answer accepted because of alternative suggestion to the question, not solution given for the problem in title.

I'm not 100% sure what Conditional Compilation has to do with being in a <script> block, but I did find that wrapping the statements in parenthesis fixed the problem.

@(RenderSection("JQueryDocumentReady"))

I do think this method has a bit of code small though. It's not a problem to just have a script section and assign things to document ready on each page. It really isn't going to save you much work, and it will force you to put javascript on views outside of script tags the way you have chosen to do it.

$.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 */});
          }
     });
});

MVC 3 and "Javascript-Disabled" browsers.

4 votes

I have a requirement to implement a web application using MVC 3, which works on browsers even if javascript is disabled. There are a lot of concepts in MVC 3 which rely on the use of jquery.

  1. What are the concepts which won't work in the case of "javascript-disabled" browsers?
  2. For those concepts which won't work, are there any alternative ways to implement those concepts in MVC 3?
  3. With these requirements, is it a good idea to implement such a website using MVC 3, or should it be implemented in asp.net (with every thing done on server side)?

MVC 3 does NOT depend on jQuery to function properly

The beauty of MVC 3 is that it is pre-packaged with a jQuery plugin which provides unobtrusive form validation. Unobtrusive means that it will work even if Javascript is disabled. MVC 3 does NOT require jQuery nor Javascript to work as intended.

Take a moment to read this blog post. The author does a good job explaining how MVC 3 and jQuery work together.

http://www.matthidinger.com/archive/2011/02/22/Progressive-enhancement-tutorial-with-ASP-NET-MVC-3-and-jQuery.aspx