Best jquery questions in March 2012

Why is jQuery.ready recommended when it’s so slow?

22 votes

I have asked a similar question before but I never made my point exactly clear, or at least I think it’s such a relevant question that it’s worth to bring it up and see if anyone can give some insightful thoughts.

When using jQuery, many of us use the jQuery.ready function to execute an init when the DOM has loaded. It has become the de-facto standard way of adding DOM manipulation programs to a web page using jQuery. A related event exists natively some browsers, but jQuery emulates it in other browsers, such as some IE versions. Example:

<head>
<script>
    var init = function() { alert('hello world'); };
    $.ready(init);
</script>

Now, all our tests show that this event can be quite slow. It’s not nearly as slow as window.onload, but it’s still often around 100 ms delay before execution. If FF it can be up to 200-300 ms, especially on refresh.

These are some very important milliseconds, because this is the amount of time the initial layout is shown before any DOM manipulations are made (such as hiding a dropdown). Many times, a layout "flicker" is mainly caused by using a slow DOM ready event, forcing programmers to hide elements using CSS instead and potentially making it less accessible.

Now if we instead place an init function in a script tag before closing the body tag, it will be executed much faster, usually around half the time but sometimes even faster:

<head>
<script>
    var init = function() { alert('hello world'); };
</script>
</head>
<body>
<!-- some HTML -->
<script>init();</script>
</body>

A simple test page that proves the differences: http://jsbin.com/aqifon/10

I mean, we are not talking about barely noticeable differences as some of the "optimization police" promotes when it comes to using effective selectors. We are talking about some major delays when doing DOM manipulations onload. Trying this example in FF, domready can sometimes be more than 100 times slower (300ms vs 2ms).

Now to my question: Why is jQuery.ready recommended to use when it’s obviously much slower that other alternatives? And what are the drawbacks of calling the init before closing the BODY vs using jQuery.ready? It’s arguably more "safe" to use domReady, but in what context is it more safe than the other option? (I’m thinking stuff like document.write and deferred scripts) We have used the BODY way for nearly 5 years on many client sites, and we never run into any problems. It’s just a lot faster.

I’m also wondering, since there is so much fuzz about jsPerf and optimizing selectors for a couple of ms per 10000 executions, how come there is not much talk about this? It’s basically the first delay the user faces, and it seems to be fairly simple to slice 50-100 ms on each page load...

To the point first:

No, there is no disadvantage in calling you init before closing the <body>. It will as you have noticed perform better that relying on $.ready() and will also work with all the browsers flawlessly (even on IE).

Now, there are however reasons to use $.ready(), which in your case they do not probably apply:

  1. $.ready() makes it easy for developers to do stuff in the right order. In particular, the critical thing is to not reference DOM elements that have not been loaded. While this is simple enough, lots of developers still find it confusing. $.ready() is a no-brainer, albeit a slow one.
  2. In you have say several scripts that need to init(), it is not necessarily easy/convenient to manually do that at the end of your body. It requires discipline and knowledge of what these scripts do. In particular you will often see $.ready() in libraries dependent on jQuery, since it makes things work no matter what way developers will use to load the libs.
  3. With Asynchronous Module Definition (for instance require.js) becoming popular as a way to load your javascript, the end of <body/> method is not guaranteed.

Why does $($) crash my page?

18 votes

Disclaimer: Do not try this at home


Why, if I am using jQuery, does $($) freeze the page?


Inspired by this Area51 question

$($) is a shortcut for $(document).ready($). So, it will run the function (when the DOM is ready or directly when this is already the case).

The function passed to .ready is passed the jQuery function for convenience (especially useful when you're in noConflict mode). So, $($) will call $ with $ as argument - and everything will happen again, which is endless recursion.


Another explanation:

  1. You call $($).
  2. jQuery adds the function argument ($) to an internal ready list.
  3. Some time later, jQuery sees that the DOM is ready and thinks: "Let's call all functions in the ready list".
  4. The only function in the ready list is $, so it calls $.
  5. jQuery sees it should pass the $ function as the argument to those functions.
  6. It calls $ with $ as argument.
  7. The $ function sees a function as its argument, but because the DOM is ready, it calls the function directly (there is nothing to wait for).
  8. The function is called with $ as the argument.
  9. Everything happens again since step 7 applies.

Is it better to use .delegate() performance wise?

12 votes

One of the developers I work with began to write all his code this way:

$('.toggles').delegate('input', 'click', function() { 
   // do something  
});

vs:

$('.toggles').click(function() { 
   // do something  
});

Are there any performance benefits to doing this?

delegate() is superseded as of jQuery 1.7.

Use .on() instead.


.on() has excellent performance benchmarks. And covers your .click() needs as well as needed

How to catch exceptions thrown in callbacks passed to jQuery?

9 votes

I'd like to catch exceptions thrown from callbacks passed to jQuery (either to event handlers like click, or to jqXHR methods such as then or always).

I've identified two options:

  • window.onerror handler - this is only a partial solution because it isn't supported on Android which is one of my target platforms
  • handling exceptions within each individual callback - not DRY at all!

The only other thing I can think of is overriding jQuery methods but that can result in problems any time I upgrade jQuery. For AJAX handlers, I could possibly use $.ajaxSetup (per the answer to Exceptions thrown in jQuery AJAX callbacks swallowed?) but I'm not sure that will allow me to catch everything.

Are there any other options?

You can wrap each callback like this:

function cbWrapper(fn) {
    return function() {
        try {
            return(fn.apply(this, arguments));
        } catch(e) {
            // handle all your exceptions here
        }
    };
}

So, when you go to pass a callback to an Ajax call, instead of passing the actual callback, you pass cbWrapper(callback).

$.get(url, cbWrapper(myRealCallback));

Or the inline anonymous version would be like this:

$.get(url, cbWrapper(function() {
    // actual callback code here
}));

A more advanced way of doing it would be to override $.get() with your own implementation that wraps the callback automatically, but that gets tricky because jQuery is so flexible about what arguments are actually passed. Because of that and because you have to override one specific argument to make this work, you would have to duplicate all of their argument detection code that figures out which arguments are present and which correspond to which actual function parameters. That code is a bit messy. It's doable and probably won't break because if jQuery broke it, then existing jQuery code would break, but it isn't very clean.

If it's all your own code, you could just make your own version of $.get() that isn't so flexible with argument positions and switch all of your code to use it instead of the actual $.get():

jQuery.fn.myGet = function(url, fn) {
    return(jQuery.get(url, cbWrapper(fn)));
}

Is jQuery .text() method XSS safe?

9 votes

I have unescaped data from users.

So is it safe to use like this:

var data = '<test>a&f"#</test>'; // example data from ajax response
if (typeof(data) === 'string')
    $('body').text(data);

Can I use like this or there is some problems like encoding or some specific symbols that I should be careful and add more strict validation?

When you set the text of an element using the text method, jQuery uses createTextNode internally, which escapes all special characters.

From the jQuery docs:

We need to be aware that this method escapes the string provided as necessary so that it will render correctly in HTML. To do so, it calls the DOM method .createTextNode(), which replaces special characters with their HTML entity equivalents (such as &lt; for <)

So yes, it should be safe. Here's your example in jsfiddle. Notice how the tags appear as literal text.

Save object states in .data or attr - Performance vs CSS?

9 votes

In response to my answer yesterday about rotating an Image, Jamund told me to use .data() instead of .attr()

First I thought that he is right, but then I thought about a bigger context... Is it always better to use .data() instead of .attr()? I looked in some other posts like what-is-better-data-or-attr or jquery-data-vs-attrdata

The answers were not satisfactory for me...

So I moved on and edited the example by adding CSS. I thought it might be useful to make a different Style on each image if it rotates. My style was the following:

.rp[data-rotate="0"] {
    border:10px solid #FF0000;
}
.rp[data-rotate="90"] {
    border:10px solid #00FF00;
}
.rp[data-rotate="180"] {
    border:10px solid #0000FF;
}
.rp[data-rotate="270"] {
    border:10px solid #00FF00;
}

Because design and coding are often separated, it could be a nice feature to handle this in CSS instead of adding this functionality into JavaScript. Also in my case the data-rotate is like a special state which the image currently has. So in my opinion it make sense to represent it within the DOM.

I also thought this could be a case where it is much better to save with .attr() then with .data(). Never mentioned before in one of the posts I read.

But then i thought about performance. Which function is faster? I built my own test following:

<!DOCTYPE HTML>
<html>
<head>
<title>test</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
function runfirst(dobj,dname){
  console.log("runfirst "+dname);
  console.time(dname+"-attr");
  for(i=0;i<10000;i++){
    dobj.attr("data-test","a"+i);
  }
  console.timeEnd(dname+"-attr");
  console.time(dname+"-data");
  for(i=0;i<10000;i++){
    dobj.data("data-test","a"+i);
  }
  console.timeEnd(dname+"-data");
}
function runlast(dobj,dname){
  console.log("runlast "+dname);
  console.time(dname+"-data");
  for(i=0;i<10000;i++){
    dobj.data("data-test","a"+i);
  }
  console.timeEnd(dname+"-data");
  console.time(dname+"-attr");
  for(i=0;i<10000;i++){
    dobj.attr("data-test","a"+i);
  }
  console.timeEnd(dname+"-attr");  
}
$().ready(function() {
  runfirst($("#rp4"),"#rp4");
  runfirst($("#rp3"),"#rp3");
  runlast($("#rp2"),"#rp2");
  runlast($("#rp1"),"#rp1");
});
</script>
</head>
<body>
    <div id="rp1">Testdiv 1</div>
    <div id="rp2" data-test="1">Testdiv 2</div>
    <div id="rp3">Testdiv 3</div>
    <div id="rp4" data-test="1">Testdiv 4</div>
</body>
</html>

It should also show if there is a difference with a predefined data-test or not.

One result was this:

runfirst #rp4
#rp4-attr: 515ms
#rp4-data: 268ms
runfirst #rp3
#rp3-attr: 505ms
#rp3-data: 264ms
runlast #rp2
#rp2-data: 260ms
#rp2-attr: 521ms
runlast #rp1
#rp1-data: 284ms
#rp1-attr: 525ms

So the .attr() function did always need more time than the .data() function. This is an argument for .data() I thought. Because performance is always an argument!

Then I wanted to post my results here with some questions, and in the act of writing I compared with the questions Stack Overflow showed me (similar titles)

And true enough, there was one interesting post about performance

I read it and run their example. And now I am confused! This test showed that .data() is slower then .attr() !?!! Why is that so?

First I thought it is because of a different jQuery library so I edited it and saved the new one. But the result wasn't changing...

So now my questions to you:

  • Why are there some differences in the performance in these two examples?
  • Would you prefer to use data- HTML5 attributes instead of data, if it represents a state? Although it wouldn't be needed at the time of coding? Why - Why not?

Now depending on the performance:

  • Would performance be an argument for you using .attr() instead of data, if it shows that .attr() is better? Although data is meant to be used for .data()?

UPDATE 1:
I did see that without overhead .data() is much faster. Misinterpreted the data :) But I'm more interested in my second question. :)

Would you prefer to use data- HTML5 attributes instead of data, if it represents a state? Although it wouldn't be needed at the time of coding? Why - Why not?

Are there some other reasons you can think of, to use .attr() and not .data()? e.g. interoperability? because .data() is jquery style and HTML Attributes can be read by all...

UPDATE 2:

As we see from T.J Crowder's speed test in his answer attr is much faster then data! which is again confusing me :) But please! Performance is an argument, but not the highest! So give answers to my other questions please too!

UPDATE 3:

My test seems to be false because of the fire-bug I used while testing! The same file in chrome listed attr faster and a second test on jsperf also says attr is faster

This performance part of the question screams of premature optimization; see below. (Lest you get the wrong idea: I too am frequently guilty of wondering about the same sort of premature optimization question.)

But getting performance out of the way (other points addressed below the graph): As far as I can see, attr is faster than data in jQuery 1.7.1: http://jsperf.com/jquery-setting-attr-vs-data This surprises me. Not that it's remotely likely to matter.

Gratuitous bar graph (longer lines = faster performance):

Gratuitous bar graph from jsperf

Are there some other reasons you can think of, to use .attr() and not .data()?

At least a couple come to mind:

  1. The advantage of data is that it doesn't have to write to the element every time; you only write to the actual element the first time, and from then on jQuery is just updating a value in a JavaScript object it maintains in a separate object cache (connected to the element via a key). (I'm not sure why it's slower than attr; perhaps because of the indirection.)

  2. One thing I dislike about data is that it's not symmetrical: The first time you access data on an element, the data object is seeded with data-* attributes from the element; but from there on out, there is no connection between the two.

    Example (live copy | live source):

    var target = $("#target");
    display("data('foo'): " + target.data("foo"));
    display("data-foo: " + target.attr("data-foo"));
    display("Setting data('foo')");
    target.data("foo", "updated data('foo')");
    display("data('foo'): " + target.data("foo"));
    display("data-foo: " + target.attr("data-foo"));
    display("Setting data-foo");
    target.attr("data-foo", "updated data-foo");
    display("data('foo'): " + target.data("foo"));
    display("data-foo: " + target.attr("data-foo"));
    

    Assuming the #target element starts out with data-foo="bar", the output is:

    data('foo'): bar
    data-foo: bar
    Setting data('foo')
    data('foo'): updated data('foo')
    data-foo: bar
    Setting data-foo
    data('foo'): updated data('foo')
    data-foo: updated data-foo

    That can be confusing and surprising. The way you have to think about it is that the data-* attributes are default values only. I just don't like how they're so dependent on whether you've called data before or not; unless you never write to the data-* attribute directly, you can't be sure what value data will get (the original from the markup, or a value you updated later before you called data). It seems a bit chaotic to me, but if you set yourself rules (never write to data-* attributes directly and only ever use data, for instance), you can avoid the chaos.

  3. When you use attr, you can only store strings. When you use data, you can store any JavaScript value or object reference.


Because performance is always an argument!

Not in 2012. :-) Or at least, it's a lot lower down the list relative to other arguments than it used to be absent a specific, demonstrable performance problem.

Let's look at your runfirst #rp4 results: 10k iterations of attr took 515ms; 10k iterations of data took 268ms. That's 51.5 usec (microseconds, millionths of a second) each vs. 26.8 usec each. So you're wondering whether to use data if it saves you 24.7 usec per operation. Humans perceive things on the order of tenths of seconds. So for it to matter, you have to do this op roughly 4,000 times in a tight loop for a human to notice the difference. That's just not even close to worth worrying about, even in a mousemove handler.

If you're into that kind of territory (4,000/second in a tight loop), you'll probably want to avoid storing the information on the element at all.

How to avoid custom/Server error in web site?

8 votes

I have asp.net web application located on server I want to avoid all custom and server error from my site.

For that I have used

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPage/TryAgainLater.aspx">   <error redirect="~/ErrorPage/PageNotFound.aspx" statusCode="404"/> </customErrors>

Using above code will able avoid some issue. ie.

Suppose "http://Exaple.com/Careers.aspx" Page available in my site then

Case 1. http://Exaple.com/Careersss.aspx "It was working correct as per above rule".

Case 2. http://Exaple.com/!@##Careersss.aspx "Not working" Note : Here I add special character

Case 3: http://Exaple.com/Careersss.aspxxxx "Not working" Note : add character after ".aspx"

case 4: http://Exaple.com/Careersss.aspx/!@!@!@! "Not works design breaking here". Note : Add '/' with special character.

please help me when user get case 2,3,4 then they automatically redirected to error page.

Thanks In advance.

For above problem we have to change IIS Setting please refer :

http://www.braintrove.com/id/46/page/2#Configure-IIS-for-custom-error-pages

http://blogs.msdn.com/b/webtopics/archive/2008/05/28/iis-7-0-http-error-pages.aspx

Techniques for javascript code grouping

8 votes

I have lots of functions and event handlers that are split across multiple javascript files which are included on different pages throughout my site.

For performance reasons I want to combine all of those files into 1 file that is global across the site.

The problem is I will have event handlers called on elements that won't necessarily exist and same function names.

This is an example of a typical javascript file...

$(document).ready(function(){
    $('#blah').keypress(function(e){
        if (e.which == 13) {
            checkMap();
            return false;
        }
    });
});

function checkMap() {
    // code
}

function loadMap() {
    // code
}

I would need to seperate this code into an object that is called on that specific page.

My thoughts are I could re-write it like this:

(function($) {
    $.homepage = {
        checkMap: function(){
            // code
        },
        loadMap: function(){
            //code  
        }
    };
})(jQuery);

And then on the page that requires it I could call $.homepage.checkMap() etc.

But then how would I declare event handlers like document.ready without containing it in it's own function?

Any advice on best practice would be great, thanks!

I think that all you need is a namespace for you application. A namespace is a simple JSON object that could look like this:

var myApp = {
    homepage : {
      showHeader : function(){},
      hideHeader : function(){},
      animationDelay : 3400,
      start : function(){} // the function that start the entire homepage logic
    },
    about : {
    .... 
    }
}

You can split it in more files:

  1. MyApp will contain the myApp = { } object, maybe with some useful utilities like object.create or what have you.
  2. Homepage.js will contain myApp.homepage = { ... } with all the methods of your homepage page.
  3. The list goes on and on with the rest of the pages.

Think of it as packages. You don't need to use $ as the main object.

 <script src="myapp.js"></script>
 <script src="homepage.js"></script>
 <-....->
 <script>
   myApp.homepage.start();
 </script>

Would be the way I would use the homepage object.

When compressing with YUI, you should have:

<script src="scripts.min.js"></script>
<script>
    myApp.homepage.start();
 </script>

When should I use jQuery deferred's "then" method and when should I use the "pipe" method?

8 votes

jQuery's Deferred has two functions which can be used to implement asynchronous chaining of functions:

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

doneCallbacks A function, or array of functions, called when the Deferred is resolved.
failCallbacks A function, or array of functions, called when the Deferred is rejected.

pipe()

deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise

doneFilter An optional function that is called when the Deferred is resolved.
failFilter An optional function that is called when the Deferred is rejected.

I know then() has been around a little longer than pipe() so the latter must add some extra benefit, but what the difference precisely is eludes me. Both take pretty much the same callback parameters though they differ in name and the difference between returning a Deferred and returning a Promise seems slight.

I've read the official docs over and over but always find them too "dense" to really wrap my head around and searching has found lots of discussion of the one feature or the other but I haven't found anything that really clarifies the different pros and cons of each.

So when is it better to use then and when is it better to use pipe?


Addittion

Felix's excellent answer has really helped clarify how these two functions differ. But I wonder if there are times when the functionality of then() is preferable to that of pipe().

It is apparent that pipe() is more powerful than then() and it seems the former can do anything the latter can do. One reason to use then() might be that its name reflects its role as the termination of a chain of functions processing the same data.

But is there a use case that requires then()'s returning the original Deferred that can't be done with pipe() due to it returning a new Promise?

They serve different purposes:

  • .then() is to be used whenever you want to work with the result of the process, i.e. as the documentation says, when the deferred object is resolved or rejected. It is the same as using .done() or .fail().

  • You'd use .pipe() to (pre)filter the result somehow. The return value of a callback to .pipe() will be passed as argument to the done and fail callbacks. It can also return another deferred object and the following callbacks will be registered on this deferred.

    That is not the case with .then() (or .done(), .fail()), the return values of the registered callbacks are just ignored.

So it is not that you use either .then() or .pipe(). You could use .pipe() for the same purposes as .then() but the converse does not hold.


Example 1

The result of some operation is an array of objects:

[{value: 2}, {value: 4}, {value: 6}]

and you want to compute the minimum and maximum of the values. Lets assume we use two done callbacks:

deferred.then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var min = Math.min.apply(Math, values);

   /* do something with "min" */

}).then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var max = Math.max.apply(Math, values);

   /* do something with "max" */ 

});

In both cases you have to iterate over the list and extract the value from each object.

Wouldn't it be better to somehow extract the values beforehand so that you don't have to do this in both callbacks individually? Yes! And that's what we can use .pipe() for:

deferred.pipe(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    return values; // [2, 4, 6]

}).then(function(result) {
    // result = [2, 4, 6]

    var min = Math.min.apply(Math, result);

    /* do something with "min" */

}).then(function(result) {
    // result = [2, 4, 6]

    var max = Math.max.apply(Math, result);

    /* do something with "max" */

});

Obviously this is a made up example and there are many different (maybe better) ways to solve this problem, but I hope it illustrates the point.


Example 2

Consider Ajax calls. Sometimes you want to initiate one Ajax call after a previous one completes. One way is to make the second call inside a done callback:

$.ajax(...).done(function() {
    // executed after first Ajax
    $.ajax(...).done(function() {
        // executed after second call
    });
});

Now lets assume you want to decouple your code and put these two Ajax calls inside a function:

function makeCalls() {
    // here we return the return value of `$.ajax().done()`, which
    // is the same deferred object as returned by `$.ajax()` alone

    return $.ajax(...).done(function() {
        // executed after first call
        $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

You'd like to use the deferred object to allow other code which calls makeCalls to attach callbacks for the second Ajax call, but

makeCalls().done(function() {
    // this is executed after the first Ajax call
});

would not have the desired effect as the second call is made inside a done callback and not accessible from the outside.

The solution would be to use .pipe() instead:

function makeCalls() {
    // here we return the return value of `$.ajax().pipe()`, which is
    // a new deferred/promise object and connected to the one returned
    // by the callback passed to `pipe`

    return $.ajax(...).pipe(function() {
        // executed after first call
        return $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

makeCalls().done(function() {
    // this is executed after the second Ajax call
});

By using .pipe() you can now make it possible to append callbacks to the "inner" Ajax call without exposing the actual flow/order of the calls.


In general, deferred objects provide an interesting way to decouple your code :)

jquery select class with value

8 votes

i want to use the html data-* attributes and have some images like this:

<img src="http://placehold.it/100.png" data-selected="true">
<img src="http://placehold.it/100.png" data-selected="false">
<img src="http://placehold.it/100.png" data-selected="false">
<img src="http://placehold.it/100.png" data-selected="true">
<img src="http://placehold.it/100.png" data-selected="false">

how can i now just only get the ones with data-selected="true"?

I tried:

$("img").each(function(){
  if($(this)).attr("data-selected") == "true") {
    //do something
  }
}

but this seems not to be the best way to me. Is there a direct selector where i can do something like

 $("img data-selected=true") ?

thanks for your help!!

$("img[data-selected='true']") but quoting of value isn't obligatory.

PS: it is called CSS attribute selector.

jquery: is there a concise way to conditionally use a 2nd selector if a 1st selector comes back empty?

8 votes

In python, I can do the following, to conditionally use a 2nd list if a 1st one is empty:

>>> x = [ ] or [1, 2]
>>> x
[1, 2]

In javascript, however,

>>> x = [ ] || [1, 2];
[ ]

So, if the "or trick" is off the table, I'm wondering whats the most concise way to do something like the following if-javascript-were-python-this-would-work pseudocode:

$elems = $('first-selector') || $('second-selector')

var elems = $("first-selector");
if(!elems.length) {
    elems = $("second-selector");
}

is not concise enough?

How about writing a little jquery extension?

$.fn.or = function(selector) {
    if (this.length) {
        return this;
    }

    return $(selector);
}

var elems = $("first-selector").or("second-selector")

jquery autoComplete with List<string> as Source

7 votes

i have text box name txtEmailList, i provided autocomplete list for it,

 <asp:TextBox runat="server" ID="txtEmailList" CssClass="txtAutoComplete">

script for autocomplete

$('#txtEmailList').autocomplete({
                source: function(request, response) {
// this is the ajax call, which is running successfully
                    var msg = 
Assessments_JqueryAutoComplete.AutoComplete(request.term).value; //(ajaxpro functions)
                    response(msg.d); 
                }

            });

output will come as like this (in firebug it shows as plain/text), how can i attach this array to source property. ( i cant use $.ajax method, as i need to use ajaxpro as office rules), so i get the list of array back from ajax call, how do i bind the autocomplete.

["List 1","List 2","List 3","List 4"];/* // this is the output response from jquery( from firebug)

[AjaxPro.AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public List<string> AutoComplete(string query)
{
List<string> objLisItmes = new List<string>();
objLisItmes.Add("List 1");
objLisItmes.Add("List 2");
objLisItmes.Add("List 3");
objLisItmes.Add("List 4");
return  objLisItmes;
}

this is the firebug output in for Response headers

Cache-Controlno-cache Content-Length40 Content-Typetext/plain; charset=utf-8 DateWed, 07 Mar 2012 10:45:37 GMT Expires-1Pragmano-cache

Instead of returning a List. I would return a string Array as:

[AjaxPro.AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public string[] AutoComplete(string query)
{
   List<string> objLisItmes = new List<string>();
   objLisItmes.Add("List 1");
   objLisItmes.Add("List 2");
   objLisItmes.Add("List 3");
   objLisItmes.Add("List 4");
   return  objLisItmes.ToArray();
}

How to know if there is any Ajax Request and ajax Success

7 votes

I wonder how can I code this

//if there is any ajax request
   $("#loader").css("display","block");
//on success:
    $("#loader").css("display","none");

Note : i am not going to code it again and again in my each ajax request function. i want it Genric. so that my script knows if there is any ajax request do $("#loader").css("display","block"); and if there is any ajax success do $("#loader").css("display","none");

The magical thing you are looking for is jQuery.ajaxStart() and jQuery.ajaxStop(). You might also find jQuery.ajaxComplete() useful.

Example:

$("#loader").ajaxStart(function() {
   $(this).show();
}).ajaxStop(function() {
   $(this).hide();
});

You should use the hide() and show() methods instead of changing the display CSS attribute.

How to make hovering over one div to trigger changes in another div?

7 votes

I am looking to create the next effect for my next website:

  1. I have 3 DIVs with some text content in the left column.
  2. I have an image in a div in the right column.
  3. Image in the right div have 3 different independent image parts, each separate part has to be highlighted when I hover over one of the divs (related to that particular image part) in the column on the left. The DIV I am hovering over has to be highlighted as well on hover.
  4. I also want the same effect only this time when I hover over any of those image parts in DIV on in the right column. I want it to highlight the related div, as well as highlight image part itself.

I know it all might sound really confusing, so I made a picture hopefully explaining my project visually. (check the attached image).

Now I am not sure if this can be solely achieved with use of only CSS, or by combination of CSS and jQuery or smn.

If anyone ever encountered similar implementation, or knows where I can find a code example, or could direct me in the right direction, I would really appreciate it!!!

You could set up mouseover bindings on your continent image and its corresponding div on the left:

$('.div1').mouseover(hoverOne);
$('.continent1').mouseover(hoverOne);
var hoverOne = function(){
    //hightlight elements
}

//lather...rinse...repeat for the rest

Finding elements with dynamic Id

7 votes

I want to make a generic function in jquery for select all functionality. I have a tabbed view in my web page.

Id of my component is : tabId:someDynamicId:rowId:componentId where, someDynamicId is dynamically generated.

So in jquery i want to find the element whose id starts with - tabId:someDynamicId & ends with componentId. And, tabId, someDynamicId & componentId would be passed as an argument to the generic function where this element needs to be find.

It's simple:

$('[id^=tabId][id$=componentId]').each(function(){
    var id = $(this).attr('id'); // tabId:someDynamicId:rowId:componentId​
    var list = id.split(':');​​

    console.log(list[0]); // tabId
    console.log(list[1]); // someDynamicId
    console.log(list[2]); // rowId
    console.log(list[3]); // componentId​
})

Wildcards in jQuery selectors

But i'm recommending to use right tools for this job. ID's are useful for finding specific element, but in your case it's better to use one or two classes and data attributes. For example:

<div class="tabs" data-component-id="x" data-tab-id="y">

Then find all $('.tabs') elements and use $(this).data('component-id') and $(this).data('tab-id')

$('.tabs').each(function(){
    var component_id = $(this).data('component-id');
    var tab_id = $(this).data('tab-id');
});

Update:

There is example of using this as function:

function(tabId,componentId) {
    $('[id^='+tabId+'][id$='+componentId+']').each(function(){
        var id = $(this).attr('id'); // tabId:someDynamicId:rowId:componentId​
        var list = id.split(':');​​

        console.log(list[0]); // tabId
        console.log(list[1]); // someDynamicId
        console.log(list[2]); // rowId
        console.log(list[3]); // componentId​
    })  
}

How to get actual (not original) height of a CSS-rotated element

6 votes

I need to obtain actual height of several different elements (for the sake of precise custom tooltip positioning), and some of these elements (not all) are rotated. $(elem).outerHeight() returns the original height, instead of the actual displayed height.

Here's the fiddle with a very simple example: http://jsfiddle.net/NPC42/nhJHE/

I see a possible solution in this answer: http://stackoverflow.com/a/8446228/253974, but am still hoping there is a simpler way.

Dusting off my high school geometry and my formidable graphics skills, I put this diagram together. If you have variables width, height, and rotation in javascript, you could express the height this way:

var rotated_height = width * Math.sin(rotation) + height * Math.cos(rotation);

enter image description here

What is the best method to make sure two people don't edit the same row on my web app?

6 votes

I have a PHP/jQuery/AJAX/MySQL app built for managing databases. I want to implement the ability to prevent multiple users from editing the same database row at the same time.

  1. What is this called?
  2. Do I use a token system and who ever has the token can edit it until they release the token?
  3. Do I use a "last edit date/time" to compare you loading the HTML form with the time in the database and if the database is the most resent edit then it warns you?
  4. Do I lock the row using database functions?

I'm just not sure which is the best. Assuming between 10 - 15 concurrent users

There are two general approaches-- optimistic and pessimistic locking.

Optimistic locking is generally much easier to implement in a web-based environment because it is fundamentally stateless. It scales much better as well. The downside is that it assumes that your users generally won't be trying to edit the same set of rows at the same time. For most applications, that's a very reasonable assumption but you'd have to verify that your application isn't one of the outliers where users would regularly be stepping on each other's toes. In optimistic locking, you would have some sort of last_modified_timestamp column that you would SELECT when a user fetched the data and then use in the WHERE clause when you go to update the date, i.e.

UPDATE table_name
   SET col1 = <<new value>>,
       col2 = <<new values>>,
       last_modified_timestamp = <<new timestamp>>
 WHERE primary_key = <<key column>>
   AND last_modified_timestamp = <<last modified timestamp you originally queried>>

If that updates 1 row, you know you were successful. Otherwise, if it updates 0 rows, you know that someone else has modified the data in the interim and you can take some action (generally showing the user the new data and asking them if they want to overwrite but you can adopt other conflict resolution approaches).

Pessimistic locking is more challenging to implement particularly in a web-based application particularly when users can close their browser without logging out or where users may start editing some data and go to lunch before hitting Submit. It makes it harder to scale and generally makes the application more difficult to administer. It's really only worth considering if users will regularly try to update the same rows or if updating a row takes a large amount of time for a user so it's worth letting them know up front that someone else has locked the row.

Issue with will_paginate page links

4 votes

I currently have a comment model that posts under a micropost and both are displayed on the same page. The issue is that both are displayed on the same page and both are paginated and I am trying to go for the facebook approach to microposting. Here is the issue below:

The links for both pagination turns into this href="/users/2?page=2" rather than href="/users/2/micropost?page=2" or href="/users/2/comment?page=2". I am unsure how to go about solving this problem. Here are some of my code. All suggestions are much appreciated!

Micropost Render HTML

<table class="microposts">
<% if microposts.any? %>
<%= render microposts %>
<%= will_paginate microposts, :page_links => false %>
<% else %>
<div class="EmptyContainer"><span class='Empty'>Add a thread!</span></div>
<% end %>
</table>

Comment Section HTML

<div id='CommentContainer-<%= micropost.id%>' class='CommentContainer Condensed2'>
<div class='Comment'>
<%= render :partial => "comments/form", :locals => { :micropost => micropost } %>
</div>
<div id='comments'>
  <% comments = micropost.comments.paginate(:per_page => 5, :page => params[:page]) %>
  <%= render comments %>
  <%= will_paginate comments, :class =>"pagination" %>
</div>
</div>

User Controller for the Show Page

  def show
    @user = User.find(params[:id])
    @comment = Comment.find(params[:id])
    @micropost = Micropost.new
    @comment = Comment.new
    @comment = @micropost.comments.build(params[:comment])
    @comments = @micropost.comments.paginate(:page => params[:page], :per_page => 5)
    @microposts = @user.microposts.order('created_at DESC').paginate(:per_page => 10, :page => params[:page])
      respond_to do |format|
      format.html
      format.js
     end
  end

Problem lies within will_paginate way of creating urls for each page (it doesn't have anything to do with jQuery).

By design, will_paginate try its best to guess what's the base url for the page user is on (internally it's using controller/action to do that). That base url is then combined with any extra params passed to will_paginate helper using :params and succesive page numbers.

For now (will_paginate 3.0.3), in order to overwrite this default behavior, you need to write your custom LinkRenderer class. Below there's example of such class - it makes use of new, extra option :base_link_url that can be passed to will_paginate view helper. Passed string is then used as a base when creating pagination links. If :base_link_url option is not passed, it will fallback to default behavior.

Put following class somewhere rails can find it on load (/lib for example, provided you've added /lib to your autoload paths in application.rb):

# custom_link_renderer.rb
class CustomLinkRenderer < WillPaginate::ActionView::LinkRenderer
  def prepare(collection, options, template)
    @base_link_url = options.delete :base_link_url
    @base_link_url_has_qs = @base_link_url.index('?') != nil if @base_link_url
    super
  end

  protected
  def url(page)
    if @base_link_url.blank?
      super
    else
      @base_url_params ||= begin
        merge_optional_params(default_url_params)
      end

      url_params = @base_url_params.dup
      add_current_page_param(url_params, page)

      query_s = []
      url_params.each_pair {|key,val| query_s.push("#{key}=#{val}")}

      if query_s.size > 0
        @base_link_url+(@base_link_url_has_qs ? '&' : '?')+query_s.join('&')
      else
        @base_link_url
      end
    end
  end
end

Usage:

# in your view
will_paginate collection, :renderer => CustomLinkRenderer, :base_link_url => '/anything/you/want'

And now back to your case. By this time you probably see the solution - you can have two will_paginate widgets on one page with different base urls by passing different :base_link_url options for those two.

jQuery multiple selectors with dot notation?

4 votes

OK. I'm somewhat of a noob... but not that noob-ish. :)

I desire to accomplish a find() in jQuery that has a similar result of dot notation or "&&". Here is an example (which does not work):

data.find("continent_country[id = 'us'].state[id = 'in']").each(function(){
// what to do
}

or

data.find("continent_country[id = 'us'] && state[id = 'in']").each(function(){
// what to do
}

I have been told to try a comma, like so:

data.find("continent_country[id = 'us'], state[id = 'in']").each(function(){
// what to do
}

... but that returns the wrong items.

My XML looks like this:

    <continent_country id="us" name="U.S.">
        <state id="al" name="Alabama"> 
            <city url="" name="auburn"/>
            <city url="" name="birmingham"/>
            <city url="" name="dothan"/>
            <city url="" name="florence / muscle shoals"/>
            <city url="" name="gadsden-anniston"/>
            <city url="" name="huntsville / decatur"/>
            <city url="" name="mobile"/>
            <city url="" name="montgomery"/>
            <city url="" name="tuscaloosa"/> 
        </state>
        <state>//more states</states>
    </continent_country>
    </continent_country id="eu" name="Europe">
        <state>//more states</states>
    </continent_country>

Some states/provinces/countries share the same id, which is why I would like to find a state in a specified continent_country.

Thanks in advance...

i think you want the child notation:

http://api.jquery.com/child-selector/

something like

data.find('continent_country[id = 'us'] > state[id='in']).each(function(){
   //do your stuff here
} 

Using appendTo and Load in click function

4 votes

jQuery newb and first poster. Please be gentle :-) I've searched and can't find an answer, but I'm sure there's a really simple solution.

Hoping someone can help me. Here's what I'm trying to achieve: I have a row of tabs, with all but the first tab using a click function to load() the external page into the required div. The first tab will have its content loaded by default, not from an external file but from a div already on the page, but further down the code for SEO reasons.

Clicking any other tab loads the content from the external page into the div but if you then want to go back to tab 1, the content is unavailable as it's been replaced by content from the load() - ie no longer in the DOM.

I suppose I could appendTo a #temp div before calling the load() and then append back if tab 1 link is clicked, but there must be a more elegant solution?

Here's code so far:

$(document).ready(function(){

    // default tab1 content div appended to containing div OK
    $("#innerDiv1").appendTo("#outerDiv");

    // tab2 link loads page2.html OK
    $("#link2").click(function(){
        $("#outerDiv").load("page2.html");
    });

    // This doesn't work as it's no longer in the DOM after #link2 clicked.
    $("#link1").click(function(){
        $("#innerDiv1").appendTo("#outerDiv");
    });

});

Any thoughts and replies greatly appreciated.

Thanks in advance M

Change the #link1 click handler to this :

$("#link1").click(function() {
   $("#outerDiv").load('originalurl.html #innerDiv1');
});

this uses AJAX to load the initial page but only grabs the '#innerDiv1' section and the replaces the contents of #outerdiv with it. You will need to replace the originalurl.html with your actual URL ... could maybe use location.href unless you update that for bookmarking ?