<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1263965490328633445</id><updated>2011-12-13T20:35:57.182+09:00</updated><category term='effects'/><category term='javascript libraries'/><category term='jsmake'/><category term='javascript animation'/><category term='Flash'/><category term='namespace'/><category term='html5'/><category term='Javascript'/><category term='closure'/><category term='perl'/><category term='Design Pattern'/><category term='jsslickspeed'/><category term='oop'/><category term='preprocessor'/><title type='text'>#web { border:none }</title><subtitle type='html'>(X)HTML,CSS, Javascript,PHP,perl and friends.
experimentation, discovery and odd hours...&lt;br&gt;
a notebook to keep track of my  learning on web development.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-9174756808756747337</id><published>2010-09-28T11:48:00.017+09:00</published><updated>2010-09-30T10:30:38.543+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jsslickspeed'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript libraries'/><title type='text'>jQuery,Ext custom css selectors: avoid the framework war</title><content type='html'>In the last &lt;a href="http://shiriru.blogspot.com/2010/09/jsslickspeed-css3-selectors-testing.html"&gt;entry&lt;/a&gt;, we saw how javascript frameworks compare when using css3 standard selector queries. Now, we will see how those frameworks compare when using custom css selectors,ie,not W3 standard selectors. jQuery is well known for implementing very nice shortcuts like ":input", ":radio" or ":even",":odd". We will see how these shortcuts are handled and see that you should avoid them when possible and stay away from the framework war...&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;












Test using jsslickspeed&lt;/h2&gt;
&lt;br /&gt;
&lt;a href="http://code.google.com/p/jsslickspeed/"&gt;jsslickspeed&lt;/a&gt; is a fork of &lt;a href="http://github.com/kamicane/slickspeed"&gt;slickspeed&lt;/a&gt; containing both standard selectors and custom selectors tests + document.querySelectorAll when available.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2010/09/jsslickspeed-css3-selectors-testing.html"&gt;Read the result for the standard selectors&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
Same frameworks, same browsers tested.&lt;br /&gt;
We will look into the custom css selectors test in this entry. You can &lt;a href="http://jsslickspeed.googlecode.com/svn/trunk/custom.html"&gt;run&lt;/a&gt; the test yourself.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;












CSS3 custom selectors result&lt;/h2&gt;
&lt;br /&gt;
It is not necessary to go through each browser results to say that frameworks custom implementation slows down from little to greatly the speed of the test.&lt;br /&gt;
&lt;br /&gt;
You can find all the result charts at the end of this article but let's sum up...&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt; Custom selectors not handled by libraries does not throw any error&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
Obviously, not all libraries implement the same selectors...&lt;br /&gt;
most of them implement the attribute negation look up "!=", the pseudo-class ":contains" and some of them ":even" and ":odd".&lt;br /&gt;
This basically means that we enter in a non-standard world where the selectors you were using with one framework may not work, even worse, send back results instead of throwing an error.&lt;br /&gt;
Well, if you are a jQuery guru, an ExtJS guru, using each framework custom selectors within one project is not going to be harmful but you may need to switch of javascript framework for your new job and you will have to learn anew what you can use and what you can not use. If you force yourself to use standard selectors, this problem will not occur.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Native standard selectors are most of the time faster than the custom ones&lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
some concrete examples:&lt;br /&gt;
&lt;br /&gt;
jQuery ":parent" tooks 8ms against 1ms for ":not(:empty)"&amp;nbsp; in Firefox 3.6...&lt;br /&gt;
&lt;br /&gt;
jQuery "div &amp;gt; *:input" took 115ms against 4ms for its counter part (i have to say that the native one is very long: div &amp;gt; input,div &amp;gt; select,div &amp;gt; textarea,div &amp;gt; button) in IE6&lt;br /&gt;
&lt;br /&gt;
jQuery ":submit" tooks 20 ms against 1ms for "[type=submit]" in Firefox even though the doc seems to specify cross-browser issue being handled...&lt;br /&gt;
&lt;br /&gt;
":odd" and ":even" takes about 13ms against 3ms for ":nth-child(even|odd)" for jQuery while Ext JS which implements these shortcuts too took a constant time. READ BELOW FOR A POSSIBLE REASON&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Custom shortcuts are not implemented the same way...&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
It seems like we are in the "browser war" again where each framework wants to implement its extra feature to make the difference...because it sounds better this way...&lt;br /&gt;
This get tricky though.&lt;br /&gt;
jQuery implements :even and :odd has a shortcut for nth-child(even) and nth-child(odd) with the difference that it is a 0 based indexed whereas the W3 standard states a 1 indexed based calculation. &lt;br /&gt;
But well, it could be ok if...&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Shortcuts may not work properly &lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;i&gt;jQuery&lt;/i&gt; returned exactly the same result for both :even and :odd...&lt;br /&gt;
&lt;br /&gt;
Looking at the result you will see the library returns the exact same number for those two selectors...so : div &amp;gt; p:even == div &amp;gt; p:odd. Both of them different from div &amp;gt;p:nth-child(even) and div &amp;gt; p:nth-child(odd)...&lt;br /&gt;
Ext also implements the :even and :odd shortcuts but does follow the W3 standard declaration and use an index starting from 1. It does send back two different results for :even and :odd and these results do match there standard counterparts, nth-child(odd|even).&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Custom selectors... are not interoperable&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
Yes, like the old time,with browsers implementing their own javascript APIs because it seemed great at the time. This left us with an horrifying war-land where no browser could be trusted...&lt;br /&gt;
ok, I am a little bit dramatic here but come to think of it...&lt;br /&gt;
If browsers decide to implement :even,:odd or :input but that they use for the first ones, the standard definition starting from 1? Libraries will have to resort to their own implementation in order to keep older applications running,eventually, slowing down the entire process. If :input is implemented but only send back input tag fields? The same here...&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;












Being a good citizen and avoid the framework war&lt;/h2&gt;
&lt;br /&gt;
All these shortcuts/customs selectors, not available by default are very useful and tempting but...&lt;br /&gt;
Obviously when you use a shortcut or a custom selector, libraries will have to use their own engine instead of using the native selector when available.&lt;br /&gt;
&lt;br /&gt;
What does it mean?&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp; It will be slower most of the time. You loose

 the speed of the native selector.&lt;/li&gt;
&lt;li&gt;&amp;nbsp;You loose the checking done by the native selector who has a real low level lexer(most of the libraries will silently return something instead of throwing an error when you write an unsupported selector)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Uncoherent implementation between frameworks is at best confusing at worst could lead to problem if the browser implements themselves these shortcuts. (let's say :even and :odd is implemented and are equal to nth-child(odd|even)... some libraries will have to resort to their own engine for compatibility issues and you will loose all the benefit of the native selector implementation). &lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;&lt;i&gt;As a result and for better interoperability you should use as much as possible the standard selectors.&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
If you can use a standard selector in lieu of a custom selector, please do so...It will be,well, standard, interoperable and faster for new browser and sometimes even older ones,for example:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;:parent use :not(:empty)&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;:even use nth-child(even)&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;:odd use nth-child(odd)&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;:input use input,select,textarea,button&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
For this one,if it is too long,most of the time your mark up should allow you to target them anyway like #formContainer label *. Obviously it does link your javascript to the underlying html layout which is not ideal...&lt;b&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt; &lt;/i&gt;&lt;br /&gt;
Below are the results for the custom selectors:&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="Safari 5 (Win) CSS3 custom selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,300&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,300,0,300,0,300,0,300,0,300,0,300,0,300,0,300&amp;amp;chd=t:67%7C112%7C157%7C77%7C82%7C38%7C40%7C16&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1+%283+errors%29%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0+%2810+errors%29%7CNative+Selector%2810+errors%29&amp;amp;chtt=Safari+5+%28Win%29+CSS3+custom+selectors" width="440" /&gt;

&lt;img alt="IE6 Emulated CSS3 custom selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,3000&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,3000,0,3000,0,3000,0,3000,0,3000,0,3000,0,3000,0,3000&amp;amp;chd=t:2891%7C971%7C835%7C844%7C1136%7C2440%7C2404%7C0&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1.0+%283+errors%29%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0+%281+error%29%7CNative+Selector%28not+implemented%29&amp;amp;chtt=IE6+Emulated+CSS3+custom+selectors" width="440" /&gt;
&lt;img alt="IE8 CSS3 custom selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,1500&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,1500,0,1500,0,1500,0,1500,0,1500,0,1500,0,1500,0,1500&amp;amp;chd=t:1222%7C754%7C603%7C200%7C362%7C1296%7C27%7C3&amp;amp;chdl=Prototype+1.6.1.0+%28non+supported%29%7CMootools+1.2.4+%28non+supported%29%7CExt+3.1+%283+errors%29%7CDojo+1.5+%28partial%29%7CjQuery+1.4.2+%28buggy%29%7CYUI+3.2.0+%28non+supported%29%7CRight+JS+2.0+%2821+errors%29%7CIE+Selector+%2821+errors%29&amp;amp;chtt=IE8+CSS3+custom+selectors" width="440" /&gt;
&lt;img alt="IE7 CSS3 custom selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,1500&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,1770,0,1500,0,1500,0,1500,0,1500,0,1500,0,1500,-10,1500&amp;amp;chd=t:1693%7C556%7C418%7C313%7C657%7C1328%7C1332%7C0&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1+%283+errors%29%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0+%2816+errors%29%7CIE+Selector+%28not+implemted%29&amp;amp;chtt=IE7+CSS3+custom+selectors" width="440" /&gt;
&lt;img alt="Chrome 6 (Win) CSS3 custom selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,300&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,300,0,300,0,300,0,300,0,300,0,300,0,300,0,300&amp;amp;chd=t:84%7C165%7C8%7C56%7C62%7C60%7C35%7C14&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1+%283+errors%29%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0+%2810+errors%29%7CNative+Selector+%2810+errors%29&amp;amp;chtt=Chrome+6+%28Win%29+CSS3+custom+selectors" width="440" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-9174756808756747337?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/9174756808756747337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=9174756808756747337' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9174756808756747337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9174756808756747337'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/09/jqueryext-custom-css-selectors-shortcut.html' title='jQuery,Ext custom css selectors: avoid the framework war'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-5361008909434907788</id><published>2010-09-27T23:19:00.010+09:00</published><updated>2010-09-28T11:53:06.899+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jsslickspeed'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript libraries'/><title type='text'>jsslickspeed: css3 selectors testing frameworks (jquery,dojo,mootools,prototype,yui,ext...) vs browser</title><content type='html'>How to create your own basic css selector in javascript.This was the plan for the next entry.Having a grasp of how this can be implemented could help many to improve the css selectors they use with their favorite framework. But before this article,it would be nice to know where actual javascript frameworks stands against one an other (including custom selectors created by some frameworks )and against the native implementation,document.querySelectorAll. Some results will be surprising...&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;












Libraries tested&lt;/h2&gt;
&lt;br /&gt;
First things first, a list of the library tested:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Prototype 1.6.1.0&lt;/li&gt;
&lt;li&gt;Mootools 1.2.4&lt;/li&gt;
&lt;li&gt;Ext js 3.1.0&lt;/li&gt;
&lt;li&gt;Dojo 1.5&lt;/li&gt;
&lt;li&gt;jQuery 1.4.2&lt;/li&gt;
&lt;li&gt;YUI 3.2.0&lt;/li&gt;
&lt;li&gt;RightJS 2.0&lt;/li&gt;
&lt;li&gt;document.querySelectorAll (when available in the browser).&lt;/li&gt;
&lt;/ul&gt;
I've included RightJS 2.0 in this tests as it was claiming to be the fastest (well, it's only a fraction of the framework that is tested) but unfortunately the css selectors supported are few...&lt;br /&gt;
We will see an in depth view of the results.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
























The test runner : jsslickspeed&lt;/h2&gt;
&lt;a href="http://code.google.com/p/jsslickspeed/"&gt;jsslickspeed&lt;/a&gt; is a fork of &lt;a href="http://github.com/kamicane/slickspeed/"&gt;slickspeed&lt;/a&gt; to use only javascript and add document.querySelectorAll in the list when available. Only tested with the following browsers so far: &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;IE6 (emulated with &lt;a href="http://www.my-debugbar.com/wiki/IETester/HomePage"&gt;IETester&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;IE7 (IE8 emulatation mode)&lt;/li&gt;
&lt;li&gt;IE8&lt;/li&gt;
&lt;li&gt;FF3.6&lt;/li&gt;
&lt;li&gt;Safari 5&lt;/li&gt;
&lt;li&gt;Chrome 6&lt;/li&gt;
&lt;/ul&gt;
jsslickspeed allows to load scripts from different servers too as I wanted to use google cdn when the library was available . &lt;br /&gt;
&lt;h2&gt;
























Tests contents&lt;/h2&gt;
2 tests:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jsslickspeed.googlecode.com/svn/trunk/index.html"&gt;CSS3 standard selectors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href="http://jsslickspeed.googlecode.com/svn/trunk/custom.html"&gt;CSS3 custom selectors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
If the standard selectors test does not need further explanation, the custom selectors test may need some explanation.&lt;br /&gt;
The frameworks offer some shortcuts, ie, :even or :radio or :submit, :contains, [attr!=foo]. We will see that these custom selectors are not implemented in the same way, may slow down the process and could even be buggy.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;























CSS3 standard selectors&lt;/h2&gt;
The test uses mostly the same selectors as the original slickspeed, I've just added some few selectors but nothing tricky (like weird construct to see how the library handles them).&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Let's start with IE series: IE6,IE,7 and IE8.&lt;/li&gt;
&lt;/ul&gt;
IE8 does have a document.querySelectorAll but unfortunately does not support css3 selectors.&lt;br /&gt;
The only one to fall in this pitfall is... RightJS. Having document.querySelectorAll does not mean that the browser supports css3 selectors. &lt;br /&gt;
This basically means that you can not write safely the same selectors across browser... Hope this bug will be fixed.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&lt;img alt="IE8" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,1500&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,1500,0,1500,0,1500,0,1500,0,1500,0,1500,0,1500,0,1500&amp;amp;chd=t:1058%7C706%7C513%7C135%7C181%7C1305%7C25%7C0&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0+%2811+errors%29%7CIE+Selector+%2811+errors%29&amp;amp;chtt=IE8" width="440" /&gt;&lt;br /&gt;
&lt;br /&gt;
The IE implementation of the selector is rather fast but does not support 11 selectors (and therefore,Right JS only using the native implementation without adding extra parser functionality when required has the same errors. The speed is not representative for this library here).&lt;br /&gt;
Dojo is the fasted followed by jQuery. YUI is extremely slow followed by Prototype, Mootools and Ext JS. &lt;br /&gt;
&lt;br /&gt;
Moving on to IE7...&lt;br /&gt;
This version of IE and below do not implement document.querySelectorAll.All the libraries use therefore their own css selector parser and implementation:&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="IE7 CSS3 standard selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,1500&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,1770,0,1500,0,1500,0,1500,0,1500,0,1500,0,1500,-10,1500&amp;amp;chd=t:1770%7C510%7C452%7C328%7C546%7C1397%7C1422%7C0&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0+%2815+errors%29%7CIE+Selector+%28not+implemted%29&amp;amp;chtt=IE7+CSS3+standard+selectors" width="440" /&gt;&lt;br /&gt;
&lt;br /&gt;
We can see that RightJS goes out of the roof but does not implement properly 15 selectors (attribute selectors,ie [class=example],are all wrong). YUI and Prototype are as slow as in IE8 but we can see that Ext JS and Mootools are faster than jQuery while Dojo is still the fastest.&lt;br /&gt;
&lt;br /&gt;
Let's move on to IE6...&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="IE6 Emulated CSS3 standard selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,3000&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,3000,0,3000,0,3000,0,3000,0,3000,0,3000,0,3000,0,3000&amp;amp;chd=t:2517%7C735%7C638%7C676%7C845%7C2175%7C2318%7C0&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1.0+%283+errors%29%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0+%281+error%29%7CNative+Selector%28not+implemented%29&amp;amp;chtt=IE6+Emulated+CSS3+standard+selectors" width="440" /&gt;&lt;br /&gt;
&lt;br /&gt;
Well, no real surprises, this is slow...&lt;br /&gt;
Ext JS is the first of all and Dojo, jQuery,Mootools follow. YUI,Prototype and RightJS(buggy anyway) are outsiders.&lt;br /&gt;
It is to note that Prototype has some selectors that make its result jumps... "div ~ p" for example takes about 450ms where other frameworks are between 40~100ms. All the attribute selectors are around 200ms and p:nth-child(n) is at 300ms against a 20~40ms for the others.&lt;br /&gt;
&lt;br /&gt;
As a conclusion on the IE series:&lt;br /&gt;
&lt;br /&gt;
IE8 does offer a native selector but unfortunately, by not implementing the css3 selectors can not be used reliably unless you intend to use only css2 selectors in your projects.&lt;br /&gt;
You should avoid RightJS if you intend to develop with css3 selectors in mind.&lt;br /&gt;
As for the speed concern, it would be too easy to reduce a library to its sole implementation of css selectors and if the speed is an indicator it can not be used a the primary reason to elude a framework(unless you intend to use heavily complex selectors beyond class selectors, id selectors and descendant selectors).&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Firefox&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;img alt="FF3.6.1 (Win) CSS3 standard selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,300&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,300,0,300,0,300,0,300,0,300,0,300,0,300,0,300&amp;amp;chd=t:108%7C185%7C228%7C89%7C84%7C72%7C83%7C49&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0%7CFF+Selector&amp;amp;chtt=FF3.6.1+%28Win%29+CSS3+standard+selectors" width="440" /&gt;
&lt;br /&gt;
&lt;br /&gt;
This gets better!&lt;br /&gt;
Prototype gets back in the track while misteriously Mootools and Ext are the slowest. But even the slowest is at around 230ms when compared to the 1400ms in IE8, this is really nothing!&lt;br /&gt;
&lt;br /&gt;
Obviously the native selector of Firefox is the fastest of all and now YUI is the first in the list.&lt;br /&gt;
Most of the libraries use the native implementation behind the scene and add some extras that's why the result gets tighter.&lt;br /&gt;
&lt;br /&gt;
Notice that Firefox implementations requires about 40ms to do the tests.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;need for speed or Chrome:&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Chrome 6 (Win) CSS3 standard selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,300&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,300,0,300,0,300,0,300,0,300,0,300,0,300,0,300&amp;amp;chd=t:66%7C89%7C75%7C42%7C32%7C28%7C38%7C14&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0%7CNative+Selector&amp;amp;chtt=Chrome+6+%28Win%29+CSS3+standard+selectors" width="440" /&gt;
&lt;br /&gt;
&lt;br /&gt;
Makes no surprise here but Chrome is blazing fast,it takes about 14ms for its native implementation to do the tests which is almost 4 times faster than Firefox. Obviously we are talking about ms here so it's not going to be as noticeable as the 2500ms of IE6...&lt;br /&gt;
&lt;br /&gt;
YUI is again the fastest of all, followed by jQuery,RightJS and Dojo.&lt;br /&gt;
RightJS using the native selector does get the test right this time.&lt;br /&gt;
Prototype,Mootools,Ext are not so bad but could gain in speed.&lt;br /&gt;
&lt;br /&gt;
&lt;img alt="Safari 5 (Win) CSS3 standard selectors" height="285" src="http://chart.apis.google.com/chart?chxr=0,0,300&amp;amp;chxt=y&amp;amp;chbh=a&amp;amp;chs=440x285&amp;amp;cht=bvg&amp;amp;chco=000000,0000FF,008000,FF9900,959529,C3D9FF,AA0033,FF0000&amp;amp;chds=0,300,0,300,0,300,0,300,0,300,0,300,0,300,0,300&amp;amp;chd=t:35%7C79%7C97%7C44%7C27%7C22%7C25%7C7&amp;amp;chdl=Prototype+1.6.1.0%7CMootools+1.2.4%7CExt+3.1%7CDojo+1.5%7CjQuery+1.4.2%7CYUI+3.2.0%7CRight+JS+2.0%7CNative+Selector&amp;amp;chtt=Safari+5+%28Win%29+CSS3+standard+selectors" width="440" /&gt;
&lt;br /&gt;
&lt;br /&gt;
Safari 5 is really fast natively and we basically have the same result as Chrome 6, no surprises here.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;i&gt;As a conclusion for the standard selectors &lt;/i&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Amongst all the libraries, Dojo and jQuery stands out as they offer the most reliable engine and speed. Prototype,YUI were very deceptive in IE while Mootools and Ext JS even if a little bit slow does offer some good results in every browsers.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: right;"&gt;
&lt;a href="http://shiriru.blogspot.com/2010/09/jqueryext-custom-css-selectors-shortcut.html"&gt;»Continue with custom selectors&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-5361008909434907788?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/5361008909434907788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=5361008909434907788' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5361008909434907788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5361008909434907788'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/09/jsslickspeed-css3-selectors-testing.html' title='jsslickspeed: css3 selectors testing frameworks (jquery,dojo,mootools,prototype,yui,ext...) vs browser'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-8864377428946955279</id><published>2010-09-24T19:12:00.002+09:00</published><updated>2010-09-28T11:55:22.602+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>Javascript: fluent API via chaining</title><content type='html'>Javascript in the browser has a set of extension to traverse and manipulate the Document Object Model (DOM) that allows to create dynamic pages very easily. But... Well...&lt;br /&gt;
Nothing's new here. &lt;br /&gt;
One function amongst them has always bugged me: &lt;code&gt;elm.insertBefore()&lt;/code&gt;. For some reasons (who said my age?), I can not remember which parameters come first. We will use this example to see how we can create a fluent API using Javascript chaining functionality and write code as follow: &lt;br /&gt;
&lt;code&gt;insert(elm).before(elm2)&lt;/code&gt; and &lt;code&gt;insert(elm).after(elm2)&lt;/code&gt;!&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
insertBefore method&lt;/h2&gt;
&lt;br /&gt;
First things first, let's see what is the usage of this method.&lt;br /&gt;
Straight from &lt;a href="https://developer.mozilla.org/en/DOM/element.insertBefore"&gt;Mozilla dev center&lt;/a&gt;:&lt;br /&gt;
&lt;pre&gt;var insertedElement = parentElement.insertBefore(newElement, referenceElement);
&lt;/pre&gt;
&lt;br /&gt;
The &lt;code&gt;insertedElement&lt;/code&gt; returned is equal to &lt;code&gt;newElement&lt;/code&gt;.&lt;br /&gt;
&lt;code&gt;insertBefore&lt;/code&gt; requires the parent of the &lt;code&gt;referenceElement&lt;/code&gt; to do its job. Therefore, &lt;code&gt;parentElement === referenceElement.parentNode&lt;/code&gt;.
Let's add a &lt;code&gt;h1&lt;/code&gt; before the &lt;code&gt;p&lt;/code&gt; tag in the example below:&lt;br /&gt;
&lt;pre&gt;&amp;lt;div&amp;gt;
 &amp;lt;p id="myPara"&amp;gt;I am THE reference.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;script type="text/javascript"&amp;gt;

var para = document.getElementById("myPara");//referenceElement - p

var parentElement    = referenceElement.parentNode;     //parentElement - div

var title            = document.createNode('h1');       //newElement - h1
    title.innerHTML = 'I am a new kid on the block';

parentElement.insertNode(title,para);
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
After running this code, you should have the following HTML:&lt;br /&gt;
&lt;pre&gt;&amp;lt;div&amp;gt;
  &amp;lt;h1&amp;gt;I am a new kid on the block&amp;lt;/h1&amp;gt;
  &amp;lt;p id="myPara"&amp;gt;I am THE reference.&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
As you can see, it is not a very hard concept!&lt;br /&gt;
One little helper would be to not have to specify the parentNode ourself. Let's create a wrapper:&lt;br /&gt;
&lt;pre&gt;var DOM= {
  insertBefore: function(newElement,referenceElement) {

      //basic checking of the parameters
      if(!newElement || !referenceElement) return;

      var oparent = referenceElement.parentNode;

      //never know...
      if(!oparent) return;

      //go!
      return oparent.insertBefore(newElement, referenceElement);
  }
};

//usage example
var inserted = DOM.insertBefore(newElement,referenceElement);
&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;
insertAfter method&lt;/h2&gt;
&lt;br /&gt;
It's going to be even faster!&lt;br /&gt;
There is no such method!&lt;br /&gt;
But we can easily simulate this behavior by using the nextSibling method and one little thing I did not mention for now... again, straight from &lt;a href="https://developer.mozilla.org/en/DOM/element.insertBefore"&gt;Mozilla dev center&lt;/a&gt;:&lt;br /&gt;
&lt;br /&gt;
If referenceElement is null, newElement is inserted at the end of the list of child nodes.
&lt;br /&gt;
&lt;br /&gt;
So if there is no referenceElement, this is just going to &lt;code&gt;appendChild&lt;/code&gt; the element.If we do have a reference, we just need to get the &lt;code&gt;nextSibling&lt;/code&gt; and &lt;code&gt;insertBefore&lt;/code&gt; it.&lt;br /&gt;
Therefore, we could write our own &lt;code&gt;insertAfter&lt;/code&gt;:&lt;br /&gt;
&lt;pre&gt;var DOM= {

  //appended after insertBefore:

  insertAfter: function(newElement,referenceElement) {

      //basic checking of the parameters
      if(!newElement || !referenceElement) return;

      var oparent = referenceElement.parentNode;

      //never know...
      if(!oparent) return;

      var nextElement    = referenceElement.nextSibling;

     //in case, you have some trouble with IE
     //but could not verify this bug so...
     // if(!nextElement) return oparent.appendChild(newElement);
    //  else
      //go!
      return oparent.insertBefore(newElement, nextElement);
  }
};

//usage example
var inserted = DOM.insertAfter(newElement,referenceElement);
&lt;/pre&gt;
&lt;br /&gt;
Alright, we have now two helper functions DOM.insertBefore and DOM.insertAfter but we did not manage to make them "fluent". We did not even make them chainable... 
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Fluent way&lt;/h2&gt;
&lt;br /&gt;
So,we still have to make this functions easier to use, more "natural".&lt;br /&gt;
First, let's see how we can chain functions in javascript:&lt;br /&gt;
&lt;pre&gt;var DOM = {

    elm : null,//will hold the element to insert

    insert : function(elm) {
        DOM.elm=elm;
        return DOM;
    }
};
&lt;/pre&gt;
&lt;br /&gt;
As you can see it is not very hard! We just need to return the object itself to allow the chaining of the functions.&lt;br /&gt;
Let's implement before and after:&lt;br /&gt;
&lt;pre&gt;var DOM = {

    elm: null,

    insert: function(elm) {
        DOM.elm=elm;
        return DOM;
    },

    before: function(elm) {
        DOM.elm=DOM.elm.parentNode.insertBefore(elm, DOM.elm);
        return DOM;
    },

    after: function(elm) {
        DOM.elm=DOM.elm.parentNode.insertBefore(elm, DOM.elm.nextSibling);
        return DOM;
    },

    //a little helper to shortcut things...
    $: function(id){
        return document.getElementById(id);
    }
};

//usage
DOM.insert(DOM.$('myelm')).before(DOM.$('anotherelm'));

//we could add a check on the parameter to see if it's a string or an object
//we could then also write it:
DOM.insert('myelm').before('anotherelm');
&lt;/pre&gt;
&lt;br /&gt;
That's it!&lt;br /&gt;
I did not check the parameters to make the code shorter but you can DIY.

&lt;br /&gt;
&lt;h2&gt;
Conclusion&lt;/h2&gt;
Chaining functions in javascript is rather straight forward and can create easier APIs to use and remember by being closer to the natural language (well, English language here).
Obviously, this is an example where we use a unique object (Singleton) but we could implement the chaining for multiple instances too:&lt;br /&gt;
&lt;pre&gt;var DOM= {

    insert: function(elm) {
        this.elm = elm;
        return this;
    },

    before: function(elm) {
        this.elm=this.elm.parentNode.insertBefore(elm, this.elm);
        return this;
    },

    after: function(elm) {
        this.elm=this.elm.parentNode.insertBefore(elm, this.elm.nextSibling);
        return this;
    },

 //a little helper to shortcut things...
    $: function(id){
        return document.getElementById(id);
    }
};
var dom = new DOM.insert(DOM.$('myelm')).before(DOM.$('anotherelm'));
&lt;/pre&gt;
&lt;br /&gt;
In that case, we use the &lt;code&gt;new&lt;/code&gt; keyword to create the instance bound to &lt;code&gt;this&lt;/code&gt; and return &lt;code&gt;this&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-8864377428946955279?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/8864377428946955279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=8864377428946955279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/8864377428946955279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/8864377428946955279'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/09/javascript-fluent-api-via-chaining.html' title='Javascript: fluent API via chaining'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-9052057514112801262</id><published>2010-09-23T17:56:00.007+09:00</published><updated>2011-04-28T12:58:11.737+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Perl &amp; Javascript: 7 common features</title><content type='html'>Javascript which is used mainly in the browser and now also extends its power on the server side (&lt;a href="http://nodejs.org/"&gt;http://nodejs.org/&lt;/a&gt;) shares some features with an other programming language, perl.&lt;br /&gt;
perl community is very active and you can always find a module that does exactly what you need for your next project.95% of the time, somebody has already done the hard work for you! perl is a very nice language that shares some programmatic idioms with Javascript.&lt;br /&gt;
Both language contains a lot of treasure and a short entry could not list them all (perl is very very extra feature rich!) but we will see some common idioms in this entry!&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


literal notation&lt;/h2&gt;
&lt;br /&gt;
Javascript is well known for the literal notation which has made is way through JSON.&lt;br /&gt;
Let's see the javascript way of creating some data:&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;




Javascript way&lt;/h3&gt;
&lt;pre&gt;var myObject = {name:"john",age:24};  //a hash/object

var myArray   = [1,2,3,"hi"]; //an array

var myJSONLike = { //JSON like structure
   title :"my title",
   entry: [
      {
         id:1,
         content:"hi"
      },
      {
        id:2,
        content:"good bye"
      }
  ]
};
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;




Perl way&lt;/h3&gt;
&lt;pre&gt;my $object = {name=&amp;gt;"john",age=&amp;gt;24};  #a hash/object

my $array   = [1,2,3,"hi"]; #an array

my $JSONLike = { #JSON like structure
   title =&amp;gt;"my title",
   entry =&amp;gt; [
      {
         id=&amp;gt;1,
         content=&amp;gt;"hi"
      },
      {
        id=&amp;gt;2,
        content=&amp;gt;"good bye"
      }
  ]
};
&lt;/pre&gt;
&lt;br /&gt;
As you can see, javascript uses ":" to separate key/value pairs in the hash/objects where perl use "=&amp;gt;".&lt;br /&gt;
You can notice also that javascript uses the "//" for a single line comment where perl uses "#".&lt;br /&gt;
Variables in perl must all use a sigil ("$" sign here,but there is also "@" and "%" and some few others!) to specify the kind of data type you use (an array, a hash, a list, a reference,etc,etc). &lt;br /&gt;
An other difference is that perl uses the keyword "my" to declare a variable whereas javascript uses the keyword "var".&lt;br /&gt;
In javascript, the scope is only at the function level, which means that "var" will limit the scope of a variable to a function whereas in perl, the scope of a variable is at the block level:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;for(var i=0;i&amp;lt;=10;i++){
  doSomething(i);
}
console.log(i);//10 - exist out of the for block

function looping() {
   for(var i=0;i&amp;lt;=10;i++){
      doSomething(i);
   }
}
console.log(i);//error - exist only in the function scope
&lt;/pre&gt;
&lt;br /&gt;
&lt;pre&gt;for(my $i=0;$i&amp;lt;=10;$i++){
  doSomething($i);
}
print $i;#nothing or an error if you are in strict mode
&lt;/pre&gt;
&lt;br /&gt;
Block level scoping offers better granularity and javascript 1.7 in FF offers the "let" keyword that allows finer tune of the variable scope.
&lt;br /&gt;
The way you access the data differs too:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt; var hash = {name:"john"};
 hash.name;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt; my $hash = {name=&amp;gt;"john"};
 $hash-&amp;gt;{name};
&lt;/pre&gt;
&lt;br /&gt;
Javascript uses the "." notation whereas perl use the "-&amp;gt;" notation.
There are more things that could be explained regarding perl variables but as you can see javascript and perl literal notation is quite similar.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


Anonymous functions&lt;/h2&gt;
&lt;br /&gt;
Both perl and javascript offers anonymous functions:&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;var testing = function () {};
&lt;/pre&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;my $testing = sub() {};
&lt;/pre&gt;
&lt;br /&gt;
I guess the obvious difference is that javascript uses the "function" keyword whereas perl uses the "sub" keyword.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


Closure&lt;/h2&gt;
Closure allows you to trap the value of a variable:&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;function evenCounter() {
    var i =0;
    return function() {
         return i+=2;
   }
}
var evens = evenCounter();
evens(); // 2
evens();//  4
evens();//  6
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;sub even_counter {
   my $i = 0;
   return sub {
        return $i+=2; 
   }
}
my $evens = even_counter;
$evens-&amp;gt;();#2
$evens-&amp;gt;();#4
$evens-&amp;gt;();#6
#or
&amp;amp;$evens; #8
&lt;/pre&gt;
&lt;br /&gt;
In javascript the camelCase convention is used but in perl it is the hyphen convention that is most used. Obviously you are free to choose whatever convention you feel more comfortable with.&lt;br /&gt;
In perl, functions (subs) return the last statement so the "return" is not mandatory but preferred for readability.&lt;br /&gt;
In perl, subs do not need to be called with "()" but this is necessary in javascript to differentiate from a simple variable. &lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


Function introspection&lt;/h2&gt;
&lt;br /&gt;
Perl and javascript offers way to get some information about the context things are happening.
Here is a little example:&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;function service() {
  return 'service is used by: '+service.caller.name;
}

function consumer() {
   return service();
}
consumer();//service is used by: consumer
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;sub service { 
    return 'service is used by: '.(caller(0))[3]; 
} 
sub consumer {
    service();
} 
consumer();//service is used by: main::consumer
&lt;/pre&gt;
&lt;br /&gt;
Here many things to notice:&lt;br /&gt;
In javascript you can get access to a function caller via functionName.caller.name or arguments.callee.caller.name where as in perl you use the caller() function.&lt;br /&gt;
In Perl functions can return an array or a string according to the context.&lt;br /&gt;
Therefore:&lt;br /&gt;
&lt;pre&gt;my $package = caller;#return the package name
my ($package,$file,$line)=caller; #return a list of variables.
&lt;/pre&gt;
&lt;br /&gt;
That's why the code enclose the call to caller(0) with "()" to force a list context.&lt;br /&gt;
Then we access the 4th parameter of the list (counting from 0) that contains the function name.&lt;br /&gt;
Concatenation of strings in javascript uses the "+" sign but perl uses the "." sign.&lt;br /&gt;
Perl returns the name of the function and its package. The default being "main::".&lt;br /&gt;
There's no such concept in javascript.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


Function arguments&lt;/h2&gt;
&lt;br /&gt;
Both perl and javascript allows you to access the arguments via a magic variable.
&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;function service() { 
     return arguments.length; 
} 
function consumer() {
    service('hi','there');
} 
consumer();//2
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;sub service { 
    return scalar @_; 
} 
sub consumer {
    service('hi','there');
} 
consumer();#2
&lt;/pre&gt;
&lt;br /&gt;
Javascript uses the arguments keywords which is an array like object containing all the arguments passed to the function whereas perl uses the @_ variable which is also a list of all the arguments passed to the function.&lt;br /&gt;
In javascript we can access the number of arguments by using the length property.&lt;br /&gt;
In perl, we use the "scalar" keyword which forces a string context where perl returns the number of element in the list.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


Javascript 1.7 in FF&lt;/h2&gt;
Firefox has introduced new constructs that make javascript/perl a little bit more alike.&lt;br /&gt;
You must specify the version of javascript:&lt;br /&gt;
&lt;pre&gt;&amp;lt;script type="application/javascript;version=1.7"&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;h2&gt;


destructing assignments&lt;/h2&gt;
Create and assign in the same time. Less temporary variables required, neater code!&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;var a,b;
[a,b] = [1,2];  
 
[a, b] = [b, a];  

console.log(a,b);//2,1
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;my ($a,$b) =(1,2);

($a,$b)=($b,$a);

print $a,',',$b;//2,1
&lt;/pre&gt;
&lt;br /&gt;
In javascript you use the array notation on the left and right side of the assignment whereas in perl you use the list notation "()".&lt;br /&gt;
&lt;br /&gt;
In javascript you can send multiple values by using the array notation, it will be handled differently according to the context, a la perl!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;function multiValues() {
    return [1,2];
}
var [a,b]= multiValues();//list context
var a = multiValues();//array context
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;sub multi_values() {
    return (4,5);
}
my ($a,$b)= multi_values;#4,5
my $c = multi_values;#5 - last element in the list
#or
sub multi_values() {
    return wantarray? (4,5):[4,5];
}
my ($a,$b)= multi_values;#4,5
my $c = multi_values;#array containing 4,5
&lt;/pre&gt;
&lt;br /&gt;
In perl, if you use a scalar context when returning a list, you will get the last element in the list but we can use the wantarray function that let us know in which context the function is being called.
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


array comprehensions&lt;/h2&gt;
&lt;br /&gt;
Array comprehensions allow you to build a set of value in one line instead of using a loop.&lt;br /&gt;
Building an array containing 1 to 100:&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;var numbersTo100 = [i for each (i in range(1, 100))]; 
&lt;/pre&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;my $numbers_to_100 = [1..100]; 
&lt;/pre&gt;
&lt;br /&gt;
perl uses ".." to specify the range whereas javascript uses the range() function.&lt;br /&gt;
You can also create more complex data:&lt;br /&gt;
&lt;h3&gt;


javascript way&lt;/h3&gt;
&lt;pre&gt;var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];  
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;


perl way&lt;/h3&gt;
&lt;pre&gt;push @evens,($_%2==0) ? $_ : next  foreach (0..21);
&lt;/pre&gt;
&lt;br /&gt;
Perl uses the "$_" variable that is set automatically in different occasions,here the use of foreach.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;


Conclusion&lt;/h2&gt;
&lt;br /&gt;
We've seen some constructs that are somehow similar in both javascript and perl.
Don't hesitate to post similar patterns in other languages!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-9052057514112801262?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/9052057514112801262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=9052057514112801262' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9052057514112801262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9052057514112801262'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/09/perl-javascript-7-common-features.html' title='Perl &amp; Javascript: 7 common features'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-2840362090027362489</id><published>2010-09-22T16:28:00.000+09:00</published><updated>2010-09-22T16:28:02.045+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jsmake'/><title type='text'>Debugging anonymous functions in Javascript.</title><content type='html'>Javascript allows you to create function without name. That's why we name them (oxymoron), anonymous functions. Almost used everywhere, this kind of function can become a real nightmare to debug. We will see what is the problem and how to solve it.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;




Anonymous functions&lt;/h2&gt;
&lt;br /&gt;
Let's first see what is an anonymous function by looking at some code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;var myObject = {
    doSomething:function () {
       console.loh("my message");
   }
};

document.body.onclick=function(){
    myObject.doSomething();
}

&lt;/pre&gt;
The code
in it self does not do much...&lt;br /&gt;
But you can see that we define functions that do not have a name.&lt;br /&gt;
They are assigned to a property.&lt;br /&gt;
&lt;br /&gt;
Notice that:&lt;br /&gt;
&lt;pre&gt;var myFunc = function() {

}
function myFunc() {

}
&lt;/pre&gt;
&lt;br /&gt;
is different in the timing you will be able to call these functions.&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;myFunc();
var myFunc = function() {

}
&lt;/pre&gt;
&lt;br /&gt;
will fail but not:
&lt;br /&gt;
&lt;pre&gt;myFunc();
function myFunc() {

}
&lt;/pre&gt;
&lt;br /&gt;
Functions are parsed first and are available, whatever the order you write your code in.
(Not true in the console of Firebug though.)
&lt;br /&gt;
By the way, did you see the typo? console.loh() instead of console.log().&lt;br /&gt;
&lt;br /&gt;
If you run this script, you will get a nice error that you can look in Firebug, Firefox:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;onclick()
(?)()
&lt;/pre&gt;
&lt;br /&gt;
Not helping...&lt;br /&gt;
If you have hundreds of line of javascript code, I can tell you that it may take some time to get to the error...&lt;br /&gt;
&lt;br /&gt;
So how can we handle this?&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;




Name your anonymous functions&lt;/h2&gt;
ok,so what's the deal? name your anonymous functions, oxymoron, here, oxymoron there...&lt;br /&gt;
&lt;br /&gt;
It's easy, give a name to your anonymous functions:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;var myObject = {
    doSomething:function $_doSomething() {
       console.loh();
   }
};

document.body.onclick=function $_bodyClick(){
    myObject.doSomething();
}

&lt;/pre&gt;
&lt;br /&gt;
Prefixing all the anonymous functions with $_ is just a convention&lt;br /&gt;
that is going to help in a few seconds.&lt;br /&gt;
Traced in Firebug, you get:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;$_doSomething()
$_bodyClick()
&lt;/pre&gt;
&lt;br /&gt;
A little bit nicer than the cryptic first output!&lt;br /&gt;
&lt;br /&gt;
But naming anonymous functions for the sole purpose of debugging is going to add unnecessary bytes right??&lt;br /&gt;
Indeed, we should name them for debugging and erase their name for the live version.&lt;br /&gt;
But this is too much of hassle and nobody will do it unless...&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Javascript Preprocessor at the rescue.&lt;/h2&gt;
There are many preprocessors out &lt;a href="http://shiriru.blogspot.com/2010/07/why-bother-with-javascript.html"&gt;there&lt;/a&gt; that allows you to simplify the build process of your javascript files.&lt;br /&gt;
One of them,&lt;a href="http://code.google.com/p/jsmake-preprocessor/"&gt;jsmake&lt;/a&gt; (which I've also written-sorry), allows you to automatically name all your anonymous functions or do the opposite, remove their names.&lt;br /&gt;
&lt;br /&gt;
In order to remove all the anonymous function names, you will need to prefix them with $_. 
If you let the preprocessor name them instead of doing it by hand, it will prefix them with $_ so that you can remove them again very easily via the same preprocessor!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A simple example will be: &lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;
var testing = function () {
    return true;
}
var myObject = {
    doSomething:function () {
       console.log();
   }
};
document.body.onclick=function(){
    myObject.doSomething();
}
document.body.addEventListener('click',function(e){
    var object= {};
    object.testing = function() {
        return true;
    }
});
&lt;/pre&gt;
 &lt;br /&gt;
Once preprocessed, you get:
 &lt;br /&gt;
&lt;pre&gt;
var testing = function $_testing1 () {
    return true;
}
var myObject = {
    doSomething : function $_doSomething1 () {
       console.log();
   }
};
document.body.onclick = function $_onclick1 (){
    myObject.doSomething();
}
document.body.addEventListener('click',function $_anon1(e){
    var object= {};
    object.testing = function $_testing2 () {
        return true;
    }
});
&lt;/pre&gt;
 &lt;br /&gt;
You can read more about this &lt;a href="http://code.google.com/p/jsmake-preprocessor/#NAME_ANON"&gt;here&lt;/a&gt;.&lt;br /&gt;
 Don't hesitate to introduce other preprocessors that do the same thing or offer even more functionality!&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-2840362090027362489?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/2840362090027362489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=2840362090027362489' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/2840362090027362489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/2840362090027362489'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/09/debugging-anonymous-functions-in.html' title='Debugging anonymous functions in Javascript.'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-4510007382287481160</id><published>2010-07-09T19:03:00.007+09:00</published><updated>2010-07-11T13:54:41.673+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='jsmake'/><category scheme='http://www.blogger.com/atom/ns#' term='preprocessor'/><title type='text'>jsmake: a simple javascript preprocessor in perl</title><content type='html'>In the &lt;a href="http://shiriru.blogspot.com/2010/07/why-bother-with-javascript.html"&gt;previous post&lt;/a&gt; I listed some javascript preprocessors you could find out there...&lt;br /&gt;
But could not find any written in perl...&lt;br /&gt;
And could not find a preprocessor that could handle package dependencies...&lt;br /&gt;
Therefore,I've taken a day to hack a command line utility to use as a basic preprocessor for javascript.&lt;br /&gt;
Only tested on my mac, it's a dirty, huge perl file but it might help some people out there until there's a real project to build a javascript preprocessor in perl.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Functionality &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This utility can:&lt;br /&gt;
&lt;br /&gt;
- compress the javascript files with 3 different algorithms:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Javascript::Mini&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;Javascript::Packer&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;Google online closure application&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
- load and merge files in order of dependency:&lt;br /&gt;
&lt;br /&gt;
jsmake follows package rules used by perl or actionscript language.&lt;br /&gt;
It transpose the package name into a folder tree. Therefore:&lt;br /&gt;
&lt;br /&gt;
Core.Util.Array&lt;br /&gt;
&lt;br /&gt;
is understood as Core/Util/Array.js.&lt;br /&gt;
&lt;br /&gt;
You can specify the dependeny at the very first line of your javascript file in a comment as follow:&lt;br /&gt;
&lt;br /&gt;
/*!require: Core.Util.String,Core.Util.Queue */&lt;br /&gt;
&lt;br /&gt;
jsmake will load all the dependencies in all the files in the right order.&lt;br /&gt;
&lt;br /&gt;
- parse the javascript source file for some directives.&lt;br /&gt;
&lt;br /&gt;
ifdef, ifndef, end, define are understood:&lt;br /&gt;
&lt;br /&gt;
/*@ifdef DEBUG */&lt;br /&gt;
console.log("debug mode");&lt;br /&gt;
/*@end */&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*@ifndef DEBUG */&lt;br /&gt;
console.log("not in debug mode");&lt;br /&gt;
/*@end */&lt;br /&gt;
&lt;br /&gt;
or if you like # better:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*#ifndef DEBUG */&lt;br /&gt;
console.log("not in debug mode");&lt;br /&gt;
/*#end */&lt;br /&gt;
&lt;br /&gt;
/*@define VERSION 1.06 */&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;How to use&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
on the terminal, just type:&lt;br /&gt;
&lt;br /&gt;
$ jsmake&lt;br /&gt;
&lt;br /&gt;
if you do not need any options just make the file executable.&lt;br /&gt;
&lt;br /&gt;
There are obviously command line options:&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;&lt;a name="input"&gt;input&lt;/a&gt;&lt;/h2&gt;
$ jsmake -input ../lib&lt;br /&gt;
&lt;br /&gt;
This 
tells where to look for the javascript to be 
merged/preprocessed/smashed. &lt;br /&gt;
&lt;h2&gt;&lt;a name="output"&gt;output&lt;/a&gt;&lt;/h2&gt;
$ jsmake -output ../src/merged.js&lt;br /&gt;
&lt;br /&gt;
This
 tells where to output the final merged output. &lt;br /&gt;
&lt;h2&gt;&lt;a name="compression"&gt;compression&lt;/a&gt;&lt;/h2&gt;
$ jsmake -compression name&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example: &lt;br /&gt;
$ jsmake -compression mini&lt;br /&gt;
&lt;br /&gt;
This tells what kind of compression it should use. &lt;br /&gt;
There 
are 3 different compressors for now: &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;packer &lt;/li&gt;
&lt;li&gt;mini &lt;/li&gt;
&lt;li&gt;closure
 &lt;/li&gt;
&lt;/ul&gt;
Closure use google online closure service with the least 
aggressive algorithm. &lt;br /&gt;
So... you just need to be connected to the 
internet to use this one. &lt;br /&gt;
packer and mini requires perl modules 
to be installed, respectively JavaScript::Packer
 and JavaScript::Minifier.
 &lt;br /&gt;
&lt;br /&gt;
Using the compression will output 2 files:  &lt;br /&gt;
the one 
uncompressed and the one compressed prefixed with the name of the 
compression type, so it might be output.js and closure-output.js &lt;br /&gt;
&lt;h2&gt;&lt;a name="packages"&gt;packages&lt;/a&gt;&lt;/h2&gt;
$ jsmake -packages name separated by
 a space
 &lt;br /&gt;
&lt;br /&gt;
Example: &lt;br /&gt;
$ jsmake -packages Core.DOM Core.Util.String &lt;br /&gt;
&lt;br /&gt;
If
 you do not specify a package jsmake will merge all the files that 
contain the !require: directive. &lt;br /&gt;
By specifying the package name,jsmake will only merge the 
file necessary for this package to work as defined in your dependencies.
 &lt;br /&gt;
&lt;h2&gt;&lt;a name="vars"&gt;vars&lt;/a&gt;&lt;/h2&gt;
$ jsmake -vars name separated by a 
space
 &lt;br /&gt;
&lt;br /&gt;
Example: &lt;br /&gt;
$ jsmake -vars DEBUG STRICT_MODE &lt;br /&gt;
&lt;br /&gt;
By 
specifying the name of some variables, you will make them come true. &lt;br /&gt;
Therefore
 all the ifdef or ifndef will be stripped down accordingly. &lt;br /&gt;
if 
you want a STRICT_MODE but no DEBUG messages, you will write: &lt;br /&gt;
$ 
jsmake -vars STRICT_MODE &lt;br /&gt;
&lt;h2&gt;&lt;a name="define"&gt;define&lt;/a&gt;&lt;/h2&gt;
$ jsmake -define name=value variable
 name=value
 &lt;br /&gt;
&lt;br /&gt;
Example: &lt;br /&gt;
$ jsmake -define VERSION=6.01 AUTHOR=myself &lt;br /&gt;
&lt;br /&gt;
vars
 allows you to overwrite the one inline in your javascript file.  &lt;br /&gt;
So
 if you define in your javascript /&lt;b&gt;#define VERSION 3.01 &lt;/b&gt;/
 but at the command line &lt;br /&gt;
set the variable to 6.01, the final 
output will be 6.01 &lt;br /&gt;
Will look into merging vars and define 
functionality into one as it is confusing... &lt;br /&gt;
&lt;br /&gt;
That's
 it!!&lt;br /&gt;
&lt;br /&gt;
so if we go for a full option set up, you can get:&lt;br /&gt;
&lt;br /&gt;
$
 jsmake -input ../lib -output ../src/merged.js -packages Core.DOM 
Core.Util.String -vars DEBUG -define VERSION=6.12 AUTHOR=myself 
-compression mini&lt;br /&gt;
&lt;br /&gt;
This will create two files merged.js and 
mini-merged.js compressed, cleaned out and with all the dependencies.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Download &amp;amp; Doc&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://code.google.com/p/jsmake-preprocessor/"&gt;http://code.google.com/p/jsmake-preprocessor/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Hope this is useful too somebody and that you won't be too hard on my perl capacities. Comment to improve the code welcome!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-4510007382287481160?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/4510007382287481160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=4510007382287481160' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4510007382287481160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4510007382287481160'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/07/jsmake-simple-javascript-preprocessor.html' title='jsmake: a simple javascript preprocessor in perl'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-5981174819146518296</id><published>2010-07-08T13:57:00.018+09:00</published><updated>2010-08-31T22:52:05.020+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='preprocessor'/><title type='text'>Why bother with javascript preprocessors you say?</title><content type='html'>Javascript is a dynamic language that offers many features to create rich online applications and is now used as a key language in heavy ajax based online applications.&lt;br /&gt;
Although enhanced by profiling, debugging tools like Firebug for Firefox, javascript developing in itself still miss features offered since a long time by other static languages.One of this feature being a preprocessor syntax that could ease development.&lt;br /&gt;
&lt;br /&gt;
A preprocessor will allow you to add extra code (like debug statements, conditional flow) that will be stripped down before going live. Some will also give you the opportunity to compress/obfuscate the final output or even merge multiple files into one or why not create different built for different environment (why should you have IE related branching code that might increase file size, slow down the UI experience when you are developing solely for an iphone/ipad version of a website?).&lt;br /&gt;
&lt;br /&gt;
So that you can grab the concept of a preprocessor for those of you who did not use any, here is a short example:&lt;br /&gt;
&lt;br /&gt;
/*@define VERSION 1.1 */&lt;br /&gt;
&lt;br /&gt;


/*@require Base.js,Math.js */&lt;br /&gt;
&lt;br /&gt;


/*@ifdef DEBUG */&lt;br /&gt;

console.log("debug mode. Version:"+/*@=VERSION */);&lt;br /&gt;

/*@end */&lt;br /&gt;
&lt;br /&gt;


function sum(num1,num2) {&lt;br /&gt;
&lt;br /&gt;

    /*@ifdef STRICT_MODE */&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;         if(num1===undefined || num2===undefined){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;              throw new Error("the function requires 2 parameters");&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
    /*@end */&lt;br /&gt;
&lt;br /&gt;
/*@ifdef DEBUG */&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
     console.log(num1+num2);&lt;br /&gt;
    /*@end */&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return num1+num2;&lt;br /&gt;
}&lt;br /&gt;
This may sound rather hard to read but you will be able to create different builts.&lt;br /&gt;
&lt;br /&gt;

The "require" directive will merge the two files listed into this one.&lt;br /&gt;
When you call the preprocessor of your choice on the command line let's say,
just give it some options:&lt;br /&gt;
&lt;br /&gt;


jspreprocessor -vars DEBUG -output merged.js -compression mini&lt;br /&gt;
&lt;br /&gt;
You will get a merged.js file containing the following output:&lt;br /&gt;
&lt;br /&gt;
//..contents of the js files required goes here&lt;br /&gt;
console.log("debug mode. Version:"+1.1);&lt;br /&gt;

function sum(num1,num2) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     console.log(num1+num2);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return num1+num2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
but compressed on top of that!!&lt;br /&gt;
&lt;br /&gt;

The preprocessor stripped down the javascript to minimize overhead and unnecessary code lines (lightweight javascript file).&lt;br /&gt;
&lt;br /&gt;
Do you see how a preprocessor could come in handy??&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Hopefully, below is a list of preprocessors that exist and could help you in your future development if you do not already use them.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Javascript Preprocessor&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;language:&lt;/i&gt;&lt;span style="color: #660000;"&gt;javascript&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.bramstein.com/projects/preprocess/"&gt;http://www.bramstein.com/projects/preprocess/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
A preprocessor combine with &lt;a href="http://ant.apache.org/manual/index.html"&gt;Apache Ant&lt;/a&gt; or &lt;a href="http://www.mozilla.org/rhino/"&gt;Rhino&lt;/a&gt; Javascript Engine or simply call from within javascript!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;jscompiler&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;language:&lt;/i&gt;&lt;span style="color: #660000;"&gt;none (online)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://jscompiler.org/usage.php%20"&gt;http://jscompiler.org/usage.php&amp;nbsp;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
an online preprocessor using java like annotations.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;JS Built Tools&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;language:&lt;/i&gt;&lt;span style="color: #660000;"&gt;Java/xml (Ant suit)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://code.google.com/p/js-build-tools/"&gt;http://code.google.com/p/js-build-tools/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
a collection of Ant tasks that contains a preprocessor, a compressor (YUI) and a doc generation based on &lt;a href="http://blog.moxiecode.com/2009/08/19/introducing-moxiedoc/"&gt;MoxieDoc&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Jsmacro&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;language:&lt;/i&gt;&lt;span style="color: #660000;"&gt;python&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://github.com/smartt/jsmacro"&gt;http://github.com/smartt/jsmacro&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
a preprocessor following a syntax closed to C.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Sprocket&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;language:&lt;/i&gt;&lt;span style="color: #660000;"&gt;ruby&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://github.com/sstephenson/sprockets"&gt;http://github.com/sstephenson/sprockets&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
a preprocessor written in ruby mainly intended to join multiple files into one through "require" and "provide" directives. work well with &lt;a href="http://pdoc.org/"&gt;Pdoc&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Juicer&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;language:&lt;/i&gt;&lt;span style="color: #660000;"&gt;ruby&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://github.com/cjohansen/juicer"&gt;http://github.com/cjohansen/juicer&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Focus on combining js and css files, compressing them with different tools.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Js preprocessor&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;language:&lt;/i&gt;&lt;span style="color: #660000;"&gt;ruby&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://js-preprocessor.com/"&gt;http://js-preprocessor.com/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Focus on combining js and css files, compressing them with different 
tools.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
I certainly forgot some preprocessor out there but don't hesitate to comment about them and give feedback on the one listed above if you use them!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-5981174819146518296?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/5981174819146518296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=5981174819146518296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5981174819146518296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5981174819146518296'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/07/why-bother-with-javascript.html' title='Why bother with javascript preprocessors you say?'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-6624297464334879077</id><published>2010-06-30T16:48:00.004+09:00</published><updated>2010-07-02T15:04:03.861+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>hijacking javascript functions part 2 - Enforce Parameters Type</title><content type='html'>We've seen in the &lt;a href="http://shiriru.blogspot.com/2010/06/hijack-javascript-functions.html"&gt;last entry&lt;/a&gt; how we could hijack functions at distance and add some checking logic to the parameters in one place. We saved some typos, some possible mistakes and probably saved hours of debugging.But we needed to know the function parameters in order to check even some basic data types. Could not it be easier if like strongly typed languages, javascript could do this for us ?&lt;br /&gt;
&lt;br /&gt;
We will see in this entry how using some naming conventions could allow us to check parameters automagically at distance and save us even more typos and ease debugging!&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Getting javascript function code dynamically &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The very nature of javascript is that it is dynamic. So dynamic that you can even access to functions code, it is not hard:&lt;br /&gt;
&lt;br /&gt;
function doSomething(param1,param2,param3) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return param1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
now, to get the code of this very useful function, it is a one liner:&lt;br /&gt;
doSomething.toString(); // returns the above function code as a string&lt;br /&gt;
&lt;br /&gt;
What is even nicer in Safari/FireFox/Chrome is that they clean up the function layout for us before giving it back to us.&lt;br /&gt;
so the following function: &lt;br /&gt;
function doSomething(param1 /* String */,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param2 /* Number */,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; param3 /* Array */) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return param1;&lt;br /&gt;
}&lt;br /&gt;
will be returned as a string as: &lt;br /&gt;
&lt;br /&gt;
function doSomething(param1,param2,param3) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return param1;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Obviously, IE does return the function as written.&lt;br /&gt;
Why does it matter will you ask?&lt;br /&gt;
Let's see what we intend to implement so that it becomes clear...&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Using Naming Conventions&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Using common conventions when programming is useful and in our case will become primordial to our purpose.&lt;br /&gt;
The above function was using param1 and param2 as parameters which does not really help. Even you in 6 months when you will be looking back to your code, perplex...&lt;br /&gt;
We will change the function so that it uses a naming convention.&lt;br /&gt;
Let's use one:&lt;br /&gt;
&lt;br /&gt;
- String Object will all start with str + [A-Z]&lt;br /&gt;
so let's say that param1 is a String, we will change it to strParam1&lt;br /&gt;
&lt;br /&gt;
- Number Object will start with num + [A-Z]&lt;br /&gt;
so let's say that param2 is a Number, we will change it to numParam2&lt;br /&gt;
&lt;br /&gt;
- Array Object will start with arr + [A-Z]&lt;br /&gt;
so let's say that 
param3 is an Array, we will change it to arrParam3&lt;br /&gt;
&lt;br /&gt;
Many conventions exists and this is just an example. Just change to what fit best your programming methods and don't hesitate to add more types.&lt;br /&gt;
&lt;br /&gt;
so our first function will be changed to:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function doSomething(strParam1,numParam2,arrParam3) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return param1;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
You will see that in the end this will help for reading and maintenance purpose anyway.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Parsing the function code to get the parameters &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This is where things get dirty...&lt;br /&gt;
As IE does not send back a clean up version of the function, we shall look into many ways to parse the function but we will make it easy for our purpose.&lt;br /&gt;
We will assume that all functions put there parameters on one line, only separated by commas and with no space in between. Like so:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function doSomething(strParam1,numParam2,arrParam3) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return param1;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
We could certainly handle different patterns but the code will get ugly. The concept is the same so we will not look too much into it.&lt;br /&gt;
So let's write a simple helper function to get the parameters:&lt;br /&gt;
&lt;br /&gt;
DataController = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _getParametersName : function (code) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //if we did not get something just return&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(code===undefined || !code) return [];&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //split the parameters&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var matches&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = code.match(/\((.*\))/);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // return them or an empty array&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return (matches[1]) ? matches[1].split(',') : [];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
As you can see here, we shall look into more checking as to if the code parameters is really a string or not but let's pretend you will DIY.&lt;br /&gt;
How do we use it?Easy as pie:&lt;br /&gt;
var paramNames = DataController.getParametersName(doSomething.toString());&lt;br /&gt;
alert(paramNames);//should display strParam1,numParam2,arrParam3&lt;br /&gt;
&lt;br /&gt;
So we have our parameter names now with the extra information about their type!&lt;br /&gt;
Let's move on to the next step then...&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Hijacking function revisited &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
First a reminder with the above _getParametersName added:&lt;br /&gt;
&lt;br /&gt;
var DataController = {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _getParametersName : function (code) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //if we did not get something just return&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(code===undefined || !code) return [];&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //split the parameters&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var matches&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = code.match(/\((.*\))/);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // return them or an empty array&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return (matches[1]) ? matches[1].split(',') : [];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hijack : function(oPackage,fName,fConstraint) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var fCode = oPackage[fName];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(typeof fCode !=='function') return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; oPackage[fName] = function() {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var parameters = DataController.toArray(arguments);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var ret = fConstraint(fName,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ret) return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return fCode.apply(oPackage,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; addConstraint : function(oPackage, fConstraint) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for(var prop in oPackage) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DataController.hijack(oPackage,prop,fConstraint);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; toArray : function (arg){&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var ret =[];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(var i=0,ln=arg.length;i &amp;lt; ln;i++){&lt;ln;i++) {=""&gt;&lt;/ln;i++)&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ret.push(arg); &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp; _isString : function(str){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str===undefined) return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str.constructor===String)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
Look at the &lt;a href="http://shiriru.blogspot.com/2010/06/hijack-javascript-functions.html"&gt;previous entry&lt;/a&gt; for further details of the what, how and why.&lt;br /&gt;
Basically what we are going to do is add some default checking in the hijack functions.&lt;br /&gt;
It will not only use the callback but also use its own default parameter checking based on pre defined type. the default checking function will look like this:&lt;br /&gt;
&lt;br /&gt;
DataController = {&lt;br /&gt;
&lt;br /&gt;
_checkDefaultType : function(func,parameters) {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get the parameters name&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var awaitedVals&amp;nbsp; = DataController._getParametersName(func.toString());&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //loop through all the parameters found&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for(var i=0,ln=awaitedVals.length;i &amp;lt; ln; i++) {&lt;ln;i++){&gt;&lt;/ln;i++){&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //if the parameter start with num followed by a capital letter&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //we check if it is a number&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(awaitedVals[i].match(/^num[A-Z]/)){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //if it's not we just log a message and return false&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isNumber(parameters[i])){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log("parameter "+i+"should be a Number but got:"+parameters[i])&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //same thing but for Array&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(awaitedVals[i].match(/^arr[A-Z]/)){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isArray(parameters[i]))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log("parameter "+i+"should be an Array but 
got:"+parameters[i])&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //same thing but for String&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(awaitedVals[i].match(/^str[A-Z]/)){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(parameters[i]))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log("parameter "+i+"should be a String but 
got:"+parameters[i])&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
This function uses some functions not listed yet they just check for the type of the data. You will find a basic implementation at the end of this entry.&lt;br /&gt;
&lt;br /&gt;
Now that we have our default type checking function available, it is just a matter of adding it to the hijack function like so:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hijack : function(oPackage,fName,fConstraint) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var fCode = oPackage[fName];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(typeof fCode !=='function') return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; oPackage[fName] = function() {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var parameters = DataController.toArray(arguments);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //here is the magic part&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var ret = DataController._checkDefaultType(fCode,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ret) return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ret = fConstraint(fName,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ret) return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return fCode.apply(oPackage,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
That's it!!!&lt;br /&gt;
May seem a lot but it was quite easy (even if there is a lot of thing to do if you want to implement a more 'realistic' function parameter parser)&lt;br /&gt;
&lt;br /&gt;
So now what do we have?&lt;br /&gt;
Basically, we can add some constraint to the a package like so:&lt;br /&gt;
var toolbox = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; doSomething: function (strParam1,numParam2,arrParam3) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return param1;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
DataController.addConstraint(toolbox,function(){return true});&lt;br /&gt;
&lt;br /&gt;
Here we return true by default as we do not add any other checking.&lt;br /&gt;
Thanks to this one line three parameters will checked automagically:&lt;br /&gt;
&lt;br /&gt;
toolbox.doSomething("bonjour",2,[2,3,4]); // return bonjour&lt;br /&gt;
toolbox.doSomething(2,"bonjour",[2,3,4]); //oops, you inverted the parameters &lt;br /&gt;
// you will get a logged message in the console and false as a result&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
We've seen how using some naming conventions, the very dynamic of javascript could allow us to hijack functions and add default type checking for free!&lt;br /&gt;
We could add a flag:&lt;br /&gt;
DataController.mode="strict";&lt;br /&gt;
If set to strict the function could also check if the number of arguments meet the number of parameters.&lt;br /&gt;
if set to undefined, we could turn off the checking entirely too...&lt;br /&gt;
Possibilities are up to your imagination and your programming style!&lt;br /&gt;
&lt;br /&gt;
Do you see any case where this kind of feature in javascript could have helped you??&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Code&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
var DataController = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _checkDefaultType : function(func,parameters) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var awaitedVals&amp;nbsp; = DataController._getParametersName(func.toString());&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(var i=0,ln=awaitedVals.length;i&lt;ln;i++){&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(awaitedVals[i].match(/^num[A-Z]/)){&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isNumber(parameters[i])){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log("parameter "+i+"should be a Number but got:"+parameters[i])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(awaitedVals[i].match(/^arr[A-Z]/)){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isArray(parameters[i]))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log("parameter "+i+"should be an Array but got:"+parameters[i])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(awaitedVals[i].match(/^str[A-Z]/)){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(parameters[i]))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log("parameter "+i+"should be a String but got:"+parameters[i])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hijack : function(oPackage,fName,fConstraint) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var fCode = oPackage[fName];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(typeof fCode !=='function') return false;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; oPackage[fName] = function() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var parameters = DataController.toArray(arguments);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var ret = DataController._&lt;/ln;i++){&gt;checkDefaultType&lt;ln;i++){&gt;(fCode,parameters);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ret) return false;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret = fConstraint(fName,parameters);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ret) return false;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fCode.apply(oPackage,parameters);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; addConstraint : function(oPackage, fConstraint) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(var prop in oPackage) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataController.hijack(oPackage,prop,fConstraint);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; toArray : function (arg){&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var ret =[];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(var i=0,ln=arg.length;i &amp;lt; ln;i++){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ret.push(arg);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;&lt;br /&gt;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isNumber : function(str){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str===undefined) return undefined;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str.constructor===Number)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isArray : function(ar){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(ar===undefined) return undefined;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(ar.constructor===Array)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp; _isString : function(str){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(str===undefined) return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(str.constructor===String)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;var StringToolBox = {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; camelize: function(strVal) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/-(.)/g, function(m, l){return l.toUpperCase()});&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hyphenize : function(strVal) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/([A-Z])/g, function(m, l){return '-'+l.toLowerCase()});&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; firstToUpperCase : function(strVal) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^([a-z])/, function(m, l){return l.toUpperCase()});&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; trim : function(strVal) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^\s+|\s+$/g, '');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;DataController.addConstraint(StringToolBox,function(){return true;});&lt;/ln;i++){&gt;&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-6624297464334879077?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/6624297464334879077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=6624297464334879077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/6624297464334879077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/6624297464334879077'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/06/hijacking-javascript-functions-part-2.html' title='hijacking javascript functions part 2 - Enforce Parameters Type'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-8081927615579405771</id><published>2010-06-25T18:40:00.116+09:00</published><updated>2010-06-29T11:17:06.488+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='closure'/><category scheme='http://www.blogger.com/atom/ns#' term='namespace'/><title type='text'>hijacking javascript functions part 1</title><content type='html'>Javascript is as you may know, a loosely typed language (ie,you can not specify if a variable will be an integer, a float or an array...).&lt;br /&gt;
This can be a strength as it offers highly dynamic options that typed languages can not offer but this can also be a real nightmare when you need to debug something that went plainly wrong... &lt;br /&gt;
Typed language can offer control at the compilation phase and therefore can ease debugging by tracking bugs at an early stage. Javascript does not offer that.&lt;br /&gt;
&lt;br /&gt;
We will see in this article how we can use the highly dynamic nature of javascript to hijack functions and add control from outside. we will be able to check function parameters at distance and turn the process on/off easily.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Hijack function&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
What is so nice about javascript is that it is very dynamic and gives you enough power to manipulate functions at a very early stage.&lt;br /&gt;
Let's take a little library that deals with strings and add some utility functions: trim, hyphenize, camelize and firstToUpperCase.&lt;br /&gt;
&lt;br /&gt;
The code will be like:&lt;br /&gt;
&lt;br /&gt;
var StringToolBox = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; camelize: function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/-(.)/g, function(m, l){return l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hyphenize : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/([A-Z])/g, function(m, l){return '-'+l.toLowerCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; firstToUpperCase : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^([a-z])/, function(m, l){return l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; trim : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^\s+|\s+$/g, '');&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
For those of you who are new to javascript, this might be hard to understand.&lt;br /&gt;
we put all the functions in an object var StringToolBox= {...} in order to avoid conflict with other javascript scripts that could have the same exact function names. Therefore you will call the trim function like so: StringToolBox.trim('&amp;nbsp;&amp;nbsp; my string&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ');&lt;br /&gt;
Then we are using Regular Expressions to look for a pattern and change it the way we want.&lt;br /&gt;
&lt;br /&gt;
So far so good!&lt;br /&gt;
&lt;br /&gt;
But what happen if you do no pass the right parameter? If you do not pass anything or for some reasons, in the process an array gets passed??&lt;br /&gt;
&lt;br /&gt;
In order to check that you do get what you want, you will need to add some control on the data itself.&lt;br /&gt;
First let's create an helper function (basic):&lt;br /&gt;
&lt;br /&gt;
var DataController = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; _isString : function(str){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str===undefined) return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str.constructor===String)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
}; &lt;br /&gt;
We will use it this way:&lt;br /&gt;
&lt;br /&gt;
DataController._isString();//should return false&lt;br /&gt;
DataController._isString(1);//should return false&lt;br /&gt;
DataController._isString("hi!");//should return true&lt;br /&gt;
&lt;br /&gt;
So now let's implement this in our little toolbox: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var StringToolBox = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; camelize: function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(str)) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log('the first parameter must be a String 
Object but seen:'+str);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/-(.)/g, function(m, l){return 
l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hyphenize : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(str)) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log('the first parameter must be a String 
Object but seen:'+str);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/([A-Z])/g, function(m, l){return 
'-'+l.toLowerCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; firstToUpperCase : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(str)) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log('the first parameter must be a String 
Object but seen:'+str);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^([a-z])/, function(m, l){return 
l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; trim : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(str)) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log('the first parameter must be a String 
Object but seen:'+str);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^\s+|\s+$/g, '');&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
}; &lt;br /&gt;
OK!&lt;br /&gt;
As a note, you may decide to handle the error in different ways. Here we just log a message to the console (Firefox will work but this code will fail in IE) but we could throw new Error or do whatever you think is relevant for your application flow. &lt;br /&gt;
&lt;br /&gt;
Now we can be a little bit more confident about our code and where things might get wrong! But as you can see this is rather verbose, we need to copy/paste the same logic in 4 functions, it increases the file size and reduce readability...&lt;br /&gt;
If we were in a strongly typed language by defining the type of the first parameter, the interpreter/compiler could handle this for us for free...&lt;br /&gt;
&lt;br /&gt;
But javascript is dynamic enough to allow us to change that!&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;HIJACK function in use&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Before we see how we will build this function, let's see how we use it:&lt;br /&gt;
&lt;br /&gt;
var StringToolBox = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; camelize: function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/-(.)/g, function(m, l){return 
l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hyphenize : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/([A-Z])/g, function(m, l){return 
'-'+l.toLowerCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; firstToUpperCase : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^([a-z])/, function(m, l){return 
l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; trim : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^\s+|\s+$/g, '');&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
DataController.addConstraint(StringToolBox,function(fName,parameters) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(parameters[0])){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log('the first parameter must be a String 
Object but seen:'+parameters[0]);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
So as we can see, we moved all the control checking logic outside of the function and&lt;br /&gt;
sum it up in one place. Way much less typing (and we do hate typing!), way much less bytes and therefore a smaller file size and better readability!&lt;br /&gt;
the addConstraint function takes an object containing the functions as the first parameter and a function that handles the checking. the function itself is a callback that receives the name of the function being hijacked and the parameters it receives.&lt;br /&gt;
&lt;br /&gt;
so now, how do we implement that??&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;HIJACK function implementation&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
First of all we need to loop over all the functions in the object, this is going to be easy:&lt;br /&gt;
&lt;br /&gt;
var DataController = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; addConstraint : function(oPackage, fConstraint) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for(var prop in oPackage) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DataController.hijack(oPackage,prop,fConstraint);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
the addConstraint just loop through all the elements in the object (oPackage where o stands for object) and call the hijack functions that will get the package, the element being looped over and the callback (fConstraint where f stands for function).&lt;br /&gt;
So as you can imagine, the meat is in the hijack function, let's see its implementation:&lt;br /&gt;
&lt;br /&gt;
var DataController = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hijack : function(oPackage,fName,fConstraint) {&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //store the original function in a temporary variable, ie, store trim&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var fCode = oPackage[fName];&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //if this is not a function return early, nothing to hijack here&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(typeof fCode !=='function') return false;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //redefine the function in the package by overwritting it, ie redefine trim&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; oPackage[fName] = function() {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //every functions have a 'arguments' variable that holds the parameters&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //we just change this into a real array&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var parameters = DataController.toArray(arguments);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //we then use the callback functions that do the controlling&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var ret = fConstraint(fName,parameters);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //if the callback return false, something went wrong, we do nothing&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ret) return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //the parameter checking was ok so we call our original function, ie trim&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return fCode.apply(oPackage,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
}; &lt;br /&gt;
&lt;br /&gt;
Hum, this gets a little bit tricky...&lt;br /&gt;
I added comments to help grab the flow.&lt;br /&gt;
Basically, we use the very dynamic nature of javascript that allows us to redefine a function and overwrite it.&lt;br /&gt;
we first save the function in temporary variable, then we redefine the function by adding the checking callback. if the checking went wrong, we return but if everything was fine, we just call the original function held in the temporary function. This makes use of closure by the way.&lt;br /&gt;
the&amp;nbsp; DataController.toArray(arguments) loops over the arguments and push them into an array. that's all!&lt;br /&gt;
the fCode.apply allows us to keep the scope of the package in case the function was using it and allows us to send the parameters back to the original function.&lt;br /&gt;
all the functions were using only one argument but there could be several of them. Using apply allows us to solve the problem in one line!&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
We were able to add some checking onto the parameters sent to javascript functions by hijacking them. It keeps our code clean and reduce the file size.&lt;br /&gt;
As we hijack the function, we could easily turn the checking on/off by adding a flag too! Which could come in handy for live vs development environment.&lt;br /&gt;
&lt;br /&gt;
Although the function allows us to check parameters at distance, you still need to know the function and their parameters. Here it was one parameter, all of them being a String. This will not be true for every functions!&lt;br /&gt;
If the function changes, you will need to change the checking too.&lt;br /&gt;
Could not it be nice if we could check the parameters automagically without even having to know about the funcions themselves??&lt;br /&gt;
we will see how we can do this in the next part of this article!&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;FULL CODE &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
var DataController = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hijack : function(oPackage,fName,fConstraint) {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var fCode = oPackage[fName];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(typeof fCode !=='function') return false;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; oPackage[fName] = function() {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var parameters = DataController.toArray(arguments);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var ret = fConstraint(fName,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ret) return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return fCode.apply(oPackage,parameters);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; addConstraint : function(oPackage, fConstraint) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for(var prop in oPackage) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DataController.hijack(oPackage,prop,fConstraint);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; toArray : function (arg){&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var ret =[];&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(var i=0,ln=arg.length;i &amp;lt; ln;i++){&lt;ln;i++) {=""&gt;&lt;/ln;i++)&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ret.push(arg); &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ret;&lt;br /&gt;
&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp; _isString : function(str){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str===undefined) return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(str.constructor===String)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var StringToolBox = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; camelize: function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/-(.)/g, function(m, l){return 
l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; hyphenize : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/([A-Z])/g, function(m, l){return 
'-'+l.toLowerCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; firstToUpperCase : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^([a-z])/, function(m, l){return 
l.toUpperCase()});&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; },&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; trim : function(str) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return str.replace(/^\s+|\s+$/g, '');&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
DataController.addConstraint(StringToolBox,function(fName,parameters)
 {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if(!DataController._isString(parameters[0])){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log('the first parameter must be a String 
Object but seen:'+parameters[0]);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-8081927615579405771?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/8081927615579405771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=8081927615579405771' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/8081927615579405771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/8081927615579405771'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/06/hijack-javascript-functions.html' title='hijacking javascript functions part 1'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-9034167139150296909</id><published>2010-06-01T13:52:00.018+09:00</published><updated>2010-06-29T11:01:52.756+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='html5'/><title type='text'>html5 implementation of deeplinking a la swfaddress</title><content type='html'>I have been using &lt;a href="http://www.asual.com/swfaddress/"&gt;swfaddress&lt;/a&gt; for some heavy ajax based projects.&lt;br /&gt;
This library allows deep linking for Flash or Ajax based applications.&lt;br /&gt;
Deep linking means that a user knows exactly on which page he/she is after  after clicking (taping/touching/you-pick-your-favorite-platform-custom-behavior) on a link.&lt;br /&gt;
&lt;br /&gt;
One of the main problem with Flash/Ajax applications is that most of the time, you have one page handling all the navigation.&lt;br /&gt;
&lt;br /&gt;
The good points:&lt;br /&gt;
&lt;br /&gt;
- no page reload.&lt;br /&gt;
&lt;br /&gt;
- Better User Experience.&lt;br /&gt;
&lt;br /&gt;
But most of the time, no reload means also one and only one URL, no browser back button available...&lt;br /&gt;
swfaddress by using an anchor tag, removes these limitations.&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&lt;br /&gt;
Let's assume that this website is in Flash or Ajax and do not reload the page at all.
&lt;br /&gt;
http://www.yoursite.com/&lt;br /&gt;
&lt;br /&gt;
if you click on the 'About Us' link, you will see the contents appear but the URL will be:
&lt;br /&gt;
&lt;br /&gt;
http://www.yoursite.com/&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
not very practical...&lt;br /&gt;
&lt;br /&gt;
swfaddress mechanism will add an anchor to the URL (which will not force the browser to reload the page):&lt;br /&gt;
&lt;br /&gt;
http://www.yoursite.com/#aboutus.html&lt;br /&gt;
&lt;br /&gt;
Your link in a Ajax based environment is as usual:&lt;br /&gt;
&lt;br /&gt;
http://www.yoursite.com/aboutus.html&lt;br /&gt;
&lt;br /&gt;
when the link is clicked, you get an event in javascript which you can handle this way:&lt;br /&gt;
&lt;br /&gt;
new Ajax({&lt;br /&gt;
&lt;br /&gt;
url :event.target.href+'?raw=true',&lt;br /&gt;
&lt;br /&gt;
onSuccess:function(resp) {&lt;br /&gt;
&lt;br /&gt;
document.getElementById('content').innerHTML=resp&lt;br /&gt;
&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
NB1: "new Ajax({})", pick your favorite js library here.&lt;br /&gt;
NB2:The code is simplified! It is not an swfaddress/javascript tutorial.&lt;br /&gt;
&lt;br /&gt;
the "raw=true" query string just says the application to output the content without the header, menu, footer,etc. (this assumes that is handled by a php/perl/python program that can output the contents in different ways).&lt;br /&gt;
&lt;br /&gt;
Why bother eliminating the page content ? Why not just get rid off it right from the beginning??&lt;br /&gt;
&lt;br /&gt;
Well, you certainly want your website to be user-friendly and seo-friendly.&lt;br /&gt;
&lt;br /&gt;
Not all search engines handle the javascript loaded on your page when they crawl your website. Which means that you still must offer them a page that will be valid and makes sense on its own. (Of course, search engines are not the only ones... I can also mention the ones that turn their javascript off...)&lt;br /&gt;
All and all, you get bookmark-able urls, a functioning browser back button. Everyone is happy.
&lt;br /&gt;
&lt;br /&gt;
BUT...
&lt;br /&gt;
This seems very hacky and quite a lot of troubles will come in your way and back fire at you.
The overhead/load/security matters that the swfaddress implies are of concern too.&lt;br /&gt;
&lt;br /&gt;
Could it be easier if we could specify all of these directly in an "a" tag???
&lt;br /&gt;
Let's say:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href="aboutus.html" target="[#content]"&amp;gt;about us &amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will tell the browser to update the url so that it becomes http://www.yoursite.com/aboutus.html&lt;br /&gt;
BUT the target specified will imply to &lt;span style="font-weight: bold;"&gt;not reload the page&lt;/span&gt; and instead append the contents into the css selector element specified. Here an element with an id of 'content'...&lt;br /&gt;
&lt;br /&gt;
nobody is going to add the 'raw=true' thiny thing for you so you may have to handle this with javascript in some way (unless the browser adds a specific header when requesting the source this way!) but it will still avoid quite a lot of headaches and offer a more SEO friendly environment...&lt;br /&gt;
&lt;br /&gt;
Well, it is not very far from iframes in itself so if they did not do it this way the first time, it is certainly because I am missing something very crucial here.&lt;br /&gt;
&lt;br /&gt;
but still... would be nice.&lt;br /&gt;
&lt;br /&gt;
?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-9034167139150296909?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/9034167139150296909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=9034167139150296909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9034167139150296909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9034167139150296909'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2010/06/html5-implementation-of-deeplinking-la.html' title='html5 implementation of deeplinking a la swfaddress'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-204875571995914052</id><published>2008-07-01T19:05:00.004+09:00</published><updated>2010-09-28T11:57:17.441+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Understand JS and effect library in 10 parts</title><content type='html'>I've been quite buzy these months with work, my wedding and teeth!&lt;br /&gt;
Anyway, I am still in the middle of introduction to JS OOP thru a queue example but
I thought it could be nice to sum up all the entries written so for regarding javascript effects and javascript. &lt;br /&gt;
These entries, far to be perfect, can be a good base to understand how javascript libraries do their magic (like JQuery,Mootools,scriptaculous,etc) and will indeed allow you to almost create your own library with a little work.&lt;br /&gt;
&lt;h2&gt;
Javascript basics:&lt;/h2&gt;
These are some side entries that relate to javascript and some cross-browsers fix required, you should read them before getting in the animation series:&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/09/my-inner-request-for-outter.html"&gt;My inner request for outer&lt;/a&gt;&lt;br /&gt;
This entry deals with the basic of javascript closure,anonymous functions which will be used during the animation effect function creation.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/10/javascript-literal-notation-basics.html"&gt;Javascript Literal Notation: basics &lt;/a&gt;&lt;br /&gt;
This entry deals with the basic of javascript literal notation which is the based of JSON and will be used during the animation effect function.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/10/setting-html-element-style-thru.html"&gt;Setting html element style thru Javascript &lt;/a&gt;&lt;br /&gt;
This entry deals with cross-browser issues that one must deal when setting the style of an html element thru javascript. You will see camelCase, hypenize string and also that some people, in comments, thinks that teaching this is a waste of time. How nice isn't it?&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/11/javascript-scoping.html"&gt;Javascript scoping : Things to keep in mind&lt;/a&gt;&lt;br /&gt;
This entry deals with javascript scoping issues. If you were to read only one entry above all in these pre-introduction, I will choose this one as you will get a deeper understanding of the this keyword, what is var, when to use it...&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2008/01/javascript-memoizing-caching-functions.html"&gt;javascript : memoizing - caching functions result&lt;/a&gt;&lt;br /&gt;
This entry deals with the ability of javascript to memoize or overwrite itself to remember a function result. Very usefull for branching functions and could help to improve further some of your functions that needs cross-browser branching for example.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/12/javascript-simulating-namespaces-basic.html"&gt;Javascript : Simulating namespaces basic approach, part 1 &lt;/a&gt;&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/12/javascript-simulating-namespaces-part-2.html"&gt;Javascript : Simulating namespaces thru prototyping part 2 &lt;/a&gt;&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/12/javascript-namespaces-import-and-export.html"&gt;Javascript Namespaces : Import and Export methods &lt;/a&gt;&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2008/01/javascript-namespaces-privacy-thru.html"&gt;Javascript Namespaces : Privacy thru closure or how to type less! &lt;/a&gt;&lt;br /&gt;
This entry deals with something that misses in javascript language, the possibility to create namespaces. You will learn what is a namespace, why it is so important in javascript and how to simulate them thru objects. You should enforce your understanding of anonymous function and relate these entries to the javascript function scoping base nature.This hasn't be used while during the animation function but this is definitly something you should be aware of and use if you plan to share your scripts.&lt;br /&gt;
&lt;h2&gt;
Javascript Effects:&lt;/h2&gt;
These entries will hopefully teach you the basic of javascript animations.
These entries will require basic understanding of closure, literal notation,etc.
They will teach how works easing and css animation,so go on and read:&lt;br /&gt;
1. &lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-simple-easing.html"&gt;Javascript Animation : basics of easing&lt;/a&gt;&lt;br /&gt;
2. &lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-controlling-time-2.html"&gt;Javascript Animation : Controlling time (2) &lt;/a&gt;&lt;br /&gt;
3. &lt;a href="http://shiriru.blogspot.com/2007/10/javascript-animation-take-it-ease-y-3.html"&gt;Javascript Animation : take it ease-y ! (3) &lt;/a&gt;&lt;br /&gt;
4. &lt;a href="http://shiriru.blogspot.com/2007/10/javascript-animation-make-things-move.html"&gt;Javascript Animation : Make things move smoothly (4) &lt;/a&gt;&lt;br /&gt;
5. &lt;a href="http://shiriru.blogspot.com/2007/10/javascript-animation-changing-colors-5.html"&gt;Javascript Animation : Changing Colors (5) &lt;/a&gt;&lt;br /&gt;
6. &lt;a href="http://shiriru.blogspot.com/2007/10/javascript-animation-several-elements.html"&gt;Javascript Animation : Several elements at once (6) &lt;/a&gt;&lt;br /&gt;
7. &lt;a href="http://shiriru.blogspot.com/2007/10/javascript-animation-curving-path-7.html"&gt;Javascript Animation : Curving the path (7) &lt;/a&gt;&lt;br /&gt;
8. &lt;a href="http://shiriru.blogspot.com/2007/11/javascript-animation-strategy-and.html"&gt;Javascript Animation : Strategy and Factory Pattern at the rescue (8) &lt;/a&gt;&lt;br /&gt;
9. &lt;a href="http://shiriru.blogspot.com/2007/11/javascript-animation-implementing.html"&gt;Javascript Animation : Implementing Margin and Padding &lt;/a&gt;&lt;br /&gt;
10. &lt;a href="http://shiriru.blogspot.com/2008/01/javascript-animation-dynamic-fps-with.html"&gt;Javascript Animation : dynamic fps with setInterval &lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
I hope these entries will be helpfull to some of view!
There are still many things to be seen like effect queuing, custom events, dom ready,namespacing everything, DOM traversial, canvas, etc,etc,etc!!!
Therefore, I will update this page when I write a new entry regarding this subject.
&lt;br /&gt;
If you'd like to get more entries regarding these topics, please leave a comment
with some details of what you would like to read!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-204875571995914052?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/204875571995914052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=204875571995914052' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/204875571995914052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/204875571995914052'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2008/07/understand-js-and-effect-library-in-10.html' title='Understand JS and effect library in 10 parts'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-1024347492838844694</id><published>2008-02-23T12:08:00.010+09:00</published><updated>2010-06-29T11:01:36.319+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Javascript : Creating a queue system part 2 :OOP way</title><content type='html'>In the last entry, we have seen what was a queue and how to implement it in javascript, in a procedural way. We also noticed that we were limited in our possible use of the program as multiple queues were not possible. We will see how moving from procedural to object oriented approach will allow us to deal with multiple queues in a simple way.
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Reviewing the queue code&lt;/h3&gt;
&lt;br /&gt;
Before we go OOP, let's review the code first:
&lt;br /&gt;
&lt;pre&gt;var q      = [];
var paused = false;

function queue() {
    for(var i=0;i &amp;lt; arguments.length;i++)
       q.push(arguments[i]);
}
function dequeue() {
     if(!empty()) q.pop();
}
function next() {
     if(empty()) return;
     if(paused)   return;
     q.shift()();
}
function empty() {
     if(q.length==0) return true;
     return false;
}
function clear() {
    q=[];
}

//application aware flush function:
//update the div with the length of the queue

function updateDIV(delay) {

 function delayed() {
   document.getElementById('queued').innerHTML+=q.length;
   next();
 }
 setTimeout(delayed,delay);
}
function flush(delay) {
 updateDIV(delay);
}
&lt;/pre&gt;
You can always read the &lt;a href="http://shiriru.blogspot.com/2008/02/javascript-creating-queue-system-part-1.html"&gt;firt part&lt;/a&gt; to get a better understanding of this code.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Limits of the above code&lt;/h3&gt;
&lt;br /&gt;
The main drawback of this programming style is that we hold our main data, the queue array and the pause flag, in the gobal space. Therefore we cannot create several queue with the above code.&lt;br /&gt;
The main advantage of putting everything in the global space is that the code is straight forward:&lt;br /&gt;
&lt;pre&gt;queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
dequeue();
next();
paused=true;
flush();
&lt;/pre&gt;
As you can see, we don't really have to care about the queue array, we just let the program deal with it for us.
Now, let's see how we can try to implement multiple queues.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Multiple queues, the procedural way&lt;/h3&gt;
In order to deal with multiple queues, we first need to allow multiple queue container.&lt;br /&gt;
Therefore, we need to change our global queue as being a parameter of the function:
&lt;br /&gt;
&lt;pre&gt;function queue(q) {
    for(var i=1;i &amp;lt; arguments.length;i++)
       q.push(arguments[i]);
    return q;
}
function dequeue(q) {
     if(!empty()) q.pop();
     return q;
}
function next(q) {
     if(empty(q)) return q;
     q.shift()();
     return q;
}
function empty(q) {
     if(q.length==0) return true;
     return false;
}
function clear(q) {
    q=[]; 
    return q;
}

//application aware flush function:
//update the div with the length of the queue

function updateDIV(q,delay) {

 function delayed() {
   document.getElementById('queued').innerHTML+=q.length;
   next(q);
 }
 setTimeout(delayed,delay);
}
function flush(q,delay) {
 updateDIV(q,delay);
}
&lt;/pre&gt;
huummmm, as you can see, this is a little bit trickier...&lt;br /&gt;
I have dropped the paused flag in order to keep thing simple.&lt;br /&gt;
Let's see how we can use the above code:&lt;br /&gt;
&lt;pre&gt;var q1=[];
var q2=[];

q1= queue(q1,function(){updateDIV(q1,300)},function() {q1,updateDIV(500)},function(q1,updateDIV(450)));
q1= dequeue(q1);
q1 = next(q1);
flush(q1);

q2= queue(q2,function(){updateDIV(q2,300)},function() {q2,updateDIV(500)},function(q2,updateDIV(450)));
q2= dequeue(q2);
q2 = next(q2);
flush(q2);
&lt;/pre&gt;
Hummmm,,,&lt;br /&gt;
This is starting to be very hard!&lt;br /&gt;
Before, as we only had one and only one queue, we didn't have to care about which queue we were working on.&lt;br /&gt;
Now that we can have several queues, we need to indicate each time on which queue we are working to the function and we need to get back the queue to stay sync with the application...&lt;br /&gt;
in other words, this is a real pain in the butt!&lt;br /&gt;
Why is it that hard? &lt;br /&gt;
Could we simplify this??&lt;br /&gt;
Yes, we can, thanks to an object oriented approach!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The object oriented approach of the queue&lt;/h3&gt;
&lt;br /&gt;
So why the code get so difficult to write and certainly, in a long run, to maintain??&lt;br /&gt;
Because we are thinking in a procedural way:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;We have functions that work on a particular data.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
By thinking this way, we need to specify what is the data to the functions.&lt;br /&gt;
Depending on what you want to do, a procedural approach will be revealant, don't think that it is a wrong way of doing things (even if hardcore oop programmer will claim that even a if else statement is devil,,,just forget about them!!)&lt;br /&gt;
&lt;br /&gt;
So how should we think the problem?&lt;br /&gt;
If we change our way of thinking, we can move to the following:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;We have a particular data that possesses,has different methods.&lt;/i&gt;
&lt;br /&gt;
&lt;br /&gt;
And that's all!&lt;br /&gt;
Instead of thinking of different individual functions that work on a particular data, we need to think that we have a particular data that share, have particular functions/methods.&lt;br /&gt;
By simply inversing the first axiom,the subject of the action, we will be able to have the easyness of a global variable and the power of multiple data, ie, multiple queues.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The object in OOP&lt;/h3&gt;
&lt;br /&gt;
So, that's nice, we have inversed the problem and so what??&lt;br /&gt;
When we created our queue, we had a queue container, a queue pause flag and functions that work on the data.&lt;br /&gt;
If you remember the first approach, we first created our queue container, our pause flag and then called the different functions that were all working on the same data, the global queue and global pause flag.&lt;br /&gt;
Using an object approach, we are just going to allow to create several queue container and flag, each hold within a box, an object. Therefore each object will have it's own internal state of the data.&lt;br /&gt;
Come to think of it, if you have two identical TVs, one in your living room, one in your room.&lt;br /&gt;
If you turn on the TV in your living room, the one in your room is not going to start and hopefully.&lt;br /&gt;
You have two objects and each of them although they do the same thing, have their own state of information, their own data.&lt;br /&gt;
We are going to learn how to create TVs!!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Understanding the queue in a OOP way&lt;/h3&gt;
&lt;br /&gt;
Let's see how we will write the code in a OOP way:&lt;br /&gt;
&lt;pre&gt;var q1 = new Queue();
q1.queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
q1.dequeue();
q1.next();
q1.flush();

var q2 = new Queue();
q2.queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
q2.dequeue();
q2.next();
q2.flush();

&lt;/pre&gt;
If you remember the procedural approach with only one global variable, you will see that is very similar, but remember:&lt;br /&gt;
We do not have functions that work on a particular data.&lt;br /&gt;
We have a set of data that has some particular functions to work on.&lt;br /&gt;
The main, main difference is the following line:&lt;br /&gt;
&lt;pre&gt;var q1 = new Queue();
&lt;/pre&gt;
In the procedural way, we add:&lt;br /&gt;
&lt;pre&gt;var q1 = [];
var paused=false;
&lt;/pre&gt;
hum ??&lt;br /&gt;
But where did you write the line defining the paused flag in the OOP way??&lt;br /&gt;
In fact, remember, we are working with a set of data that we enclose in a box, an object.&lt;br /&gt;
Whene we write 'new Queue()', in the background we have created an object that has a queue container, an array, and a paused flag set to false!&lt;br /&gt;
If you have your TV on and that you change of channels, you don't expect your TV in your room to change of channel too, right?&lt;br /&gt;
Here it is the same thing, we have turned on our queue, set our initial state of information (an empty queue, a paused flag to false) and get an image back, in fact, an object holding all this information.&lt;br /&gt;
If you have never done OOP until now, you need to know that the return value is not a string or an array, it is what we call an object, which is yet an other structure of data.&lt;br /&gt;
We are lucky because in javascript creating an object is the same has using an hash, or associative array!&lt;br /&gt;
So we get back an hash that holds the following info:&lt;br /&gt;
&lt;pre&gt;var q1 = new Queue();
q1.toSource(); //=&amp;gt; {  queue:[],  paused:false };
&lt;/pre&gt;
But this hash is a little bit different from a simple hash.&lt;br /&gt;
If you buy exactly the same TV in a store, they will share exactly the same properties, the same features but if you need to repair one of them, you need to have a way to differentiate them, this can be a code barre or a client code.&lt;br /&gt;
Therefore, when you create a new object in javascript, you will get back a hash, that contains the name of the object, here Queue and obviously a particular memory address.&lt;br /&gt;
So when you do the following:&lt;br /&gt;
&lt;pre&gt;var q1 = new Queue();
var q2 = new Queue();
var q3 = new Queue();
&lt;/pre&gt;
You are creating each time a new Queue hash that has a particular memory address with their own state of the information.&lt;br /&gt;
&lt;br /&gt;
And what the heck with the rest of the code????&lt;br /&gt;
&lt;pre&gt;var q1 = new Queue();
q1.queue(function(){updateDIV(300)},function() {updateDIV(500)},function(updateDIV(450)));
q1.dequeue();
q1.next();
q1.flush();
&lt;/pre&gt;
How can we call functions on the q1 variable??&lt;br /&gt;
Again, remember, we do not have functions that work on a particular data, we have a set of data that has some functions.&lt;br /&gt;
In a OOP language, we don't refer to functions but to methods.&lt;br /&gt;
Each new queue container array and paused flag are not variables but properties.&lt;br /&gt;
Properties are state, methods are actions.&lt;br /&gt;
A human being has the following property : 2 legs, 2 eyes, a mouth, 2 ears,etc.
And a human being has the following methods, actions : run, walk, speak, sleep,etc.
Sleeping being my favorite action of all!&lt;br /&gt;
&lt;br /&gt;
So we have initialised our particular set of data, hold in an object called q1 and each time you will be calling methods (actions) on it, the methods will be working on the data of this object!&lt;br /&gt;
So with OOP, we can create has many queues as we want, we do not have to care about passing the queue array around or the paused flag around, everything is held within the object, within each object.&lt;br /&gt;
That's why our code is easier to write in the end because we do not have to deal with the state of the information, the object is doing it for us!!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
Writting the implementation code here will make the entry too long so we will see how to implement the OOP way in a third party!!&lt;br /&gt;
But I hope that this entry has help you understanding the difference between a procedural approach, where functions work on data and an object oriented approach where a set of data has methods.&lt;br /&gt;
Understanding this will allow to ease the next entry development phase!&lt;br /&gt;
I hope you have seen how powerful can be a OOP approach where an object can hold has many information as you want and deal with them internally without having you to care!&lt;br /&gt;
So keep on reading!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-1024347492838844694?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/1024347492838844694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=1024347492838844694' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/1024347492838844694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/1024347492838844694'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2008/02/javascript-creating-queue-system-part-2.html' title='Javascript : Creating a queue system part 2 :OOP way'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-4228439941082209150</id><published>2008-02-03T18:09:00.002+09:00</published><updated>2010-06-29T11:01:26.449+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Javascript - Creating a queue system part 1 : procedural way</title><content type='html'>We queue all the time : at the administration, at the supermarket, at school for lunch....&lt;br /&gt;
The first in the queue, will go out first and the last one, well, will be out the last. This is the basic system that many programs use to process commands,functions in a particular order, here the first in, first out order (FIFO). It can be used to create chained effects, delayed remote call to server, sending mails by bunch, etc. We'll see in this entry the underlyings of a queue!
&lt;br /&gt;
(this is a &lt;i&gt;very basic&lt;/i&gt; procedural approach, that will be improved in the next entry)
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Example&lt;/h3&gt;
Before we go on and dive into the coding of our queue system, let's see what we will be able to do with a simple example.&lt;br /&gt;
Each time you click on queue, you will add an elment in the queue.&lt;br /&gt;
Each time you click on dequeue, you will remove the last element in the queue.&lt;br /&gt;
When you click on the flush queue, all the elements are going to be called one after an other (when the last action has finished).&lt;br /&gt;
And pause, we'll just pause the queue!&lt;br /&gt;
You will see the number of element actually present in the queue each time you click on next in queue of flush queue:&lt;br /&gt;
So 0 means that there is nothing in the queue and 1,2,3 are the elements left in the queue:&lt;br /&gt;
&lt;script type="text/javascript"&gt;
var q=[];
var paused=false;

function queue() {
    for(var i=0;i &lt; arguments.length;i++)
       q.push(arguments[i]);
}
function dequeue() {
     if(!empty()) q.pop();
}
function next() {
     if(empty()) return;
     if(paused)   return;
     q.shift()();
}
function flush () {
     if(paused) paused=false;
     while(!empty()) next();
}
function empty() {
     if(q.length==0) return true;
     return false;
}
function clear() {
    q=[];
}

function updateDIV(delay) {

 function delayed() {
  document.getElementById('queued').innerHTML+=q.length;
  var width=40+i*q.length;
  document.getElementById('contents2').style.width=width+'px';
  next();
 }
 setTimeout(delayed,delay);
}
function updateDIVFlush(delay) {
 updateDIV(delay);
}
var i=0;
window.onload=function() {
addToQueue();
addToQueue();
}
function addToQueue () {
 i++;
 queue(function() {updateDIV(i*30)});
}
function removeFromQueue () {
 dequeue();
}
function nextInQueue () {
 if(paused==true) paused=false;
 next();
 paused=true;
}
function flushAllQueue () {
 paused=false;
 next();
}
function pauseQueue () {
 paused=true;
}
function clearQueue() {
  clear();
  document.getElementById('queued').innerHTML='';
  document.getElementById('contents2').style.width='40px';
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="queued"&gt;
&lt;/div&gt;
&lt;div id="contents2" style="background-color: blue; border: 1px solid black; color: white; height: 40px; width: 40px; word-wrap: normal;"&gt;
&amp;nbsp;
&lt;/div&gt;
&lt;a href="javascript:addToQueue()"&gt;queue&lt;/a&gt;
&lt;a href="javascript:removeFromQueue()"&gt;dequeue&lt;/a&gt;
&lt;a href="javascript:nextInQueue()"&gt;next in queue&lt;/a&gt;
&lt;a href="javascript:flushAllQueue()"&gt;flush queue&lt;/a&gt;
&lt;a href="javascript:pauseQueue()"&gt;pause&lt;/a&gt;
&lt;a href="javascript:clearQueue()"&gt;clear&lt;/a&gt;
&lt;br /&gt;
&lt;h3&gt;
 What do we queue?&lt;/h3&gt;
&lt;br /&gt;
A queue contains most of the time functions or commands that a program needs to execute in a FIFO order.&lt;br /&gt;
In javascript, a common use of queues are for chaining effects or even queueing remote server calls while offline or in a slow network context and that a call has failed...&lt;br /&gt;
It could also be used to trigger other functions when a certain signal is fired, like an event.Indeed, a queue is also the base of what could be our own event sytem triggering functions on demand!(observer pattern with subjects/ observers or publishers and subscribers).&lt;br /&gt;
As you can see queues can be very useful and indeed are!&lt;br /&gt;
Let's see the features a queue needs.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
What are the queue features?&lt;/h3&gt;
&lt;br /&gt;
&lt;br /&gt;
When you are queueing at the supermarket, you need to wait for the signal of the cashier to move forward.&lt;br /&gt;
Sometimes, you need to stop people from moving and pause them!&lt;br /&gt;
Sometimes, the cashier can ask you to go to an other place and get rid off you!&lt;br /&gt;
Sometimes, you just need to get rid off the entire queue because time is over!&lt;br /&gt;
Obviously, you need something that contains in the order they came in the clients.&lt;br /&gt;
Well, we are lucky because the container in Javascript, that keeps things in order they come is nothing more than an array!&lt;br /&gt;
Let's see:&lt;br /&gt;
&lt;pre&gt;var clients=[]; // or new Array();
clients.push('first in');
clients.push('second in');
clients.push('last in');
alert(clients[0]); 'first in'
alert(clients[1]); 'second in'
&lt;/pre&gt;
So as you can see, it was very easy to create the base of a queue!&lt;br /&gt;
We create an array and we just 'push' the clients as they come in!&lt;br /&gt;
the first client is in the slot 0 and the last one in the slot 1, as we only have 2 clients!&lt;br /&gt;
There is also a very useful function in Javascript in order to deal with arrays, it is the pop function that will just get rid off the last entry in the array:&lt;br /&gt;
&lt;pre&gt;var client= clients.pop();
alert(client); // 'last in'
alert(clients); // return in order : first in, second in
&lt;/pre&gt;
As you can see the pop get rid off the last element and send it back to us.&lt;br /&gt;
There is obviously the counter part of pop, that is, the shift function that gets rid off the first element in the queue:&lt;br /&gt;
&lt;pre&gt;var first = clients.shift();
alert(first); // 'first in'
alert(clients); // return : second in
&lt;/pre&gt;
So basically, we have all the 4 main ingredients required for a queue:&lt;br /&gt;
- a container : the array&lt;br /&gt;
- a way to add in order : push, adds element at the end of the array&lt;br /&gt;
- a way to remove the first element : shift&lt;br /&gt;
- a way to remove the last element : pop&lt;br /&gt;
&lt;br /&gt;
when we add an element at the end of the queue, we say that we 'enqueue' or 'queue'.&lt;br /&gt;
when we remove the last element of the queue, we say that we 'dequeue'
when we advance in the queue, which is to say, calling the first element in the queue and getting rid off it, we say that we 'advance' or that we call the 'next' in the queue.&lt;br /&gt;
When we call all the elements in the queue one after an other, we say that we 'flush'
the queue.&lt;br /&gt;
In the end, we restart the queue from the beginning, we 'clear' the queue.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The main functions&lt;/h3&gt;
&lt;br /&gt;
From there we can define the main elements required:&lt;br /&gt;
&lt;pre&gt;var q=[];//our queue container
var paused=false; // a boolean flag
function queue() {}
function dequeue() {}
function next() {}
function flush() {}
function clear() {}
&lt;/pre&gt;
you may also want to 'pause' the queue. We will therefore use a boolean flag too.
&lt;br /&gt;
Now let's see the implementation, this is going to be very straightforward:&lt;br /&gt;
&lt;pre&gt;var q      = [];
var paused = false;

function queue() {
 for(var i=0;i&amp;lt; arguments.length;i++)
     q.push(arguments[i]);
}
function dequeue() {
    if(!empty()) q.pop();
}
function next() {
    if(empty()) return; //check that we have something in the queue
    paused=false; //if we call the next function, set to false the paused
    q.shift()(); // the same as var func = q.shift(); func();
}
function flush () {
    paused=false;
    while(!empty()) next(); //call all stored elements
}
function empty() {  //helper function
    if(q.length==0) return true;
    return false;
}
function clear() {
    q=[];
}
&lt;/pre&gt;
&lt;script type="text/javascript"&gt;
function example1(){
queue(function() { alert(1)},function(){ alert(2)},function(){alert(3)});
next(); 
dequeue();
flush();
clear();
}
&lt;/script&gt;
And here we have our basic queue system!&lt;br /&gt;
let's see how we can use it:&lt;br /&gt;
&lt;pre&gt;queue(function() { alert(1)},function(){ alert(2)},function(){alert(3)});
next(); // alert 1
dequeue(); // the last function, alerting 3 is removed
flush(); // call everything, here alert 2
clear(); // the queue is already empty in that case but anyway...
&lt;/pre&gt;
&lt;a href="javascript:example1()"&gt;You can try the above code&lt;/a&gt;
&lt;br /&gt;
As you can see, it works like expected but let's say that instead of alerting something we decide to update a div...&lt;br /&gt;
Let's take the following function:
&lt;br /&gt;
&lt;pre&gt;function updateDiv(val) {
   function delayed() {
        document.getElementById('test').innerHTML+=val;
   } 
   setTimeout(delayed,500);
}
&lt;/pre&gt;
We add a timeout to simulate an application taking time to perform.&lt;br /&gt;
if we rewrite our example:&lt;br /&gt;
&lt;pre&gt;queue(function() { updateDiv(1)},function(){ updateDiv(2)},function(){updateDiv(3)});
flush(); // call everything
&lt;/pre&gt;
&lt;script type="text/javascript"&gt;
function example2() {
  queue(function() { updateDiv(1)}, 
        function(){ updateDiv(2)},
        function(){updateDiv(3)});
  flush();
function updateDiv(val) {
   function delayed() {
        document.getElementById('test').innerHTML+=val;
   } 
   setTimeout(delayed,500);
}
}
&lt;/script&gt;
If we keep the principle of a queue, we should have each function called one after an other, &lt;a href="javascript:example2()"&gt;try it yourself&lt;/a&gt;
&lt;br /&gt;
&lt;div id="test"&gt;
&lt;/div&gt;
And it doesn't work as expected!!&lt;br /&gt;
Well in fact, the flush function is something that we cannot build independently of the application.&lt;br /&gt;
Why?&lt;br /&gt;
Because our flush function calls each function without even knowing if the precedent one has finished!&lt;br /&gt;
In order to create a queue, we need to call the next function at the end of the last executed queued function. Therefore, the queue and the application needs to be related to some extend.&lt;br /&gt;
We should rewrite our function like this:&lt;br /&gt;
&lt;pre&gt;function updateDiv(val) {
   function delayed() {
        document.getElementById('test').innerHTML+=val;
        next();
   } 
   setTimeout(delayed,500);
}
&lt;/pre&gt;
Now, the queue is going to be processed after the end of each function, the recursive call to the next function will create our application related flush:&lt;br /&gt;
&lt;pre&gt;queue(function() { updateDiv(1)},function(){ updateDiv(2)},function(){updateDiv(3)});
next(); // call next function that will work as a flush here
&lt;/pre&gt;
Now, if you try the &lt;a href="javascript:example3()"&gt;above code&lt;/a&gt;
&lt;script type="text/javascript"&gt;
function example3() {
  queue(function() { updateDiv2(1)}, 
        function(){ updateDiv2(2)},
        function(){updateDiv2(3)});
  next();
  function updateDiv2(val) {
      function delayed() {
        document.getElementById('test2').innerHTML+=val;
        next();
      } 
      setTimeout(delayed,500);
  }
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="test2"&gt;
&lt;/div&gt;
And it works as expected!&lt;br /&gt;
In fact, each application should have its own flush method.&lt;br /&gt;
In order to create a flush function, we need to know when the function is done to move on to the next element in the queue.&lt;br /&gt;
But how do I stop the queue processing or just advance one element in the queue then??&lt;br /&gt;
Well, we just need to change the flush function and wrap the next function like so:&lt;br /&gt;
&lt;pre&gt;function advance() {
 paused=false;
 next();
 paused=true;
}
function flush() {
 paused=false;
 next();
}
&lt;/pre&gt;
So, the advance function change the pause flag to false at the beginning and set it right away to true after calling the next function. The next function will stop at the following call as the pause flag will be set to true!&lt;br /&gt;
On the other hand the flush function just wrap the next function that will be called by each functions in the queue!&lt;br /&gt;
As you can see if some elements can be true to all queues, the flushing of a queue needs to be application aware and can hardly be generalize.&lt;br /&gt;
If you add a function in the queue that doesn't call the next function when it is done, your queue won't work and stop there.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
We have built here a very basic queue system that allows us to understand the underlying process of a queue.&lt;br /&gt;
Javascript offers everything that we need to make it very easy like arrays, push, pop, shift functions.&lt;br /&gt;
Obviously these functions can have some overheads that a queue implemented at lower level won't have but the cost is not that much nowadays.&lt;br /&gt;
&lt;br /&gt;
But this queue system has a real huge drawback:&lt;br /&gt;
our container and our pause flag is in the global space and we won't be able to have several queues running at the same time!!&lt;br /&gt;
Therefore we will see in the next entry an other approach that allows us to create several queue entities,objects that will keep track of their own internal state of the queue.&lt;br /&gt;
We will be switching from a procedural approach to an object oriented approach(OOP) and therefore see some of the advantages of this technique over this one.&lt;br /&gt;
We will also see how to use a queue in a real context, chaining effects!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-4228439941082209150?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/4228439941082209150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=4228439941082209150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4228439941082209150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4228439941082209150'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2008/02/javascript-creating-queue-system-part-1.html' title='Javascript - Creating a queue system part 1 : procedural way'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-5258775560329561176</id><published>2008-01-19T09:54:00.002+09:00</published><updated>2010-09-28T11:57:17.441+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : dynamic fps with setInterval</title><content type='html'>if you read the 'javascript animation' entries, you know that we built an animation function using setTimeout as a base. duration, fps, multiple settings, easing were also available! let's an other way of implementing this animation function by using setInterval&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Refresh, refresh!&lt;/h3&gt;
&lt;br /&gt;
Before we go on with the new implementation, let's see where we left the animation first!&lt;br /&gt;
If you read the 'javascript namespaces' entries, you will notice that everything is in the global space but for now, let's pretend you didn't see it!&lt;br /&gt;
So here we go:&lt;br /&gt;
&lt;div class="javascript"&gt;
&lt;span class="kw2"&gt;function&lt;/span&gt; animate&lt;span class="br0"&gt;(&lt;/span&gt;elm,props, duration, fps,easing&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;duration = parseFloat&lt;span class="br0"&gt;(&lt;/span&gt;duration&lt;span class="br0"&gt;)&lt;/span&gt; || &lt;span class="nu0"&gt;1000&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;fps &amp;nbsp; &amp;nbsp; &amp;nbsp;= parseFloat&lt;span class="br0"&gt;(&lt;/span&gt;fps&lt;span class="br0"&gt;)&lt;/span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;|| &lt;span class="nu0"&gt;30&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;easing &amp;nbsp; = easing || &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;t,b,c,d&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; b + &lt;span class="br0"&gt;(&lt;/span&gt;c/d&lt;span class="br0"&gt;)&lt;/span&gt;*t;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;}&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; interval &amp;nbsp; &amp;nbsp;= Math.&lt;span class="me1"&gt;ceil&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="nu0"&gt;1000&lt;/span&gt;/fps&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; totalframes = Math.&lt;span class="me1"&gt;ceil&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;duration/interval&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; i=&lt;span class="nu0"&gt;1&lt;/span&gt;;i &amp;lt;= totalframes;i++&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; frame=i;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; setAnimation=&lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; prop &lt;span class="kw1"&gt;in&lt;/span&gt; props&lt;span class="br0"&gt;)&lt;/span&gt;&lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;strategyFactory&lt;span class="br0"&gt;(&lt;/span&gt;totalframes,frame,prop,props,easing&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; timer = setTimeout&lt;span class="br0"&gt;(&lt;/span&gt;setAnimation,interval*frame&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;}&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;; &amp;nbsp; &lt;br /&gt;
&amp;nbsp; &lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="kw2"&gt;function&lt;/span&gt; strategyFactory&lt;span class="br0"&gt;(&lt;/span&gt;totalframes,frame,prop,props,easing&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; start=props&lt;span class="br0"&gt;[&lt;/span&gt;prop&lt;span class="br0"&gt;]&lt;/span&gt;.&lt;span class="me1"&gt;start&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="re0"&gt;/&lt;span class="br0"&gt;[&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;&lt;span class="nu0"&gt;-9&lt;/span&gt;&lt;span class="br0"&gt;]&lt;/span&gt;+/.&lt;span class="me1"&gt;test&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;parseInt&lt;span class="br0"&gt;(&lt;/span&gt;start&lt;span class="br0"&gt;)&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &amp;amp;&amp;amp; !/\s/&lt;/span&gt;.&lt;span class="me1"&gt;test&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;start&lt;span class="br0"&gt;)&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;NumericStrategy&lt;span class="br0"&gt;(&lt;/span&gt;totalframes,frame,prop,props,easing&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;true&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; strategy=camelize&lt;span class="br0"&gt;(&lt;/span&gt;firstToUpperCase&lt;span class="br0"&gt;(&lt;/span&gt;prop&lt;span class="br0"&gt;)&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;window&lt;span class="br0"&gt;[&lt;/span&gt;strategy&lt;span class="br0"&gt;]&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; window&lt;span class="br0"&gt;[&lt;/span&gt;strategy&lt;span class="br0"&gt;]&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;totalframes,frame,prop,props,easing&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;true&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw2"&gt;false&lt;/span&gt;;&lt;br /&gt;
&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
How it works&lt;/h3&gt;
We are not going to review all the entries but put it simply:&lt;br /&gt;
- we first set the basic options like the duration, the frame rate per second&lt;br /&gt;
- we calculate the interval and the total number of frames required&lt;br /&gt;
- then we loop thru each frames, create a closure just to scope the counter i into the setAnimation function&lt;br /&gt;
- delegate all the calculation to the strategyFactory&lt;br /&gt;
- change the interval of the timeout according to the actual frame.&lt;br /&gt;
&lt;br /&gt;
This is basically how it works, you can read past entries entitled 'javascript Animation :' to get more detail.&lt;br /&gt;
So in that case, we are using setTimeout, closure and a dynamic interval.&lt;br /&gt;
Let's see how to get the same result but with setInterval!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
setInterval : dynamic frame rate&lt;/h3&gt;
&lt;br /&gt;
If with setTimeout we were looping thru each frames until the end, with setInterval, we are going to calculate the acutal frame and determine if we shall stop or continue by taking into account the elapsedtime!&lt;br /&gt;
The strategyFactory is the same, so let's put the animate function only:&lt;br /&gt;
&lt;div class="javascript"&gt;
&lt;span class="kw2"&gt;function&lt;/span&gt; animate&lt;span class="br0"&gt;(&lt;/span&gt;elm,props, duration, fps,easing&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;duration = parseFloat&lt;span class="br0"&gt;(&lt;/span&gt;duration&lt;span class="br0"&gt;)&lt;/span&gt; || &lt;span class="nu0"&gt;1000&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;fps &amp;nbsp; &amp;nbsp; &amp;nbsp;= parseFloat&lt;span class="br0"&gt;(&lt;/span&gt;fps&lt;span class="br0"&gt;)&lt;/span&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;|| &lt;span class="nu0"&gt;30&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;easing &amp;nbsp; = easing || &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;t,b,c,d&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; b + &lt;span class="br0"&gt;(&lt;/span&gt;c/d&lt;span class="br0"&gt;)&lt;/span&gt;*t;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;}&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; interval &amp;nbsp; &amp;nbsp;= Math.&lt;span class="me1"&gt;ceil&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="nu0"&gt;1000&lt;/span&gt;/fps&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; totalframes = Math.&lt;span class="me1"&gt;ceil&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;duration/interval&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; startTime &amp;nbsp;= &lt;span class="kw2"&gt;new&lt;/span&gt; Date&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;.&lt;span class="me1"&gt;getTime&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; frame &amp;nbsp; &amp;nbsp; &amp;nbsp;= &lt;span class="nu0"&gt;1&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; timer &amp;nbsp; &amp;nbsp; &amp;nbsp;= &lt;span class="kw2"&gt;null&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; setAnimation=&lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; time = &lt;span class="kw2"&gt;new&lt;/span&gt; Date&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;.&lt;span class="me1"&gt;getTime&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;frame = parseInt&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;time - startTime&lt;span class="br0"&gt;)&lt;/span&gt; / interval&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; prop &lt;span class="kw1"&gt;in&lt;/span&gt; props&lt;span class="br0"&gt;)&lt;/span&gt;&lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;strategyFactory&lt;span class="br0"&gt;(&lt;/span&gt;totalframes,frame,prop,props,easing&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;(&lt;/span&gt;time &amp;gt;= startTime + duration&lt;span class="br0"&gt;)&lt;/span&gt; &lt;span class="br0"&gt;{&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; clearInterval&lt;span class="br0"&gt;(&lt;/span&gt;timer&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class="br0"&gt;}&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; timer = setInterval&lt;span class="br0"&gt;(&lt;/span&gt;setAnimation,interval&lt;span class="br0"&gt;)&lt;/span&gt;;&lt;br /&gt;
&lt;span class="br0"&gt;}&lt;/span&gt;
&lt;/div&gt;
&lt;br /&gt;
There aren't that many changes but let's see step by step:&lt;br /&gt;
- we first set the basic options like the duration, the frame rate per second.&lt;br /&gt;
- we calculate the interval and the total number of frames required.&lt;br /&gt;
- we keep in memory the starting time of the animation and initialize some variables like the frame and the timer.&lt;br /&gt;
- then we defined the setAnimation function that calculates dynamically the actual frame by comparing the elapsed time with the interval.&lt;br /&gt;
It means that if the application is slow, the actual frame, that should be 12, can be 14 or 17 because the computer can not handle as expected.&lt;br /&gt;
Here if you want to get the frame rate per second, just do the following computation:&lt;br /&gt;
var actualFPS = parseInt((new Date().getTime() - time)/frame);&lt;br /&gt;
Output this in a div to see it evolve (you need to do some heavy stuff around though)&lt;br /&gt;
- delegate all the calculation to the strategyFactory&lt;br /&gt;
- check if we have reached the duration required and if so stop the interval.&lt;br /&gt;
- launch the setAnimation thru a regular interval.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The differences&lt;/h3&gt;
&lt;br /&gt;
As you can see using the setInterval method add some calculations that the simple setTimeout didn't require.&lt;br /&gt;
Here we need to check the elapsed time to stop the timer and keep in memory the starting time.&lt;br /&gt;
As we are using a closure within the main animation function, the startTime is kept in memory and we can also access the timer even after the function has returned.&lt;br /&gt;
The advantage of using the setInterval is that you are only going to do what the computer can really handle, nothing more, nothing less.&lt;br /&gt;
It allows to reduce the general overhead that can occur when simultanate actions are taking place!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
We have seen how we could easily re-implement the animate function by using the setInterval function instead of the setTimeout.&lt;br /&gt;
We didn't have to deal with too many unnecessary things as we kept all the computation outside of the main function.&lt;br /&gt;
The closure used within the animate function is the premice of object oriented programming, as it allows the function to keep state of variables thru time.&lt;br /&gt;
But this is far to be perfect:&lt;br /&gt;
- We send bunches of variables to the strategyFactory that delegates these bunches of variables to other functions, which could be made simpler by using an object oriented approach where we could keep several variables internal to the application.&lt;br /&gt;
- everything is in the global namespace!&lt;br /&gt;
We can easily change this and use the Package function developped in the javascript namespaces entries and clean a little our mess!&lt;br /&gt;
&lt;br /&gt;
We will see in next entries:&lt;br /&gt;
- how to namespace everything and use object oriented concepts&lt;br /&gt;
- how to deal with borders&lt;br /&gt;
- how to use a cascading style sheet to define your animation where it should be : in a css class and stay DRY!&lt;br /&gt;
- how to use custom events (onStart,onProgress, onComplete )&lt;br /&gt;
,etc!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-5258775560329561176?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/5258775560329561176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=5258775560329561176' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5258775560329561176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5258775560329561176'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2008/01/javascript-animation-dynamic-fps-with.html' title='Javascript Animation : dynamic fps with setInterval'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-7861650285054173050</id><published>2008-01-05T17:59:00.001+09:00</published><updated>2008-02-23T21:46:24.671+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>javascript : memoizing - caching functions result</title><content type='html'>The use of Javascript in a browser context requires to keep an eye on resources. Avoiding unnecessary variables and computation is one way to minimize a crash due to CPU overflow.We will see how we can reduce the number of computations by memoizing functions result.
&lt;br /&gt;&lt;br /&gt;
&lt;h3&gt;A concrete example : setting css style&lt;/h3&gt;
&lt;br /&gt;
if you read the entry about setting the style thru javascript, you saw that the standard and IE way of naming the float attribute was different:
&lt;br /&gt;
Standard : cssFloat&lt;br /&gt;
IE       : styleFloat&lt;br /&gt;

Therefore, let's see the setStyle function again:&lt;br /&gt;
&lt;pre&gt;
function setStyle(elm,prop,val) {
  if(prop=='opacity') 
    return setOpacity(elm,parseFloat(val));
  if(prop=='float')
    prop = (window.attachEvent) ? 'styleFloat' : 'cssFloat';

  prop = camelize(prop);
  elm.style[prop] = val;
  return elm;
}
&lt;/pre&gt;
As you can see, in order to use the proper naming for float, we use a ternary operator that looks for a IE method, attachEvent.&lt;br /&gt;
If we use this function many time, this computation is going to be done again and again.&lt;br /&gt;
Let see two ways to solve this problem:&lt;br /&gt;
-lazy setting:&lt;br /&gt;
&lt;pre&gt;
var styleFloat=(window.attachEvent) ? 'styleFloat' : 'cssFloat';

function setStyle(elm,prop,val) {
  if(prop=='opacity')
     return setOpacity(elm,parseFloat(val));
  if(prop=='float')
     prop = styleFloat;
  prop = camelize(prop);
  elm.style[prop] = val;
  return elm;
}
&lt;/pre&gt;
There is not that much difference!&lt;br /&gt;
we just put the computation outside the function to have a variable holding the proper float naming for us, once and for good.&lt;br /&gt;
The other way is to use a dynamic definition:&lt;br /&gt;

&lt;pre&gt;
function getStyleFloat() {
    //alert('first call');
    var float =(window.attachEvent) ? 'styleFloat' : 'cssFloat';
    this.getStyleFloat = function() {
       //alert('second call');
        return float;
    }
    return float;
}

function setStyle(elm,prop,val) {
  if(prop=='opacity')
     return setOpacity(elm,parseFloat(val));
  if(prop=='float') prop = getStyleFloat();
  prop = camelize(prop);
  elm.style[prop] = val;
  return elm;
}
&lt;/pre&gt;
Well, this is a lot of typing right?&lt;br /&gt;
The getStyleFloat can seem complex but in fact, it is very easy!&lt;br /&gt;
In order to use this dynamic definition pattern, you just need to create your function as you always do!&lt;br /&gt;
We just redefine the function by using a closure. Here this refers to the window object and just put the getStyleFloat function into the global space.&lt;br /&gt;
We are just 'overwritting ourself'!&lt;br /&gt;
the first time you call the function it will do the usual computation and all the following calls will just send you back the result, like a cache!&lt;br /&gt;
This is a rather trivial example but for heavy computation, this can be very usefull!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;A second example : XMLHttpRequest&lt;/h3&gt;
&lt;br /&gt;
Here again, we have to face differences between IE and the rest of the world.&lt;br /&gt;
In that case, IE was the pioneer by creating the XMLHttpRequest and it is the rest of the world who has copied this functionality.&lt;br /&gt;
But IE, only for the windows platform, requires to use the ActiveX component, which is not available in all OS, that's why other browsers have created their own XMLHttpRequest.&lt;br /&gt;
Let's see how to switch between them:&lt;br /&gt;
&lt;pre&gt;
function getXHR() {
   var xhr = '';
   if (window.XMLHttpRequest) {
      xhr  = new XMLHttpRequest();
   }
   else if (window.ActiveXObject) {
      xhr = new ActiveXObject('Microsoft.XMLHTTP');
   }
   return xhr;
}
&lt;/pre&gt; 
so here again, we will do the following computation everytime we call the function.&lt;br /&gt;
And even worse, we are going to instantiate the xhr object several times!&lt;br /&gt;
We are therefore going to see how to cache the result and on top of that create a singleton (a singleton is a way to have only one and unique instantiation of a class during the course of the program):&lt;br /&gt;
&lt;pre&gt;
function getXHR() {
   var xhr = '';
   if (window.XMLHttpRequest) {
      xhr  = new XMLHttpRequest();
   }
   else if (window.ActiveXObject) {
      xhr = new ActiveXObject('Microsoft.XMLHTTP');
   }
   this.getXHR = function() {
       return xhr;
   }
   return xhr;
}
&lt;/pre&gt; 
And voila!&lt;br /&gt;
The first call to the function will do the computation and all the other call will send back the result from the first call!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;br /&gt;
You can find many use to this dynamic definition pattern, especially in order to deal with cross-browser issues that we face in javascript!&lt;br /&gt;
This can also be used to create a singleton like above or to cache some heavy computation you may need to do for animations or else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-7861650285054173050?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/7861650285054173050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=7861650285054173050' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/7861650285054173050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/7861650285054173050'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2008/01/javascript-memoizing-caching-functions.html' title='javascript : memoizing - caching functions result'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-6518744505803725645</id><published>2008-01-03T17:11:00.000+09:00</published><updated>2008-01-03T18:09:31.640+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>Javascript Namespaces : Privacy thru closure or how to type less!</title><content type='html'>we have seen in the last entry how we could create a basic namespace simulation in javascript. We have seen how to import in the global space what we needed. Packages should not though import anything to keep the global space clean but it could be nice to shortcut things within packages too. We will see how to do so thanks to closures.
&lt;br /&gt;
&lt;h3&gt; Privacy thru functions&lt;/h3&gt;
&lt;br /&gt;
If you read the entry &lt;a href="http://shiriru.blogspot.com/2007/11/javascript-scoping.html"&gt;Javascript scoping: things to keep in mind&lt;/a&gt;, you certainly remember that it is possible to create scoping thru functions, therefore, the following variables won't be available outside of the scope of the function:&lt;br /&gt;
&lt;pre&gt;
function privacy() {
    var myvar=1; // can't be accessed from outside
    myvar    =2: // can be accessed from outside
}
&lt;/pre&gt;
We can create a function by putting a reference to it in a variable too : 
&lt;pre&gt;
privacy = function() {
    var myvar=1; // can't be accessed from outside
    myvar2    =2: // can be accessed from outside 
}
alert(myvar); //error
alert(myvar2); //error
privacy();
alert(myvar); //error
alert(myvar2); //2
&lt;/pre&gt;
We are using an anonymous function which definition is referenced to the privacy variable that will act like a normal function now.&lt;br /&gt;
But as you can see we need to call the privacy function in order to access the public variable we have created. It won't be available as long as we do not execute the function.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Closures as scope container&lt;/h3&gt;
&lt;br /&gt;
There is a way to create scoping without even having to name the function at all. 
we just need to define the anonymous function and have it execute right away.&lt;br /&gt;
we can do this, thanks to the following notation:&lt;br /&gt;
&lt;pre&gt;
(function () {

 //your code here


})();
&lt;/pre&gt;
This is just an anonymous function held within a block. By doing so, the code defined in the anonymous function will be executed right away and therefore, what is defined within it will be available to us.&lt;br /&gt;
Let's try:&lt;br /&gt;
&lt;pre&gt;
(function() {
   alert('hi!');
})();
&lt;/pre&gt;
If you try this code, you get the alert prompt saying hi!.&lt;br /&gt;
In fact within this closure, you can write your javascript code like you always do!!&lt;br /&gt;
It will create a space hold in memory but not accessible from outside.&lt;br /&gt;
Well unless, you allow variables to be accessed from outside:&lt;br /&gt;
&lt;pre&gt;
(function() {
    var myvar=1; // can't be accessed from outside
    myvar    =2: // can be accessed from outside 
})();
&lt;/pre&gt;
Closures are a very powerfull tool allowing many many other things!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt; Packages and closure : creating privacy for us, the lazy!&lt;/h3&gt;
&lt;br /&gt;
we have seen different packages holding some utilities function developped so far.
There is especially one of them that has a dependency to an other package, the number package. Let's see the package in question:
&lt;pre&gt;
JAME.Package('JAME.Util.Color');

JAME.Util.Color = {
    rgb2h:function (r,g,b) { 
       var d2h = JAME.Util.Number.d2h;
       return [d2h(r),d2h(g),d2h(b)];
    },
    h2rgb:function (h,e,x) {  
       var h2d = JAME.Util.Number.h2d;
       return [h2d(h),h2d(e),h2d(x)];
   },
   cssColor2rgb:function (color) {
       if(color.indexOf('rgb')&lt;=-1) {
  return this.hexStr2rgbArray(color);
       }
       return this.rgbStr2rgbArray(color);
  },
  hexStr2rgbArray:function (color) {
      return this.h2rgb(color.substring(1,3),
                        color.substring(3,5),
                        color.substring(5,7));
  },
  rgbStr2rgbArray:function (color) {
     return color.substring(4,color.length-1).split(',');
  },
  Export : function() {
     JAME.Exporter(this);
  }
};
&lt;/pre&gt;
You can see that we have created a shortcut for 2 functions.&lt;br /&gt;
We have placed them within the function definition in order not to put them into the global space.&lt;br /&gt;
it was fine, because we only need them in one place but if we had them used in different places? Create a property into the object definition to hold them could be a solution but will polluate the package a little.&lt;br /&gt;
In that case, it is easier to create a closure to hold all the dependencies we require, therefore we can rewrite it this way:&lt;br /&gt;
&lt;pre&gt;
JAME.Package('JAME.Util.Color');

  
(function () {

      var d2h = JAME.Util.Number.d2h;
      var h2d = JAME.Util.Number.h2d;

      JAME.Util.Color = {
           rgb2h:function (r,g,b) { 
              return [d2h(r),d2h(g),d2h(b)];
           },
           h2rgb:function (h,e,x) {  
              return [h2d(h),h2d(e),h2d(x)];
           },
           cssColor2rgb:function (color) {
           if(color.indexOf('rgb')&lt;=-1) {
          return this.hexStr2rgbArray(color);
           }
           return this.rgbStr2rgbArray(color);
           },
           hexStr2rgbArray:function (color) {
           return this.h2rgb(color.substring(1,3),
                                    color.substring(3,5),
                                    color.substring(5,7));
           },
           rgbStr2rgbArray:function (color) {
           return color.substring(4,color.length-1).split(',');
           },
           Export : function() {
                JAME.Exporter(this);
           }
      };

})();
&lt;/pre&gt;
the 2 shortcuts won't be available outside and therefore will keep the global space clean while allowing less typo!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;br /&gt;


You should be aware that a closure will keep everything defined in it and that it will stay in memory as long as the program goes. It can also lead to memory leaks especially in IE when mixed with DOM manipulation.&lt;br /&gt;
It is therefore a very powerfull tool but can have underisable effects that won't be 
noticable right away.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-6518744505803725645?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/6518744505803725645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=6518744505803725645' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/6518744505803725645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/6518744505803725645'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2008/01/javascript-namespaces-privacy-thru.html' title='Javascript Namespaces : Privacy thru closure or how to type less!'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-5713398099575911453</id><published>2007-12-24T23:42:00.000+09:00</published><updated>2010-08-31T22:53:19.043+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='namespace'/><title type='text'>Javascript Namespaces : Import and Export methods</title><content type='html'>We have seen how important namespaces are and how to simulate them thru objects.
If protecting ourselves and users from collisions is a good thing, writing 4 to 6 names before accessing the desire functions can be a real pain! &lt;br /&gt;
we will see how to shortcut things and make our life easier when needed!
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Namespaces : the Namespace function&lt;/h3&gt;
&lt;br /&gt;
Let's sum up what we have seen in our last entry by taking the example of the JAME namespace (Javascript Animations Made Easy).&lt;br /&gt;
We won't put anything directly in the global namespace, that's why we will have to create our first namespace, JAME, without the Namespace function:&lt;br /&gt;
&lt;pre&gt;
JAME = function () {};
JAME = JAME.prototype = function () {};
&lt;/pre&gt;
Now, let's attach the Namespace function onto the JAME namespace.&lt;br /&gt;
Let's rename the function to Package, because...&lt;br /&gt;
Well, I like Package and it's in the ES4 proposal.&lt;br /&gt;
Rename it to whatever you want (I will avoid x345SW2aqefje because it is overused)
&lt;br /&gt;&lt;br /&gt;
&lt;div class="javascript"&gt;
JAME.&lt;span class="kw2"&gt;Package&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;sName&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;//split the name by dots&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; namespaces=sName.&lt;span class="me1"&gt;split&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'.'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; || &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;sName&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; nlen=namespaces.&lt;span class="me1"&gt;length&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; root = window;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; F &amp;nbsp; &amp;nbsp;= &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; i=&lt;span class="nu0"&gt;0&lt;/span&gt;;i&amp;lt;nlen;i++&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; ns = namespaces&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;i&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw1"&gt;typeof&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;root&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;ns&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;===&lt;span class="st0"&gt;'undefined'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; root = root&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;ns&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = F;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; root = root.&lt;span class="me1"&gt;prototype&lt;/span&gt; = F;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;else&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;root = root&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;ns&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;h3&gt;Some packages definition&lt;/h3&gt;
&lt;br /&gt;
We have seen how to use it with the utility functions built so far to create 
the animation function.&lt;br /&gt;
Let's see the strings and colors related functions in their package:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="javascript" style="white-space: nowrap;border: 1px dotted #a0a0a0; font-family: 'Courier New', Courier, monospace; font-size: 110%; background-color: #f0f0f0; margin: 0; line-height: 110%; padding: 0;color: #0000bb;"&gt;
&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;JAME.&lt;span class="kw2"&gt;Package&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'JAME.Util.Color'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;JAME.&lt;span class="me1"&gt;Util&lt;/span&gt;.&lt;span class="me1"&gt;Color&lt;/span&gt; = &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; rgb2h:&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;r,g,b&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; Num=JAME.&lt;span class="me1"&gt;Util&lt;/span&gt;.&lt;span class="me1"&gt;Number&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;Num.&lt;span class="me1"&gt;d2h&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;r&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,Num.&lt;span class="me1"&gt;d2h&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;g&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,Num.&lt;span class="me1"&gt;d2h&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;b&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; h2rgb:&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;h,e,x&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; Num=JAME.&lt;span class="me1"&gt;Util&lt;/span&gt;.&lt;span class="me1"&gt;Number&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;Num.&lt;span class="me1"&gt;h2d&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;h&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,Num.&lt;span class="me1"&gt;h2d&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;e&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,Num.&lt;span class="me1"&gt;h2d&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;x&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; cssColor2rgb:&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;color&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;color.&lt;span class="me1"&gt;indexOf&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'rgb'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&amp;lt;=&lt;span class="nu0"&gt;-1&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;hexStr2rgbArray&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;color&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;rgbStr2rgbArray&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;color&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; hexStr2rgbArray:&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;color&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="kw1"&gt;this&lt;/span&gt;.&lt;span class="me1"&gt;h2rgb&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;color.&lt;span class="me1"&gt;substring&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;,&lt;span class="nu0"&gt;3&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;color.&lt;span class="me1"&gt;substring&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;3&lt;/span&gt;,&lt;span class="nu0"&gt;5&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;color.&lt;span class="me1"&gt;substring&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;5&lt;/span&gt;,&lt;span class="nu0"&gt;7&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; rgbStr2rgbArray:&lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;color&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;return&lt;/span&gt; color.&lt;span class="me1"&gt;substring&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="nu0"&gt;4&lt;/span&gt;,color.&lt;span class="me1"&gt;length&lt;/span&gt;&lt;span class="nu0"&gt;-1&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.&lt;span class="me1"&gt;split&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;','&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div class="javascript"&gt;
&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;JAME.&lt;span class="kw2"&gt;Package&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'JAME.Util.String'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;JAME.&lt;span class="me1"&gt;Util&lt;/span&gt;.&lt;span class="me1"&gt;String&lt;/span&gt;=&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; camelize: &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/-&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;.&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;/g&lt;/span&gt;, &lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;m, l&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="kw1"&gt;return&lt;/span&gt; l.&lt;span class="me1"&gt;toUpperCase&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; hyphenize : &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;A-Z&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;/g&lt;/span&gt;, &lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;m, l&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="st0"&gt;'-'&lt;/span&gt;+l.&lt;span class="me1"&gt;toLowerCase&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; firstToUpperCase : &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/^&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;a-z&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;/&lt;/span&gt;, &lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;m, l&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="kw1"&gt;return&lt;/span&gt; l.&lt;span class="me1"&gt;toUpperCase&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; trim : &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/^\s+|\s+$/g&lt;/span&gt;, &lt;span class="st0"&gt;''&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
How do we use them?&lt;br /&gt;
&lt;div class="javascript"&gt;
&lt;ol&gt;&lt;li class="li1"&gt;&lt;span class="co1"&gt;// display backgroundColor&lt;/span&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&lt;span class="kw3"&gt;alert&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;JAME.&lt;span class="me1"&gt;Util&lt;/span&gt;.&lt;span class="me1"&gt;String&lt;/span&gt;.&lt;span class="me1"&gt;camelize&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;background-color&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;span class="co1"&gt;// display 255,0,255 &lt;/span&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&lt;span class="kw3"&gt;alert&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;JAME.&lt;span class="me1"&gt;Util&lt;/span&gt;.&lt;span class="me1"&gt;Color&lt;/span&gt;.&lt;span class="me1"&gt;hexStr2rgbArray&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;#FF00FF&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;; &lt;/div&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
That's a lot of typing!&lt;br /&gt;
We have seen that we could create an alias very easily:&lt;br /&gt;
&lt;pre&gt;
window["camelize"]       = JAME.Util.String.camelize;
window["hex2rgbArray"] = JAME.Util.Color.hex2rgbArray;
&lt;/pre&gt;
Now you can call the camelize and hex2rgbArray directly without having to worry about the namespaces!&lt;br /&gt;
But this is still quite cumbersome to type this! And if you want to import everything in your namespace?&lt;br /&gt;
Let's build a function that will allow to import everything by just specifying the desired namespace then!&lt;br /&gt;&lt;br /&gt;

&lt;h3&gt;The Import method&lt;/h3&gt;&lt;br /&gt;
Let's see how we would like to use it first:&lt;br /&gt;
&lt;pre&gt;
JAME.Import(JAME.Util.String,JAME.Util.Color,JAME.Util.Number);
&lt;/pre&gt;
So we will just specify the namespace we need and as many as we wish.&lt;br /&gt;
In order to allow as many parameters as needed, we are going to use the arguments keyword.&lt;br /&gt;
By the way, the arguments keyword is not a real array in that you cannot push, slice....&lt;br /&gt;
&lt;br /&gt;
&lt;div class="javascript"&gt;
&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;JAME.&lt;span class="kw2"&gt;Import&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;//get the number of parameters&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; nlen=arguments.&lt;span class="me1"&gt;length&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;//loop thru each package/namespace&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; i=&lt;span class="nu0"&gt;0&lt;/span&gt;;i&amp;lt;nlen;i++&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;// get the actual package&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; &lt;span class="kw2"&gt;package&lt;/span&gt;=arguments&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;i&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;//test the existence of an Export method&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;package&lt;/span&gt;.&lt;span class="kw2"&gt;Export&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="co1"&gt;//call the Export function&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;package&lt;/span&gt;.&lt;span class="kw2"&gt;Export&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
The definition of this function is not very hard.&lt;br /&gt;
We just loop thru each package and test for the Export method.&lt;br /&gt;
But what is this Export method??&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Need some privacy!&lt;/h3&gt;
&lt;br /&gt;
The Export function should be defined within the packages and should define what functions can be exported as their exported name.&lt;br /&gt;
It is easier and safier to let the package creator defines what he/she thinks can be exported safely.&lt;br /&gt;
A function name can be perfectly safe within the boundaries of a package but could be too obvious once in the global scope.&lt;br /&gt;
Therefore, renaming the function in order to avoid conflicts by prefixing it should be up to the package author.&lt;br /&gt;
So let's see the Export function within the string package :
&lt;br /&gt;
&lt;div class="javascript"&gt;
JAME.&lt;span class="kw2"&gt;Package&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'JAME.Util.String'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
JAME.&lt;span class="me1"&gt;Util&lt;/span&gt;.&lt;span class="me1"&gt;String&lt;/span&gt;=&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; camelize: &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/-&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;.&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;/g&lt;/span&gt;, &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;m, l&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="kw1"&gt;return&lt;/span&gt; l.&lt;span class="me1"&gt;toUpperCase&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; hyphenize : &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;A-Z&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;/g&lt;/span&gt;, &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;m, l&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="kw1"&gt;return&lt;/span&gt; &lt;span class="st0"&gt;'-'&lt;/span&gt;+l.&lt;span class="me1"&gt;toLowerCase&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; firstToUpperCase : &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/^&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;a-z&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;/&lt;/span&gt;, &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;m, l&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="kw1"&gt;return&lt;/span&gt; l.&lt;span class="me1"&gt;toUpperCase&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; trim : &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;str&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;return&lt;/span&gt; str.&lt;span class="me1"&gt;replace&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="re0"&gt;/^\s+|\s+$/g&lt;/span&gt;, &lt;span class="st0"&gt;''&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;Export&lt;/span&gt; : &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; method &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="kw1"&gt;this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;method===&lt;span class="st0"&gt;&amp;quot;Export&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="kw1"&gt;continue&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; window&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;method&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;=&lt;span class="kw1"&gt;this&lt;/span&gt;&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;method&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt; &amp;nbsp; &amp;nbsp;&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;/div&gt;
As you can see, in that case, it was pretty straightforward as we just loop thru each method in the string package and alias them onto the window object.&lt;br /&gt;
Obviously, we skip the Export method that is internal to the package!&lt;br /&gt;
But let's say that you want to rename the trim function to JStrim in order to avoid conflict?
You will have to verify if it is the trim method then change it's naming.&lt;br /&gt;
Or let's say that you just want to export 2 functions among 5 or 6 functions?&lt;br /&gt;
In order to make lifer easier and keep things DRY, we are going to create an Exporter function that will ease the export process!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The Exporter method&lt;/h3&gt;
&lt;br /&gt;
Let's see its definition first:&lt;br /&gt;
&lt;div class="javascript"&gt;
JAME.&lt;span class="me1"&gt;Exporter&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;oName,sPref&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!sPref&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; sPref=&lt;span class="st0"&gt;''&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; method &lt;span class="kw1"&gt;in&lt;/span&gt; oName&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;method===&lt;span class="st0"&gt;&amp;quot;Export&amp;quot;&lt;/span&gt; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|| &lt;span class="re0"&gt;/^_.+/&lt;/span&gt;.&lt;span class="me1"&gt;test&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;method&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;continue&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; window&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;sPref+method&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;=oName&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;method&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
The function accepts two parameters:&lt;br /&gt;
an object that can be 'this' to export everything or a literal object defining the exported function name and its original version with the package path.&lt;br /&gt;
And a string that defines a prefixe to put on the exported function name.&lt;br /&gt;
An example will help:&lt;br /&gt;
&lt;pre&gt;
JAME.Util.String= {
...
   _mymethod : function() {...} // will not be exported
   Export : function() {

       JAME.Exporter(this,'JS');
       //or 
       JAME.Exporter({"hyphenize":JAME.Util.String.hyphenize},"JS");
   }
}
&lt;/pre&gt;
As you can see in the exporter function, we skip the Export function and all methods or variables that start with an underscore.&lt;br /&gt;
This is just a convention used in many languages to specify private variables.&lt;br /&gt;
Even if it is possible to simulate private variables and methods in javascript, thisw won't be the case here, unless you wrap all the code within an other function.&lt;br /&gt;
Beware that we do not check against variables or functions already defined in the global namespace, which means that these functions will be overwritten!&lt;br /&gt;
It should be easy to add a flag to set it to overwrite mode or not.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The final script&lt;/h3&gt;
&lt;br /&gt;
And here we are with a basic namespace simulation and exporting/importing process.&lt;br /&gt;
Here is the code that recaps everything seen:&lt;br /&gt;
&lt;div class="javascript"&gt;
JAME = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
JAME = JAME.&lt;span class="me1"&gt;prototype&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
JAME.&lt;span class="kw2"&gt;Package&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;sName&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; namespaces=sName.&lt;span class="me1"&gt;split&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;'.'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; || &lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;sName&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; nlen=namespaces.&lt;span class="me1"&gt;length&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; root = window;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; F &amp;nbsp; &amp;nbsp;= &lt;span class="kw2"&gt;function&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; i=&lt;span class="nu0"&gt;0&lt;/span&gt;;i&amp;lt;nlen;i++&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw2"&gt;var&lt;/span&gt; ns = namespaces&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;i&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw1"&gt;typeof&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;root&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;ns&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;===&lt;span class="st0"&gt;'undefined'&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; root = root&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;ns&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; = F;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; root = root.&lt;span class="me1"&gt;prototype&lt;/span&gt; = F;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;else&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;root = root&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;ns&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
JAME.&lt;span class="kw2"&gt;Import&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; nlen=arguments.&lt;span class="me1"&gt;length&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; i=&lt;span class="nu0"&gt;0&lt;/span&gt;;i&amp;lt;nlen;i++&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;var&lt;/span&gt; &lt;span class="kw2"&gt;package&lt;/span&gt;=arguments&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;i&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;package&lt;/span&gt;.&lt;span class="kw2"&gt;Export&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw2"&gt;package&lt;/span&gt;.&lt;span class="kw2"&gt;Export&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
JAME.&lt;span class="me1"&gt;Exporter&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;oName,sPref&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;!sPref&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; sPref=&lt;span class="st0"&gt;''&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;for&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;var&lt;/span&gt; method &lt;span class="kw1"&gt;in&lt;/span&gt; oName&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="kw1"&gt;if&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;method===&lt;span class="st0"&gt;&amp;quot;Export&amp;quot;&lt;/span&gt; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; || &lt;span class="re0"&gt;/^_.+/&lt;/span&gt;.&lt;span class="me1"&gt;test&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;method&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;continue&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; window&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;sPref+method&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;=oName&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;method&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
JAME.&lt;span class="kw2"&gt;Export&lt;/span&gt; = &lt;span class="kw2"&gt;function&lt;/span&gt; &lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="br0"&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; JAME.&lt;span class="me1"&gt;Exporter&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#123;&lt;/span&gt; &lt;span class="st0"&gt;&amp;quot;Package&amp;quot;&lt;/span&gt; : JAME.&lt;span class="kw2"&gt;Package&lt;/span&gt;, &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="st0"&gt;&amp;quot;Import&amp;quot;&lt;/span&gt; &amp;nbsp;: JAME.&lt;span class="kw2"&gt;Import&lt;/span&gt;&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class="br0"&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;br /&gt;
These 3 entries allowed us to experiment with namespaces in javascript!&lt;br /&gt; Understanding their importances, object simulation advantages and creating functions to simplify our code and make it cleaner, organised have been seen.&lt;br /&gt;
Obviously, this is just a starter and many features could be added or improved.&lt;br /&gt;
If you have some ideas, don't hesitate to post them out!&lt;br /&gt;
The extension thru inheritance is not assumed here and should be developed though.&lt;br /&gt;
If you are interested in packages, namespaces way of managing your code, you can look at some other libraries that offer ways to deal with that:&lt;br /&gt;

-&lt;a href="http://ajile.iskitz.com/"&gt;AJILE&lt;/a&gt; : library offering many import, include,namespaces functions.&lt;br /&gt;

-&lt;a href="http://openjsan.org/"&gt;JSAN&lt;/a&gt; : a very good project idea that I invite you to collaborate to in anyway you can!&lt;br /&gt;

Happy new year!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-5713398099575911453?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/5713398099575911453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=5713398099575911453' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5713398099575911453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5713398099575911453'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/12/javascript-namespaces-import-and-export.html' title='Javascript Namespaces : Import and Export methods'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-7020348114278575551</id><published>2007-12-03T23:49:00.000+09:00</published><updated>2010-08-31T22:53:19.044+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='namespace'/><title type='text'>Javascript : Simulating namespaces thru prototyping part 2</title><content type='html'>In the first part, we have seen how we could simulate namespaces very basically with one function used as a container.&lt;br /&gt;
We have seen that namespaces allow to create clean clode, that do not interfere or polluate the global space too much.&lt;br /&gt;
We will see here how to extend the namespace simulation thru a simple Namespace function&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Namespace thru prototype&lt;/h3&gt;
&lt;br /&gt;
We have seen that a simple function used as a namespace could give us a lot of advantages but the drawback was that the main function,used as a namespace, wrapped all the other functions.&lt;br /&gt;
And so what?&lt;br /&gt;
It won't have too much overhead if this function is used only once in your application, but if you 'instantiate' the 'class' several times and that it contains hundreds of line, these hundreds of lines will be kept in memory several times.
&lt;br /&gt;
In order to avoid this, we are going to use the prototype keyword.&lt;br /&gt;
Every functions get a 'prototype' attached to them to which you can add further functions.&lt;br /&gt;
Let's see the example we used in the first entry to see what's going on : &lt;br /&gt;
&lt;pre&gt;
function Arrays() {
    this.toArray = function(elm){
         var tmpArray=[];
         for(var i=0;i &lt; elm.length;i++){
            tmpArray.push(elm[i]);
         }
         return tmpArray;
    },
    this.search = function(elm,search) {
          for(var i=0;i &lt; elm.length;i++){
              if(elm[i]===search) return i;
          }
          return false;
    }
}
Arrays = new Arrays();
alert(Arrays.toSource());#won't work in IE.
&lt;/pre&gt;
The above code create a 'class' containing all the functions.&lt;br /&gt;
We then instantiate an object and see what it contains thru the toSource function.&lt;br /&gt;
Executing this code, you will see that everything defined within the function Arrays, used as a namespace, will be present in the object.&lt;br /&gt;
If you were to create several instances, each instance we hold the entire computation.&lt;br /&gt;
Even if you only instantiate it once,you may not need the search function though.&lt;br /&gt;
Here comes the prototype!&lt;br /&gt;
The prototype allows us to attach functions afterwards.&lt;br /&gt;
Let's see how it works :&lt;br /&gt;
&lt;pre&gt;
function Arrays() {
    this.toArray = function(elm){
         var tmpArray=[];
         for(var i=0;i &lt; elm.length;i++){
            tmpArray.push(elm[i]);
         }
         return tmpArray;
    }
}
oArrays= new Arrays();
alert(oArrays.toSource());

Arrays.prototype = {
    search : function(elm,search) {
          for(var i=0;i &lt; elm.length;i++){
              if(elm[i]===search) return i;
          }
          return false;
    }
};

alert(oArrays.toSource());
alert(oArrays.search(['bonjour','aurevoir','hi'],'hi')); 
#error, function search not defined
&lt;/pre&gt;

If you execute the code, you will see that the instance oArrays of Arrays only contains the toArray function and not search function.&lt;br /&gt;
You also see that adding the search function to the prototype of the Arrays function doesn't change what is contained in the oArrays instance.&lt;br /&gt;
But on the other hand, you see that the oArrays instance doesn't contain the search function at all and will throw an error when trying to call it!&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;How work the prototype?&lt;/h4&gt;

In the above code, we have done the thing in this order:&lt;br /&gt;
&lt;pre&gt;
1) define the namespace Arrays with one function
2) create an instance of the Arrays 'class' called oArrays
3) Add a new object containing the definition of the search function to the prototype
of Arrays
4) call the search function on the oArrays instance
&lt;/pre&gt;

There is one thing to remember about the prototype keyword and instantiation:&lt;br /&gt;
only defined prototype functions will be available to the instance.&lt;br /&gt;
In other word, if you call the Arrays function,create an instance of it and then define a new prototype to it, the prototype won't be available to your instance, here oArrays.&lt;br /&gt;
Here is how we should have done to make it available to the oArrays object:&lt;br /&gt;
&lt;pre&gt;
1) define the namespace Arrays with one function
3) Add a new object containing the definition of the search function to the prototype
of Arrays
2) create an instance of the Arrays 'class' called oArrays
4) call the search function on the oArrays instance
&lt;/pre&gt;
And now, you will be able to use the search function!&lt;br /&gt;
Why ?
Basically, your program is going to be analized in a top-bottom process.&lt;br /&gt;
Nothing really different form other languages! 
But everything happens at run-time, which means that when you instantiate the class, the object will contain the information only available at that time!(only the code that has been parsed- simplified explanation).&lt;br /&gt;
So let's rewrite the code so that we can access what we need:&lt;br /&gt;

&lt;pre&gt;
function Arrays() {
    this.toArray = function(elm){
         var tmpArray=[];
         for(var i=0;i &lt; elm.length;i++){
            tmpArray.push(elm[i]);
         }
         return tmpArray;
    }
}
oArrays= new Arrays();
alert(oArrays.toSource());

Arrays.prototype = {
    search : function(elm,search) {
          for(var i=0;i &lt; elm.length;i++){
              if(elm[i]===search) return i;
          }
          return false;
    }
};
oArrays2= new Arrays();#re-instantiate the class here!
alert(oArrays2.toSource()); #same result as oArrays, just the toArray definition
alert(oArrays2.search(['bonjour','aurevoir','hi'],'hi')); #return 2

&lt;/pre&gt;

As you can see by creating a new object, oArrays2, after the prototype definition, you will be able to use the search function!&lt;br /&gt;
Even more!&lt;br /&gt;
You see that the instance, oArrays and oArrays2 just hold the toArray function!&lt;br /&gt;
In fact, by default, when calling a function on an instance (call a method in that case), javascript will try to see if it can find the definition within the prototype and goes back to all the prototype chain if necessary!&lt;br /&gt;
Thanks to the prototype chain, we can now create a simple empty namespace, ie a function and then attach the functions thru the prototype!&lt;br /&gt;
You will be then able to load only what you really need!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;How to use namespaces : Choosing the root&lt;/h3&gt;
&lt;br /&gt;
In javascript, there is no real standard defining all the libraries and namespaces in use (like CPAN for perl - we will talk about jsan later).&lt;br /&gt;
In order to be sure that your functions and libraries are not going to polluate the global space too much , or enter in conflict with an other library, you should place everthing into a base namespace.&lt;br /&gt;
This namespace can be seen as the root of the tree or as the root of folders on your hard drive or an id, like an IP address.&lt;br /&gt;
We have been developping an animation function that had many helper functions in the global namespace.&lt;br /&gt;
We will then use the namespace concept to clean this out and play nice with other libraries!&lt;br /&gt;
The hardest thing to do is to find the root name, it should be very unique and we should make it not too evident!&lt;br /&gt;
Alright, we are going to use JAME, which is a name that I have found right now, so don't be to hard on me!&lt;br /&gt;
This stands for : Javascript Animations Made Easy&lt;br /&gt;
As you can see, this is not a too evident name like Animation, Tween...&lt;br /&gt;
As far as you are sure that your root namespace is not too evident, then you can always do:&lt;br /&gt;
&lt;pre&gt;
JAME.Util.Strings
JAME.Util.Arrays
&lt;/pre&gt;
These are evident names, almost standards, but they are all attached to the JAME root namespace that protects them!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The Root Namespace by hand&lt;/h3&gt;
&lt;br /&gt;
We have seen that JAME is going to be the root of our namespace tree that is why it is not necessary to have any real definitions into it, we should see it as a place holder.&lt;br /&gt;
We can create the namespace very easily then:&lt;br /&gt;
&lt;pre&gt;
JAME = function() {};
&lt;/pre&gt;
And here we are!&lt;br /&gt;
But we also know that we will need to extend the JAME namespace thru its prototype and not directly as we want to be able to load only what we need.&lt;br /&gt;
Therefore, we shoud do it this way:&lt;br /&gt;
&lt;pre&gt;
JAME = function() {};
JAME = JAME.prototype=function () {};
&lt;/pre&gt;
Now any elements add to JAME will be added to the prototype.&lt;br /&gt;
We want to create an other namespace within JAME that will contain all the helper functions we've been using so far.&lt;br /&gt;
Therefore,we will add the Util namespace, that is an other place older.&lt;br /&gt;
So we just create an empty namespace here too.&lt;br /&gt;
&lt;pre&gt;
JAME.Util = function() {};
JAME.Util = JAME.Util.prototype= function() {};
&lt;/pre&gt;
And now we have the JAME.Util namespace.&lt;br /&gt;
But as you can see this is quite a lot of typo!&lt;br /&gt;
We are going to create a function that will deal with creating namespaces for us.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The Namespace function&lt;/h3&gt;
&lt;br /&gt;
Before we define the function, we will see how to use it:&lt;br /&gt;
&lt;pre&gt;
Namespace("JAME.Util.Strings");
&lt;/pre&gt;
As you can see this is pretty straightforward!&lt;br /&gt;
We just write a string containing each namespace seperated by a dot.&lt;br /&gt;
Let's see how to create a one depth namespacing function, that is just going to wrap what we have done above:&lt;br /&gt;
&lt;pre&gt;
function Namespace(name) {
    window[name]=function() {};
    window[name]=window[name].prototype=function() {};
}
&lt;/pre&gt;
So now you can do:&lt;br /&gt;
&lt;pre&gt;
Namespace("JAME");
JAME.Util=function() {};
&lt;/pre&gt;
We just put the name onto the window object and then create the shortcut to work directly with the prototype of the name.&lt;br /&gt;

If we follow the above namespace, in order to add a namespace of depth 2, we should write:&lt;br /&gt;
&lt;pre&gt;
function Namespace(name1,name2) {
    window[name1]=function() {};
    window[name1]=window[name1].prototype=function() {};
    window[name1][name2]=function () {};
    window[name1][name2]=window[name1][name2].prototype=function() {};
}
&lt;/pre&gt;
you can see that we can add the depth thru [][].&lt;br /&gt;
If we had 3 elements, it will be [][][].&lt;br /&gt;

Let's create a general function that will deal with n depth elements.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;
function Namespace (sName) {

 var namespaces = sName.split('.') || [sName];
 var nlen = namespaces.length;
 var root = window;
 var F = function() {};

 for(var i=0; i &lt; nlen; i++) {
  var ns = namespaces[i];
  if(typeof(root[ns])==='undefined') {
   root = root[ns] = F;
   root = root.prototype = F;
  }
  else
   root = root[ns];
 }
}
&lt;/pre&gt;
What's going on?&lt;br /&gt;
First we split our string by dots or put the sole name in an array.&lt;br /&gt;
Then we create an alias to the window object.&lt;br /&gt;
Then we loop thru each namespaces.&lt;br /&gt;
We first check that the namespace doesn't already exist.&lt;br /&gt;
If not, we assign F to the root and then assign the prototype to the root again.&lt;br /&gt;
If we do it step by step:&lt;br /&gt;
First loop root = window so:&lt;br /&gt;
root = window[namespace[0]] = F;
window[root] = root.prototype = F;
Then second loop:&lt;br /&gt;
root = root[namespace[1]] = F;
window[root] = root.prototype = F;
...
&lt;br /&gt;
And now you can create namespaces very easily!&lt;br /&gt;
&lt;pre&gt;
Namespace("JAME.Util.Strings");
Namespace("JAME.Util.Colors");
Namespace("JAME.Util.Numbers");
&lt;/pre&gt;
Let's see all the helper functions we have seen so far:
&lt;pre&gt;
function camelize(str) {
  return str.replace(/-(.)/g, function(m, l){return l.toUpperCase()});
}
function hyphenize (str) {
  return str.replace(/([A-Z])/g, function(m, l){return '-'+l.toLowerCase()});
}
function firstToUpperCase(str) {
  return str.replace(/^([a-z])/, function(m, l){return l.toUpperCase()});
 }
function trim(str) {
  return str.replace(/^\s+|\s+$/g, '');
}
&lt;/pre&gt;
These are all the helper functions related to strings we've been using so far to create the animation functions.&lt;br /&gt;
We are now, just going to put this into the JAME.Util.Strings namespace :
&lt;pre&gt;
//in the Util folder, we add Strings.js 

//we define the namespace
Namespace("JAME.Util.Strings");


JAME.Util.Strings={
camelize: function(str) {
   return str.replace(/-(.)/g, function(m, l){return l.toUpperCase()});
},
hyphenize : function(str) {
  return str.replace(/([A-Z])/g, function(m, l){return '-'+l.toLowerCase()});
},
firstToUpperCase : function(str) {
  return str.replace(/^([a-z])/, function(m, l){return l.toUpperCase()});
},
trim : function(str) {
   return str.replace(/^\s+|\s+$/g, '');
}
};
&lt;/pre&gt;
Now let's define the colors and numbers:
&lt;pre&gt;
//in the Util folder, we add Numbers.js 

//we define the namespace
Namespace("JAME.Util.Numbers");

JAME.Util.Number= {
    d2h : function(dec) { 
       return dec.toString(16);
    },
    h2d :function(hex) { 
       return parseInt(hex,16);
   },
   randomize : function(min,max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
   }
};
&lt;/pre&gt;
And the colors:&lt;br /&gt;
&lt;pre&gt;
Package('JAME.Util.Colors');

JAME.Util.Colors = {
rgb2h:function (r,g,b) { 
    return [JAME.Util.Numbers.d2h(r),JAME.Util.Numbers.d2h(g),JAME.Util.Numbers.d2h(b)];
},
h2rgb:function (h,e,x) {  
     return [JAME.Util.Numbers.h2d(h),JAME.Util.Numbers.h2d(e),JAME.Util.Numbers.h2d(x)];
},
cssColor2rgb:function (color) {
if(color.indexOf('rgb')&lt;=-1) {
   return this.hexStr2rgbArray(color);
}
   return this.rgbStr2rgbArray(color);
},
hexStr2rgbArray:function (color) {
return this.h2rgb(color.substring(1,3),color.substring(3,5),color.substring(5,7));
},
rgbStr2rgbArray:function (color) {
return color.substring(4,color.length-1).split(',');
}

};
&lt;/pre&gt;
We are not going to see them all for now but I guess you got the picture!&lt;br /&gt;
Now you can use them this way:&lt;br /&gt;
&lt;pre&gt;
JAME.Util.Strings.trim(str);
&lt;/pre&gt;
So you may think, and you are right, that it is a lot of typo!&lt;br /&gt;
Indeed it is but you should not decide for the end user what to put in the global space, the end user can do it very easily:&lt;br /&gt;
&lt;pre&gt;
window["trim"]=JAME.Util.Strings.trim;
trim(str);
&lt;/pre&gt;
The user can give it an other namespace if he/she wants!&lt;br /&gt;
It's up to the context they're in!&lt;br /&gt;
You should avoid functions/variables in the global namespace.&lt;br /&gt;
If you use the global namespace, be sure to make a list available to the end user!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;br /&gt;
We have seen how to create a very basic Namespace function (note namespace and package are reserved words so you can choose either Namespace or Package and be sure it will work).&lt;br /&gt;
This allow us to keep our code clean, structured and if we think of each namespaces as being folders as we have been doing above, we will be able to automaticly create a javascript file containing only the contents you have choosen!&lt;br /&gt;
We can import everything in the global namespace or rename the namespace very easily but we need to offer a tool to import namespaces.&lt;br /&gt;
Inheritance within the namespace hierarchy is not handled yet.&lt;br /&gt;
&lt;br /&gt;
We will see in the next entry how to create an Import function that we'll allow to import functions by controlling what's going on(what if you have split in Arrays and split in Strings and that you import both in the global namespace??)&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-7020348114278575551?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/7020348114278575551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=7020348114278575551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/7020348114278575551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/7020348114278575551'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/12/javascript-simulating-namespaces-part-2.html' title='Javascript : Simulating namespaces thru prototyping part 2'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-3767974202060354289</id><published>2007-12-02T22:40:00.000+09:00</published><updated>2010-08-31T22:53:19.045+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='namespace'/><title type='text'>Javascript : Simulating namespaces basic approach, part 1</title><content type='html'>we have seen in &lt;a href="http://shiriru.blogspot.com/2007/11/javascript-scoping.html"&gt;javascript scoping : things to keep in mind&lt;/a&gt;, that the window object was the global space englobing everything from variables to functions. &lt;br /&gt;

We have also seen that we could create private scoped variables and functions.
Due to the 'last in, win' policy, we have also specified that we should avoid putting everything in the global space as it could lead to unexpected bugs.&lt;br /&gt;

We will see in this entry what are namespaces and how to simulate them in javascript.
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Namespaces ?&lt;/h3&gt;

We have seen that the window object was the global space.&lt;br /&gt;
We could also say that window is the name of a space, that happens to be the global one.&lt;br /&gt;
It doesn't really help?&lt;br /&gt;
Ok, in order to explain the namespace concept we are going to take an everyday life example:&lt;br /&gt;
You are in charge of two sports club named respectivly, Football and Basketball.&lt;br /&gt;
Every players receive an id and each ids are not related to each club.&lt;br /&gt;
If somebody came to you asking for the player 340, you will not be able to know which player it is.&lt;br /&gt;
if the same person asked for Football 340, you will know where to go.&lt;br /&gt;
Football and Basketball are therefore the names that represent a space in which you keep some related information.&lt;br /&gt;
the id 340 in the Football namespace doesn't represent the same player with the same id in the Basketball namespace but they do represent a person.&lt;br /&gt;
&lt;br /&gt;
You could think of folders in your computer:&lt;br /&gt;
&lt;br /&gt;
/usr/home/Football&lt;br /&gt;&lt;br /&gt;
and an other folder:&lt;br /&gt;
&lt;br /&gt;
/usr/home/Basketball&lt;br /&gt;&lt;br /&gt;
Each of them could have a file called list.osd.&lt;br /&gt;You won't have any problem as long as the files are located in different folders.&lt;br /&gt;
You can think of folders and their path, as namespaces too!&lt;br /&gt;
This is so true to life that some languages, like perl, translate packages (a way to create namespaces) into folder path!&lt;br /&gt;
we will see that it is a good idea and use it too in the next entry!&lt;br /&gt;
&lt;br /&gt;

&lt;h3&gt;Namespace for what?&lt;/h3&gt;

As you can see namespaces are a way to keep information in compartimented slot.&lt;br /&gt;
you can have the same id, the same variable or function names if you want:they won't run into each other as long as they are in their related namespace.&lt;br /&gt;

In javascript, if you don't specify anything, your variable or function will be attached to the window namespace.&lt;br /&gt;
If you load two libraries that define the same function name but that they don't do the same thing, it will be very hard to determine where the problem is. 
You might not even know that there is such a function and wonder why you don't get what you expect.&lt;br /&gt;
&lt;br /&gt;

Let's see a stupid example:&lt;br /&gt;
&lt;pre&gt;
// somewhere in your own set of functions
// take a pseudo array and turn it into a real javascript array
// something you could get from a DOM function
function toArray(elm) {
     var tmpArray=[];
     for(var i=0;i&lt; elm.length;i++){
           tmpArray.push(elm[i]);
     }
     return tmpArray;
}

//somewhere in an other library, internal use:
//change a string into an array
function toArray(str) {
     return str.split();
}
&lt;/pre&gt;

Well,,, I guess you get the picture!&lt;br /&gt;
If you have several libraries and that you don't protect yourself from some global space pollution that may occur, you're good for hours of debugging!&lt;br /&gt;
&lt;br /&gt;
Using namespaces is also a very good way to keep your code clean and organized!&lt;br /&gt;
Here we had Football and Basketball but in programming you could have Utilities.Strings, Utilities.Arrays,CSS.Border...
&lt;BR /&gt;
Naming and structuring your code in sub parts will allow to track easily bugs and make your life easier!&lt;br /&gt;

let's see how we can simulate a basic namespace.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;First approach : prefix&lt;/h3&gt;
&lt;br /&gt;
A very easy way to simulate namespace is to simply prefix all your functions. This is a method that you can often find in language that do not support namespaces, like php for example:
&lt;pre&gt;
__MyLibraryToArray();
&lt;/pre&gt;
Here you will prefix all your functions with '__MyLibrary'.&lt;br /&gt;
To some extend, this is a very basic and simple way to simulate namespace.&lt;br /&gt;
clash risks are decreased and one can easily see where the function comes from.&lt;br /&gt;
But this can start to be very cumbersome when your function names reach 30 letters length!&lt;br /&gt;
&lt;pre&gt;
__MyLibraryUtilElementsToArray();
&lt;/pre&gt;

If you use this method, you are sure to type a lot and if you want to change the name..., no, you don't change your name!!&lt;br /&gt;
&lt;br /&gt;
We are therefore going to see how we can make things a little bit simpler and more expandable with javascript objects!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Second Approach : functions as objects&lt;/h3&gt;
&lt;br /&gt;
We have seen in &lt;a href="http://shiriru.blogspot.com/2007/11/javascript-scoping.html"&gt;javascript scoping : things to keep in mind&lt;/a&gt; that functions allow to scope variables and other functions within them.&lt;br /&gt;
We could then define some private functions not accessible from outside of the function and public methods that we could call on the function name:&lt;br /&gt;
&lt;pre&gt;
function Elements() {

    this.toArray = function(elm){
         var tmpArray=[];
         for(var i=0;i&lt; elm.length;i++){
            tmpArray.push(elm[i]);
         }
         return tmpArray;
    }
}
//example of use:
var Elements = new Elements();
Elements.toArray(elm);
&lt;/pre&gt;

Let's say now that you want to put several functions that will deal with arrays, you can just rename the function to keep things coherent:

&lt;pre&gt;
function Arrays() {

    this.toArray = function(elm){
         var tmpArray=[];
         for(var i=0;i&lt; elm.length;i++){
            tmpArray.push(elm[i]);
         }
         return tmpArray;
    }
    this.search = function(elm,search) {
          for(var i=0;i&lt; elm.length;i++){
              if(elm[i]===search) return i;
          }
          return false;
    }
}

//example of use:
var Arrays= new Arrays();
Arrays.toArray(elm);
Arrays.search(elm2,'hi');

&lt;/pre&gt;

but how do you do with all the code that refers to Elements.toArray??&lt;br /&gt;
Well, using functions to create namespaces is very powerful as you just need to create an alias that joins the old namespace with the new one:&lt;br /&gt;
&lt;pre&gt;
Elements=Arrays;
&lt;/pre&gt;
And you can know create legacy code if necessary with just one line!&lt;br /&gt;
Something that simple prefixing will not allow you.&lt;br /&gt;
&lt;br /&gt;

You could even be lazy and because you know that you are not going to use some other libraries, you want to access the function directly:&lt;br /&gt;
&lt;pre&gt;
var Arrays=new Arrays();
window['search']=Arrays.search;
//now you can call it directly:
search(elm,'hi');
&lt;/pre&gt;

Here again, this shows how powerful and useful namespaces can be!&lt;br /&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;
We have seen a very basic way of simulating namespaces in javascript thru a simple function used as a container for several related functions.&lt;br /&gt;
Using namespaces allow to make your code clean and organized but yet flexible as we have seen above!&lt;br /&gt;
This obviously allows you to protect your code or people using your code from global space pollution which can be very handy when dealing with several libraries!&lt;br /&gt;
Obviously, the above method is far to be the best one as we have put everything in one function.&lt;br /&gt;
Each time you will call the function or someone does it, all the computation within the function will be kept in memory. If you are sure that you will call the namespace just once, that can be ok but you never know!&lt;br /&gt;
We will see in an other entry how we can extend our namespaces functionnalities with objects!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-3767974202060354289?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/3767974202060354289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=3767974202060354289' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/3767974202060354289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/3767974202060354289'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/12/javascript-simulating-namespaces-basic.html' title='Javascript : Simulating namespaces basic approach, part 1'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-5668697264584265221</id><published>2007-11-17T11:00:00.000+09:00</published><updated>2007-11-18T22:12:05.251+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>Javascript scoping : Things to keep in mind</title><content type='html'>Because scope in javascript can be the source of very hard to track bugs, we will see how work the variable scoping in javascript. Depending on your programming languages background (block level scoping or not), you may have some surprises.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt; Defining the global space&lt;/h3&gt;
&lt;br /&gt;
In most of the actual browsers, the window object is the global space that contains all the core functions of the language and all the variables, functions that will be defined in it. In perl, this will be the 'main' namespace.&lt;br /&gt;
&lt;br /&gt;
If you declare a variable, you will see that you can call it on the window object:&lt;br /&gt;

&lt;pre&gt;
var mywidth=100;
myheight=200;
alert(window['mywidth']); // returns 100
// you could also write it like so : window.mywidth

alert(window['myheight']); // returns 200
alert(window['myheight']===myheight); // returns true

&lt;/pre&gt;
Calling variable or functions on the window object can be very useful when you take a function name as a string from an other function!&lt;br /&gt;
Let's see an example:&lt;br /&gt;
&lt;pre&gt;
function getFunction(func) {
      func();
}
getFunction('myalert');

function myalert() {
   alert('I am going to fail!');
}
&lt;/pre&gt;
The above example will fail because we are trying to resolve what javascript considers as being a string into a function and obviously, this is not going to work!&lt;br /&gt;
We could then try to eval the string and change the getFunction:&lt;br /&gt;
&lt;pre&gt;
function getFunction(func) {
     var ref=eval(func);
     ref();
}
&lt;/pre&gt;
This will work but eval'uating the string into a function has some overhead and security problems that we could get rid off by calling the function on the window object directly!&lt;br /&gt;
&lt;pre&gt;
function getFunction(func) {
    window[func]();
}
&lt;/pre&gt;
The first example will then work!&lt;br /&gt;
Obviously not everything is accessible from the window object as we can induce scoping in javascript at a function level.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt; to var or not to var ?&lt;/h3&gt;
&lt;br /&gt;
In javascript there are two ways of defining a variable, with the keyword var or without!&lt;br /&gt;
The main thing to understand is that contrary to the abbreviation, var doesn't mean you are declaring a variable, it will indicate the scope of your variable!&lt;br /&gt;(my keyword vs our keyword in perl)
We've been using both notations in the above examples and we see that variables define in the global space do not have their scope change.&lt;br /&gt;
&lt;pre&gt;
//the following notations are the same:
var myheight=100; 
myheight=100;
alert(window.myheight==100);//return true
&lt;/pre&gt;
In the global namespace, the var keyword doesn't have any influence on the scoping of the variable, therefore we can do the following:
&lt;pre&gt;
var myheight=100;
mywidth=100;

function getwidthAndHeight() {
 alert(myheight+' and '+mywidth);
}
&lt;/pre&gt;
Variables defined in the global namespace will be accessible from within all the functions because they are hold in the window object.&lt;br /&gt;
The var keyword starts to be interesting only once use in a function context.&lt;br /&gt;
We can see in the example below that the use of var will change the scope of the variable:&lt;br /&gt;
&lt;pre&gt;
var myheight=100;
mywidth=100;

function getwidthAndHeight() {
 alert(myheight+' and '+mywidth); 
 var mycolor='#000000';
 mybackgroundColor='#FFFF00';
}
function getColorAndBackgroundColor() {
   alert(mycolor+' and '+mybackgroundColor);
}
getwidthAndHeight(); //alert 100 and 100
getColorAndBackgroundColor() //alert undefined and #FFFF00
&lt;/pre&gt;
Here you need to be very careful to the getWidthAndHeight way of defining the variables.&lt;br /&gt;
the mycolor variable is defined using the var keyword while the mybackgroundcolor doesn't.&lt;br /&gt;
In fact, when a variable is defined without the var keyword within a function, in the bakcground the following will be interpreted:&lt;br /&gt;
&lt;pre&gt;
function getwidthAndHeight() {
 alert(myheight+' and '+mywidth); 
 var mycolor='#000000';
 window.mybackgroundColor='#FFFF00';
}
&lt;/pre&gt;
Every variables that are not defined with the var keyword in a function context will be assigned to the window object and therefore becomes global variables too.&lt;br /&gt;
That's why you should always be aware of when use or not use the var keyword in a function.&lt;br /&gt;
A variable defined with the var keyword in a function is not accessible from outside, that's why we can refer to it as a private variable!&lt;br /&gt;
You can also create private functions within a function thanks to closure:&lt;br /&gt;
&lt;pre&gt;
function getwidthAndHeight() {
 var mycolor='#000000';
 var mywidth=function () {
     return mycolor;
 }
 alert(mywidth());//alert #000000
}
//outside of the function
alert(mywidth()); // error!
&lt;/pre&gt;
The following variables, one holding a string and one a reference to function will not be accessible from outside and are private to the function they are defined in!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Reminder : Avoid global space variables&lt;/h3&gt;
&lt;br /&gt;
Javascript follows a very basic rule when use within a browser:&lt;br /&gt;
Last in, win!&lt;br /&gt;
Putting variables and even functions in the global space is to avoid as if you have the same variables or functions defined into 2 differents javascript files, the last javascript file will 'overwrite' the precedent functions and variables!&lt;br /&gt;
Therefore you might not be working with the function you were thinking of.&lt;br /&gt;
It is not very relevant if you only use two or three functions but when you add some libraries from outside and if they put functions or variables in the global name space, you will have a hard time to understand why you're not getting what you were expecting, thinking there is a bug in your function!!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt; Block level scoping&lt;/h3&gt;
&lt;br /&gt;
There aren't!&lt;br /&gt;
You have to be aware that variables define within the scope of block statement (for, while, if...) will be accessible outside of this block:&lt;br /&gt;
&lt;pre&gt;
if(mywidth==100){
   var myheight=200;
}
alert(myheight); // alert 200
&lt;/pre&gt;
This behavior is not true in all languages where a variable defined within a scope will end its life once the block is terminated.&lt;br /&gt;
There is one thing you have to be aware of:&lt;br /&gt;
&lt;pre&gt;
for(var i=0;i&lt;=100;i++) {
   mycolor=i;
}
for(; i&lt;50;i++) {
   mywidth=i;
}
alert(mycolor); //100
alert(mywidth); // error
&lt;/pre&gt;
The following might not give you back what you could expect!&lt;br /&gt;
defining the i variable with the var keyword in the for loop doesn't give the i keyword a scope to that loop.&lt;br /&gt;
Therefore when entering the second loop, i is equal to 100 and the second loop will never start!&lt;br /&gt;
In order to avoid this kind of problem, you should always use different name for counters:&lt;br /&gt;
&lt;pre&gt;
for(var i=0;i&lt;=100;i++) {
   mycolor=i;
}
for(j=0; j&lt;50;j++) {
   mywidth=j;
}
&lt;/pre&gt;
This will avoid some unexpected bugs and make your life easier!&lt;br /&gt;
i,j,k,l,m,n you can just increment the name according to the alphabet letters.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Functions and scope&lt;/h3&gt;
&lt;br /&gt;
We have seen that the var keyword has only a meaning within the context of a function.&lt;br /&gt;
Therefore we can have privates and global variables if we want.&lt;br /&gt;
But functions allows to define an other scope: the name of the function!&lt;br /&gt;
We have seen that all variables define within a function without the var keyword were assigned in the background to the window object.&lt;br /&gt;
That's fine but let's say that you want to create clean code and avoid global variables but that you would like to use the variable from outside the function, how could we do?&lt;br /&gt;
In fact, outside of a function, in the global namespace, we can give to the window object an other name, an other keyword : this.&lt;br /&gt;
The this keyword is very important in javascript and can be confusing at the beginning but let's see the following code:&lt;br /&gt;
&lt;pre&gt;
mycolor=100;
alert(this.mycolor);//return 100
alert(window.mycolor);//return 100
alert(window===this); return true
&lt;/pre&gt;
The this keyword in the global namespace is equal to the window object!&lt;br /&gt;
Functions allows us to use the this keyword within them but in that case, the this keyword do not refer to the window object anymore but to the function name!&lt;br /&gt;
But be careful, the way you call the function can switch back the this keyword to the window object!&lt;br /&gt;
&lt;pre&gt;
function changeColor() {
  alert(this);
}
changeColor(); // object
new changeColor(); // object Object
&lt;/pre&gt;
Javascript is telling that the first call to the changeColor refers to a native object, that is the window object while the second object is a user defined Object, that is changeColor.&lt;br /&gt;
We can verify that the this keyword refers to the function name with the instanceof keyword that tells us if something corresponds to a certain name:&lt;br /&gt;
&lt;pre&gt;
function changeColor() {
  alert(this instanceof changeColor);
}
changeColor(); // false
new changeColor(); // true
&lt;/pre&gt;
This may sound a little bit confusing but using the new keyword will create in the background for us, an object (like the window object but not native) and bind this object to the name of the function.&lt;br /&gt;
(In perl, you 'bless' an hash with its package name to get an object)&lt;br /&gt;
&lt;br /&gt;
What can we do with this?&lt;br /&gt;
Well, now, we are able to create variables scoped to the name of the function!Giving us 3 types of scope for variables:&lt;br /&gt;
&lt;pre&gt;
function scopeIsFun() {

    globalVariable=100;

    var privateVariable=200;

    this.publicVariable=300;

    this.publicMethod=function() {
         alert('You can call me on the scopeIsFun object!');
    }
    var privateMethod=function() {
        alert('you cannot call me from outside!!');
    }
}
alert(globalVariable); // 100

alert(privateVariable); //error

alert(scopeIsFun.privateVariable); //error

alert(scopeIsFun.publicVariable); // 300

alert(publicVariable); // error

alert(scopeIsFun.publicMethod()) // 'You can call me on the scopeIsFun object!'

alert(publicMethod()) // error

alert(scopeIsFun.privateMethod()); // error

alert(privateMethod()); // error

&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;br /&gt;
Javascript scoping may seem weird at the beginning but it can be a very powerful tool to build nice libraries that won't walk on other librairies.&lt;br /&gt;
The different ways to scope a variable or methods within a function is the base that will allow to simulate namespace in javascript and the base of object oriented programming.&lt;br /&gt;
We will see what is and how to simulate namespace by using what we've seen here in a next entry!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-5668697264584265221?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/5668697264584265221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=5668697264584265221' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5668697264584265221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5668697264584265221'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/11/javascript-scoping.html' title='Javascript scoping : Things to keep in mind'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-5717052387447876879</id><published>2007-11-13T23:18:00.001+09:00</published><updated>2010-09-28T11:57:17.442+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : Implementing Margin and Padding</title><content type='html'>After changing our main animation function to a pluggable one, thanks to the strategy associated with the factory pattern, we will see how ce can implement multipart css values like margin and padding.
&lt;br /&gt;
&lt;h3&gt;
Differentiating the settings&lt;/h3&gt;
&lt;br /&gt;
Many css properties can be written with 3 to 4 values, each of them setting a particular sub property.&lt;br /&gt;
The margin and padding properties are one of those and we will just see what each setting means concretly.&lt;br /&gt;
&lt;h4&gt;
The clock wise cycle&lt;/h4&gt;
As you know a div or a block element can be resumed to a simple square.&lt;br /&gt;
This square has a top, right, bottom and left property.&lt;br /&gt;
If you think of a square and put each sub properties on their position, you will see that the above describes the movement of a clock wise.&lt;br /&gt;
let's see a simple div:&lt;br /&gt;
&lt;div style="border-color: rgb(0, 0, 255) rgb(0, 255, 0) rgb(255, 0, 0) rgb(255, 0, 255); border-style: none; border-width: medium; height: 50px; width: 50px;"&gt;
&lt;/div&gt;
As we can see we have a different color for each line of the square, if you follow each line from top in the clock wise order, you will get:&lt;br /&gt;
&lt;pre&gt;top
right
bottom
left
&lt;/pre&gt;
&lt;br /&gt;
Well when you set each properties for the padding or margin property, each value will set the sub property in this order.&lt;br /&gt;
&lt;pre&gt;margin:1px 2px 3px 4px;
&lt;/pre&gt;
If you want to set the same value to all the sub properties, you just write it once:&lt;br /&gt;
&lt;pre&gt;margin:1px
&lt;/pre&gt;
If you set only 2 properties then:&lt;br /&gt;
&lt;pre&gt;margin:1px 2px;
&lt;/pre&gt;
Well, this will distribute each value in this order:&lt;br /&gt;
&lt;pre&gt;margin-top:1px;
margin-right:2px;
margin-bottom:1px;
margin-left:2px;
&lt;/pre&gt;
And if you set 3 properties?&lt;br /&gt;
&lt;pre&gt;margin:1px 2px 3px;
&lt;/pre&gt;
&lt;pre&gt;margin-top:1px;
margin-right:2px;
margin-bottom:3px;
margin-left:2px;
&lt;/pre&gt;
So, as you can see, it follows a pattern that you can apply to all properties taking up to 4 values.&lt;br /&gt;
We can resume as follow:&lt;br /&gt;
&lt;pre&gt;1 value  [TOP  RIGHT BOTTOM LEFT]
2 values [TOP BOTTOM][RIGHT LEFT]
3 values [TOP][RIGHT LEFT][BOTTOM]
4 values [TOP][RIGHT][BOTTOM][LEFT]
&lt;/pre&gt;
&lt;h4&gt;
Representing the unusual clock wise&lt;/h4&gt;
&lt;br /&gt;
Now that we know what's going on exactly, we just need to find a way to express the same rule in javascript.&lt;br /&gt;
First let's create a literal array containing each sub property:&lt;br /&gt;
&lt;pre&gt;var subProperties=['Top','Right','Bottom','Left'];
&lt;/pre&gt;
If you remember the above explanation, when you set only one value, each sub properties will be assigned this value.&lt;br /&gt;
Let's create 4 javascript variables representing each sub properties set in the example above:&lt;br /&gt;
&lt;pre&gt;var top    =1;
var right  =1;
var bottom =1;
var left   =1;
&lt;/pre&gt;
If we set 2 values, we will get:&lt;br /&gt;
&lt;pre&gt;var top    =1;
var right  =2;
var bottom =1;
var left   =2;
&lt;/pre&gt;
if we set 3 values, we will get:&lt;br /&gt;
&lt;pre&gt;var top    =1;
var right  =2;
var bottom =3;
var left   =2;
&lt;/pre&gt;
And if we set 4 values:&lt;br /&gt;
&lt;pre&gt;var top    =1;
var right  =2;
var bottom =3;
var left   =4;
&lt;/pre&gt;
We can get from there, a litteral array that will be in relation with each sub properties:&lt;br /&gt;
&lt;pre&gt;var subProperties=['Top','Right','Bottom','Left'];
var subPropertiesValues=[top,right,bottom,left];
&lt;/pre&gt;
If you understood the above, everything will be fine!&lt;br /&gt;
It's time to go back a little and see how to separate each values!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Separating the values&lt;/h3&gt;
&lt;br /&gt;
We have seen how the values could be written and we know that we have a numeric strategy that handles single numeric-like value for us.&lt;br /&gt;
What does it mean?&lt;br /&gt;
If we set the margin or padding with only one value, the numeric strategy will do its work!&lt;br /&gt;
It means that we do not really have to deal with this case!&lt;br /&gt;
Let's see again a margin set with several values:&lt;br /&gt;
&lt;pre&gt;margin:1px 2px 3px 4px;
&lt;/pre&gt;
Well, what we need to do, is separate each value, set the right sub property and send everything to our numeric strategy!&lt;br /&gt;
Let's split the string:&lt;br /&gt;
&lt;pre&gt;function splitMultiPart(str){
 return str.split(/\s/) || [];
}
&lt;/pre&gt;
Our function will split the string by looking for a space and return an array.&lt;br /&gt;
That was easy!&lt;br /&gt;
Our array can have different length according to the number of value set.&lt;br /&gt;
If there is only one value, it will be of 1 length.&lt;br /&gt;
If there is 4 values, it will be a 4 length array.&lt;br /&gt;
But we know that an array starts from 0 to access its value.&lt;br /&gt;
We can write the following:&lt;br /&gt;
&lt;pre&gt;var top=0,right=0,bottom=0,left=0;
if(elm.length==2) top=0,right=1,bottom=0,left=1;
if(elm.length==3) top=0,right=1,bottom=2,left=1;
if(elm.length==4) top=0,right=1,bottom=2,left=3;
&lt;/pre&gt;
Here we are not setting the value of each sub properties, but we are simply setting the position of the value in the array we got from the split!&lt;br /&gt;
If there is only one value, each sub properties, top, right, bottom, left will be set with the value contained in the unique slot, slot 0.&lt;br /&gt;
If there is 4 values, each sub properties, top, right,bottom,left will be set with the value contained in each slot 0,1,2,3.&lt;br /&gt;
Let's see the function:&lt;br /&gt;
&lt;pre&gt;function setMultiPart(totalframes,frame,prop,props,easing){
    
  //split the string of each properties
    var begin  = splitMultiPart(props[prop].start);
    var end    = splitMultiPart(props[prop].end);
    var bezier = (props[prop].bezier)? splitMultiPart(props[prop].bezier):[];
   
  //define each array slot according to the number of values set
    var top=0,right=0,bottom=0,left=0;
    if(values.length==2) top=0,right=1,bottom=0,left=1;
    if(values.length==3) top=0,right=1,bottom=2,left=1;
    if(values.length==4) top=0,right=1,bottom=2,left=3;

 //put each value into one array
    var v = [top,   right,  bottom,  left];
    var p = ['Top','Right','Bottom','Left'];
    var propTmp='';


    for(var i=0;i &amp;lt; v.length;i++) {
          //create one property ie, marginTop,marginRight...
             propTmp  = prop+p[i]; 
          //assing each value to the object
             props[prop].start  = begin[v[i]];
             props[prop].end    = end[v[i]];
             props[prop].bezier = bezier[v[i]];
           //then send the property to the numeric strategy!
             NumericStrategy(totalframes,frame,propTmp,props,easing);
   }
}
&lt;/pre&gt;
As you can see, this is not very hard!&lt;br /&gt;
We just split the string by their space, assign each value to their sub property (margin-top,margin-left) and then let the calculation to the numeric strategy!&lt;br /&gt;
Now we just need to create wrappers function called Margin and Padding as our intelligent factory is going to call them:&lt;br /&gt;
&lt;pre&gt;function Margin(totalframes,frame,prop,props,easing) {
   setMultiPart(totalframes,frame,prop,props,easing);
}
function Padding(totalframes,frame,prop,props,easing) {
   setMultiPart(totalframes,frame,prop,props,easing);
}
&lt;/pre&gt;
&lt;br /&gt;
And we are done!&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
In this entry, we have seen how we could extend our animation function by extending the css properties it can handle.&lt;br /&gt;
As you can see we only focused on resolving the multipart redistribution to each sub property without changing the internal behavior of the animate function!&lt;br /&gt;
We are now able to extend when needed the css properties we can handle in a pluggable manner!&lt;br /&gt;
There is no example of the actual addition as we will see in a next entry how to change the parameters we send to the function and in the same time add the border property!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-5717052387447876879?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/5717052387447876879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=5717052387447876879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5717052387447876879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5717052387447876879'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/11/javascript-animation-implementing.html' title='Javascript Animation : Implementing Margin and Padding'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-5138651440683806533</id><published>2007-11-07T00:16:00.002+09:00</published><updated>2010-09-28T11:57:17.442+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Design Pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : Strategy and Factory Pattern at the rescue (8)</title><content type='html'>In just 7 entries, we've seen how to start with a basic easing effect dealing with 2  or 3 css attributes at a time and end up with a rich animation function able to deal with time, frames,manipulate several properties at once in a cross browser way, animate colors, create several easing in/out effects and deviate the path thru a bezier curve! but...&lt;br /&gt;
&lt;br /&gt;
The main drawbacks is that we were adding new possibilities directly into the animate function with the help of if...else statements...&lt;br /&gt;
If it may be a good work around for a time and for few properties, when the css properties you want to handle grow up, that new css properties pop up, having to add if... else if... else statements in the core function can become cumbersome:&lt;br /&gt;
- you may have to handle many new css attributes&lt;br /&gt;
- you will need to add more and more if statements, making the function hardly readable
- even if you use just 10 percents of the function capacities, you will have to load the entire function
- if the code has been working for a while, adding directly in the core can bring bugs, unexpected chaining effects...&lt;br /&gt;
&lt;br /&gt;
In other word, the code will be a mess!!&lt;br /&gt;
&lt;br /&gt;
Here comes the strategy pattern associated with the factory pattern to the rescue !&lt;br /&gt;
we will see how to create an expandable function that can be plugged from outside to add new properties like margin or padding thanks to this pattern!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Design pattern what ?&lt;/h3&gt;
&lt;br /&gt;
Design patterns are common solutions to common problems.&lt;br /&gt;
We have seen above what kind of problems our program could lead to in the long run.&lt;br /&gt;
In fact, our program is a solution to the problem but unfortunately not the better one!&lt;br /&gt;
The gang of four, authors of design patterns, have brought to us many solutions to many common problems.Solutions thought and re-thought, try and retried to end up to be a 'design pattern'. If you want, a kind of solution template for a recurrent problem !&lt;br /&gt;
They all relate to object oriented programming but we will see that we can use the concept behind the patterns in a procedural way too.
&lt;br /&gt;
&lt;h3&gt;
Strategy pat... what ?&lt;/h3&gt;
&lt;br /&gt;
We have seen that we had to change our effect calculation strategy according to the value we got:&lt;br /&gt;
- we had a specific calculation strategy for a simple numeric value like 12px or 1 that could be resumed to simple numbers (12 instead of 12px) or&lt;br /&gt;
- we had an other specific calculation strategy for a string that contains the numeric value in a different format like the colors #FF00FF or rgb(255,0,255)!&lt;br /&gt;
In order to face this divergence we just added an if statement to handle numeric values and colors.&lt;br /&gt;
By doing so, we were aware that the function was becoming messy... hard to read, hard to maintain and not expandable as we could wish.&lt;br /&gt;
Let's say that we know want to manipulate margin or padding...&lt;br /&gt;
We can see their value structure:&lt;br /&gt;
margin:12px;&lt;br /&gt;
margin:12px 1px;&lt;br /&gt;
margin:12px 1px 5px;&lt;br /&gt;
margin:12px 1px 5px 8px;&lt;br /&gt;
&lt;br /&gt;
The same for the padding!&lt;br /&gt;
We face 4 different values in one attribute and the number of value changes the sub attribute they relate to !&lt;br /&gt;
We could do this at first:&lt;br /&gt;
&lt;pre&gt;if(numeric) {
//calculation
}
else if (color) {
//calculation 
}
else if (multi) {
//calculation
}
&lt;/pre&gt;
I have shorten up the code but I guess that you can see that if else if else statements (even if disguised under a switch statement!!) is far to be the most expandable way of doing it!&lt;br /&gt;
Is there a way to change of strategy automagicly without even having to specify it?&lt;br /&gt;
Well, there is!&lt;br /&gt;
&lt;h3&gt;
The Strategy pattern&lt;/h3&gt;
The strategy pattern allows to change the behavior of part of an algorythm in a class or in our case in a function!&lt;br /&gt;
Basically we are going to put outside of the function each strategy in order to keep our core function clean and easy to maintain.&lt;br /&gt;
By putting outside the calculation, we will also be able to add new strategies very easily!&lt;br /&gt;
Let's see the actual function first:&lt;br /&gt;
&lt;pre&gt;function animate(elm,props, duration, fps,easing) {

 duration = (duration) ? parseFloat(duration) : 1000;
 fps      = (fps)      ? parseFloat(fps)      : 20;
 easing   = (easing)   ? easing               : linearEase;

 var interval    = Math.ceil(1000/fps);
 var totalframes = Math.ceil(duration/interval);

 for(i=1;i &amp;lt;= totalframes;i++) {
   (function() {
      var frame=i;
      displacement=function() {
          for(var prop in props){
              if(!/olor/.test(prop)) {
                  var begin = props[prop].start*100;
                  var end   = props[prop].end*100;
                  var bezier = props[prop].bezier*100;
                  var actualDisplacement=
                  easing(frame, begin, end-begin, totalframes);
                  if(bezier) 
                    actualDisplacement=
                    QuadBezier(frame,actualDisplacement,end,bezier,totalframes);
                    setStyle(elm,prop,actualDisplacement/100;
                  } else {
                    var b = hexStr2rgbArray(props[prop].start);
                    var e = hexStr2rgbArray(props[prop].end);
                    var rgb=[];
                    for(j=0;j&amp;lt;3;j++) 
                    rgb.push(parseInt(easing(frame, b[j], e[j]-b[j], totalframes)));
                    setStyle(elm,prop,'rgb('+rgb.join(',')+')');  
        }
   }
       }
       timer = setTimeout(generalProperty,interval*frame);
   })();   
 }
}

&lt;/pre&gt;
huh, it's a pretty long function!&lt;br /&gt;
We first do some initialisation then some calculation for the entire function then we calculate the animation within a loop.&lt;br /&gt;
In order to change our calculation strategy according to the property, we check to see if we have a color and if not we switch to the other one.&lt;br /&gt;
we see that this won't work with the margin property anymore...&lt;br /&gt;
In order to add the margin,padding calculation strategy within the function we will have to change the way we identify the type of the incoming property, which could lead to errors and eventually, a function that you won't be able to maintain and understand.&lt;br /&gt;
Therefore, let's do a simple thing: put outside each strategy!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Identifying the strategies&lt;/h3&gt;
&lt;br /&gt;
We have two ways of calculating the property : one for the numeric values and one for the strings that contains an hexadecimal color code.&lt;br /&gt;
We can then create two helpers functions:&lt;br /&gt;
&lt;pre&gt;function NumericStrategy(totalframes,frame,prop,props,easing) {
    var begin  = props[prop].start*100;
    var end    = props[prop].end*100;
    var bezier = props[prop].bezier*100;
    var actualDisplacement=easing(frame, begin, end-begin,totalframes);
    if(bezier) {
      actualDisplacement=QuadBezier(frame,actualDisplacement,end,bezier,totalframes);
    }
    setStyle(elm,prop,actualDisplacement/100;
}
function ColorStrategy(totalframes,frame,prop,props,easing) {
   var b = hexStr2rgbArray(props[prop].start);
   var e = hexStr2rgbArray(props[prop].end);
   var rgb=[];
   for(j=0;j&amp;lt;3;j++) {
        rgb.push(parseInt(easing(frame, b[j], e[j]-b[j], totalframes)));
   }
   setStyle(elm,prop,'rgb('+rgb.join(',')+')');
}
&lt;/pre&gt;
The numeric function will be in charge of working with numbers and therefore allow to handle many css properties : height, width, opacity, font-size,top,left...&lt;br /&gt;
We consider a number being a unique decimal number followed by its unity.&lt;br /&gt;
&lt;pre&gt;width:120px,
top:-100px,
opacity:.9
&lt;/pre&gt;
All these properties can be resumed to a unique number.&lt;br /&gt;
A margin or padding property is not considered a unique number but a property composed of serveral numbers, that the above function could handle individually.&lt;br /&gt;
The Color function is in charge of calculating the value for a string written in an hexadecimal way and defining a color.&lt;br /&gt;
This one is rather specific to one type of property but we can use it for color, background-color.&lt;br /&gt;
For now, there isn't that big changes, we have just put outside the calculation for each strategy, making the core function a little bit easier to understand but still unable to deal with margin or padding.&lt;br /&gt;
Before we go ahead, I shall show you how the strategy pattern does really look like as defined and how it will be used in practice in general:&lt;br /&gt;
&lt;pre&gt;var prop={
    color:{start:'#FFFFFF',end:'#0000FF'},
    'background-color':{start:'#FF0000',end:'#00FF00'}
};
animate(elm,prop,1500,25,easeInOutBounce,ColorStrategy);
var prop={
    width:{start:'150px',end:'20px'},
    top:{start:'0px',end:'-100px'},
    opacity:{start:0,end:1}
};
animate(elm,prop,1500,25,easeInOutBounce,NumericStrategy);
&lt;/pre&gt;
In that case, there won't be any switch of strategy in the function like we used to do at the beginning, the function will just apply the strategy given as a parameter in the function, like we did for the easing functions.&lt;br /&gt;
This is the usual basic way of implementing the strategy pattern but as you can see this is not very useful!&lt;br /&gt;
Now you can only animate one type of property at a time and you have to be aware of the strategy to apply...This is not what I will call a user friendly programming interface!&lt;br /&gt;
We need to keep the interface easy to use and hide all the process from the end user: the user shouldn't have to know that we change our strategy to calculate the property and the user should obviously not even know the existence of the 2 strategy functions!&lt;br /&gt;
In general, in a object oriented programming concept, this is what we call encapsulation or putting everything in a box that hides all the process to the end user. &lt;br /&gt;
In this regard, a function is the core, the basic tool you can use to create encapsulation!&lt;br /&gt;
instead of writing again and again the same calculation everywhere in your program, you put the calculation in a function, give it an easy to understand name and here you go, you encapsulate the process!&lt;br /&gt;
Our first approach, which was to switch the strategy in the function was a good way of keeping encapsulation.&lt;br /&gt;
So let's go back a little and keep the encapsulation by having the switching process between the strategies in the function, by using a simple if... else statement:

&lt;br /&gt;
&lt;pre&gt;if(/[0-9]+/.test(parseInt(start)) &amp;amp;&amp;amp; !/\s/.test(start)) {
 NumericStrategy(totalframes,frame,prop,props,easing);
} else {
 ColorStrategy(totalframes,frame,prop,props,easing);
}
&lt;/pre&gt;
We have seen that looking for a property containing the word color to switch between numeric or color strategy is not going to work with margin and padding.&lt;br /&gt;
Instead we are going to change our split strategy!&lt;br /&gt;
We will be looking for what we consider as being a numeric value and everything else!
We first check to see if the parseInt value result in a number.&lt;br /&gt;
If parseInt can't find a number, it will send back the string,NaN, which stands for Not a Number.&lt;br /&gt;
But the margin will be considered as a numeric value so we need to look for any space in the string, if there is, we know that it's not something that our numeric function will be able to handle so we let the ColorStrategy does its works.&lt;br /&gt;
This is a little bit naive as it might in fact be the margin or padding or even worse, something we didn't think about!! and our function will crash...&lt;br /&gt;
But for now, let's go back to the end user and see how it works:&lt;br /&gt;
&lt;pre&gt;var prop={
    color:{start:'#FFFFFF',end:'#0000FF'},
    'background-color':{start:'#FF0000',end:'#00FF00'}
    width:{start:'150px',end:'20px'},
    top:{start:'0px',end:'-100px'},
    opacity:{start:0,end:1}
};
animate(elm,prop,1500,25,easeInOutBounce);
&lt;/pre&gt;
As you can see, this is a little bit easier for the end user!&lt;br /&gt;
It doesn't have to worry about the type of the property he/she used and therefore, keep the process very easy.&lt;br /&gt;
We have gain in the background an easier function to read and debug as we have put outside the calculation.
let's see how the function looks like now:
&lt;br /&gt;
&lt;pre&gt;function animate(elm,props, duration, fps,easing) {

      var duration    = (duration) ? parseFloat(duration) : 1000;
      var fps         = (fps)      ? parseFloat(fps)      : 20;
      var easing      = (easing)   ? easing               : easeOutBounce;
      var interval    = Math.ceil(1000/fps);
      var totalframes = Math.ceil(duration/interval);
      var Animator    = new Animate();

      for(var i=1;i &amp;lt;= totalframes;i++) {
         (function() {
     var frame=i;
            var setAnimation=function() {
     for(var prop in props){
                       var start=props[prop].start;
                       if(/[0-9]+/.test(parseInt(start)) &amp;amp;&amp;amp; !/\s/.test(start)) {
                           NumericStrategy(totalframes,frame,prop,props,easing);
                       } else {
                           ColorStrategy(totalframes,frame,prop,props,easing);
                       }
     }
            }
            var timer = setTimeout(setAnimation,interval*frame);
        })();   
     }
}
&lt;/pre&gt;
As you can see, the function is shorter and as we have put outside the calculation into functions with easy to understand name, we can almost understand what's going on without having to think too much!&lt;br /&gt;
We can now change the numeric or color function without fearing to create bugs in the core function!&lt;br /&gt;
But if maintainability has been improved, our function is still unable to deal with margin or padding!&lt;br /&gt;
If we want to do so, we will need to go in the function, change our if... else statements, with all the problemes this could bring.&lt;br /&gt;
We should put this switch between strategy outside and use a function to wrap this, a function that will be in charge of building the right calculation, the right strategy, a kind of factory!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The factory pattern&lt;/h3&gt;
&lt;br /&gt;
You've been using the factory pattern all the time without even knowing it!&lt;br /&gt;
If we go back to the source and think of what is a factory, we could define it as something taking a raw element or several raw elements to output something that we can use.&lt;br /&gt;
When you write a function that changes an hexadecimal color string into an array of 3 numeric values, you are creating a factory: it takes a raw string that you can't use and change it into something usable and valuable for you!&lt;br /&gt;
In our case, the factory will be in charge of defining the proper strategy for the css element it receives and call it to have our final product in every case: a number to which we can apply a computation and therefore create an animation.&lt;br /&gt;
The definition of our strategy factory is very easy for now, we just wrap the if else statements in a function:&lt;br /&gt;
&lt;pre&gt;function strategyFactory(totalframes,frame,prop,props,easing) {
     var start=props[prop].start;
     if(/[0-9]+/.test(parseInt(start)) &amp;amp;&amp;amp; !/\s/.test(start)) {
         NumericStrategy(totalframes,frame,prop,props,easing);
     } else {
         ColorStrategy(totalframes,frame,prop,props,easing);
     }
}
&lt;/pre&gt;
This is one way of implementing the factory pattern in a procedural way, the basic and easy way.&lt;br /&gt;
Now, we will have to change the strategyFactory instead of the animate function, which is a little improvement but can we make things easier?&lt;br /&gt;
Of course we can!&lt;br /&gt;
Increasing the number of if... else statements, turning them into a switch statement to make it a little bit more readable won't change the fact that you will have to change the function everytime a new property you didn't think of appears.&lt;br /&gt;
If someone wants to add a new property, he/she will have to create a function and then go into the strategyFactory so that it can handle the new feature.&lt;br /&gt;
In short, nobody will try to extend your function!!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
What will be a factory without a chart?&lt;/h3&gt;
&lt;br /&gt;
Every factories follow a chart : i need to have a tree with this property of this weight and length in order to create that desk. I need to use this particular stone in order to create a ring...&lt;br /&gt;
Here, our factory just required us to pass the proper arguments to the function to do its job and choose the right strategy&lt;br /&gt;
We are going to add a new chart!&lt;br /&gt;
The strategies should be named with the name of the css property they cover, changed in camelCase with the first letter in uppercase!&lt;br /&gt;
What does it mean?&lt;br /&gt;
if you want to implement the background-color css property, your function shall be called BackgroundColor, if you want to create a function that handles the margin property, it has to be called Margin...&lt;br /&gt;
By creating a naming convention and thus extending our chart, we will be able to have an intelligent factory able to call the required function without endless if... else statements!!&lt;br /&gt;
Let's see the function with the new chart:&lt;br /&gt;
&lt;pre&gt;function strategyFactory(totalframes,frame,prop,props,easing) {
     var start=props[prop].start;
     if(/[0-9]+/.test(parseInt(start)) &amp;amp;&amp;amp; !/\s/.test(start)) {
         NumericStrategy(totalframes,frame,prop,props,easing);
         return true;
     }
     strategy=camelize(firstToUpperCase(prop));
     if(window[strategy]) { 
        window[strategy](totalframes,frame,prop,props,easing);
        return true;
     }
     return false;
}
function firstToUpperCase(val){
     return val.replace(/^([a-z])/,function(m,l) { return l.toUpperCase();})
}
&lt;/pre&gt;
???&lt;br /&gt;
You said there won't be any if else statements !!&lt;br /&gt;
No, in fact we are going to keep one and only one if statement in order to make things easier to develop!
Let's see what's going on so that you understand why we keep this if:&lt;br /&gt;
The first part of the function is trying to determine if we are dealing with a unique number.&lt;br /&gt;
As you know, each css property should have a function that handles the calculation strategy but simple numerical css properties are numerous: top, left, width, height, opacity, border-radius,margin-top,margin-left,padding-top...&lt;br /&gt;
If we follow our new chart, we will have to create a function for each of them:&lt;br /&gt;
&lt;pre&gt;function Top(totalframes,frame,prop,props,easing) {
       NumericStrategy(totalframes,frame,prop,props,easing);
}
function Left(totalframes,frame,prop,props,easing) {
       NumericStrategy(totalframes,frame,prop,props,easing);
}
function Width(totalframes,frame,prop,props,easing) {
       NumericStrategy(totalframes,frame,prop,props,easing);
}
function Height(totalframes,frame,prop,props,easing) {
       NumericStrategy(totalframes,frame,prop,props,easing);
}
function MarginTop(totalframes,frame,prop,props,easing) {
       NumericStrategy(totalframes,frame,prop,props,easing);
}
&lt;/pre&gt;
I am not going to write them all but as you can see this a fair amount of wrapper functions to write. We can think of a unique numerical value as being the generality and everything else as being the exception, therefore this is what we do!&lt;br /&gt;
If we don't have a number, we change the css property in camelCase and then change the first letter into uppercase.&lt;br /&gt;
we need to call the function on the window object,that is the global space, holding all the functions and variables.&lt;br /&gt;
We then see if the function exists and apply it.&lt;br /&gt;
If the function doesn't exist we just retun false.&lt;br /&gt;
Now, we will be able to add new css properties without touching the factory and the core function!&lt;br /&gt;
It will be very easy for users to contribute to the function by just creating a function that has a name following the chart !&lt;br /&gt;
Now, we need to create the functions we are aware of that deal with one color formatted in hexadecimal:
&lt;br /&gt;
&lt;pre&gt;function Color(totalframes,frame,prop,props,easing) {
   var b = hexStr2rgbArray(props[prop].start);
   var e = hexStr2rgbArray(props[prop].end);
   var rgb=[];
   for(j=0;j&amp;lt;3;j++) {
        rgb.push(parseInt(easing(frame, b[j], e[j]-b[j], totalframes)));
   }
   setStyle(elm,prop,'rgb('+rgb.join(',')+')');
}
function backgroundColor(totalframes,frame,prop,props,easing) {
      Color(totalframes,frame,prop,props,easing);
}
&lt;/pre&gt;
The little drawback is that we need to create a wrapper around the Color function for the background-color but we will be able to use the Color function in many other cases, we will see !
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
We have seen in this entry how we could create an expandable animation function that delegates strategies to outside functions.&lt;br /&gt;
We have seen how to use the strategy pattern associated with the factory pattern to get the most of it in a procedural way!&lt;br /&gt;
- The main function, animate is now smaller, which will create less overhead when using it&lt;br /&gt;
- The main function doesn't need to be aware of the css properties that exists as it has been abstracted in sub functions.&lt;br /&gt;
- Our animate function, abstracted of css properties, can now be extended as will by other users by following a simple naming convention.
- we can load only the strategies we need for an animation if we want! (if you don't animate colors, don't import the color strategy!)
- the animate function can be extended with more elements like events without fearing to create a monster function!&lt;br /&gt;
We have seen how we can use the concepts behind design patterns generally used for object oriented programming in a procedural manner but we have several problems with the procedural approach:&lt;br /&gt;
- All our functions is in the global name space, the window name space.Therefore, conflicts with other libraries that could use the same naming conventions could appear and create hard to track bugs.&lt;br /&gt;
- we can't share a state between functions easily

We will see in the next entry how we can simulate namespaces in javascript thru objects and how we can extend the number of css properties our function can handle with Margin and Padding functions !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-5138651440683806533?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/5138651440683806533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=5138651440683806533' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5138651440683806533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/5138651440683806533'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/11/javascript-animation-strategy-and.html' title='Javascript Animation : Strategy and Factory Pattern at the rescue (8)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-4366736045504741332</id><published>2007-11-01T08:18:00.000+09:00</published><updated>2007-11-02T12:21:57.488+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>E4CSS: Turn your stylesheets into ESON Objects (1)</title><content type='html'>We will see in this entry how we can turn our stylesheets into ESON objects with Javascript.&lt;br /&gt;
E4CSS will allow us to manipulate the data thru Javascript and Flash, bringing us even more animation/interactivity capacities!&lt;br /&gt;
&lt;br /&gt;


&lt;h3&gt;Final API example&lt;/h3&gt;
&lt;br /&gt;

Before we deal with cross-browsers fixes and the ESONification, we will see the end user program:&lt;br /&gt;
&lt;pre&gt;
//get the ESON object by specifying the stylesheet

var css = new E4CSS('layout.css'); //or 0,1

alert(css['#errors .warnings p']["fontSize"]); //give you back 12px

//modify the stylesheet
css.insertRule({"#debugConsole":{'background-color':'blue','font-size':'15px'}});

//delete a rule
css.deleteRule("#debugConsole");

&lt;/pre&gt;

As you can see this is really straightforward!&lt;br /&gt;
We will just see how to create the ESON in this entry as we will need to deal with cross-browsers fix!(although, we won't see all of them)&lt;br /&gt;
In order to understand what is the recommandation, we will see the standard and browser implementation way of doing it.&lt;br /&gt;
&lt;br /&gt;

&lt;h3&gt;Standard and browser implementation&lt;/h3&gt;
&lt;br /&gt;
First we will see how standards define the API to access stylesheets.&lt;br /&gt;
Basically Firefox tries to stick to these standards so the code below will work in this browser:&lt;br /&gt;

&lt;pre&gt;
//you cannot directly specify the stylesheet name, 
//you need to call it by its position in the xhtml file...
var sheets=document.styleSheets;
//get the style sheet object for the first stylesheet
var sheet=sheets[0];

// get the style sheet contents object 
var sheetRules=sheet.cssRules; 

//you cannot directly specify the selector
//you need to call it by its position in the stylesheet!

alert(sheetRules[12].selectorText); // is the selector you work on
alert(sheetRules[12].style['font-size']); // alert 12px;

//insert a new rule in the style sheet
sheet.insertRule("#debugConsole : { background-color:blue; font-size:15px }",sheetRules.length);

//delete a rule by its position in the stylesheet...
sheet.deleteRule(12);
&lt;/pre&gt;

As you can see this is far to be the easiest way of dealing with stylesheet contents as most of the time you need to refer to element positions : the style sheet position, the selector position...&lt;br /&gt;
I don't know for you but I can remember the name of the selectors but I hardly ever know their position in the stylesheet! Even more, I can remember the name of the stylesheet but can hardly remember the order in which I have inserted them in the xhtml document (well, it depends on the number of stylesheets you use)&lt;br /&gt;
&lt;br /&gt;
This was the standard way but as usual, IE has its own naming conventions:&lt;br /&gt;

-cssRules becomes rules&lt;br /&gt;
-insertRule becomes addRule with different parameters&lt;br /&gt;
-deleteRule becomes removeRule&lt;br /&gt;
&lt;br /&gt;
They are many other differences regardings the methods IE offers to deal with the style sheets.We will not see them all though as not all of them we'll be helpful for our main purpose : Creating an Object from the style sheet to manipulate it thru Javascript or Actionscript.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Getting the hands dirty&lt;/h3&gt;
&lt;br /&gt;
Even if we haven't seen all the differences you can see that not everything is gonna be easy.&lt;br /&gt;
First let's see how to create a function that will allow us to retrieve a style sheet thru its position number or its name:&lt;br /&gt;
&lt;pre&gt;
var getCssRules = function(val) {
     var sheets=(document.styleSheets) ? document.styleSheets : undefined;
     if(typeof val=='number') {
         if(val &gt; sheets.length) return;
         return sheets[val]['cssRules' || 'rules'] || undefined;
     }
     var regex=new RegExp(val);
     for(i in sheets) {
        if(regex.test(sheets[i].href)) {
            return sheets[i]['cssRules' || 'rules'] || undefined;
        }
        return undefined;
    }
}
&lt;/pre&gt;
The code isn't too hard as we are just dealing with cross-browsers fixes:&lt;br /&gt;
First we check to see if we can get the style sheets objects, and store it in a variable.&lt;br /&gt;
if the parameter is a number, we check that the number isn't greater than the number of style sheets. &lt;br /&gt;
If it's ok,we try the IE or standard methods and as a last resort we return undefined.&lt;br /&gt;
If this is not a number, we are dealing with a string.&lt;br /&gt;
So we just loop thru each style sheets objects and test the href property to see if we find it and if not return undefined.&lt;br /&gt;
At that point, we just have an improved cross-browser document.styleSheets function that allows us to specify the style sheet number or file name.&lt;br /&gt;
Now that we have the object we will need to loop thru it in order to create our own ESON version of the object.&lt;br /&gt;
We will use the document.styleSheets.cssRules advantages : &lt;br /&gt;
- no comments, &lt;br /&gt;
- a space between the attribute and its value inserted for us&lt;br /&gt;
But we also have huge disadvantages:&lt;br /&gt;
- IE put in Uppercase all the xhtml tags in the selector !&lt;br /&gt;
- IE put all the attributes in uppercase!&lt;br /&gt;
- Firefox changes all the colors in the rgb notations while IE keeps what comes in&lt;br /&gt;
- Firebox, IE and Safari don't send back the same attributes when an attribute can be divided in several sub elements ie border:'1px solid red' has borderTopWidth,borderTopStyle,borderTopColor, borderLeftWidth,borderLeftStyle...)
IE sends back two attributes for the above example, Firefox sends back 4 attributes and Safari is the winner with 12!&lt;br /&gt;
- IE keeps multiple selectors separted by ',' into one selector where others separate them so h1,h2 {} will be h1 {} and h2 {}

let's see the objects we'd like to get back:&lt;br /&gt;
&lt;pre&gt;
{
 '#navigation' :{
        'backgroundColor':'#000000',
        'height':'20px',
        'width':'600px'
 },
 '#header a:hover' : {
        'color':'#FF0000',
        'fontSize':'12px'
 }
}
&lt;/pre&gt;
Let's see the code:&lt;br /&gt;
&lt;pre&gt;
var parse = function(cssFileName) {

    //we get the object in a cross browser way
    var rules=getCssRules(cssFileName);
    if(!rules) return;

    //we instantiate the object that will keep our properties
    var objs=new Object();//or just function () {}

    //we loop thru each selectors in the stylesheet
    for(var i=0;i &lt; rules.length;i++ ) {

        //we get the name of the selector
 var selector=rules[i].selectorText;
 if(!selector) continue;

        // we split the attributes by their ';'
 var csss=rules[i].style.cssText.split(';');

        //we create an object that will store attributes:value pairs
 var props={};

        //we loop thru the array we created from the split
 for(var j=0;j&lt; csss.length;j++ ) {

            //we split each pairs by their ':'
     var s=csss[j].split(/:\s/);
     if(s[0].length==1 || !s[0] || !s[1]) continue;

            //we change everything in camelCase and lowercase
     var tmp=camelize(s[0].toLowerCase());
            //we trim some unwelcome spaces
     props[trim(tmp)]=s[1];
       }
       //we split selectors
       var selectors=selector.split(',') || [selector];
       //loop thru them and add the above attributes
       for(k=0;k &lt; selectors.length;k++ ) {
   if(objs[selectors[k]]) {
      for(var attr in props)
  objs[selectors[k].toLowerCase()][attr]=props[attr];
   }
   else objs[selectors[k].toLowerCase()]=props; 
       }
    }
    return objs;
}
&lt;/pre&gt;

They are some works that we still need to do to have the same objects across browsers.&lt;br /&gt;
&lt;br /&gt;
That's why standards are great:&lt;br /&gt;
They don't make you hack your hack !&lt;br /&gt;

&lt;br /&gt;
Here are the helpers camelize and trim:&lt;br /&gt;
&lt;pre&gt;
function camelize(val) {
   return val.replace(/-(.)/g, function(m, l){ return l.toUpperCase()});
}
function trim(val) {
   var val= val.replace(/^\s+/,'');
   return val.replace(/\s+$/,'');
}
&lt;/pre&gt;
As you see, we have been created all the functions in the global space, that is the window object.&lt;br /&gt;
In order to avoid conflicts with other libraries that we may use, we should put this in a namespace.&lt;br /&gt;
We will create a basic class that will allow us to create a namespace but also keep track of the style sheets loaded in the object&lt;br /&gt;
Here we go:&lt;br /&gt;
&lt;pre&gt;
function E4CSS(val) {
     return (this instanceof E4CSS) ? this.parse(val) : new E4CSS(val);
}
&lt;/pre&gt;
This is the constructor of the class.&lt;br /&gt;
if the function is called without the new keyword binding the this keyword to the E4CSS object we just instantiate the object for our user!&lt;br /&gt;
Therefore, we could call the constructor:&lt;br /&gt;
&lt;pre&gt;
var css= new E4CSS('layout.css');
//or
var css= E4CSS('layout.css');
&lt;/pre&gt;
Now we are just going to put the above two functions we have seen into the prototype of the class.&lt;br /&gt;
&lt;pre&gt;
E4CSS.prototype={

     styleSheet : 0,
     sheets     : (document.styleSheets) ? document.styleSheets : undefined,

     getCssRules : function(val) {

       if(val=='undefined') return this;
       if(this.sheets=='undefined')  return undefined;

       if(typeof val=='number') {
          this.styleSheet=val;
          if(val &gt; this.sheets.length) return;
          this.sheets[val]['cssRules' || 'rules'];
      }
     var regex=new RegExp(val);
     for(i in this.sheets) {
        if(regex.test(this.sheets[i].href)) {
          this.styleSheet=i;
          return this.sheets[i]['cssRules'||'rules'] || this;
       }
   }
 },

 parse : function(cssFileName) {

    var rules=this.getCssRules(cssFileName);
    if(!rules) return this;

    var objs=new Object();

    for(var i=0;i &lt; rules.length;i++) {

        var selector=rules[i].selectorText;
        if(!selector) continue;

        var csss=rules[i].style.cssText.split(';');
        var props={};
        for(var j=0;j &lt; csss.length;j++) {
    var s=csss[j].split(/:\s/);
    if(s[0].length==1 || !s[0] || !s[1]) continue;
    var tmp=camelize(s[0].toLowerCase());
    props[trim(tmp)]=s[1];
        }
        var selectors=selector.split(',') || [selector];
        for(k=0;k &lt; selectors.length;k++) {
    if(objs[selectors[k]]) {
        for(var attr in props)
   objs[selectors[k].toLowerCase()][attr]=props[attr];
    }
    else objs[selectors[k].toLowerCase()]=props;           }
   }
   for(var prop in this) objs[prop]=this[prop];
   return objs;
      }
}
&lt;/pre&gt;
We just take the functions and put them in the namespace of the E4CSS class.&lt;br /&gt;
we added a default value for the style sheet we will deal with.&lt;br /&gt;
Before returning the new object, we extend its possibilities with the one of the E4CSS.&lt;br /&gt;
Therefore, you will be able to call the parse function on the new object!&lt;br /&gt;
For now this is not very helpful but this will come in handy when we will see how to add insertRule and deleteRule on the object!&lt;br /&gt;
So for now, you just have a read object that allows you to do the following:&lt;br /&gt;
&lt;pre&gt;
var css=new E4CSS('layout.css');
alert(css["#navigation"]["backgroundColor"]);
css.parse(3);
alert(css.toSource()); // firefox function to see the object structure.
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;br /&gt;
We have seen how we could change a css style sheet into ESON allowing us for now to read the property in both actionscript or javascript!&lt;br /&gt;
We choose to camelize the css attributes as this is the way both javascript and actionscript access them.&lt;br /&gt;
We didn't do anything for the color and for the multipart attributes for now.&lt;br /&gt;
Safari sends back 12 properties when Firefox sends back 4 and IE sends back 2!!&lt;br /&gt;
If we think of the use we could have from within a javascript or flash application, the more the better.&lt;br /&gt;
We will see how to insert new rules or delete rules in a cross-browsers way from within our E4CSS objects in the next entry.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-4366736045504741332?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/4366736045504741332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=4366736045504741332' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4366736045504741332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4366736045504741332'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/11/e4css-turn-your-stylesheets-into-eson.html' title='E4CSS: Turn your stylesheets into ESON Objects (1)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-2127244469076953434</id><published>2007-10-28T00:48:00.000+09:00</published><updated>2007-10-30T08:04:37.610+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Flash &amp; Javascript :How to communicate with Objects (or why JSON should be renamed ESON)</title><content type='html'>Flash allows to create rich web interface : very cool effects, 3D animations,data-driven websites. Actionscript,language based on ECMAScript, offers a lot of power to Flash applications.&lt;br /&gt;
Here, we will be using Actionscript 3 to see how we can communicate with Javascript objects thru the literal notation and DOM !&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Creating a pseudo-div in Flash&lt;/h3&gt;
&lt;br /&gt;
I am sorry as I cannot put any flash animations here but first, we will see how to create a textField in actionScript 3. Even if it is very different from the so-called div html elements, I will call this textField a div.
Here we go with a function that will create a basic textField:&lt;br /&gt;
&lt;pre&gt;
function createDiv(y:Number,x:Number,height:Number,width:Number):TextField {
     var div:TextField=new TextField();
     div.y=y;
     div.x=x;
     div.height=height;
     div.width=width;
     div.background=true;
     div.backgroundColor='0xFF0000';
     addChild(div);
     return div;
}
&lt;/pre&gt;
As you can see this function takes several parameters and create a textField that we place on the scene thru the addCild function.&lt;br /&gt;
This is how we will use it :&lt;br /&gt;
&lt;pre&gt;
var div=createDiv(50,50,50,50);
&lt;/pre&gt;
For those of you that knows javascript this must be quite familiar.&lt;br /&gt;
Basically we just create a square that is at the top 50 and the left 50 from the movie clip with a height and width of 50.&lt;br /&gt;
We also add a default color to see it!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Talking to Javascript from Flash&lt;/h3&gt;&lt;br /&gt;
Communicating with javascript from Flash is very easy in actionscript 3!&lt;br /&gt;
You first need to import the class that contains the function that will do so:&lt;br /&gt;
&lt;pre&gt;
import flash.external.ExternalInterface;
&lt;/pre&gt;
This will load the API necessary to communicate with external entities.&lt;br /&gt;
Importing this give us access to the following function:&lt;br /&gt;
&lt;pre&gt;
ExternalInterface.addCallback(javascriptFunctionName, actionscriptFunctionName);
&lt;/pre&gt;
This addCallback method takes 2 parameters:&lt;br /&gt;
The name of the function that javascript will use to call flash&lt;br /&gt;
the name of the actionscript function that will be used.&lt;br /&gt;
Most of the time the 2 parameters will have the same name!&lt;br /&gt;
Let's see an example:&lt;br /&gt;
(just place the code in the action panel of an empty flash movie)
&lt;pre&gt;
import flash.external.ExternalInterface;

ExternalInterface.addCallback("calledByJS", calledByJS);

function calledByJS(str:String):void {
 var div=createDiv(50,50,50,50);
 div.htmlText=str;
}
&lt;/pre&gt;
So when javascript will use the calledByJS function on a flash movie passing a string, it will call the actionscript function with the same name and put the text into the textField.&lt;br /&gt;
But let's see how we can call this function from javascript!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Calling Actionscript functions from Javascript&lt;/h3&gt;&lt;br /&gt;
The first thing javascript needs to do is to use the function on the right movie clip!&lt;br /&gt;
You may have several clips on your page but perhaps only one of them will have the calledByJS function.&lt;br /&gt;
So we need to create a javascript function that will find the movie clip object in the page:&lt;br /&gt;
&lt;pre&gt;
function getFlashMovie(objectId,embedId) {
  return (window[objectId]) ? window[objectId] 
              : document[embedId];
}
&lt;/pre&gt;
Unfortunately the code that you may find in the actionscript documentation will not work under safari mac. This version should work in IE,FireFox and Safari Windows/Mac.&lt;br /&gt;
You should pass the id of the object tag and the id of the embed tag.&lt;br /&gt;
Let's see the code to add a flash movie in an html page so that you may understand:&lt;br /&gt;
&lt;pre&gt;

&amp;lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" 
width="250px" height="250px" id="swf2"&amp;gt;
&amp;lt;param name="movie" value="FlashWithESON.swf"&amp;gt;
&amp;lt;embed src="FlashWithESON.swf" width="250px" height="250px" id="swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"&amp;gt;
&amp;lt;/object&amp;gt;

&lt;/pre&gt;
The important thing to notice is the id set on the object tag and the id set on the embed tag.&lt;br /&gt;
you have swf and swf2 and that is what we pass in the function getFlashMovie:&lt;br /&gt;
&lt;pre&gt;
var movie=getFlashMovie('swf2','swf');
&lt;/pre&gt;
And now, we can call the function calledByJS on the movie object!&lt;br /&gt;
&lt;pre&gt;
movie.calledByJS('Hi from Javascript');
&lt;/pre&gt;
This code shall display the text into the textField that we have set thru actionscript in our flash movie!&lt;br /&gt;&lt;br /&gt;

&lt;h3&gt;Interacting with several functions with one function&lt;/h3&gt;&lt;br /&gt;

We have seen that we need to specify the function that javascript will be able to call and that's fine if you only have one or two functions.&lt;br /&gt;
But this might be cumbersome to specify the function each time we need too:&lt;br /&gt;
&lt;pre&gt;
import flash.external.ExternalInterface;

ExternalInterface.addCallback("calledByJS", calledByJS);

function calledByJS(str:String):void {
 var div=createDiv(50,50,50,50);
 div.htmlText=str;
}
ExternalInterface.addCallback("calledByJS2", calledByJS2);

function calledByJS2(str:String):void {
 var div=createDiv(50,50,50,50);
 div.htmlText=str;
}
ExternalInterface.addCallback("calledByJS3", calledByJS3);

function calledByJS3(str:String):void {
 var div=createDiv(50,50,50,50);
 div.htmlText=str;
}
&lt;/pre&gt;
You see that it is rather painfull to have to write this addCallback all the time.&lt;br /&gt;
Couldn't it be nice if we could build the function on the fly ? Creating one function that will be in charge of calling the final function ? &lt;br /&gt;
A function that will work like a factory where you put it in something raw (like a string!) and get something finished (like a function!)&lt;br /&gt;
This is what we are going to do:&lt;br /&gt;
&lt;pre&gt;
import flash.external.ExternalInterface;

ExternalInterface.addCallback("apply", functionFactory);

function functionFactory(func:String,obj:String):void {
 this[func](obj);
}
&lt;/pre&gt;
Alright, here you see that the function that javascript will call is different from the one actionscript will really call.&lt;br /&gt;
Why ?&lt;br /&gt;
Well, if you put your self in a javascript programmer, this may be weird to write 'calledByJS' all the time!! After he/she is using javascript, no need to remember this every time!&lt;br /&gt;
We have seen that javascript will need to find the movie clip and call the function on the movie object so for the javascript programmer, this may make more sense to write this:&lt;br /&gt;
&lt;pre&gt;
var movie=getFlashMovie('swf2','swf');
movie.apply('calledByJS','Hi from Javascript');
&lt;/pre&gt;
This could be 'call' or 'execute' or something like that!&lt;br /&gt;
On the other hand, this will not make that much sense on an actionscript programmer point of view!&lt;br /&gt;
That's why we gave an other name to the function that will describe what will be the end result:&lt;br /&gt;
&lt;pre&gt;
ExternalInterface.addCallback("apply", functionFactory);

function functionFactory(func:String,obj:String):void {
        this[func](obj);
}
&lt;/pre&gt;
So the functionFactory says it all : this is a function that is in charge of building, creating,calling other function.&lt;br /&gt;
In actionscript, we cannot just 'eval' the string to turn it into a function so we call the function as a method of the this object (the scene)
and then put the parameter into it!&lt;br /&gt;
We are done!&lt;br /&gt;
We have a factory that will launch any functions called by javascript without needing us to call ExternalInterface.addCallback every time!&lt;br /&gt;
But I know what you are thinking :&lt;br /&gt;
My function is not going to need only one parameter everytime so I will have to call the ExternalInterface anyway...&lt;br /&gt;
That's where objects comes in!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Passing arguments thru ESON&lt;/h3&gt;
ESON is just a name that I give to JSON that stands for JavaScript Object Notation.&lt;br /&gt;
In fact, we can use this notation and send it to actionscript from javascript and we can send actionscript notation to send it to javascript too!&lt;br /&gt;
So this is not JSON but ESON, ECMAScript Object Notation.&lt;br /&gt;
So now, we will change the functionFactory so that it accepts an object, it is easy:&lt;br /&gt;
&lt;pre&gt;
ExternalInterface.addCallback("apply", functionFactory);

function functionFactory(func:String,obj:Object):void {
 this[func](obj);
}
&lt;/pre&gt;
We have just change the type of obj from String to Object!&lt;br /&gt;
Let's say that you have build a nice actionscript API that gives hook to javascript to modify the look and feel of the application and the text too so you have several functions dedicated to communicating with javascript, one of them being:&lt;br /&gt;
&lt;pre&gt;
function modifyDiv(obj:Object):void {
 
 var style=obj.style;
 div.y=parseInt(style['top']);
 div.x=parseInt(style['left']);
 div.width=parseInt(style['width');
 div.height=parseInt(style['height']);
 div.backgroundColor=style['backgroundColor'].replace(/#/,'0x');
 div.textColor=style['color'].replace(/#/,'0x');
 div.htmlText=obj['text'];
}
&lt;/pre&gt;
The modifyDiv will be called by javascript to change the appearance of the textField thru a javascript object!&lt;br /&gt;
Let's see the javascript side coding:&lt;br /&gt;
&lt;pre&gt;
function getFlashMovie(objectId,embedId) {
  return (window[objectId]) ? window[objectId] 
              : document[embedId];
}

//wrapper that memoize the result
// i have put an alert so that you can see that
//next call to the function will return the second alert
function callFlash(func,obj) {
    alert('first call');
    var movie=getFlashMovie('swf','swf2');
    this.callFlash=function() { alert('other calls'); movie.apply(func,obj); };
    return movie.apply(func,obj); 
} 

function changeDiv() {
 var elm={style:{
                      top:'20px',
                      left:'60px',
                      width:'200px',
                      height:'80px',
                      'background-color':'#OOOOFF',
                      color:'#FF0000'
                 },
                 text:'hi from javascript! lets change your look !'
        };
   callFlash('modifyDiv',elm);
}
&lt;/pre&gt;
so as you can see we create a literal object in javascript that define the new style of the textField and the new text. Then we pass the object to the modifyDiv function define in actionscript!&lt;br /&gt;
Let's look back to the modifyDiv actionscript function:&lt;br /&gt;
&lt;pre&gt;
function modifyDiv(obj:Object):void {
 
 var style=obj.style;
 div.y=parseInt(style['top']);
 div.x=parseInt(style['left']);
 div.width=parseInt(style['width');
 div.height=parseInt(style['height']);
 div.backgroundColor=style['backgroundColor'].replace(/#/,'0x');
 div.textColor=style['color'].replace(/#/,'0x');
 div.htmlText=obj['text'];
}
&lt;/pre&gt;
This is quite an ugly function I know but for our purpose, it will be fine!
As you can see it accepts an object and then apply each element to the textField.&lt;br /&gt;
But why I didn't send an integer directly instead of sending the value with pixels?&lt;br /&gt;
Well, I guess that you have found that in fact I am simulating sending css properties from javascript to flash!&lt;br /&gt;
Here we have hardcoded the setting but perhaps we could create a function that will loop thru the javascript object and set the value automaticly!&lt;br /&gt;
So instead of creating a javascript object and putting the text into javascript, couldn't we do something else?&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Passing DOM objects to Actionscript&lt;/h3&gt;
&lt;br /&gt;
Well, I have written this ugly actionscript function only for that purpose!&lt;br /&gt;
Let's see the javascript side code as the actionscript doesn't need any change:&lt;br /&gt;
&lt;pre&gt;
function wrapper() {
   var elm=document.getElementById('text');
   callFlash('modifyDiv',{style:elm.style,text:elm.innerHTML});
}
&lt;/pre&gt;
As it is a very basic example, here is the xhtml that goes with it (the style is defined in the xhtml which is not a good habit but for now, forgive me!):&lt;br /&gt;
&lt;pre&gt;
&amp;lt;div id="text" style="top:20px;left:60px;width:200px;height:80px;background-color:#OOOOFF;color:#FF0000"&amp;gt;
&amp;lt;p&gt;let's try to send some text to flash!&amp;lt;p&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
As you can see, the javascript is fairly simple!&lt;br /&gt;
And now, we can manipulate the look and feel and contents of a Flash animation with properties that relate to xhtml and css!&lt;br /&gt;
You could build an application that will define some property of the look in a css file, the contents in a xhtml document and you will have a full SE friendly application!!&lt;br /&gt;
The css and xhtml will be used when javascript is off otherwise, the cool flash animation will do its wow job!&lt;br /&gt;
&lt;br /&gt;

&lt;h3&gt;Putting the pieces together&lt;/h3&gt;
&lt;br /&gt;
First let's put the actionscript code that you can put on the action panel of an emply fla:&lt;br /&gt;
&lt;pre&gt;
 //code to let javascript call actionscript functions

 import flash.external.ExternalInterface;

 ExternalInterface.addCallback("apply", functionFactory);

 function functionFactory(func:String,obj:String):void {
        this[func](obj);
 }

 //code related to our API(dirty example)

 var div=createDiv(50,50,50,50);
 function modifyDiv(obj:Object):void {
 
   var style=obj.style;
   div.y=parseInt(style['top']);
   div.x=parseInt(style['left']);
   div.width=parseInt(style['width']);
   div.height=parseInt(style['height']);
   div.backgroundColor=style['backgroundColor'].replace(/#/,'0x');
   div.textColor=style['color'].replace(/#/,'0x');
   div.htmlText=obj['text'];
 }
 function createDiv(y:Number,x:Number,height:Number,width:Number):TextField {
     var div:TextField=new TextField();
     div.y=y;
     div.x=x;
     div.height=height;
     div.width=width;
     div.background=true;
     div.backgroundColor='0xFF0000';
     addChild(div);
     return div;
 }
&lt;/pre&gt;
&lt;br /&gt;
Now, let's see the javascript code:&lt;br /&gt;
&lt;pre&gt;
//find the movie clip we need
function getFlashMovie(objectId,embedId) {
  return (window[objectId]) ? window[objectId] 
              : document[embedId];
}
//wrapp into one function : callFlash
function callFlash(func,obj) {
    var movie=getFlashMovie('swf','swf2');
    this.callFlash=function() { movie.apply(func,obj); };
    return movie.apply(func,obj); 
} 

//execute the modification to actionscript textField here:
function changeDiv() {
   var elm=document.getElementById('text');
   callFlash('modifyDiv',{style:elm.style,text:elm.innerHTML});
}

&lt;/pre&gt;
&lt;br /&gt;
And in the end, the html you can find in the body:&lt;br /&gt;

&lt;pre&gt;
&amp;lt;div id="text" style="top:20px;left:60px;width:200px;height:80px;background-color:#OOOOFF;color:#FF0000"&amp;gt;
&amp;lt;p&gt;let's try to send some text to flash!&amp;lt;p&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" 
width="250px" height="250px" id="swf2"&amp;gt;
&amp;lt;param name="movie" value="FlashWithESON.swf"&amp;gt;
&amp;lt;embed src="FlashWithESON.swf" width="250px" height="250px" id="swf" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"&amp;gt;
&amp;lt;/object&amp;gt;
&lt;/pre&gt;
In fact we should clean this code and load the flash animation thru swfObject in order to allow the switch between html and flash when necessary.&lt;br /&gt;
&lt;br /&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;
As you can see it is very easy to communicate with javascript thru ESON.&lt;br /&gt;
You can now create applications that gives hook to javascript with only one actionscript function, acting like a Factory, that will call the function and pass the object to it.&lt;br /&gt;
Using objects allow us to pass as many parameters as we want without having to redefine our main function, therefore allowing to ease maintainability of your code!&lt;br /&gt;
We have seen a cross-browser way to find a movie clip with javascript and how to call actionscript functions from their!
There is no real standard about the name of the function javascript should use as this is pretty new in the ESON world (perhaps other bodies are doing this and if so they should give us their tips!) but it could be nice to specify a standard so that javascript could interact directly with Flash thru one function that will take the actionscript function name as a first parameter and a literal object as a second!&lt;br /&gt;
We didn't see how to call javascript from actionscript but you will see that there is a lot of good surprises awaiting us!&lt;br /&gt;
We might see in an other entry how to interact with css thru actionscript (not with the getStyle actionscript function...) so that you can offer your users to edit in real time the css thru tools like firebug and see the change in flash directly!&lt;br /&gt;

I hope you enjoy this article! &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-2127244469076953434?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/2127244469076953434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=2127244469076953434' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/2127244469076953434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/2127244469076953434'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/flash-javascript-how-to-communicate.html' title='Flash &amp; Javascript :How to communicate with Objects (or why JSON should be renamed ESON)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-941632564649972991</id><published>2007-10-21T13:54:00.001+09:00</published><updated>2010-09-28T11:57:17.443+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : Curving the path (7)</title><content type='html'>We've seen that we could define the core concept of an animation thru a linear equation that took basic elements like time, begin, end, change.&lt;br /&gt;
We have changed the equation to create some easing effects, making the animation a lot more interesting.&lt;br /&gt;
But there is one thing that we cannot do : describe a curve when going from point A to point B.&lt;br /&gt;
Let's see how to implement a curved path!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Curve by example&lt;/h3&gt;
&lt;br /&gt;
I guess it's easier to understand what we are talking about if we have a grasp of the final result.&lt;br /&gt;
First, this is what we are able to do know:&lt;br /&gt;
We can go from y0,x0 to y1,x1 or from top0, left0 to top1, left1.&lt;br /&gt;
Even if we use an easing effect, going from point A to B will describe a straight line:&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function animate(elm,props, duration, fps,easing) {

      duration = (duration) ? parseFloat(duration) : 1000;
      fps      = (fps)      ? parseFloat(fps)      : 20;
      easing   = (easing)   ? easing               : linearEase;

      var interval    = Math.ceil(1000/fps);
      var totalframes = Math.ceil(duration/interval);

      for(i=1;i &lt;= totalframes;i++) {
              (function() {
             var frame=i;
                   generalProperty=function() {
     for(var prop in props){
                           if(!/olor/.test(prop)) {
                                var begin = props[prop].start*100;
                                var end   = props[prop].end*100;
         var bezier = props[prop].bezier*100;
         var actualDisplacement=easing(frame, begin, end-begin, totalframes);
         if(bezier) var actualDisplacement=linearEase(frame, actualDisplacement, end-actualDisplacement, totalframes,bezier);
               setStyle(elm,prop,actualDisplacement/100);

         } else {
                                var b = hexStr2rgbArray(props[prop].start);
                                var e = hexStr2rgbArray(props[prop].end);
              var rgb=[];
                                for(j=0;j&lt;3;j++) rgb.push(parseInt(easing(frame, b[j], e[j]-b[j], totalframes)));
                                setStyle(elm,prop,'rgb('+rgb.join(',')+')');  
        }
     }
                   }
                  timer = setTimeout(generalProperty,interval*frame);
             })();   
     }
}
function d2h(dec) { 
  return dec.toString(16);
}
function h2d(hex) { 
   return parseInt(hex,16);
}
function rgb2h(r,g,b) { 
    return [d2h(r),d2h(g),d2h(b)];
}
function h2rgb(h,e,x) {  
     return [h2d(h),h2d(e),h2d(x)];
}
function cssColor2rgb(color) {
     if(color.indexOf('rgb')&lt;=-1) {
  return hexStr2rgbArray(color);
     }
 return rgbStr2rgbArray(color);
}
function hexStr2rgbArray(color) {
 return h2rgb(color.substring(1,3),color.substring(3,5),color.substring(5,7));
}
function rgbStr2rgbArray(color) {
 return color.substring(4,color.length-1).split(',');
}
function camelize(val) {
         return val.replace(/-(.)/g, function(m, l){return l.toUpperCase()});
}
function setOpacity(elm,val) {
          elm.style.zoom = 1;
          elm.style.filter = "alpha(opacity=" + parseFloat(val*100) + ")";
          elm.style.opacity  = parseFloat(val); 
    return elm;
}

function setStyle(elm,prop,val) {
        if(prop=='opacity') return setOpacity(elm,parseFloat(val));
  if(prop=='float')   prop = (window.attachEvent) ? 'styleFloat' : 'cssFloat';
  prop = camelize(prop);
        unit=(prop=='zIndex'||prop=='zoom') ? '':'px';
  elm.style[prop] = (typeof val=='string') ? val : val+unit;
        return elm;
}

//backAndForth
function linearEase(frame,begin,change,totalframes,bezier) {
 //linear bezier :
      //return begin+((begin+change)-begin)*(frame/totalframes);

 var t=frame/totalframes;
       var end=begin+change;
       var p=begin;
 bezier=bezier || begin;
 return (1-t)*(1-t)*begin + 2*t*(1-t)*bezier + t*t*end;

 //return (1-t)*(1-t)*begin + 2*t*(1-t)*(end+change) + t*t*p;
 return easeOutBounce(frame,begin,y-begin,totalframes);
}
easeOutBounce = function (t, b, c, d) {
 if ((t/=d) &lt; (1/2.75)) { return c*(7.5625*t*t) + b;} 
        else if (t &lt; (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;} 
        else if (t &lt; (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;}
        else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; }
};
easeInOutSine = function (t, b, c, d) {
 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
};
var easeInCirc = function (t, b, c, d) {
 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
};

function goUp() {
 elm=document.getElementById('goup');
 var ops1={
                 backgroundColor:{start:'#000000',end:'#FF0000'},
           borderColor:{end:'#000000',start:'#FF0000'},
       top:{start:0,end:-100},
     left:{start:0,end:250}

       };
       animate(elm,ops1,1500,20,easeInCirc);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="goup" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; overflow: hidden; padding: 20px; position: relative; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;a href="javascript:goUp();"&gt;Go up&lt;/a&gt;&lt;br /&gt;
As you see, the easing effect is applied and the container goes from point A to B in a straight line.&lt;br /&gt;
Here is the code to create the effect:&lt;br /&gt;
&lt;pre&gt;function goUp() {
 elm=document.getElementById('goup');
 var ops1={
   backgroundColor:{start:'#000000',end:'#FF0000'},
   borderColor:{end:'#000000',start:'#FF0000'},
   top:{start:0,end:-100},
   left:{start:0,end:250}
 };
 animate(elm,ops1,1500,20,easeInCirc);
}
&lt;/pre&gt;
So we get the element,set the css properties we want to animate and then specify an animation of 1 second and a half with an easeInCirc effect.&lt;br /&gt;
&lt;br /&gt;
That's find, but it could be nice if we could control the path going from top.0,left.0 to top.-100,left.250.&lt;br /&gt;
We can set an in-between point that will 'attract' the animation.&lt;br /&gt;
we have 3 divs/square on the screen here:&lt;br /&gt;
The beginning square,&lt;br /&gt;
The attracting square,&lt;br /&gt;
The final square&lt;br /&gt;
You can set different value for the attracting point and see how the animation will behave:&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function goUpCurved() {
 elm=document.getElementById('curvedgoup');
 bTop=parseInt(document.getElementById('attractionTop').value);
 bLeft=parseInt(document.getElementById('attractionLeft').value);
 var bezier=document.getElementById('bezierpoint');
 setStyle(bezier,'top',bTop);
 setStyle(bezier,'left',bLeft);
 var ops1={
     backgroundColor:{start:'#000000',end:'#FF0000'},
     borderColor:{end:'#000000',start:'#FF0000'},
     top:{start:0,end:-100,bezier:bTop},
     left:{start:0,end:450,bezier:bLeft}
 };
 animate(elm,ops1,1500,20,easeInCirc);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div style="position: relative;"&gt;
&lt;div id="bezierpoint" style="border: 1px solid black; height: 10px; left: 300px; position: relative; top: 200px; width: 10px;"&gt;
&lt;/div&gt;
&lt;div id="start" style="border: 1px solid black; height: 10px; left: 0px; position: relative; top: 0px; width: 10px;"&gt;
&lt;/div&gt;
&lt;div id="end" style="border: 1px solid black; height: 10px; left: 450px; position: relative; top: -100px; width: 10px;"&gt;
&lt;/div&gt;
&lt;div id="curvedgoup" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; overflow: hidden; padding: 20px; position: relative; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;/div&gt;
&lt;form&gt;
Attraction Point:&lt;br /&gt;
top:&lt;input id="attractionTop" type="text" value="200" /&gt;
&lt;br /&gt;
left:&lt;input id="attractionLeft" type="text" value="300" /&gt;
&lt;/form&gt;
&lt;a href="javascript:goUpCurved();"&gt;animate with curve&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the animation will not go straight to the final point but will describe a curve according to the attracting point you have set!&lt;br /&gt;
We can now have little control on the path!&lt;br /&gt;
But let's see how it works.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Going back to the root : y=mx+b&lt;/h3&gt;
&lt;br /&gt;
As you certainly remember, we've seen that a linear displacement from one value to an other could be resumed to one equation:&lt;br /&gt;
value =(change/duration)*frame + start&lt;br /&gt;
or&lt;br /&gt;
y=mx+b&lt;br /&gt;
Where m is (change/duration) or c/d&lt;br /&gt;
&lt;br /&gt;
In fact, we can rewrite this linear equation so that it becomes the root of an other equation : the Bezier equation.&lt;br /&gt;
Let's rewrite it:&lt;br /&gt;
value = begin+(begin+change-begin)*(frame/totalframes)&lt;br /&gt;
If you look at the changement, you will see that we do we take a deturned path:&lt;br /&gt;
change = begin+change-begin&lt;br /&gt;
Which is not very helping in here!&lt;br /&gt;
In fact, this is the basic equation for a linear Bezier curve!&lt;br /&gt;
We can rewrite it like so:&lt;br /&gt;
value = begin+(end-begin)*(frame/totalframes)&lt;br /&gt;
or&lt;br /&gt;
var t=frame/totalframes&lt;br /&gt;
var b=begin&lt;br /&gt;
value=begin+(end-begin)*t&lt;br /&gt;
&lt;br /&gt;
In the Bezier curve, t must always be within 0 and 1 and this will always be true for how frame/totalframes.&lt;br /&gt;
The upper equation can be rewritten again:&lt;br /&gt;
value = (1-t)*begin + t*end&lt;br /&gt;
&lt;br /&gt;
This is an other way of creating a linear easing!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
From linear to Quadratic Bezier curve&lt;/h3&gt;
&lt;br /&gt;
As for now, we were just rewritting a linear equation to an other linear equation!&lt;br /&gt;
In fact, we can add an other point, like we did in the animation above and this will allow us to curve the path.&lt;br /&gt;
We will need p0,p1 and p2 where p1 is the deviator point:&lt;br /&gt;
value= (1-t)*(1-t)*p0 + 2*t*(1-t)*p1 + t*t*p2&lt;br /&gt;
In our case, with javascript variable name, this will give us:&lt;br /&gt;
&lt;pre&gt;var t=frame/totalframes;
value = (1-t)*(1-t)*begin + 2*t*(1-t)*deviator + t*t*end;
&lt;/pre&gt;
&lt;br /&gt;
Let's see the Bezier curve with a javascript implementation:&lt;br /&gt;
&lt;pre&gt;function linearBezier(frame,begin,end,totalframes) {
      var t=frame/totalframes;
      return (1-t)*begin + t*end;
}
function QuadBezier(frame,begin,end,deviator,totalframes) {
    var t=frame/totalframes;
    return (1-t)*(1-t)*begin + 2*t*(1-t)*deviator + t*t*end;
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Implementing the Bezier Curve&lt;/h3&gt;
&lt;br /&gt;
Now that we know how to curve the path thru a Bezier curve, we just need to see how we can implement this in our animate function.&lt;br /&gt;
First, we need to add a third point, a deviator point when setting the values.&lt;br /&gt;
A simple way of doing it,will be to set the deviators like so:&lt;br /&gt;
&lt;pre&gt; var ops1={
     backgroundColor:{start:'#000000',end:'#FF0000'},
     borderColor:{end:'#000000',start:'#FF0000'},
     top:{start:0,end:-100,bezier:-300},
     left:{start:0,end:450,bezier:-100}
 };
 animate(elm,ops1,1500,20,easeInCirc);
&lt;/pre&gt;
I have written it bezier because this is a common denomination that you can find in photoshop, illustrator, Flash...&lt;br /&gt;
The Bezier curve is used in many graphic applications so let's use a standard name!&lt;br /&gt;
Now, let's add this bezier into the animate function:&lt;br /&gt;
&lt;pre&gt;function animate(elm,props, duration, fps,easing) {

 duration = (duration) ? parseFloat(duration) : 1000;
 fps      = (fps)      ? parseFloat(fps)      : 20;
 easing   = (easing)   ? easing               : linearEase;

 var interval    = Math.ceil(1000/fps);
 var totalframes = Math.ceil(duration/interval);

 for(i=1;i &amp;lt;= totalframes;i++) {
   (function() {
      var frame=i;
      displacement=function() {
          for(var prop in props){
              if(!/olor/.test(prop)) {
                  var begin = props[prop].start*100;
                  var end   = props[prop].end*100;
    var bezier = props[prop].bezier*100;
    var actualDisplacement=
                      easing(frame, begin, end-begin, totalframes);
    if(bezier) 
                    actualDisplacement=
                    QuadBezier(frame,actualDisplacement,end,bezier,totalframes);
           setStyle(elm,prop,actualDisplacement/100;
               } else {
                    var b = hexStr2rgbArray(props[prop].start);
                    var e = hexStr2rgbArray(props[prop].end);
      var rgb=[];
                    for(j=0;j&amp;lt;3;j++) 
                    rgb.push(parseInt(easing(frame, b[j], e[j]-b[j], totalframes)));
                    setStyle(elm,prop,'rgb('+rgb.join(',')+')');  
        }
   }
       }
       timer = setTimeout(generalProperty,interval*frame);
   })();   
 }
}
&lt;/pre&gt;
So what do we do?&lt;br /&gt;
We first calculate the actual value of the property according to the easing type.&lt;br /&gt;
If we find that a bezier property exists,we use the value calculated by the easing type as the start for the bezier equation !&lt;br /&gt;
That's all!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
A new effect thru Bezier : backAndForth&lt;/h3&gt;
&lt;br /&gt;
In the above example, we need to supply a value for the bezier curve to happen, but we can always calculate the bezier point by manipulating the beging and end value!&lt;br /&gt;
Let' see the code:&lt;br /&gt;
&lt;pre&gt;function backAndForth(frame,begin,change,totalframes) {
 var t=frame/totalframes;
 var end=begin+change;
 return (1-t)*(1-t)*begin + 2*t*(1-t)*(end+change) + t*t*begin;
}
&lt;/pre&gt;
As we are using the backAndForth function as an easing effect, we are not getting the end directly but the change so we need to get back the change.&lt;br /&gt;
Here I've decided that the deviator will be the end+change and that the final point will be the beginning!&lt;br /&gt;
Let's see what we get with the following settings:&lt;br /&gt;
&lt;pre&gt; var ops1={
     backgroundColor:{start:'#000000',end:'#FF0000'},
     borderColor:{end:'#000000',start:'#FF0000'},
     top:{start:0,end:-100},
     left:{start:0,end:450},
     borderWidth:{start:5,end:1}
 };
&lt;/pre&gt;
&lt;script type="text/javascript"&gt;
function backAndForth(frame,begin,change,totalframes) {
 var t=frame/totalframes;
 var end=begin+change;
 return (1-t)*(1-t)*begin + 2*t*(1-t)*(end+change) + t*t*begin;
}
function goBAF() {
 var ops1={
     backgroundColor:{start:'#000000',end:'#FF0000'},
     borderColor:{end:'#000000',start:'#FF0000'},
     top:{start:0,end:-100},
     left:{start:0,end:450},
     borderWidth:{start:5,end:1}
 };
 animate(document.getElementById('baf'),ops1,1500,20,backAndForth);
}
function goBAF2() {
 var ops={
     backgroundColor:{start:'#000000',end:'#FF0000'},
     borderColor:{end:'#000000',start:'#FF0000'},
     top:{start:0,end:-100,bezier:-300},
     left:{start:0,end:450,bezier:200},
     borderWidth:{start:5,end:1,bezier:80}
 };
 animate(document.getElementById('baf2'),ops,1500,20,backAndForth);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="baf" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; overflow: hidden; padding: 20px; position: relative; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;a href="javascript:goBAF();"&gt;back and forth&lt;/a&gt;&lt;br /&gt;
As you can see, the animation goes to the end value and goes back to where it started!&lt;br /&gt;
This is not really an easing effect but more an effect in itself but this can be useful!&lt;br /&gt;
&lt;br /&gt;
What happens if we mix the backAndForth easing with some bezier points??&lt;br /&gt;
Until up to now, we've been applying the bezier points only on the top or left property but can we apply the bezier points to other properties?&lt;br /&gt;
Let's try, with the following settings:&lt;br /&gt;
&lt;pre&gt; var ops={
     backgroundColor:{start:'#000000',end:'#FF0000'},
     borderColor:{end:'#000000',start:'#FF0000'},
     top:{start:0,end:-100,bezier:-300},
     left:{start:0,end:450,bezier:200},
     borderWidth:{start:5,end:1,bezier:80}
 };
 animate(elm,ops,1500,20,backAndForth);
&lt;/pre&gt;
&lt;div id="baf2" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; overflow: hidden; padding: 20px; position: relative; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;a href="javascript:goBAF2();"&gt;Go back and forth with bezier&lt;/a&gt;
&lt;br /&gt;
Well, this is not going back and forth anymore!&lt;br /&gt;
The bezier equation is last in the function so it will reach the final destination and the backAndForth will create a kind of easing effect.&lt;br /&gt;
If we inverse the order in which bezier/easing is calculated, we will get an other effect...&lt;br /&gt;
We notice that the value set in the border-width can be used as a simple intermediate value for the animation too!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
We have seen a basic way of implementing the a quadratic bezier curve in our animation process and we have seen that playing around with the value used in the bezier can allow some unexpected effects!&lt;br /&gt;
But as always, drawbacks are numerous:&lt;br /&gt;
- we can set only one bezier point per property, most of the time cubic bezier is used, which allows to set up 2 points per property. We could even find a way to set as many as bezier points as we like!&lt;br /&gt;
- we cannot add a bezier points to the colors as this will require a different calculation.&lt;br /&gt;
- we modified the animation directly which could lead to some weird bugs if we were to add more features (several beziers, beziers to colors...).&lt;br /&gt;
The core code is starting to be huge and it will certainly be better to find a way to improve some functionalities of the animate function thru callbacks for example.&lt;br /&gt;
Therefore we could keep the basic function simple in its process and allow us to extend its possibilities without fearing to create bugs or to create a monster function!&lt;br /&gt;
After all, we may not need the bezier possibilities so why put it in the core of the function?&lt;br /&gt;
Obviously I have specified other drawbacks in the previous entry and they still hold true!&lt;br /&gt;
But anyway, enjoy the function as for now and try to create your own effects based on all the tools you have!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-941632564649972991?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/941632564649972991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=941632564649972991' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/941632564649972991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/941632564649972991'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/javascript-animation-curving-path-7.html' title='Javascript Animation : Curving the path (7)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-7434658069541102903</id><published>2007-10-14T22:56:00.001+09:00</published><updated>2010-09-28T11:57:34.142+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : Several elements at once (6)</title><content type='html'>Until up to now, we have seen how to manipulate one css property of an element at a time and few css styles. I guess it is time to see how to manipulate several css properties in one animation!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Some examples&lt;/h3&gt;
&lt;br /&gt;
Before we dive into the code, we are going to see some of the effects you will be able to create.&lt;br /&gt;
These effects only include the linear easing, which means a fix step,
but you could apply the easeInOutQuad, CircularOut, Bounce...&lt;br /&gt;
You can use the function in many different ways and these are just few ideas:&lt;br /&gt;
(Ideas inspired by the &lt;a href="http://mootools.net/"&gt;mootools&lt;/a&gt; demo page)
&lt;script type="text/javascript"&gt;
function animate(elm,props, duration, fps,easing) {

      duration = (duration) ? parseFloat(duration) : 1000;
      fps      = (fps)      ? parseFloat(fps)      : 20;
      easing   = (easing)   ? easing               : linearEase;

      var interval    = Math.ceil(1000/fps);
      var totalframes = Math.ceil(duration/interval);

      for(i=1;i &lt;= totalframes;i++) {
              (function() {
             var frame=i;
                   generalProperty=function() {
     for(var prop in props){
                           if(!/olor/.test(prop)) {
                                var begin = props[prop].start*100;
                                var end   = props[prop].end*100;
               setStyle(elm,prop,easing(frame, begin, end-begin, totalframes)/100);
         } else {
                                var b = hexStr2rgbArray(props[prop].start);
                                var e = hexStr2rgbArray(props[prop].end);
              var rgb=[];
                                for(j=0;j&lt;3;j++) rgb.push(parseInt(easing(frame, b[j], e[j]-b[j], totalframes)));
                                setStyle(elm,prop,'rgb('+rgb.join(',')+')');  
        }
     }
                   }
                  timer = setTimeout(generalProperty,interval*frame);
             })();   
     }
}
function d2h(dec) { 
  return dec.toString(16);
}
function h2d(hex) { 
   return parseInt(hex,16);
}
function rgb2h(r,g,b) { 
    return [d2h(r),d2h(g),d2h(b)];
}
function h2rgb(h,e,x) {  
     return [h2d(h),h2d(e),h2d(x)];
}
function cssColor2rgb(color) {
     if(color.indexOf('rgb')&lt;=-1) {
  return hexStr2rgbArray(color);
     }
 return rgbStr2rgbArray(color);
}
function hexStr2rgbArray(color) {
 return h2rgb(color.substring(1,3),color.substring(3,5),color.substring(5,7));
}
function rgbStr2rgbArray(color) {
 return color.substring(4,color.length-1).split(',');
}
function camelize(val) {
         return val.replace(/-(.)/g, function(m, l){return l.toUpperCase()});
}
function setOpacity(elm,val) {
          elm.style.zoom = 1;
          elm.style.filter = "alpha(opacity=" + parseFloat(val*100) + ")";
          elm.style.opacity  = parseFloat(val); 
    return elm;
}

function setStyle(elm,prop,val) {
        if(prop=='opacity') return setOpacity(elm,parseFloat(val));
  if(prop=='float')   prop = (window.attachEvent) ? 'styleFloat' : 'cssFloat';
  prop = camelize(prop);
        unit=(prop=='zIndex'||prop=='zoom') ? '':'px';
  elm.style[prop] = (typeof val=='string') ? val : val+unit;
        return elm;
}

//backAndForth
function linearEase(frame,begin,change,totalframes) {
 //linear bezier :
      return begin+((begin+change)-begin)*(frame/totalframes);
 var t=frame/totalframes;var end=begin+change;var p=begin;
 return (1-t)*(1-t)*begin + 2*t*(1-t)*(end+change) + t*t*p;
 return easeOutBounce(frame,begin,y-begin,totalframes);
}
function SlideOut(elm) {
 elm=document.getElementById(elm);
 animate(elm,{marginLeft:{start:-elm.offsetWidth,end:0}});
}
function SlideIn(elm) {
 elm=document.getElementById(elm);
 animate(elm,{marginLeft:{start:0,end:-elm.offsetWidth}});
}
function SlideOutVertical(elm) {
 elm=document.getElementById(elm);
 animate(elm,{marginTop:{start:-elm.offsetHeight,end:0}});
}
function SlideInVertical(elm) {
 elm=document.getElementById(elm);
 animate(elm,{marginTop:{start:0,end:-elm.offsetHeight}});
}
function FadeOut(elm) {
 elm=document.getElementById(elm);
 animate(elm,{opacity:{start:1,end:0}});
}
function FadeIn(elm) {
 elm=document.getElementById(elm);
 animate(elm,{opacity:{start:0,end:1}});
}
function Morph(nb) {
 elm=document.getElementById('morph');
 var ops1={
    backgroundColor:{start:'#000000',end:'#FF0000'},
          color:{start:'#FFFFFF',end:'#0000FF'},
          borderWidth:{start:4,end:2},
    borderColor:{start:'#FF0800',end:'#0000FF'},
          width:{start:350,end:250},
          padding:{start:0,end:20},
    top:{start:0,end:30},
          left:{start:0,end:50},
    fontSize:{start:14,end:10}
       };
 var ops2={
    backgroundColor:{end:'#000000',start:'#FF0000'},
          color:{end:'#FFFFFF',start:'#0000FF'},
          borderWidth:{end:4,start:1},
    borderColor:{end:'#FF0800',start:'#FF08FF'},
          width:{end:350,start:250},
          padding:{end:20,start:0},
    top:{end:0,start:30},
          left:{end:0,start:50},
    fontSize:{end:14,start:10}
       };

 if(nb==1) animate(elm,ops1);
       else animate(elm,ops2);


}
&lt;/script&gt;

&lt;br /&gt;
&lt;h4&gt;
Slide Horizontal&lt;/h4&gt;
&lt;a href="javascript:SlideIn('slide');"&gt;Slide In&lt;/a&gt;
&lt;a href="javascript:SlideOut('slide');"&gt;Slide Out&lt;/a&gt;
&lt;br /&gt;
&lt;div style="overflow: hidden;"&gt;
&lt;div id="slide" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; padding: 20px; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;
Slide Vertical&lt;/h4&gt;
&lt;a href="javascript:SlideInVertical('slide2');"&gt;Slide In&lt;/a&gt;
&lt;a href="javascript:SlideOutVertical('slide2');"&gt;Slide Out&lt;/a&gt;
&lt;br /&gt;
&lt;div style="overflow: hidden;"&gt;
&lt;div id="slide2" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; overflow: hidden; padding: 20px; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;
Fade&lt;/h4&gt;
&lt;a href="javascript:FadeIn('fade');"&gt;Fade In&lt;/a&gt;
&lt;a href="javascript:FadeOut('fade');"&gt;Fade Out&lt;/a&gt;
&lt;br /&gt;
&lt;div id="fade" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; overflow: hidden; padding: 20px; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;h4&gt;
Morph&lt;/h4&gt;
&lt;a href="javascript:Morph(1);"&gt;Morph to&lt;/a&gt;
&lt;a href="javascript:Morph(2);"&gt;Morph back&lt;/a&gt;
&lt;br /&gt;
&lt;div id="morph" style="background-color: black; border: 4px solid rgb(255, 8, 0); color: white; overflow: hidden; padding: 20px; position: relative; width: 350px;"&gt;
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.  
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Manipulating several elements&lt;/h3&gt;
Until up to now, we were manipulating only one css property at a time, it could be the width, the height, the opacity but not all of them at once!&lt;br /&gt;
In order to define several properties at once, we are going to use a literal object.(You can read a simple introduction about this here:&lt;a href="http://shiriru.blogspot.com/2007/10/javascript-literal-notation-basics.html"&gt;Javascript literal notation:basics&lt;/a&gt;)&lt;br /&gt;
As a reminder this is how we used to call the function:&lt;br /&gt;
&lt;pre&gt;animate(elm,property,start,end,duration,fps,easingType);
&lt;/pre&gt;
You can read the previous articles of the series if necessary.&lt;br /&gt;
As we are going to use a literal object to define the properties, this is how we will call the function:&lt;br /&gt;
&lt;pre&gt;animate(elm,properties,duration,fps,easingType);
&lt;/pre&gt;
We could define different ways to define the css properties:&lt;br /&gt;
&lt;pre&gt;var properties={
   color:['#FFFFFF','#00FF00'],
  'background-color':['#000000','#ffffff'],
   opacity:[1,.5],
   width:[200,400]
}
&lt;/pre&gt;
Here we create a literal object and then define the start and end value in an array literal for each css properties.&lt;br /&gt;
This is fine but this is not very clear and if we were to add some functionalities, this might get cumbersome to remember the order, therefore, we will write it this way:&lt;br /&gt;
&lt;pre&gt;var properties={
   color:{start:'#FFFFFF',end:'#00FF00'},
  'background-color':{start'#000000',end:'#ffffff'},
   opacity:{start:1,end:.5},
   width:{start:200,end:400}
}
&lt;/pre&gt;
Instead of defining the beginning and the end of the animation thru a literal array, we use a literal object.&lt;br /&gt;
This is a little bit longer to write but clearer and allow to add further elements like callbacks, type of easing per property basis if we want!&lt;br /&gt;
As for the css properties, the colors and some cross-browsers implementation, you can read the following entries:&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/10/javascript-animation-changing-colors-5.html"&gt;Javascript Animation: Changing Colors (5)&lt;/a&gt;&lt;br /&gt;
And &lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/10/setting-html-element-style-thru.html"&gt;Setting html element style thru Javascript&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
We will need to use some of the functions explained in these entries so feel free to read these if you don't get it.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The animation code&lt;/h3&gt;
&lt;br /&gt;
Let's see the main function : animate!&lt;br /&gt;
&lt;pre&gt;function animate(elm,props, duration, fps,easing) {

 duration = (duration) ? parseFloat(duration) : 1000;
 fps      = (fps)      ? parseFloat(fps)      : 20;
 easing   = (easing)   ? easing               : linearEase;

 var interval    = Math.ceil(1000/fps);
 var totalframes = Math.ceil(duration/interval);

 for(i=1;i &amp;lt;= totalframes;i++) {
  (function() {
    var frame=i;
    interpolate=function() {
      for(var prop in props){
        if(!/olor/.test(prop)) {
          var begin = props[prop].start*100;
          var end   = props[prop].end*100;
          setStyle(elm,prop,
                   easing(frame, begin, end-begin, totalframes)/100);
        } 
        else {
          var b = hexStr2rgbArray(props[prop].start);
          var e = hexStr2rgbArray(props[prop].end);
          var rgb=[];
          for(j=0;j&amp;lt;3;j++) 
              rgb.push(parseInt(
                       easing(frame, b[j], e[j]-b[j], totalframes)));
          setStyle(elm,prop,'rgb('+rgb.join(',')+')');  
        }
      }
    }
    timer = setTimeout(interpolate,interval*frame);
   })();   
  }
}
&lt;/pre&gt;
There's not that much new:&lt;br /&gt;
First we define some default values for the duration, fps and easing.&lt;br /&gt;
Then we calculate the total number of frames and loop thru them.&lt;br /&gt;
We loop thru each properties in the object and set the style to the element.&lt;br /&gt;
We need to separate the colors from other properties as we need to calculate 3 values at a time!&lt;br /&gt;
We apply the easing function passed in the function.It could be Bouncing, Quad, Quart...All of them calculating the evolution from start to the end in a non-fix manner!&lt;br /&gt;
That's all!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Helper functions&lt;/h3&gt;
&lt;br /&gt;
You have certainly noticed that the function use other functions to set the style, calculate the colors.&lt;br /&gt;
Here is a list of all the helper functions:&lt;br /&gt;
&lt;pre&gt;function d2h(dec) { 
  return dec.toString(16);
}
function h2d(hex) { 
   return parseInt(hex,16);
}
function rgb2h(r,g,b) { 
    return [d2h(r),d2h(g),d2h(b)];
}
function h2rgb(h,e,x) {  
     return [h2d(h),h2d(e),h2d(x)];
}
function cssColor2rgb(color) {
     if(color.indexOf('rgb')&amp;lt;=-1) {
       return hexStr2rgbArray(color);
     }
 return rgbStr2rgbArray(color);
}
function hexStr2rgbArray(color) {
 return h2rgb(color.substring(1,3),color.substring(3,5),color.substring(5,7));
}
function rgbStr2rgbArray(color) {
 return color.substring(4,color.length-1).split(',');
}
function camelize(val) {
   return val.replace(/-(.)/g, function(m, l){return l.toUpperCase()});
}
function setOpacity(elm,val) {
    elm.style.zoom = 1;
    elm.style.filter = "alpha(opacity=" + parseFloat(val*100) + ")";
    elm.style.opacity  = parseFloat(val); 
    return elm;
}

function setStyle(elm,prop,val) {
  if(prop=='opacity') 
     return setOpacity(elm,parseFloat(val));
  if(prop=='float')   
     prop = (window.attachEvent) ? 'styleFloat' : 'cssFloat';
  prop = camelize(prop);
  unit=(prop=='zIndex'||prop=='zoom') ? '':'px';
  elm.style[prop] = (typeof val=='string') ? val : val+unit;
  return elm;
}

function linearEase(frame,begin,change,totalframes) {
      return change*(frame/totalframes)+begin;
}
&lt;/pre&gt;
Some of them can be reused alone like the setStyle, setOpacity or even the camelize...&lt;br /&gt;
I don't put all the easing functions as you can find them in the past entry:&lt;br /&gt;
&lt;a href="http://shiriru.blogspot.com/2007/10/javascript-animation-make-things-move.html"&gt;Javascript Animation: Make things move smoothly&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
The function allows us to do some nice effects, controlling the time, the number of frames per second, the type of easing and now we can manipulate several properties at a time in a cross-browser way!&lt;br /&gt;
But as always, the drawbacks are numerous:&lt;br /&gt;
- They are some css properties that need to be written in multiple stage to work like the border or margin properties.&lt;br /&gt;
- We can apply only one type of easing for all the properties in one animation but sometimes you will like a linear easing (color) combined with a bouncing easing (top,left properties).&lt;br /&gt;
- We didn't define a way to have callbacks and chain effects one after an other.&lt;br /&gt;
- If you click several times on a link, the animation will just go out of control! We need to keep somewhere the state of the animation!&lt;br /&gt;
- We need to write all the css properties, which can be cumbersome quickly and we don't keep the DRY principle (Don't Repeat Yourself!) as you will certainly define a css class and then rewrite some of the elements in the animation! From there, we can think that this could be nice to be able to set the animation from one class to an other!&lt;br /&gt;
- If you want to move your element from top0,left0 to top1,left1, this will be a straight line, even if you apply an easing function, you won't be able to curve the path...Perhaps, we could use a Bezier as we may already have the ingredients!
The list is still long so I will stop for now but have fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-7434658069541102903?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/7434658069541102903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=7434658069541102903' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/7434658069541102903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/7434658069541102903'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/javascript-animation-several-elements.html' title='Javascript Animation : Several elements at once (6)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-3320694827013100198</id><published>2007-10-13T14:43:00.000+09:00</published><updated>2007-10-14T22:56:41.513+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>Javascript Literal Notation: basics</title><content type='html'>Javascript offers different way to create arrays.&lt;br /&gt;
We will see how to create them by using the literal notation and see some advantages of this notation.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Arrays creation:the old way&lt;/h3&gt;
&lt;br /&gt;
Javascript offers a way to store multiple values in one variable.Each variable is associated with a number starting from 0.&lt;br /&gt;
This variable, containing several values is called an array.&lt;br /&gt;
Here is how you can create an array:&lt;br /&gt;
&lt;pre&gt;
var words=new Array();
words[0]='hi';
words[1]='good bye';
words[2]='good morning';
words[3]=4;
&lt;/pre&gt;
You could define in the constructor new Array the number of values that will be stored:&lt;br /&gt;
&lt;pre&gt;
var words=new Array(4);
&lt;/pre&gt;
The array will contain 4 slots ready to be used.&lt;br /&gt;
You could also defined the values directly in the Array constructor:&lt;br /&gt;
&lt;pre&gt;
var words=new Array('hi','good bye','good morning',4);
&lt;/pre&gt;
This is shorter and you can access the value by their position in the array:&lt;br /&gt;
&lt;pre&gt;
var words=new Array('hi','good bye','good morning',4);
alert(words[1]); // alert good bye
alert(words[3]); //alert 4
&lt;/pre&gt;
Remember that it starts from 0 and as you can see, the value are kept in the order you have written them!&lt;br /&gt;
You can change a value afterward too:&lt;br /&gt;
&lt;pre&gt;
words[3]='good afternoon';
&lt;/pre&gt;
What was a number,4, is now the string 'good afternoon'.&lt;br /&gt;
&lt;br /&gt;
Creating an array, gives you access to different properties and method:&lt;br /&gt;
&lt;pre&gt;
alert(words.length); //4
alert(words.sort()); //4,good bye,godd morning,hi
alert(words.reverse()); //hi,good morning,good bye,4
alert(words.join()); //hi,good morning,good bye,4
alert(words.join('|')); //hi|good morning|good bye|4
alert(words.toString()); //hi,good morning,good bye,4


alert(words.slice(0)); //hi,good morning,good bye,4
alert(words.slice(0,3));//hi,good morning,good bye
alert(words.slice(2,3));//good bye
alert(words.slice(0,-2));//hi, good morning
alert(words.slice(0,words.length-2));hi, good morning
&lt;/pre&gt;
You also have functions/methods to add/delete element from the array:&lt;br /&gt;
&lt;pre&gt;
alert(words.pop());//4
alert(words.shift());//hi
alert(words.push());//2
alert(words.unshift());//undefined
alert(words.splice(0,2,'good afternoon')); //good morning,good bye
&lt;/pre&gt;
You can read more about this subject &lt;a href="http://www.w3schools.com/jsref/jsref_obj_array.asp"&gt;here&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Arrays creation: the new way&lt;/h3&gt;
&lt;br /&gt;
The new way is an addition to the old way, which means that you can still use the old way.&lt;br /&gt;
&lt;pre&gt;
var words=[];
words[0]='hi';
words[1]='good bye';
words[2]='good morning';
words[3]=4;
&lt;/pre&gt;
or&lt;br /&gt;
&lt;pre&gt;
var words=['hi','good bye','good morning',4];
&lt;/pre&gt;
which in the end allows to do the same manipulation as above!&lt;br /&gt;
This is shorter and allows you to nest arrays:&lt;br /&gt;
&lt;pre&gt;
var words=['hi',['salut','heil'],'good bye',['au revoir','Auf Wiedersehen']'good morning',['bonjour','Guten Morgen'],4];
&lt;/pre&gt;
Then you can do this:&lt;br /&gt;
&lt;pre&gt;
alert('english'+words[0]);//hi
alert('french'+words[1][0]);//salut
alert('german'+words[1][1]);//heil
&lt;/pre&gt;
That's nice!&lt;br /&gt; 
But nested arrays are not very easy to deal with...&lt;br /&gt;
You have to remember that you have the english word followed by an array containing first the French version and then the German.&lt;br /&gt;It is not very intituive that's why there is an other way to store multiple values in one variable.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Associative arrays or Hash or Dictionaries&lt;/h3&gt;&lt;br /&gt;
I have written all the name you may encounter in different languages.&lt;br /&gt;
They all define the same base ideas, having the final implementation sometimes diverging from a language to an other.&lt;br /&gt;
As we have seen we can store several values in one variable thru arrays.&lt;br /&gt;
We can then call the value we need by referencing its position in the array.&lt;br /&gt;
But calling values thru their position is not very as friendly as it could be and if the order change, you will have to rewrite many things in your code.&lt;br /&gt;
It could be nice if we could set a name to the variables we store and then we could refer to this name instead of the position.&lt;br /&gt;
Basically an associative array associate a name with a value and store everything into one variable.&lt;br /&gt;
In javascript unfortunately, you don't have associative arrays!&lt;br /&gt;
But you have what is called object and we can use them to create some pseudo-associative arrays.&lt;br /&gt;
Why aren't they true associative arrays ?&lt;br /&gt;
Because you don't have access to all the functions and methods we have seen for the arrays!&lt;br /&gt;
Let's see how we can create an object in javascript.&lt;br /&gt;
They are many ways:&lt;br /&gt;
&lt;pre&gt;
var dictionary=new Object();
dictionary.english=['hi','good bye','good morning'];
//or
dictionary['english']=['hi','good bye','good morning'];
dictionary['french']=['salut','au revoir','bonjour'];
dictionary['german']=['heil','Auf Wiedersehen','Guten Morgen'];
&lt;/pre&gt;
Then we can do the following:&lt;br /&gt;
&lt;pre&gt;
alert(dictionnary['english'][0]); // return hi
alert(dictionnary['french'][0]); // return salut
alert(dictionnary['german'][0]); // return heil
&lt;/pre&gt;
So we created an object and stored into each language an array literal of each words.&lt;br /&gt;
But this is not very better than our nested arrays, we still need to refer to the value thru their position in the array.&lt;br /&gt;
If we can nest array literal, we can aslo nest object literals!&lt;br /&gt;
First let's see how to create a literal object:&lt;br /&gt;
&lt;pre&gt;
var dictionary={};
&lt;/pre&gt;
Here you go, you have created your object!&lt;br /&gt;
To notice that literal notations don't give access to all the properties/methods you could have with the usual creation.&lt;br /&gt;
For objects, you won't have access to the prototype methods but for now, this is ok as this won't be a problem for our purpose.&lt;br /&gt;
Then we could rewrite the above like this:&lt;br /&gt;
&lt;pre&gt;
var dictionnary={
     english:['hi','good morning','good bye'],
     french:['salut','bonjour','au revoir'],
     german:['heil','Guten Morgen','Auf Wiedersehen']
}
&lt;/pre&gt;
As you can see we separate each new property from their value by using ':'.&lt;br /&gt;
&lt;br /&gt;
So now, how could we make our access to each words easier?&lt;br /&gt;
Let's nest object literals!&lt;br /&gt;
&lt;pre&gt;
var dictionary = {
    hi:{
       french:'salut',
       german:'heil'
    },
    'good bye': {
       french:'au revoir',
       german:'auf Wiedersehen'
    },
    'good morning':{
       french:'bonjour',
       german:'Guten Morgen'
    }
};
&lt;/pre&gt;
Let's explain the above a little.&lt;br /&gt;
We create an object by using the literal notation, then we can enter some properties name. Instead of assigning a simple value to the property, we assign again a literal object! We are therefore nesting objects!&lt;br /&gt;
This is how we can then call the different words:&lt;br /&gt;
&lt;pre&gt;
dictionary['hi']['french']; // salut;
dictionary['hi']['german']; // heil;
dictionary['good morning']['french']; // bonjour;
&lt;/pre&gt;
Here we don't refer to any position of the value, we refer to their property name, which allow to create more readable programs!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;A good example of literal notation use:Function parameters&lt;/h3&gt;&lt;br /&gt;
&lt;h4&gt;The problem&lt;/h4&gt;
It often happens that you create a function that requires several parameters:&lt;br /&gt;
&lt;pre&gt;
createElement(ElementType,idName);
&lt;/pre&gt;
This function will create an element according to the parameters.This is fine for now as it is just 2 parameters, easy to remember!&lt;br /&gt;
&lt;pre&gt;
createElement('div','container');
&lt;/pre&gt;
But then you decide that it could be nice if we could set the width and height:&lt;br /&gt;
&lt;pre&gt;
createElement(ElementType,idName,width,height);
//example
createElement('div','container',200,150);
&lt;/pre&gt;
This starts to be harder to remember the order of each element and if somebody reads the function call, he/she won't have any clue about what are the numbers 200 and 150.&lt;br /&gt;
This could be the widht and height or the height and width...&lt;br /&gt;
But it is still just 4 parameters, that's fine.&lt;br /&gt;
Then as you create div very often, you choose to set the div creation as the default behavior of your function and you add the colors:&lt;br /&gt;
&lt;pre&gt;
createElement(idName,width,height,backgroundColor,color,elementType);
//example
createElement('container',200,150,'#FFFFFF','#FF0000');
//example
createElement('container',200,150,'#FFFFFF','#FF0000','p');
&lt;/pre&gt;
Here again, it is starting to be harder to remember the order of each element.&lt;br /&gt;
Sometimes you won't even need to set the background color so you will have to write:&lt;br /&gt;
&lt;pre&gt;
createElement('container',200,150,'','#FF0000');
&lt;/pre&gt;
This is not that bad but you may have a typo miss like:&lt;br /&gt;
&lt;pre&gt;
createElement('container',200,150,'#FF0000','p');
&lt;/pre&gt;
Did you really want to set the background color or did you just forget to skip the background color and then set the color? Here your color will be a paragraph element!!&lt;br /&gt;
Hummm...That's becoming hard.&lt;br /&gt;
&lt;h4&gt;Solution:use a literal object!&lt;/h4&gt;
If you use a literal object, you will be able to write each parameters in the order you like and only if you need them!&lt;br /&gt;
&lt;pre&gt;
var parameters={
     element:'div',
     id:'container',
     height:'200',
     width:'150',
     color:'#0000FF',
     'background-color':'#FFFFFF'
}
createElement(parameters);
//or 
createElement({id:'container',element:'p'});
&lt;/pre&gt;
The code is self-explainatory, you don't have to remember the position of each paremeters in the function call and it's really easy to have optional parameters!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
We have seen how we can create literal arrays and literal objects and how we can use them in real programming problems!&lt;br /&gt;
Obviously, we didn't really explain the concept of object and we have seen a very basic use of them.&lt;br /&gt;
We will see in an other entry what are the principle behing objects and what you can do we them!&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-3320694827013100198?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/3320694827013100198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=3320694827013100198' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/3320694827013100198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/3320694827013100198'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/javascript-literal-notation-basics.html' title='Javascript Literal Notation: basics'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-2059457436810033417</id><published>2007-10-10T20:56:00.000+09:00</published><updated>2007-10-28T02:42:44.256+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Flash : How developers create bad SEO websites with XML</title><content type='html'>There are many ways to get your website more interactive with a nice user interface embedded with little fade in effects to Real time 3D universe.&lt;br /&gt;
Flash, Silverlight, Javascript are some of these tools allowing you to built a rich interface nowadays.&lt;br /&gt;
Let's look at some data driven Flash website implementations and see why their use of XML should rethink for a better SEO approch.&lt;br /&gt;

&lt;h3&gt;Flash and XML&lt;/h3&gt;

For whatever reasons, you want cool clunky animations within your main left navigation bar.&lt;br /&gt;
You have choosen to put this into a beautiful Flash applications that fulfills all your dreams.&lt;br /&gt;
Where is the trap ?&lt;br /&gt;
&lt;br /&gt;
This animation use an XML file that allows you to update your links and all in all, it was a breathe to have this in place :&lt;br /&gt;
- good bye cross-browsers hacks
- good bye sad navigation...&lt;br /&gt;
- good bye users!&lt;br /&gt;
&lt;br /&gt;
As you may no it's very hard for search engines to index the contents of a flash animation.&lt;br /&gt;
If your contents is created on the fly and not hardcoded in the Flash animation, you cannot use the accessibility feature.&lt;br /&gt;
Even if you could, this will give you some raw data:&lt;br /&gt;
- good bye semantics,&lt;br /&gt;
- good bye google rank.&lt;br /&gt;
&lt;br /&gt;
we don't even think of the people who does not have Flash (There are so few, it's not that big deal)&lt;br /&gt;
But you are loosing users and all the pages lost within Flash will ever hardly hits.&lt;br /&gt;
&lt;br /&gt;
There is something really simple to do in that case:&lt;br /&gt;
Get a semantic XML File!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Why sometimes reinventing the wheel is not a good idea&lt;/h3&gt;&lt;br /&gt;
&lt;br /&gt;
Let's see an example of an xml file, it is I guess from a tutorial that you can find on the web:&lt;br /&gt;
&lt;pre&gt;
&amp;lt;root&amp;gt;
&amp;lt;menu name="nav"&amp;gt;
     &amp;lt;menu name="TOP" view="horizontal"&amp;gt;
 &amp;lt;item name="Top1" action="gotoURL" variables="/top/index.html"/&amp;gt;
 &amp;lt;item name="Top2" action="gotoURL" variables="/top/top2.html"/&amp;gt;
    &amp;lt;/menu&amp;gt;
    &amp;lt;menu name="TUTORIALS" view="horizontal"&amp;gt;
 &amp;lt;menu name="Javascript" action="gotoURL" variables="/javascipt/index.html"&amp;gt;
      &amp;lt;item name="Beginners" action="gotoURL" variables="/javascript/b/index.html"/&amp;gt;
      &amp;lt;item name="Seniors" action="gotoURL" variables="/javascript/s/index.html"/&amp;gt;
 &amp;lt;/menu&amp;gt;
 &amp;lt;item name="PHP" action="gotoURL" variables="/php/index.html"/&amp;gt;
   &amp;lt;/menu&amp;gt; 
&amp;lt;/menu&amp;gt;
&amp;lt;/root&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
Alright, here is nice, well-formated XML!&lt;br /&gt;
What people says about XML ?&lt;br /&gt;
- it's portable&lt;br /&gt;
- it's easy&lt;br /&gt;
- it does cook late at night&lt;br /&gt;
&lt;br /&gt;
These were the main arguments using XML with Flash and also the fact that the only you can manipulate data in Flash is thru an XML document.&lt;br /&gt;
That's true that this XML is very portable: you will be able to use it with THIS flash animation and nothing else.&lt;br /&gt;
It's true that it's easy, you just read the documents and figure out in 30 minutes how you should update this document.&lt;br /&gt;
&lt;br /&gt;
There must be an even easier way...&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;XML : Somebody forgot the HT!&lt;/h3&gt;&lt;br /&gt;
&lt;br /&gt;
There's something even more portable, even easier than THIS XML file, 
it is called XHTML!&lt;br /&gt;
Alright, we are dealing with the Internet, links, websites, we are not interchanging data for something else than a browser!&lt;br /&gt;
If you look the XML document, you will see that it is just reinventing the XHTML:&lt;br /&gt;
- The navigation could be a list of ul and li!&lt;br /&gt;
- The action='goToUrl' is a link, a&lt;br /&gt;
- The variable is the href property of this link&lt;br /&gt;
- The name could be the title or the id, or the class&lt;br /&gt;
&lt;br /&gt;
Let's change this XML into XHTML:&lt;br /&gt;
&lt;pre&gt;
&amp;lt;div id="main_nav"&amp;gt;
  &amp;lt;ul class="nav"&amp;gt;
     &amp;lt;li&amp;gt;
         &amp;lt;h2&amp;gt;TOP&amp;lt;/h2&amp;gt;
         &amp;lt;ul&amp;gt;
       &amp;lt;li&amp;gt;&amp;lt;a title="Top1" href="/top/index.html"&amp;gt;Top1&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
       &amp;lt;li&amp;gt;&amp;lt;a title="Top2" href="/top/top2.html"&amp;gt;Top2&amp;lt;/a&amp;gt;&amp;lt;li&amp;gt;
         &amp;lt;/ul&amp;gt;
    &amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;
        &amp;lt;h2&amp;gt;TUTORIALS&amp;lt;/h2&amp;gt;
        &amp;lt;ul&amp;gt;
   &amp;lt;li&amp;gt;&amp;lt;a title="Javascript" href="/javascipt/index.html"&amp;gt;Javascript&amp;lt;/a&amp;gt;
            &amp;lt;ul&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;a title="Beginners" href="/javascript/b/index.html"&amp;gt;Beginners&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;a title="Seniors" href="/javascript/s/index.html"&amp;gt;Seniors&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
         &amp;lt;/li&amp;gt;
 &amp;lt;li&amp;gt;&amp;lt;a title="PHP" href="/php/index.html"&amp;gt;PHP&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
   &amp;lt;/li&amp;gt; 
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
The good thing about this document is that it is both XML compliant and XHTML compliant.&lt;br /&gt;
Obviously we are missing the &lt;?xml version="1.1"?&gt; tag at the beginning and we do not have any doctype specified.&lt;br /&gt;
You should see this file as an include file (like when Flash is actually calling the xml file)&lt;br /&gt;
You could use it as an html document and as the xml for the Flash animation.&lt;br /&gt;
The good point are:&lt;br /&gt;
- The chance that somebody knows html is bigger than the chance of knowing mr Johns XML specification.&lt;br /&gt;
- You can have a semantic website browsable by the search engines!&lt;br /&gt;
- You can add css to it (no need of xml+xslt...)&lt;br /&gt;
iF you call this xhtml as an xml document in Flash, even with the xml tags off, Flash will read it as long as it is a well-forment xml!&lt;br /&gt;
&lt;br /&gt;

&lt;h3&gt;Mixing the 2 worlds&lt;/h3&gt;&lt;br /&gt;
How can you have both the Flash and the XHTML together in the same page?&lt;br /&gt;
First of all, you should load your flash animation thru swfObject, that is thru Javascript.&lt;br /&gt;
If javascript is off or Flash is not going to be installed then the XHTML will be displayed.&lt;br /&gt;
If flash is installed, users will see the flash version while search engines will get the XHTML version!&lt;br /&gt;
From there, you can add the xhtml by using a noscript tag or by changing the display:block to none thru javascript/&lt;br /&gt;
If the users has javascript on, the content will be hidden, it javascript is off, the xhtml will  be displayed normally.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;
I have seen some websites and companies saying that THEY HAVE THE TOOL TO MAKE FLASH SE FRIENDLY.&lt;br /&gt;
Well, all their tools is crap...&lt;br /&gt;
I took the example of a menu but this is likely to be true for many different texts that you will 
have in a Flash animation.&lt;br /&gt;
ALWAYS TRY TO CREATE AN XHTML STRUCTURE FIRST!&lt;br /&gt;
And your website should be a search-engine friendly website.&lt;br /&gt;
But before using Flash, try to see if a Javascript solution could be better.&lt;br /&gt;
In this entry, I didn't talk about the XML that were setting some styles to the Flash!&lt;br /&gt;
Here it is the same thing!&lt;br /&gt; Don't reinvent CSS...&lt;br /&gt;
Obviously, this might be harder to deal with css thru Flash as it has a very poor implementation of it(less than javascript)&lt;br /&gt;
I was thinking about a CSS parser in PHP or Perl that will change it into a javActionScript object.&lt;br /&gt;
Then, actionscript could just get the element they are interested in...&lt;br /&gt;
But perhaps there is already such a parser?&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-2059457436810033417?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/2059457436810033417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=2059457436810033417' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/2059457436810033417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/2059457436810033417'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/flash-how-developers-create-bad-seo.html' title='Flash : How developers create bad SEO websites with XML'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-1459100100771363270</id><published>2007-10-09T22:55:00.000+09:00</published><updated>2007-10-10T12:00:14.413+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>Setting html element style thru Javascript</title><content type='html'>I guess that setting some style to an html element thru CSS has become something very usual : writing an xhtml compliant document and then decorate it with css thru classes, id and all the tools we can use.&lt;br /&gt;
In this entry, we will see a simple way to set some style thru javascript allowing dynamic styling and why not,creating some cool transitional effects from one style to an other !&lt;br /&gt;
For now, let's see the dynamic setting in action:&lt;br /&gt;
&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function camelize(val) {
         return val.replace(/-(.)/g, function(m, l){return l.toUpperCase()});
}
function setOpacity(elm,val) {
          elm.style.zoom = 1;
          elm.style.filter = "alpha(opacity=" + parseFloat(val*100) + ")";
          elm.style.opacity  = parseFloat(val); 
    return elm;
}

function setStyle(elm,prop,val) {
        if(prop=='opacity') return setOpacity(elm,parseFloat(val));
  if(prop=='float')   prop = (window.attachEvent) ? 'styleFloat' : 'cssFloat';
  prop = camelize(prop);
         unit=(prop=='zIndex'||prop=='zoom'||/olor/.test(prop)) ? '':'px';
  elm.style[prop] = (typeof val=='string') ? val : val+unit;
        return elm;
}
&lt;/script&gt;
&lt;a href="javascript:void(0)" onclick="setStyle(document.getElementById('mySuperClass2'),'background-color','#00FFFF');"&gt;
Background-color:#00FFFF&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="setStyle(document.getElementById('mySuperClass2'),'opacity',.5);"&gt;
opacity:.5&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="setStyle(document.getElementById('mySuperClass2'),'font-size','15px');"&gt;
font-size:15px&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="setStyle(document.getElementById('mySuperClass2'),'width',100);"&gt;
width:100px&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;style type="text/css"&gt;
div#mySuperClass2 {
    width:200px;
    height:200px;
    color:#FFFFFF;
    background-color:#000000;  
    z-index:100;
}
&lt;/style&gt;
&lt;div id="mySuperClass2"&gt;cool text&lt;/div&gt;
&lt;h3&gt;The CSS way&lt;/h3&gt;
&lt;br /&gt;
I am not going to explain how CSS works as this will be too long but we will just see a simple class defined in an coolStyle.css file:&lt;br /&gt;
&lt;pre&gt;
div#mySuperId{
    width:200px;
    height:200px;
    color:#FFFFFF;
    background-color:#000000;  
    z-index:100;
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;
div#mySuperId {
    width:200px;
    height:200px;
    color:#FFFFFF;
    background-color:#000000;  
    z-index:100;
}
&lt;/style&gt;
&lt;div id="mySuperId" &gt;&lt;/div&gt;
Alright, we are just styling a div set with an id called mySuperId.&lt;br /&gt;
We set different properties like the width, height, color and background-color...&lt;br /&gt;
Something you have certainly done hundreds of time!&lt;br /&gt;
As you can see properties require to specify an unit, a color, an integer or a string.&lt;br /&gt;
Composite words are separated by an hyphen, therefore making it easier to read.&lt;br /&gt;
Do you know the other way we could do this in general ?&lt;br /&gt;
Well, we could use the camelcase style!&lt;br /&gt;
This will transform our hyphened properties to this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;
backgroundColor:#000000;
zIndex:100;
&lt;/pre&gt;
Basically, we write the first word in lower-case and separate each new words by putting the first letter in upper-case, which is not without reminding the humps of the camel, thus the name!&lt;br /&gt;
You know what?&lt;br /&gt;
This is with this convention that javascript can access the style properties of an html element!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The Javascript Way&lt;/h3&gt;
&lt;br /&gt;
So first we need to get the element we will be working on, here an html div element:&lt;br /&gt;
&lt;pre&gt;
var elm=document.getElementById('mySuperId');
//now we can work on the style properties of this element:
elm.style.width='400px';
elm.style.height='100px';
elm.style.background-color='#FF00FF'; //Won't work!
elm.style.backgroundColor='#FF00FF'; // Now, it will
&lt;/pre&gt;
From there, we can decide between 2 options : people write the css properties in javascript with the camelcase style or we find a way to let them write the css way.&lt;br /&gt;
Well, we need to change a word that is hyphenized by doing so :&lt;br /&gt;
If the string has an hyphen followed by a letter, erase the hyphen and then change the following first letter into an upper-case...&lt;br /&gt;
This may seem complicated, but this will be almost a one-liner!&lt;br /&gt;
Thanks to regular expressions, we can do this:&lt;br /&gt;
&lt;pre&gt;
function camelize(val) {
   return val.replace(/-(.)/g, function(m, l){return l.toUpperCase()});
}
//example
camelize('background-color'); return backgroundColor
&lt;/pre&gt;
Thru the replace function we look for an hyphen followed by any letter ('.').&lt;br /&gt;
We capture the letter found thanks to the parenthizes then we apply a an anonymous function to the result.&lt;br /&gt;
The first parameter is the entire match which, in that case will be -c.&lt;br /&gt;
The following parameters represent each capturing parentheses.&lt;br /&gt;
We just change the captured letter to upper-case and send it back!&lt;br /&gt;
Was easy right ?&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;A first draft&lt;/h3&gt;
&lt;br /&gt;
As I think that being inventive is one of my best attribute in this world, I will call this function... setStyle... &lt;br /&gt;
This is how we are going to call the function:&lt;br /&gt;
&lt;pre&gt;
setStyle(elm,prop,val);
//example
setStyle(document.getElementById('mySuperClass'),'background-color','#FF00FF');
&lt;/pre&gt;
And as you can see we will have to camelize the property, so let's do it:&lt;br /&gt;
&lt;pre&gt;
function setStyle(elm,prop,val) {
           prop=camelize(prop);
           elm.style[prop]=val;
           return elm;
}
&lt;/pre&gt;
This is a blueprint because unfortunately, if we have seen the css way, the javascript way, now we have to see the browser way !&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The browser way&lt;/h3&gt;
&lt;br /&gt;
This should be the browsers way in fact!&lt;br /&gt;
If you have read the entries about javascript animation, we've been already setting style to the properties and we have done some cross-browser correction.&lt;br /&gt;
Let's see the properties that could be troublesome.&lt;br /&gt;
&lt;h4&gt;Opacity&lt;/h4&gt;
&lt;br /&gt;
Well, this is easy: this property just do not exist in IE!&lt;br /&gt;
IE has it's own property that is filter:[typeOfFilter:value];&lt;br /&gt;
Where others accept a value between 0 and 1, IE wants a value between 0 and 100!&lt;br /&gt;
So to set the opacity of an element in cross-browser way, we will create one function :&lt;br /&gt;
&lt;pre&gt;
function setOpacity(elm,val) {
          if(window.attachEvent) {
               elm.style.zoom = 1;
               elm.style.filter = "alpha(opacity=" + parseFloat(val*100) + ")";
                return elm;
          }
          elm.style.opacity  = parseFloat(val); 
   return elm;
}
&lt;/pre&gt;
First we check for an IE function that is not implemented in other browsers.&lt;br /&gt;
If the function exist we set an other IE property, zoom.
(you can check what it is here:&lt;a href="http://www.satzansatz.de/cssd/onhavinglayout.html"&gt;hasLayout&lt;/a&gt;&lt;br /&gt;Zoom is an IE style property that gives the element the layout properties, adding some new features to the element)&lt;br /&gt;
We set the property the IE way and then we return.&lt;br /&gt;
If it's not IE, we do it the standard way.&lt;br /&gt;
&lt;br /&gt;
I even think that we can simplify even more by just not checking the browser:&lt;br /&gt;
&lt;pre&gt;
function setOpacity(elm,val) {
          elm.style.zoom = 1;
          elm.style.filter = "alpha(opacity=" + parseFloat(val*100) + ")";
          elm.style.opacity  = parseFloat(val); 
   return elm;
}
&lt;/pre&gt;
If we set a property that is not understood, the browser will just set it and ignore it but apply the property it can handle.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;Float&lt;/h4&gt;&lt;br /&gt;
The float is a keyword in Javascript and cannot be used, so javascript needs to refer to an other naming convention to refer to the style float property.&lt;br /&gt;
&lt;br /&gt;
Ie refers to it as styleFloat&lt;br /&gt;
Others refer to it as cssFloat&lt;br /&gt;
&lt;br /&gt;
let's update the function:&lt;br /&gt;
&lt;pre&gt;
function setStyle(elm,prop,val) {
         if(prop=='opacity') return setOpacity(elm,parseFloat(val));
  if(prop=='float')   prop = (window.attachEvent) ? 'styleFloat' : 'cssFloat';
  prop = camelize(prop);
  elm.style[prop] = val;
         return elm;
}
function setOpacity(elm,val) {
          elm.style.zoom = 1;
          elm.style.filter = "alpha(opacity=" + parseFloat(val*100) + ")";
          elm.style.opacity  = parseFloat(val); 
   return elm;
}
&lt;/pre&gt;
we first check the 2 above properties: if it is opacity, we just return the setOpacity function, if it is the float property, we set the right naming according to the browser.&lt;br /&gt;
We could by the way do some lazy initialization here regarding the float property:&lt;br /&gt;
&lt;pre&gt;
var styleFloat=(window.attachEvent) ? 'styleFloat' : 'cssFloat';
function setStyle(elm,prop,val) {
         if(prop=='opacity') return setOpacity(elm,parseFloat(val));
  if(prop=='float')   prop = styleFloat;
  prop = camelize(prop);
  elm.style[prop] = val;
         return elm;
}
&lt;/pre&gt;
The styleFloat variable will be set just once so we won't be checking this everytime the setStyle function is called.&lt;br /&gt;
This is not going to speed up your app that much but it's a way to do it.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;Other properties&lt;/h4&gt;
Well, all properties accept a unit like pixel, em, pt and whatsoever but the followings:&lt;br /&gt;
z-index,zoom and all the properties related to color!&lt;br /&gt;
So we are just going to check for the property and add the value with the proper unit:&lt;br /&gt;
&lt;pre&gt;
function setStyle(elm,prop,val) {
        if(prop=='opacity') return setOpacity(elm,parseFloat(val));
  if(prop=='float')   prop = (window.attachEvent) ? 'styleFloat' : 'cssFloat';
  prop = camelize(prop);
         unit=(prop=='zIndex'||prop=='zoom'||/olor/.test(prop)) ? '':'px';
  elm.style[prop] = (typeof val=='string') ? val : val+unit;
         return elm;
}
&lt;/pre&gt;
If this is a property that doesn't require a unit, we set the unit to empty else we apply a default unit that is px,for pixel.&lt;br /&gt;
Then we check if the value is a string ('#FFFFFF','400px'), if it is we set it as it is, if it's a number, we set the unit to 'px'.&lt;br /&gt;
&lt;br /&gt;
Here is how you can call the function:&lt;br /&gt;
&lt;pre&gt;
var elm=document.getElementById('mySuperId');
setStyle(elm,'background-color','#00FFFF');
setStyle(elm,'opacity',.5);
setStyle(elm,'font-size','15px');
setStyle(elm,'width',200);

&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;
Well, this function allows us now to set the style of an html element in a cross-browser manner but we didn't check for complex properties like margin:0px 10px 2px 3px; or 
border:1px solid red and this will not work for now ! you will have to write each of them: margin-top, margin-left...&lt;br /&gt;
Also we can only set one property at a time, which is not a very fast way of doing it but let's see this in a next entry!&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-1459100100771363270?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/1459100100771363270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=1459100100771363270' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/1459100100771363270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/1459100100771363270'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/setting-html-element-style-thru.html' title='Setting html element style thru Javascript'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-1550342156311015254</id><published>2007-10-07T00:45:00.001+09:00</published><updated>2010-09-28T11:57:34.143+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : Changing Colors (5)</title><content type='html'>We have seen so far how to manipulate different properties of a div such as the width, height, top, left and opacity. We also know how to apply easing to the interpolation in order not to have a mechanical animation.&lt;br /&gt;
Well, I guess it is time to expand the properties we can deal with and see how to animate colors !&lt;br /&gt;
&lt;h3&gt;
The animation&lt;/h3&gt;
&lt;script type="text/javascript"&gt;
function d2h(dec) { return dec.toString(16);}
function h2d(hex) { return parseInt(hex,16);}
function rgb2h(r,g,b) { return [d2h(r),d2h(g),d2h(b)];}
function h2rgb(h,e,x) {return [h2d(h),h2d(e),h2d(x)];}
function cssColor2rgb(color) {
     if(color.indexOf('rgb')&lt;=-1) {
  return h2rgb(color.substring(1,3),color.substring(3,5),color.substring(5,7));
     }
 var color=color.substring(1,4);
 increase=color.substring(color.length-1);
 return increase.split(',');

}

function animateColor(elm,begin,end, duration, fps) {

  if(!duration) duration = 1000;
  if(!fps) fps = 20;
  duration=parseFloat(duration);
  fps=parseFloat(fps);
  var interval    = Math.ceil(1000/fps);
  var totalframes = Math.ceil(duration/interval);

  for(i=1;i &lt;= totalframes;i++) {
                 (function() {
                   var frame=i;
                   var b = cssColor2rgb(begin);
                   var e  = cssColor2rgb(end);
                   var change0=e[0]-b[0];
                   var change1=e[1]-b[1];
                   var change2=e[2]-b[2];

                  function generalProperty() {
                  var increase0=ease(frame, b[0], change0, totalframes);
                  var increase1=ease(frame, b[1], change1, totalframes);
                  var increase2=ease(frame, b[2], change2, totalframes);

    elm.style['backgroundColor']  = 'rgb('+parseInt(increase0)+','+parseInt(increase1)+','+parseInt(increase2)+')';       
                  }
                  timer = setTimeout(generalProperty,interval*frame);
                 })(); 
 }
}
function ease(frame,begin,change,totalframes) {
 //linear bezier :
       return begin+((begin+change)-begin)*(frame/totalframes);
}




function changeColor() {
var start=document.getElementById('colorStart').value;
var end=document.getElementById('endStart').value;
animateColor(document.getElementById('squareColor'),start,end,3000,20);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="squareColor" style="background-color: red; height: 150px; width: 150px;"&gt;
&lt;/div&gt;
Starting color:&lt;input id="colorStart" type="text" value="#FF0000" /&gt;&lt;br /&gt;
End color:&lt;input id="endStart" type="text" value="#0000FF" /&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="changeColor()"&gt;test&lt;/a&gt;

&lt;br /&gt;
&lt;h3&gt;
Colors ?&lt;/h3&gt;
&lt;br /&gt;
What a better start than a refresher about colors ?&lt;br /&gt;
This may sound too much but let's see quickly some basic things about them as this will help us understand some programmatic points.&lt;br /&gt;
(Obviously, books exist only about colors but we will just see what is relevant for us in that case)
&lt;br /&gt;
As you may know all the colors human can see is a combination of 3 primary colors.&lt;br /&gt;
The 3 primary colors are arbitrary colors that respond to some particular needs.&lt;br /&gt;
In art, the 3 primary colors are red, yellow and blue.&lt;br /&gt;
Electronic displays use for the most, red green and blue.&lt;br /&gt;
In printing industry, cyan, magenta and yellow.&lt;br /&gt;
The mixing of one set of primary colors allow to recreate all the colors you may need.&lt;br /&gt;
Computer displays use the red, green and blue primary colors, abbreviated to rgb.&lt;br /&gt;
So do the browsers!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
RGB Notation&lt;/h3&gt;
&lt;br /&gt;
These 3 colors can be set different values, allowing different flavor of each : red or light red or light light red... for example.&lt;br /&gt;
Actual displays set 8 bits for each colors per pixel.&lt;br /&gt;
For reference' sake, 8 bits or one byte is something like : 01001100.&lt;br /&gt;
one bit can be set to 0 or 1, which means 2 possible value.&lt;br /&gt;
Therefore, one color can have 2&lt;sup&gt;8&lt;/sup&gt; values, 256 values or 255(starting from 0).&lt;br /&gt;
&lt;br /&gt;
The RGB notation used the numerical value within 0 to 255 to define the value of one color, thus we get:&lt;br /&gt;
&lt;br /&gt;
red:0 to 255&lt;br /&gt;
green:0 to 255&lt;br /&gt;
blue:0 to 255&lt;br /&gt;
&lt;br /&gt;
As an example, if you set red as being 255 and green, blue as being 0, you get red&lt;br /&gt;
If you set red as 0, green as 255 and blue as 0, you will get... green !&lt;br /&gt;
&lt;br /&gt;
But why I am talking about this ?&lt;br /&gt;
&lt;br /&gt;
Because browsers deal internally with colors by using the RGB Notation like this:&lt;br /&gt;
&lt;br /&gt;
rgb(255,112,220);&lt;br /&gt;
&lt;br /&gt;
And this will help us a lot as we know how to interpolate and calculate numbers!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The HEXADECIMAL NOTATION&lt;/h3&gt;
&lt;br /&gt;
As you can see the rgb notation will certainly be helpful but have you ever written such a color when setting some style to your xhtml thru CSS ?&lt;br /&gt;
&lt;br /&gt;
You have certainly written something like:&lt;br /&gt;
color:#FF0000;&lt;br /&gt;
which prints out the text in red!&lt;br /&gt;
&lt;br /&gt;
This notation use the hexadecimal version of the rgb notation!&lt;br /&gt;
...&lt;br /&gt;
The hexadecimal counts from 0 to F (base 16) instead of 0 to 9 in decimal (base 10).&lt;br /&gt;
So A is equal to 10, B to 11, C to 12...&lt;br /&gt;
1A is 1*16+10=26&lt;br /&gt;
FF is 15*16+15=255&lt;br /&gt;
&lt;br /&gt;
You won't really have to count using the hexadecimal base.&lt;br /&gt;
The hexadecimal system is used to set the 3 colors in a shorter way and easier way to remember, that's all we need to know!&lt;br /&gt;
So, #FF1AF1 is setting red as FF, green as 1A and blue as F1 which in decimal notation will be red:255,green:26 and blue:241!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Browsers and Colors&lt;/h3&gt;
&lt;br /&gt;
So we set the colors in hexadecimal but we need the rgb decimal numbers to animate the color!&lt;br /&gt;
&lt;br /&gt;
In Firefox there won't be any problems because if you set the color in hexadecimal and query it thru javascript, Firefox will send you back the rgb notation!&lt;br /&gt;
But IE will send you back the hexadecimal value!&lt;br /&gt;
So we will need to convert the hexadecimal value back to a rgb notation!&lt;br /&gt;
&lt;pre&gt;document.getElementById('square').style.color='#FFFFFF';
alert(document.getElementById('square').style.color);
//In ie return #FFFFFF
//In Firefox return rgb(255,255,255)
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Converting notations in Javascript&lt;/h3&gt;
&lt;br /&gt;
Well, we are lucky because javascript already has the function we need!&lt;br /&gt;
&lt;pre&gt;function d2h(dec) { 
       return dec.toString(16);
}
function h2d(hex) { 
       return parseInt(hex,16);
}
&lt;/pre&gt;
We are just wrapping them into two functions to short it up!&lt;br /&gt;
The d2h (decimal to hexadecimal) takes a decimal value and will send back the hexadecimal value.&lt;br /&gt;
&lt;pre&gt;alert(d2h(255));//alert FF
&lt;/pre&gt;
The h2d (hexadecimal to decimal) takes an hexadecimal value and will send back the decimal value.&lt;br /&gt;
&lt;pre&gt;alert(d2h('FF'));//alert 255
&lt;/pre&gt;
From there we can build 2 functions that will convert rgb and hexadecimal notation:&lt;br /&gt;
&lt;pre&gt;function rgb2h(r,g,b) { 
         return [d2h(r),d2h(g),d2h(b)];
}
function h2rgb(h,e,x) {
        return [h2d(h),h2d(e),h2d(x)];
}
&lt;/pre&gt;
These two functions send back an array of each value.&lt;br /&gt;
If you are not familiar with the [] notation, just know that it creates an array.&lt;br /&gt;
I'll write about this later I guess&lt;br /&gt;
&lt;br /&gt;
We can use them like so:&lt;br /&gt;
&lt;pre&gt;rgb2h(255,255,255);// return [FF,FF,FF]
h2rgb('FF','FF','FF');// return [255,255,255]
&lt;/pre&gt;
Now it's time to create a cross-browser function that will allow us to get back an array of value of each rgb value:&lt;br /&gt;
&lt;pre&gt;function cssColor2rgb(color) {
     if(color.indexOf('rgb')&amp;lt;=-1) {
     return h2rgb(color.substring(1,3),color.substring(3,5),color.substring(5,7));
     }
     return color.substring(4,color.length-1).split(',');
}
//example:
cssColor2rgb('#FFFFFF'); return [255,255,255]
cssColor2rgb('rgb(255,255,255)'); return [255,255,255]

&lt;/pre&gt;
First we check if we do not have an hexadecimal value thru indexOf that will return the position of the search in the string if found or -1 if not found.&lt;br /&gt;
Then if the function didn't find the rgb string, it means that we are dealing with an hexadecimal notation so we send each value to the h2rgb thru the substring function:&lt;br /&gt;
color.substring(1,3) is FF as 0,3 is '#FF'&lt;br /&gt;
Then return&lt;br /&gt;
(By the way we check if rgb doesn't exist instead of looking for # because browsers start counting the value found from 0 or 1 but -1 means everywhere that it wasn't found)&lt;br /&gt;
Otherwise, we are in front of a string 'rgb(value,value,value)'.&lt;br /&gt;
The 'rgb(' and ')' are not necessary so we just get rid of them and split the string by comma returning an array.&lt;br /&gt;
So now we have solved the cross browser problem, let's see how to incorporate this in the animation!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The Color Animation Code&lt;/h3&gt;
&lt;br /&gt;
In order to simplify the code, we are going to see how to animate only the color and not other properties.&lt;br /&gt;
We are stepping back but this is to jump higher!&lt;br /&gt;
&lt;pre&gt;function animateColor(elm,begin,end, duration, fps) {

  if(!duration) duration = 1000;
  if(!fps) fps = 20;
  duration=parseFloat(duration);
  fps=parseFloat(fps);
  var interval    = Math.ceil(1000/fps);
  var totalframes = Math.ceil(duration/interval);

  for(i=1;i &amp;lt;= totalframes;i++) {
                 (function() {
                   var frame=i;
                   var b = cssColor2rgb(begin);
                   var e  = cssColor2rgb(end);
                   var change0=e[0]-b[0];
                   var change1=e[1]-b[1];
                   var change2=e[2]-b[2];

                  function color() {
                  var increase0=ease(frame, b[0], change0, totalframes);
                  var increase1=ease(frame, b[1], change1, totalframes);
                  var increase2=ease(frame, b[2], change2, totalframes);

    elm.style['backgroundColor']  = 'rgb('+parseInt(increase0)+','+parseInt(increase1)+','+parseInt(increase2)+')';        
                  }
                  timer = setTimeout(color,interval*frame);
                 })(); 
 }
}
function ease(frame,begin,change,totalframes) {
       return begin+change*(frame/totalframes);
}
//example:
animateColor(document.getElementById('squareColor'),'#ff0000','#0000ff',3000,20);
&lt;/pre&gt;
Well, this function is almost like the one we have seen so far!&lt;br /&gt;
We have simplify as we do not set the property we are animating for now.&lt;br /&gt;
Then we change the hexadecimal values to rgb notation, calculate a linear step for each rgb value and pass the integer value (parseInt)to the property!&lt;br /&gt;
That's all!&lt;br /&gt;
&lt;br /&gt;
The hardest thing was to deal with the switching from one notation to an other!&lt;br /&gt;
The main function in itself doesn't change that much even if, for now, we have created a new function dedicated to color animation.&lt;br /&gt;
We will soon see how to reincorporate this into the main function animate!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
We do know now how to animate colors and I guess this can be very useful but as always, there are many drawbacks;&lt;br /&gt;
- we have created a function to animate only the background color of the element!&lt;br /&gt;
We should be able to animate all the properties with only one function to allow complex animations&lt;br /&gt;
- we still need to add some properties to our animation tool box!&lt;br /&gt;
- we used the linear easing here, even if we have several easing flavors with us.&lt;br /&gt;
Could we create some new way of animating the element thru equations ?&lt;br /&gt;
I guess so...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-1550342156311015254?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/1550342156311015254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=1550342156311015254' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/1550342156311015254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/1550342156311015254'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/javascript-animation-changing-colors-5.html' title='Javascript Animation : Changing Colors (5)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-9148453650270531007</id><published>2007-10-04T16:19:00.001+09:00</published><updated>2010-09-28T11:57:34.143+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : Make things move smoothly (4)</title><content type='html'>We have seen so far many ways to move a div property : you know how to make its width, height, top, left, opacity change over a chosen time and a number of frames. You also know the basic of easing and how it works, everything starts from one linear equation : y=mx+b.&lt;br /&gt;
Thanks to this, we are know able to create bunches of easing effects.&lt;br /&gt;
Let's explore them !&lt;br /&gt;
&lt;h3&gt;
Easing by example : the square was the source&lt;/h3&gt;
&lt;br /&gt;
Let's start by a little animation that can handle what we have seen so far and some cool easing.&lt;br /&gt;
Obviously, they are many things we can improve and we will !&lt;br /&gt;
&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function animate2(obj,elm,begin,end, duration, fps,easing) {

        if(!duration) duration = 1000;
        if(!fps) fps = 20;

     begin    = parseFloat(begin);
     end      = parseFloat(end);
     duration = parseFloat(duration);
     fps      = parseFloat(fps);

    var change      = end-begin;
    var interval    = Math.ceil(1000/fps);
    var totalframes = Math.ceil(duration/interval);
    var step        = change/totalframes;
       

 for(i=1;i &lt;= totalframes;i++) {
     (function() {
         var frame=i;
         function innerChangeWidth() {
             var s=eval(easing);
             var increase=s(frame,begin,change,totalframes);
             var slope=increase-begin
            
             unit=(elm=='opacity') ? '' : 'px';
             if(window.attachEvent &amp;&amp; !unit) { 
                  increase*=100; 
                  obj.style.zoom = 1;
                  obj.style.filter = "alpha(opacity=" + increase + ")";
              } else {
                     obj.style[elm]  = increase+unit; 
              }
    }
    timer = setTimeout(innerChangeWidth,interval*frame);
              })();
 }
}


linear = function (t, b, c, d) {
 var m=c/d;
 var a =t/d;
 return m*t + b;
};


easeInQuad = function (t, b, c, d) {
 return c*(t/=d)*t + b;
};
easeOutQuad = function (t, b, c, d) {
 return -c *(t/=d)*(t-2) + b;
};
easeInOutQuad = function (t, b, c, d) {
 if ((t/=d/2) &lt; 1) return c/2*t*t + b;
 return -c/2 * ((--t)*(t-2) - 1) + b;
};
easeInCubic = function (t, b, c, d) {
 return c*(t/=d)*t*t + b;
};
easeOutCubic = function (t, b, c, d) {
 return c*((t=t/d-1)*t*t + 1) + b;
};
easeInOutCubic = function (t, b, c, d) {
 if ((t/=d/2) &lt; 1) return c/2*t*t*t + b;
 return c/2*((t-=2)*t*t + 2) + b;
};
easeInQuart = function (t, b, c, d) {
 return c*(t/=d)*t*t*t + b;
};
easeOutQuart = function (t, b, c, d) {
 return -c * ((t=t/d-1)*t*t*t - 1) + b;
};
easeInOutQuart = function (t, b, c, d) {
 if ((t/=d/2) &lt; 1) return c/2*t*t*t*t + b;
 return -c/2 * ((t-=2)*t*t*t - 2) + b;
};
easeInQuint = function (t, b, c, d) {
 return c*(t/=d)*t*t*t*t + b;
};
easeOutQuint = function (t, b, c, d) {
 return c*((t=t/d-1)*t*t*t*t + 1) + b;
};
easeInOutQuint = function (t, b, c, d) {
 if ((t/=d/2) &lt; 1) return c/2*t*t*t*t*t + b;
 return c/2*((t-=2)*t*t*t*t + 2) + b;
};
easeInSine = function (t, b, c, d) {
 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
};
easeOutSine = function (t, b, c, d) {
 return c * Math.sin(t/d * (Math.PI/2)) + b;
};
easeInOutSine = function (t, b, c, d) {
 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
};
easeInExpo = function (t, b, c, d) {
 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
};
easeOutExpo = function (t, b, c, d) {
 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
};
easeInOutExpo = function (t, b, c, d) {
 if (t==0) return b;
 if (t==d) return b+c;
 if ((t/=d/2) &lt; 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
};
easeInCirc = function (t, b, c, d) {
 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
};
easeOutCirc = function (t, b, c, d) {
 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
};
easeInOutCirc = function (t, b, c, d) {
 if ((t/=d/2) &lt; 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
};
//a: amplitude (optional), p: period (optional)
easeInElastic = function (t, b, c, d, a, p) {
 if (t==0) {
  return b; 
 } 
 if ((t/=d)==1) {
  return b+c;  
 }
 if (!p) {
  p=d*.3;
 }
 if (a &lt; Math.abs(c)) {
   a=c; 
   s=p/4; 
 }
 else {
  a=Math.abs(c);
  s = p/(2*Math.PI) * Math.asin(c/a);
 }
 
 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
};
easeOutElastic = function (t, b, c, d, a, p) {
 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
 if (a &lt; Math.abs(c)) { a=c; var s=p/4; }
 else {   a=Math.abs(c); var s = p/(2*Math.PI) * Math.asin (c/a);}
 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
};
easeInOutElastic = function (t, b, c, d, a, p) {
 if (t==0) return b;  
 if ((t/=d/2)==2) return b+c;  
 if (!p) p=d*(.3*1.5);
 if (a &lt; Math.abs(c)) { 
  a=c; var s=p/4; 
 }
 else {
  a=Math.abs(c);
  var s = p/(2*Math.PI) * Math.asin (c/a);
 }
 if (t &lt; 1) {
  return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
 }
 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
};
easeInBack = function (t, b, c, d, s) {
 if (s == undefined) s = 1.70158;
 return c*(t/=d)*t*((s+1)*t - s) + b;
};
easeOutBack = function (t, b, c, d, s) {
 if (s == undefined) s = 1.70158;
 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
};
easeInOutBack = function (t, b, c, d, s) {
 if (s == undefined) s = 1.70158; 
 if ((t/=d/2) &lt; 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
};
easeInBounce = function (t, b, c, d) {
 return c - easeOutBounce (d-t, 0, c, d) + b;
};
easeOutBounce = function (t, b, c, d) {
 if ((t/=d) &lt; (1/2.75)) {
  return c*(7.5625*t*t) + b;
 } else if (t &lt; (2/2.75)) {
  return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
 } else if (t &lt; (2.5/2.75)) {
  return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
 } else {
  return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
 }
};
easeInOutBounce = function (t, b, c, d) {
 if (t &lt; d/2) return easeInBounce (t*2, 0, c, d) * .5 + b;
 return easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
};
function Motion(type) {
var start=150;
var end=250;
var duration=1500;
var fps     =15;
var elm=document.getElementById('bluesquareMotion');
if (type=='high') fps=35;
if (type=='low')  fps=6;
if (type=='slow')  duration=6000;
if (type=='fast')  duration=600;
var prop=document.getElementById('prop').value;
if (type=='fadeIn')  {start=0; end=1;prop='opacity';}
if (type=='fadeOut')  {start=1; end=0; prop='opacity';}
if (type=='slideIn')  {start=0; end=250; prop='height';}
if (type=='slideOut')  {start=250; end=0;prop='height';}
if (prop=='fontSize')  {start=15; end=30;}
var easing=document.getElementById('easetype').value;
animate2(elm,prop,start,end,duration,fps,easing);
}
function resetDiv() {
var elm=document.getElementById('bluesquareMotion');
elm.style.height="150px";
elm.style.width='150px';
elm.style.backgroundColor='blue';
elm.style.top='0px';
elm.style.left='0px';
elm.style.fontSize='15px';
if(!window.attachEvent) elm.style.opacity=1;
else  elm.style.filter = "alpha(opacity=100)";
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="bluesquareMotion" style="background-color: blue; color: white; font-size: 15px; height: 150px; position: relative; width: 150px;"&gt;
&lt;br /&gt;
Cool Text&lt;/div&gt;
&lt;form&gt;
&lt;select id="easetype"&gt;
&lt;option value="easeInBounce"&gt;InBounce&lt;/option&gt;
&lt;option value="linear"&gt;Linear&lt;/option&gt;
&lt;option value="easeInOutBounce"&gt;InOutBounce&lt;/option&gt;
&lt;option value="easeOutBounce"&gt;OutBounce&lt;/option&gt;
&lt;option value="easeInOutBack"&gt;InOutBack&lt;/option&gt;
&lt;option value="easeOutBack"&gt;OutBack&lt;/option&gt;
&lt;option value="easeInBack"&gt;InBack&lt;/option&gt;
&lt;option value="easeInOutElastic"&gt;InOutElastic&lt;/option&gt;
&lt;option value="easeOutElastic"&gt;OutElastic&lt;/option&gt;
&lt;option value="easeInElastic"&gt;InElastic&lt;/option&gt;
&lt;option value="easeInOutCirc"&gt;InOutCirc&lt;/option&gt;
&lt;option value="easeOutCirc"&gt;OutCirc&lt;/option&gt;
&lt;option value="easeInCirc"&gt;InCirc&lt;/option&gt;
&lt;option value="easeInOutExpo"&gt;InOutExpo&lt;/option&gt;
&lt;option value="easeOutExpo"&gt;OutExpo&lt;/option&gt;
&lt;option value="easeInExpo"&gt;InExpo&lt;/option&gt;
&lt;option value="easeInOutSine"&gt;InOutSine&lt;/option&gt;
&lt;option value="easeOutSine"&gt;OutSine&lt;/option&gt;
&lt;option value="easeInSine"&gt;InSine&lt;/option&gt;
&lt;option value="easeInOutQuint"&gt;InOutQuint&lt;/option&gt;
&lt;option value="easeOutQuint"&gt;OutQuint&lt;/option&gt;
&lt;option value="easeInQuint"&gt;InQuint&lt;/option&gt;
&lt;option value="easeInOutQuart"&gt;InOutQuart&lt;/option&gt;
&lt;option value="easeOutQuart"&gt;OutQuart&lt;/option&gt;
&lt;option value="easeInQuart"&gt;InQuart&lt;/option&gt;
&lt;option value="easeOutCubic"&gt;OutCubic&lt;/option&gt;
&lt;option value="easeInCubic"&gt;InCubic&lt;/option&gt;
&lt;/select&gt;

&lt;select id="prop"&gt;
&lt;option value="width"&gt;width&lt;/option&gt;
&lt;option value="height"&gt;height&lt;/option&gt;
&lt;option value="top"&gt;top&lt;/option&gt;
&lt;option value="left"&gt;left&lt;/option&gt;
&lt;option value="opacity"&gt;opacity&lt;/option&gt;
&lt;option value="fontSize"&gt;font-size&lt;/option&gt;
&lt;/select&gt;&lt;/form&gt;
&lt;a href="javascript:void(0)" onclick="resetDiv()"&gt;reset&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion()"&gt;Normal motion&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('high')"&gt;Normal motion  high quality&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('low')"&gt;Normal motion low quality&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('slow')"&gt;Slow motion&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('fast')"&gt;Fast motion&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('fadeIn')"&gt;Fade In&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('fadeOut')"&gt;Fade Out&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('slideIn')"&gt;SlideIn&lt;/a&gt;&lt;br /&gt;
&lt;a href="javascript:void(0)" onclick="Motion('slideOut')"&gt;SlideOut&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Easing equations&lt;/h3&gt;
&lt;br /&gt;
I hope you enjoyed this little basic effects because we will see how to do even more soon!&lt;br /&gt;
If you remember the last entry about easing, we have seen that everything was in relation with some core elements:&lt;br /&gt;
- object to animate&lt;br /&gt;
- start&lt;br /&gt;
- end
- duration&lt;br /&gt;
&lt;br /&gt;
From there we could built some other elements:&lt;br /&gt;
&lt;br /&gt;
- object's property (we shall say properties soon!)&lt;br /&gt;
- frame per second or fps&lt;br /&gt;
- change in animation being the end-start&lt;br /&gt;
&lt;br /&gt;
All these elements are linked thru one basic liner equation:&lt;br /&gt;
property value =(change/duration)*frame + start&lt;br /&gt;
or&lt;br /&gt;
y=mx+b&lt;br /&gt;
Where m is (change/duration) or c/d&lt;br /&gt;
&lt;br /&gt;
We know that this is the shortest path to go from the start to the end as this equation will draw a line but we also know that life is not a straight line but something curved, changing all the time !&lt;br /&gt;
&lt;br /&gt;
We tried to change the equation to something else by keeping the proportions of the equation, which means that if we had somewhere, we must remove somewhere else.&lt;br /&gt;
&lt;br /&gt;
y=m*x*(x/d)+b&lt;br /&gt;
&lt;br /&gt;
This is not a straight line but a curved line and that correspond to a quadratic easing !&lt;br /&gt;
If you multiply again by (x/d), it will be quintic...&lt;br /&gt;
We could create our own functions and I'm sure you will but let's for now, use the equations from &lt;a href="http://robertpenner.com/"&gt;Robert Penner&lt;/a&gt; from whom I have learn a lot !&lt;br /&gt;
He has spent a lot of time finding some cool equations creating effects, they are all based upon the following components:&lt;br /&gt;
- frame (time or t)&lt;br /&gt;
- change (c)&lt;br /&gt;
- start (begin or b)&lt;br /&gt;
- duration (d)&lt;br /&gt;
&lt;br /&gt;
As it's not about reinventing the wheel all the time, we will use them!&lt;br /&gt;
I have kept Robert Penner abbreviation as you will certainly find them in many javascript frameworks like mootools, jQuery and the like !&lt;br /&gt;
So here we go!&lt;br /&gt;
&lt;pre&gt;easeInQuad = function (t, b, c, d) {
 return c*(t/=d)*t + b;
};
easeOutQuad = function (t, b, c, d) {
 return -c *(t/=d)*(t-2) + b;
};
easeInOutQuad = function (t, b, c, d) {
 if ((t/=d/2) &amp;lt; 1) return c/2*t*t + b;
 return -c/2 * ((--t)*(t-2) - 1) + b;
};
easeInCubic = function (t, b, c, d) {
 return c*(t/=d)*t*t + b;
};
easeOutCubic = function (t, b, c, d) {
 return c*((t=t/d-1)*t*t + 1) + b;
};
easeInOutCubic = function (t, b, c, d) {
 if ((t/=d/2) &amp;lt; 1) return c/2*t*t*t + b;
 return c/2*((t-=2)*t*t + 2) + b;
};
easeInQuart = function (t, b, c, d) {
 return c*(t/=d)*t*t*t + b;
};
easeOutQuart = function (t, b, c, d) {
 return -c * ((t=t/d-1)*t*t*t - 1) + b;
};
easeInOutQuart = function (t, b, c, d) {
 if ((t/=d/2) &amp;lt; 1) return c/2*t*t*t*t + b;
 return -c/2 * ((t-=2)*t*t*t - 2) + b;
};
easeInQuint = function (t, b, c, d) {
 return c*(t/=d)*t*t*t*t + b;
};
easeOutQuint = function (t, b, c, d) {
 return c*((t=t/d-1)*t*t*t*t + 1) + b;
};
easeInOutQuint = function (t, b, c, d) {
 if ((t/=d/2) &amp;lt; 1) return c/2*t*t*t*t*t + b;
 return c/2*((t-=2)*t*t*t*t + 2) + b;
};
easeInSine = function (t, b, c, d) {
 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
};
easeOutSine = function (t, b, c, d) {
 return c * Math.sin(t/d * (Math.PI/2)) + b;
};
easeInOutSine = function (t, b, c, d) {
 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
};
easeInExpo = function (t, b, c, d) {
 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
};
easeOutExpo = function (t, b, c, d) {
 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
};
easeInOutExpo = function (t, b, c, d) {
 if (t==0) return b;
 if (t==d) return b+c;
 if ((t/=d/2) &amp;lt; 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
};
easeInCirc = function (t, b, c, d) {
 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
};
easeOutCirc = function (t, b, c, d) {
 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
};
easeInOutCirc = function (t, b, c, d) {
 if ((t/=d/2) &amp;lt; 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
};
//a: amplitude (optional), p: period (optional)
easeInElastic = function (t, b, c, d, a, p) {
 if (t==0) { return b; } 
 if ((t/=d)==1) { return b+c; }
 if (!p) { p=d*.3; }
 if (a &amp;lt; Math.abs(c)) {  a=c; s=p/4; }
 else { a=Math.abs(c); s = p/(2*Math.PI) * Math.asin(c/a);}
 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
};
easeOutElastic = function (t, b, c, d, a, p) {
 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
 if (a &amp;lt; Math.abs(c)) { a=c; var s=p/4; }
 else {   a=Math.abs(c); var s = p/(2*Math.PI) * Math.asin (c/a);}
 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
};
easeInOutElastic = function (t, b, c, d, a, p) {
 if (t==0) return b;  
 if ((t/=d/2)==2) return b+c;  
 if (!p) p=d*(.3*1.5);
 if (a &amp;lt; Math.abs(c)) { a=c; var s=p/4; }
 else {a=Math.abs(c);var s = p/(2*Math.PI) * Math.asin (c/a);}
 if (t &amp;lt; 1) {return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;}
 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
};
easeInBack = function (t, b, c, d, s) {
 if (s == undefined) s = 1.70158;
 return c*(t/=d)*t*((s+1)*t - s) + b;
};
easeOutBack = function (t, b, c, d, s) {
 if (s == undefined) s = 1.70158;
 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
};
easeInOutBack = function (t, b, c, d, s) {
 if (s == undefined) s = 1.70158; 
 if ((t/=d/2) &amp;lt; 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
};
easeInBounce = function (t, b, c, d) {
 return c - easeOutBounce (d-t, 0, c, d) + b;
};
easeOutBounce = function (t, b, c, d) {
 if ((t/=d) &amp;lt; (1/2.75)) { return c*(7.5625*t*t) + b;} 
        else if (t &amp;lt; (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;} 
        else if (t &amp;lt; (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;}
        else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; }
};
easeInOutBounce = function (t, b, c, d) {
 if (t &amp;lt; d/2) return easeInBounce (t*2, 0, c, d) * .5 + b;
 return easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
};
&lt;/pre&gt;
&lt;br /&gt;
Wow, this was huge!&lt;br /&gt;
Finding evolutions to the animation thru equations might not be as easy but it gives you full control of what you want to do!&lt;br /&gt;
Remember that all these functions start from only one equation:&lt;br /&gt;
y=mx+b&lt;br /&gt;
So don't fear to try yourself!&lt;br /&gt;
3D games and much complexed animations are all based upon equations related to physics.&lt;br /&gt;
Why not had a friction coefficient ? an hypothetic wind ? some random evolutions too ?

&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
I guess the animation function is starting to be interesting but as always, there are still many drawbacks:&lt;br /&gt;
- You can not animate several properties of an element! It's one property at a time.&lt;br /&gt;
- We do not cover all the properties possible like colors, borders and a bunch of other css properties!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-9148453650270531007?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/9148453650270531007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=9148453650270531007' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9148453650270531007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/9148453650270531007'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/javascript-animation-make-things-move.html' title='Javascript Animation : Make things move smoothly (4)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-4850388359508283430</id><published>2007-10-01T21:49:00.002+09:00</published><updated>2010-09-28T11:57:34.144+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : take it ease-y ! (3,)</title><content type='html'>&lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-simple-easing.html" title="javascript animation:basics of easing"&gt;Javascript Animation : basics of easing&lt;/a&gt; and &lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-controlling-time-2.html" title="javascript animation: controlling time"&gt;Javascript : Controlling time&lt;/a&gt; entries developed some basics of what is easing and how to apply duration and frames to an animation. 
&lt;br /&gt;
&lt;br /&gt;
In the first entry, we've seen how to create an easing out that will expand the width of a div quickly at the beginning and slowly at the end.&lt;br /&gt;
But we noticed that we didn't have any control over the time the animation will take and the second entry tries to answer this problem in a simple way. We were able to manipulate different properties of the div such as its width, height, opacity, left and top position thru an number of frames and a duration.&lt;br /&gt;
&lt;br /&gt;
But... &lt;br /&gt;
We forgot about easing !&lt;br /&gt;
Let's see the actual function.&lt;br /&gt;
&lt;h3&gt;
The animation function&lt;/h3&gt;
&lt;br /&gt;
&lt;pre&gt;function animate(elm,prop,begin,end,duration,fps) {

     if(!duration) duration=1000;
     if(!fps) fps = 12;

     var change       = end-begin;
     var interval     = Math.ceil(1000/fps);
     var totalFrames  = Math.ceil(duration/interval);
     var fixedStep    = change/totalFrames;
            
     for(i=1;i&amp;lt;=totalFrames;i++) {
        (function() {
           var frame=i;
           function inner() {
              var actualValue=begin+fixedStep*frame;

              unit=(elm=='opacity') ? '' : 'px';
              if(window.attachEvent &amp;amp;&amp;amp; !unit) { 
                  actualValue*=100; 
                  obj.style.zoom = 1;
                  obj.style.filter = "alpha(opacity=" + actualValue + ")";
              } else {
                  obj.style[elm]  = actualValue+unit; 
              }
           }
           timer = setTimeout(inner,interval*frame);
        })();
    }
}
//example
animate(document.getElementById('bluesquare'),'width',150,400,1500,20);
&lt;/pre&gt;
You can find how this function works with some examples in the &lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-controlling-time-2.html" title="javascript animation: controlling time"&gt;Javascript : Controlling time&lt;/a&gt;  entry.&lt;br /&gt;
So, this function is basically adding a fix value to the property over time.&lt;br /&gt;
Let's suppose that we want to animate the width property of a div from 150px to 400px in 1.5 seconds with a 12 frames per second base, this is how the change will happen:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;begin         = 150;
end           = 400;
change        = end-begin         = 400 - 150 = 250;
interval      = 1000/frames       = 1000/20   = 50;
total frames  = duration/interval = 1500/ 50  = 30;
fix value added per frame         = change/total frames = 250/30 = 8.33333..
&lt;/pre&gt;
&lt;br /&gt;
So, we'll have a width changing from 150 to 400 pixels within 1500 milliseconds, separated by 30 frames of 50 milliseconds each, adding 8.3334 pixels&lt;br /&gt;
This is how then, we were calculating the new value of the width thru each frames : &lt;br /&gt;
&lt;pre&gt;var actualValue = begin+step*frame;
//first frame
var actualValue = 150 + 8.333*1  = 158.333
//second frame
var actualValue = 150 + 8.333*2  = 166.666
//third frame
var actualValue = 150 + 8.333*3  = 174.999
&lt;/pre&gt;
As you can see, we are adding a fix value multiplied by the actual frame to the original width.&lt;br /&gt;
When the function we'll reach the last frame, the width will be equal to 400 pixels&lt;br /&gt;
&lt;br /&gt;
If you look at the calculation, we can see that the only value changing is the frame number, the actual time of the animation.&lt;br /&gt;
We can then write the general calculation for this animation like this:&lt;br /&gt;
&lt;pre&gt;actualValue = 150 + 8.3333*frame;
&lt;/pre&gt;
or...&lt;br /&gt;
&lt;pre&gt; v = 150 + 8.333*frame;
//or 
y = 150 +8.333*x;
&lt;/pre&gt;
&lt;br /&gt;
Noooooooo !!!&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Fear not !&lt;br /&gt;
You shall keep reading, even if it reminds you some of these hours where you felt like everything was going upside-down in your head !&lt;br /&gt;
This is going to be very easy!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Linear easing equation : The Graph shows it all&lt;/h3&gt;
&lt;br /&gt;
Yes, I used the E-word, this is an equation but a very easy one (I can understand it, to say !)&lt;br /&gt;
You've seen that the animation was quite mechanical and indeed, if you take this equation and trace a graph of it, 
you will get a beautiful straight line !&lt;br /&gt;
Check for yourself with this website and enter this :&lt;br /&gt;
150+8.333*x&lt;br /&gt;
&lt;a href="http://www.freemathhelp.com/equation-grapher.html" target="_blank"&gt; graph in new window&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.freemathhelp.com/equation-grapher.html"&gt; graph in same window&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
You should see this red line going straight !&lt;br /&gt;
In our animation code, y is equal to the value of the width and x is equal to the elapsed time expressed in frames.&lt;br /&gt;
So, the width (y) is a function of the time (x).&lt;br /&gt;
When looping thru the frames, the only unknown value is the the width that is calculated thanks to the frame.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Why Trying to get some curve ?&lt;/h3&gt;
&lt;br /&gt;
Before going further with this equation, we should perhaps remember what is so cool about easing.&lt;br /&gt;
Perhaps some of you are happy with the way the actual function perform the interpolation thru A to B, but don't you feel this is too clean ? too predictable ? too mechanical ?&lt;br /&gt;
In our last entry about controlling time, we took the example of a runner targeting 120 meters in 15 seconds.&lt;br /&gt;
We then calculated the average ratio, our runner should run per second to get from 0 to 120 meters within this 15 seconds.&lt;br /&gt;
&lt;pre&gt;var ratio = 120/15 = 8m/s 
&lt;/pre&gt;
So, our runner shall run with a constant speed of 8 meters per second...&lt;br /&gt;
That's theoretical, mathematical but is it really realistic ?&lt;br /&gt;
If we change the meters into kilometers, is our runner being able to keep with a constant speed ?&lt;br /&gt;
He will certainly start at a slow speed at the beginning to keep some of his strength and speed up at the very end to be the first&lt;br /&gt;
In the meantime, he might be tired, get a sudden strength boosting him up, making its speed going up/down.&lt;br /&gt;
&lt;br /&gt;
I guess that almost everything that moves is doing so with a speed that changes over time.&lt;br /&gt;
This is something natural and average should be kept for statistics.&lt;br /&gt;
Human eyes is used to see things change of speed in their run and that's the way we feel that this has to be 'real'.&lt;br /&gt;
&lt;br /&gt;
Our calculation is everything but 'natural' or even closed to be !&lt;br /&gt;
In fact, it will never be but we can make it a little bit more natural by some calculations that will allow us to vary the ratio over time and thus, creating the Ease that will make it live !&lt;br /&gt;
With the first calculation, we were going straight to the point.&lt;br /&gt;
With easing, we will take a curved path to go to the same point!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Trying to get some life !&lt;/h3&gt;
&lt;br /&gt;
Now, it's time to play with this equation a little !&lt;br /&gt;
We are trying to add some calculation to the equation and see what we get:&lt;br /&gt;
y=150+8.333*x-((20*x)/x);&lt;br /&gt;
&lt;br /&gt;
Don't try to understand why I have done this because I do not even know myself !&lt;br /&gt;
It's just an experimentation and you can copy and paste this into the above link and see how it goes!&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function animate2(obj,elm,begin,end, duration, fps) {

        if(!duration) duration = 1000;
        if(!fps) fps = 20;

  begin=parseFloat(begin);
  end=parseFloat(end);
  duration=parseFloat(duration);
        fps=parseFloat(fps);

        var change      = end-begin;
        var interval    = Math.ceil(1000/fps);
        var totalframes = Math.ceil(duration/interval);
        var step        = change/totalframes;

        var start=new Date().getTime();
        document.getElementById('gnl_info3').innerHTML='entered value:&lt;br /&gt;begin position='+begin+'&lt;br /&gt;end position='+end+'&lt;br /&gt; duration='+duration+'&lt;br /&gt;fps:'+fps+'&lt;br /&gt;&lt;br /&gt;';
        document.getElementById('gnl_info4').innerHTML='calculated value:&lt;br /&gt;change:'+change+'&lt;br /&gt;interval:'+interval+'&lt;br /&gt; total frames:'+totalframes+'&lt;br /&gt; steps:'+step;

 for(i=1;i &lt;= totalframes;i++) {
     (function() {
         var frame=i;
         function innerChangeWidth() {

             var looping=new Date().getTime();
             var bet=looping-start;
             document.getElementById('between_time2').innerHTML='elapsed time='+bet+'&lt;br /&gt;';

             var increase=begin+(change/totalframes)*frame-(20*frame/frame);;

             document.getElementById('actual_value2').innerHTML='actual value='+increase;
             if(frame==totalframes) {
                document.getElementById('end_time2').innerHTML='The animation has end';
             }
             unit=(elm=='opacity') ? '' : 'px';
             if(window.attachEvent &amp;&amp; !unit) { 
                  increase*=100; 
                  obj.style.zoom = 1;
                  obj.style.filter = "alpha(opacity=" + increase + ")";
              } else {
                     obj.style[elm]  = increase+unit; 
              }
    }
    timer = setTimeout(innerChangeWidth,interval*frame);
              })();
 }
}

function doIt2() {
var prop=document.getElementById('prop').value;
var start=document.getElementById('start').value;
var end=document.getElementById('end').value;
var duration=document.getElementById('duration').value;
var fps=document.getElementById('fps').value;
animate2(document.getElementById('bluesquare3'),prop,start,end,duration,fps);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="bluesquare3" style="background-color: blue; height: 150px; position: relative; width: 150px;"&gt;
&lt;/div&gt;
&lt;form&gt;
&lt;select id="prop"&gt;
&lt;option value="height"&gt;height&lt;/option&gt;
&lt;option value="width"&gt;width&lt;/option&gt;
&lt;option value="top"&gt;top&lt;/option&gt;
&lt;option value="left"&gt;left&lt;/option&gt;
&lt;option value="opacity"&gt;opacity&lt;/option&gt;
&lt;/select&gt;
Start:&lt;input id="start" type="text" value="150" /&gt;&lt;br /&gt;
End:&lt;input id="end" type="text" value="250" /&gt;&lt;br /&gt;
Duration:&lt;input id="duration" type="text" value="1000" /&gt;&lt;br /&gt;
FPS:&lt;input id="fps" type="text" value="12" /&gt;&lt;/form&gt;
&lt;a href="javascript:void(0)" onclick="doIt2()"&gt;test&lt;/a&gt;
&lt;br /&gt;
&lt;div id="gnl_info3"&gt;
&lt;/div&gt;
&lt;div id="gnl_info4"&gt;
&lt;/div&gt;
&lt;div id="between_time2"&gt;
&lt;/div&gt;
&lt;div id="actual_value2"&gt;
&lt;/div&gt;
&lt;div id="end_time3"&gt;
&lt;/div&gt;
&lt;div id="end_time2"&gt;
&lt;/div&gt;
&lt;br /&gt;
You can see the value changing thru each frame.&lt;br /&gt;
What is important to notice is that you have the animation going back a little and then keeping its way.&lt;br /&gt;
This could be a kind of easing but if you look at the final value, you will see that it doesn't  reach the one set !&lt;br /&gt;
So it's not exactly what we want...&lt;br /&gt;
&lt;br /&gt;
In fact, we need to keep things related to the frame which multiply the constant.&lt;br /&gt;
Remember that we want to go from A to B by taking different paths.&lt;br /&gt;
We need therefore to keep things proportional to the main factor on which the value depends on : the time/frame.&lt;br /&gt;
By the way, we should perhaps change this constant back to what is was:&lt;br /&gt;
&lt;pre&gt;var step        = change/totalframes;
var actualValue = begin + step*frame;
//becomes 
var actualValue = begin + (change/totalframes)*frame;
&lt;/pre&gt;
The more constant we have, the more we'll be able to change their value during the process and create different easing type!&lt;br /&gt;
&lt;br /&gt;
Ok, let's implement a basic easing out:&lt;br /&gt;
&lt;pre&gt;var actualValue=(change*frame/totalframes)*(frame/totalframes)+begin;
&lt;/pre&gt;
You should try to see the corresponding graph with the settings above:&lt;br /&gt;
250*((x/30)*(x/30))+150&lt;br /&gt;
and the original one:&lt;br /&gt;
150+(250/30)*x&lt;br /&gt;
You can see that the new equation is curved but more importantly, you can see
that the two lines intersect at exactly the same point:&lt;br /&gt;
The final width!&lt;br /&gt;
We are just taking a different path, that's all.&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function animate(obj,elm,begin,end, duration, fps) {

        if(!duration) duration = 1000;
        if(!fps) fps = 20;

  begin=parseFloat(begin);
  end=parseFloat(end);
  duration=parseFloat(duration);
        fps=parseFloat(fps);

        var change      = end-begin;
        var interval    = Math.ceil(1000/fps);
        var totalframes = Math.ceil(duration/interval);
        var step        = change/totalframes;

        var start=new Date().getTime();
        document.getElementById('gnl_info').innerHTML='entered value:&lt;br /&gt;begin position='+begin+'&lt;br /&gt;end position='+end+'&lt;br /&gt; duration='+duration+'&lt;br /&gt;fps:'+fps+'&lt;br /&gt;&lt;br /&gt;';
        document.getElementById('gnl_info10').innerHTML='calculated value:&lt;br /&gt;change:'+change+'&lt;br /&gt;interval:'+interval+'&lt;br /&gt; total frames:'+totalframes+'&lt;br /&gt; steps:'+step;

 for(i=1;i &lt;= totalframes;i++) {
     (function() {
         var frame=i;
         function innerChangeWidth() {

             var looping=new Date().getTime();
             var bet=looping-start;
             document.getElementById('between_time2').innerHTML='elapsed time='+bet+'&lt;br /&gt;';

             var increase=easeQuad(begin,change,totalframes,frame);

             document.getElementById('actual_value').innerHTML='actual value='+increase;
             if(frame==totalframes) {
                document.getElementById('end_time').innerHTML='The animation has end';
             }
             unit=(elm=='opacity') ? '' : 'px';
             if(window.attachEvent &amp;&amp; !unit) { 
                  increase*=100; 
                  obj.style.zoom = 1;
                  obj.style.filter = "alpha(opacity=" + increase + ")";
              } else {
                     obj.style[elm]  = increase+unit; 
              }
    }
    timer = setTimeout(innerChangeWidth,interval*frame);
              })();
 }
}
function easeQuad(begin,change,totalframes,frame) {
 var s= (change*frame/totalframes)*(frame/totalframes)+begin;
document.getElementById('end_time10').innerHTML='actual ratio:'+s;
 return s;
}
function doIt() {
var prop=document.getElementById('prop2').value;
var start=document.getElementById('start2').value;
var end=document.getElementById('end2').value;
var duration=document.getElementById('duration2').value;
var fps=document.getElementById('fps2').value;
animate(document.getElementById('bluesquare'),prop,start,end,duration,fps);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="bluesquare" style="background-color: blue; height: 150px; position: relative; width: 150px;"&gt;
&lt;/div&gt;
&lt;form&gt;
&lt;select id="prop2"&gt;
&lt;option value="height"&gt;height&lt;/option&gt;
&lt;option value="width"&gt;width&lt;/option&gt;
&lt;option value="top"&gt;top&lt;/option&gt;
&lt;option value="left"&gt;left&lt;/option&gt;
&lt;option value="opacity"&gt;opacity&lt;/option&gt;
&lt;/select&gt;
Start:&lt;input id="start2" type="text" value="150" /&gt;&lt;br /&gt;
End:&lt;input id="end2" type="text" value="250" /&gt;&lt;br /&gt;
Duration:&lt;input id="duration2" type="text" value="1000" /&gt;&lt;br /&gt;
FPS:&lt;input id="fps2" type="text" value="12" /&gt;&lt;/form&gt;
&lt;a href="javascript:void(0)" onclick="doIt()"&gt;test&lt;/a&gt;
&lt;br /&gt;
&lt;div id="gnl_info"&gt;
&lt;/div&gt;
&lt;div id="gnl_info10"&gt;
&lt;/div&gt;
&lt;div id="between_time"&gt;
&lt;/div&gt;
&lt;div id="actual_value"&gt;
&lt;/div&gt;
&lt;div id="end_time"&gt;
&lt;/div&gt;
&lt;div id="end_time10"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
If we want to create different easing, we should get the calculation of the actual value outside of the main function:&lt;br /&gt;
&lt;pre&gt;function animate(obj,elm,begin,end, duration, fps) {

  if(!duration) duration = 1000;
  if(!fps)      fps      = 20;

  begin     = parseFloat(begin);
  end       = parseFloat(end);
  duration  = parseFloat(duration);
  fps       = parseFloat(fps);

  var change      = end-begin;
  var interval    = Math.ceil(1000/fps);
  var totalframes = Math.ceil(duration/interval);
  var step        = change/totalframes;


  for(i=1;i &amp;lt; = totalframes;i++) {
    (function() {
        var frame=i;
        function inner() {
            var increase=easeQuad(begin,change,totalframes,frame);
            unit=(elm=='opacity') ? '' : 'px';
            if(window.attachEvent &amp;amp;&amp;amp; !unit) { 
                increase*=100; 
                obj.style.zoom = 1;
                obj.style.filter = "alpha(opacity=" + increase + ")";
            } else {
                obj.style[elm]  = increase+unit; 
            }
       }
       timer = setTimeout(inner,interval*frame);
    })();
  }
}
function easeQuad(begin,change,totalframes,frame) {
 return (change*frame/totalframes)*(frame/totalframes)+begin;
}
&lt;/pre&gt;
By putting the calculation outside, we'll be able to set different easing as callback functions&lt;br /&gt;
You will be then able to apply your flavor of easing by adding the function you want to use!&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
We've seen how to create some easing from the function we created&lt;br /&gt;
We don't have that much possibilities for now so we'll see this in an other entry but don't forget to try to find some cool easing and share with everyone!&lt;br /&gt;
As for the function, it is still limited as we cannot apply more than one property at a time, it could be nice to be able to change the width, height, left,top and opacity properties in the same time to have something really interesting.&lt;br /&gt;
I'll write an other entry about some other functionalities!&lt;br /&gt;
Have fun with graphs and equations!&lt;br /&gt;
(I've never thought I will say such a thing one day!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-4850388359508283430?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/4850388359508283430/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=4850388359508283430' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4850388359508283430'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4850388359508283430'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/10/javascript-animation-take-it-ease-y-3.html' title='Javascript Animation : take it ease-y ! (3,)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-4299189016836088312</id><published>2007-09-29T18:03:00.001+09:00</published><updated>2010-09-28T11:57:34.144+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript animation'/><category scheme='http://www.blogger.com/atom/ns#' term='effects'/><title type='text'>Javascript Animation : Controlling time (2)</title><content type='html'>As we've seen in the entry &lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-simple-easing.html" title="javascript animation, basics of easing"&gt;basics of easing&lt;/a&gt;,
we can apply very basic animations to a div by
increasing its width.&lt;br /&gt;
We could change other properties like its height, opacity
or color if we want, allowing some nice effects like 
fade in, fade out or slide in, slide out...&lt;br /&gt;
&lt;br /&gt;
However,the animation didn't offer any control over the 
time required to reach the final width.&lt;br /&gt;
It will end when it will end !&lt;br /&gt;
This is fine if you don't need too complexed animations
but being able to set the duration of the animation could be nice !&lt;br /&gt;
&lt;br /&gt;
We will see in this entry how to control the time of the animation developed 
in &lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-simple-easing.html" title="javascript animation, basics of easing"&gt;basics of easing&lt;/a&gt;
&lt;br /&gt;
&lt;h2&gt;
What is an animation ?&lt;/h2&gt;
&lt;br /&gt;
If we go back a little and think about what is an animation,
we could say that an animation offers the evolution of a value over time.&lt;br /&gt;
Basically, an animation starts, change something and ends.&lt;br /&gt;
the time between the starts and the end is the duration&lt;br /&gt;
So an animation will be:&lt;br /&gt;
&lt;br /&gt;
- a subject to animate&lt;br /&gt;
- a start point&lt;br /&gt;
- a end point&lt;br /&gt;
- a duration&lt;br /&gt;
Let's take an example to understand a bit more what an animation involves.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Run Forest...&lt;/h3&gt;
&lt;br /&gt;
Let's say you want to run 120 meters in 15 seconds.&lt;br /&gt;
- The start line represents the beginning, 0 meter.&lt;br /&gt;
- The arrival point represents the end, 100th meter.&lt;br /&gt;
- The change between the start and the end is: chane=end-start,120-0=120&lt;br /&gt;
(In that case, the change is equal to the end)&lt;br /&gt;
- 15 seconds represent the duration.&lt;br /&gt;
If you want to reach 120 meters in 15 seconds, what is the number of meters(velocity)  you must run per second ?&lt;br /&gt;
velocity = end/duration = 120/15 = 8 m/s.&lt;br /&gt;
&lt;br /&gt;
We can then find back the reach point:&lt;br /&gt;
&lt;br /&gt;
end = duration*velocity = 15*8 = 120 meters&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Animation&lt;/h3&gt;
&lt;br /&gt;
Let's go back to our width animation by keeping in mind the runner 
example which gives a good idea of what is an animation, something in movement
over time.&lt;br /&gt;
if our square has a width of 150px and that we want to animate it
until 350px in 1000 milliseconds, we will have the following:&lt;br /&gt;
-start : 150&lt;br /&gt;
-end   : 350&lt;br /&gt;
-duration : 1000&lt;br /&gt;
We will need to increase the width by:&lt;br /&gt;
-change : 350-150=200&lt;br /&gt;
&lt;br /&gt;
- velocity = change/duration = 200/1000 = 0.2 px/ms.&lt;br /&gt;
We can then find back the reach point:&lt;br /&gt;
end = start + duration*velocity = 150+ 1000*0.2 = 350&lt;br /&gt;
&lt;br /&gt;
We calculate the velocity by dividing the change by the duration in milliseconds,
which give us the rise per millisecond of the width.&lt;br /&gt;
This can be a little bit too much to animate the width per milliseconds basis.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Movies&lt;/h3&gt;
A movie is a sequence of images placed one after an other.&lt;br /&gt;
Human eyes will feel the movement is fluid if within one second you have 24 images.&lt;br /&gt;
It means you don't have an image changing each milliseconds !&lt;br /&gt;
You have the following interval:&lt;br /&gt;
&lt;br /&gt;
interval=1000/24=41.66666666...&lt;br /&gt;
&lt;br /&gt;
It means that we have one image every 41 milliseconds.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Animation and frames&lt;/h3&gt;
We are going to use the same idea and use a rate that will give us the number of 
steps to perform the animation.&lt;br /&gt;
In our movie example, 24 is the number of steps or frames per second.&lt;br /&gt;
This is what you can add now;&lt;br /&gt;
- start : 150&lt;br /&gt;
- end   : 350&lt;br /&gt;
- change : 350-150=200&lt;br /&gt;
- duration : 1000&lt;br /&gt;
- frames/s : 20&lt;br /&gt;
&lt;br /&gt;
In that case, the interval will be :&lt;br /&gt;
&lt;br /&gt;
interval = duration/frames = 1000/20 = 50&lt;br /&gt;
&lt;br /&gt;
So what does it mean ?&lt;br /&gt;
In other words, we will have 20 frames (images for a movie) per second to create the animation.&lt;br /&gt;
which means that we'll animate every 50 milliseconds the width of the div 20 times or frames.&lt;br /&gt;
&lt;br /&gt;
And if I want my animation to last 1700 milliseconds with 20 frames per second ??&lt;br /&gt;
We can find the total number of frames very easily;&lt;br /&gt;
&lt;br /&gt;
interval per second = 1000/frames= 1000/20 = 50&lt;br /&gt;
frames required for the animation = duration/interval per second = 1700/50 = 34&lt;br /&gt;
&lt;br /&gt;
It means that to perform a 20 frames per second base animation over 1700 seconds, we will need 34 frames in total.&lt;br /&gt;
&lt;br /&gt;
This may seem a little bit confusing but let's see the code that will implement everything we have seen so far !&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
The code&lt;/h3&gt;
&lt;br /&gt;
&lt;br /&gt;
First let's see how we are going to use the function;&lt;br /&gt;
&lt;pre&gt;//general definition
function changeWith(elm,begin,end,duration,fps);
//example
changeWidth(document.getElementById('bluesquare'),150,400,1500,20);
&lt;/pre&gt;
&lt;br /&gt;
Our function takes as parameters everything we have seen so far.&lt;br /&gt;
So we will animate a element with an id of 'bluesquare' extends its width to 400px in
1 second and a half and with 20 frames per second.&lt;br /&gt;
Here is the html and css code:&lt;br /&gt;
&lt;br /&gt;
HTML+CSS:&lt;br /&gt;
&lt;pre&gt;&amp;lt;style type="text/css"&amp;gt;
#bluesquare {
width:150px;
height:150px;
background-color:blue;
}
&amp;lt;/style&amp;gt;
&amp;lt;div id="bluesquare"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
The javascript code&lt;/h3&gt;
&lt;br /&gt;
We first need to do some calculation with the value passed to the function.&lt;br /&gt;
If you remember, we were calculating interval, change, total number of frames...&lt;br /&gt;
&lt;pre&gt;function changeWidth(elm,begin,end,duration,fps) {

       var change      = end-begin;
       var interval    = 1000/fps;
       var totalFrames = duration/interval;
       var fixedStep   = change/totalFrames;

       //code continues...
}
changeWidth(document.getElementById('bluesquare'),150,400,1500,20);
&lt;/pre&gt;
&lt;br /&gt;
So first we calculate the difference between the start width and the end width.&lt;br /&gt;
In that case, it will be 400-150=250&lt;br /&gt;
Then we calculate the interval per second according to the frame rate.&lt;br /&gt;
(for a movie,we were calculating 24 images per second = 1000/24 =41.6666... milliseconds of interval between the images)&lt;br /&gt;
In that case, we will get 1000/20=50 milliseconds&lt;br /&gt;
As the animation last more than one seconds, the total of frames will differ from the frame per second rate, and we will get:&lt;br /&gt;
total frames = duration/interval = 1500/50 = 30&lt;br /&gt;
&lt;br /&gt;
In the end, we calculate a simple constant that will tell us how many pixels we must add at every frame, which is to say every 50 milliseconds, to reach the 400 pixels.&lt;br /&gt;
fixedStep=change/totalFrames=400/30 = 13.33333...

You can see that we have rounded the value of the interval.&lt;br /&gt;
We keep the fixedStep precise has it will help reach the final value of the animation.&lt;br /&gt;
&lt;br /&gt;
So what's next ??&lt;br /&gt;
We know that we will animate a total of 30 frames spaced by 50 milliseconds for a total of 1500 milliseconds.&lt;br /&gt;
Each frame will add 13.333 pixels to the total of the element width and reach 400px.&lt;br /&gt;
A loop that goes from 1 to 30 frames will just do the job!&lt;br /&gt;
&lt;pre&gt;//...
for(i=1;i &amp;lt;= totalFrames;i++) {

 (function() {
      var n = i;
      function innerChangeWidth() {
           var width        = begin+(fixedStep*n);
           elm.style.width  = width+'px';
      }
      timer = setTimeout(innerChangeWidth,interval*n);
  })();
}
&lt;/pre&gt;
So we are looping thru the number of frames.&lt;br /&gt;
We capture the value of the actual frame within an anonymous function.&lt;br /&gt;
Then we calculate the value of the width :&lt;br /&gt;
&lt;pre&gt;var width        = begin+(fixedStep*n);
first frame:
var width        = 150 + (13.3333*1) = 163.3333
second frame:
var width        = 150 + (13.3333*2)= 176.6666
....
&lt;/pre&gt;
and add it to the elem.&lt;br /&gt;
We put these calculations within a inner function as we are not applying the new width directly but according to the value of the interval.&lt;br /&gt;
Therefore we set the function to a setTimeout with a delay calculated according to the frame:&lt;br /&gt;
&lt;pre&gt;timer = setTimeout(innerChangeWidth,interval*n);
first frame:
timer = setTimeout(innerChangeWidth,50*1);
second frame:
timer = setTimeout(innerChangeWidth,50*2);
...
&lt;/pre&gt;
As you can see the interval will grow accordingly from 50 to 100, then 150 until 1500 that will be the end !&lt;br /&gt;
If you do not understand the anonymous function and the inner function, you can have a quick look at &lt;a href="http://shiriru.blogspot.com/2007/09/my-inner-request-for-outter.html" title="javascript closure : my inner request for outer"&gt;my inner request for outer&lt;/a&gt; that explains the basics of this.&lt;br /&gt;
If we glue the pieces together, this is what we get:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;function changeWidth(elm,begin,end,duration,fps) {

    var change      = end-begin;
    var interval    = Math.ceil(1000/fps);
    var totalFrames = Math.ceil(duration/interval);
    var fixedStep   = change/totalFrames;

    for(i=0;i &amp;lt; totalFrames;i++) {
     (function() {
         var n = i;
         function innerChangeWidth() {
              var width        = begin+(fixedStep*n);
              elm.style.width  = width+'px';
         }
         timer = setTimeout(innerChangeWidth,interval*n);
     })();
   }
}
&lt;/pre&gt;
&lt;h3&gt;
Finally some animations here!&lt;/h3&gt;
&lt;br /&gt;
It's been certainly boring some times or not very clear, but we can finally see the result of this function and if you came that far, I applaud !&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function animate(obj,elm,begin,end, duration, fps) {
        if(!duration) duration = 1000;
 if(!fps) fps = 20;
 var start=new Date().getTime();

        var change      = end-begin;
 var interval    = Math.ceil(1000/fps);
        var totalframes = Math.ceil(duration/interval);
 var step        = change/totalframes;
        document.getElementById('gnl_info').innerHTML='entered value:&lt;br /&gt;begin position='+begin+'&lt;br /&gt;end position='+end+'&lt;br /&gt; duration='+duration+'&lt;br /&gt;fps:'+fps+'&lt;br /&gt;&lt;br /&gt;';
        document.getElementById('gnl_info2').innerHTML='calculated value:&lt;br /&gt;change:'+change+'&lt;br /&gt;interval:'+interval+'&lt;br /&gt; total frames:'+totalframes+'&lt;br /&gt; steps:'+step;

 for(i=1;i &lt;= totalframes;i++) {
     (function() {
    var n=i;
    function innerChangeWidth() {
   var looping=new Date().getTime();
   var bet=looping-start;
   document.getElementById('between_time').innerHTML='elapsed time='+bet+'&lt;br /&gt;';
   var increase=begin+(step*n);
   document.getElementById('actual_value').innerHTML='actual value='+increase;
   if(n==totalframes) {
      document.getElementById('end_time').innerHTML='The animation has end';
   }
   unit=(elm=='opacity') ? '' : 'px';
                        if(window.attachEvent &amp;&amp; !unit) { 
                               increase*=100; 
                               obj.style.zoom = 1;
          obj.style.filter = "alpha(opacity=" + increase + ")";
                        } else {
              obj.style[elm]  = increase+unit; 
                        }
    }
    timer = setTimeout(innerChangeWidth,interval*n);
              })();
 }
}
function doIt() {
animate(document.getElementById('bluesquare'),'width',150,400,1500,12);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="bluesquare" style="background-color: blue; height: 150px; width: 150px;"&gt;
&lt;/div&gt;
&lt;a href="javascript:void(0)" onclick="doIt()"&gt;test&lt;/a&gt;
&lt;br /&gt;
&lt;div id="gnl_info"&gt;
&lt;/div&gt;
&lt;div id="gnl_info2"&gt;
&lt;/div&gt;
&lt;div id="between_time"&gt;
&lt;/div&gt;
&lt;div id="actual_value"&gt;
&lt;/div&gt;
&lt;div id="end_time"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
What's next ?&lt;/h3&gt;
&lt;br /&gt;
As you can see we have taken control over time !&lt;br /&gt;
This was a little bit long but I hope you have grasped the concepts.&lt;br /&gt;
We called this function 'changeWidth' but hey, why not make it a little bit more flexible ?&lt;br /&gt;
I guess we can do the following animations with very few changes:&lt;br /&gt;
&lt;br /&gt;
- width&lt;br /&gt;
- height&lt;br /&gt;
- left&lt;br /&gt;
- top&lt;br /&gt;
- opacity&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Refactoring the code&lt;/h4&gt;
As I told you, we can keep the same function and change just a few things:&lt;br /&gt;
&lt;pre&gt;function animate(elm,prop,begin,end,duration,fps) {

        if(!duration) duration=1000;
        if(!fps) fps = 12;

        var change       = end-begin;
        var interval     = Math.ceil(1000/fps);
        var totalFrames  = Math.ceil(duration/interval);
        var fixedStep    = change/totalFrames;
            
        for(i=1;i&amp;lt;=totalFrames;i++) {
           (function() {
              var n=i;
              function innerChangeWidth() {
                 var increase=begin+(step*n);
                 unit=(elm=='opacity') ? '' : 'px';
                 if(window.attachEvent &amp;amp;&amp;amp; !unit) { 
                      increase*=100; 
                      obj.style.zoom = 1;
                      obj.style.filter = "alpha(opacity=" + increase + ")";
                 } else {
                     obj.style[elm]  = increase+unit; 
                 }
             }
             timer = setTimeout(innerChangeWidth,interval*n);
           })();
       }
}
//example
animate(document.getElementById('bluesquare'),'width',150,400,1000,12);
//or 
animate(document.getElementById('bluesquare'),'width',150,400);
animate(document.getElementById('bluesquare'),'height',150,400);
animate(document.getElementById('bluesquare'),'top',0,100);
animate(document.getElementById('bluesquare'),'left',0,150);
animate(document.getElementById('bluesquare'),'opacity',0.2,0.8);
&lt;/pre&gt;
So what did we do ?&lt;br /&gt;
Well, we added one parameter,prop, to the function that is in charge of specifying the property on which the animation will work: width, height, top,left, opacity.&lt;br /&gt;
We set some default value to the duration and the fps.&lt;br /&gt;
There is may be an obscure part related to the opacity, but I will link to this subject later as it is just a cross-browser fix.&lt;br /&gt;
&lt;br /&gt;
We are now able to move the div, create a slide in, slide out, fade in, fade out,
slide in horizontal, slide out horizontal !&lt;br /&gt;
With one function !&lt;br /&gt;
&lt;br /&gt;
&lt;script type="text/javascript"&gt;
function animate2(obj,elm,begin,end, duration, fps) {
        if(!duration) duration = 1000;
        if(!fps) fps = 20;
        begin=parseFloat(begin);
        end=parseFloat(end);
        duration=parseFloat(duration);
        fps=parseFloat(fps);

        var start=new Date().getTime();
        var change      = end-begin;
        var interval    = Math.ceil(1000/fps);
        var totalframes = Math.ceil(duration/interval);
        var step        = change/totalframes;
        document.getElementById('gnl_info3').innerHTML='entered value:&lt;br /&gt;begin position='+begin+'&lt;br /&gt;end position='+end+'&lt;br /&gt; duration='+duration+'&lt;br /&gt;fps:'+fps+'&lt;br /&gt;&lt;br /&gt;';
        document.getElementById('gnl_info4').innerHTML='calculated value:&lt;br /&gt;change:'+change+'&lt;br /&gt;interval:'+interval+'&lt;br /&gt; total frames:'+totalframes+'&lt;br /&gt; steps:'+step;

 for(i=1;i &lt;= totalframes;i++) {
     (function() {
         var n=i;
         function innerChangeWidth() {
             var looping=new Date().getTime();
             var bet=looping-start;
             document.getElementById('between_time2').innerHTML='elapsed time='+bet+'&lt;br /&gt;';
             var increase=begin+(step*n);

             document.getElementById('actual_value2').innerHTML='actual value='+increase;
             if(n==totalframes) {
                document.getElementById('end_time2').innerHTML='The animation has end';
             }
             unit=(elm=='opacity') ? '' : 'px';
             if(window.attachEvent &amp;&amp; !unit) { 
                  increase*=100; 
                  obj.style.zoom = 1;
                  obj.style.filter = "alpha(opacity=" + increase + ")";
              } else {
                     obj.style[elm]  = increase+unit; 
              }
    }
    timer = setTimeout(innerChangeWidth,interval*n);
              })();
 }
}
function doIt2() {
var prop=document.getElementById('prop').value;
var start=document.getElementById('start').value;
var endi=document.getElementById('end').value;
var duration=document.getElementById('duration').value;
var fps=document.getElementById('fps').value;
animate2(document.getElementById('bluesquare3'),prop,start,endi,duration,fps);
}
&lt;/script&gt;
&lt;br /&gt;
&lt;div id="bluesquare3" style="background-color: blue; height: 150px; position: relative; width: 150px;"&gt;
&lt;/div&gt;
&lt;form&gt;
&lt;select id="prop"&gt;
&lt;option value="height"&gt;height&lt;/option&gt;
&lt;option value="width"&gt;width&lt;/option&gt;
&lt;option value="top"&gt;top&lt;/option&gt;
&lt;option value="left"&gt;left&lt;/option&gt;
&lt;option value="opacity"&gt;opacity&lt;/option&gt;

&lt;/select&gt;
Start:&lt;input id="start" type="text" value="150" /&gt;&lt;br /&gt;
End:&lt;input id="end" type="text" value="250" /&gt;&lt;br /&gt;
Duration:&lt;input id="duration" type="text" value="1000" /&gt;&lt;br /&gt;
FPS:&lt;input id="fps" type="text" value="12" /&gt;&lt;/form&gt;
&lt;a href="javascript:void(0)" onclick="doIt2()"&gt;test&lt;/a&gt;
&lt;br /&gt;
&lt;div id="gnl_info3"&gt;
&lt;/div&gt;
&lt;div id="gnl_info4"&gt;
&lt;/div&gt;
&lt;div id="between_time2"&gt;
&lt;/div&gt;
&lt;div id="actual_value2"&gt;
&lt;/div&gt;
&lt;div id="end_time2"&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
&lt;br /&gt;
In one function, we are now able to create different animations that will work on different properties, have a desired duration and frames !&lt;br /&gt;
We know control the time but this is far to be perfect...&lt;br /&gt;
&lt;br /&gt;
We focus ourself on being able to play with the time, which in term will perhaps allow us to go back and forth in time, rewind, forward the animation as will but 
we forgot one element:&lt;br /&gt;
&lt;br /&gt;
EASING&lt;br /&gt;
&lt;br /&gt;
As we are just adding a constant to each new frame to the animated element, the animation is very mechanical and is a little bit boring.&lt;br /&gt;
We need to find a way to create some easing in/out like we did in the first entry so that the animation will look more appealing by having not a constant added to each frame  !&lt;br /&gt;
Now, that we control the time and different parameters of the animation, we might be able to create some cool easing in, easing out, easing in/out !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-4299189016836088312?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/4299189016836088312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=4299189016836088312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4299189016836088312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/4299189016836088312'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/09/javascript-animation-controlling-time-2.html' title='Javascript Animation : Controlling time (2)'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-6858000539478601694</id><published>2007-09-29T00:20:00.000+09:00</published><updated>2010-08-31T22:54:17.195+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='closure'/><title type='text'>My inner request for Outer !</title><content type='html'>&lt;script type="text/javascript"&gt;
function myEvents(elm,events) {
   for(i=0;i &lt; events.length;i++) {
      elm['on'+events[i]]=function () { 
           alert(i);
        }
   }
}
function myEvents2(elm,events) {
   for(i=0;i &lt; events.length;i++) {
      function display() {
      elm['on'+events[i]]=function () {
           var n=i; 
           alert(n);
        }
      }
      display();
   }
}
function myEvents3(elm,events) {
   for(i=0;i &lt; events.length;i++) {
      function display() {
        var n=i; 
      elm['on'+events[i]]=function () {
           alert(n);
        }
      }
      display();
   }
}

window.onload=function () {
myEvents(document.getElementById('the_click'),['mouseover','mouseout']);
myEvents2(document.getElementById('the_click2'),['mouseover','mouseout']);
myEvents3(document.getElementById('the_click3'),['mouseover','mouseout']);


}
&lt;/script&gt;
If you read the preceding entry &lt;a href="http://shiriru.blogspot.com/2007/09/javascript-animation-simple-easing.html" title="javascript animation, basics of easing"&gt;basics of easing&lt;/a&gt; and that your are not familiar with javascript, you were perhaps surprised with
the following code concept:&lt;br /&gt;

&lt;pre&gt;
function greetings(msg) {
        function display() {
            alert(msg);
        }
        display();
}
&lt;/pre&gt;
So what's going on there ?&lt;br /&gt;
We have a main function that receives a string as a parameter.&lt;br /&gt;
Nothing extraordinary here!&lt;br /&gt;
Then we define a function within the main function that will be in charge of alerting the parameter.&lt;br /&gt;
Here it's a little bit unusual!&lt;br /&gt;

In fact, you can define a function from within a function in javascript and you can nest the functions as will !&lt;br /&gt;
The inner function can access the global variables define within the scope of the outer function.&lt;br /&gt;
Why is it so cool will you ask?&lt;br /&gt;
Well, the cool thing about inner functions is that they will work even if the outer function as returned and this can be very useful for dealing with variable scoping.&lt;br /&gt;
You can write the above inner function with an anonymous function if you want:&lt;br /&gt;
&lt;pre&gt;
function greetings(msg) {
        (function() {
            alert(msg);
        })();
}
&lt;/pre&gt;
This is an anonymous function as it does not have any name !&lt;br /&gt;
Enclosing an anonymous function with parentheses ()();, will cause the function to be executed right away !&lt;br /&gt;
&lt;br /&gt;
Ok, this example is very simple and is not very useful, so let's see something more powerful.&lt;br /&gt;

If you do the following, what's going to happen ?&lt;br /&gt;
&lt;pre&gt;

function myEvents(elm,events) {
   for(i=0;i &lt; events.length;i++) {
      elm['on'+events[i]]=function () { 
           alert(i);
        }
   }
}
myEvents(document.getElementById('the_click'),['mouseover','mouseout']);
&lt;/pre&gt;
&lt;a href="javascript:void(0)" id="the_click"&gt;try me&lt;/a&gt;&lt;br /&gt;
if you try this function, mouseovering and mouseoutting (it's new) the html element will alert... 2 every time !&lt;br /&gt;
We could have expect 0 for mouseover and then 1 for mouseout but no,no.&lt;br /&gt;
Why then ?&lt;br /&gt;
This is a scoping problem;&lt;br /&gt;
myEvents function, the main function has elm, events and i as variables.&lt;br /&gt;
As I said, inner functions can access the variables of the outer functions but one important thing:&lt;br /&gt;
If you don't call the inner function during the loop,the function will accede the value of the variables once the outer function has returned !&lt;br /&gt;
That is why this outputs the last value of i and not the value in between.&lt;br /&gt;
&lt;br /&gt;
So how can we output the right value ?&lt;br /&gt;
As this is a scoping problem, we need to scope the value of the variable to the scope of an inner function that we will call right away. &lt;br /&gt;
&lt;pre&gt;
function myEvents(elm,events) {
   for(i=0;i &lt; events.length;i++) {
      function display() {
      elm['on'+events[i]]=function () {
           var n=i; 
           alert(n);
        }
      }
      display();
   }
}
myEvents(document.getElementById('the_click'),['mouseover','mouseout']);
&lt;/pre&gt;
&lt;a href="javascript:void(0)" id="the_click2"&gt;try me&lt;/a&gt;&lt;br /&gt;
Tadam !&lt;br /&gt;
&lt;br /&gt;
It doesn't work !&lt;br /&gt;
If you have a closer look to the function above, we are trying to scope the value of i within the anonymous function applied to the object.&lt;br /&gt;
But this function is not executed right away, it will be executed when you will mouseover or mouseout on the link.Therefore, this function is calling the last value of the outer function.&lt;br /&gt; 
We need to capture the value within an inner function that will be executed right away.&lt;br /&gt;
So...&lt;br /&gt;
&lt;pre&gt;
function myEvents(elm,events) {
   for(i=0;i &lt; events.length;i++) {
      function display() {
        var n=i; 
      elm['on'+events[i]]=function () {
           alert(n);
        }
      }
      display();
   }
}
myEvents(document.getElementById('the_click'),['mouseover','mouseout']);
&lt;/pre&gt;
&lt;a href="javascript:void(0)" id="the_click3"&gt;try me&lt;/a&gt;&lt;br /&gt;
Tadam !&lt;br /&gt;
&lt;br /&gt;
It works !&lt;br /&gt;

In this last function, we capture literally the value of the global i to the scope of the display function by putting it in the variable n.&lt;br /&gt;
While we have this value under the hat,in our scope, we execute the function that will refer to the value we want !&lt;br /&gt;

If writing and finding a name to this 'capturing' function is a pain, just short it up:&lt;br /&gt;
&lt;pre&gt;
function myEvents2(elm,events) {
   for(i=0;i &lt; events.length;i++) {
      (function () {
           var n=i;
      elm['on'+events[i]]=function () { 
           alert(n);
        }
      })();
   }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1263965490328633445-6858000539478601694?l=shiriru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shiriru.blogspot.com/feeds/6858000539478601694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1263965490328633445&amp;postID=6858000539478601694' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/6858000539478601694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1263965490328633445/posts/default/6858000539478601694'/><link rel='alternate' type='text/html' href='http://shiriru.blogspot.com/2007/09/my-inner-request-for-outter.html' title='My inner request for Outer !'/><author><name>shiriru</name><uri>http://www.blogger.com/profile/15157129219364042703</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='http://1.bp.blogspot.com/_tjt7YLjLCNk/TCxib4MrJ0I/AAAAAAAAAAM/HlwWG-bszYY/S220/m_ffbff296ca9048a083ccd2bf740a12ae.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1263965490328633445.post-9095839635575830379</id><published>2007-09-27T23:36:00.000+09:00</published><updated>2010-08-31T22:53:57.481+09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Javascript'/><title type='text'>debugging,developping and loving it.. perhaps...</title><content type='html'>When you browse the Internet, you are using a... browser.&lt;br /&gt;

Not really surprising to know that browsers are the most used software nowadays.&lt;br /&gt;

But I guess there's nothing new there.&lt;br /&gt;



When you browse the web as a user, that's find.&lt;br /&gt;


You don't think about how the page is rendered, how this element is placed here
or how this flying ufo goes thru the window, making you feel nervous....&lt;br /&gt;



Well, if you develop for the web, the browser is going to be your best friend....&lt;br /&gt;


or your best enemy !.&lt;br /&gt;


There are different browsers, different way of interpreting the code that says
this ufo goes from here to there and this text is placed here with this color...&lt;br /&gt;



If you are using Windows, you are certainly using the default browser shipped with it:.&lt;br /&gt;

Internet Explorer or IE..&lt;br /&gt;

If you are using a Macintosh, you are probably using Safari....&lt;br /&gt;


There are other browsers: Firefox, Opera...&lt;br /&gt;



The 4 browsers listed so far are the main browsers you will perhaps need to watch
carefully !&lt;br /&gt;



We are in 2007 and IE 7 is out but hey, almost 80% of people are still using IE 6, helas !&lt;br /&gt;

Why is it not a good news ?&lt;br /&gt;



Well, they are rules that say the text of an internet page should be blue,
aligned right with a border on the left...&lt;br /&gt;

You know for sure that pages are created using different languages such as (X)HTML,CSS, Javascript, Flash, Java and the list goes on that specify the above rules.
&lt;br /&gt;&lt;br /&gt;

(X)HTML,CSS, Javascript directly depends on how the browser has implemented their behavior.&lt;br /&gt;


And here start the fun !&lt;br /&gt;



At the beginning, when browser vendors started to appear, they weren't any rules defining the way each language should be interpreted and the chaos took place.&lt;br /&gt;


Think of it : you want to have your text in blue but you need to write the rules 3 times for 3 different browsers ! Fun hey ?&lt;br /&gt;



That's why a consortium, the W3C, stands up to define some standards, rules that browser vendors should follow to put some order in there.&lt;br /&gt;


Well, browser vendors doesn't have to follow these standards, they can implement them the way they like...&lt;br /&gt;

That's why you can find some convergence and differences between how IE 6 and Firefox will render exactly the same page !&lt;br /&gt;


You can find many differences between IE 6 and IE 7 too !&lt;br /&gt;


(if you are using IE 6, it's time to update !)&lt;br /&gt;



IE was one of the first and pride or what, IE staffs are a kind of reluctant to follow the W3C standards whereas other browsers try to converge as possible to these standards.&lt;br /&gt;

Browsers converging to standards is beneficial for the programmer : .&lt;br /&gt;
if everyone follow the same rules,follow the same way to render a page, you will not have to waste your time checking them on different browsers,learn different ways of doing things and try to find some hacks to make everything works !&lt;br /&gt;

&lt;br /&gt;


But to tell the truth, that's find ! The difference is not too huge and some good functionalities can exist in some browsers. If they are good, they will be copied, enhanced for the joy of everyone !&lt;br /&gt;
Still, differences exists and this can be a real pain to deal with.&lt;br /&gt;
&lt;br /&gt;
So here we are, with different browsers, different rules but one programmer..&lt;br /&gt;

You need to check your pages in different browsers to be sure they will render the same.&lt;br /&gt;
And here comes some tools to help you develop your page (xhtml,css and javascript essentially).&lt;br /&gt;&lt;br /&gt;
They are not going to help you make your code working for all of the browsers though.&lt;br /&gt;
These tools will just help you spouting out places where the browser bugs with a particular code.&lt;br /&gt;


We will start by my favorite browser :&lt;br /&gt;&lt;br /&gt;

&lt;span style="font-size:130%;"&gt;Firefox&lt;/span&gt; !
&lt;br /&gt;
You can plug some new tools too it very easily in 2 clicks !&lt;br /&gt;

As an open source project, there is a huge community that enhance the browser continuously and that's why you can find thousands of plugins !&lt;br /&gt;

Below is the page that list the plugins related to development :&lt;br /&gt;


&lt;a href="https://addons.mozilla.org/en-US/firefox/browse/type:1/cat:4"&gt;https://addons.mozilla.org/en-US/firefox/browse/type:1/cat:4&lt;/a&gt;&lt;br /&gt;

Then I will list my favorite tools;&lt;br /&gt;


- html validator&lt;br /&gt;
&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/249"&gt;https://addons.mozilla.org/en-US/firefox/addon/249&lt;/a&gt;&lt;br /&gt;
This plugin will tell you if there is something wrong with your xhtml page !&lt;br /&gt;

-web developer&lt;br /&gt;
&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/60"&gt;https://addons.mozilla.org/en-US/firefox/addon/60&lt;/a&gt;&lt;br /&gt;
I just cannot live without !&lt;br /&gt;
You can edit in place the css, html, cookies,&lt;br /&gt;
see the page structure, change the window size and so on and so forth !&lt;br /&gt;

- Fire bug&lt;br /&gt;
&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/1843"&gt;https://addons.mozilla.org/en-US/firefox/addon/1843&lt;/a&gt;&lt;br /&gt;
Well, this one rules too ! very powerful with some features like the one of web developer
plus some others very nice and helpful !&lt;br /&gt;
&lt;br /&gt;

As for Javascript, Firefox is shipped with a debugger that is very helpfull
and can allow you to track down bugs efficiently !&lt;br /&gt;
You can look for Venkman plugin if you need something even more powerfull.


&lt;br /&gt;&lt;br /&gt;


IE...&lt;br /&gt;


- script debugger&lt;br /&gt;
&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=2F465BE0-94FD-4569-B3C4-DFFDF19CCD99&amp;amp;displaylang=en"&gt;http://www.microsoft.com/downl
