23 Dec 2010

Hawt new jQuery UI effects!

Sup!? Told ya I'd be blogging about some cool stuff, so here 'tis! New jQuery UI effects!

I saw my buddy Paul Irish doing a shout out to developers to help out where they can and couldn't agree more with him. So I jumped on it and started with the first item in the list: porting these animations from Dojo to jQuery. I've got to say it's starting to look pretty good!

So, check out the first examples and let me know what you guys think. Any feedback is welcome!

If you're interested in following or - even better - joining the progress, you can watch my github repository or just keep tabs on my blog!

13 Dec 2010

You shouldn't bake a cake using MS Word!

79ab79b3_cake_fail

PS: I'll be updating with some real articles upcoming weeks!
What can you expect?
  • Dive into the jQuery Data Link plugin
  • A closer look at the new innovations made to jQuery 1.4.4 (also an update on my previous $.fn.data post)
  • And more practical solutions to your everyday problems (courtesy of #jquery questions)
16 Oct 2010

Digging into jQuery 1.4.3's data method

The data method in jQuery 1.4.3 has undergone a couple notable changes, which you should take into account when you're thinking of upgrading to this new and hawt version. 

I've listed all the changes the jQuery team made to the data method and added some code samples to visually explain what exactly is the difference is between jQuery 1.4.2 and 1.4.3 and what you should pay attention too when you're upgrading.

* When you're viewing the code examples, be sure to switch between jQuery 1.4.2 and 1.4.3 to see what exactly changed

** This post is regarding: http://blog.jquery.com/2010/10/16/jquery-143-released/

Access to data attributes

In jQuery 1.4.3 the data method now enables you to directly access any data- prefixed attributes attached to your element. Enabling you to access <div data-id="1"> by simply using $(elem).data ('id').jQuery will even evaluate values such as true, false, objects and such.

Example: http://jsfiddle.net/seankoole/GycKb/

Example using (valid!) JSON in attributehttp://jsfiddle.net/seankoole/7cf5A/

Note: The jQuery blog states: "The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery)."

However in my example, you can clearly see that changes made by the $.fn.attr method are also picked up. When looking closer we find out (http://tutorialzine.com/misc/experiments/jquery-source/ on line 1256) that the attribute elements aren't being cached, therefor untill you set a key with that exact name jQuery will always read from the data- attribute (also see native manipulation: http://jsfiddle.net/seankoole/xmrax/).

Storing objects extends the current cache

In jQuery 1.4.2 a simple $(elem).data ({foo: bar, bar: baz}) would result in overwriting all your stored data. In jQuery 1.4.3 the data method now uses $.extend to extend the cache data. This not only enables jQuery to always be sure their internal data is secure (such as events which is stored in .data ('events')) and won't be overwritten, but it also gives you more flexibility to store data coming from an external source (such as a JSON call).

What to watch when upgrading:

The integrity of your object can be damaged, which could cause unexpected results when fetching data. An example would be that you keep refreshing your elements data and then check if it still contains a specific key. This key won't be removed anymore by simply adding an object as argument.

Example: http://jsfiddle.net/seankoole/kHSMk/

Handling JavaScript objects

The new data method also treats native JavaScript objects differently than before. It used to keep the data internally not manipulating the object (except for adding a cache identifier). In 1.4.3 the data method doesn't cache JavaScript objects anymore, instead it stores and pulls everything on/from the object.

What to watch when upgrading:

Because jQuery doesn't use it's internal caching anymore for objects, your objects integrity could be damaged:

  • Because the data method now stores the data in the object itself, expected property values could be entirely different because it's being assigned a new value by the data method
  • Because the data method also reads directly from the object, the value of your data call could also not be the value you're expecting, because it might've been reassigned a new value somewhere else

Example: http://jsfiddle.net/seankoole/nyXS5/

Note: This is also used in the new Data Link plugin

Data events triggers

Not much happening here.. The release post of jQuery .1.4.3 states a change in the way setData and getData work: they won't bubble like they did in 1.4.2. After doing some research however, I found out that getData never actually bubbled in 1.4.2 (setData did).

Example: http://jsfiddle.net/seankoole/FbZK8/

Also the releasenotes introduce a new event called changeData which gets fired after the new value is assigned to the data property. Like getData and setData it also doesn't bubble.

Example: http://jsfiddle.net/seankoole/FbZK8/

What to watch when upgrading:

The only major change is that the events (actually just one) won't bubble anymore. Meaning you can't bind to a wrapper but you'll have to attach it directly to the element.

Flash

Its a small change, but still noteworthy. In jQuery 1.4.3 you can now also store data on <object> tags, but only if they're flash!

Conclusion

I can honestly say I'm a big fan of the new data method and I congratulate the team for their innovative idea and approach on it. I've enjoyed looking at the source, picking it apart and finding out some under the hood stuff.

If you have anything to add or comment to the research, please let me know by using the comment section!

15 Oct 2010

The perils of working with Facebook's FBJS

Recently I had set myself the task to write an interface for my Content Management System to publish content to either a personal page or a fanpage page on Facebook or how they call it: canvas. Assuming this wasn't so difficult I entered the developer namespace of Facebook, where I was unpleasently surprised by a couple of things.

It turns out Facebook has it's own set of JavaScript rules and regulations which it most cleaverly named FBJS. After using it I've come up with some important things you should know when developing with FBJS.

Before we start, let's ask ourselves:

What is FBJS?

FaceBook JavaScript is a JavaScript library which you can (hardly) compare to a library like jQuery. It can help you as a developer to make your pages more interactive with the use of DOM manpulation (event delegation, creating elements, ..), Proxy'd AJAX (to fetch content from your own server) and User Interface elements (dialog, modal).

When your application is loaded into a Facebook canvas, your FBJS is first parsed serverside by Facebook, prepending all your declared variables and functions with a namespace. Thus assuring them you will have no access to whatever JavaScript they themselves have on the page.

For example, when you write:

function foo (bar)

    var obj {propertybar}
    return obj.property
}

Facebook will parse this and turn it into:

function a12345_foo (a12345_bar)

    var a12345_obj {propertya12345_bar};
    return a12345_obj.property
}

The document variable

FBJS will even spoof the native document variable and replace it with it's own version providing you limit access to it's original and only enabling document.getElementById and document.createElement. That's it. Even the use of document.getElementsByTagName is not allowed!

The spoofed document variable is created to restrict your access in order to protect as well as Facebook and their visitor from misusage of JavaScript. In all fairness, I fully understand their reasons. You can imagine what kind of threats would arise if they would grant full JavaScript access to anyone.

However, these limitations will make life a living HELL for usas a developer. Because not only do they restrict the usage of the DOM. They also restrict you from using any JavaScript libraries such as jQuery or Dojo. Can you imagine doing simple animations? Traversing through the dom using a query method? These are two of the main features you'll miss when developing in FBJS and you'll have to do by hand.

DOM elements

The spoofed document variable offered by FBJS has a direct effect on DOM elements: these are spoofed as well. Here are a few important things you should know about DOM elements in FBJS.

As they are spoofed they won't shop up as normal elements in your console. Instead they are shown as Object {PRIV_obj}.

These DOM elements do not offer the attributes you're so used to in natie JavaScript. Instead they only offer methods of which you can see a list here.

DOM elements offer an addClassName, removeClassName, toggleClassName and hasClassName method.

The methods in DOM elements always return their respective element (unless metioned otherwhise) which means they are chainable. This means you can do div.addEventListener ('click', function () { }).addClassName ('listener1').addEventListener ('click', function () { }).addClassName ('listener2');

Event listeners/handlers, "waitforclick" and user interaction

FBJS supports event listeners in the same syntax as normal JavaScript, except the lack of the useCapture argument. Beside the syntax and lack of useCapture there is, however a big surprise waiting for those that will use them -- they won't get fired the first time.

Oke, for this to make sense, let me introduce you to another restriction Facebook has bound to the use of FBJS called waitforclick. You could call it a restriction, but it's actually an event listener bound to your canvas stating that any and all JavaScript will be stalled from execution untill the user either triggers a focus, click or mouseup event.

This means that all JavaScript - even that in self executing functions - will have to wait for this event to be triggered. Resulting the user having to click twice on elements to which you've bound a click event using the addEventListener method.

There is an upside: After the first waitforclick event all other pages you might link to that require the canvas to be reloaded, will not have this restriction. Note this does not include a complete refresh of the browsers window.

So, what's the workaround? There is one ways you can work around this.. and that's by using inline event listeners (e.g. <a href="" onClick="something (this);">).

Here's an example of a succesful splash fade to give you some insight in what you'd be working with:

<div id="splash" onClick="splash ();"></div>

function splash ()
{
    var el          document.getElementById ('splash');
    var duration    1000// 1 second fade
    var step        100;
    var current     1;
    
    (
        function run ()
        {
            var temp    current step;
            current        temp temp 0;
            
            el.setStyle ('opacity'current);
            
            if (current == 0)
                document.getElementById ('content').removeChild (el);
            else
                setTimeout (run10);
        }
    )();
}

Unlike the addEventListener method, which relies on the JavaScript to be ran first. Inline attached events are directly attached to the DOM element regardless of JavaScript execution. Thus, the code above will execute regardless of the waitforclick event, because you've bound the click event directly to the element. 

If you don't trust me.. I've tried a couple of work arounds which all failed to mislead the waitforclick restriction, like:

  • adding an inline onMouseOver="init ()" to my content container.. this however, to my surprise, did not work.
  • catching the event using an inline event, which will fail horribly
  • suggested Facebook technique http://developers.facebook.com/docs/fbjs#unobtrusive

No external JavaScript

Using FBJS you cannot include external files. For big applications it's always useful to seperate your code in files so I suppose they're telling you to KISS (Keep it simple, stupid).

Limited to inline JavaScript tags, my advice (and my personal method) is to store your files externally, but use a serverside method to include them between the inline <script/> tags. This will allow you to keep things seperate and flexibile while developing, while obeying the Facebook restrictions.

Facebook documentation is not always right

When developing with FBJS you'll realize their documentation is sometimes a bit off and sometimes even their logic. The easiest example is the code they've used in their Unobtrusive example.

Their idea to use addEventListener is a clean and respectable approach, I use it all the time. However, when the user loads the page for the first time and there hasn't been a waitforclick event, the init function will not run untill that event happens. Resulting you to have to click twice before the hello_world function is run.

Another great thing is their use of document.getElementByTagName which for one is a typo. But even if correct the use of document.getElementsByTagName isn't allowed.

Conclusion

Facebook's FBJS isn't all that and could surely use some upgrading. I'm very keen on looking at what they'll be offering with the upcoming iframe implementation. Will it be the same as they support for applications or something entirely different? Who knows!

All I can say, I hope you've learned from this post and comments and/or questions are always appreciated.

* Note: A great help in developing will be #facebook on freenode.net. These are the guys that already have delt with the issues I've described in this post and you'll probably find me there also :)

11 Oct 2010

addEventListener, the use of useCapture

On #jquery someone wanted to learn about binding events using JavaScript instead of - for example - using the onclick attribute. Easiest thing is to point them out to MDC's addEventListener page as it explains in dept the how, what and when.

However, the only thing I'm really missing is some information on what the third (useCapture) argument does when adding an event using target.addEventListener(type, listener, useCapture);

Quick introduction to events and bubbling

When an event is triggered the event bubbles up the DOM. This makes it possible to trace a click on a child element and treat it as a click on the parent element. In the following code a click on the span will bubble up the DOM and will also trigger a click event on the parent div:

<div>
    <span>click me</span>
</div>

This bubbling makes developing a lot easier as you can bind an event to a wrapper and just stuff it with other elements. You don't have to bind an event to every element to know whether it was clicked or not. If you've worked with events before, you'll know about this behaviour, but you might not know the influence of the useCapture argument.

useCapture (false)

Setting useCapture to false is the standard when using event listeners, it will let events bubble up the DOM as expected. The code in the introduction above uses this setting.

useCapture (true)

Setting useCapture to true creates an entirely different bubble effect. The event will first fire for the parent element that has useCapture set to true and will then jump down to the element you've actually clicked. After it has triggered that element it will bubble back up again, but it will not trigger the already triggered event for it's parent with useCapture (true).

To explain the difference between useCapture false and true, I've set up a jsFiddle which uses your console to show how the event is treated by your browser. This way you can see the difference when useCapture is set to true instead of false. To view the jsFiddle, click here.

Sean Koole's blogidyblog blog

An application developer, utilizing whatever tools the web will offer him (client and serverside), working at Yellowfizz and living in Amsterdam.