Ajax Bestiary: A Javascript Field Guide
 
Ajax Bestiary: A Javascript Field Guide
 
 

Entries Tagged as 'Tutorial'

Implicit Vs. Explicit Conversion in Javascript

Posted by Don Albrecht

A question emerged out of my boredom on my flight yesterday.  Which is faster, implicit vs explicit conversion.  Most javascript developers use implicit conversion out of habit. For example:

!!x; instead of Boolean( x ); and x + “”; instead of String( x);. 

I decided to try an experiment for myself and record the performance of casting a number to a Boolean or String on my Windows box in Safari 3, Firefox 2, Opera 9 and IE 7.

The Verdict:

Implicit conversion wins handily, demonstrating over a 7 fold performance increase in one test. Overall, the performance gain for using implicit conversion averaged out to 53% across browsers after 10 tests.

The Numbers:

  Implicit Boolean Explicit Boolean Implicit String Explicit String
Firefox 2 0.162 0.312 0.248 0.358
IE 7 0.042 0.100 0.074 0.152
Opera 9 0.030 0.088 0.020 0.142
Safari 3 0.028 0.036 0.074 0.100
Cross Browser Average 0.066 0.134 0.104 0.188

You can find the code I used after the jump.

Keep reading →

Javascript Best Practices: parseInt( x, 10 );

Posted by Don Albrecht

ParseInt is one of the handiest universal functions in javascript. Even though javascript’s ability to cast most any primitive to any other primitive on the fly is handy to say the least, sometimes we need to explicitly parse a string to make sure we have a legitimate number to work with.

ParseInt does this for us. What most developers don’t realize is that parseInt is base agnostic. While it typically assumes base ten, any base between 2 and 36 can be used and is indicated by the optional second argument.

Why is this a problem you might ask? Because octal numbers can be represented by a leading zero. In practice this can cause some interesting effects in your code.

For example:

var x = "010";

console.log( x );

console.log( x - 0 );

console.log( parseInt( x ) );

console.log( parseInt( x , 10 ) );

Returns:


"010"

10

8

10

Note: “010″ is equivalent to 10 in  “x - 0″!

!! You’re True (or False)

Posted by Don Albrecht

Ok, so you probably know that Javascript like most other programming languages treats “0″ as false and any other numerical value as true in logic statements. Usually, this is sufficient, unfortunately, sometimes, you need a bit more consistent behavior. For example, ( 2 && 3 && true ) = 2.

Luckily there is a simple fix. Since, ! only operates on boolean data. !(0) is true and !( any other non-null value is false). Therefore, !! returns the boolean value of the original expression.

Another way of coding it, would be “Boolean ( expression );” and directly casting the expression to a Boolean. All things being equal, this would honestly be my preferred way of doing it. After all, legibility in code is one of the utmost considerations for most development, but since bandwidth is also a major consideration in javascript and !! is reasonably intuitive, I personally use it wherever necessary.

Handling Nested Clicks with jQuery Revisited

Posted by Don Albrecht

Yesterday, I posted instructions for handling a series of nested clicks with jquery. Today I’m going to follow up that post with a more sophisticated solution to handle a corner case we discovered in testing. I will be rehashing some but not all of yesterdays solution in this tutorial, but you may want to review it.

The problem:

We have nested clickable divs created by using the jQuery $().click( function … ) function. If the user clicks on the nested div, the click event fires for the parent div as well. Since this isn’t traditional event bubbling, we aren’t able to restrict the event to the innermost div by returning false from the click function or using event.stopPropagation(); & event.cancelBubble = true;.

We handled this yesterday by the simple expedience of using a status flag to verify that a child div hasn’t already been clicked on and erasing the status flags globally when ever an element is selected. This works beautifully for most cases, unfortunately it makes it impossible to select the parent of a previously selected element.

The Solution:

We needed to build a solution that could deal with 5 cases:

  1. Target div is innermost clicked div
  2. Target div is not innermost clicked div but selection hasn’t been processed for innermost clicked div
  3. Target div is not innermost clicked div and selection has been processed for innermost clicked div
  4. Target div is innermost clicked div and parent of previously selected div
  5. Target div is child of innermost clicked div and was previously selected.

Our previous solution handled cases 1 - 3 well. We now need a fix for cases 4 & 5. We accomplish this by providing a tracking a bit more information than the selected / not selected flag. We declare a global variable clickedDivStack that maintains an array of the currently selected div & its ancestors.

First we determine if the target is the innermost div of a selected stack (none of its children have the selected flag set on them). In this case, we know we don’t have to worry about situations 4 & 5 so we simply set the div as selected. Then we reset the clickedDivStack array to contain only the target.

if (!$(target).find(".selected").size()) {
$('.selected').removeClass("elected");
$(target).addClass("selected");
clickedDivStack = [target];
return; }

Next, we check for case 4 & 5 by comparing the target to the contents of the clickedDivStack Array. If the length of the array is greater than 1 & the target is already in the array, we know that this was an attempt to click on the parent of a previously selected element & the current target is the innermost div of the new selection. We can then process this as a new innermost selection and return.

for (var i = 1; i < selecteddiv.length; i++) {
if (selecteddiv[i] == target) {
$('.selected').removeClass("elected");
$(target).addClass("selected");
clickedDivStack = [target];
return; }}

If the target is not a new innermost selection, it must be a parent div. Since we need to track parent divs, we add it to the array of parent divs.

clickedDivStack = [target];
return;

It’s a bit more complex, but the perfomance is excellent and it smoothly handles the click selection of divs, even coping with nested elements in all corner cases found.

Handling Nested Clicks With jQuery.

Posted by Don Albrecht

Alright, so here’s the problem. I need to apply the ability to select any div inside an ajax app. Including divs nested inside other nestable divs. ex.

<div id="outer" class="clickable">
<div id="inner" class="clickable"></div>
</div>

In jQuery, if I simply call $('.clickable').click(...); I wind up with a click event that fires twice when inner is clicked. Once with target inner and once with target outer. Since I only care about the inner most div selected, I need some way to ignore the click event on the outer div.

I achieve this by assigning an attribute to the currently selected div. In the case of my most recent project, I was able to piggyback on a class change, but any attribute would do.

Step 1: Determine if this is the innermost selected div

There are two possible scenarios for any target div. It is either the innermost clicked div or it isn’t. If it isn’t the innermost div it will either already have a child div with a set “selected” attribute or it won’t. If it has a selected child div, we escape.

if ($(target).find(".selected").size() ) { return; }

Otherwise, we remove all elements with set selected attributes and set the selected attribute for the target div.

$('.selected').removeClass( "selected");
$(target).addClass( "selected" );

Note: If the containing div was the first processed, we don’t have a problem because we will clean up the current selection when the function is called on the innermost div.

The system is working like a charm for me in my current project.  If anyone knows a more efficient way to do it, please share it in the comments below.

Streamline Your Javascript with Shorthand

Posted by Don Albrecht

D’bug has published a wonderful list of techniques for abbreviating Javascript and improving performance.

You can find the article here:

http://blog.reindel.com/2007/11/01/javascript-shorthand-tips-and-tricks/

LightBox, ThickBox & Framework Conflicts

Posted by Don Albrecht

Lightbox & CodaSlider aren’t compatible.  A situation that was brought to my attention while participating in the comments on a blog post at http://www.ndoherty.com/.  Conflicts like this are a common experience for many of us and I thought this was a good opportunity to explore the cause of one such conflict.

In the case of Lightbox & CodaSlider, the fundamental frameworks were at odds with each other.  Lightbox is built with the Prototype / Scriptaculous framework stack, CodaSlider uses the jQuery framework.  Superficially, this doesn’t seem like a big deal.  While it’s usually bad form to load down a web page with multiple frameworks, I know it’s a crime many of us have been guilty of in the name of expediency or through multiple vendor integrations.  Usually this works, but in this case, the developer was attempting to integrate two widgets that were instantiated at different times and by different methods.

Luckily, there’s a simple solution to the problem.  I directed her towards the popular “ThickBox” widget instead.  In fact, that’s the greatest strength of the Ajax Bestiary we all have at our disposal.  There’s usually another tool available for us to use and in the case of popular frameworks like jQuery, a native solution is out there.  So if you ever find yourself in this situation, try to find the native solution.

jQuery $ unleash the power of selectors

Posted by Don Albrecht

While jQuery is many powerful things, Selectors are quite possibly its most capable and useful feature. So here’s the jQuery Selector crash course.

The Ground Rules:

  1. Selectors work just like CSS (1-3) selectors # for ID’s, . for classes p, div, ul, li etc.
  2. XPath an also be used.
  3. CSS & XPATH selectors can be combined

The $ wrapper.

Selectors + $ = jQuery Nirvana. The $() function accepts any selector and returns an object that can be manipulated.
Filters 

jQuery filters enhance jQuery Selectors by providing additional logic.  Here’s a list of supported filters:

  • Not (selector)
  •  first
  • last
  • even
  • odd
  • eq( index) matches an elements index in returned array
  • gt( index) matches all elements after given index in an array
  • lt( index ) matches all elements before given index in an array
  • header matches all h elements (h1 h2 h3 etc)
  • animated (matches all elements that are currently being animated)
  • contains( text) matches all elements which contain given text
  • empty matches all empty elements
  • has(selector) matches all elements containing an element that matches the given selector
  • parent matches all elements that are parents / have child element. (opposite of empty)
  • hidden matches all elements of type hidden
  • visible (opposite of hidden)

Great Tutorial on OO programing in Prototype 1.60

Posted by Don Albrecht

Prototype 1.6 is fast approaching and we’re already seeing loads of developers adopting the update in projects.  As this tutorial shows, The improvements to Class & inheritance in are truly compelling reasons to jump.

Prototype 1.6 Inheritance tutorial via Ajaxian

Excellent Resource for Learning MooTools

Posted by Don Albrecht

This has been out there for quite a while now, but I thought it should be included in the bestiary out of completeness.

http://clientside.cnet.com