<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.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:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-34454975</id><updated>2009-11-07T11:46:53.670+01:00</updated><title type="text">Web Reflection</title><subtitle type="html">behind the design</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://webreflection.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default?start-index=26&amp;max-results=25" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>329</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/WebReflection" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><id>tag:blogger.com,1999:blog-34454975.post-8629187637872056286</id><published>2009-10-25T20:39:00.004+01:00</published><updated>2009-10-30T12:17:00.008+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Mouse" /><category scheme="http://www.blogger.com/atom/ns#" term="DOM" /><category scheme="http://www.blogger.com/atom/ns#" term="WebKit" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><category scheme="http://www.blogger.com/atom/ns#" term="events" /><title type="text">Android DOM "Finger" Events</title><content type="html">&lt;img src="http://gearmedia.ign.com/gear/image/article/912/912821/t-mobile-g1-android-enabled-phone-announced-20080923034929715.jpg" /&gt;&lt;br /&gt;This is the Android based device I am talking about and the installed software is version 1.6, apparently with multi-touch support for more recent devices so mine is not the case.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Disclaimer&lt;/h3&gt;The reason I am writing this post is my attempt to reproduce the Android OS interface via browser, hilariously possible with every browser except the original one: the WebKit in Android.&lt;br /&gt;&lt;em&gt;Why would I do that?&lt;/em&gt; The mouse has been around for ages, thanks Xerox, but later these years we've seen so many touch screen based devices without common mouse pattern. Since I think both Android, iPhone, and others, have done an excellent work with the way we use the device UI I thought: Why not! It could be a great time to start analysis and piece of libraries to replicate in a cross browser way some device independent event. Well, as I've already said, and as you'll see next, right now it is not possible!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mouse Events .. ahem, Finger Events&lt;/h3&gt;Every mouse related event we know does not make much sense with a touchscreen, at least the tested one. Think about it: a finger points something (aka: mousedown) move somewhere (aka: mousemove) remove the finger itself (aka: mouseup). &lt;strong&gt;This is not what truly happens&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mouse Events Order&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;mouseout, optionally fired when point if before we pointed another element&lt;/li&gt;&lt;li&gt;mouseover, optionally fired if the pointed event is different (or no elements have been pointed before)&lt;/li&gt;&lt;li&gt;mousemove, always before mousedown, sometimes fired twice if the internal cursor is in position 0,0 - &lt;strong&gt;this event is not performed while we move the finger!&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;mousedown&lt;/li&gt;&lt;li&gt;mouseup&lt;/li&gt;&lt;li&gt;click, which is so far the only event that makes sense&lt;/li&gt;&lt;li&gt;DOMActivated, a common WebKit "bug"&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mousemove Events ... Whatever ...&lt;/h3&gt;Fired events are device dependent, my device fires these events just in order but &lt;strong&gt;whatever we change in the DOM wont be called/rendered until we release&lt;/strong&gt;. Mousemove is fired once, maximum twice, but never during movement.&lt;br /&gt;In few words the only "mouse event" that makes sense is click, not performed if we scroll.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Forget The Drag And Drop!&lt;/h3&gt;Even if the most interesting part of the Android interface is the drag and drop, via WebKit mobile we cannot even try to emulate it just because &lt;strong&gt;the only event fired while we move the pointer is scroll&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Scroll ... Whatever ...&lt;/h3&gt;This event could be considered just a notify and nothing else. If we do whatever action while we scroll a page nothing will happen until we release the pointed element. Accordingly we cannot use the element to synchronize somehow the rendered page since again, nothing will happen during the scroll. The phone browser is basically frozen during the entire lifecycle of a gesture, or a pointer (via finger) operation.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;(window || document) // it does not matter&lt;br /&gt;    .addEventListener(&lt;br /&gt;        "scroll",&lt;br /&gt;        (function(i){&lt;br /&gt;            return function scroll(e){&lt;br /&gt;                // it's a waste of time&lt;br /&gt;                // to perform whatever&lt;br /&gt;                // action here&lt;br /&gt;                // let's speed up things&lt;br /&gt;                // adding delay&lt;br /&gt;                if(i)&lt;br /&gt;                    clearTimeout(i);&lt;br /&gt;                i = setTimeout(function(){&lt;br /&gt;                    i = 0;&lt;br /&gt;                    onScroll();&lt;br /&gt;&lt;br /&gt;                }, /* about */ 250);&lt;br /&gt;            };&lt;br /&gt;        })(0)&lt;br /&gt;    )&lt;br /&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Above snippet represents a delayed onScroll event which aim is to be performed faster without slowing down the page while we are scrolling.&lt;br /&gt;I know this could sound a nonsense but operation will be performed in any cases but never rendered so why should we let our phone compute stuff will never be showed?&lt;br /&gt;Also a scroll could be not perfect, since the mouse wheel won't be there and a pointer has 10 pixels of tolerance so just wait the end of the action, and only at that point perform something.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Resize&lt;/h3&gt;Both window or document, no difference in this case, will always perform a resize event. This is the last reliable event we have so far in a G1 device.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Drop Down Menu Not Worth It&lt;/h3&gt;Common JavaScript drop down menu usually activated via mouseover and removed on mouseout won't work as expected in common touchscreens while if we implement a "clever" click manager Desktop users will be a bit disoriented 'cause we failed implementing these menus everywhere just because these are strictly device pointer dependent, so not re-adaptable/usable at all.&lt;br /&gt;Moreover, a finger is not a mouse and it's more complicated to click the right menu/link at first shot. We need to rethink a little bit the UI if our aim is to make a website usable, without having 2 versions to maintain, with both desktop and mobile or touchscreen.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;As Summary&lt;/h3&gt;We have basically 3 events, and few others, such onload, DOMContentLoaded, focus and key related for inputs, but these a part other events won't necessarily act as expected.&lt;br /&gt;We need to bear in mind that mousemove or mouseover/out are quite meaningless since there is no mouse and no sensor able to monitor the finger activity when close to the screen. iPhone implemented a touch event but still, touch does not allow drag and drop so if we would like to emulate the Mobile OS interface via the Mobile Browser, we simply cannot: what a joke, but that's how it is.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-8629187637872056286?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/8629187637872056286/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=8629187637872056286" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/8629187637872056286" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/8629187637872056286" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/dHsOBAACFXE/android-dom-finger-events.html" title="Android DOM &quot;Finger&quot; Events" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/android-dom-finger-events.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-2033970983594880104</id><published>2009-10-23T22:43:00.006+02:00</published><updated>2009-10-23T23:19:38.316+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="sourceIndex" /><category scheme="http://www.blogger.com/atom/ns#" term="vice-versa" /><category scheme="http://www.blogger.com/atom/ns#" term="cross-browser" /><title type="text">Node sourceIndex for every browser</title><content type="html">I was doing a couple of tests in my bloody Android and I don't even know how I ended up with such snippet ... anyway, accordingly with @&lt;a href="http://twitter.com/ppk"&gt;ppk&lt;/a&gt; table &lt;a href="http://www.quirksmode.org/dom/w3c_core.html#t77"&gt;sourceIndex&lt;/a&gt; is a node property compatible with every version of Internet Explorer and latest Opera browser but not with Chrome, Firefox, or Safari (WebKit Android and iPhone as well).&lt;br /&gt;&lt;br /&gt;Being these unsupported browsers compatible with both native Array.prototype.indexOf and __defineGetter__ and being 5 to 100 times faster than IE, I thought: why don't put this as well into &lt;a href="http://code.google.com/p/vice-versa/"&gt;vice-versa&lt;/a&gt;?&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;/** sourceIndex by vice-versa - Mit Style License&lt;br /&gt; * @target  FireFox, Safari, Chrome&lt;br /&gt; */&lt;br /&gt;if(typeof document.documentElement.sourceIndex == "undefined")&lt;br /&gt;    HTMLElement.prototype.__defineGetter__("sourceIndex", (function(indexOf){&lt;br /&gt;        return function sourceIndex(){&lt;br /&gt;            return indexOf.call(this.ownerDocument.getElementsByTagName("*"), this);&lt;br /&gt;        };&lt;br /&gt;    })(Array.prototype.indexOf));&lt;br /&gt;;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I so much would have cached the live getElementsByTagName("*") object then I thought there must be a reason if different libraries pass via node.ownerDocument rather than direct document ... isn't it? Well, if not I'll change soon but right now I am pretty much happy with performances :)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why sourceIndex&lt;/h3&gt;&lt;br /&gt;If we would like to know, as example, if a node is before or after another one (considering that nested nodes will be considered always after their container) I bet there's nothing simpler than:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;if(a.sourceIndex &lt; b.sourceIndex){&lt;br /&gt;    // move up b, move down a&lt;br /&gt;} else {&lt;br /&gt;    // move up a, move down b&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;... or something similar, enjoy&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;br /&gt;Apparently in &lt;a href="http://groups.google.com/group/sizzlejs/browse_thread/thread/44d2b3fd5d532b5b"&gt;jQuery dev list&lt;/a&gt; somebody already talked about analogue snippets (thanks @&lt;a href="http://twitter.com/diegoperini"&gt;diegoperini&lt;/a&gt;) but it's not my idea to normalize anything, respecting what sourceIndex should do: compare index in the full HTMLCollection and nothing else, the rest could be easily implemented over this snippet :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-2033970983594880104?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/2033970983594880104/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=2033970983594880104" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/2033970983594880104" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/2033970983594880104" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/mK8oInoH-9w/node-sourceindex-for-every-browser.html" title="Node sourceIndex for every browser" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/node-sourceindex-for-every-browser.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-648231067355740053</id><published>2009-10-23T00:55:00.004+02:00</published><updated>2009-10-23T01:31:27.197+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="for in" /><category scheme="http://www.blogger.com/atom/ns#" term="runtime" /><title type="text">JavaScript For In Madness</title><content type="html">Have you never instinctively written a &lt;em&gt;for in&lt;/em&gt; loop like the next one, instantly correcting it since you need a variable to perform it? &lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;for(var k in {oops:null}){&lt;br /&gt;    // cool, got "k" here ...&lt;br /&gt;    // now how do I get&lt;br /&gt;    // the bloody "oops" value?&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This quick post talks about above nonsense case providing a solution I will explain only if anybody will be interested about it, since (I am quite lazy and tired right now and ...) I think I've been able to solve the trick using almost every JavaScript bad practice :D&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Runtime Assigned For In Loop&lt;/h3&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;(function(self, Function){&lt;br /&gt;// Another (C) WebReflection Silly Idea&lt;br /&gt;"use strict"; // Mit Style Weirdness&lt;br /&gt;var $o;&lt;br /&gt;self.o = function o($){&lt;br /&gt;    if(!$)&lt;br /&gt;        self.o = $o;&lt;br /&gt;    else {&lt;br /&gt;        $o = self.o;&lt;br /&gt;        self.o = Function(&lt;br /&gt;            "$", "return function o(" +&lt;br /&gt;                new Array(($.length || 0) + 1).join(",k").slice(1)  +&lt;br /&gt;            "){return $(arguments[0])}"&lt;br /&gt;        )(o);&lt;br /&gt;        for(var k in $)&lt;br /&gt;            self.o[k] = $[k]&lt;br /&gt;        ;&lt;br /&gt;    };&lt;br /&gt;    return $;&lt;br /&gt;};&lt;br /&gt;})(this, Function);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;WTF Is That&lt;/h3&gt;Above agglomerate of dynamic assignments/compositions let us perform a forIn without creating (virtually speaking) a variable. How?&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;for(var k in o({a:"b", c:"d"})){&lt;br /&gt;    alert([k, o[k]]);&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In few words we don't need to define the "o" object in any place. The trick works as expected with blocked properties, as length is for a function, name, and whatever else was assigned to the object and &lt;strong&gt;even nested&lt;/strong&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;for(var k in o({&lt;br /&gt;    length:123,&lt;br /&gt;    name:"test"&lt;br /&gt;})){&lt;br /&gt;&lt;br /&gt;    alert([k, o[k]]);&lt;br /&gt;&lt;br /&gt;    // nested for in ...&lt;br /&gt;    for(var k in o({a:"b"}))&lt;br /&gt;        alert([k, o[k]])&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;    o(); // back in town parent object&lt;br /&gt;&lt;br /&gt;    alert(o.name); // test&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Isn't it cool? Even with Arrays!&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;for(var k in o([1, 2, 3])){&lt;br /&gt;    alert([k, o[k]]);&lt;br /&gt;    // 0,1&lt;br /&gt;    // 1,2&lt;br /&gt;    // 2,3&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The good part is that break will work as expected and the changed object is quite static since it is a function, looped over original object properties.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why This Abomination&lt;/h3&gt;Well, let's say with &lt;em&gt;let&lt;/em&gt; and &lt;em&gt;var&lt;/em&gt; we can do what we want in a generic for loop but we are kinda stuck with a single variable with a "for in" one.&lt;br /&gt;What would be truly nice in my opinion is the possibility to implement this kind of syntax:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;for(var o = {a:"b"}, k; k in o){&lt;br /&gt;    // common loop with o and o[k]&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Something similar to PHP world where we have:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;foreach(array('a'=&gt;'b') as $key =&gt; $value){&lt;br /&gt;    // do stuff and forget about the config variable&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I am pretty much sure JavaScript will never implement above syntax but hey, that's why I have created a monster I'll probably never use in my programming life :P&lt;br /&gt;&lt;br /&gt;The main trick about supported length property is described in &lt;a href="http://webreflection.blogspot.com/2009/04/javascript-static-collection-new-type.html"&gt;this post&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-648231067355740053?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/648231067355740053/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=648231067355740053" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/648231067355740053" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/648231067355740053" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/DawGFNbnAuY/javascript-for-in-madness.html" title="JavaScript For In Madness" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/javascript-for-in-madness.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-4117720789015590875</id><published>2009-10-15T02:59:00.008+02:00</published><updated>2009-10-15T03:44:39.458+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="relation" /><category scheme="http://www.blogger.com/atom/ns#" term="DOM" /><category scheme="http://www.blogger.com/atom/ns#" term="JavaScirpt" /><category scheme="http://www.blogger.com/atom/ns#" term="proxy" /><title type="text">DOM Node Proxy</title><content type="html">This is just a quick post from home sweet home.&lt;br /&gt;A common DOM related problem is to create an association between a node and a generic object. The most dirty, memory leaks prone, and obtrusive way to perform this task is this one:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;document.body.obj = {&lt;br /&gt;    prop:"value",&lt;br /&gt;    otherProp:function(){}&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Above snippet is a &lt;strong&gt;bad practice&lt;/strong&gt; for different reasons.&lt;ol&gt;&lt;li&gt;&lt;strong&gt;obtrusive&lt;/strong&gt;, it's assuming that no other libraries will use "obj" property name to perform an analogue task&lt;/li&gt;&lt;li&gt;&lt;strong&gt;dirty&lt;/strong&gt;, if we associate a primitive value Internet Explorer will &lt;a href="http://webreflection.blogspot.com/2009/04/divexpando-null-or-divremoveattributeex.html"&gt;expose it in the node string representation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;memory leaks&lt;/strong&gt;, if the object points something "live", another node, or a HTMLCollection, the generic node will never be collected by the garbage&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Alternatives&lt;/h3&gt;Specially to avoid last problem, the memory consumption, it's a good practice to store an index, rather than an object. To make things less obtrusive and get rid of conflicts, we usually create a "unique id".&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// the array with all objects&lt;br /&gt;var stack = [];&lt;br /&gt;&lt;br /&gt;// the unobtrusive property name&lt;br /&gt;var expando = "prefix" + new Date().getTime();&lt;br /&gt;&lt;br /&gt;// the obejct to relate&lt;br /&gt;var o = {};&lt;br /&gt;&lt;br /&gt;stack.push(o);&lt;br /&gt;&lt;br /&gt;// the relation via index (last object)&lt;br /&gt;document.body[expando] = stack.length - 1;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As I have already linked and explained, &lt;a href="http://webreflection.blogspot.com/2009/04/divexpando-null-or-divremoveattributeex.html"&gt;this technique is still dirty&lt;/a&gt; because Internet Explorer will show the unique id via outerHTML or generic node representation.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Strategies&lt;/h3&gt;jQuery, and many others, create an association for each manipulated dom node. This could consume RAM without a reason since there could be a lot of nodes with an associated object that will never be used.&lt;br /&gt;Next version of jQuery, right now in alpha stage, understood this point changing the object association logic. I have not read how yet, but I would like to write something I've been used for a while, a sort of proxy object created for DOM nodes and object relations.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;DOM Node Proxy&lt;/h3&gt;&lt;pre class="code"&gt;var proxy = (function(){&lt;br /&gt;    // another (C) WebReflection silly idea&lt;br /&gt;    var expando = "@".concat(+new Date, Math.random()),&lt;br /&gt;        stack   = []&lt;br /&gt;    ;&lt;br /&gt;    return function proxy(){&lt;br /&gt;        return stack[this[expando]] || stack[&lt;br /&gt;            this[expando] = new Number(stack.push({}) - 1)&lt;br /&gt;        ];&lt;br /&gt;    };&lt;br /&gt;})();&lt;/pre&gt;&lt;br /&gt;Above snippet uses almost all strategies I know to avoid obtrusive property, dirty layout, and direct object assignment (index strategy).&lt;br /&gt;To better understand what exactly is above function I have commented each part of it:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var proxy = (function(){&lt;br /&gt;&lt;br /&gt;    // another (C) WebReflection silly idea&lt;br /&gt;&lt;br /&gt;    // one function to associate as proxy&lt;br /&gt;    // Being assignment a direct one&lt;br /&gt;    // standard browsers won't modify&lt;br /&gt;    // attributes while being proxy&lt;br /&gt;    // an object (not primitive value)&lt;br /&gt;    // IE won't expose it in node string&lt;br /&gt;    // representation (e.g. outerHTML)&lt;br /&gt;    function proxy(){&lt;br /&gt;&lt;br /&gt;        // a proxy call costs only once:&lt;br /&gt;        // the first time it's called&lt;br /&gt;        // Other calls will return the object&lt;br /&gt;        // This is to avoid objects association&lt;br /&gt;        // even if these are not necessary&lt;br /&gt;        return stack[this[expando]] || stack[&lt;br /&gt;        &lt;br /&gt;            // the index is the last one in the&lt;br /&gt;            // private stack Array. To avoid&lt;br /&gt;            // leaks we don't associate directly&lt;br /&gt;            // an object but simply an integer.&lt;br /&gt;            // If we directly associate&lt;br /&gt;            // a primitive value, IE will expose&lt;br /&gt;            // is in the dom string representation&lt;br /&gt;            // (e.g. outerHTML)&lt;br /&gt;            // To avoid this we can just assign&lt;br /&gt;            // a Number instance, rather than&lt;br /&gt;            // a primitive "number"&lt;br /&gt;            this[expando] = new Number(&lt;br /&gt;            &lt;br /&gt;                // push returns the new length&lt;br /&gt;                // we need last inserted object&lt;br /&gt;                // index to relate the object&lt;br /&gt;                stack.push({}) - 1&lt;br /&gt;            )&lt;br /&gt;        ];&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    var&lt;br /&gt;        // private unique expando with&lt;br /&gt;        // an  invalid char as prefix&lt;br /&gt;        // in order to make attr name&lt;br /&gt;        // easy to recognize in a possible&lt;br /&gt;        // IE attributes loop&lt;br /&gt;        expando = "@".concat(&lt;br /&gt;            +new Date,&lt;br /&gt;            Math.random()&lt;br /&gt;        ),&lt;br /&gt;        &lt;br /&gt;        // list of associated object&lt;br /&gt;        stack   = []&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;    // ready to go!&lt;br /&gt;    return proxy;&lt;br /&gt;&lt;br /&gt;})();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Is it clear enough? This is a simple usage example (please reado NOTEs):&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;onload = function(){&lt;br /&gt;&lt;br /&gt;    // associate a proxy&lt;br /&gt;    // NOTE: this is still obtrusive&lt;br /&gt;    // the property name should be a unique id&lt;br /&gt;    // or it should have library prefix&lt;br /&gt;    // otherwise we could have conflicts&lt;br /&gt;    document.body.proxy = proxy;&lt;br /&gt;    // aka: node[expando] = proxy;&lt;br /&gt;&lt;br /&gt;    // retrieve the proxy object&lt;br /&gt;    var p = document.body.proxy();&lt;br /&gt;&lt;br /&gt;    // test proxy: true&lt;br /&gt;    alert(p === document.body.proxy());&lt;br /&gt;&lt;br /&gt;    // test clean body string representation&lt;br /&gt;    alert(document.documentElement.innerHTML);&lt;br /&gt;&lt;br /&gt;    // find proxy created property&lt;br /&gt;    for(var k in document.body){&lt;br /&gt;        if(k.charAt(0) === "@")&lt;br /&gt;            alert([k, document.body[k]])&lt;br /&gt;        ;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;As Summary&lt;/h3&gt;This is more a proof of concept but I hope showed code will help us to replicate the behavior. The main missed part is the internal stack management: how can I clean the stack index when I don't need the node anymore? All we need is an extra in-proxy-scope function or a specific associated instance rather than a raw object.&lt;br /&gt;In ew words there are no best strategies for this second problem, it just depends what we need.&lt;br /&gt;From a logical point of view, if we give indirect access to that stack, exposing its length or via functions able to modify it, stack safety could be compromised. What I could suggest is something like:&lt;pre class="code"&gt;var proxy = (function(){&lt;br /&gt;    // (C) WebReflection - Mit Style License&lt;br /&gt;    function proxy(){&lt;br /&gt;        return stack[this[expando]] || stack[&lt;br /&gt;            this[expando] = new Number(stack.push(new $proxy) - 1)&lt;br /&gt;        ];&lt;br /&gt;    };&lt;br /&gt;    function $proxy(){&lt;br /&gt;        this._index = stack.length;&lt;br /&gt;    };&lt;br /&gt;    $proxy.prototype.destroy = function destroy(){&lt;br /&gt;        delete stack[this._index];&lt;br /&gt;    };&lt;br /&gt;    var expando = "@".concat(+new Date, Math.random()),&lt;br /&gt;        stack   = []&lt;br /&gt;    ;&lt;br /&gt;    return proxy;&lt;br /&gt;})();&lt;/pre&gt;where the stack is manipulated indirectly while nothing is publicly exposed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-4117720789015590875?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/4117720789015590875/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=4117720789015590875" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4117720789015590875" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4117720789015590875" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/R_Gl1bgkXg4/dom-node-proxy.html" title="DOM Node Proxy" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">13</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/dom-node-proxy.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-4512517579486137203</id><published>2009-10-13T01:00:00.006+02:00</published><updated>2009-10-13T01:25:54.337+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="resolution" /><category scheme="http://www.blogger.com/atom/ns#" term="ie" /><category scheme="http://www.blogger.com/atom/ns#" term="Internet Explorer" /><category scheme="http://www.blogger.com/atom/ns#" term="scope" /><category scheme="http://www.blogger.com/atom/ns#" term="JScript" /><title type="text">Internet Explorer Scope Resolution</title><content type="html">I have enclosed in only 5 steps JScript weirdness, hoping all precedent deliriums about functions, standards, and Internet Explorer, will make more sense now.&lt;br /&gt;&lt;iframe frameborder="0" style="border:0;width:420px;height:560px;" src="http://www.3site.eu/doc/IE_scope/IE_scope_1.html"&gt;&lt;/iframe&gt;&lt;br /&gt;Here there is the link to &lt;a href="http://www.3site.eu/doc/IE_scope/IE_scope_1.html"&gt;original HTML slides&lt;/a&gt;, I hope this will help everybody to have clearer ideas.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-4512517579486137203?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/4512517579486137203/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=4512517579486137203" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4512517579486137203" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4512517579486137203" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/GlMrL20K40g/internet-explorer-scope-resolution.html" title="Internet Explorer Scope Resolution" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/internet-explorer-scope-resolution.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-2867847141458598128</id><published>2009-10-12T19:38:00.010+02:00</published><updated>2009-10-13T01:29:33.686+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="function" /><category scheme="http://www.blogger.com/atom/ns#" term="solution" /><category scheme="http://www.blogger.com/atom/ns#" term="name" /><category scheme="http://www.blogger.com/atom/ns#" term="JavaScirpt" /><title type="text">Named function expressions demystified III</title><content type="html">&lt;strong&gt;Update&lt;/strong&gt; For those interested about Internet Explorer scope resolution, I summarized everything in &lt;a href="http://webreflection.blogspot.com/2009/10/internet-explorer-scope-resolution.html"&gt;5 slides&lt;/a&gt;.&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;This is hopefully the end of the &lt;em&gt;Named function expressions demystified&lt;/em&gt; trilogy, where here you can find &lt;a href="http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified.html"&gt;episode I&lt;/a&gt;, and &lt;a href="http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified_11.html"&gt;episode II&lt;/a&gt;.&lt;br /&gt;Juriy knows I am hard to convince, but apparently he is not better than me at all ...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Inglorious Correction&lt;/h3&gt;Sure, it's better than nothing, but after I have spent dunno how many tweets plus 2 posts, all I have obtained is a small correction in &lt;a href="http://yura.thinkweb2.com/named-function-expressions/#expr-vs-decl"&gt;the whole article&lt;/a&gt; (and you have to scroll a bit before):&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Generally, we can emulate function statements behavior from the previous example with this standards-compliant (and unfortunately, more verbose) code:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;  var foo;&lt;br /&gt;  if (true) {&lt;br /&gt;    foo = function foo(){ return 1; };&lt;br /&gt;  }&lt;br /&gt;  else {&lt;br /&gt;    foo = function foo() { return 2; };&lt;br /&gt;  };&lt;br /&gt;&lt;br /&gt;  // call the function, easy?&lt;br /&gt;  foo();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Above snippet is the best solution in the entire article but probably to avoid my name in article credits, and it does not matter since I have already said it's not about the copyright, and surely to avoid personal ego conflicts, the suggested one is a &lt;strong&gt;surrogate of above snippet&lt;/strong&gt;, quite embarrassing from a developer point of view, isn't it?&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;  var f; // create an alias, WHY!!!!!!!!!&lt;br /&gt;  if (true) {&lt;br /&gt;    f = function foo(){ return 1; };&lt;br /&gt;  }&lt;br /&gt;  else {&lt;br /&gt;    f = function foo() { return 2; };&lt;br /&gt;  };&lt;br /&gt;&lt;br /&gt;  // create a reference in order to remove a reference, WHY!!!!!!!!!!!&lt;br /&gt;  var foo = null;&lt;br /&gt;&lt;br /&gt;  // call the function via another alias, WHY!!!!!!!!!!!&lt;br /&gt;  f();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Above snippet is just a surrogate because the first one simply create an alias which will &lt;strong&gt;refer the proper function&lt;/strong&gt;. Let's be simply developers avoiding obtuseness, OK?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Re Solution Pros&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;it's &lt;strong&gt;standard&lt;/strong&gt;, no excuses at all!&lt;/li&gt;&lt;li&gt;&lt;strong&gt;variables on top&lt;/strong&gt;, no way we can forget to nullify the function and we don't need to create a reference which aim is to remove a reference, cause the reference is already assigned, no memory problems at all (possibly less, since there is nothing referenced to a null value)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;semantic&lt;/strong&gt;, we can easily refer to the function, since the whole point is to solve the missed arguments.callee plus IE inconsistency ... &lt;/li&gt;&lt;li&gt;&lt;strong&gt;standard again&lt;/strong&gt;, because it perfectly &lt;strong&gt;emulates ECMAScript 3rd Edition behavior&lt;/strong&gt; even in Internet Explorer&lt;/li&gt;&lt;li&gt;the day we will need to nullify the function will be the day we meant it, and not a surpassed convention&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why My Re Solution Is More Standard&lt;/h3&gt;This is the expected behavior in all browsers, except Internet Exlorer and Opera, via Internet Explorer emulation:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;  var f; // let's use the suggested alias&lt;br /&gt;         // for demonstration purpose&lt;br /&gt;  if (true) {&lt;br /&gt;    f = function foo(){&lt;br /&gt;        // this is LOGICAL&lt;br /&gt;        // but in IE it will be false&lt;br /&gt;        // because foo will be the &lt;br /&gt;        // the other one, even if that&lt;br /&gt;        // else will never be executed!&lt;br /&gt;        alert(foo == arguments.callee)&lt;br /&gt;    };&lt;br /&gt;  }&lt;br /&gt;  else {&lt;br /&gt;    // IE will declare this function&lt;br /&gt;    // in any case since there is NO DIFFERENCE&lt;br /&gt;    // between expression and declaration&lt;br /&gt;    f = function foo() { return 2; };&lt;br /&gt;  };&lt;br /&gt;&lt;br /&gt;  f();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With my Re Solution the behavior is the expected one, &lt;em&gt;alert(foo == arguments.callee)&lt;/em&gt; will be &lt;strong&gt;true&lt;/strong&gt; in every browser ... do you still have doubts?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Re Solution Cons&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;strike&gt;unfortunately, more verbose&lt;/strike&gt;&lt;/li&gt;&lt;/ol&gt;This must be a joke ... more verbose? First of all we are dealing with developers that don't care at all about verbosity. Kangax as everybody else in credits always preferred verbosity since minifier and compressor could take care about this verbosity &lt;strong&gt;recreating&lt;/strong&gt;, and I love the irony of this part, &lt;strong&gt;exactly the suggested case&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Re Solution Pros II&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;being the function name declared on the top of the function, as I have said a well known good practice, every IDE will automatically &lt;strong&gt;suggest&lt;/strong&gt; that name as soon as we'll startt to type it: does verbosity matter?&lt;/li&gt;&lt;li&gt;As we all know &lt;strong&gt;gzip&lt;/strong&gt; and &lt;strong&gt;deflate&lt;/strong&gt; compresses repeated words &lt;strong&gt;more efficiently&lt;/strong&gt;, as result the Re Solution is even smaller if we don't munge it, does verbosity matter?&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Re Solution Is More Logical And Smaller&lt;/h3&gt;Here the simple test everybody can do. Two pages, same code, except the first one is Re Solution, 99 bytes, while the second one is Juriy suggestion, 111 bytes.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;?php ob_start(&amp;apos;ob_gzhandler&amp;apos;); ?&amp;gt;&lt;br /&gt;var foo;&lt;br /&gt;if (true) {&lt;br /&gt;    foo = function foo(){ return 1; };&lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt;    foo = function foo() { return 2; };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;?php ob_start(&amp;apos;ob_gzhandler&amp;apos;); ?&amp;gt;&lt;br /&gt;var f;&lt;br /&gt;if (true) {&lt;br /&gt;    f = function foo(){ return 1; };&lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt;    f = function foo() { return 2; };&lt;br /&gt;};&lt;br /&gt;var foo = null;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Do we have a single valid reason to use the Juriy suggestion over mine? I would honestly feel an idiot preferring the second one, since few bytes and more logic (foo is the function foo) against spread variables declarations (top and the middle with F = null) via aliases rather than function names inside the function itself where a debugger will show the name but we have to remember the alias, plus the possibility we forget to nullify the reference consuming more memory ... I mean, this is not the first of April, isn't it?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;And That's Not All Folks&lt;/h3&gt;We are developers, not monkey, I always dislike generic affirmations a la &lt;em&gt;eval is evil&lt;/em&gt;, the most used function since Ajax epoch, obviously included in json2.js itself, since is natural and logical to use it when necessary. Juriy corrected his article to underline how unprofessional am I suggesting a last option for IE behavior ... well, probably he has never thought about ternary assignment, isn't it?&lt;br /&gt;&lt;strong&gt;// Never do this!&lt;/strong&gt;, that's what I can read at some point, but we should think carefully before these statements.&lt;br /&gt;Here there is an example where the function will be a named one but there are no differences in this case for IE, indeed the last option is the IE one.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// somewhere in a closure ...&lt;br /&gt;// (otherwise add will be public in IE,&lt;br /&gt;// but I hope we went further than this&lt;br /&gt;//  at this point and after 3 posts&lt;br /&gt;//  plus an entire article ...)&lt;br /&gt;var event = {&lt;br /&gt;    add:document.addEventListener?&lt;br /&gt;        function add(){&lt;br /&gt;            alert([add, document.addEventListener]);&lt;br /&gt;        }:&lt;br /&gt;        function add(){&lt;br /&gt;            alert([add, document.attachEvent]);&lt;br /&gt;        }&lt;br /&gt;    ,&lt;br /&gt;    del:document.removeEventListener?&lt;br /&gt;        function del(){&lt;br /&gt;            alert([del, document.removeEventListener]);&lt;br /&gt;        }:&lt;br /&gt;        function del(){&lt;br /&gt;            alert([del, document.detachEvent]);&lt;br /&gt;        }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In one shot we have created a unique add reference, a named function, plus the right one for the event object. Now guess what's up if we invert the order putting the IE version at the end ... add will be the last option ... the one with addEventListener, got the point?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;As Summary&lt;/h3&gt;I am pretty much sure I'll be criticized again and only for the last part of this post where obviously things work but somebody will argue about future IE9 sci-fi behavior or stuff like that ... well, that day my library will be deprecated in any case and, if needed, it's easy to implement over my Re Solution&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var event = {&lt;br /&gt;    add:(function(add){document.addEventListener?&lt;br /&gt;        (add = function add(){&lt;br /&gt;            alert([add, document.addEventListener]);&lt;br /&gt;        }):&lt;br /&gt;        (add = function add(){&lt;br /&gt;            alert([add, document.attachEvent]);&lt;br /&gt;        }); return add&lt;br /&gt;        })()&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now let's see if the most interesting analysis about functions expressions and declaration will keep ending up with the wrong suggestion, rather than mine ... kinda curios, still hopeful though.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-2867847141458598128?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/2867847141458598128/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=2867847141458598128" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/2867847141458598128" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/2867847141458598128" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/uTKvsVeCD0g/named-function-expressions-demystified_12.html" title="Named function expressions demystified III" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified_12.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-6241939087102443006</id><published>2009-10-11T22:19:00.006+02:00</published><updated>2009-10-11T22:44:44.324+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="ES5" /><category scheme="http://www.blogger.com/atom/ns#" term="this" /><title type="text">ES5 and function default scope</title><content type="html">This is just a quick one. One of the worst decision about ES5, after the one to remove arguments.callee when "use strict" is present, is the missed default reference to the global object. Probably the most secure trick to retrieve the native window in JavaScript is this one:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// wherever we are&lt;br /&gt;var global = function(){return this}();&lt;br /&gt;&lt;br /&gt;// while window, could be simply a variable&lt;br /&gt;// assigned somewhere else in this scope&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I have already talked about this, and I am still against some ES5 "feature" which aim is probably the one to make JavaScript as fast as possible, regardless all code that will break if "use strict" is present in the generic scope.&lt;br /&gt;&lt;br /&gt;Another non-sense is to allow a &lt;strong&gt;this&lt;/strong&gt; in a context where there is no this. Rather than an error, ES5 will point refer &lt;em&gt;this&lt;/em&gt; to &lt;em&gt;undefined&lt;/em&gt;.&lt;br /&gt;Are you kidding me? &lt;em&gt;this&lt;/em&gt; is a special keywords related to the context and you are telling me a context is undefined? so I guess &lt;em&gt;open()&lt;/em&gt;, as example, should throw an error there, since window cannot be implicit in an undefined context, isn't it? ... anyway, fortunately the whole problem could be quickly solved in this way:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// ES5 problem&lt;br /&gt;(function(){&lt;br /&gt;"use strict";&lt;br /&gt;&lt;br /&gt;this === undefined; // true ... LOL!!!&lt;br /&gt;&lt;br /&gt;})();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// WebReflection QAD solution&lt;br /&gt;(function(){&lt;br /&gt;"use strict";&lt;br /&gt;&lt;br /&gt;this === window; // true ... yeah baby!&lt;br /&gt;&lt;br /&gt;}).call(this);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This simple modification could avoid lots of headaches plus could avoid scope resolution for every window variable.&lt;br /&gt;&lt;br /&gt;It's probably quite obvious but I can already imagine lots of people changing the whole function body rather than add a call at the end :D&lt;br /&gt;&lt;br /&gt;The trick to retrieve the global context won't work in any case for nested functions, unless we are not sure that this points to window, but being the trick goal the one to make window resolution quick and safe, there is not window,self,top, whatever check that could solve the problem (unless [].sort() will be still buggy ...)&lt;br /&gt;&lt;br /&gt;As summary, the day JavaScript will be that fast thanks to removed dynamic and run-time features, it won't be JavaScript anymore but another language a la ActionScript 2 when ActionScript 1 was enough, and the problem was the player rather than the language, which indeed has been replaced by ActionScript 3 even if the problem is still the player and not the language, since it can be compilable into old versions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-6241939087102443006?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/6241939087102443006/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=6241939087102443006" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6241939087102443006" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6241939087102443006" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/xYJKQG_9KNc/es5-and-function-default-scope.html" title="ES5 and function default scope" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/es5-and-function-default-scope.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-1435753668713446259</id><published>2009-10-11T15:34:00.008+02:00</published><updated>2009-10-12T23:15:54.266+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="function" /><category scheme="http://www.blogger.com/atom/ns#" term="name" /><title type="text">Named function expressions demystified II</title><content type="html">&lt;strong&gt;Update&lt;/strong&gt; If after this reading things are still the same, please read the &lt;a href="http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified_12.html"&gt;part 3&lt;/a&gt; of this post, thanks.&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;I have been criticized &lt;em&gt;just for fun&lt;/em&gt; and in a impulsive way without analysis or tests (I am not talking about Juriy who gently replied with interesting points in the &lt;a href="http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified.html"&gt;part 1 of this post&lt;/a&gt; - and I replied back).&lt;br /&gt;First of all, if the purpose of an article is to describe a behavior and provide a solution, there should not be any challenge or run for the copyright ... we are developers, and we &lt;strong&gt;want&lt;/strong&gt; the best solution, for us and others, if this solution has been published.&lt;br /&gt;&lt;br /&gt;Specially for a complicated language as JavaScript is, Virtual Machine and cross browser troubles speaking, is really difficult, sometimes impossible, to find the ultimate and perfect solution, so let's keep the argument in a professional way, agree?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What Is Wrong With Juriy Solution&lt;/h3&gt;Somebody does not get it, and it could be my fault. So this is about inconsistencies, and I'll show you Juriy code to avoid any kind of misunderstanding, OK?&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;  var fn = (function(){&lt;br /&gt;&lt;br /&gt;    // declare a variable to assign function object to&lt;br /&gt;    var f;&lt;br /&gt;&lt;br /&gt;    // conditionally create a named function&lt;br /&gt;    // and assign its reference to `f`&lt;br /&gt;    if (true) {&lt;br /&gt;      f = function F(){&lt;br /&gt;          // now try to create a setTimeout here&lt;br /&gt;          // assuming we need it&lt;br /&gt;&lt;br /&gt;          // error, there is no F reference&lt;br /&gt;          // anymore in this context.&lt;br /&gt;          // This function obviously exists and&lt;br /&gt;          // the entire point is to find a solution&lt;br /&gt;          // to replace arguments.callee&lt;br /&gt;          // so do you think is a good design&lt;br /&gt;          // we cannot use the function name&lt;br /&gt;          // with every browser?&lt;br /&gt;          setTimeout(F, 1000);&lt;br /&gt;&lt;br /&gt;          // insted we have to use another name&lt;br /&gt;          // but there is NO REASON to do this&lt;br /&gt;          // if you understood my precedent post&lt;br /&gt;          setTimeout(f, 1000);&lt;br /&gt;&lt;br /&gt;          // so the purpose is to make function&lt;br /&gt;          // call possible via name and the solution&lt;br /&gt;          // is to do not use the function name&lt;br /&gt;          // am I the only one spotting&lt;br /&gt;          // inconsistency here?&lt;br /&gt;&lt;br /&gt;          alert(f == F); // FALSE&lt;br /&gt;          // because F was the last option&lt;br /&gt;          // and F has been referenced to null&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    else if (false) {&lt;br /&gt;      // same as above&lt;br /&gt;      f = function F(){ }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;      // same as above&lt;br /&gt;      f = function F(){ }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Assign `null` to a variable corresponding to a function name&lt;br /&gt;    // This marks the function object (referred to by that identifier)&lt;br /&gt;    // available for garbage collection&lt;br /&gt;    var F = null;&lt;br /&gt;&lt;br /&gt;    // NO, this does not mark anything&lt;br /&gt;    // this is another layer in JScript&lt;br /&gt;    // the function exists, as exists the last one&lt;br /&gt;    // if we are nullify a reference, the garbage&lt;br /&gt;    // will discard the function because not&lt;br /&gt;    // referenced ANYWHERE in this contest&lt;br /&gt;    &lt;br /&gt;    // This behavior is EXACTLY THE SAME&lt;br /&gt;    // if we have last option callback&lt;br /&gt;    // in IE since the last function reference&lt;br /&gt;    // will be the only one, then other functions&lt;br /&gt;    // will be collected&lt;br /&gt;&lt;br /&gt;    // Moreover, with "Re Solution"&lt;br /&gt;    // the function is trapped in the reference&lt;br /&gt;    // where the reference HAS THE SAME NAME&lt;br /&gt;    // this means we have THE FUNCTION NAME&lt;br /&gt;    // as valid one in the current scope&lt;br /&gt;    // NO ALIASES, and garbage is fine&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // return a conditionally defined function&lt;br /&gt;    return f;&lt;br /&gt;  })();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Re Solution&lt;/h3&gt;To keep best compatibility the last option could be a bit messy in Opera or old Safari. That is why I have suggested my Re Solution.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;  var fn = (function(){&lt;br /&gt;&lt;br /&gt;    // declare the FUNCTION NAME we want to use&lt;br /&gt;    var F;&lt;br /&gt;&lt;br /&gt;    // conditionally create a named function&lt;br /&gt;    // and assign its reference to ITS NAME&lt;br /&gt;    if (true) {&lt;br /&gt;      F = function F(){&lt;br /&gt;          // EASY!!!&lt;br /&gt;          alert(F == arguments.callee); // TRUE&lt;br /&gt;          setTimeout(F, 1000);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    else if (false) {&lt;br /&gt;      // same as above&lt;br /&gt;      F = function F(){ }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;      // same as above&lt;br /&gt;      F = function F(){ }&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    // In this cotext there is&lt;br /&gt;    // ONE AND ONLY ONE&lt;br /&gt;    // reference to function F&lt;br /&gt;    // being the reference evaluated&lt;br /&gt;    // AFTER function declaration&lt;br /&gt;    // It does not matter if &lt;br /&gt;    // there are other functions&lt;br /&gt;    // with the same name because&lt;br /&gt;    // the reference, which comes after&lt;br /&gt;    // WILL POINT TO THAT FUNCTION&lt;br /&gt;    // which is a named one&lt;br /&gt;&lt;br /&gt;    // EASY ???&lt;br /&gt;    return F;&lt;br /&gt;  })();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;As Summary&lt;/h3&gt;I hope things are finally clear for everybody. I hope Juriy will get my point, and I am always ready to negate everything I wrote as soon as somebody will demonstrate it is wrong. Again, we are developers, there's no trophy here if we want make something public for developers community.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-1435753668713446259?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/1435753668713446259/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=1435753668713446259" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1435753668713446259" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1435753668713446259" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/srlDU9HmW18/named-function-expressions-demystified_11.html" title="Named function expressions demystified II" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified_11.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-6329113639758540919</id><published>2009-10-10T00:56:00.028+02:00</published><updated>2009-10-11T22:52:12.540+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="function" /><category scheme="http://www.blogger.com/atom/ns#" term="lambda" /><category scheme="http://www.blogger.com/atom/ns#" term="expression" /><category scheme="http://www.blogger.com/atom/ns#" term="scope" /><category scheme="http://www.blogger.com/atom/ns#" term="name" /><category scheme="http://www.blogger.com/atom/ns#" term="JavaScirpt" /><title type="text">Named function expressions demystified</title><content type="html">&lt;strong&gt;Update&lt;/strong&gt; If after this reading things are still the same, please read the &lt;a href="http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified_11.html"&gt;part 2 of this post&lt;/a&gt;, thanks.&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;br /&gt;This is a re-post, and few considerations, about the good &lt;a href="http://yura.thinkweb2.com/named-function-expressions/"&gt;Juriy article&lt;/a&gt;, which I suggest for every JavaScript developer with a deeper knowledge than just an API (jQuery or others).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Github For Everything!&lt;/h3&gt;My first consideration is about github, something I've never used that much since via Google Code I feel pretty comfortable with subversion. I find truly interesting the way Juriy is tracking his documentation, I've never thought about an article, as my old &lt;a href="http://www.3site.eu/doc/"&gt;JavaScript Prototypal Inheritance&lt;/a&gt; could be, in a code repository as &lt;a href="http://github.com/kangax/nfe/commits/master/"&gt;kangax&lt;/a&gt; did: good stuff!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;My Alternative Solution&lt;/h3&gt;There are few extra consideration to do over Juriy explanation, plus minor inconsistencies. The first thing is that Internet Explorer basically manages Function expressions and Function declarations in the same way, there's no such &lt;em&gt;VS&lt;/em&gt; in the middle.&lt;br /&gt;The fact we assign the function to a whatever named variable does not make any difference:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;alert(F); // (function F(f){/*IE Function*/return f})&lt;br /&gt;&lt;br /&gt;F((function F(f){/*Function Declaration*/return f}));&lt;br /&gt;F((function F(f){/*IE Function*/return f}));&lt;br /&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;br /&gt;var f = (function F(){return F}); // &lt;== which F?&lt;br /&gt;function F(){/*IE Function*/};    // this one!&lt;br /&gt;&lt;br /&gt;alert(f()); // function F(){/*IE Function*/};&lt;br /&gt;&lt;/pre&gt;We can play with above IE traps for ages but the point is simple: the last defined function with that name, will simply take the place of the other one, if any, in the same scope, and at the end of its resolution, before code execution.&lt;br /&gt;&lt;br /&gt;What IE does is basically a top-down parsing over functions without taking care at all about code execution or normal and expected syntax execution flow.&lt;br /&gt;This simply means that return whatever, var whatever = function whatever(){} ... does not change anything for our loved IE:&lt;strong&gt;what we see or what we expect is not what will be&lt;/strong&gt;, otherwise IE would have been a perfect browser.&lt;br /&gt;To better understand what I am talking about, this example should speak for me:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var f = 123;&lt;br /&gt;alert(F); // last function&lt;br /&gt;(function(){&lt;br /&gt;alert(F); // (function F(){alert(f);return arguments.callee})&lt;br /&gt;var f = (function F(){alert(f);return arguments.callee})();&lt;br /&gt;// undefined&lt;br /&gt;})();&lt;br /&gt;function F(){};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;After these two snippets is quite logical understand this behavior:&lt;ol&gt;&lt;li&gt;scope resultion&lt;/li&gt;&lt;li&gt;function resolution plus optional inline assignment, if any, before next function resolution&lt;/li&gt;&lt;li&gt;code interpretation/execution over scope resolution&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Accordingly with this &lt;a href="http://groups.google.com/group/comp.lang.javascript/msg/5b508b03b004bce8"&gt;Richard Cornford&lt;/a&gt; post, in JScript every function is performed sending the execution context, a behavior somehow similar to the injected context via eval in Firefox few months ago.&lt;br /&gt;The latter one has been considered a security hole ... same kind of hole we need to deal with IE on daily basis every time we would simply chose a name for a bloody function.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;My Solution&lt;/h3&gt;Juriy perfectly knows my point of view about this problem, he knows it so well that his addEvent solution example is created ad hoc to make mine inefficient (and I'll tell you later why).&lt;br /&gt;It does not matter, as long as I can use the same example, avoiding IE4 support ...&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var addEvent = (function(){&lt;br /&gt;    var docEl = document.documentElement;&lt;br /&gt;    if (docEl.addEventListener) {&lt;br /&gt;      /* return */ function addEvent(element, eventName, callback) {&lt;br /&gt;        element.addEventListener(eventName, callback, false);&lt;br /&gt;      };&lt;br /&gt;    } else {&lt;br /&gt;      // IE has to be the last option&lt;br /&gt;      // other addEvent will be "lost"&lt;br /&gt;      // cause this will be the only named reference&lt;br /&gt;      // in this scope ... &lt;br /&gt;      function addEvent(element, eventName, callback) {&lt;br /&gt;        element.attachEvent('on' + eventName, callback);&lt;br /&gt;      }&lt;br /&gt;    };&lt;br /&gt;    return addEvent;&lt;br /&gt;})();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The key is simple, and is based exactly over same considerations and suggestions Juriy gives in the &lt;a href="http://yura.thinkweb2.com/named-function-expressions/#alt-solution"&gt;Alternative solution&lt;/a&gt; paragraph, except my suggestion uses an explicit last option callback, without requiring &lt;em&gt;var this or that&lt;/em&gt; plus &lt;em&gt;var this or that = null&lt;/em&gt; in any place, and for this purpose.&lt;br /&gt;&lt;br /&gt;Indeed, for the same reason Juriy did not perform this task at the end of his latest suggestion and before the returned function:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;if (typeof docEl.addEventListener != 'undefined') {&lt;br /&gt;      attachEvent = addEventAsProperty = null;&lt;br /&gt;      return addEventListener;&lt;br /&gt;    }&lt;br /&gt;    elseif (typeof docEl.attachEvent != 'undefined') {&lt;br /&gt;      addEventListener = addEventAsProperty = null;&lt;br /&gt;      return attachEvent;&lt;br /&gt;    }&lt;br /&gt;    addEventListener = attachEvent = null;&lt;br /&gt;    return addEventAsProperty;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;totally boring and absolutely anti pattern, on daily basis and real case scenarios, with my suggestion there is absolutely no need to remember to nullify variables used only to refer inline assignments and, moreover, only as Internet Explorer workaround!!! That's too much, I mean we have to change our code, change JS logic, to support such drama JS engine, we even need to write more and nullify everything? No way!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;But It Could Be Inefficient&lt;/h3&gt;The only real side effect about my suggestion, surprisingly working in Safari 2 as well and solving its problems with names, is that if we have to deal with two different versions of IE in the same scope, we cannot use the "&lt;em&gt;last definition&lt;/em&gt;" trick, 'cause one out of 2, 3, or 234567 versions of the most problematic browser since Web epoc, still Internet Explorer and JavaScript speaking, will mess up like a charm ... to be honest, IE4 days, the one without try catch and much more support, are far away from 2009, and I've never had to deal with such problem but in this case, there is nothing better, so far, than Juriy proposal.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;br /&gt;In my addEvent example Opera, thanks to its duality, will behave IE like. This is not a problem, since addEvent will work in any case, but we can return if we would like to force Opera with addEventListener (avoiding Safari 2 then). To solve this problem, when necessarym we can use the best from both proposal.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Re Solution&lt;/h3&gt;&lt;pre class="code"&gt;&lt;br /&gt;  var addEvent = (function(){&lt;br /&gt;    var docEl = document.documentElement,&lt;br /&gt;        addEvent;&lt;br /&gt;    if (docEl.addEventListener) {&lt;br /&gt;      addEvent = function addEvent(element, eventName, callback) {&lt;br /&gt;        element.addEventListener(eventName, callback, false);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;      addEvent = function addEvent(element, eventName, callback) {&lt;br /&gt;        element.attachEvent('on' + eventName, callback);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;    return addEvent;&lt;br /&gt;  })();&lt;br /&gt;&lt;/pre&gt;Quite semantic, isn't it? ;)&lt;br /&gt;The principle is still the same suggested by Juriy except &lt;strong&gt;there is nothing to nullify&lt;/strong&gt;, just a reference to return, and being based on variable assignment, we can have 2345IE versions in the if else without problems at all.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;As Summary&lt;/h3&gt;&lt;strong&gt;In Internet Explorer there is no difference between function expression and function declaration&lt;/strong&gt;, this is the whole point of this post, plus the updated suggestion which makes things a bit more logical, from a developer point of view - addEvent is a well defined &lt;strong&gt;reference&lt;/strong&gt;, and that's what we need.&lt;br /&gt;The &lt;em&gt;var F = null;&lt;/em&gt; in Juriy suggestion is useless for IE. References comes after, in the interpretation flow, while references come before in the execution one. &lt;strong&gt;var F = null; will nullify a reference, it won't mark anything for the IE garbage collector.&lt;/strong&gt;&lt;br /&gt;Juriy article is in any case a must read as soon as we understand JavaScript scope and lambdas, and specially if we would like to support multiple browsers.&lt;br /&gt;Hopefully these &lt;em&gt;gotchas&lt;/em&gt; will disappear with ES5 and the next "dreamed" IE9 with its totally new fabulous V8 engine ( OK, OK, ... let me dream please ... )&lt;br /&gt;The day IE will disappear from browsers panorama I'll be the most happy and drunk web developer in the area but until that day, we can say the panorama is still weird, at least well explained, and with all possible solutions, we have choices!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-6329113639758540919?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/6329113639758540919/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=6329113639758540919" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6329113639758540919" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6329113639758540919" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/WI_diTJB7Vg/named-function-expressions-demystified.html" title="Named function expressions demystified" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/named-function-expressions-demystified.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-8254776307057574279</id><published>2009-10-09T00:47:00.002+02:00</published><updated>2009-10-09T00:54:28.619+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="3site.it" /><category scheme="http://www.blogger.com/atom/ns#" term="devpro.it" /><title type="text">devpro.it is down</title><content type="html">As usual, when there is a merging or an acquisition, the classic "&lt;em&gt;Dear customer, don't worry, everything will be just like before and even better&lt;/em&gt;" becomes automatically "&lt;em&gt;Who are you, what'ya want from us, do we know each other? Re-buy the service if you have troubles!&lt;/em&gt;" ... in few words, devpro.it and 3site.it are down because there is no such thing anymore: the host! ... a little detail, that will be hopefully solved soon (next week at some point).&lt;br /&gt;Fortunately, I have my backup, thanks to SQLite, actually version 2, which has maintained in performances and stability for years and hundreds of thousands of records both read only or constantly changed (counters, stats, code serving).&lt;br /&gt;&lt;br /&gt;Maybe it's a good occasion to re-think devpro.it? Dunno yet, and time is zero, I am just sorry for any inconvenient caused by my different programming languages sources.&lt;br /&gt;&lt;br /&gt;At least we can have fun with a classic video from &lt;a href="http://www.thewebsiteisdown.com/"&gt;The Web Site Is Down&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-8254776307057574279?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/8254776307057574279/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=8254776307057574279" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/8254776307057574279" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/8254776307057574279" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/d9mDSfPBo_Y/devproit-is-down.html" title="devpro.it is down" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/devproit-is-down.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-7670082694154278373</id><published>2009-10-06T01:39:00.006+02:00</published><updated>2009-10-06T03:06:21.693+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="selector" /><category scheme="http://www.blogger.com/atom/ns#" term="performances" /><category scheme="http://www.blogger.com/atom/ns#" term="NWMatcher" /><title type="text">NWMatcher - A Quick Look</title><content type="html">As usual, as soon as I decide it's time to go to sleep, &lt;em&gt;&lt;a href="http://twitter.com/jdalton"&gt;somebody&lt;/a&gt;&lt;/em&gt; :P has to post a stunning benchmark about a selector matcher ... did I shut down? No, I had to read the entire source code of the library, and this is my quick summary, but consider I am tired ...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;a href="http://javascript.nwbox.com/NWMatcher/"&gt;NWMatcher&lt;/a&gt;, A Selector Monster&lt;/h3&gt;First of all, I did not know or remember this project and I must congrats with &lt;a href="http://twitter.com/diegoperini"&gt;Diego Perini&lt;/a&gt; for different reasons.&lt;br /&gt;The first one is that Diego used almost all best and unobtrusive technique to make it as reliable as possible, which is good, the second one is that Diego introduced something new to achieve its goal: create a Ferrari matcher via pre-&lt;em&gt;compiled&lt;/em&gt; functions.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;About NWMatcher&lt;/h3&gt;It is a lightweight stand alone library (so far, but already namespaced) which aim is to standardize some common DOM related task. The initial aim was to create a faster way to understand if a node matches a specific selector, something truly useful with event delegation.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;About The Technique&lt;/h3&gt;To make things as fast as possible, Diego used a pre compilation strategy which is absolutely brilliant. Without XPath transformation, which is also not fully compatible with CSS in any case, and taking care of every single browser "gotcha", Diego creates once, and never again, the function able to perform selector related tasks. The result is that first call a part, with a new selector, the match method will perform a &lt;a href="http://dl.getdropbox.com/u/513327/nwmatcher_match_performance.png"&gt;light speed&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;This is the notable good part of NWMatcher, and now there's the bad one (not that bad in any case)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Few Inconsistencies&lt;/h3&gt;Except a weird procedure to understand if array slice could be performed over nodes, something I always got in 3 lines:&lt;pre class="code"&gt;&lt;br /&gt;var slice = Array.prototype.slice;&lt;br /&gt;try{slice.call(document.childNodes)}catch(e){slice=function(){&lt;br /&gt;    // whatever to emulate slice for this scope&lt;br /&gt;}};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Diego uses a callback to understand native methods from fakes. This is generally good, and this function is isNative, but since these kind of checks are for greedy developers with global pollution maniac, I cannot understand why at some point there is a root.addEventListener ? ... and no checks if addEventListener is native one, something that could make the entire caching system useless or able to generate errors. OK, that would be silly, I mean to inject an event like that, impossible to emulate in Internet Explorer, but who knows what a library could do with such event ...&lt;br /&gt;Another inconsistency is about being unobtrusive, goal reached 99.9% ... what is that, a public property attached directly in the used context? We need to be aware that the document will probably have a snapshot, plus an isCaching property, not a drama, but I think those are the exception that confirm the rule.&lt;br /&gt;Another thing I'll never get is the usage of new in front of functions which aim is to return a non primitive value.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;function A(){&lt;br /&gt;    return {};&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Above function could be called with or without new and the result will be always the same, the returned object. This simply means that if we use new we are &lt;strong&gt;consuming CPU and RAM for no reason&lt;/strong&gt;. So why a performances based library should not take care of this simple fact?&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// example&lt;br /&gt;function Snapshot(){&lt;br /&gt;    // here this exists&lt;br /&gt;    // and it has a prottype attached&lt;br /&gt;    // and it has been internally initialized&lt;br /&gt;    // to be used as Snapshot instance&lt;br /&gt;&lt;br /&gt;    // we return an instanceof Object?&lt;br /&gt;    // well done, so the garbage collector&lt;br /&gt;    // has to consider this instance&lt;br /&gt;    // which is a ghost instance, never used&lt;br /&gt;    // but it has been created&lt;br /&gt;    return {&lt;br /&gt;        // whatever ...&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// let every comment inside the function&lt;br /&gt;// make sense simply adding new&lt;br /&gt;var snap = new Snapshot();&lt;br /&gt;&lt;br /&gt;// a non-sense, imho, since this&lt;br /&gt;// would have produced exactly the same&lt;br /&gt;// without instance generations&lt;br /&gt;var snap = Snapshot();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it. This stuff is really simple to get with C, C++, or those languages where we have to declare types, names, etc etc, and a new in front of a function is not transparent, is something to think about, cause a new is a new, we are asking for an instance, and a function able to return always another value, rather than the generated instance, shouldn't be called via new.&lt;br /&gt;&lt;br /&gt;Diego, I am sorry, I am using this irrelevant gotcha simply because I wrote about these things dunno how many times ... please remove every new Snapshot from your code, or just use the instance, attaching proeprties.&lt;pre class="code"&gt;&lt;br /&gt;Snapshot =&lt;br /&gt;    function() {&lt;br /&gt;        this.isExpired = false;&lt;br /&gt;        this.ChildCount = [ ];&lt;br /&gt;        this.TwinsCount = [ ];&lt;br /&gt;        this.ChildIndex = [ ];&lt;br /&gt;        this.TwinsIndex = [ ];&lt;br /&gt;        this.Results = [ ];&lt;br /&gt;        this.Roots = [ ];&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Makes sense? For performances reason, I still suggest to simply remove every new, leaving just Snapshot ... OK, that is probably more than I was planning to say ...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mutation Events Side Effects&lt;/h3&gt;For compatible browsers NWMatcher uses mutations events such DOMAttrModified, DOMNodeInserted, and DOMNodeRemoved. The cache is partially arbitrary, activated by defaults, deactivated via setCache(false).&lt;br /&gt;Mutations events are used to cache results. Why mutation events? Let's say in a single function is so common, specially in jQuery world as example, to search the same bloody thing hundreds of time ...&lt;pre class="code"&gt;&lt;br /&gt;$("body").doStuff($whatever);&lt;br /&gt;$("body").doOtherStuff($whatever);&lt;br /&gt;$("body").doSomethingElse();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Above way to code is present in dunno how many examples, articles, books, and is as elegant as illogical. If we need a collection, I know we all like the $("thingy") style, but it's that difficult to write code such:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var $body = $("body"); // that's it, wrapped once, SPEED!&lt;br /&gt;$body.doStuff($whatever);&lt;br /&gt;$body.doOtherStuff($whatever);&lt;br /&gt;$body.doSomethingElse();&lt;br /&gt;&lt;/pre&gt;I am sure it is difficult, and Diego knows this stuff better than me, indeed he is using result cache to avoid repetitive expensive searches over potentially massive structures as a DOM could be, in order to guarantee best returned results performances. So far, so good ... and mutations events, attached to the root of the DOM, the document, are able to clear the cache ... how? via a callback. Simple? Sure, it is simple ... but there is a little detail we should consider.&lt;br /&gt;&lt;br /&gt;Nowadays, Ajax based Web applications are &lt;strong&gt;constantly muted&lt;/strong&gt;, eachAjax call aim is to change something, show something, or remove something. With these perpetual changes whatever event is attached into a mutation event will be fired dozen of times but Diego, which is not the last JavaScript hacker, found a way to partially avoid this problem. He removes the mutation so the first fired one, will avoid same operations for other N times. This is good, but there is still an event to manage, internally, and a callback to call, but the bad part is that for each select, those events have to be reassigned, or checked, again (isCached attaced property).&lt;br /&gt;Talking about performances, we need to consider the real case scenario, rather than a static benchmark over the same selection, or couple of selections, where nodes are, as I have said, constantly changed via innerHTML, innerText, appendChild, removeChild, insertBefore, insertAfter, all operations probably present in every single function of our JavaScripted page.&lt;br /&gt;&lt;br /&gt;Now, is it truly worth it to cache results? Why, if it was the key, browser vendors are not caching results when we perform a getWhateverByWhatever or querySelectorAll?&lt;br /&gt;Is our library truly that slow that a couple of searches performed consecutively are such big problem so we need to increase libraries complexities, side effects, and browser problems/behaviors, for something that on daily basis will be used I guess 5% of the time due to constant DOM manipulation?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Always Cached Matches&lt;/h3&gt;The brilliant strategy used to pre compile functions could be a bit greedy if used lots of time, over lots of different CSS queries, and for a long online session. What am I talking about? Mobile devices, a la iPhone with 2Mb of RAM limit, and all those lambdas stored in any case in memory. Is there any test about this? I'd love to see or create one, but I need a good iPhone web app before. Finally, this is just a hint, when the selector "*" is present, I think there is no point to parse anything or create the pre-compiled function. That return true in the body, should be enough, so in dozen of reg exp, I would have used a simple "*" check, and return just true. OK, talking about consistency, this is not a real case scenario, 'cause we have to be silly to know if a node matches "*" ... of course it will ... but what we should not forgot, at least in version 1.1.1, is that a node, not present in the DOM, will match "*" in any case, as is for every other match. This could be Diego aim as well, not sure WebKit and FF nightly behave the same, but I honestly don't think a non rendered element should match a CSS selector...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;As Summary&lt;/h3&gt;NWMatcher is definitively the best answer I have seen so far to match a css. Diego experience is everywhere in the code, and people in credits gave good help and advices as well. I have been probably too strong about these few things I have spot in the code, but I am planning to use NWMatcher and to test it on mobile devices as well so the purpose of this post is: please, make it perfect Diego, and thanks a lot, truly good stuff!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-7670082694154278373?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/7670082694154278373/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=7670082694154278373" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/7670082694154278373" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/7670082694154278373" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/OViBEoCeAPI/nwmatcher-quick-look.html" title="NWMatcher - A Quick Look" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/nwmatcher-quick-look.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-2741622984513865851</id><published>2009-10-05T23:14:00.004+02:00</published><updated>2009-10-05T23:19:52.925+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Options" /><category scheme="http://www.blogger.com/atom/ns#" term="Batch" /><category scheme="http://www.blogger.com/atom/ns#" term="Frame" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrome" /><title type="text">Chrome Frame Options</title><content type="html">As posted in Frame ML, &lt;a href="http://twitter.com/WebReflection/status/4637700115"&gt;twitted&lt;/a&gt; after (exactly 140 chars :D), and uploaded on my &lt;a href="http://code.google.com/p/chromefix/"&gt;chromefix&lt;/a&gt; page, there is a new batch script file able to launch frame and let us clear, as example, the cache or perform some other operation.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;start &amp;quot;Frame&amp;quot; /B &amp;quot;%PROGRAMFILES%\Google\Chrome Frame\Application\chrome.exe&amp;quot; &amp;quot;--user-data-dir=%APPDATA%\Google\ChromeExp\User Data\iexplore&amp;quot;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The reason this launcher could be useful is that apparently the cache used via Frame could be blocked and the user unable to clean it via common IE options procedure.&lt;br /&gt;Enjoy, and thanks Tommi for the tip.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-2741622984513865851?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/2741622984513865851/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=2741622984513865851" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/2741622984513865851" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/2741622984513865851" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/mzjSOlYASmg/chrome-frame-options.html" title="Chrome Frame Options" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/chrome-frame-options.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-6578792705414362411</id><published>2009-10-04T11:05:00.003+02:00</published><updated>2009-10-04T11:14:11.545+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="Math" /><category scheme="http://www.blogger.com/atom/ns#" term="decimal" /><category scheme="http://www.blogger.com/atom/ns#" term="broken" /><category scheme="http://www.blogger.com/atom/ns#" term="module" /><title type="text">[Q&amp;D] Fix Decimal Module Operator</title><content type="html">This is a &lt;acronym title="Quick And Dirty"&gt;Q&amp;D&lt;/acronym&gt; solution for some JavaScript precision problem when we use the module operator with floating point numbers.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Problem&lt;/h3&gt;If we are dealing with the module operator we could have this case:&lt;pre class="code"&gt;alert(&lt;br /&gt;    8.25 % .05&lt;br /&gt;);&lt;br /&gt;// 0.049999999999999545 &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We expected 0 but we have a floating point inconsistency instead. This is a well known problem, and not only with JavaScript, truly annoying when we have to show run-time computed money/trends operations.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Solution&lt;/h3&gt;This comes from my reply in a JS forum, knowing that the module will be a simply floating point, let's say .1 to .001, if we remove floating point from the right side of the operation everything works just fine:&lt;pre class="code"&gt;&lt;br /&gt;function mod(num, mod){&lt;br /&gt;    // Another WebReflection silly idea&lt;br /&gt;    var pow = Math.pow(10, (("" + mod).split(".")[1] || "").length);&lt;br /&gt;    return ((num * pow) % (mod * pow)) / pow;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;alert(&lt;br /&gt;    mod(8.25, .05)&lt;br /&gt;);  // 0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;alert(&lt;br /&gt;    mod(8.25, .1)&lt;br /&gt;);  // 0.5&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's it, have a nice Sunday&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-6578792705414362411?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/6578792705414362411/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=6578792705414362411" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6578792705414362411" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6578792705414362411" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/SPOXT4iuEe0/q-fix-decimal-module-operator.html" title="[Q&amp;D] Fix Decimal Module Operator" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/q-fix-decimal-module-operator.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-6078400295169985062</id><published>2009-10-01T20:23:00.004+02:00</published><updated>2009-10-01T21:03:38.246+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="TechHub" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows" /><category scheme="http://www.blogger.com/atom/ns#" term="IE6" /><category scheme="http://www.blogger.com/atom/ns#" term="Ajaxian" /><title type="text">Randomly Speaking ...</title><content type="html">These days have been a bit chaotic, lots of news, good and bad, unfortunately somebody decided a day has only 24 hours and somebody else decided sometimes we need to sleep, so from 24 we pass to 18 ... this is a quick random post about changes and thoughts&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;I Am &lt;a href="http://ajaxian.com/about-us#AndreaGiammarchi"&gt;One Of The Ajaxians&lt;/a&gt;!&lt;/h3&gt;Thanks to &lt;a href="http://ajaxian.com/about-us#DionAlmaer"&gt;Dion Almaer&lt;/a&gt;, or if you prefer "&lt;em&gt;it's Dion fault!!!&lt;/em&gt;", I am glad to be one of those guys there talking about everything Web related, development, techniques, news, mobiles, whatever, as long as it makes sense and will keep us updated with the latest kill app.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Formaldehyde Has Been Updated&lt;/h3&gt;My simple &lt;a href="http://code.google.com/p/formaldehyde/"&gt;Ajax / PHP debugger&lt;/a&gt; has slightly changed to solve a couple of annoying bugs. One was a typo, another one a new XHR feature (or better, limit) so theoretically, Formaldehyde should not caouse problems anymore.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Real Problem Is Not IE6 But Windows 2000, 98, Me&lt;/h3&gt;&lt;a href="http://code.google.com/chrome/chromeframe/"&gt;Google Chrome Frame&lt;/a&gt; demonstrated that &lt;strong&gt;people want a better browser&lt;/strong&gt; but there are still so many companies stuck in &lt;strong&gt;deprecated operating systems&lt;/strong&gt;.&lt;br /&gt;The most interesting analysis I could do is thanks to &lt;a href="http://groups.google.com/group/google-chrome-frame/browse_thread/thread/96826f25ac27b2e3"&gt;this reply in Frame ml&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Our company uses ALMOST 100% Windows 2000 OSes ... in our business, we always use a web application that uses a LOT of javascript, IE6 is Slow and always gets a javascript Error and needed the browser to restart.. the employees productivity&lt;br /&gt;is continually monitored, this browser failures are a big problem.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Please let me summarize with a reply ...&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Dear Companies&lt;/h3&gt;If your business is mainly based over a web/network architecture, the only one that will fall down day after day will be simply &lt;strong&gt;your business&lt;/strong&gt;. An upgrade does not cost anything, and old PCs could install without any problems whatever free Operating System without slowing down your productivity making you, and your business, &lt;strong&gt;updated&lt;/strong&gt;, 'cause the rest of the world and everything that works behind a browser is moving forward, so you are simply deciding to &lt;strong&gt;stay behind without a valid reason&lt;/strong&gt;.&lt;br /&gt;How can you justify slow productivity? How much this slow productivity, missed IE6 features, and an old, deprecated, application based over IE6, can mean for your incomes? &lt;strong&gt;Think!&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The London JavaScript Group Should Survive!&lt;/h3&gt;This is the bloody Europe financial capital and one of the main IT center and nobody is interested into the programming language of the past, the present, and the future? &lt;strong&gt;This is unacceptable&lt;/strong&gt;, is often thanks to JavaScript ignorance that our business is not that interesting as USA one ... with all those new thingy that "&lt;em&gt;must be Flash or Silverlight!&lt;/em&gt;" while nowadays, 70% of the time, it is &lt;strong&gt;simply JavaScript&lt;/strong&gt;!!! If I could have produced some silly stuff like the &lt;a href="http://www.3site.eu/examples/liquid/vaio.html"&gt;Liquid FX&lt;/a&gt;, guess how much JavaScript skills and knowledge could bring inside your on-line applications. Be interested, and do not follow Jurassic patterns a la "&lt;em&gt;server side developer and just a web designer with jQuery knowledge&lt;/em&gt;", this is not enough for whatever start-up or whatever web based service.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;TechHub Is Getting Started&lt;/h3&gt;This IS what I was expecting from this city when I moved here almost 2 years ago and not a dead JavaScript group ... &lt;strong&gt;&lt;a href="http://techhub.com/"&gt;ThechHub&lt;/a&gt;&lt;/strong&gt;, finally some fresh air outside deprecated development models so loved in most of those companies fell down during the credit crunch ... &lt;strong&gt;Innovation&lt;/strong&gt; is the key, everything that let us survive is wrong, everything that let us grow up, is good ... even in latter case, we could grow up even more, doing right steps, &lt;strong&gt;Think&lt;/strong&gt;!&lt;br /&gt;&lt;br /&gt;That's it, told'ya it was random ... have a nice week end if I won't have time to post again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-6078400295169985062?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/6078400295169985062/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=6078400295169985062" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6078400295169985062" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/6078400295169985062" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/4J2YHiPqn6o/randomly-speaking.html" title="Randomly Speaking ..." /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/10/randomly-speaking.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-4942556262074119143</id><published>2009-09-25T01:33:00.002+02:00</published><updated>2009-09-25T01:37:59.660+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="default" /><category scheme="http://www.blogger.com/atom/ns#" term="on" /><category scheme="http://www.blogger.com/atom/ns#" term="Frame" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="toolbar" /><category scheme="http://www.blogger.com/atom/ns#" term="button" /><title type="text">Chrome Frame Always On IE Toolbar Button</title><content type="html">As promised in the CF ML, here I am with the first Chrome Frame Button application.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.3site.eu/chrome/chrome_frame_button.gif" /&gt;&lt;br /&gt;&lt;br /&gt;It's beta not because of its functionality, it works 100% at least in my old laptop, but because when you click the button the Chrome Frame is always on or of as expected, but to see the new icon or the new label we need to restart IE.&lt;br /&gt;&lt;br /&gt;Anyway, this button is not created to switch every second, this button is "just for fun", as fun was the &lt;a href="http://webreflection.blogspot.com/2009/09/chrome-frame-on-by-default.html"&gt;first always on application&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;How it works? Grab the zip file from my &lt;a href="http://code.google.com/p/chromefix/"&gt;chromefix&lt;/a&gt; project. Unpack it, and read the file README.TXT ... it's really simple, basically a double click and nothing else&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-4942556262074119143?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/4942556262074119143/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=4942556262074119143" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4942556262074119143" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4942556262074119143" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/wM5VLhO3hzc/chrome-frame-always-on-ie-toolbar.html" title="Chrome Frame Always On IE Toolbar Button" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/chrome-frame-always-on-ie-toolbar.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-1028161578808907535</id><published>2009-09-24T22:31:00.006+02:00</published><updated>2009-09-24T23:16:12.340+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="quality" /><category scheme="http://www.blogger.com/atom/ns#" term="software" /><category scheme="http://www.blogger.com/atom/ns#" term="bug" /><title type="text">Software Quality - We Are Loosing It</title><content type="html">This may sounds silly, surely not technical, but today I've lived the last drop before crackpots!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;IE6 Inside The Cash Point&lt;/h3&gt;I am not joking, I have no idea how many cash points use windows and IE to run a 7 screens software. Have you never noticed a "&lt;em&gt;click clack&lt;/em&gt;" while you are performing your operations?&lt;br /&gt;OK, maybe banks do not even buy Microsoft licenses, or maybe those are dedicated cache machine version of Windows, but I could never imagine to find a windows popup with an error in a cache machine, it is ridiculous!&lt;br /&gt;Those one with just text? Well, they look old and ugly, but I've rarely seen one disabled.&lt;br /&gt;We have dozen of valid Operating System able to perform the same software for years without requiring a single reboot. How difficult will be to create an OS specific for a cash point where operations are always the same, adding just 1 image format supported? What I mean is that you can find active screens with lottery ads inside running 24/7 without problems over a hilarious hardware.&lt;br /&gt;Take one of them, add 20 buttons function, that's all we need to click: £10 and digit few numbers, isn't it?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Hub 2.0 Router Firmware Disaster&lt;/h3&gt;I am having constant problems with my ADSL since the first day. First of all the company wrote in the website that for first 10 days I could have noticed disservice but after everything would have been fine. So far, so cool, I was freaking out thinking "&lt;em&gt;OMG, my router is alive, it programs itself!!!&lt;/em&gt;" ... then I have simply realized that this company is just selling, so once they bring you the router they have a ready excuse if things are not working as expected ... you have already signed, and good luck with assistance 5 days a day, without specific hours, and during the week ... sure, I day off to wait somebody for somethig I am already paying.&lt;br /&gt;Moreover, without touching anything, and monitoring the router directly via its interface, they asked me via phone if I was in Wireless or Cable ... I mean: &lt;em&gt;WHAT? THE ROUTER IS TELLING ME ITS SPEED, I HAVE NOT A NETWORK PROBLEM!!!&lt;/em&gt;&lt;br /&gt;It does not matter, I am struggling with 160kbps of bandwidth and apparently, even if for 2 weeks everything was almost fine, now it's my problem ... they need to come here ... to do what?&lt;br /&gt;Checking online the firmware of this router has the worst history ever.&lt;br /&gt;Is it that difficult to develop a firmware or this company just payed the cheapest one "&lt;em&gt;who cares about the software if it works somehow&lt;/em&gt;"?&lt;br /&gt;Right, now I have the latest version of one of the most problematic firmware I have ever seen. I was complaining with ASUS and its firmware nightmare where nightmare meant 1 every year and now I have discovered than a much simple device has so many software problem ... OK, cheap router, but they sell it like gold, and crappy software ... that's cool!!! I wonder how many problems there could be in a standard configuration as whatever phone line is. Is too noisy? Cable problems? No, it's the router, but they'll never tell us their router has problem. Most likely they'll let us buy a new PC to discover that the problem was not the PC ... cool!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Supermarket Big Chains With Bugged Self Check Out&lt;/h3&gt;Again, I am not joking, in the place where I go almost every day to buy something for lunch I hve never seen all self check out machines active without problems, &lt;strong&gt;never&lt;/strong&gt;!&lt;br /&gt;The hardware is pretty simple though, touch screen with basically 3 big buttons, a barcode reader, and a money counter for the change. Simple, isn't it? &lt;strong&gt;It's not&lt;/strong&gt;, 'cause these machines never work more than 2 consecutive days ... always problems. Well done Big Chain, as summary you paid the cheapest machines, and your are paying 10 times more due to constant problems these machines have. Everybody does its business, right? Today there were 2 3 of us stuck in front of these machines all without notes change ... I mean, the machine counts money, it is never wrong with the change, and &lt;strong&gt;it does not understand when it is finished&lt;/strong&gt;? The money scanner knows there's no money left there, and it tries again, and again, and again ... used software did not think that when it's finished, it's finished, the machine should simply start to flash the top red light with a clear warning: I HAVE NO MORE MONEY&lt;br /&gt;This would make everything more efficient, since I spent 10 minutes in a self check out machine rather than 1 in the human driven one ... cool!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Run To Deliver&lt;/h3&gt;Too many competitors, but apparently it's not the same about developers quality. This is true for the web, for microwaves, for every electric stuff ... the hardware does not cost anymore, &lt;strong&gt;what we pay is always the software&lt;/strong&gt;. 20 years ago there was less software but hell if it was working as expected. Nowadays, software development time is too frenetic, there is no time to do a proper analysis, no time to properly structure the code, no time to write decent comments, no time to describes problems, no time for brainstorming, no time to find the best solution, the first that quickly work is fine ... &lt;strong&gt;everything is a quick fix&lt;/strong&gt;, and if it is not and we had time to things properly, we won't have time to create &lt;strong&gt;unit tests&lt;/strong&gt;. Agile, SCRUM, Extreme, these therms are rarely concretely applied over whatever development team but they are fashionable therms, so everybody is Agile today ... We used that OS lib, without showing credits anywhere in our sold application, we have quickly fixed everything without testing, but &lt;strong&gt;we have respected the ridiculous deadline&lt;/strong&gt; 'cause the customer is waiting ... but isn't the customer the one unhappy when things do not work as expected?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;AS Summary&lt;/h3&gt;We need to slow down, we need to think more, we need to understand why that program worked better, why that library is solving this or that problem and &lt;strong&gt;how&lt;/strong&gt; it is doing it, if we would like to be able to extend it or to customize it. This "&lt;em&gt;1 hour deadline&lt;/em&gt;" for everything is visible, touchable, on daily basis with daily software wherever it is ... what is going on? We can't blame always outsourcing though, isn't it?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-1028161578808907535?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/1028161578808907535/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=1028161578808907535" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1028161578808907535" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1028161578808907535" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/Gic4fDv9HC4/software-quality-we-are-loosing-it.html" title="Software Quality - We Are Loosing It" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/software-quality-we-are-loosing-it.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-8159137231413779783</id><published>2009-09-24T08:41:00.004+02:00</published><updated>2009-09-24T08:55:18.222+02:00</updated><title type="text">Chrome Frame On By Default ?</title><content type="html">A quick one for those interested into Frame switch on.&lt;br /&gt;Two options&lt;ul&gt;&lt;li&gt;use regedit to add or modify the key HKCU\Software\Google\ChromeFrame\OptInUrls with char *&lt;/li&gt;&lt;li&gt;download my &lt;a href="http://code.google.com/p/chromefix/"&gt;Chrome Frame Switch&lt;/a&gt; executable application.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Latter one, is a zip with two versions of the same application, one for 32bit, one for 64bit. The application allows us to automatically set or remove that register key.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.3site.eu/ChromeFrameSwitch.gif" width="209" height="83" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-8159137231413779783?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/8159137231413779783/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=8159137231413779783" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/8159137231413779783" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/8159137231413779783" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/Djs8juQYNzE/chrome-frame-on-by-default.html" title="Chrome Frame On By Default ?" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/chrome-frame-on-by-default.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-1759927257637387812</id><published>2009-09-23T19:55:00.013+02:00</published><updated>2009-09-26T10:44:36.058+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Frame" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="Google" /><category scheme="http://www.blogger.com/atom/ns#" term="tests" /><category scheme="http://www.blogger.com/atom/ns#" term="impression" /><title type="text">Google Chrome Frame - A First Look</title><content type="html">In one single day the news about &lt;a href="http://code.google.com/chrome/chromeframe/"&gt;Google Chrome Frame&lt;/a&gt; has reached, I suppose, every web related company or developer. &lt;a href="http://webreflection.blogspot.com/2009/09/web-terminator-salvation-google-chrome.html"&gt;As posted before&lt;/a&gt;, I hope this plug-in will be adopted soon throwing away every other plug-in "&lt;em&gt;record&lt;/em&gt;", thanks to its target: the most used, discussed, slow, and not standard, casa Microsoft default browser, Internet Explorer.&lt;br /&gt;I have spent part of my precedent night &lt;strike&gt;sleeping&lt;/strike&gt; testing this little revolution from Big G. and here there are first suggestions, impressions, results.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Correct Way To Set Chrome Frame&lt;/h3&gt;The Google &lt;a href="http://code.google.com/chrome/chromeframe/developers_guide.html"&gt;Getting Started&lt;/a&gt; guide is a good lecture, but &lt;strong&gt;it is not enough&lt;/strong&gt;.&lt;br /&gt;The &lt;a href="http://code.google.com/chrome/chromeframe/developers_guide.html#Making_Your_Pages_Work"&gt;Making Your Pages Work with Google Chrome Frame&lt;/a&gt; is incomplete, and I will tell you why.&lt;br /&gt;First of all, we need to understand that Chrome is a &lt;strong&gt;Runtime Embedded Browser&lt;/strong&gt; plug-in, not a tag related one then, as Adobe Flash Player is.&lt;br /&gt;Writing something like:&lt;blockquote&gt;Just add this tag to the top of the page: That's it!&lt;/blockquote&gt; is confusing and not that detailed info.&lt;br /&gt;A meta tag is normally placed in the header one, top of the page, but as soon as developers read about "&lt;em&gt;that's it&lt;/em&gt;" most of them tried to add via JavaScript this meta tag to switch engine: &lt;strong&gt;this is wrong&lt;/strong&gt;.&lt;br /&gt;We cannot mess up IE default Trident engine with a completely different one as WebKit via Chrome Frame is. Different are also variables, if any, globals, if any, render itself, and the best case scenario is that &lt;em&gt;everything will break up&lt;/em&gt;!&lt;br /&gt;As summary, runtime browser switch is not truly a good practice, for both main page, or iframes, since the Chrome Frame nature is to change the entire browsed content and since it does not make sense to have such hybrid, non-sense, configuration between JScript and V8, Trident and WebKit.&lt;br /&gt;Accordingly, the best way to activate Chrome Frame is to put in the head tag, top of the page, and before whatever JavaScript action, the meta.&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;        &amp;lt;title&amp;gt;Google Chrome Frame&amp;lt;/title&amp;gt;&lt;br /&gt;        &amp;lt;meta http-equiv=&amp;quot;content-type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&amp;gt;&lt;br /&gt;        &amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;chrome=1&amp;quot; /&amp;gt;&lt;br /&gt;    ... the rest of the page, scripts, css, whatever&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That is still not it!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Detecting Google Chrome Frame and Prompting to Install&lt;/h3&gt;One more time, we need to thanks Google for all this effort but &lt;a href="http://code.google.com/chrome/chromeframe/developers_guide.html#Detecting_Google_Chrome_Frame"&gt;suggested solution&lt;/a&gt; &lt;strong&gt;is not ideal&lt;/strong&gt;! (quick update: Alex Russel agrees, so the page is hpefully gonna change soon).&lt;br /&gt;Chrome Frame is, so far, an Internet Explorer related plug-in which means that the external script will not do anything interesting with every other browser such Firefox, Opera, Safari, or Chrome.&lt;br /&gt;Google truncates web pages (body tag) to make things as fast as possible but it is suggesting us a "&lt;em&gt;slowdown without reasons&lt;/em&gt;" practice.&lt;br /&gt;The best way to suggest Chrome Frame is to put that external script in a &lt;strong&gt;conditional comment&lt;/strong&gt;:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;        &amp;lt;title&amp;gt;Google Chrome Frame&amp;lt;/title&amp;gt;&lt;br /&gt;        &amp;lt;meta http-equiv=&amp;quot;content-type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&amp;gt;&lt;br /&gt;        &amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;chrome=1&amp;quot; /&amp;gt;&lt;br /&gt;        &amp;lt;!--[if IE]&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;![endif]--&amp;gt;&lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;    document.body.appendChild(&lt;br /&gt;        document.createTextNode(navigator.userAgent)&lt;br /&gt;    );&lt;br /&gt;    &amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If for some reason we are worried about how to know if IE supports the plug-in, all we need to do is this:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var cf = (function(i,ua){&lt;br /&gt;return i&amp;lt;ua.indexOf("chromeframe")||i&amp;lt;ua.indexOf("x-clock")&lt;br /&gt;})(-1,navigator.userAgent.toLowerCase());&lt;br /&gt;// cf is true when plug-in is installed&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Do We Truly Need To Know?&lt;/h3&gt;I think IE support cannot disappear today, I wish it would, but that's not gonna happen. If we develop a cross-browser Web application/site is quite useless to understand if we are using the plug in or not, 'cause if Google Chrome will be supported, special features detections a part, the website will simply looks exactly as it looks in Chrome.&lt;br /&gt;I cannot spot a single valid reason, except the &lt;em&gt;Install Prompt&lt;/em&gt; for IE, to include that file &lt;strong&gt;but&lt;/strong&gt; my crystal ball says that Chrome Frame is planning to be installed as plug-in in other browsers as well in a not that far future ... so one day maybe it will make sense to remove that script from conditional comments.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Server Side Chrome Activation ?&lt;/h3&gt;Not yet, apparently an header in the server with chrome=1 value is useless. I hope this is a temporary issue 'cause to avoid switch delay once Trident has been already started, the server side header could be the best solution. On the other hand, being Chrome a Trident plug-in, I think Trident needs to start before the plug-in can be activated ... uhm, hell problem!&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// this won't have effect so far ... &lt;br /&gt;header('X-UA-Compatible: Chrome=1', true);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;br /&gt;To understand if the browser will be render the page via Chrome Frame we can use this snippet as example:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;$userAgent = $_SERVER[&amp;apos;HTTP_USER_AGENT&amp;apos;];&lt;br /&gt;if(&lt;br /&gt;    strpos($userAgent, &amp;apos;chromeframe&amp;apos;) !== false&lt;br /&gt;) {&lt;br /&gt;    // your cool standard layout for Chrome&lt;br /&gt;} else {&lt;br /&gt;    // your crappy IE dedicated one&lt;br /&gt;}&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;My First Impression&lt;/h3&gt;Enabling runtime Chrome Frame via url, &lt;em&gt;cf:&lt;/em&gt; as url prefix, I have tested &lt;a href="http://dante.dojotoolkit.org/taskspeed/"&gt;Taskspeed&lt;/a&gt; and many others benchmarks realizing that if I had used Google Chrome the result would have been exactly the same.&lt;br /&gt;The only difference is the little delay, &lt;em&gt;not that little&lt;/em&gt; with extremely old hardware, when the meta tag is interpreted and the switch activated runtime, specially the first time.&lt;br /&gt;Chrome Frame is in any case 100% WebKit and Chrome. &lt;strong&gt;IE features&lt;/strong&gt;, included conditional comments, for both layout or script, attachEvent and friends or CSS expressions, &lt;strong&gt;are not supported&lt;/strong&gt;.&lt;br /&gt;While features such V8 &lt;strong&gt;multi tab threading is supported&lt;/strong&gt; ... again, 100% Chrome.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;What's Next ?&lt;/h3&gt;I am prety much sure the reason this plug-in is not stable is the native OS integration nature of Internet Exploer.&lt;br /&gt;Talking about IE8 we have Accelerators and other specific stuff that will probably not work with this plug-in, but personally I have never used them.&lt;br /&gt;In the Jurassic IE6 case the Operating System dependency is more than hard, and so far it is the most problematic browser but right now I have never encountered a single problem with this plug-in and to make it stable as soon as possible we all need to install it and test it in every single page. This procedure will help Chromium team to better and faster understand possible troubles, if any, so let's contribute: in the worst case scenario we'll have a better Web experience thanks to Chrome overall stunning performances, standards and HTML5 support.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;P.S.&lt;/strong&gt; the Developer console in IE8 should be activatd before the switch, and not after, otherwise with this version it won't work!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-1759927257637387812?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/1759927257637387812/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=1759927257637387812" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1759927257637387812" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1759927257637387812" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/AqjNxx7LlM8/google-chrome-frame-first-look.html" title="Google Chrome Frame - A First Look" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/google-chrome-frame-first-look.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-4481644925583675935</id><published>2009-09-22T23:23:00.008+02:00</published><updated>2009-09-23T00:23:04.808+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="Revolution" /><category scheme="http://www.blogger.com/atom/ns#" term="Frame" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="Google" /><title type="text">Web Terminator Salvation - Google Chrome Frame</title><content type="html">&lt;strong&gt;&lt;a href="javascript:void(location.href='cf:'+location.href)"&gt;Google Chrome Frame Bookmark&lt;/a&gt;&lt;/strong&gt;, if you are surfing for whatever reason in IE, right click in precedent link, add to favorite and save as: &lt;strong&gt;FINALLY THE WEB&lt;/strong&gt;, or simply copy this code and past in the website url you are surfing with IE&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// corrected via kangax&lt;br /&gt;javascript:void(location.href='cf:'+location.href));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;It's the beginning of a &lt;strong&gt;Web Revolution&lt;/strong&gt;, it's the dream of every Web developer, it's the annihilation of the most slow, problematic, non-standard, engine ever: the whatever version inside Internet Explorer!&lt;br /&gt;&lt;br /&gt;It's the "&lt;em&gt;Say Fucking What? Buggy Flash Player Yes For Ages And &lt;a href="http://blog.chromium.org/2009/09/introducing-google-chrome-frame.html"&gt;Chrome Frame&lt;/a&gt; No?&lt;/em&gt;" era, it's something &lt;a href="http://webreflection.blogspot.com/2009/04/internet-explorer-with-v8-engine.html"&gt;I've been trying for ages&lt;/a&gt; without that direct switch, provided by this plug-in, able to forget Internet Explorer except its frame (weird choice about the name though, Google) ... it's the new stats where IE could increase again it's market share who fuckin' care as long as we can &lt;strong&gt;finally develop real web applications&lt;/strong&gt;, is the &lt;strong&gt;no more need to wait that pachyderm&lt;/strong&gt; libraries development ... is that ...&lt;br /&gt;&lt;br /&gt;... uh wait, now we have another IE scenario to test ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-4481644925583675935?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/4481644925583675935/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=4481644925583675935" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4481644925583675935" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4481644925583675935" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/-X6PLoe1Ft4/web-terminator-salvation-google-chrome.html" title="Web Terminator Salvation - Google Chrome Frame" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/web-terminator-salvation-google-chrome.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-323975706399739457</id><published>2009-09-21T22:15:00.006+02:00</published><updated>2009-09-21T23:08:01.491+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="all" /><category scheme="http://www.blogger.com/atom/ns#" term="getElementsByTagName" /><category scheme="http://www.blogger.com/atom/ns#" term="getElementsByClassName" /><category scheme="http://www.blogger.com/atom/ns#" term="LiveMonitor" /><category scheme="http://www.blogger.com/atom/ns#" term="live" /><category scheme="http://www.blogger.com/atom/ns#" term="document" /><title type="text">One Function To Trap Them All</title><content type="html">This is a quick one. This technique could have some side-effect I am not aware about but I've never seen it so far in any library. Talking about &lt;a href="http://webreflection.blogspot.com/2009/09/livemonitor-asynchronous-property.html"&gt;LiveMonitor&lt;/a&gt; I have successfully tested same concept to create faster implementation of some of my DOM common code, not yet updated in &lt;a href="http://code.google.com/p/vice-versa/"&gt;vice-versa&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;document.getElementsByClassName Example&lt;/h3&gt;&lt;pre class="code"&gt;&lt;br /&gt;(function(childNodes){&lt;br /&gt;&lt;br /&gt;/* Another (C) WebReflection Silly Idea */&lt;br /&gt;&lt;br /&gt;// how to re-use them all, just an example&lt;br /&gt;if(!document.getElementsByClassName)&lt;br /&gt;    document.getElementsByClassName = function getElementsByClassName(className){&lt;br /&gt;        for(var&lt;br /&gt;            re = new RegExp(&amp;quot;(?:\\s|^)&amp;quot; + className + &amp;quot;(?:\\s|$)&amp;quot;),&lt;br /&gt;            ret = [], i = 0, l = 0, length = childNodes.length, node;&lt;br /&gt;            i &amp;lt; length; ++i&lt;br /&gt;        ){&lt;br /&gt;            if((node = childNodes[i]).nodeType === 1 &amp;&amp; re.test(node.className))&lt;br /&gt;                ret[l++] = node&lt;br /&gt;            ;&lt;br /&gt;        };&lt;br /&gt;        return ret;&lt;br /&gt;    }&lt;br /&gt;;&lt;br /&gt;&lt;br /&gt;// let the magic happen&lt;br /&gt;})(document.getElementsByTagName(&amp;quot;*&amp;quot;));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What we have here?&lt;ol&gt;&lt;li&gt;A trapped live object, probably used in 90% of selector libraries, but performed via scope resolution (the document) and a function execution (the &lt;strong&gt;getElementsByTagName&lt;/strong&gt; method) over all nodes ("*")&lt;/li&gt;&lt;li&gt;a theoretically zero performances impact to retrieve again every node, being live there is no need to refresh it, and being trapped run-time, it will contain few nodes during the first execution&lt;/li&gt;&lt;li&gt;a single scope able to create N functions based on one of the most common created HTMLCollection&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;What do you think?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-323975706399739457?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/323975706399739457/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=323975706399739457" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/323975706399739457" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/323975706399739457" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/DVtAUyjQgvY/one-function-to-trap-them-all.html" title="One Function To Trap Them All" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">10</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/one-function-to-trap-them-all.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-4498562355739622589</id><published>2009-09-21T19:31:00.004+02:00</published><updated>2009-09-21T21:00:23.984+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="solution" /><category scheme="http://www.blogger.com/atom/ns#" term="CSS" /><category scheme="http://www.blogger.com/atom/ns#" term="position" /><category scheme="http://www.blogger.com/atom/ns#" term="fixed" /><title type="text">CSS Position Fixed Solution</title><content type="html">Who does not know CSS 2.1? &lt;em&gt;... silence (maybe) ...&lt;/em&gt;&lt;br /&gt;Good, so who does not know the &lt;a href="http://www.w3.org/TR/CSS2/visuren.html#choose-position"&gt;CSS 2.1 position property&lt;/a&gt;? &lt;em&gt;... silence (still maybe though) ...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Excellent! Finally, who would like to use in a lightweight, cross-browser, unobtrusive way, without JavaScript dependencies, the property &lt;strong&gt;fixed&lt;/strong&gt;? &lt;em&gt;... silence again, but this time I can spot a different expression in your face ...&lt;/em&gt;&lt;br /&gt;&lt;img src="http://www.3site.it/CAXXATE/homer.gif" width="43" height="50" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Common Browsers With position:fixed Support&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Chrome&lt;/li&gt;&lt;li&gt;Firefox&lt;/li&gt;&lt;li&gt;Internet Explorer 7 and 8 but &lt;strong&gt;NOT in &lt;a href="http://www.quirksmode.org/css/quirksmode.html"&gt;quirks mode&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Opera&lt;/li&gt;&lt;li&gt;Safari&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Common Browsers WithOut position:fixed Support&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Internet Explorer &lt;strong&gt;6&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Internet Explorer 7 and 8 in quirks mode&lt;/li&gt;&lt;li&gt;WebKit for &lt;strong&gt;Android&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;WebKit for &lt;strong&gt;iPhone&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;To Quirks Or Not To Quirks&lt;/h3&gt;&lt;strike&gt;For backward compatibility reasons IE let developers choose between two box models ...&lt;/strike&gt; Our loved bloody &lt;em&gt;64 years&lt;/em&gt;* old browser Internet Explorer 6 has never supported such property while both Internet Explorer 7 and 8 do nt support it if we are in quirks mode, a modality tendentiously dead thanks to new simple HTML 5 doctype declaration: &lt;em&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/em&gt;.&lt;br /&gt;To solve this issue I have created a dedicated file to include via &lt;a href="http://www.quirksmode.org/css/condcom.html"&gt;conditional comments&lt;/a&gt; which includes a set of "&lt;em&gt;never before that useful&lt;/em&gt;" &lt;a href="http://msdn.microsoft.com/en-us/library/ms537634%28VS.85%29.aspx"&gt;expressions&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Why Expressions&lt;/h3&gt;CSS expressions are compatible, so far, only with Microsoft IE browser and they are totally alien for both other browsers and developers. The reason I am saying that is because they are completely unpredictable: it is not possible to easily understand or to predict when expressions will be executed, where, and how!&lt;br /&gt;Technically speaking, being expressions dedicated for CSS hacks, their executions will be performed &lt;strong&gt;at least&lt;/strong&gt; every time the element is somehow involved, and to make it involved, we &lt;strong&gt;need to touch some property&lt;/strong&gt; in order to make expression useful (in this solution case the property offsetHeight of the current node).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Direct Example&lt;/h3&gt;Here we have two pages: the &lt;a href="http://www.3site.eu/examples/position-fixed/"&gt;standard or strict mode&lt;/a&gt; and the &lt;a href="http://www.3site.eu/examples/position-fixed/quirks.html"&gt;quirks one&lt;/a&gt;.&lt;br /&gt;As you can test via your favorite browsers, there are always 5 elements in that page, a top div, a center one, a bottom one, and two divs one left and one right, above and over the center one.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How Does It Work&lt;/h3&gt;It is very simple, consider these CSS classes:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;/** A WebReflection Solution */&lt;br /&gt;.position-fixed-top {&lt;br /&gt;    position:fixed !important;&lt;br /&gt;    top: 0;&lt;br /&gt;}&lt;br /&gt;.position-fixed-center {&lt;br /&gt;    position:fixed !important;&lt;br /&gt;    top: 50%;&lt;br /&gt;}&lt;br /&gt;.position-fixed-bottom {&lt;br /&gt;    position:fixed !important;&lt;br /&gt;    bottom:0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Hopefully choose name are semantic enough, so it's quite clear that these classes aim is &lt;strong&gt;only to position&lt;/strong&gt; elements, and nothing else, in order to be able to add other classes for whatever other property, zIndex if necessary included.&lt;br /&gt;Choose classes are about most common usage of fixed elements in a page, top, center, or bottom, and adjusting positions or margins it is really simple to put the element in whatever part of the page starting from the bottom, from the top, or the left.&lt;br /&gt;To let the magic be in Internet Explorer 6 and others in quirks mode, these classes are completely replaced, as you can read in &lt;a href="http://www.3site.eu/examples/position-fixed/position-fixed.IE.css"&gt;IE dedicated file&lt;/a&gt;.&lt;br /&gt;Being the IE solution based on CSS expressions, there should not be anything better or quicker than that, render time and call speaking, same should be for memory leaks, timers, and whatever strategy we have adopted 'till now (but of course if there is something better please share!).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Android &amp; iPhone - Not Worth It&lt;/h3&gt;These mobile devices implement a stunning browser as dedicated WebKit is, able to render faster than IE8, for example, my last &lt;a href="http://www.3site.eu/examples/liquid/vaio.html?left"&gt;Liquid FX&lt;/a&gt;, based on &lt;strong&gt;1&lt;/strong&gt; image, and one div, that's it! (congrats IE8 for stretched images rendering time! 7, 6, and 5.5. are much better) ... uh, wait, it's not about IE ... &lt;br /&gt;Android and iPhone have both a great CSS 2.1 support, and even some CSS 3. Unfortunately the position fixed does not work as expected. To fix it I have tried different scripts &lt;strong&gt;failing&lt;/strong&gt; each time. The reason is quite simple: both Android and iPhone &lt;strong&gt;block timers or render during scroll&lt;/strong&gt;, so the effect is that divs move with the scrolled page and only after, eventually, divs come back in the expected position. This is against position fixed idea, and having a truly small screen we should ask our self if it makes sense to cover precious pixels with something fixed there.&lt;br /&gt;It does not matter, as soon as I'll be &lt;a href="http://webreflection.blogspot.com/2009/09/i-would-simply-like-to-support-iphone.html"&gt;able to test an iPhone&lt;/a&gt; I will continue to optimize my script in order to make the position fixed property usable somehow with mobile devices as well ( center right or center left could be interesting, bottom or top bar quite intrusive for user and/or zooming features ).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How To Implement My Solution&lt;/h3&gt;It's simple, if we are in a quirks page, we should include the CSS hacked file after the normal one, and for every IE:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;position-fixed.css&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;!--[if IE]&amp;gt;&lt;br /&gt;    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;position-fixed.IE.css&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;![endif]--&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;While for every standard or strict web page we can include the hack only for IE less than version 7:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;position-fixed.css&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;!--[if lt IE 7]&amp;gt;&lt;br /&gt;    &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;position-fixed.IE.css?444&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;![endif]--&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I can spot a new expression in your face, isn't it?&lt;br /&gt;&lt;img src="http://www.3site.it/CAXXATE/Burns2.gif" width="107" height="107" /&gt;&lt;br /&gt;&lt;br /&gt;* if we multiply per 7 dogs age, I think it is reasonable to say that &lt;em&gt;in IT each year could be multiplied for 8&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-4498562355739622589?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/4498562355739622589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=4498562355739622589" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4498562355739622589" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4498562355739622589" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/co0m7pwDFC8/css-position-fixed-solution.html" title="CSS Position Fixed Solution" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">11</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/css-position-fixed-solution.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-1706104454101946794</id><published>2009-09-19T14:10:00.010+02:00</published><updated>2009-09-20T12:02:30.784+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="Liquid" /><category scheme="http://www.blogger.com/atom/ns#" term="FX" /><title type="text">JavaScript Liquid Image FX</title><content type="html">Yesterday I have been in Brixton Academy for Massive Attack concert: amazing!&lt;br /&gt;&lt;br /&gt;I have been totally impressed by their choreography: it looked apparently rudimentary stuff but once they started playing I could not avoid to think all the time how beautiful special effects are and how simple, sometimes, they could be for a stunning result.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Liquid FX&lt;/h3&gt;I cannot forget my ActionScript Developer past and of my favorite coded special effects has always been the liquid one. What is a liquid effect? Here a preview:&lt;br /&gt;&lt;img src="http://www.3site.eu/examples/liquid/preview.jpg" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Test Liquid FX Directly In Your Browser&lt;/h3&gt;Well, if the preview image is not explicative enough, I am sure this &lt;strong&gt;&lt;a href="http://www.3site.eu/examples/liquid/"&gt;demo page&lt;/a&gt;&lt;/strong&gt; is :)&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Update&lt;/strong&gt;, this &lt;strong&gt;&lt;a href="http://www.3site.eu/examples/liquid/vaio.html"&gt;Sony VAIO Flash Style Splash Page&lt;/a&gt;&lt;/strong&gt; could be interesting as well, isn't it? And all in &lt;strong&gt;14Kb&lt;/strong&gt; images, JS, and layout included ;)&lt;br /&gt;&lt;img src="http://www.3site.eu/examples/liquid/vaio_splash.gif" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How Does Liquid Work&lt;/h3&gt;There is a Liquid function, and its configuration object:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;Liquid({&lt;br /&gt;&lt;br /&gt;    // image src, whatever format&lt;br /&gt;    src:"myimage.png",&lt;br /&gt;&lt;br /&gt;    // element to use as Liquid FX container&lt;br /&gt;    target: document.getElementById("fx") // $("#fx")[0] for lazy people,&lt;br /&gt;&lt;br /&gt;    // optional direction, left by default&lt;br /&gt;    // accepted: left, right, bottom, top&lt;br /&gt;    direction: "left",&lt;br /&gt;&lt;br /&gt;    // optional scale factor, 2000% by default&lt;br /&gt;    // it is how much the image should be stretched&lt;br /&gt;    scale: 2000,&lt;br /&gt;&lt;br /&gt;    // optional speed, 1 to whatever, by default 10&lt;br /&gt;    speed: 10,&lt;br /&gt;&lt;br /&gt;    // optional callback,will be executed at the end of the FX&lt;br /&gt;    callback:function(){alert("it's Liquid!")}&lt;br /&gt;&lt;br /&gt;    // NEW IN V1.3&lt;br /&gt;&lt;br /&gt;    // optional onload to perform some operation after the image has been loaded&lt;br /&gt;    onload:function(){FX not started yet but image loaded}&lt;br /&gt;&lt;br /&gt;    // optional reverse property over a completed liquid FX&lt;br /&gt;    reverse:true&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;strong&gt;New in version 1.3&lt;/strong&gt;, the Liquid function returns the configuration object and it adds two methods: &lt;strong&gt;pause&lt;/strong&gt; and &lt;strong&gt;play&lt;/strong&gt;.&lt;br /&gt;Specially pause is useful to stop FX if we need to clean the target container.&lt;br /&gt;&lt;pre class="code"&gt;// pause/play example&lt;br /&gt;var lq = Liquid({&lt;br /&gt;    src:"mycoolimage.gif",&lt;br /&gt;    target:document.body,&lt;br /&gt;    onload:function(){&lt;br /&gt;        setTimeout(function(){&lt;br /&gt;            lq.pause();&lt;br /&gt;            setTimeout(function(){&lt;br /&gt;                lq.play();&lt;br /&gt;            }, 500);&lt;br /&gt;        }, 500);&lt;br /&gt;    }&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is pretty much it, so far. &lt;strike&gt;I am planning to implement a LiquidReversed function as well, in order to let the images disappear in the same way they appear.&lt;/strike&gt;&lt;br /&gt;The source code with Mit Style License is &lt;a href="http://www.devpro.it/javascript_id_200.html"&gt;here&lt;/a&gt; while the inspiration is from my 2005 &lt;a href="http://www.devpro.it/as1_id_8.html"&gt;ActionScript 1 imageStretcher&lt;/a&gt; code.&lt;br /&gt;&lt;br /&gt;enjoy&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-1706104454101946794?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/1706104454101946794/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=1706104454101946794" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1706104454101946794" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1706104454101946794" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/MtuhMLQVpi0/javascript-liquid-image-fx.html" title="JavaScript Liquid Image FX" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">10</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/javascript-liquid-image-fx.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-399518934059158645</id><published>2009-09-16T22:26:00.012+02:00</published><updated>2009-09-23T21:26:05.364+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="support" /><category scheme="http://www.blogger.com/atom/ns#" term="iPhone" /><category scheme="http://www.blogger.com/atom/ns#" term="development" /><category scheme="http://www.blogger.com/atom/ns#" term="cross-platform" /><category scheme="http://www.blogger.com/atom/ns#" term="debug" /><category scheme="http://www.blogger.com/atom/ns#" term="test" /><title type="text">I Would Simply Like To Support iPhone But I Cannot</title><content type="html">&lt;strong&gt;Update&lt;/strong&gt;&lt;br /&gt;Before other silly flame/blame will start, I have already twitted that my next laptop will be a netbook. Here the &lt;a href="http://twitter.com/WebReflection/status/4120170203"&gt;related tweet&lt;/a&gt;.&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;let me summarize the story: at that time I had a girlfriend with an iPhone so I though &lt;em&gt;why on earth shouldn't I buy an Android instead? If I need some test online I'll have both to test it&lt;/em&gt;, and I've rarely been that wrong.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Wanna Develop for iPhone? Buy a Mac&lt;/h3&gt;As marketing strategy sounds "&lt;em&gt;cool&lt;/em&gt;" except I do not want to develop iPhone application, the present and the future is online, why on earth should I learn another programming language from the scratch, Objective-C, to develop something that will be relatively soon replaceable via WebKit and a good host?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Wanna Develop Web for iPhone? Buy a Mac&lt;/h3&gt;Again!!! Unbelievable, there is not such a thing: &lt;em&gt;online iPhone tester&lt;/em&gt;, everything I found Googling was about a silly image with an iframe just to test the iPhone size ... &lt;strong&gt;are you kidding me&lt;/strong&gt;?&lt;br /&gt;It's like put IE inside an iframe inside an "&lt;em&gt;Android frame&lt;/em&gt;" ... where is webkit? Where is the real JS engine? Where is the &lt;strong&gt;real render engine&lt;/strong&gt;?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Wanna Develop for Apple Devices? Buy Apple&lt;/h3&gt;OK, I got your point, so now I am stuck with an Android contract and moreover I "love" my Android and it's about a year I am using it writing at &lt;em&gt;light speed&lt;/em&gt; thanks to hidden keyboard, and using for whatever Web purpose thanks to its WebKit which is maybe not perfect but it works like a charm, generally speaking.&lt;br /&gt;I do not want to buy a Mac only to test iPhone Web engine via &lt;strong&gt;Xcode&lt;/strong&gt;, I'd love to have better reasons for a Mac, and I don't want to buy an iPhone only to test it online.&lt;br /&gt;That will mean another contract to surf the Net as well ... and why on earth should I do this while I am simply &lt;strong&gt;trying to support iPhone&lt;/strong&gt;?&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;I Would Simply Like To Support iPhone But I Cannot&lt;/h3&gt;Now I am a single developer, but I cannot imagine all other engineers, JavaScript hackers, W3C "slaves", cross-browser maniacs, &lt;strong&gt;unable to develop a web application for iPhone&lt;/strong&gt;. With this strategy Apple is missing the possibility to fix a wider range of problems related to iPhone WebKit dedicated build and moreover it is avoiding iPhone Web support for "&lt;em&gt;silly developers&lt;/em&gt;" like me that in this case was only trying to fix a common problem, the css position fixed property, but I am unable to make it works in an iPhone while &lt;strong&gt;every other A-Grade browser is supported&lt;/strong&gt;, Android included, and here is the &lt;strong&gt;&lt;a href="http://www.3site.eu/examples/position-fixed/"&gt;example&lt;/a&gt;&lt;/strong&gt;!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;As Summary&lt;/h3&gt;People like &lt;a href="http://www.quirksmode.org/"&gt;Peter-Paul Koch&lt;/a&gt; have the privilege to try any kind of mobile device in order to test compatibility. Unfortunately for Mobile Devices Vendors Peter-Paul alone will never be able to cover every kind of test. &lt;strong&gt;Even Microsoft&lt;/strong&gt; releases time bombed images for Virtual Machines in order to test &lt;strong&gt;other versions of Internet Explorer&lt;/strong&gt;. The Android OS is Open Source and it is possible to test it almost via whatever platform, same is for other browsers but &lt;strong&gt;not the iPhone&lt;/strong&gt;. I know you do not mind but you are missing my contribute and support for projects a la &lt;a href="http://code.google.com/p/sessionstorage/"&gt;sessionStorage&lt;/a&gt;, &lt;a href="http://code.google.com/p/formaldehyde/"&gt;Formaldehyde&lt;/a&gt;, the incoming &lt;a href="http://www.3site.eu/examples/position-fixed/"&gt;position-fixed&lt;/a&gt;, &lt;a href="http://code.google.com/p/vice-versa/"&gt;vice-versa&lt;/a&gt; or &lt;a href="http://code.google.com/p/noswfupload/"&gt;noSWFUpload&lt;/a&gt; ... and again, I am only one out of million of web developers.&lt;br /&gt;&lt;br /&gt;Please think about it,&lt;br /&gt;Best Regards&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-399518934059158645?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/399518934059158645/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=399518934059158645" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/399518934059158645" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/399518934059158645" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/v2-7tpgBJ7g/i-would-simply-like-to-support-iphone.html" title="I Would Simply Like To Support iPhone But I Cannot" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">9</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/i-would-simply-like-to-support-iphone.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-4762770279816971828</id><published>2009-09-14T21:26:00.005+02:00</published><updated>2009-09-14T22:01:45.579+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="notification" /><category scheme="http://www.blogger.com/atom/ns#" term="Object" /><category scheme="http://www.blogger.com/atom/ns#" term="LiveMonitor" /><category scheme="http://www.blogger.com/atom/ns#" term="HTMLCollection" /><category scheme="http://www.blogger.com/atom/ns#" term="watch" /><category scheme="http://www.blogger.com/atom/ns#" term="asynchronous" /><title type="text">LiveMonitor - Asynchronous Property Monitor</title><content type="html">Today I would like to introduce you a quite uncommon JavaScript &lt;em&gt;trick&lt;/em&gt;, a trapped Live Object or, generally speaking, a lightweight monitor able to understand when a generic property has been changed.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;About Live Objects&lt;/h3&gt;A live object could be described as a particular object able to change without our interaction. The most common live object example is this:&lt;pre class="code"&gt;&lt;br /&gt;// this is the most common live object&lt;br /&gt;// the HTMLCollection&lt;br /&gt;var divs = document.getElementsByTagName("div");&lt;br /&gt;divs.length; // let's say 4&lt;br /&gt;&lt;br /&gt;// let's add another div inside a generic node&lt;br /&gt;document.body.appendChild(&lt;br /&gt;    document.createElement("div")&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;divs.length; // 5!&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In few words DOM searches are dynamic, which is the reason almost every selector library needs to transform the current result into a static &lt;strong&gt;Array&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;About LiveMonitor&lt;/h3&gt;Specially suited for live objects, LiveMonitor is a function which aim is to notify us when the specified property change:&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;// LiveMonitor example&lt;br /&gt;var lm = new LiveMonitor(&lt;br /&gt;    // the entire list of elements trapped&lt;br /&gt;    document.getElementsByTagName("*"),&lt;br /&gt;    // the property to monitor&lt;br /&gt;    "length"&lt;br /&gt;);&lt;br /&gt;&lt;br /&gt;// add one or more notifier&lt;br /&gt;lm.onchange(function(collection){&lt;br /&gt;    // this, will be the lm object&lt;br /&gt;    this.value; // will be collection.length&lt;br /&gt;    collection.length; // is the new length&lt;br /&gt;&lt;br /&gt;    alert([&lt;br /&gt;        "All nodes collection contained ",&lt;br /&gt;        this.value,&lt;br /&gt;        " nodes but now there are ",&lt;br /&gt;        collection.length&lt;br /&gt;    ].join("\n"));&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The example is quite silly, but the concept is that as soon as the monitor will check the "length" property, in this case in the one of the trapped collection, it will fire the onchange event, notifying us that somebody did something somewhere, and this something changed our monitored property.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;LiveMonitor Code&lt;/h3&gt;&lt;pre class="code"&gt;&lt;br /&gt;var LiveMonitor = (function(){&lt;br /&gt;&lt;br /&gt;/** LiveMonitor :: Asynchronous Property Monitor&lt;br /&gt; * @author      Andrea Giammarchi&lt;br /&gt; * @license     Mit Style&lt;br /&gt; * @blog        http://WebReflection.blogspot.com/&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;function LiveMonitor(object, property){&lt;br /&gt;    this.value = object[property];&lt;br /&gt;    this._property = property;&lt;br /&gt;    this._object = object;&lt;br /&gt;    this._event = [];&lt;br /&gt;    this._i = 0;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;LiveMonitor.prototype.onchange = function onchange(callback){&lt;br /&gt;    this._event.push(callback);&lt;br /&gt;    if(this._i === 0){&lt;br /&gt;        var _property   = this._property,&lt;br /&gt;            _object     = this._object,&lt;br /&gt;            _event      = this._event,&lt;br /&gt;            self        = this&lt;br /&gt;        ;&lt;br /&gt;        this._i = setTimeout(function _i(){&lt;br /&gt;            if(self.value !== _object[_property]){&lt;br /&gt;                for(var i = 0, length = _event.length; i &amp;lt; length; ++i){&lt;br /&gt;                    if(_event[i].call(self, _object) === false)&lt;br /&gt;                        break&lt;br /&gt;                    ;&lt;br /&gt;                };&lt;br /&gt;                self.value = _object[_property];&lt;br /&gt;            };&lt;br /&gt;            if(0 &lt; self._i)&lt;br /&gt;                self._i = setTimeout(_i, 15)&lt;br /&gt;            ;&lt;br /&gt;        }, 15);&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;LiveMonitor.prototype.offchange = function offchange(callback){&lt;br /&gt;    for(var _event  = this._event, i = 0, length = _event.length; i &amp;lt; length; ++i){&lt;br /&gt;        if(_event[i] === callback)&lt;br /&gt;            _event.splice(i, 1)&lt;br /&gt;        ;&lt;br /&gt;    };&lt;br /&gt;    if(_event.length === 0){&lt;br /&gt;        clearTimeout(this._i);&lt;br /&gt;        this._i = 0;&lt;br /&gt;    };&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;LiveMonitor.prototype.clear = function clear(){&lt;br /&gt;    this._event = [];&lt;br /&gt;    this.offchange(null);&lt;br /&gt;    this.value = this._object[this._property];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;return LiveMonitor;&lt;br /&gt;&lt;br /&gt;})();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Not Only DOM Searches&lt;/h3&gt;LiveMonitor could be actually used as asynchronous notifier for any kind of variable.&lt;br /&gt;Let's say we have an environment able to load runtime scripts but we cannot change loaded scripts (external source inclusion).&lt;br /&gt;At some point we press the "&lt;em&gt;load jQuery&lt;/em&gt;" button and we would like to be able to be notiied when it is available ...&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;if(!window.jQuery){&lt;br /&gt;&lt;br /&gt;    // create a LiveMonitor instance over&lt;br /&gt;    // jQuery property&lt;br /&gt;    var jqlm = new LiveMonitor(window, "jQuery");&lt;br /&gt;&lt;br /&gt;    // add onchange event&lt;br /&gt;    jqlm.onchange(function(window){&lt;br /&gt;&lt;br /&gt;        // remove this event&lt;br /&gt;        this.offchange(arguments.callee);&lt;br /&gt;        // remove jqlm as well, it is not useful&lt;br /&gt;        // anymore for this example&lt;br /&gt;&lt;br /&gt;        // use jQuery, it's here for sure!&lt;br /&gt;        $("body").html("Hello LiveMonitor!");&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    // load external script&lt;br /&gt;    loadScript("http://external/jQuery.js");&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;With a cross-browser, portable, and lightweight function, we can use notifications without effort over objects, HTMLCollections, Arrays, or everything else we would like to monitor. Let's say this is a sort of asynchronous cross browser Object.prototype.watch, but this time &lt;a href="http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html"&gt;without alchemy&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-4762770279816971828?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/4762770279816971828/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=4762770279816971828" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4762770279816971828" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/4762770279816971828" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/j_kAQgn2Jog/livemonitor-asynchronous-property.html" title="LiveMonitor - Asynchronous Property Monitor" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/livemonitor-asynchronous-property.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-34454975.post-1006486625569787050</id><published>2009-09-10T23:17:00.002+02:00</published><updated>2009-09-10T23:17:58.026+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript" /><category scheme="http://www.blogger.com/atom/ns#" term="log" /><category scheme="http://www.blogger.com/atom/ns#" term="cross-browser" /><category scheme="http://www.blogger.com/atom/ns#" term="Formaldehyde" /><category scheme="http://www.blogger.com/atom/ns#" term="console" /><title type="text">Formaldehyde JS - The Circle Is Close</title><content type="html">As announced in &lt;a href="http://ajaxian.com/archives/formaldehyde-php-debug-info-for-the-client-side"&gt;Ajaxian&lt;/a&gt;, I have created &lt;a href="http://code.google.com/p/formaldehyde/"&gt;Formaldehyde JS&lt;/a&gt; with exactly the same &lt;strong&gt;Zero Config&lt;/strong&gt; logic.&lt;br /&gt;&lt;br /&gt;We put this file before everything else and that's it, Formaldehyde will automatically decide how to show errors in a wide range of browsers:&lt;ul&gt;&lt;li&gt;Chrome&lt;/li&gt;&lt;li&gt;Firefox&lt;/li&gt;&lt;li&gt;Internet Explorer 5, 5.5, 6, 7, 8 with or whout console&lt;/li&gt;&lt;li&gt;Opera&lt;/li&gt;&lt;li&gt;Safari&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Logs will naturally degrade until the most primitive &lt;em&gt;alert&lt;/em&gt; but hey, Formaldehyde is for debug and development environments, not for production.&lt;br /&gt;&lt;br /&gt;Enjoy ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/34454975-1006486625569787050?l=webreflection.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://webreflection.blogspot.com/feeds/1006486625569787050/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=34454975&amp;postID=1006486625569787050" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1006486625569787050" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/34454975/posts/default/1006486625569787050" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WebReflection/~3/27-Us1SzVus/formaldehyde-js-circle-is-close.html" title="Formaldehyde JS - The Circle Is Close" /><author><name>Andrea Giammarchi</name><uri>http://www.blogger.com/profile/16277820774810688474</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="11324065305198565288" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://webreflection.blogspot.com/2009/09/formaldehyde-js-circle-is-close.html</feedburner:origLink></entry></feed>
