Best jquery questions in February 2011

How can jquery deferred be used?

43 votes

jQuery 1.5 brings the new Deferred object and the attached methods .when, .Deferred and ._Deferred.

For those who havn't used .Deferred before I've annotated the source for it

What are the possible usages of these new methods, how do we go about fitting them into patterns?

I have already read the API and the source, so I know what it does. My question is how can we use these new features in everyday code?

I have a simple example of a buffer class that calls AJAX request in order. (Next one start after previous one finishes).

/* Class: Buffer
 *  methods: append
 *
 *  Constructor: takes a function which will be the task handler to be called
 *
 *  .append appends a task to the buffer. Buffer will only call a task when the 
 *  previous task has finished
 */
var Buffer = function(handler) {
    var tasks = [];
    // empty resolved deferred object
    var deferred = $.when();

    // handle the next object
    function handleNextTask() {
        // if the current deferred task has resolved and there are more tasks
        if (deferred.isResolved() && tasks.length > 0) {
            // grab a task
            var task = tasks.shift();
            // set the deferred to be deferred returned from the handler
            deferred = handler(task);
            // if its not a deferred object then set it to be an empty deferred object
            if (!(deferred && deferred.promise)) {
                deferred = $.when();
            }
            // if we have tasks left then handle the next one when the current one 
            // is done.
            if (tasks.length > 0) {
                deferred.done(handleNextTask);
            }
        }
    }

    // appends a task.
    this.append = function(task) {
        // add to the array
        tasks.push(task);
        // handle the next task
        handleNextTask();
    };
};

I'm looking for demonstrations and possible uses of .Deferred and .when.

It would also be lovely to see examples of ._Deferred.

Linking to the new jQuery.ajax source for examples is cheating.

Bounty: Show us what techniques are available when we abstract away whether an operation is synchronously or asynchronously done.

The best use case I can think of is in caching AJAX responses. Here's a modified example from Rebecca Murphey's intro post on the topic:

var cache = {};

function getData( val ){

    // return either the cached value or an
    // jqXHR object (which contains a promise)
    return cache[ val ] || $.ajax('/foo/', {
        data: { value: val },
        dataType: 'json',
        success: function( resp ){
            cache[ val ] = resp;
        }
    });
}

$.when(getData('foo')).then(function(resp){
    // do something with the response, which may
    // or may not have been retreived using an
    // XHR request.
});

Basically, if the value has already been requested once before it's returned immediately from the cache. Otherwise, an AJAX request fetches the data and adds it to the cache. The $.when/.then doesn't care about any of this; all you need to be concerned about is using the response, which is passed to the .then() handler in both cases.

Deferreds are perfect for when the task may or may not operate asynchronously, and you want to abstract that condition out of the code.

Another real world example using the $.when helper:

$.when( $.getJSON('/some/data/'), $.get('template.tpl') ).then(function( data, tmpl ){

    $( tmpl ) // create a jQuery object out of the template
        .tmpl( data) // compile it
        .appendTo( "#target" ); // insert it into the DOM

});

Preferred way of modifying elements that have yet to be created (besides events)

33 votes

There are a lot of questions about binding future manipulations to non-existent elements that all end up answered with live/delegate. I am wondering how to run an arbitrary callback (to add a class or trigger a plugin, for example) to all existing elements that match a selector and all future elements that match that same selector that are yet to be created.

It seems that the main functionality of the livequery plugin made it into the core but the other part, attaching arbitrary callbacks got lost along the way somehow.

Another common answer is event delegation but what if one doesn't have access to all of the vendor code that is creating the elements to have it trigger the events?


Here is some real-world code:

// with livequery
$('input[type=text], input[type=password], textarea, .basic_form .block select, .order_form .form_item select, .order_form .form_item input')
    .livequery(function(){
        $(this)
            .focus(function(){
                $(this).addClass('active');
            })
            .blur(function(){
                $(this).removeClass('active');
            })
            .addClass('text');
    });

// with live
$('input[type=text], input[type=password], textarea, .basic_form .block select, .order_form .form_item select, .order_form .form_item input')
    .live('focus', function(){
            $(this).addClass('active');
        })
    .live('blur', function(){
            $(this).removeClass('active');
        });
    // now how to add the class to future elements?
    // (or apply another plugin or whatever arbitrary non-event thing)

One approach would be to monitor when new nodes are added/removed and re-trigger our selectors. Thanks to @arnorhs we know about the DOMNodeInserted event, which I would ignore the cross-browser problems in the hope that those small IE patches could someday land upstream to jQuery or knowing the jQuery DOM functions could be wrapped.

Even if we could ensure that the DOMNodeInserted fired cross-browser, however, it would be ridiculous to bind to it with multiple selectors. Hundreds of elements can be created at any time, and making potentially dozens of selector calls on each of those elements would crawl.

My best idea so far

Would it maybe be better to monitor DOMNodeInserted/Deleted and/or hook into jQuery's DOM manipulation routines to only set a flag that a "re-init" should happen? Then there could just be a timer that checks that flag every x seconds, only running all those selectors/callbacks when the DOM has actually changed.

That could still be really bad if you were adding/removing elements in great numbers at a fast rate (like with animation or __). Having to re-parse the DOM once for each saved selector every x seconds could be too intense if x is low, and the interface would appear sluggish if x is high.

Any other novel solutions?

I will add a bounty when it lets me. I have added a bounty for the most novel solution!

Basically what I am getting at is a more aspect-oriented approach to manipulating the DOM. One that can allow that new elements are going to be created in the future, and they should be created with the initial document.ready modifications applied to them as well.

JS has been able to do so much magic lately that I'm hoping it will be obvious.

In my opinion, the DOM Level 3 events DOMNodeInsertedhelp (which fires only for nodes) and DOMSubtreeModifiedhelp (which fires for virtually any modification, like attribute changes) are your best shot to accomplish that task.

Of course, the big downside of those events is, that the Internet Explorers of this world don't support them
(...well, IE9 does).

The other reasonable solution for this problem, is to hook into any method Which can modify the DOM. But then we have to ask, what is our scope here?

Is it just enough to deal with DOM modification methods from a specific library like jQuery? What if for some reason another library is modifying the DOM or even a native method ?

If it's just for jQuery, we don't need .sub() at all. We could write hooks in the form of:

HTML

<div id="test">Test DIV</div>

JS

(function(_append, _appendTo, _after, _insertAfter, _before, _insertBefore) {
    $.fn.append = function() {
        this.trigger({
            type: 'DOMChanged',
            newnode: arguments[0]
        });
        return _append.apply(this, arguments);
    };
    $.fn.appendTo = function() {
        this.trigger({
            type: 'DOMChanged',
            newnode: this
        });
        return _appendTo.apply(this, arguments);
    };
    $.fn.after = function() {
        this.trigger({
             type: 'DOMChanged',
             newnode: arguments[0]
         });
        return _after.apply(this, arguments);
    };

    // and so forth

}($.fn.append, $.fn.appendTo, $.fn.after, $.fn.insertAfter, $.fn.before, $.fn.insertBefore));

$('#test').bind('DOMChanged', function(e) {
    console.log('New node: ', e.newnode);
});

$('#test').after('<span>new span</span>');
$('#test').append('<p>new paragraph</p>');
$('<div>new div</div>').appendTo($('#test'));

A live example of the above code can be found here: http://www.jsfiddle.net/RRfTZ/1/

This of course requires a complete list of DOMmanip methods. I'm not sure if you can overwrite native methods like .appendChild() with this approach. .appendChild is located in Element.prototype.appendChild for instance, might be worth a try.

update

I tested overwriting Element.prototype.appendChild etc. in Chrome, Safari and Firefox (official latest release). Works in Chrome and Safari but not in Firefox!


There might be other ways to tackle the requirement. But I can't think of a single approach which is really satisfying, like counting / watching all descendents of a node (which would need an interval or timeouts, eeek).

Conclusion

A mixture of DOM Level 3 events where supported and hooked DOMmanip methods is probably the best you can do here.

Choosing Mobile Web HTML5 Framework

19 votes

Hey

For the new project, I have been searching for a framework with support of HTML5 and runs on mobile, that is IPhone, IPads. I found out these:

The main thing for me is HTML5. Although I went over the features they offer, I just wanted to know your experience if any with them.

Which one should I go for when looking for:

  • Quick Start
  • Good documentation
  • Similar Web-way development
  • Good support for the mobile platform

It depends on what your target audience is and how interactive the site you are building is.

jQTouch:
heavy on the CSS, light on the JavaScript, MIT license
For a framework that provides a quick start, but not a lot of documentation unfortunately, use jQTouch. It requires very little to get started and coding is fairly straight forward. It uses CSS classes for detecting the appropriate animations and interactions.

Sencha Touch:
almost completely JavaScript, GPL not for use on commercial sites without a license
If you are building a complex enterprise application with a lot of visual interactions, I would strongly recommend Sencha Touch, it is heavily documented, with a strong professional team providing support.

M-Project:
MIT license, heavy on the JavaScript, appears to be in Alpha, may be buggy
Although I have never worked with M-Project myself (thanks for pointing it out) it does appear to be a very robust, and the coding style appears to be very similar to Sencha Touch, which is based on ExtJS, so if your team already has experience with ExtJS, it might be wise to consider one of these frameworks.

Nimblekit:
This appears to be for iOS only, not a good thing if you ever decide to expand your application to Android or some other platform.

Wink Toolkit:
appears to be MIT, or some variation there of In my opinion, wink seems to have plenty going for it, but the documentation feels cold

jQuery Mobile:
Dual license MIT or GPL 2, just the right mixture of JavaScript and CSS
I will let someone with more experience talk about the merits, but jQuery mobile (though it is in alpha as well) is backed by a strong team and a community of supporters by extension of the core jQuery library. Probably the best choice for anything except the most enterprise centric applications.

Titanium:
Titanium is not an HTML5 mobile framework, it is a javascript based interface to native code modules included in the framework. It is a fairly straight forward framework, but I would consider the documentation sparse.

Bottom Line:
1. jQuery mobile - as long as your app is not enterprise centric
2. Sencha Touch - if your application is enterprise centric or heavy on user interactions
3. jQTouch - if what you are looking for is a simple framework to get started with quickly, but you don't need a lot of gusto.
4. Titanium - if you are more concerned with having actual native controls in your application

What are some empirical technical reasons not to use jQuery?

19 votes

Context: I am astounded by the number of front end developers that hack at HTML, Javascript and CSS all day long and that ignore tools like jQuery ( or other equivalent helper frameworks ) and refuse to use them. I am not talking about JavaScript gurus, I am talking about in the trenches every day Joe production developers. I get a lot of arguments that are more like excuses or personal opinions that I don't think have any technical merit, I want to make sure I am not missing something.

Question: What are some empirical technical reasons not to use jQuery?

I am not looking for religious or dogmatic arguments or subjective opinions "like some other framework is better", consider jQuery the straw man for all comparable frameworks in the question.

I'll answer about jQuery but those are the same arguments that I've heard against using YUI, Prototype, Dojo, Ext and few others. Main arguments that I've heard:

  1. file size, which in fact is 29KB - probably smaller than the logo on an average website and can be served from Google's CDN which is likely to be already in the cache of most of your visitors. As using jQuery always means smaller file size of your own JavaScript files, it can actually mean smaller download, even if not already in the browser cache.

  2. speed - writing pure JavaScript may be faster, but writing portable JavaScript seems to be impossible for most of the people. A website that is faster but doesn't work on every popular browser is useless in the real world. Besides jQuery uses some pretty heavy optimizations to actually be pretty damn fast and keeps getting even faster with every release, so it's actually not so easy to write faster code by hand for anything other than trivial examples.(*)

  3. "intellectual property" - a company is scared using someone else's code - while in fact jQuery is open source and free software that is used everywhere from your grandma's blog to Amazon, from Twitter to Bank of America, from Google to Microsoft - if they can use it then any company can use it.

  4. I can't remember hearing any other argument being used seriously.

(*) Here's a trivial example: getElementById('someid') vs. jQuery('#someid')

Is using getElementById faster? Yes. And of course everyone always checks the parentNode to catch when Blackberry 4.6 returns nodes that are no longer in the document, right? jQuery does. And everyone handles the case where IE and Opera return items by name instead of ID, right? jQuery does. If you don't do it then your code is not portable and you introduce subtle bugs that can be very difficult to find. And getElementById is the most trivial example that one could possibly find - don't even get me started on events and AJAX and the DOM...

Update:

There is actually a fourth result of asking why someone doesn't want to use jQuery. I forgot to put it on this list because it is not really an answer but rather the lack of any answer. The comment I got yesterday reminded me about it. This is hardly a "technical reason" to be added to the list but may be interesting nonetheless and may actually be the most common reaction.

What I personally suspect to be the main underlying reason to all of those reactions, though, is what I believe to be the biggest obstacle to progress in computer science: "I don't want to use it because I never did, therefore it must not be that important."

It was once the reaction to optimizing assemblers, compilers, structured programming, higher level languages, garbage collection, object oriented programming, closures or pretty much everything that we now take for granted — and today it's AJAX libraries. Maybe some day no one will remember that we once used to manually interact with the raw DOM API on the application level like now no one remembers that we once used to write programs using raw, unadorned, inscrutable hexadecimal numbers.

What are deferred objects?

14 votes

jQuery 1.5 adds "Deferred Objects". What are they, and what exactly do they do?

Deferred Object

As of jQuery 1.5, the Deferred object provides a way to register multiple callbacks into self-managed callback queues, invoke callback queues as appropriate, and relay the success or failure state of any synchronous or asynchronous function.

Deferred Methods:

Deferred In Action:

$.get("test.php").done(
    function(){ alert("$.get succeeded"); }
);

$.get("test.php")
    .done(function(){ alert("$.get succeeded"); })
    .fail(function(){ alert("$.get failed!"); });

And it seems that the existing ajax() method callbacks can be chained rather than declared in the settings:

var jqxhr = $.ajax({ url: "example.php" })
    .success(function() { alert("success"); })
    .error(function() { alert("error"); })
    .complete(function() { alert("complete"); });

Working Example From Eric Hynds blog post: http://jsfiddle.net/ehynds/Mrqf8/


jqXHR

As of jQuery 1.5, the $.ajax() method returns the jXHR object, which is a superset of the XMLHTTPRequest object. For more information, see thejXHR section of the $.ajax entry


From JQUERY 1.5 RELEASED:

DEFERRED OBJECTS

Along with the rewrite of the Ajax module a new feature was introduced which was also made publicly available: Deferred Objects. This API allows you to work with return values that may not be immediately present (such as the return result from an asynchronous Ajax request). Additionally it gives you the ability to attach multiple event handlers (something that wasn’t previously possible in the Ajax API).

Additionally you can make your own deferred objects using the exposed jQuery.Deferred. More information about this API can be found in the Deferred Object documentation.

Eric Hynds has written up a good tutorial on Using Deferreds in jQuery 1.5.

JQuery 1.5 and new "Text JSON" datatype

12 votes

Hi,

I have just updated to JQuery 1.5 and all my ajax calls that return JSON and a number of plugins instantly broke.

In my pre-1.5 code, I specified the dataType like:

dataType: "json"

Changing the dataType to:

dataType: "text json"

Fixes the problem but I do not want to manually change the plugins as this will affect upgrades.

Is there a way of handling this better with less disruption?

Cheers

Paul

This problem is caused by the jQuery validation plugin and how it extends the ajaxSettings object for its own use (changes json calls to jsonp calls). There will hopefully be an official update to the validation plugin soon, but in the meantime, there's a patch available here that fixes the problem:

https://github.com/bigfix/jquery-validation/commit/9aa53f9241224ba349f9fe1b2c801be0f431b63b

Edit:

jQuery Validation Plugin, compatible with jQuery 1.5.1, available on git hub: https://github.com/jzaefferer/jquery-validation

Edit #2: jQuery Validation Plugin 1.8, compatible with jQuery 1.5.1 (and earlier) is released:

Read about it: http://bassistance.de/2011/03/25/release-validation-plugin-1-8/

Download it: http://bassistance.de/jquery-plugins/jquery-plugin-validation/

Approach to handle javascript on bigger projects?

12 votes

Hi everyone,

After discovering jQuery a few years ago, I realized how easy it was to really make interactive and user friendly websites without writing books of code. As the projects increased in size, so did also the time required to carry out any debugging or perhaps implementing a change or new feature.

From reading various blogs and staying somewhat updated, I've read about libraries similar to Backbone.js and JavascriptMVC which both sound like good alternatives in order to make the code more modular and separated.

However as being far from an Javascript or jQuery expert, I am not really not suited to tell what's a good cornerstone in a project where future ease of maintainability, debugging and development are prioritized.

So with this in mind - what's common sense when starting a project where Javascript and jQuery stands for the majority of the user experience and data presentation to the user?

Thanks a lot

Both Backbone.js and JavascriptMVC are great examples of using a framework to organize large projects in a sane way (SproutCore and Cappuccino are nice too). I definitely suggest you choose a standard way of deal with data from the server, handling events from the DOM and responses from the sever, and view creation. Otherwise it can be a maintenance nightmare.

Beyond an MVC framework, you should probably choose a solution for these problems:

  • Dependency management: how will you compile and load javascript files in the right order? My suggestion would be RequireJS.
  • Testing: testing UI code is never easy but the guys over at jQuery have been doing for a while and their testing tool QUnit is well documented/tested.
  • Minification: you'll want to minify your code before deploying to production RequireJS has this built in but you could also use the Closure Compiler if you want to get crazy small source.
  • Build System: All these tools are great but you should pull them all together in one master build system so you can run a simple command on the commandline and have you debug or production application. The specific tool to use depends on your language of choice - Ruby => Rake, Python -> Write your own, NodeJS as a build tool (i like this option the most) -> Jake

Beyond that just be aware if something feels clunky or slow (either tooling or framework) and refactor.

How can I give a plugin's default settings access to the final settings?

11 votes

I'm working on a jQuery plugin. When the plugin runs, the first thing it does is determine its settings. It does this by taking some default settings and overriding some or all of them with whatever the user passed in.

Here's a simplified version:

(function( $ ) {
  $.fn.somePlugin = function(userOptions) {
    // Short name for internal use - exposed below for external modification
    var defaults = $.fn.somePlugin.defaults;

    // Decide settings
    // User settings overrule defaults, but merge both into an empty 
    // hash so that original defaults hash isn't modified
    var settings = $.extend(true, {}, defaults, userOptions);

    settings.alerter.call();

    // More code, etc.
  }

  $.fn.somePlugin.defaults = {
    name: 'Captain Slappy von Martinez, Esquire, DDS',
    favoriteColor: 'red',
    alerter: function(){alert("I got bones!");}        
  }

})( jQuery );

So, if you call the plugin like this:

    $('div').somePlugin({alerter: function(){alert('No bones here!');}});

... you override the default alerter function, but use the default favoriteColor.

I'm defining the defaults outside the plugin itself so that they are publicly accessible. So if you want to change the default value for favoriteColor, you can just do this:

$.fn.somePlugin.defaults.favoriteColor = 'blue';

... and that will change it for every instance on the page after that.

All of this works fine.

Here's my problem: in one of the default functions, I need to refer to settings. Something like this:

  $.fn.somePlugin.defaults = {
    name: 'Captain Slappy von Martinez, Esquire, DDS',
    favoriteColor: 'red',
    alerter: function(){alert("Paint me " + settings.favoriteColor);}        
  }

But when I try this, I get a Javascript error on the line where the default alerter function is declared: "settings is not defined." True enough: it's not defined yet when the parser hits that line. It WILL be defined by the time the function runs, but that doesn't seem to matter.

So my question is: How can I import my default function into the plugin in such a way that it has access to settings?

  • Is there a way to delay evaluation of settings until the function is actually called?
  • If so, is there a way to make sure it has access to the local scope of the plugin, even though I assume that, as an object, this function is being passed by reference? I know that I can alter the value of this inside a function by using someFunction.call(valueToUseForThis), but I don't know whether I can alter its scope after the fact.

Some Stuff that Doesn't Work

  • Initially, it seemed that if I declared settings in the outer, self-executing function, that would make it available to the defaults. But declaring it there causes problems: if I use my plugin multiple times on a page, the instances get their settings mixed up.

Any attempts to change scope after the fact are doomed. There's no dynamic scoping in JavaScript.

Workaround 1. Pass settings to the alerter explicitly:

$.fn.somePlugin = function(userOptions) {
  var settings = $.extend(...);
  settings.alerter(settings)
}

$.fn.somePlugin.defaults = {
  favoriteColor: 'red',
  alerter: function(settings) { alert("Paint me " + settings.favoriteColor) }
}

Workaround 2. Pass settings to the alerter implicitly:

$.fn.somePlugin = function(userOptions) {
  var settings = $.extend(...);
  settings.alerter()
}

$.fn.somePlugin.defaults = {
  favoriteColor: 'red',
  alerter: function() { alert("Paint me " + this.favoriteColor) }
}

Both solutions tested and work well with multiple uses of the plugin. If you have no plans for using this keyword in your alerter, you can use it for referencing settings.

The third valid solution, which you and fudgey mentioned, is to attach settings object to the DOM element itself:

$.fn.somePlugin = function(userOptions) {
  var settings = $.extend(...);
  $(this).data('somePlugin', {settings: settings})
  settings.alerter.call(this)
}

$.fn.somePlugin.defaults = {
  favoriteColor: 'red',
  alerter: function() {
      alert("Paint me " + $(this).data('somePlugin').settings.favoriteColor)
  }
} 

Extra fun. Emulating dynamic scope, a.k.a don't do this

function dynamic(fn) {
  var parts = fn.toString().split('{')
  fn = parts.shift() + '{ with (args) { ' + parts.join('{') + '}'
  return {bind: function(args) { return eval('(' + fn + ')') }}
}

a = b = c = 0

function adder(c) {
  alert(a + b + c)
}

dynamic(adder).bind({a: 1, b: 2})(3) // alert(6)

Usage in a plugin:

$.fn.somePlugin = function(userOptions) {
  var settings = $.extend(...);
  dynamic(settings.alerter).bind({settings: settings})()
}

$.fn.somePlugin.defaults = {
  favoriteColor: 'red',
  alerter: function() { alert("Paint me " + settings.favoriteColor) }
}

Cancel single image request in html5 browsers

10 votes

I'm loading (large) images dynamically to draw into a html5 canvas, something like this:

var t = new Image();
t.onload = ...
t.src = 'http://myurl';

But every once in a while would like to cancel the image request completely.

The only way I came up with is setting src to ''. i.e.

t.src = ''

This works in many browsers, but it seems that only Firefox actually cancels the http request for the image.

I tested this with Fiddler2 by disabling caching and enabling "emulate modem speed". Then running a fiddle to test canceling a image request. (I'd love to hear other ideas on how to test this)

I know there are ways to cancel all requests (as in this question), but I'd like to only cancel one.

Any ideas on other ways (especially on mobile browsers) to do this?

This is the only way that I managed to get it to work in all modern browsers (Chrome, Safari, Mobile-Safari, Firefox, and IE9).

  • Load an empty and hidden iframe
  • append an image tag to the body in the iframe
  • when the img.onload completes, you can use that image dom element to draw to an html5 canvas with drawImage()
  • if you want to cancel the load, issue a stop() on the iframe's contentWindow (or execCommand("stop", false) on contentDocument in IE).
  • after you cancel a image load, you can reuse the iframe to load more images.

I created a class for this, and put the coffeescript code (and it's compiled javascript) on github: Cancelable Html5 Image Loader

If you want to play with it, I also created a jsfiddle to test it out. Remember to start Fiddler2 (or something like it) to see that the actual network request is really being canceled.

Know what overflow:hidden has hidden

10 votes

I wat to know if there is any way you can call and use what the overflow:hidden has well hidden.

To clarify what I mean, in this example I would like to know that "This is hidden" is the hidden part of the div.

Is this even possible? How would you approach it?

I've tagged the question jQuery but of course whatever gets the job done is great, pure CSS or Javascript will do just fine.

Thanks in advance!

Try this:

CSS:

.text{


    outline:1px solid orange;

    width:100px;
    height:20px;
    overflow:hidden;

}

HTML:

<div class="text">This is shown. This is hidden</div>

<div id="result"></div>

<div id="container" style="visibility:hidden;"></div>

JS:

$("<span />").text($(".text").text()).appendTo("#container"); 

$("#result").append("<span>"+$(".text").width()+"</span><br />");
$("#result").append("<span>"+$("#container span").width()+"</span><br />");

$("#result").append("<span>Overflow: "+ (($("#container span").width() > $(".text").width()) ? "yes" : "no")+"</span><br />");

Example

EDIT

Try this:

based on this plugin

New Example

CSS:

.text{
    outline:1px solid orange;
    width:100px;
    height:20px;
    overflow:hidden;
}

HTML:

<br/>
<br/>
<div class="text" id="test1">This is shown. This is hidden</div>
<div class="text" id="test2">No hidden</div>
<br/>
<br/>
<div id="result"></div>

JS:

(function($) {

    $.fn.noOverflow = function(){

        return this.each(function() {

            var el = $(this);

            var originalText = el.text();
            var w = el.width();

            var t = $(this.cloneNode(true)).hide().css({
                'position': 'absolute',
                'width': 'auto',
                'overflow': 'visible',
                'max-width': 'inherit'
            });
            el.after(t);

            var text = originalText;
            while(text.length > 0 && t.width() > el.width()){
                text = text.substr(0, text.length - 1);
                t.text(text + "");
            }
            el.text(t.text());

            /*
            var oldW = el.width();
            setInterval(function(){
                if(el.width() != oldW){
                    oldW = el.width();
                    el.html(originalText);
                    el.ellipsis();
                }
            }, 200);
            */

            this["overflow_text"] = {
                hasOverflow: originalText != el.text() ? true : false,
                texOverflow: originalText.substr(el.text().length)
            };

            t.remove();

        });

    };

})(jQuery);

$("#test1").noOverflow();

$("#result").append("<span>Test 1</span><br />");

$("#result").append("<span>Has Overflow: "+ (($("#test1")[0].overflow_text.hasOverflow) ? "yes" : "no")+"</span><br />");

$("#result").append("<span>Text Overflow: "+ $("#test1")[0].overflow_text.texOverflow+"</span><br />");

$("#test2").noOverflow();

$("#result").append("<br /><span>Test 2</span><br />");
$("#result").append("<span>Has Overflow: "+ (($("#test2")[0].overflow_text.hasOverflow) ? "yes" : "no")+"</span><br />");
$("#result").append("<span>Text Overflow: "+ $("#test2")[0].overflow_text.texOverflow+"</span><br />");

How to load images dynamically (or lazily) when users scrolls it into view

10 votes

I've noticed this in numerous "modern" websites (e.g. facebook and google image search) where the images load only when user scrolls down the page enough to bring them inside the visible viewport region. What is this technique called, how does it work and in how many browsers does it work. And is there a jQuery plugin that can achieve this behavior with minimum coding.

Edit

Bonus: can someone explain if there is a "onScrolledIntoView" or similar event for HTML elements. If not, how do these plugins work?

Some of the answers here are for inifite page. What Salman is asking is lazy loading of images.

Plugin: http://www.appelsiini.net/projects/lazyload

Demo: http://www.appelsiini.net/projects/lazyload/enabled.html

EDIT: How do these plugins work?

This is a simplified explanation:

  1. Find window size and find the position of all images and their sizes
  2. If the image is not within the window size, replace it with a placeholder of same size
  3. When user scrolls down, and position of image < scroll + window height, the image is loaded

Good tips and tricks to "streamlining" your Javascript and jQuery

9 votes

Obviously you have the basic Minify and Packer techniques...

But I wondered if there are any little Javascript techniques for smaller code (like those alternative if statements with ? and : etc in them).

THEN, once I have nice streamlined code (...) I will minify/pack it up

A very good technique to help minifiers, is to pass variables into a self invoking function:

(function(window, document, $, undefined) {
      // all of your application logic goes in here
}(window, window.document, jQuery));

A minifier will then create shortcuts for the arguments, like a, b, c, d.

(function(a, b, c, d) {
}(window, window.document, jQuery));

Now, window, document and jQuery (if it's used) and the undefined value are accessed quite often normally. This will help to decrease the filesize even more.

A few nice Javascript shortcuts, are described in this article.

For instance, use ~~ instead of Math.floor().

var floored = Math.floor(55.2115);  // = 55

var floored = ~~(55.2115);  // = 55

Another really neat thing is, that almost all Javascript interpreters convert numbers for you. For instance, we want to have a setTimeout which fires after 3 minutes. Instead of doing it like

setTimeout(function() {
}, 180000);

or 60 * 3 * 1000, we can just call:

setTimeout(function() {
}, 18e4);

Which probably makes much more sense, on much bigger numbers, but anyway :-)

flash effect with jquery

9 votes

i want to fadein and fadeout backgroud-color using jquery but, i tried bellow code, it's affect the full div content , i need to add flash effect only for backgroud-color.

    $('.countbox').css("background-color","#FF0000").fadeIn("fast").delay(800)
.fadeout("fast");
<div class="countbox">checkout</div>

i tried this on also but it's not working

$('.countbox').css("background-color","#FF0000").fadeIn("fast").delay(800).css("background-color","#FFFFFF");

What's the problem anyone can help me !

Edit

oops! my answer not applying to all window . which one only giving flash effect for current window but i need to get the flash effect for all window.. for example :- When i click a button it should give me flash effect for div for all windows

exactly like this http://www.beezid.com/

to do this in separate windows as you're mentioning in your comments, you will need to have some sort of postback to a server to signal when this will happen.

extending omerkirk's answer (which is the correct way to do this IMO).

do an setInterval(function(){.get();}); that periodicially gets information from some background server that stores the current state (per user probably...). When the current state changes, you do the .animate(); on the current window's background to match that of the background server...

This can get very tricky and problematic if you have multiple 'driving' windows instead of just one master window and x client ones...

Really this is a bad idea IMO...

Finding memory leaks in JavaScript using firebug?

9 votes

Are there any add-ons for Firefox that I can use to find out with part of the JavaScript causes memory leaks?

I've got nothing for firefox, but the webkit inspector in Chrome has a profiler built in that is great for that kind of thing.

As an added bonus it also shows you all browser events such as repaints, so you can engineer your code to have the least impact on the browser.

CSS 3 equivalent to jQuery slideUp and slideDown?

9 votes

My application is performing poorly with jQuery's slideDown and slideUp. I'm looking to use a CSS 3 equivalent in browsers which support it.

Is it possible, using CSS 3 transitions, to change an element from display: none; to display: block; while sliding the item down or up?

Thanks!

You could do something like this:

#youritem .fade.in {
    -webkit-animation-name: fadeIn;
}

#youritem .fade.out {
    -webkit-animation-name: fadeOut;
}

@-webkit-keyframes fadeIn {
    0% {
        opacity: 0;
        -webkit-transform: translateY(startYposition);
    } 
    100% {
        opacity: 1;
        -webkit-transform: translateY(endYposition);
    }
}

@-webkit-keyframes fadeOut {
    0% {
        opacity: 1;
        -webkit-transform: translateY(startYposition);
    } 
    100% {
        opacity: 0;
        -webkit-transform: translateY(endYposition);
    }
}

Example - Slide and Fade:

This slides and animates the opacity - not based on height of the container, but on the top/coordinate. View example

Example - Auto-height/No Javascript: Here is a live sample, not needing height - dealing with automatic height and no javascript.
View example

Can IE manipulate XML using jQuery?

9 votes

What I am not trying to do:

  • Simply "read" XML in IE using jQuery. Been there, done that. Works for the most part.
  • Load XML via AJAX. This is a legacy system using XML in a hidden field (oh yah, baby!) between postbacks to store a wizard data structure. Rewriting it would suck.

What I am trying to do:

  • Manipulate the XML document using jQuery in IE
  • Use the same code across all browsers, using the native jQuery functionality

What I would be okay with:

  • Overriding/overloading the same jquery methods to get them to work in IE when manipulating the XML DOM.

It just doesn't work and I feel like it just isn't possible in a 100% cross browser way using plain old jQuery methods.

Case in point:

<!DOCTYPE html>
<html>
<head>
    <title>IE Sucks</title>
    <script src="Scripts/jquery-1.5.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        var xml =
            '<Browsers>' +
                '<CoolBrowsers>' +
                    '<Browser name="Opera"></Browser>' +
                    '<Browser name="Chrome"></Browser>' +
                    '<Browser name="Firefox"></Browser>' +
                '</CoolBrowsers>' +
                '<ShitBrowsers>' +
                    '<Browser name="IE6"></Browser>' +
                '</ShitBrowsers>' +
            '</Browsers>';

        $(function () {

            $("#xml").text(xml);

            var uncoolBrowser = $("<Browser />").attr("name", "IE7");

            // In 1.5, using this...
            var $xml = $($.parseXML(xml));

            // Nope. Works everywhere else, though!
            // var $xml = $(xml);     


            // Throws a "Type mismatch"
            // Works everywhere except IE
            // This is case sensitive (??? WTF ???)
            // Lowercase "shitbrowsers" nothing happens
            // Uppercase "SHITBROWSERS" nothing happens
            // Best part? $xml.find("ShitBrowsers").length === 1
            $xml.find("ShitBrowsers").append(uncoolBrowser);

            // Only way to output XML in IE
            $("#result").text($xml[0].xml);

            // Fuggetaboutit
            // Technically, it does work in IE but not when using $.parseXML()
            // $("#result").text($("<div></div>").append($xml.clone()).html());
        });
    </script>
</head>
<body>
    <pre id="xml"></pre>
    <pre id="result"></pre>
</body>
</html>

Is it possible? Can this simple scenario be done or has IE just forsaken us all? $(xml).everything, etc. works in FF, Opera, Chrome, and Safari.

Update

It is possible using voodoo magicks.

I've created a jQuery plugin that takes care of reconciling the differences between different browser handling of XML. I also made an .xml() function based on similar code elsewhere, though mine fixes an IE-only issue. This works in all browsers, IE7 & IE8 for sure, can't test IE6.

I have posted this on my github. If anyone has suggestions or improvements, let me know. There are several things I've already run into but I have been fixing them as I run into them.

This is more of a guess as I don't know offhand what .parseXml does but IE needs createElement for unknown node names. Can you try document.createElement('ShitBrowsers') for every new node you are going to manipulate?

This is the case with HTML5 and that's why there are shiv scripts. You can try just taking this:

http://html5shiv.googlecode.com/svn/trunk/html5.js

Copying it, append your new node names to var z, and then:

<!--[if lt IE 9]>
<script src="file.js"></script>
<![endif]-->

how to move a div with arrow keys

8 votes

I would like to move a div with my arrow keys using jQuery. So right, left, down and up.

Found a demo of what I want to accomplish here

I would like to be able to move a div around in another div.

How can this be done?

HTML:

<div id="pane">
    <div id="box"></div>
</div>

CSS:

#pane {
    position:relative;
    width:300px; height:300px;
    border:2px solid red;
}

#box {
    position:absolute; top:140px; left:140px;
    width:20px; height:20px;          
    background-color:black;
}

JavaScript:

var pane = $('#pane'),
    box = $('#box'),
    w = pane.width() - box.width(),
    d = {},
    x = 3;

function newv(v,a,b) {
    var n = parseInt(v, 10) - (d[a] ? x : 0) + (d[b] ? x : 0);
    return n < 0 ? 0 : n > w ? w : n;
}

$(window).keydown(function(e) { d[e.which] = true; });
$(window).keyup(function(e) { d[e.which] = false; });

setInterval(function() {
    box.css({
        left: function(i,v) { return newv(v, 37, 39); },
        top: function(i,v) { return newv(v, 38, 40); }
    });
}, 20);

Variable explanations:
w - the maximal left/top value that the box can have (to stay within bounds)
x - the distance (in px) that the box moves in each interval
d - this object stores the information on what key is being pressed. For instance, while the user holds down the LEFT ARROW key, d['37'] is true. Otherwise it's false. BTW, 37 is the key-code for the LEFT ARROW key and this value is stored in the e.which property of the event object. The d object is being updated on each keydown and keyup event.

An setInterval which is executed every 20ms, updates the left and top CSS properties of the box element. The new values are calculated via the newv function.

The newv function will calculate the new left/top value based on a) the old value v and b) the d object.

The expression n < 0 ? 0 : n > w ? w : n ensures that the new value is in the permitted bounds (which are 0 to w). If n is < 0, zero will be returned. If n is > w, w will be returned.


Live demo: http://jsfiddle.net/bDMnX/7/


Update: This code has the same functionality as the original code above. The only difference is that I used more meaningful names for my variables and arguments. As you can see, it looks awful - the original version is clearly better. :P

var pane = $('#pane'),
    box = $('#box'),
    maxValue = pane.width() - box.width(),
    keysPressed = {},
    distancePerIteration = 3;

function calculateNewValue(oldValue, keyCode1, keyCode2) {
    var newValue = parseInt(oldValue, 10)
                   - (keysPressed[keyCode1] ? distancePerIteration : 0)
                   + (keysPressed[keyCode2] ? distancePerIteration : 0);
    return newValue < 0 ? 0 : newValue > maxValue ? maxValue : newValue;
}

$(window).keydown(function(event) { keysPressed[event.which] = true; });
$(window).keyup(function(event) { keysPressed[event.which] = false; });

setInterval(function() {
    box.css({
        left: function(index ,oldValue) {
            return calculateNewValue(oldValue, 37, 39);
        },
        top: function(index, oldValue) {
            return calculateNewValue(oldValue, 38, 40);
        }
    });
}, 20);

jQuery dollar sign ($) as function argument?

8 votes

I understand JavaScript closures, and I've seen this done in native JS:

(function () {
  // all JS code here
})();

But, what does adding the jQuery spice do?

(function ($) {
  // all JS code here
})(jQuery);

Its a way of mapping jQuery to the $ in a way so that not all code in a page will see it.

Maybe you have an existing script that uses jQuery that you like to reuse but you also use prototype that also uses $ in the same page.

By wrapping any jQuery using code in that construct you redefine $ to jQuery for the contained part without coming into conflict with other code in the page.

Consecutive Ajax calls

8 votes

I need a little help in my application design. Using Ajax I want to get some PHP resources consecutively but I don't think if it is good to retrieve them using JQuery $.ajax method.

I think something like this means wrong design:

$.ajax({
     url: SERVERURL+'index.php/home/checkAvailability',
     datatype: 'text',
     success: function(data){
        if(data == 'unavailable'){
           // do stuff
        }
        else{
           $.ajax({
              url: SERVERURL+'index.php/home/getWebTree/',
              dataType: 'json',
              success: function(data){
                 // do stuff
              }
           });
        }
     }
  });

Can anybody give me a suggestion to get a better design? How can I do the same in a better way?

Thanks!

EDIT: like @arnorhs tell us, using async parameter could be a solution. But I'm still think that there are other solutions instead of using consecutive ajax calls.

EDIT2: checkAvailability and getWebTree are PHP functions using CodeIgniter that I've developed to get resources from an external server using Http_Request object.

function checkAvailability() {
      $this->load->library('pearloader');
      $http_request = $this->pearloader->load('HTTP', 'Request');
      $http_request->setURL('http://myurl');
      $http_request->_timeout = 5;
      $http_request->sendRequest();
      $res = 'available';
      if (!$http_request->getResponseCode())
         $res = 'unavailable';
      return $res;
   }

Doing the calls all the same time

If you want to do all the ajax calls at the same time, you can simply call an ajax request right after the others. You could even assign them the same success handler. If you want a more "elegant" approach, I would do something like this:

// define a set of requests to perform - you could also provide each one
// with their own event handlers..
var requests = [
    { url: 'http://someurl', data: yourParams   },
    { url: 'http://someurl', data: yourParams   },
    { url: 'http://someurl', data: yourParams   },
    { url: 'http://someurl', data: yourParams   }
];

var successHandler = function (data) {
    // do something
}

// these will basically all execute at the same time:
for (var i = 0, l = requests.length; i < l; i++) {
    $.ajax({
        url: requests[i].url,
        data: requests[i].data,
        dataType: 'text',
        success: successHandler
    });
}

.

Do a single request

I don't know your use case, but of course what you really should be trying to do is retrieve all the data you're retrieving in a single request. That won't put a strain on your server, the site/application will seem faster to the user and is a better long term approach.

I would try to combine checkAvailability and getWebTree into a single request. Instead of receiving the data in Javascript as text objects, a better approach would be to receive them as json data. Luckily PHP provides very easy functions to convert objects and arrays to json, so you'll be able to work with those objects pretty easily.

edit: small modifications in the PHP code now that I understand your use case better.

So something like this in the PHP/CI code:

function getRequestData () {
    if (checkAvailability() == 'available') {
        $retval = array (
            'available' => '1',
            'getWebTree' => getWebTree()
        );
    } else {
        $retval = array (
            'available' => '0'
        );
    }   
    header('Content-type: text/javascript; charset=UTF-8');     
    echo json_encode($retval););
}

And the Javascript code can then access those by a single ajax request:

$.ajax({
    url: 'http://yoururl/getRequestData',
    dataType: 'json',
    success: function (jsonData) {
        // we can now access the parameters like this:
        if (jsonData.checkAvailability) {
            // etc
        }
        //and of course do something with the web tree:
        json.getWebTree
    }
});

.

Execute the requests synchronously

If you set the async parameter in the $.ajax options to false the functions will be made in a synchronous fashion so your code halts until execution has been completed.. or as the documentation says:

asyncBoolean

Default: true

By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

See http://api.jquery.com/jQuery.ajax/

Jquery not working in IE9 RC

7 votes

Hello all!

I have just upgraded to IE9 RC (which i must add isnt too bad an attempt by microsoft, so far, they still have time to mess it up! Please dont comment below on how wonderful/rubbish you think it is, I dont want a browser war!) in order to test websites.

Now I understand its only a release candidate, and is still being developed, but for some reason none of jQuery on my site is not being rendered properly (I say not rendering properly, I really mean not working fullstop).

The only way to get it to work is to use IE9 Browser Mode and IE8 Standards. Using IE9 Broswer Mode and IE9 Standards stops the jQuery working.

I understand im probably going to have to wait until they either ugrade IE or the jQuery API but does anyone know why this is or possibly have a fix?

Cheers guys!

UPDATE

Ok so then guys you can either go back to jQuery V1.4 or use this release candidate of jQuery v1.5 - http://code.jquery.com/jquery-1.5.1rc1.js

http://code.jquery.com/jquery-1.5.1rc1.js

That should help ;)