Sunday, July 12, 2009

Elsewhere - Sandboxes Have Never Been That Easy

One of the most common problems in Web 2.0 Development, is the amount of libraries we can possibly include into a single project and conflicts these libraries could have.
Some library is truly aggressive. It could change the entire behavior of each other lib present in the page via not-standard or future implementations of some global object prototype, such String, Object itseld, Array, or others.
Since this is a well known problem, some library/framework can try to avoid conflicts in different ways. As example, jQuery has a noConflict method which aim is to make development as painless as possible ... but it is not always that simple. One of Elsewhere purpose is to connect a completely different and external scope into the main window, avoiding any sort of conflict a library with its global properties, functions, or prototypes, could have. First example:

new Elsewhere(
"scripts/libs/jquery.1.3.2.min.js"
).execute(function(ready){
// this scope is elsewhere in a perfectly clean environment.
// In this case jQuery will be manifested as global "$" function.
// To bring jQuery outside, we can use this sandbox parent reference
parent.jQuery = function(search, context){
// to make sure we do not search in an "empty" document,
// the one part of this sandbox, we pass the context
// if not present as parent.document
return $(search, context || parent.document);
};

// we can call the ready callback
ready(parent.jQuery);
},
[ // one or more arguments to pass into Elsewhere function execution
function($){

// let's do something on ready event
// please note there is no var in front of jQuery
// since it has been declared as global
jQuery(function(){
// we could use the argument as well
// since in this case it is exactly
// the same jQuery function
$("body").html("Here I Am");
});

}
]);

Confused? Please read more ;)

Quick Answer: What Is A Sandbox


Every time we open a new window in our browser, the latter one creates a (almost)clean environment to run, if presents, each JavaScript file. The same happens for each tab, which means that if we define a function Z(){} in tab a, this will not be present in tab b. Finally, same things happens inside frames or iframes as well. Each window, framed, tabbed, or not, will have then its own JavaScript environment and in JS world this is called sandbox.

What Is Elsewhere


Elsewhere is a lightweight, less than 1Kb if minified and gzipped, almost fully cross-browser library (so far compatible with each browser I tested) able to create runtime a sandbox including zero, one, or more scripts. The first showed example, creates a sandbox including jQuery library and bringing its power outside the box.
The important thing to understand, is that used function scope will be completely extraneous to the one the function itself has been created ... in few words, that scope will be elsewhere!
Thanks to possibility to send arguments when this external function will be executed, and thanks to parent or top reference, it is possible to play between different scopes avoiding conflicts, creating bridges, loading JSONP, and more!

// JSONP example
new Elsewhere(
"http://mycoolservice.com?fn=parent.callback"
);
// that's it!

About JSONP, via Elsewhere a response could be more than just a callback. It could be an entire different environment with runtime created bridges. Example:

// output produced by a generic REST service
// myservice.server/name/WebReflection

// a function which name is not a problem
function getReferences(){
return userInfo.name + " has " + userInfo.posts + " posts";
};

// a global object which name is not a problem
var userInfo = {
name:"WebReflection",
site:"http://webreflection.blogspot.com/",
posts:12345
};

// a bridge for Elsewhere instance
// every Elsewhere sandbox has a reference to its isntance
// This reference is retrieved via global sandbox window object
// and the property @_Elsewhere
window["@_Elsewhere"].getUserProperty = function(name){
return userInfo[name];
};

// please note you cannot access that property directly
// window.@_Elsewhere will cause an error
window["@_Elsewhere"].getReferences = getReferences;

// ...

// our main page via Elsewhere
var myservice = new Elsewhere("myservice.server/name/WebReflection");
myservice.execute(function(fn){fn()}, [function(){
alert(myservice.getUserProperty("site")); // http://webreflection.blogspot.com/
alert(myservice.getReferences()); // WebReflection has 12345 posts
}]);


Understanding execute Method: How Elsewhere Works


How can be possible that a function defined inside a scope is totally ignorant about surrounding variables or scopes? It is really simple!
Elsewhere is based on Function.prototype.toString de-compilation, creating passed function directly as script inside the sandbox and returning, if status is ready, its value or undefined.
The important thing to understand is that if we create a global scope variable, this will be present next call, whenever we decide to perform it.

var sb = new Elsewhere();
// sb.ready is true, no external scripts loaded
alert(sb.execute(function(){
// generic function
function sum(a, b){
return a + b;
};

// define sum as global in this scope
window.sum = sum;

// test the function
return sum(1, 2);

})); // will be 3


// do other stuff and ...
sb.execute(function(){
return sum(3, 4);
}); // will be 7, sum was already defined

alert(typeof sum); // undefined
// sum exists only Elsewhere

About the ready status flag, it is instantly true if we do not load external script, while it could be true or false, depending on which browser we are using (in some browser an iframe document with external scripts is loaded sync while with Firefox 3.5 an iframe does not block main page content so it is not sync).

// more than a file ...
new Elsewhere([
// order is respected and reliable
"jquery.js",
"jquery.ui.js"
]).execute(function(onjQueryAndUILoaded, initialTime){
// execute is always performed
// after everything has been loaded
onjQueryAndUILoaded(jQuery, new Date - initialTime);
}, [
// we can optionally pass one or more arguments
function($, elaspedTime){
// let's understand how much it took
alert(elaspedTime);
},
new Date
]);


Understanding extend Method: Fast Bridge


Every time we execute a function inside an Elsewhere instance, we are de-compiling and injecting it inside another document. This operation is not that expensive but if we need to perform some task in that scope frequently, we could consider to extend an Elsewhere instance via its own method, creating a sort of fast bridge between two or more than two different worlds.

// empty sandbox
var sb = new Elsewhere()
// extend returns the instance itself
.extend(
{
extendObject:function(){
var toString = Object.prototype.toString;

// note, this Object is not the main one
// but the one from this sandbox (main not affected)
Object.prototype.type = function(){
var s = toString.call(this);
return s.substr(8, s.length - 9);
};

// avoid future modification
window.extendObject = function(){};
},
createObject:function(o){
// create an Elsewhere Object
return new Object(o);
},

// if an extend key is a global variable
// different from undefined
// this will simply be the variable from
// this sandbox
Object:1,

// if the value is not a function
// it will simply be saved as is
cool:true
}
);

// extend Elsewhere Object.prototype
sb.extendObject();

// test it
var o = sb.createObject("test");
alert(o.type()); // String

// o is not instanceof this main page Object
alert(o instanceof Object); // false

// but it could be used as if was
// an Object
alert(o instanceof sb.Object); // true

alert(sb.cool); // true


As Summary


Elsewhere can open hundreds of possibilities without bringing nothing new, except that browsers are starting to implement different threads for each sandbox (tab, or window) and I expect this library will bring an even more simple way to implement web workers. Right now main points are conflicts resolution, when libraries are able to deal from a sandbox, new JSONP interaction ways, multiple native constructor prototype definitions via one or more Elsewhere instances, just a simple way to load external scripts or ... well, whatever else our imagination could create with such tiny, cross-browser, library. Have fun with sandboxes 8).

The script? Via post title or here, in devpro.it.

Labels: , ,

Friday, July 10, 2009

ECMAScript 5 Full Specs String trim, trimLeft, and trimRight

During last evenings I have updated a little bit my vice-versa project.
Since vice-versa aim is to bring in every browser what is possible to implement and, in most of the cases, already defined as standard (from W3 or MSDN when it is worthy) I decided to get rid of the Ariel Flesler fast trim proposal to introduce my lightweight full specs String.prototype.trim, trimLeft, and trimRight.
For full specs I mean that vice-versa String.prototype.trim replace exactly same characters replaced by native Firefox 3.5 implementation, rather than only characters which code is less than 33 as is for Ariel proposal.

The good part of vice-versa ( to be honest I cannot find bad parts so far ;) ) is that every single file is stand-alone, so if you do not like benefits the entire "lib" could bring, you can always adopt only one of its files, for example the String one, the Array one, or the last full specs ECMAScript 5 Date constructor, compatible with ISO strings, new Date("2009-07-10") and with a complete toISOString method for each created Date instance (of course even if replaced, new Date will produce instances of Date and their constructor will be Date itself).

If you want to give vice-versa minified a try, a little monster which size is about 5Kb gzipped, please do not hesitate to download it.

Have fun with future standards and few MSDN standard coolness for every browser ;)

Labels: , , , , , , ,

Frameworks: To Choose Or Not To Choose

Few days ago the BBC announced the release of their framework called Glow.
John Resig commented this event in a "logical and reasonable way" but instantly different developers reacted over his thoughts.
What John says, in few words, is that BBC developers used jQuery before and they were partially happy with it.
Rather than help jQuery community to grow up, opening tickets, adding patches, or forking the library itself improving it adding Safari 1.3 support, a 0% market share browser that in my opinion is used only inside BBC labs and nowhere else, they decided to spend about 2 years to create a library that apparently does not bring anything new, and which is even more supported by some obsolete or deprecated browser, rather than latest one (Chrome 1 or 2, Opera 10, or Firefox 3.5). This post is about what I think after almost 10 years of Web development experience, where I have used both frameworks and I wrote some for internal purpose. Cases are different for each situation, requirements are different as well as different could be time to create or complete a project.



About Library Browsers Support


Dear net surfers, there is nothing to do, if you need internet, if your business is partially based on internet, if you want everything internet has to offer, you must be updated! That's the story, and this is that simple.
There is not a single valid excuse to be stuck in the past, and if some application in your company works only in IE6, first of all you should consider to upgrade that application, it's deprecated, secondly you should consider alternatives at least for new Web services, that in the best case scenario will suggest you to upgrade while in the worst one will simply do NOT work and you, minority, will just miss that train!

As everybody knows technologies quickly evolves and if you walk down the street with a Walkman rather than an iPod like device, you are mentally 80 years old, retired, and you are missing infinity possibilities, starting from more than an album and hours of music.

Internet, the Web, the Web business, and everything around it, is drastically changing day after day.
Reasons are different, starting from an initial and general misunderstanding about same Web standards and related logics, goals, and behaviors, ending with a revolution that thanks to new technologies, programming languages, and companies, where Google is one of the most important leaders, are acting on daily basis.

In few words: are you a net surfer? Do you need internet? You are probably already upgraded, thanks to be patience and to read this post 'till the end.

Are you someone that does NOT know internet, what it has to offer, does not need it for your business, and surfs the Web few minutes per month?
Do not complain then if the rest of the world that needs internet is moving on in the meanwhile, thank you!

Are you a company that understood only recently the power of the web? If you do not upgrade your browser your business will be decades behind others!

Is IE6 there because of "security bla bla bla"? IE6 is one of the most bugged and vulnerable browsers in the history, fire your system administrator and move on with the rest of the world!

All this effort is just to let you understand that modern web libraries are doing their best to be as much compatible as possible.
Unfortunately, some old browser cannot physically solve "nowadays Web problems" because these browsers have been programmed when internet was nothing more than a "advertisement coupon", with flashing images, providing zero services.

Just consider that an iPhone or a G1, mobile devices, integrate a better browser than IE6 or Safari 1.3 ... is it time to move forward? IE8 is there, as Firefox, Chrome, Safari and Opera are. You have choices, and mainly for free, to avoid to collapse with deprecated services and applications.

So, are you spending money for a Jurassic business, internet time speaking? If yes, why are you wasting money with a browser such Safari 1.3, 98% useless for every recent website, or IE6, forced to be somehow compatible but for its own limits obviously deprecated for modern businesses and applications?

As summary, I do not understand why on earth BBC needs to support people that do not use internet. It could make sense to still support IE6, right now below IE8, market share speaking, but unfortunately still there thanks to people ignorance. But a browser that could be compared with Internet Explorer for Mac, abandoned by Microsoft itself years ago, cannot be a good excuse to avoid libraries ... I simply cannot believe this reason and I would like to have real stats about Safari 1.3 usage in their website.



About Choosing Libraries Or Frameworks


There are hundreds of valid choices out there but this case is mainly about the decision to avoid jQuery.
A good library as jQuery is, if I am not wrong the most used one right now and recently adopted in Wikipedia pages as well, has basically these pro:

  • widely cross-browser supported, more market share than Glow or other home made libraries

  • day after day improvements, bug fixes, speed ups, thanks to an active community, a tickets system and again, thanks to its wide adoption from biggest to smallest website, which can only hep to improve jQuery stability and/or features

  • constant cross-browser tests, which aim is to guarantee stability and functionality over any kind of customer, client, administrator, or simply net surfer


These are not jQuery specific features, these are simply the reason developers prefer to use a well known library rather than an home made one.
Less effort, most of what we need is there, and jQuery is truly reach about plug-ins, so what is not there has been probably already implemented. Charts? Timeline stuff? Widgets? Fields helpers? Almost everything, and it simply works thanks to the core library and its stability, jQuery again.
Just to be honest, I do not even use jQuery except when I need it for compatibility or time reasons, so please do not get me wrong, I am not a fanatic, I read Ext JS, dojo, YUI, and other libraries authors or mailing lists as well so this is just an impartial point of view about libraries and nothing else but, there is always a but, I can understand as well the other point of view ...



About Creating Your Own Library


If we understand the reason a library or a framework is a good choice, whatever programming language we are talking about, even if latter one is created via JavaScript, the most problematic programming language ever due to its intrinsic unstable or different nature (not just one virtual machine but lots of different interpreters, few strictly standard behaviors, thousands of browsers implementation bugs or standards misunderstanding, zero compilation, etc etc) there could be an absolutely valid reason to decide to create our own libraries.
First of all, if we do not want to be "monkeys" but developers, the only way we have to deeply learn a programming language and its problems is to use it as much as possible, without stopping a single day to learn more about it.
If a library/framework does magically everything and we are not curious enough to understand how this library is solving or implementing our daily problems or features, we have probably chose the wrong job, unless we are not designers with different goals, where a library is "just what we were looking for" to quickly solve "that problem" which was not Photoshop related.
Sometimes, we could be simply not interested about the language itself, thanks to frameworks able to translate some "serious language" a la Java or C# into the blamed one: JavaScript (and to be honest I can't wait to laugh about some JavaScript related problem not considered by that framework, who you gonna call: Ghost Busters?!)
Another important fact to consider is the time, never enough in this "everybody agile" web era where if at least the business client core functionality and its tests are delegated to someone else, we are half way through our application goals.
But how different are things if we are plenty of time to develop our own library?

  • we are not necessarily reinventing the wheel, if we are skilled enough, and we have studied problems, features, and adopted solutions, we could simply create something new or just perfect for what we need (as example, the dollar function "is prototype stuff", what jQuery did with it was simply different, but I am sure John will agree about this innovation or "just what we need" point)

  • we will have full control over releases and source code, being able to solve problems in a bit and without dependencies over third parts libraries. We all know that even if have skills to quickly change a library core feature, this library next release could probably mess up our internal patch, or vice versa, and sometimes our case is so particular or simply impossible to reproduce outside our business box, that a ticket could not make sense at all. I personally changed some library core function, or overwritten some core method, and simply because of problems and situations impossible to reproduce into the ticket system. The reason is simple: when the application is complex enough, and it is an internal one (admin areas anybody?), we cannot spend a day to create a ticket which emulates somehow our specific problem. Got the point?

  • the final silly point: we are developers, for code sake, and a typical stereotype is that we are all better than everybody else. In few words, if we think it, knowing what others are doing about same thoughts, we are thinking "better than others", and if we are not shy to write a lot of code and test it, because we have time, why on earth we should depend again on third parts libraries?





As Summary


There is not an absolute point about these kind of choices, except one: flexibility. I do appreciate the fact BBC team at least tried jQuery library before they chose to create their own one. The point about death browsers is an excuse, IMHO, they should have been more decided about their points because if that was the reason, I do not get it at all and people talking about public money would be absolutely right. On the other hand, latest points about proprietary libraries advantages could make BBC site less problemtic, for their supported browsers, considering they know what they are doing, they had even too much time to develop 300Kb of core library comment included ( I wrote 3 times of code in one month over another library and nothing was redundant ... ), and they are (ta da ta da!!!) BBC, good to see their source code (lovely comments, not everything lovely in the code though but this is another story)

This post is just my humble opinion about a subject extremely common in this sector and interesting as well.
I am just a developer with passion for code, curiosity about ASM, C knowledge, a "JavaScript Ninja" currently technical editor of an imminent related book, with PHP Zend Engineer certifications, few Java related experiences, and daily C# exposure. In few words, I have collaborated with different companies and created internal libraries or used third parts libraries. Please consider my experience so far before you'll blame me for this post, thanks :D

P.S. I promise, I'll add every related link asap, right now my temporary Internet connection is running out of bytes!!!

Sunday, July 05, 2009

YUI Compressor Meets The Batch Scripting

Mainly to work, also to investigate some good old DOS feature, I created a batch file able to make YUI Compressor more portable and easy for every Windows based client/server developer.
I wrote the story, and I described each file, plus I added a workable Zip with everything you need to understand what I have created and use it, starting with a double click into a projects/vice-versa.bat file which aim is to create from a list of files a unique YUI Compressed one.
Here is the link, the rest is up to you (comments, questions, suggestions, etc)

Labels: , , , ,

Saturday, July 04, 2009

UK Bing Roundtable - Just My Opinion

It is probably too late and I did not check other guys blogs, but I would like to bring here my impressions about this Bing event I have been invited few days ago.

How Did It Start


Hi Andrea,
I'm writing on behalf of Microsoft to invite you to a discussion about Bing, the new search engine that recently launched in beta in the UK.

...

Colin Mercer, a member of Microsoft Life Without Walls initiative group, is a truly nice guy. Spontaneous, friendly, exactly that kind of guy that could let a group of foreigners feel comfortable since first meet up minutes. Being glad to have been invited without asking, and without being a Microsoft fun as well, of course I was there: to understand what this initiative was about and why they called me, raising my doubts from this high geek technical blog.

Bing Round Table, The Good Part


To be honest, I am not going to be that nice about this event, but I have to admit that seeing Microsoft trying to be closer than before with people that make Web live, any topic blogger in this case, was a nice surprise. The organization, the choose place, and the catering was excellent, even if there were only about 10 guests and there was no time to eat and drink. It is a good start point from a company famous to be closed for its selling purpose only. Good Stuff, please keep doing it, it can only brings benefits from different points of view.


Special Moronic Guests, That Is What We Are


The presentation started with a lovely woman and a sort of jingle: "Bing"! OK, that was to make us comfortable, that was to have a quick laugh, that was to break the ice, that was ... only the begin!
The entire presentation showed us stats, those stats were retrieved from God Knows which tool bar present only in Internet Explorer, and those stats, even if from IE world, put Microsoft search engines in third position, I can't imagine what could come from Mozilla or Google, if they present stats based on their own products ... I guess Bing would not even exists ...
Since those stats were not that pro-bing, they stopped into a slide with classical promises a la "it's simple, it's friendly, it's new, it's brand, it's something you should use, it makes your life better" ... no comment.
Fortunately, some guy started instantly to ask what was new, what was interesting, what was the missing piece that other well known search engines do not have ... and every question had behind a though like: why are we here and what are you showing us? We are not dummies and we know what we want, what other offer, and what we are looking for.
Were we interested about TV ad like presentation? NO
Were we interested about promises other search engines maintain since ages? NO
Were we interested about U.S.A. verion, being in London, where Bing is still beta and smells like Live from miles without bringing a single new feature and positioning bing itself in the second place when you search for bing in the uk version? NO
So what were they showing us? Did they think we do not know what is a search engine? Probably

Missed Expectations


At least that what I think,everybody was looking for that genius thing that nobody else have ... it did not happen! Apparently, the most innovative thing is the live video preview for video results ... OK, I want to be honest, I think everybody over 18 has seen some xxx search engine and everybody knows that a quick preview in a video link is not a Bing idea ... isn't it?
The second most important innovation is a vertical focused lateral bar, something that simply remove spaces fr mobile devices, something useful because with that kind of layout and images behind white links people could even not notice top links so here they are with an innovative lateral menu ... is this wow?

Bing UK, I Want Developers Name!


First of all, for a company that sell enterprise software a la Visual Studio Team System, I wonder how it can be possible that whatever country version is different from every other ... merge projects and use one big development team? Naaaaaaaaa, they prefer to delegate search engine development in each country ... what a waist of money! The UK version is a new graphical version of the Live.co.uk search engine, same weird results (Bing itself in second position after a link called News about Bing ...), not a single lateral bar, nothing useful in the home page ... and about this, 110Kb of home page because of course if a user needs to search something he has to wait the castle, the building, the big sized image in home page. Moreover, with 13 inline JavaScript files, when you chose a different search type switching from Web to Image, the entre page is reloaded and the only difference is the form action, using /images/ rather than the main path ... I mean: Are You Serious?
Design wise, as I said in some other post I am partially color blind. I perfectly recognize red and green, but slight gradients make my life truly difficult.
Google, in its simplicity, studied a lot color contrasts to make everything clear, now try to read the disclaimer, or links bottom right ... oh really? You did not even know there were links there? I am not a designer, but you do not need a PHD to understand that bright text over a bit brighter background does not make sense ... now put white text over images loads of details ... and now tell me how long you spent to read that text, and how much all these problems do not exists in both Yahoo and Google. Is it all about design? Does it make sense to create a 100Kb home page just to add noise and confusion? Did they truly need 13 inline JavaScript for a page that has no functionality rather than a field? Where is the simplicity they are talking about?
Google, 25Kb, you write, you press enter, that's it, that's why they are the number one search engine ... no confusion, not a single waist of time or bandwidth, optimized for mobile devices and even if Microsoft has more than one HTC device, they do not care ... try to surf Bing with iPhone or Android ... are we still in 2000 or in the netbook/small screen devices era? A splash in the past, and still nothing new!

Bing U.S.A. You Click Rather Than Scroll!


Again, I did not get this "feature", the vertical oriented menu on the left suppose to make everything simple because in Gogle you have to scroll ... What?
The scrolling operation with a mouse is extremely natural and it can be performed everywhere in the page while it is still natural with mobile devices where with a finger or a dedicated button you just ... scroll! The search, point, and click is a boring, slow, tedious, operation, even more difficult with mobile devices and whatever "finger-pad" panel we all have in our mobile devices. In few words, in UK Bing presentation they showed us how simple is to find Washington map ... you search for Washington, the engine is so clever to understand that you are looking for a city ( again, moronic stuff, we all know that this is the abc for a top ten search engine ) and if you click Map in the left side menu, you will find the map. In Google, you have to scroll ( weird, I always found maps in the top of the page ) to find information, so they organized everything, with a response page which average is again about 70Kb VS 30 to 35 for Google, where in the latter one you can find everything you need in one page, quick, simple, that is simple!
I do not want to comment the fact they proposed U.S.A. related searches, and non UK images in the home page for the UK Bing version ...

There Will Be Time For Technical Question?


After any sort of question and hundreds of good points about missed interesting news for this new Microsoft search engine, I simply called time to ask technical question. THey said yes but thre was no time, and you know what? I got time blowing out loudly and quickly my points producing non-sense sentences cause I lost number of things to ask or say ... but one thing I will never forget: I asked about 13 inline scripts and the reason if in the UK version I click images I have to reload the page just to change a form target ... the answer was: I do not know what you are talking about ... OK, probably misunderstanding, probably not DB related, but at the end of the day, the only though in my mind was this one: Why on earth they called me? Did they think I was a web troll? Did they think I was a teenager with a lot of time to waist behind the PC? Did they ever consider me as a 10 years experienced web developer with deep JavaScript knowledge, server side certifications, and studies that not a single young Phd person have unless he/she has not my same passion?
Disappointed, partially humiliated, and still load of doubts about how the presentation supposed to be and the reason they called us.

Is Everything That Bad?

One thing I truly appreciated, which does not come from this meeting, is the Bing API, in my opinion well done and flexible enough to let us create interesting applications or web gadgets. If you'll stay tuned, I am planning to create a bookmarkable script that will make searches nice, simple, and friendly, exactly how Bing should, in Microsoft mind, be.

Finally, this post is only my impression, my opinions, and nothing else. I may have misunderstood a lot of words/questions, specially after a couple of fresh beers, but I still wonder why I was there ... and if I would like to be there again. Let's see how things will be.

Post Scriptum

All my opinions come from 30 minutes analysis in place, during the meeting, I've never had time these days to investigate the search engine itself so I may have missed something ... again, take carefully what I said about Bing, thanks.

Labels: , ,

ECMAScript ISO Date For Every Browser

One most than welcome new entry of ECMAScript 5 is the Date.prototype.toISOString function and ability for Date constructor to accept an ISO String and to generate a Date instance.
This feature will make JSON Date instances import/export extremely fast and simple, but why should we wait ES5 release when we can have both features now?

Full Specs ISO 8601 Parser Plus Unobtrusive toISOString Method


We all do not like that much to extend native JavaScript constructors, so here I am with a proposal that will not touch the Date prototype:

if(!Date.ISO)(function(){"use strict";
/** ES5 ISO Date Parser Plus toISOString Method
* @author Andrea Giammarchi
* @blog WebReflection
* @version 2009-07-04T11:36:25.123Z
* @compatibility Chrome, Firefox, IE 5+, Opera, Safari, WebKit, Others
*/
function ISO(s){
var m = /^(\d{4})(-(\d{2})(-(\d{2})(T(\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|((\+|-)(\d{2}):(\d{2}))))?)?)?$/.exec(s);
if(m === null)
throw new Error("Invalid ISO String");
var d = new Date;
d.setUTCFullYear(+m[1]);
d.setUTCMonth(m[3] ? (m[3] >> 0) - 1 : 0);
d.setUTCDate(m[5] >> 0);
d.setUTCHours(m[7] >> 0);
d.setUTCMinutes(m[8] >> 0);
d.setUTCSeconds(m[10] >> 0);
d.setUTCMilliseconds(m[12] >> 0);
if(m[13] && m[13] !== "Z"){
var h = m[16] >> 0,
i = m[17] >> 0,
s = m[15] === "+"
;
d.setUTCHours((m[7] >> 0) + s ? -h : h);
d.setUTCMinutes((m[8] >> 0) + s ? -i : i);
};
return toISOString(d);
};
var toISOString = Date.prototype.toISOString ?
function(d){return d}:
(function(){
function t(i){return i<10?"0"+i:i};
function h(i){return i.length<2?"00"+i:i.length<3?"0"+i:3<i.length?Math.round(i/Math.pow(10,i.length-3)):i};
function toISOString(){
return "".concat(
this.getUTCFullYear(), "-",
t(this.getUTCMonth() + 1), "-",
t(this.getUTCDate()), "T",
t(this.getUTCHours()), ":",
t(this.getUTCMinutes()), ":",
t(this.getUTCSeconds()), ".",
h("" + this.getUTCMilliseconds()), "Z"
);
};
return function(d){
d.toISOString = toISOString;
return d;
}
})()
;
Date.ISO = ISO;
})();

The public static ISO Date method accepts a valid ISO 8601 String compatible with W3 Draft:

Year:
YYYY (eg 1997)
Year and month:
YYYY-MM (eg 1997-07)
Complete date:
YYYY-MM-DD (eg 1997-07-16)
Complete date plus hours and minutes:
YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
Complete date plus hours, minutes and seconds:
YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
Complete date plus hours, minutes, seconds and a decimal fraction of a second
YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)

where:

YYYY = four-digit year
MM = two-digit month (01=January, etc.)
DD = two-digit day of month (01 through 31)
hh = two digits of hour (00 through 23) (am/pm NOT allowed)
mm = two digits of minute (00 through 59)
ss = two digits of second (00 through 59)
s = one or more digits representing a decimal fraction of a second
TZD = time zone designator (Z or +hh:mm or -hh:mm)

The only limit is about milliseconds and JavaScript Date itself, the latest parameter will be rounded if there are more than 3 digits (JS precision is up to a millisecond, no microsecond yet).
The toISOString method is created for every browser that does not support this prototype yet but it is simply assigned and compiled once to avoid Date prototype problems and to optimize memory and performances.
I interpreted ISO specs as Zulu default:

var normalDate = new Date(2009, 06, 04);
var ISODate = Date.ISO("2009-07-04");

normalDate.toISOString = ISODate.toISOString;

alert([ // being in UK ...

// 2009-07-03T23:00:00.000Z
normalDate.toISOString(),

// 2009-07-04T00:00:00.000Z
ISODate.toISOString()
].join("\n"));

Since solar time is +01 hour, if I create a Date with midnight time, the respective Zulu one (UTC) will be the day before at 23:00:00 while since ISO consider an unspecified Time Zone the Zulu one, +00:00, the created Date will be exactly the specified one but obviously if we try to get ISODate.getHours() it will be 01 and not 00, accordingly with my local settings.

This is a little function/proposal that has zero dependencies, is widely compatible, and could be a standard or a must for every library/framework. Waiting for your thoughts, have a nice we 8)

Labels: , , , , ,

Sunday, June 28, 2009

Bing Round Table - Tomorrow

Tomorrow I am going to #meetbing to talk about Bing ( :P ) and its present/future.
The event has been better described by Phil Leggetter and as He did, I would like to know if there is any tech question you would like me to bring there.

So far, I kinda like what Bing API offers, and I am planning to use it soon, but my only concern is about requests limits over a single IP.
Thinking about firewalled/natted/DHCPped infrastructure, 7 different people could not use a generic Bing gadget in the same moment ... anything else?

Labels:

Wednesday, June 24, 2009

ES5 arguments and callee, I was wrong!

JavaScript is not JavaScript, I am not crazy, it is just a consideration between the language itself and what is behind it: another programming language with lower level rules and logic ... sounds silly and obvious, but please keep reading to understand what I mean.

No Results Yet, But I've Already Lost My Battle

I spread comments, I wrote post after posts to defend ECMAScript 5 arguments.callee decision with "use strict", but I have to admit I have never investigate the internal behavior of callee, an arguments property which is not what we think is ...

Discovering In Core The Callee Property

What I was thinking was something hilarious for a C or C++ programmer: an inherited property for a mutable instance.

// JavaScript should have a "secret" Arguments class
// and for each function, something like this
function Test(){};

// we have declared the function Test
// internally there should be a secret operation like this:

Test._createArguments = function(args){
for(var i = 0; i < args.length; i++)
this[i] = args[i];
};
Test._createArguments.prototype.callee = Test;


// and for each Test call, there should be
// a secret operation like this one:
Test._injectArguments(
new Test._createArguments(args);
);

// in order to retrieve Test arguments
// variable for each call ... inheriting
// automatically the callee property

Apparently, except for Internet Explorer, I was so wrong.
arguments.callee is not a pointer or a static variable retrieved instantly as {callee:"it's a me!"}.callee could be, arguments, plus callee is a property with a "discover latency" able to make each call execution up to 100 times slower than a regular function!

We Want Perfomance? Get Rid Of Arguments And Callee Then!

Even with most advanced JavaScript Engines, like the V8 one used by Google Chrome Browser, arguments and arguments.callee are a big bottleneck. Test by yourself!

(function(){
// Array to store execution time
var execution = [];

// named function
function factorial(i){
return i < 2 ? i : i * factorial(i - 1);
};
for(var i = 0, t = new Date; i < 1000; ++i)
factorial(100);
t = new Date - t;
execution.push(
"Native named function: " + t
);

// named function with arguments
function fact(i){
var i = arguments[0];
return i < 2 ? i : i * fact(i - 1);
};
for(var i = 0, t = new Date; i < 1000; ++i)
fact(100);
t = new Date - t;
execution.push(
"Native named with arguments: " + t
);

// arguments.callee
fact1 = function(i){
return i < 2 ? i : i * arguments.callee(i - 1);
};
for(var i = 0, t = new Date; i < 1000; ++i)
fact1(100);
t = new Date - t;
execution.push(
"arguments.callee: " + t
);

alert(execution.join("\n"));
})();

Impressive is the responsiveness of Internet Explorer, the browser which is "die hard" and the only one I was trying to defend about this decision, due to named functions misbehavior. IE is about 100 times slower when arguments variable is used, while Firefox 3 for example is about 50 time slower when arguments.callee is discovered. Chrome is about 4 times slower with both arguments, and callee, and the same is for Safari and Opera, impressive results. A little note about Chrome, apparently the main problem is the scope resolution, rather than arguments or callee.

We Still Love Scripting: A Callee Proposal

During these tests, I can proudly say I found a way to understand in which era we are, thanks to this simple snippet:

// WebReflection knows if we are in ES5 era!
navigator.ES5 = (function(){"use strict";try{return !arguments.callee}catch(e){return true}})();

Avoiding conflicts via global navigator object, ES5 will tell us if the browser is compatible with ECMAScript 5 "use strict"; rule or not, allowing our code to behave differently when necessary.
It does not really matter in any case, to use my callee proposal we need to inject a callee property, as I suggested in the latest post, and for the sake of good gode, via eval:

// Another WebReflection Silly Idea
function F/*or whatever name you prefer*/(callee){
return eval("(callee="+callee+")");
};

Above function is able to take a user defined function and to inject a callee property creating another defined function, a sort of operation usually performed once and never again. In few words, inside our function body we will find another variable with local scope: callee

(function(){
"use strict"; // or not

var execution = [];

// create the function via F
factorial = F(function(i){
// we got arguments, and callee
return i < 2 ? i : i * callee(i - 1);
});
for(var i = 0, t = new Date; i < 1000; ++i)
factorial(100);
t = new Date - t;
execution.push(
"WebReflection F: " + t
);

alert(execution.join("\n"));
})();

This strategy is particularly useful for these cases:

  • classic configuration object, new Ext.Panel({listeners:render:F(function(Panel){
    Panel.removeListener("render", callee);
    })})

  • classic pre-compiled function, var circle = F(Function("r,i","return !i ? r*callee(r," + Math.PI + ") : r*i"));

  • every time we would like to retrieve arguments.callee


Last point is the one that should let us think about what we have done so far.
If we try to execute latest benchmark, we will realize that specially with Internet Explorer, the evaluation trap works faster than arguments.callee so every time we need callee, but we do not need arguments, we should go for it.

Deeper Investigation

I'll keep digging inside this stuff but right now the only thing I can say is that I will try to avoid the usage of arguments.callee every single time I can because specially for the already JS speaking slow browser Internet Explorer, it is a performances killer I could not even imagine.

I hope I gave you more knowledge about this problem and why ECMAScript group decided to get rid of callee, and in a possible future get rid of arguments as well. One side is pro scriptish stuff, and we all love it, bot the other side is about how much this stuff could slow down Web possibilities. Stay tuned!

P.S. amazing, in FF and Chrome you can set whatever property into the navigator object and rather than transform it into a string a la window.name, you can safe whatever amount of data without loosing it until you do not close that tab!!! Stay tuned for this as well, it is a new security or hack problem we could use for better purposes ;)

Labels: , , ,

Monday, June 22, 2009

Do Not Remove arguments.callee - Part II

Few days ago kangax demystified named function expressions, underling the importance of the read only function name property and how messy is Internet Explorer JScript engine with named function and their scope.

Before that post, I wrote one about ECMAScript 5 decision to remove arguments.callee when "use strict"; is present (note in the link: it is not deprecated right now, it is an arguments property)

How These Two Things Are Related

While kangax post was more focused about possible leaks and unexpected functions definitions, I would like to grab more attention about what this problem will cause in tomorrow libraries and JavaScript usage. Removing arguments.callee, our code size, apparently faster in core thanks to this missed variable, will increase drastically and a big part of the beauty of JavaScript language will disappear with this callee decision.

The Classic Configuration Object Problem

How many libraries base constructors via configuration objects?
jQuery Ajax ?

$.ajax({
url:"page.server",
success:function(data){
if(data){
$.ajax({
url:"fallback.server",
success:arguments.callee
});
} else
alert("everything is OK");
}
});

NO? Simple enough, but of course I could use the "long kangax procedure" to wrap that function to avoid IE problems ... and in any case, what about two Ajax calls in the same page?

$.ajax({
url:"page.server",
success:function success(data){
// whatever will be
// .... but don't ya think it is a bit
// redundant? How will be our code style,
// worse than an open close XML tag?
}
});

// second call ...
$.ajax({
url:"page.server",
success:function success(data){
// which one will be the
// function success in
// Internet Explorer ???
}
});

More comes with User Interface libraries, take ExtJS as example ...

new Ext.Panel({
renderTo:document.body,
listeners:{
render:function(Panel){
// do some stuff ... and ...
Panel.removeListener("render", arguments.callee);
}
}
});

Above snippets is so simple that ECMAScript 5 better decided to transform it into something like this:

new Ext.Panel({
renderTo:document.body,
listeners:{
// not suitable for IE and multiple
// Panel creations ...
render:function render(Panel){
Panel.removeListener("render", render);
}
}
});

// suitable for IE as well
new Ext.Panel({
renderTo:document.body,
listeners:{
render:function(Panel){
var callee = Panel.initialConfig.listeners.render;
// note how long and boring is precedent string/operation

Panel.removeListener("render", callee);
}
}
});

In few words, we have to forget shortcuts to add and remove listeners for any kind of configuration object. Nice, isn't it?

The Classic Pre Compiled Function Problem

Another problem comes with Function constructor, able to create an anonymous function (lambda) via string and a preferred solution over eval calls. A pre compiled function is something created once and executed at "native speed" for each call. Example:

// classic function
function circle(r){
return r * r * Math.PI;
};

// pre compiled one
var circle = Function("r", "return r * r * " + Math.PI);

The main difference between above functions is that the first one needs to discover in the scope the Math "variable" plus its PI parameters for each call, while the second one will be exactly the function:

function anonymous(r) {
return r * r * 3.141592653589793;
}

which is about 1.6 to 2 times faster than the other one .... cool? Perfect, now try to imagine that our pre-compiled function is more complicated and inside a closure ... how the hell do you think to retrieve the function itself?

(function(){
// my library scope

// this one will generate an errror
// Function evaluates in a global scope
var f = Function("i", "return i < 2 ? i : i + f(i - 1)");

// we have only two options here ...
// the elegant one:
var f = Function("i", "return i < 2 ? i : i + arguments.callee(i - 1)");

// or the horrible namespace conflicts prone one ...
var hopefullyNoProblems = "myLib" + (""+Math.random()).slice(2);
window[hopefullyNoProblems] =
Function("i", "return i < 2 ? i : i + window." + hopefullyNoProblems + "(i - 1)");

})();

Cool enough? That function will be extremely slower than a pre-compiled one due to the global window object which is a variable not that fast to retrieve.
Moreover, since they decided that null or undefined should not be considered as window object, the usage of this of run-time called function is not a shortcut anymore, is it?

As Summary

This is my last chance to explain the importance of arguments.callee which is NOT the reason JavaScript is less secure, it is only a pain in the ass for JS engines developers as is arguments variable itself, the magic one which apparently is going to disappear as well.
What I do not understand, is why they do not make callee a reserved keyword and put this variable inside the function body as is for arguments and the function name.

function itsEasy(i){
// itsEasy lives only here in every browser except IE
// arguments lives only here in every browser
// so it is simple to put itsEasy, arguments,
// but so many problems with a callee variables ?
return i < 2 ? i : i + callee(i - 1);
};

We'll see how much we will have to change our code and how bigger will be for this non-sense decision ... JavaScript beauties should not be changed, even PHP has at least a function to retrieve the arguments array ... put a function then, whatever other solution, but please do not constrict developers to name in a completely meaningless and redundant way every single lambda. Not a single lambda based language is that fossy about it, IMHO.

Labels: , ,