behind the design
My JavaScript book is out!
Don't miss the opportunity to upgrade your beginner or average dev skills.
Monday, December 31, 2007
[OT] Never forget old school!
Another year has gone, new technologies are coming but please never forget genuine old style. Happy new year to everyone from me and old "friend" :D
Saturday, December 29, 2007
Is JSON forgetting something?
I played many times with JSON serialized data, creating odd alternatives too like JSTONE or JSOMON.
Few years ago I created even a PHP compatible serializzation but nowadays, with PHP5, json_encode and json_decode are natively integrated in PHP language and, at the same time, even faster than old serialize and unserialize global functions.
Both JSON and PHP Serialized data have the same goal: transport objects and data over http protocol or storage these informations inside a cookie, a database or why not, a file.
However, PHP serialize and unserialize functions do more things than JSON serializzation, adding charset/indexes informations transporting even private or protected parameters.
With JavaScript 3rd edition We have not latter kind of properties so we shouldn't care about this limit during serializzation.
This is probably the most important difference between these two different serializzation but there is another one that should be easily implemented in JavaScript too: magic __sleep and __wakeup methods.
The most important information we need to make JSON more magic than ever should be the constructor name. Without this information every kind of instance will lose its special methods/properties reducing them as a common Object.
Usually, this is exactely what we would like to transport, keys and values or, in the case of Array, only its values.
I'm thinking about something like that:
I think that original objects doesn't need their constructor name.
In this way the unique change is for different instances and JSON syntax is quite the same.
With a string like that we should use eval too in a simple way:
The __wakeup magic method should be used to do something before the object will be assigned, extremely useful in a lot of common situations.
The magic __sleep method should be the same used with PHP.
A simple prototype that could do everything but that needs to return properties we want to serialize.
This should be a JSON parser problem that could check every instance and use, only if it's present, its __sleep method.
This is just a personal brainstorming/proposal and I would like to know what do you think about that.
P.S. marry Christmas and happy new year :-)
Few years ago I created even a PHP compatible serializzation but nowadays, with PHP5, json_encode and json_decode are natively integrated in PHP language and, at the same time, even faster than old serialize and unserialize global functions.
The big difference between JSON and PHP serializzation
Both JSON and PHP Serialized data have the same goal: transport objects and data over http protocol or storage these informations inside a cookie, a database or why not, a file.
However, PHP serialize and unserialize functions do more things than JSON serializzation, adding charset/indexes informations transporting even private or protected parameters.
With JavaScript 3rd edition We have not latter kind of properties so we shouldn't care about this limit during serializzation.
This is probably the most important difference between these two different serializzation but there is another one that should be easily implemented in JavaScript too: magic __sleep and __wakeup methods.
What do we need
The most important information we need to make JSON more magic than ever should be the constructor name. Without this information every kind of instance will lose its special methods/properties reducing them as a common Object.
Usually, this is exactely what we would like to transport, keys and values or, in the case of Array, only its values.
I'm thinking about something like that:
function A(){};
function B(){};
B.prototype.__wakeup = function(){
this.d = String.fromCharCode(this.c + this.a.charCodeAt(0));
};
var a = new A;
a.a = "b";
a.c = "d";
a.e = new B;
a.e.a = "b";
a.e.c = 3;
alert(encode(a));
// $("A",{"a":"b","c":"d","e":$("B",{"a":"b","c":3})})
I think that original objects doesn't need their constructor name.
In this way the unique change is for different instances and JSON syntax is quite the same.
With a string like that we should use eval too in a simple way:
function decode(str){
function $(constructor, o){
var result = eval("new ".concat(constructor)), key;
for(key in o){
if(o.hasOwnProperty(key))
result[key] = o[key];
};
if(typeof result.__wakeup === "function")
result.__wakeup();
return result;
};
return eval(str);
};
function A(){};
function B(){};
B.prototype.__wakeup = function(){
this.d = String.fromCharCode(this.c + this.a.charCodeAt(0));
};
var o = decode('$("A",{"a":"b","c":"d","e":$("B",{"a":"b","c":3})})');
alert([o instanceof A, o.e instanceof B, o.e.d]);
The __wakeup magic method should be used to do something before the object will be assigned, extremely useful in a lot of common situations.
What about __sleep?
The magic __sleep method should be the same used with PHP.
A simple prototype that could do everything but that needs to return properties we want to serialize.
This should be a JSON parser problem that could check every instance and use, only if it's present, its __sleep method.
Improvements
- constructor name for instances that are not just objects
- better server side parsers to manage instances without loosing their constructor name
- a global name for dollar function, if some library use them as constructor too to avoid problems during instance creation (or a simple global-scope evaluation for each new "constructor" assignment)
This is just a personal brainstorming/proposal and I would like to know what do you think about that.
P.S. marry Christmas and happy new year :-)
Friday, December 21, 2007
JavaScript Iterator for IE and other browsers
This is just my proposal to add Iterator in Internet Explorer and other browsers too.
The best way to use them is with iter.next() method but you could use a for in loop too.
However, in latter case if the object has a next property, it will be overwrote by dynamic method but this problem apart, enjoy iterators :-)
(function(){
function Iterator(obj, name){
// Iterator(obj) and new Iterator(obj) behaviour
if(this instanceof Iterator){
var i = 0,
result = [],
skip = false,
key;
for(key in obj){
result[i++] = name ? key : [key, obj[key]];
this[key] = undefined;
if(!skip && (key == "constructor" || key == "toString" || key == "valueOf"))
skip = true;
};
// solve IE problems
for(var l = 0, arr = ["constructor", "toString", "valueOf"]; !skip && obj.hasOwnProperty && l < arr.length; l++){
if(obj.hasOwnProperty(arr[l])){
result[i++] = name ? arr[l] : [arr[l], obj[arr[l]]];
this[arr[l]] = undefined;
};
};
// add next method if any next in object
this.next = function(){
if(i === result.length)
throw new StopIteration;
else
return result[i++];
};
// reset result "pointer"
i = 0;
}
else
return new Iterator(obj, !!name);
};
function StopIteration(message, fileName, lineNumber){
this.message = message;
this.fileName = fileName;
this.lineNumber = lineNumber;
};
StopIteration.prototype = new Error;
// global scope check
if(!this.Iterator)
this.Iterator = Iterator;
if(!this.StopIteration)
this.StopIteration = StopIteration;
})();
// test it!
var iter = Iterator({a:"b", next:"c", toString:"hello"}),
output = [];
try{
while(true)
output.push(iter.next());
}
catch(err){
if(err instanceof StopIteration)
output.push("End of record");
else
output.push("Unknown error: " + err.description);
};
alert(output.join("\n"));
The best way to use them is with iter.next() method but you could use a for in loop too.
However, in latter case if the object has a next property, it will be overwrote by dynamic method but this problem apart, enjoy iterators :-)
Thursday, December 20, 2007
packed.it ... again online
I am sorry for last days while packed.it wasn't working as expected because of new server.
It seems to be faster than precedent one so thank you again Daniele, I'll write your link as soon as I can :-)
Enjoy both JavaScript and CSS compressed files in a single one, enjoy packed.it!
It seems to be faster than precedent one so thank you again Daniele
Enjoy both JavaScript and CSS compressed files in a single one, enjoy packed.it!
Monday, December 10, 2007
FireFox, Safari, and Opera ... JavaScript Conditional Comment
I've still written a comment in John Resig blog about Re-Securing JSON and FireFox or Safari 3 const behaviour to create an immutable function, called Native, and to retrieve original Array, Object, String or other constructors.
This is the function:
At the same time I've talked about IE behaviour and its missed support for const.
While I was thinking about that I imagined a way to use a piece of code, in this case the keyword const, compatible with every browser.
It should sounds simple, just use the well know trick IE=/*@cc_on ! @*/false; followed by if(IE) ... but ... hey, I need everytime to create a double version of the "same script" ... is it good?
Try to imagine a variable that should be a constant for every compatible browser but at the same time should be declared just one time ...
With every day practices we should use a try catch or some strange trick to evaluate a const declaration ... don't we?
But we have a particular behaviour of the conditional comment ... it should contains a comment itself too, sounds cool?
Can anyone trigger an error with above piece of code? :-)
In this way FireFox 2+, Safari 3+ (I don't know about 2), and Opera 9+ could work without problems disabling Native variable re-declaration while every IE browser will ignore the const keyword.
I suppose this trick is not so new but never as this time it should be useful to make code more slim and efficient.
Instant Update
The usage of const inside the private scope of Native function declaration is not so useful (just a little bit of paranoia :D) but in these cases we could use a better trick to create local variables with internet explorer too.
This is an example:
Above example shows how should be possible to initializzate multiple variables using a comma and respecting the private scope.
Internet Explorer will use var while every other browser will try to use const if it's compatible.
Sounds even better? I hope so :-)
P.S. Native function is quite interesting, imho, that's why I choosed to add them in devpro.it
This is the function:
const Native = (function(){
const NArray = Array,
NBoolean = Boolean,
NDate = Date,
NError = Error,
NMath = Math,
NNumber = Number,
NObject = Object,
NRegExp = RegExp,
NString = String;
return function(Native){
switch(Native){
case Array:return NArray;
case Boolean:return NBoolean;
case Date:return NDate;
case Error:return NError;
case Math:return NMath;
case Number:return NNumber;
case Object:return NObject;
case RegExp:return NRegExp;
case String:return NString;
};
};
})();
// Example
Array = Native(Array);
eval("[1,2,3]");
At the same time I've talked about IE behaviour and its missed support for const.
While I was thinking about that I imagined a way to use a piece of code, in this case the keyword const, compatible with every browser.
It should sounds simple, just use the well know trick IE=/*@cc_on ! @*/false; followed by if(IE) ... but ... hey, I need everytime to create a double version of the "same script" ... is it good?
Try to imagine a variable that should be a constant for every compatible browser but at the same time should be declared just one time ...
const MyConstant = 1;
With every day practices we should use a try catch or some strange trick to evaluate a const declaration ... don't we?
But we have a particular behaviour of the conditional comment ... it should contains a comment itself too, sounds cool?
/*@cc_on // @*/ const
Native = function(){
// whatever You need
};
Can anyone trigger an error with above piece of code? :-)
In this way FireFox 2+, Safari 3+ (I don't know about 2), and Opera 9+ could work without problems disabling Native variable re-declaration while every IE browser will ignore the const keyword.
I suppose this trick is not so new but never as this time it should be useful to make code more slim and efficient.
Instant Update
The usage of const inside the private scope of Native function declaration is not so useful (just a little bit of paranoia :D) but in these cases we could use a better trick to create local variables with internet explorer too.
This is an example:
Native = (function(){
/*@cc_on var // @*/ const
NArray = Array,
NBoolean = Boolean;
return function(Native){
return Native === Array ? Narray : NBoolean;
};
})();
Above example shows how should be possible to initializzate multiple variables using a comma and respecting the private scope.
Internet Explorer will use var while every other browser will try to use const if it's compatible.
Sounds even better? I hope so :-)
P.S. Native function is quite interesting, imho, that's why I choosed to add them in devpro.it
Wednesday, December 05, 2007
Looking for a job in London ... or not?
It's about 2 weeks that I'm studying in London to improve my English knowledge, specially my spoken one (I know, written is not so perfect too).
I put my cv on line in a famous recluting search engine but it seems that most interested people are Agency's employees that usually look for generic IT - Web masters.
I would like to explain my "strange situation": I am not absolutely a web designer, I do know quite nothing about graphic, I could just know how to start Gimp!!! :D
It seems that if You know quite perfectly ActionScript 1.0/2.0, that's basically ECMAScript 3rd edition or, in case of 2.0, 4th one closed, you can be only a Web Designer and not a programmer, even if You know Flash Player bugs and you're able to find out workarounds.
It seems that if You know deeply JavaScript (best practices, OOP, Ajax, cross-browser/platform development, bugs, common libraries suggestions) it's not important ... just a preferred plus ... but at the same time everybody is looking for Ajax and Web 2.0 skilled developers, a role that absolutely requires a good programming background (not just a bit of DreamWeaver).
It seems that if you know different languages or technologies ... there's always a missed one.
How can a person to be "senior in every program language"?
I can't call their "expert or senior everything developers", a part for someone who has at least 20 years or more experience.
However, excellent OO PHP 4/5,JavaScript,ActionScript,(x)HTML,CSS,XML skills aren't enough while a good knowledge of C# for ASP.NET or MONO, and Python is not enough as a technical plus.
Maybe someone should be interested in my good database skills, starting from SQLite 2/3 to MySQL 3/4/5, passing inside PostgresSQL ... but it's not enough.
What about security practices and code optimization skills? Who cares about that!
As sum, and as someone said before me: please hire me !!! :-)
Best regards,
Andrea Giammarchi
I put my cv on line in a famous recluting search engine but it seems that most interested people are Agency's employees that usually look for generic IT - Web masters.
I would like to explain my "strange situation": I am not absolutely a web designer, I do know quite nothing about graphic, I could just know how to start Gimp!!! :D
It seems that if You know quite perfectly ActionScript 1.0/2.0, that's basically ECMAScript 3rd edition or, in case of 2.0, 4th one closed, you can be only a Web Designer and not a programmer, even if You know Flash Player bugs and you're able to find out workarounds.
It seems that if You know deeply JavaScript (best practices, OOP, Ajax, cross-browser/platform development, bugs, common libraries suggestions) it's not important ... just a preferred plus ... but at the same time everybody is looking for Ajax and Web 2.0 skilled developers, a role that absolutely requires a good programming background (not just a bit of DreamWeaver).
It seems that if you know different languages or technologies ... there's always a missed one.
How can a person to be "senior in every program language"?
I can't call their "expert or senior everything developers", a part for someone who has at least 20 years or more experience.
However, excellent OO PHP 4/5,JavaScript,ActionScript,(x)HTML,CSS,XML skills aren't enough while a good knowledge of C# for ASP.NET or MONO, and Python is not enough as a technical plus.
Maybe someone should be interested in my good database skills, starting from SQLite 2/3 to MySQL 3/4/5, passing inside PostgresSQL ... but it's not enough.
What about security practices and code optimization skills? Who cares about that!
As sum, and as someone said before me: please hire me !!! :-)
Best regards,
Andrea Giammarchi
Thursday, November 01, 2007
A quite totally standard enviroment before ECMAScript 4th Edition in less than 3Kb - JSL 1.8+
JavaScript Standard Library Revision
After the success of my old JSL project I learned more about JavaScript and I found some trick to solve different problems such setInterval and extra arguments for Internt Explorer, a function to evaluate code in a global scope with every browser as Internet Explorer does with its proprietary execScript.
Since these days We're waiting for ECMAScript 4th Edition, aka JavaScript 2 but since We always don't know when it should be really usable within productions, I choosed to create a revisited version of JavaScript Standard Library.
I removed Internet Explorer 4 support but I modified a lot of common prototyes to make them faster, more standard and more scalable than ever.
You can use, for example, every JS 1.6+ Array.prototype with HTMLCollections too as it's possible from many Years with FireFox or Safari:
Array.prototype.forEach.call(document.getElementsByTagName("div"), function(node){
alert(node.innerHTML);
});
I fixed different standard behaviours and I implemented setTimeout and setInterval.
I add execScript, not standard, but really useful when You need to evaluate JavaScript in a global scope with FireFox, Safari, Opera and every other as Internet Explorer does from many years with its own execScript global function.
JSL creates a quite totally standard JavaScript 1.6+ enviroment adding prototypes only to browsers that don't support them or that have different behaviours and everything in a hilarious size of
With JSL You can forget your own not always standard prototypes implementations so every library size could decrease its code quickly, basing them on standard JavaScript 1.6+ enviroment and increasing performances for every standard browser like FireFox or Safari (about 40% of users ... growing up every day!).
This is the last chance to have a more standard Internet Explorer implementation because if We need to wait their fixes We should go better to sleep.
Have fun with JSL Revision and a quite real ECMAScript 3rd Edition enviroment.
Monday, October 29, 2007
[COW] JavaScript define PHP like function
This time my personal COW is a quite totally cross browser function to define a JavaScript constant.
With FireFox or Safari a const variable should be nested or global but the most important thing, it cannot be assigned two times
A constant should be every kind of JavaScript variable and if this feature will be available on future versions of Internet Explorer and Opera, a lot of security problems should be solved (think for example about JSON, Array, Object and every other constructor, method or callback).
Unlikely We can't use this feature with Opera browser and, quite more important, Internet Explorer doesn't support JavaScript constants.
The only way to create a global scope constant variable with Internet Explorer is using another language: VBScript
This IE dedicated language supports PHP like defined constants: scalar values like integer, float, string or boolean.
This function works like PHP define one, except for last argument, case-sensitive, and it is compatible with Internet Explorer (maybe every version), FireFox 2 or greater, Safari 2 or greater and finally Opera 9 o greater too.
The most important thing is that You can't change arbitrary a defined constant and it should be useful in many different cases.
Only Opera 9 has a wrong const implementation because it's just a var alias and not a real constant creation.
Since Opera hasn't a watch Object prototype and since a prototype should be always defined everywhere, this last browser is compatible but it allows value mutation so please remember this when (and if) You choose to use my define proposal.
Finally, please remembre that a constant should respect some rules:
Remark: to ensure cross browser compatibility every value is parsed by function, checking for its toString native or assigned returned value.
This means that define("MY_BOOL", "true") creates a constant called MY_BOOL that will be exactly a boolean true value and the same thing happens if You use "false" that will create a boolean false constant.
This is true for numbers too:
That's all :-)
With FireFox or Safari a const variable should be nested or global but the most important thing, it cannot be assigned two times
const scriptCantChangeMe = "some text";
scriptCantChangeMe = "something else";
alert(scriptCantChangeMe); // some text
A constant should be every kind of JavaScript variable and if this feature will be available on future versions of Internet Explorer and Opera, a lot of security problems should be solved (think for example about JSON, Array, Object and every other constructor, method or callback).
Unlikely We can't use this feature with Opera browser and, quite more important, Internet Explorer doesn't support JavaScript constants.
The only way to create a global scope constant variable with Internet Explorer is using another language: VBScript
This IE dedicated language supports PHP like defined constants: scalar values like integer, float, string or boolean.
JavaScript define function
This function works like PHP define one, except for last argument, case-sensitive, and it is compatible with Internet Explorer (maybe every version), FireFox 2 or greater, Safari 2 or greater and finally Opera 9 o greater too.
define("MY_NOT_MUTABLE_VALUE", 123);
alert(MY_NOT_MUTABLE_VALUE); // 123
MY_NOT_MUTABLE_VALUE = 456; // error with Internet Explorer
alert(MY_NOT_MUTABLE_VALUE); // 123 with both FireFox and Safari
The most important thing is that You can't change arbitrary a defined constant and it should be useful in many different cases.
Only Opera 9 has a wrong const implementation because it's just a var alias and not a real constant creation.
Since Opera hasn't a watch Object prototype and since a prototype should be always defined everywhere, this last browser is compatible but it allows value mutation so please remember this when (and if) You choose to use my define proposal.
Finally, please remembre that a constant should respect some rules:
- its name must be UPPERCASE (MY_CONST instead of MyConst or my_const)
- its name should have a dedicated prefix/suffix to don't be intrusive (MY_LIB_NAME_INITVALUE instead of INITVALUE)
Remark: to ensure cross browser compatibility every value is parsed by function, checking for its toString native or assigned returned value.
This means that define("MY_BOOL", "true") creates a constant called MY_BOOL that will be exactly a boolean true value and the same thing happens if You use "false" that will create a boolean false constant.
This is true for numbers too:
define("MY_STRING", "123") === define("MY_NUMBER", 123); // true
define("MY_STRING", "true") === define("MY_BOOLEAN", true); // true
define("MY_STRING", "-123.456") === define("MY_NUMBER", -123.456); // true
That's all :-)
Thursday, October 25, 2007
adsense destructive function!
Google AdSense is a free and cool service and is widely used inside many sites.
It allows site managers to get paid while they show their content ... it's great and thank You Google for this service.
However adsense uses a function that's probably the most obtrusive one You can use or find while You write JavaScript.
This function is exactely this one:
Using them with own objects is absolutely not a problem but what kind of object do You think that b is? The Window one!
It's absolutely a non-sense for a service that uses JavaScript inside a closure to respect other libraries and to be free to use every name it needs to be executed!
We always use third party libraries or We write JavaScript directly but in both cases We (others) should implement a generic Object.prototype inside our code ... just think, for example, to toJSONString prototype, OK ?
Now suppose that You write your own function, called toJSONString to manage everything else, objects too.
Just add adsense in Your page and everything will not work ... seems interesting?
The right thing is that Object.prototype is always a problem if You don't use method hasOwnProperty inside a generic for(var key in obj) loop.
If You forgot them You should parse, manage, modify, properties that aren't part of your code (however these shoulkd be a part of your code too) and that's exactely what adsense does at the end of its execution.
The reason seems to be simple, adsense script would remove every global variables You write everytime You need them to allow a single page to contain different versions of adsense without any sort of problem with precedent settings.
At the same time every method or parameter assigned to Object.prototype will be "globally deleted" (becoming a null value) so if DjProto called one prototype, for example, escape You'll never be able to use escape as a native function.
At the same time google adsense code itself should fail too because if I write 2 prototypes like these:
and I add one adsense in my page, next one will not be able to encode any kind of string that should be sent to Google service.
Cool?
Since Object.prototype.hasOwnProperty is available only in IE6 or greater (I can't remembre if IE 5.5 has it) Google shouldn't implement this check but it should implement another one even more simple but efficient for this purpose.
In this way every JavaScript compatible browser will remove or will assign to null Google adsense global scoped K object properties only (that are, again, objects of this type google_rl_mode:{url_param:"rl_mode",gfp:0}) without enviroment destruction possibility :-)
Another trick should be this one:
Finally, this post should be helpful to understand better for in loops and problems adding Object.prototype parameters or methods ... and at the same time is another reason to pray that ES4 will be available as soon as Mozilla developers can - it simply let You define which property should be enumerable and which not!
It allows site managers to get paid while they show their content ... it's great and thank You Google for this service.
However adsense uses a function that's probably the most obtrusive one You can use or find while You write JavaScript.
This function is exactely this one:
function $(b){
for(var a in K){
b[a]=null
}
}
Using them with own objects is absolutely not a problem but what kind of object do You think that b is? The Window one!
It's absolutely a non-sense for a service that uses JavaScript inside a closure to respect other libraries and to be free to use every name it needs to be executed!
Why this function is an obtrusive monster?
We always use third party libraries or We write JavaScript directly but in both cases We (others) should implement a generic Object.prototype inside our code ... just think, for example, to toJSONString prototype, OK ?
Now suppose that You write your own function, called toJSONString to manage everything else, objects too.
function toJSONString(){
// doStuff
};
Just add adsense in Your page and everything will not work ... seems interesting?
The right thing is that Object.prototype is always a problem if You don't use method hasOwnProperty inside a generic for(var key in obj) loop.
If You forgot them You should parse, manage, modify, properties that aren't part of your code (however these shoulkd be a part of your code too) and that's exactely what adsense does at the end of its execution.
The reason seems to be simple, adsense script would remove every global variables You write everytime You need them to allow a single page to contain different versions of adsense without any sort of problem with precedent settings.
At the same time every method or parameter assigned to Object.prototype will be "globally deleted" (becoming a null value) so if DjProto called one prototype, for example, escape You'll never be able to use escape as a native function.
At the same time google adsense code itself should fail too because if I write 2 prototypes like these:
Object.prototype.escape = Object.prototype.encodeURIComponent = function(){
return escape(this.toString());
};
and I add one adsense in my page, next one will not be able to encode any kind of string that should be sent to Google service.
Cool?
A really simple and crossbrowser solution
Since Object.prototype.hasOwnProperty is available only in IE6 or greater (I can't remembre if IE 5.5 has it) Google shouldn't implement this check but it should implement another one even more simple but efficient for this purpose.
function $(b){
for(var a in K){
if(Object.prototype[a]!=K[a])
b[a]=null
}
}
In this way every JavaScript compatible browser will remove or will assign to null Google adsense global scoped K object properties only (that are, again, objects of this type google_rl_mode:{url_param:"rl_mode",gfp:0}) without enviroment destruction possibility :-)
Another trick should be this one:
function $(b){
for(var a in K){
if(/^google/i.test(a))
b[a]=null
}
}
Finally, this post should be helpful to understand better for in loops and problems adding Object.prototype parameters or methods ... and at the same time is another reason to pray that ES4 will be available as soon as Mozilla developers can - it simply let You define which property should be enumerable and which not!
Upload progress bar with PHP5, APC and jQuery
Yesterday I wrote a little tutorial (Italian language, sorry) that explain how to create an info panel while a file is uploaded.
Here You can view final result:
While this is the entire archive with everything You need to test by Yourself my code:
APCQuery
To test them You need PHP 5.2 or greater and APC enabled.
Please verify that rfc is enabled too:
If You test them locally please remember to try form using big files (from 40Mb to 200M for fast PCs) changing php.ini upload_max_filesize and post_max_size directives (I suppose 200M is enough).
If someone is interested about an English version of tutorial I'll try to find time to translate them.
Here You can view final result:
While this is the entire archive with everything You need to test by Yourself my code:
APCQuery
To test them You need PHP 5.2 or greater and APC enabled.
Please verify that rfc is enabled too:
extension=php_apc.dll
apc.rfc1867 = On
If You test them locally please remember to try form using big files (from 40Mb to 200M for fast PCs) changing php.ini upload_max_filesize and post_max_size directives (I suppose 200M is enough).
If someone is interested about an English version of tutorial I'll try to find time to translate them.
Tuesday, October 23, 2007
[ES4] ... good by my darlin' toy ...
... and
I can't wait one more minute ... Go ES4 implementations, GO!
Welcome Control Over Performances !!!
I can't wait one more minute ... Go ES4 implementations, GO!
Saturday, October 20, 2007
[COW] locAction - hash JavaScript location wrapper
One of the problems using JavaScript and Ajax is history managment and location behaviour.
A good solution was found by backbase many months ago, using reserved hash location property to manage correctly interactions and history itself.
This COW should be used to manage hash property as a full compilant location, allowing developers to know pathname, search (query string) and in some cases (JavaScript and Opera) hash itself too.
You can view a demo in this page comparing native location and wrapped one using locAction callback.
Please note that backbase too removed this practice from its site (which problems?) but my locAction proposal is compatible with every kind of JavaScript compatible browser (of course, IE4 and NN4 too).
These are few examples:
As You can see with location You can manage directly a parallel/alternative JavaScript/Ajax dedicated url, accepting GET variables as different paths.
In few words You'll have two different address, one for JavaScript disabled browsers and one for JavaScript enabled browsers.
Both locations, original one and generated using locAction, will have same methods too: replace, assign and reload but locAction() object should be always use these methods (direct assignment is not allowed, however native location direct assignment uses transparently assign method so it's quite tha same).
What else? locAction generated object shoud accept hash string but not with Internet Explorer or Safari (at least 3).
A good solution was found by backbase many months ago, using reserved hash location property to manage correctly interactions and history itself.
This COW should be used to manage hash property as a full compilant location, allowing developers to know pathname, search (query string) and in some cases (JavaScript and Opera) hash itself too.
You can view a demo in this page comparing native location and wrapped one using locAction callback.
Please note that backbase too removed this practice from its site (which problems?) but my locAction proposal is compatible with every kind of JavaScript compatible browser (of course, IE4 and NN4 too).
These are few examples:
// basic example - standard location
href: http://localhost:80/?key=value&other
protocol: http
hostname: localhost
port: 80
pathname: /
search: ?key=value&other
hash:
// basic example - locAction(location)
// using http://localhost:80/?key=value&other#hash
href: http://localhost:80/hash
protocol: http
hostname: localhost
port: 80
pathname: /hash
search:
hash:
// full example - standard location
href: http://localhost:80/mypage.html?key=value&other#ajax/page.html?other=key&value
protocol: http
hostname: localhost
port: 80
pathname: /mypage.html
search: ?key=value&other
hash: #ajax/page.html?other=key&value
// full example - locAction(location)
// using http://localhost:80/mypage.html?key=value&other#ajax/page.html?other=key&value
href: http://localhost:80/ajax/page.html?other=key&value
protocol: http
hostname: localhost
port: 80
pathname: /ajax/page.html
search: ?other=key&value
hash:
As You can see with location You can manage directly a parallel/alternative JavaScript/Ajax dedicated url, accepting GET variables as different paths.
In few words You'll have two different address, one for JavaScript disabled browsers and one for JavaScript enabled browsers.
Both locations, original one and generated using locAction, will have same methods too: replace, assign and reload but locAction() object should be always use these methods (direct assignment is not allowed, however native location direct assignment uses transparently assign method so it's quite tha same).
What else? locAction generated object shoud accept hash string but not with Internet Explorer or Safari (at least 3).
Saturday, October 13, 2007
[COW] Web RAM - a JavaScript function to share safely strings
This time my COW is really strange as Web concept ... a total size of 256 bytes (seems hilarius?) to share strings inside each browser window.
This idea is not so new, I wrote JSTONE few months ago to do something similar, however it seems that JSTONE requires dedicated JSON implementation or something similar to work correctly.
Now, let me explain why I wrote this tiny function and for what it should be used for.
window.name is a string always present every time We open a window.
The cool, but not so secure, behaviour of this property is that this persists even if We change site or domain or We refresh page using F5.
While We use the same window, window name will be available, seems cool?
RAM function is capable to save a lot of informations using a Random Access strategy, where the "memory address" is created by yourself, using your personal keyword.
Both keywords and saved data can contain every kind of char excepted for \x00 one (End Of String or null char).
It's based on a sort of automatic namespace management but your keyword is not really your one but as is for libraries, everyone should use a dedicated namespace without conflicts, don't You agree?
Finally, window.name can save strings of hundred of thousand chars, I didn't find a limit for saved informations but as is for real RAM, if You turn off your PC (in this case browser window) it will be automatically resetted.
These days I'm testing my last creation, packed.it, to find problems or to test decompression speed with big data size.
One thing I tough is that with packed code (using packed.it, packer or similar compressors), size is not the real problem as decompression CPU overload is.
I was try to find a way to cache or speed up unpack operation but every test I did failed (bad results).
That's why I created this simple function, to test clear code evaluation performances instead of runtime decompression, allowing users to unpack every kind of code 1 time each window instead of every time.
This means that during navigation in the same window, a new user will unpack code only first time but after first clear code creation procedure, You sohuld save them inside window.name and evaluate them in every other page viewed inside same browser window.
At the same time, if user will leave your page and then come back using back button it will have again code stored if external site didn't modify window.name or modify them without RAM function.
Finally, I could save an address, called for example jQuery :-) ... saving clear source and check them every time one page that use them is called:
Every link in the same window and every site viewed after this one should use same strategy to perform packed sources evaluations faster than ever because decompression will be performed only first time ... not a real solution but at least a simple way to optmize, a bit, navigation and decompression speed?
I'll try to do some test with packed.it, probably as option.
The battle is between a little overload of 256 bytes against 1 to 5 seconds for really big packed sources ... uhm ... what do You think is better?
Do I forget something? Uhm, both keywords and sources could use SOH char too (\x01) without problems but each SOH will be duplicated inside window.name and replaced before You'll read them again to preserve string as is when You get them using RAM.
Update 2007/10/15
DarkCraft sayd that NoScript doesn't allow many chars inside window.name when You change domain, reload the page or do something similar.
I wonder why NoScript guys allows few chars in window.name (someone shoud use them to save user and passwords, for example) instead of clear one ... however, RAM should work without problems with NoScript enabled browsers too, just using a try catch statement.
If You use this piece of code NoScript enabled browsers will just "decompile" each time saved informations, if these contains special chars too.
Please remember that RAM goal is to believe in itself, it's quite obvious that if some malicius site/page/code replace informations or uses malicius version of common libraries RAM function should become totally insecure.
The best practice I could suggest is to use a "private mutable key":
That in a session based enviroment should be something like this code:
To be sure library is shared only during a valid session.
A random cookie should be good enough too but paranoia is always with us :D
Finally, in packed.it I'll add a RAM option based on project name, different each time.
These practices disable cross site library sharing but I hope one day malicious site, developers, will be banned from the Web (just a "little utopia")
This idea is not so new, I wrote JSTONE few months ago to do something similar, however it seems that JSTONE requires dedicated JSON implementation or something similar to work correctly.
Now, let me explain why I wrote this tiny function and for what it should be used for.
Random Access Memory
window.name is a string always present every time We open a window.
The cool, but not so secure, behaviour of this property is that this persists even if We change site or domain or We refresh page using F5.
While We use the same window, window name will be available, seems cool?
RAM function is capable to save a lot of informations using a Random Access strategy, where the "memory address" is created by yourself, using your personal keyword.
Both keywords and saved data can contain every kind of char excepted for \x00 one (End Of String or null char).
It's based on a sort of automatic namespace management but your keyword is not really your one but as is for libraries, everyone should use a dedicated namespace without conflicts, don't You agree?
Finally, window.name can save strings of hundred of thousand chars, I didn't find a limit for saved informations but as is for real RAM, if You turn off your PC (in this case browser window) it will be automatically resetted.
Why RAM function ?
These days I'm testing my last creation, packed.it, to find problems or to test decompression speed with big data size.
One thing I tough is that with packed code (using packed.it, packer or similar compressors), size is not the real problem as decompression CPU overload is.
I was try to find a way to cache or speed up unpack operation but every test I did failed (bad results).
That's why I created this simple function, to test clear code evaluation performances instead of runtime decompression, allowing users to unpack every kind of code 1 time each window instead of every time.
This means that during navigation in the same window, a new user will unpack code only first time but after first clear code creation procedure, You sohuld save them inside window.name and evaluate them in every other page viewed inside same browser window.
At the same time, if user will leave your page and then come back using back button it will have again code stored if external site didn't modify window.name or modify them without RAM function.
Finally, I could save an address, called for example jQuery :-) ... saving clear source and check them every time one page that use them is called:
eval(RAM("jQuery") || RAM("jQuery", function(p,a,c,k,e,d){/* ... */}));
Every link in the same window and every site viewed after this one should use same strategy to perform packed sources evaluations faster than ever because decompression will be performed only first time ... not a real solution but at least a simple way to optmize, a bit, navigation and decompression speed?
So, RAM function should be used to ... ?
- save each kind of informations rappresented as a string (JSON as every other kind of string)
- share common libraries between different pages / sites
- evaluate big strings if compressor believes in RAM function
I'll try to do some test with packed.it, probably as option.
The battle is between a little overload of 256 bytes against 1 to 5 seconds for really big packed sources ... uhm ... what do You think is better?
Do I forget something? Uhm, both keywords and sources could use SOH char too (\x01) without problems but each SOH will be duplicated inside window.name and replaced before You'll read them again to preserve string as is when You get them using RAM.
<script type="text/javascript" src="RAM.js"><!--// Function RAM //--></script>
<script type="text/javascript"><!--//
eval(
/* from second time You visit this page */
RAM("my personal key") ||
/* only first time You visit this page */
RAM("my personal key", "alert('Hello World')")
);
//--></script>
Update 2007/10/15
DarkCraft sayd that NoScript doesn't allow many chars inside window.name when You change domain, reload the page or do something similar.
I wonder why NoScript guys allows few chars in window.name (someone shoud use them to save user and passwords, for example) instead of clear one ... however, RAM should work without problems with NoScript enabled browsers too, just using a try catch statement.
// RAM example for NoScript browsers
try{
eval(RAM("my lib")||"this=0")
}catch(e){
eval(RAM("my lib", (function(p,a,c,k,e,d){return 'alert("hello my lib")'})()))
};
If You use this piece of code NoScript enabled browsers will just "decompile" each time saved informations, if these contains special chars too.
Please remember that RAM goal is to believe in itself, it's quite obvious that if some malicius site/page/code replace informations or uses malicius version of common libraries RAM function should become totally insecure.
The best practice I could suggest is to use a "private mutable key":
try{
eval(RAM("jQuery-1.2.1-" + location.hostname)||"this=0")
}catch(e){
eval(RAM("jQuery-1.2.1-" + location.hostname, (function(p,a,c,k,e,d){return 'alert("hello my lib")'})()))
};
That in a session based enviroment should be something like this code:
try{
eval(RAM("jQuery-1.2.1-<?php echo session_id();?>")||"this=0")
}catch(e){
eval(RAM("jQuery-1.2.1-<?php echo session_id();?>", (function(p,a,c,k,e,d){return 'alert("hello my lib")'})()))
};
To be sure library is shared only during a valid session.
A random cookie should be good enough too but paranoia is always with us :D
Finally, in packed.it I'll add a RAM option based on project name, different each time.
These practices disable cross site library sharing but I hope one day malicious site, developers, will be banned from the Web (just a "little utopia")
Worry about gzip ? No problem, packed.it preferes DEFLATE
I didn't test so much DEFLATE version of packed.it service and it seems that this one didn't work correctly with some browser ( ... ehr ... sorry guys ).
So I've just fixed deflate version and in my tests it works perfectly ... so perfectly that I choosed to use DEFLATE as first generator option, instead of gzip.
It seems that gzip causes too many problems with some version of Internet Explorer while I havenot just read anything something about DEFLATE problems too.
Well, it seems that DEFLATE performs a compression quite faster than gzip but packed.it goal is to forget runtime compression ... so this point doesn't matter while decompression speed should be a better plus, again, for DEFLATE.
At the same time DEFLATE seemsfree of has some problems with every compatible browsers ... and as You know, Internet Explorer is compatible with this compression too :-)
The result code should be more slim using gzip but We are talking about 2%, max 3%, that's not a problem with both big and medium / regular compressed sources.
The news is that now packed.it generators (PHP 4 or 5, C# Mono or .NET, Python PSP or WSGI) works correctly with deflate version (now compressed respecting RFC 1951) and choose them as first option.
You can obviously change priority by yourself, if You think gzip is better, however I'll mantain this choice if anyone will tell me that DEFLATE has same or more problems that gzip.
Have a nice optimization with packed.it ! (and please let me know if deflate will cause problems that gzip didn't cause)
So I've just fixed deflate version and in my tests it works perfectly ... so perfectly that I choosed to use DEFLATE as first generator option, instead of gzip.
It seems that gzip causes too many problems with some version of Internet Explorer while I have
gzip VS DEFLATE ?
Well, it seems that DEFLATE performs a compression quite faster than gzip but packed.it goal is to forget runtime compression ... so this point doesn't matter while decompression speed should be a better plus, again, for DEFLATE.
At the same time DEFLATE seems
The result code should be more slim using gzip but We are talking about 2%, max 3%, that's not a problem with both big and medium / regular compressed sources.
So what's new ?
The news is that now packed.it generators (PHP 4 or 5, C# Mono or .NET, Python PSP or WSGI) works correctly with deflate version (now compressed respecting RFC 1951) and choose them as first option.
You can obviously change priority by yourself, if You think gzip is better, however I'll mantain this choice if anyone will tell me that DEFLATE has same or more problems that gzip.
"gzip" is the gzip format, and "deflate" is the zlib format. They should probably have called the second one "zlib" instead to avoid confusion with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 correctly points to the zlib specification in RFC 1950 for the "deflate" transfer encoding, there have been reports of servers and browsers that incorrectly produce or expect raw deflate data per the deflate specficiation in RFC 1951, most notably Microsoft. So even though the "deflate" transfer encoding using the zlib format would be the more efficient approach (and in fact exactly what the zlib format was designed for), using the "gzip" transfer encoding is probably more reliable due to an unfortunate choice of name on the part of the HTTP 1.1 authors.
Have a nice optimization with packed.it ! (and please let me know if deflate will cause problems that gzip didn't cause)
Monday, October 08, 2007
packed.it screencast ... (maybe) Yesss!!!
However, I'll try to explain these two screencast.
First one - Ext JS Home Page - from 223Kb to 52Kb
This video shows a saved version of Ext JS Home Page.
This site uses a lot of external CSS, one imported and one in page but not every one is used by JavaScript disabled browsers.
Total CSS size is about 93,2Kb while 4 used JavaScript files size is about 130Kb.
With packed.it You can create a project using both CSS and JavaScript and the result will be a single file with total size of 52Kb, including both CSS and JavaScript.
I didn't add to project Google Analytics unrich.js file but this should be included without problems too saving other 15Kb.
As You can see (I hope), the result is even smaller on page, just three tags, using IE5 compatibility one, instead of 8 inside page ... these are few bytes less than original and layout is even more clean than ever.
CSS file dedicated only for JavaScript incompatible or disabled browsers is just 36Kb instead of 93 without optimization but as You know You could use packed.it to serve an optimized version of this file too (just change packed.it folder name to packed.css, for example, and change prefix inside automatic generator).
Prototype and Scriptaculous in less than a minute, from 230Kb to 38Kb
This second example just shows a JavaScript only project, Scriptaculous 1.7.1 beta 3 using prototype version 1.5.1
You just need to upload these sources and with a click You'll download full Scriptaculous enviroment, reducing size from 230Kb to 38Kb.
Using client compression too, every gzip or deflate incompatible browser will download about 90Kb instead of 230Kb, reducing bandwidth about 38% of original.
Sorry for missed audio and bad video quality, I'll try to do something better next time, ok? :-)
Saturday, October 06, 2007
new packed.it automatic content generator
packed.it service now creates archives with 3 types of automatic content generator: ASP.NET (C#), PHP (4 or 5) and Python (mod_python and psp or WSGI version).
These generators complete packed.it service and are usable with MyMin produced code too if You choose to manage your own projects by yourself.
Probably there will be future implementations (Java, Perl, Ruby), however today You can use packed.it to create optimized CSS and JavaScript for more than 80% of hosting solutions.
A special thanks to Cristian Carlesso for C# porting, He doesn't like my revision style so much ... but it works perfectly and it's more simple to mantain too (at least for me :D)
Have fun with packed.it :-)
These generators complete packed.it service and are usable with MyMin produced code too if You choose to manage your own projects by yourself.
Probably there will be future implementations (Java, Perl, Ruby), however today You can use packed.it to create optimized CSS and JavaScript for more than 80% of hosting solutions.
A special thanks to Cristian Carlesso for C# porting, He doesn't like my revision style so much ... but it works perfectly and it's more simple to mantain too (at least for me :D)
Have fun with packed.it :-)
Friday, October 05, 2007
MyMin project 1.0.1 available
I've just uploaded last version of MyMin project fixing only JSmin problems with regular expressions when it's not inside a closure, not after '{' or ';' allowing them to parse entire jQuery UI, for example, without problems.
This fix has been successfully tested on Python 2.5, PHP 5.2, C# 2 and JavaScript 1.3
You can find MyMin project description in this page while You can optimize CSS and JavaScript in a single file simply using my on-line packed.it service.
Have fun with optimizations and please feel free to post a comment if You find some bug using MyMin project, Thank You!
This fix has been successfully tested on Python 2.5, PHP 5.2, C# 2 and JavaScript 1.3
You can find MyMin project description in this page while You can optimize CSS and JavaScript in a single file simply using my on-line packed.it service.
Have fun with optimizations and please feel free to post a comment if You find some bug using MyMin project, Thank You!
Thursday, October 04, 2007
A "little bastard" BUG using JSmin parsers
Update
It seems I found a valid fix for "strange" regular expressions. I suppose MyMin will be available tomorrow while packed.it has been just updated with last client version.
Have fun with packed.it and please tell me if some source cannot be parsed.
--------------------------------------
While I was testing every kind of source and CSS with my last creation, packed.it, I found a bug on JSmin logic, partially recoded inside MyMin project as JavaScript minifier (MyMinCSS and MyMinCompressor seem to work perfectly).
This bug seems to be present on every version linked in JSmin page.
I found this bug parsing jQuery UI + every CSS with my new service but one JavaScript file has one single, simple problem:
Bye bye JSmin, regexp will be parsed as string and an error will be raised.
The problem is reproducible just with a string that contains only this (so a source that begins and end with these 3 chars):
that's a normal regexp ... at this point I can be happy to found first packed.it and MyMin project bug and the coolest thing is that is inside a part of project that's not really mine :D
To solve this problem, just use
return new RegExp
or just asign reg to a var before return them ... it seems to be the only one bug I found parsing every kind of source. Did anyone solve them?
I know it's not so simple, just because a char by char parser cannot simply know if slash is for a division, a comment or a regexp.
Do You have any sugest to solve this problem? It will be really appreciated! :-)
It seems I found a valid fix for "strange" regular expressions. I suppose MyMin will be available tomorrow while packed.it has been just updated with last client version.
Have fun with packed.it and please tell me if some source cannot be parsed.
--------------------------------------
While I was testing every kind of source and CSS with my last creation, packed.it, I found a bug on JSmin logic, partially recoded inside MyMin project as JavaScript minifier (MyMinCSS and MyMinCompressor seem to work perfectly).
This bug seems to be present on every version linked in JSmin page.
I found this bug parsing jQuery UI + every CSS with my new service but one JavaScript file has one single, simple problem:
function(){return /reg exp with this ' char/;}
Bye bye JSmin, regexp will be parsed as string and an error will be raised.
The problem is reproducible just with a string that contains only this (so a source that begins and end with these 3 chars):
/'/
that's a normal regexp ... at this point I can be happy to found first packed.it and MyMin project bug and the coolest thing is that is inside a part of project that's not really mine :D
To solve this problem, just use
return new RegExp
or just asign reg to a var before return them ... it seems to be the only one bug I found parsing every kind of source. Did anyone solve them?
I know it's not so simple, just because a char by char parser cannot simply know if slash is for a division, a comment or a regexp.
Do You have any sugest to solve this problem? It will be really appreciated! :-)
Wednesday, October 03, 2007
Are You Ready To Pack ?
I'm pleased to announce my last revolutionary project called packed.it !
No guys! packed.it goals is to reduce using best practices both CSS and JavaScript sources in a single file.
You can write directly on JS area or in CSS one or upload one or more file, choosing which one should be executed before others.
Based on MyMin project, a personal revisit of JSmin plus a dedicated compressor and a CSS minifier for C#, JavaScript, PHP or Python languages, packed.it creates a project archive, in zip format, that will contain everything You need to server your files gzipped, deflated or clear for browsers or robots that does not support gz pages.
The innovative packed.it idea is to process both JavaScript and CSS to create a single project file just compiled to be served using gzip, deflate or clear text.
In this case your server will not need to do anything, just serve correct file verifying its sha1 summary to choose it browser need to download them or use them from its cache.
Any other JavaScript compressor system includes possibility to pack CSS too and the reason is really simple.
How many times You write CSS dedicated only for your client library?
How many times You use words such div, body, li, #some-id, float, width inside CSS using same words inside JavaScript too?
Think about document.body, var li, getElementsByTagName("div"), getElementById("some-id"), setStyle("width") and so on.
My personal compressor, inspired by fantastic Dean Edwards packer idea, creates a single list of keywords used inside both CSS and JavScript sources.
Its simple but efficient algorithm counts how many times one word is present inside merged sources, CSS + JavaScript, and orders them to put most common words at the begin of keywords list, moving before words with length bigger than others.
In few words, every word will be replaced inside source reducing its size from 30% to 60% and if browser is compatible with gzip or deflate, final size should be even less than 20% of original one.
MyMin is originally based on JSmin C implementation but it was partially rewrote to be compatible with JavaScript conditional comments too (for example: /*@cc_on @*/ and //@cc_on) while MyMinCSS is a simply but powerful minifier dedicated only for CSS and totally wrote by myself.
MyMin Compressor works with every kind of source. This mean that You don't need to respect any rule when You write your JS or CSS code just because it doesn't modify original output and result will be exactly the same.
Its also based on fastest decompression algorithm I could thought and sources parsed with this Compressor will be available quickly even using old computers.
Its decompression procedure is compatible with every recent browser (IE 5.5 or greater, FireFox 1 or greater, Safari 2 or greater, KDE 3 or greater, Opera 7 or greater, NetScape 6 or greater, others too!) and should be compatible with old browsers too just adding a little function like this one before decompression (required only with IE5 or lower).
I hope there's no reason to don't use packed.it service:
Ok, I know, It's beta ... but it's just working so please tell me some question to create a useful F.A.Q. site section or tell me if something doesn't work as expected.
Regards, and have fun with Web 2.0 technologies !
P.S. I'm working to include a C# and Python variant to packed.it.php file (gzipped and deflated files just works with every language).
If You want to do it for me before I'll do that, please tell me and I'll put your credits in dedicated page, thank You :-)
Example using Ext (all both for JS and CSS)
ext-all.js + ex-all.css ... original size: 559.90 Kb
after packed.it conversion: one file, total size: 129.81 Kb :-)
Example using jQuery + jQuery UI + every CSS theme
From 260 Kb to 40Kb , about 15% :-)
Example using bytefx
From 18 Kb to 1.5 Kb , about 8% and Yessss, less than 2kb! :-)
Update
Please note that packed.it is beta and not totally debugged with different browsers.
However to be sure your JavaScript enabled browser is compatible with packed.it result projects just visit this page.
If You can read a text over a background #DDD body, Your browser is compatible with packed.it produced code.
Just another minifier packer alternative ???
No guys! packed.it goals is to reduce using best practices both CSS and JavaScript sources in a single file.
You can write directly on JS area or in CSS one or upload one or more file, choosing which one should be executed before others.
Based on MyMin project, a personal revisit of JSmin plus a dedicated compressor and a CSS minifier for C#, JavaScript, PHP or Python languages, packed.it creates a project archive, in zip format, that will contain everything You need to server your files gzipped, deflated or clear for browsers or robots that does not support gz pages.
Not only JavaScript !
The innovative packed.it idea is to process both JavaScript and CSS to create a single project file just compiled to be served using gzip, deflate or clear text.
In this case your server will not need to do anything, just serve correct file verifying its sha1 summary to choose it browser need to download them or use them from its cache.
Any other JavaScript compressor system includes possibility to pack CSS too and the reason is really simple.
How many times You write CSS dedicated only for your client library?
How many times You use words such div, body, li, #some-id, float, width inside CSS using same words inside JavaScript too?
Think about document.body, var li, getElementsByTagName("div"), getElementById("some-id"), setStyle("width") and so on.
My personal compressor, inspired by fantastic Dean Edwards packer idea, creates a single list of keywords used inside both CSS and JavScript sources.
Its simple but efficient algorithm counts how many times one word is present inside merged sources, CSS + JavaScript, and orders them to put most common words at the begin of keywords list, moving before words with length bigger than others.
In few words, every word will be replaced inside source reducing its size from 30% to 60% and if browser is compatible with gzip or deflate, final size should be even less than 20% of original one.
Do You want to know more about MyMin ?
MyMin is originally based on JSmin C implementation but it was partially rewrote to be compatible with JavaScript conditional comments too (for example: /*@cc_on @*/ and //@cc_on) while MyMinCSS is a simply but powerful minifier dedicated only for CSS and totally wrote by myself.
Do You want to know more about MyMin Compressor ?
MyMin Compressor works with every kind of source. This mean that You don't need to respect any rule when You write your JS or CSS code just because it doesn't modify original output and result will be exactly the same.
Its also based on fastest decompression algorithm I could thought and sources parsed with this Compressor will be available quickly even using old computers.
Its decompression procedure is compatible with every recent browser (IE 5.5 or greater, FireFox 1 or greater, Safari 2 or greater, KDE 3 or greater, Opera 7 or greater, NetScape 6 or greater, others too!) and should be compatible with old browsers too just adding a little function like this one before decompression (required only with IE5 or lower).
Do You need something else to choose packed.it ?
I hope there's no reason to don't use packed.it service:
- it's innovative
- it's free
- it's compatible with W3 validator and WatchFire too (WAI-AAA friendly)
Ok, I know, It's beta ... but it's just working so please tell me some question to create a useful F.A.Q. site section or tell me if something doesn't work as expected.
Regards, and have fun with Web 2.0 technologies !
P.S. I'm working to include a C# and Python variant to packed.it.php file (gzipped and deflated files just works with every language).
If You want to do it for me before I'll do that, please tell me and I'll put your credits in dedicated page, thank You :-)
Example using Ext (all both for JS and CSS)
ext-all.js + ex-all.css ... original size: 559.90 Kb
after packed.it conversion: one file, total size: 129.81 Kb :-)
Example using jQuery + jQuery UI + every CSS theme
From 260 Kb to 40Kb , about 15% :-)
Example using bytefx
From 18 Kb to 1.5 Kb , about 8% and Yessss, less than 2kb! :-)
Update
Please note that packed.it is beta and not totally debugged with different browsers.
However to be sure your JavaScript enabled browser is compatible with packed.it result projects just visit this page.
If You can read a text over a background #DDD body, Your browser is compatible with packed.it produced code.
Tuesday, October 02, 2007
Extended parseInt and toString with radix
With JavaScript You can parse a Number using its toString native function.
This one supports a radix argument, an integer between 1 and 37.
This method should be really useful but should be used to reduce integer size too.
The limit of this function is its max usable radix, 36, but is possible to extend this one? Of course :-)
My Base63 implementation allows both toString(radix) and parseInt functions to be compatible with maximum possible radix.
For possible I mean only these chars: [0-9] [a-z] [A-Z] plus last special char _
These chars are compatible with \w RegExp syntax and this means that You can use less than 60% of chars to rappresent an integer value.
At this point, with a small code overload, You could quickly trasform every \w match into original integer value.
Interesting? Just think, for example, about an array of integers and a JSON like client/server interaction.
I hope this will be useful, regards.
This one supports a radix argument, an integer between 1 and 37.
alert(
(10).toString(16) // a
);
alert(
(35).toString(36) // z
);
This method should be really useful but should be used to reduce integer size too.
The limit of this function is its max usable radix, 36, but is possible to extend this one? Of course :-)
alert([
(35).toString(63), // z
(61).toString(63), // Z
(62).toString(63) // _
]);
My Base63 implementation allows both toString(radix) and parseInt functions to be compatible with maximum possible radix.
For possible I mean only these chars: [0-9] [a-z] [A-Z] plus last special char _
These chars are compatible with \w RegExp syntax and this means that You can use less than 60% of chars to rappresent an integer value.
var myInt = 123456789012345,
myTinyInt = myInt.toString(63);
alert([
String(myInt).length, // 15
myTinyInt.length, // 8
myInt, // 123456789012345
myTinyInt // vlzFV_Fx
]);
At this point, with a small code overload, You could quickly trasform every \w match into original integer value.
alert(
"vlzFV_Fx.Az49_7".replace(
/\w+/g,
function(s){var b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_",l=s.length,p=0,r=0;while(l--)r+=Math.pow(63,l)*b.indexOf(s.charAt(p++));return r}
)
); // 123456789012345.36280109005
Interesting? Just think, for example, about an array of integers and a JSON like client/server interaction.
I hope this will be useful, regards.
Wednesday, September 26, 2007
What's wrong with new IEContentLoaded solution?
Update
This post talk about old implementation posted in Ajaxian before this one.
After some interesting comment, posted by Diego Perini, it seems that His last proposal is logically the best We can use today to solve this IE problem.
What I missed in my one is an onreadystatechange alternative to be sure function is called before onload one.
In my case this is not a problem but if You use third party code libraries it should be a big problem.
At this point Diego solution seems to be perfect for every case so just use them and thank You Diego and every other developer that helped Him to find this cool, portable, efficient solution :-)
---------------------------------------------
The solution proposed in this page to solve in another way DOMContentLoaded IE problem, ir really interesting.
I didn't test them so much but I suppose this is a valid alternative.
I didn't know doScroll behaviour too, so it's quite a surprise for me and I'm happy if this will work as expected simply because alternatives uses a script with a particular source string that one day should be a problem for every secure site: src="://"
Firsto point is that it's logic is quite bugged.
In fact, since this line:
should be useful to free memory, I can't understand why author choosed to put them inside try.
try, as You know, works as a sentinel ... when a single error occurs, catch is instantly called and every other piece of code inside try will never be executed.
If the goal was to free memory (but You'll read here that's even not important) it should be wrote after catch statement:
The other point is wrote inside first linked page:
Well, at this point, if this is true ... why do you create an element each timeout?
At this point You can see that solution is even simpler than original one.
document.firstChild, if You know how to write an (x)HTML page, is never a scrollable element.
This mean that You can use it directly, instead of create every time a new element.
The last point is that the best secure way to use a piece of code only with IE it to use conditional comment while last point is that a setTimeout with 0 as delay is never respected by browser because 0 means the minimum possible delay and not 0!
Is that's all? none
You can use conditional comment to create an window.onReady portable and cross-browser function:
That should be packed in few bytes:
Seems cool?
This post talk about old implementation posted in Ajaxian before this one.
After some interesting comment, posted by Diego Perini, it seems that His last proposal is logically the best We can use today to solve this IE problem.
What I missed in my one is an onreadystatechange alternative to be sure function is called before onload one.
In my case this is not a problem but if You use third party code libraries it should be a big problem.
At this point Diego solution seems to be perfect for every case so just use them and thank You Diego and every other developer that helped Him to find this cool, portable, efficient solution :-)
---------------------------------------------
The solution proposed in this page to solve in another way DOMContentLoaded IE problem, ir really interesting.
I didn't test them so much but I suppose this is a valid alternative.
I didn't know doScroll behaviour too, so it's quite a surprise for me and I'm happy if this will work as expected simply because alternatives uses a script with a particular source string that one day should be a problem for every secure site: src="://"
ok guys, but what's wrong with this solution?
Firsto point is that it's logic is quite bugged.
In fact, since this line:
tempNode = null;
should be useful to free memory, I can't understand why author choosed to put them inside try.
try, as You know, works as a sentinel ... when a single error occurs, catch is instantly called and every other piece of code inside try will never be executed.
If the goal was to free memory (but You'll read here that's even not important) it should be wrote after catch statement:
var tempNode = document.createElement('document:ready');
try {
tempNode.doScroll('left');
alert('window.onDocumentReady()');
}catch (err){
setTimeout(arguments.callee, 0);
};
tempNode = null;
The other point is wrote inside first linked page:
“… A few methods, such as doScroll, require the primary document to be completely loaded. If these methods are part of an initialization function, they should be handled when the ondocumentready event fires. …”
Well, at this point, if this is true ... why do you create an element each timeout?
(function (){
if(!document.uniqueID && document.expando) return;
try {
document.firstChild.doScroll('left');
alert('window.onDocumentReady()');
}catch (err){
setTimeout(arguments.callee, 0);
}
})();
At this point You can see that solution is even simpler than original one.
document.firstChild, if You know how to write an (x)HTML page, is never a scrollable element.
This mean that You can use it directly, instead of create every time a new element.
The last point is that the best secure way to use a piece of code only with IE it to use conditional comment while last point is that a setTimeout with 0 as delay is never respected by browser because 0 means the minimum possible delay and not 0!
/*@cc_on
(function(){
try{
document.firstChild.doScroll('left');
alert("window.onDocumentReady()")
}catch(e){
setTimeout(arguments.callee, 10)
}
})();
@*/
Is that's all? none
You can use conditional comment to create an window.onReady portable and cross-browser function:
onReady = (function(ie){
var d = document;
return ie ? function(c){
var n = d.firstChild,
f = function(){
try{
c(n.doScroll('left'))
}catch(e){
setTimeout(f, 10)
}
}; f()
} :
/webkit|safari|khtml/i.test(navigator.userAgent) ? function(c){
var f = function(){
/loaded|complete/.test(d.readyState) ? c() : setTimeout(f, 10)
}; f()
} :
function(c){
d.addEventListener("DOMContentLoaded", c, false);
}
})(/*@cc_on 1@*/);
onReady(function(){
alert("Hello DOM");
});
That should be packed in few bytes:
onReady=(function(ie,d){d=document;return ie?
function(c){var n=d.firstChild,f=function(){try{c(n.doScroll('left'))}catch(e){setTimeout(f,10)}};f()}:/webkit|safari|khtml/i.test(navigator.userAgent)?
function(c){var f=function(){/loaded|complete/.test(d.readyState)?c():setTimeout(f,10)};f()}:
function(c){d.addEventListener("DOMContentLoaded", c, false)}
})(/*@cc_on 1@*/);
onReady(function(){
alert("Hello DOM");
});
window.onReady(function(){
alert("Hello one more time");
});
Seems cool?
Tuesday, September 25, 2007
[TOD] The most compact Array.prototype.indexOf
The TOD is a JavaScript standard Array indexOf prototype implementation.
I know this is a basic trick but many times useful in IE too:
That's all ... in the most compact way ... but what about most compact lastIndexOf prototype?
Update
Thanks to Laurent, the most compact lastIndexOf should be this one:
Probably one slice instead of two reverse should be a better choice? I'll test them :-)
Performances? Good enough ... Compatibility? IE4 or greater!
I know this is a basic trick but many times useful in IE too:
Array.prototype.indexOf=function(o,i){for(var j=this.length,i=i<0?i+j<0?0:i+j:i||0;i<j&&this[i]!==o;i++);return j<=i?-1:i}
That's all ... in the most compact way ... but what about most compact lastIndexOf prototype?
Array.prototype.lastIndexOf=function(o,i){var s=this,r=s.reverse().indexOf(o,i);s.reverse();return r}
Update
Thanks to Laurent, the most compact lastIndexOf should be this one:
Array.prototype.lastIndexOf=function(o,i){return this.slice(0).reverse().indexOf(o,i)}
Probably one slice instead of two reverse should be a better choice? I'll test them :-)
Performances? Good enough ... Compatibility? IE4 or greater!
Monday, September 24, 2007
[ITA] Colpo basso a Beppe Grillo o un banale autogoal ?
Oggi, 24 settembre 2007, il telegiornale Studio Aperto ha trasmesso un servizio inerente un vecchio spettacolo del Beppe nazionale dove lo stesso criticava Internet e distruggeva un computer, descrivendo con rabbia l'inutilità della rete ma soprattutto l'incapacità di sfruttare la tecnologia a favore del lavoro e del progresso.
Sebbene questo servizio possa sembrare, secondo il mio opinabile e probabilmente azzardato giudizio, volutamente screditante nei confronti delle "recenti" vicessitudini del noto comico, è possibile azzardare l'ipotesi che lo stesso sia nato indirettamente dal blog di un altro comico che stimo e seguo da molti anni ma che ha incentrato parte di una personale riflessione sul marketing.
E' nel blog di Daniele Luttazzi infatti che si può leggere, ormai da giorni, il suo lucido giudizio riguardo il V-day e, prima ancora, sulle strategie commerciali della satira proposta da Grillo.
Nel settore dell'IT, oggi l'italia si colloca al 38esimo posto nella classifica mondiale, dietro nazioni come la Tailandia, la Tunisia, il Cile, il Lussemburgo, Malta, Israele, la Slovenia e tutti gli altri.
Questo non solo significa che nel nostro paese le ciambelle di settore riescono quasi sempre senza il buco, ma che l'ignoranza prevale sulle reali possibilità offerte dalle tecnologie che ruotano attorno al World Wide Web.
Al tempo del vecchio spettacolo di Beppe Grillo non esisteva ancora il Web 2.0, concetto ormai ben chiaro a tutte le persone minimamente informate sul mondo del Web ma che per ovvi motivi è totalmente estraneo alla maggior parte delle persone ed in questo caso, dei media.
Nel lontano 2001 in Italia, i concetti come condivisione dei contenuti, partecipazione attiva da parte dei navigatori, spazi aperti ed informazione per e/o verso tutti, non esistevano.
Internet era semplicemente un ammasso informe composto per lo più da siti strutturati tramite le peggiori pratiche di progettazione e realizzazione, pratiche in buona parte contestate anche nei più recenti lavori di realizzazione pubblica, pagati milioni di euro da noi umili ed impotenti contribuenti.
Fin dalla nascita di progetti come Wikipedia, un'icona del nuovo Web 2.0, Beppe Grillo non ha fatto altro che enfatizzare le notevoli caratteristiche del servizio appena citato nonché complimentarsi con il nuovo modo di intendere la rete, nato dagli stessi addetti ai lavori e popolato quotidianamente da milioni di utenti.
Quello che il comico non poteva certo fare nel 2001 era lodare l'insieme di apparati e società che non curanti delle reali potenzialità della rete pensavano soprattutto ai guadagni, ad eccezione di alcune stelle che hanno scelto di permettere a chiunque di avere accesso alla stessa rete senza costi di attivazione ( un grazie doveroso e sincero va a Tiscali ! ).
A quanto pare però l'ignoranza riguardo il Web e soprattutto della sua ultima evoluzione, la versione 2.0, in Italia è ancora all'ordine del giorno e se Grillo poteva al tempo criticare lo strapotere Microsoft (ricordo che con Mac o Linux il problema virus, ad esempio, è dimezzato se non nella maggior parte dei casi inesistente) e condividere l'incapacità collettiva di sfruttare attivamente queste nuove tecnologie (a scuola si studia ancora il Pascal, a volte "col Turbo", ma invece di insegnare il Web, al massimo si spiega il funzionamento di qualche software proprietario e di inevitabile mancata conformità con gli standard internazionali definiti dal consorzio W3), oggi utilizza tramiti odierni per comunicare con cittadini, fans e per finire, ministri interessati al suo blog.
Per concludere, vorrei solo consigliare a tutti quelli che criticano il vecchio (e l'attuale) operato di Grillo di ricordare quante volte questo "comico" si sia dimostrato anni avanti o più aggiornato di tutti noi: probabilmente grazie al fatto che lui le notizie non le aspettava ne cercava tra i media di questo paese, gli stessi che ci collocano al 40esimo posto della classifica internazionale sulla libertà di stampa.
Sono un fan di Grillo? Diciamo che lo ammiro ma che son prima un fan della corretta informazione.
Grazie per l'attenzione e soprattutto grazie Italia per continuare a non aggiornarti sulle materie, qualunque siano, reality esclusi.
Cordialmente,
un cittadino qualunque.
Sebbene questo servizio possa sembrare, secondo il mio opinabile e probabilmente azzardato giudizio, volutamente screditante nei confronti delle "recenti" vicessitudini del noto comico, è possibile azzardare l'ipotesi che lo stesso sia nato indirettamente dal blog di un altro comico che stimo e seguo da molti anni ma che ha incentrato parte di una personale riflessione sul marketing.
E' nel blog di Daniele Luttazzi infatti che si può leggere, ormai da giorni, il suo lucido giudizio riguardo il V-day e, prima ancora, sulle strategie commerciali della satira proposta da Grillo.
Ma di che cosa parlava veramente Grillo nello spettacolo del 2001?
Nel settore dell'IT, oggi l'italia si colloca al 38esimo posto nella classifica mondiale, dietro nazioni come la Tailandia, la Tunisia, il Cile, il Lussemburgo, Malta, Israele, la Slovenia e tutti gli altri.
Questo non solo significa che nel nostro paese le ciambelle di settore riescono quasi sempre senza il buco, ma che l'ignoranza prevale sulle reali possibilità offerte dalle tecnologie che ruotano attorno al World Wide Web.
Al tempo del vecchio spettacolo di Beppe Grillo non esisteva ancora il Web 2.0, concetto ormai ben chiaro a tutte le persone minimamente informate sul mondo del Web ma che per ovvi motivi è totalmente estraneo alla maggior parte delle persone ed in questo caso, dei media.
Nel lontano 2001 in Italia, i concetti come condivisione dei contenuti, partecipazione attiva da parte dei navigatori, spazi aperti ed informazione per e/o verso tutti, non esistevano.
Internet era semplicemente un ammasso informe composto per lo più da siti strutturati tramite le peggiori pratiche di progettazione e realizzazione, pratiche in buona parte contestate anche nei più recenti lavori di realizzazione pubblica, pagati milioni di euro da noi umili ed impotenti contribuenti.
Fin dalla nascita di progetti come Wikipedia, un'icona del nuovo Web 2.0, Beppe Grillo non ha fatto altro che enfatizzare le notevoli caratteristiche del servizio appena citato nonché complimentarsi con il nuovo modo di intendere la rete, nato dagli stessi addetti ai lavori e popolato quotidianamente da milioni di utenti.
Quello che il comico non poteva certo fare nel 2001 era lodare l'insieme di apparati e società che non curanti delle reali potenzialità della rete pensavano soprattutto ai guadagni, ad eccezione di alcune stelle che hanno scelto di permettere a chiunque di avere accesso alla stessa rete senza costi di attivazione ( un grazie doveroso e sincero va a Tiscali ! ).
A quanto pare però l'ignoranza riguardo il Web e soprattutto della sua ultima evoluzione, la versione 2.0, in Italia è ancora all'ordine del giorno e se Grillo poteva al tempo criticare lo strapotere Microsoft (ricordo che con Mac o Linux il problema virus, ad esempio, è dimezzato se non nella maggior parte dei casi inesistente) e condividere l'incapacità collettiva di sfruttare attivamente queste nuove tecnologie (a scuola si studia ancora il Pascal, a volte "col Turbo", ma invece di insegnare il Web, al massimo si spiega il funzionamento di qualche software proprietario e di inevitabile mancata conformità con gli standard internazionali definiti dal consorzio W3), oggi utilizza tramiti odierni per comunicare con cittadini, fans e per finire, ministri interessati al suo blog.
Per concludere, vorrei solo consigliare a tutti quelli che criticano il vecchio (e l'attuale) operato di Grillo di ricordare quante volte questo "comico" si sia dimostrato anni avanti o più aggiornato di tutti noi: probabilmente grazie al fatto che lui le notizie non le aspettava ne cercava tra i media di questo paese, gli stessi che ci collocano al 40esimo posto della classifica internazionale sulla libertà di stampa.
Sono un fan di Grillo? Diciamo che lo ammiro ma che son prima un fan della corretta informazione.
Grazie per l'attenzione e soprattutto grazie Italia per continuare a non aggiornarti sulle materie, qualunque siano, reality esclusi.
Cordialmente,
un cittadino qualunque.
Saturday, September 22, 2007
[COW] document.create cross-browser implementation
This COW goal is to use a simple, cross-browser and fast way to create a DOM element.
This function works in a different way if used inside browser Internet Explorer.
This allows developers to create some HTML element instead of single one using its tag name.
Some library uses personal function to add an element, using its tag name, or to add a piece of HTML code, using innerHTML property instead of DOM element creation and manipulation.
This function works in the same way inside every browser and its goal is to create a text node to add inside another element.
A Text Element is the correct way to write something inside a generic HTMLElement and doesn't work as innerHTML because it automatically escape each char.
This function choose what kind of element You need to create automatically.
Its behaviour is based on sent argument string:
document.create just analyze first argument string char.
If this is "<", You're creating an element and its content using innerHTML without modify current DOM while if first char is this one "#" You're creating a TextNode.
In other cases You're creating a generic element using regular document.createElement function.
In this last case You can use more than one argument to append nested elements.
Do You need an example ?
You can view this example at work here while updated function code is in this one.
Do You like them?
P.S. Robert, I think this function should be a cool DOMAssistant add on, do You agree?
About document.createElement
This function works in a different way if used inside browser Internet Explorer.
This allows developers to create some HTML element instead of single one using its tag name.
// Only with IE
document.body.appendChild(
document.createElement("<iframe />")
);
Some library uses personal function to add an element, using its tag name, or to add a piece of HTML code, using innerHTML property instead of DOM element creation and manipulation.
About document.createTextNode
This function works in the same way inside every browser and its goal is to create a text node to add inside another element.
document.body.appendChild(
document.createTextNode("Hello Text Element")
);
A Text Element is the correct way to write something inside a generic HTMLElement and doesn't work as innerHTML because it automatically escape each char.
About COW, document.create function
This function choose what kind of element You need to create automatically.
Its behaviour is based on sent argument string:
- document.create("div"), creates an HTMLElement (in this case a div) using DOM and document.createElement function
- document.create("<span>Hello</span>"), creates a span element with "Hello" text using innerHTML to create entire element
- document.create("#This is a text element"), creates an element using document.createTextNode and return them
document.create just analyze first argument string char.
If this is "<", You're creating an element and its content using innerHTML without modify current DOM while if first char is this one "#" You're creating a TextNode.
In other cases You're creating a generic element using regular document.createElement function.
In this last case You can use more than one argument to append nested elements.
Do You need an example ?
onload = function(){
for(var key in {
"<h2>This is a document.create example</h2>":1,
"hr":2,
"#And this is just a comment":3
})
document.body.appendChild(document.create(key));
document.body.appendChild(
document.create("div", "#And this is just a list", "<ul><li>item 1</li><li>item 2</li></ul>")
);
};
You can view this example at work here while updated function code is in this one.
Do You like them?
P.S. Robert, I think this function should be a cool DOMAssistant add on, do You agree?
Tuesday, September 18, 2007
noscript problems? Just fixed ;-)
While I was writing precedent post I thought about a really simple solution, showed in this post using PHP but compatible with every server-side program language.
Head page doesn't accept a noscript tag but it accpets without problems one or more script tags.
If I'm not wrong, page download and parse is syncronous and that's mean that if I write a piece of code inside a script, next one will have this code ready or just executed.
Since downloading is syncronous, I can use this behaviour to save in a session this information and to show different layout using next tag.
The order is absolutely important to use this solution, just because first file need to do something like that:
while second file, page CSS, just need to show correct CSS, based on session JavaScript variable that will be setted only on JS enabled browsers:
At this point We should put a gz_handler inside CSS file
optimizing download speed for gz compatible browsers.
At the end, with a bit of immagination, We could directly use first script tag to append dinamically one or more dedicated stylesheet, returning just an empty string on page link request if JavaScript session var is set to true.
I hope this is a solution to solve W3 rules for a problem that "didn't exists" when (X)HTML was drafted for the first time ;-)
demo page
self brainstorming
Head page doesn't accept a noscript tag but it accpets without problems one or more script tags.
If I'm not wrong, page download and parse is syncronous and that's mean that if I write a piece of code inside a script, next one will have this code ready or just executed.
Since downloading is syncronous, I can use this behaviour to save in a session this information and to show different layout using next tag.
<head>
<script type="text/javascript" src="cssFilter.php"><!--// CSS Filter //--></script>
<link rel="stylesheet" media="all" href="myPage.php" />
</head>
The order is absolutely important to use this solution, just because first file need to do something like that:
<?php
session_start();
$_SESSION['JavaScript'] = true;
header('Content-Type: text/javascript');
exit('this;');
?>
while second file, page CSS, just need to show correct CSS, based on session JavaScript variable that will be setted only on JS enabled browsers:
<?php
session_start();
$output = file_get_contents(
isset($_SESSION['JavaScript']) && $_SESSION['JavaScript'] === true ?
'scriptEnabled.css':
'scriptDisabled.css'
);
header('Content-Type: text/css');
header('Content-Length: '.strlen($output));
$_SESSION['JavaScript'] = false;
exit($output);
?>
At this point We should put a gz_handler inside CSS file
ob_start('ob_gzhandler');
optimizing download speed for gz compatible browsers.
At the end, with a bit of immagination, We could directly use first script tag to append dinamically one or more dedicated stylesheet, returning just an empty string on page link request if JavaScript session var is set to true.
I hope this is a solution to solve W3 rules for a problem that "didn't exists" when (X)HTML was drafted for the first time ;-)
demo page
noscript tag behaviour and head conflicts
In this Web 2.something era there's a big problem with noscript tag and I wonder what does W3 think about them.
This tag is really useful to increase page informations or accessibility, allowing developers to show an alternative content if user has not JavaScript enabled or his browser doesn't support other kind of tags.
This is a basic example of noscript usage and expected behaviour is that every JS compatible browser will try to execute code insde script tag while every JS disabled or not compatible browser will show an alternative information.
When a browser is JS compatible ignores totally noscript tag.
It doesn't render its informations, just "jump" after the end of this tag.
At the same time, if a browser is not compatible with tag used before noscript, it will ignore totally every kind of its informations such src, code execution plugin initializzation or other things.
In few words, noscript is a WAI-AAA but at the same time has too many limitations that are totally against the real accessibility.
In fact, (X)HTML doesn't accept a noscript tag inside head one and at the same time doesn't accept external resources inside noscript tag.
This simply means that You can't include a dedicated stylesheet or link tag inside noscript one so every navigator need to download entire page, included noscript, even if it'll never use its informations.
At the same time is not possible to run a UI dedicated style using JavaScript inside head tag, the right place to put style, link and / or script tags.
All these things mean that a page can't separe, respecting W3 standards, content for JS enabled browsers and other, simply because every navigator has to download at least two kinds of CSS, even if the biggest one, dedicated for example to render correctly YUI!, Dojo, Ext, Interface, Moo or every other client libraries that today are strongly used inside a big range of sites.
I'm obviously talking about external resources and DOM with a goal to make page smaller than ever downloading only useful resources: JS + dedicated CSS for enabled browsers, dedicated CSS for browsers without JS support.
I read about new XHTML 2.0 handler tag, but the question, now, is:
will W3 ever remove from its validator program the error about noscript inside head tag?
Can anyone explain me why noscript can't be after a script inside head and why noscript can't contain in every part of page an external resource?
Please, tell me if there's a way to solve this problem or if ignore them is the only one solution just because every browser support noscript tag inside head one and load its external resources correctly, thank You.
noscript and its standard implementation
This tag is really useful to increase page informations or accessibility, allowing developers to show an alternative content if user has not JavaScript enabled or his browser doesn't support other kind of tags.
<script type="text/jvascript">doStuff()</script>
<noscript>Your browser can't do my Stuff</noscript>
This is a basic example of noscript usage and expected behaviour is that every JS compatible browser will try to execute code insde script tag while every JS disabled or not compatible browser will show an alternative information.
So, what's wrong with noscript ?
When a browser is JS compatible ignores totally noscript tag.
It doesn't render its informations, just "jump" after the end of this tag.
At the same time, if a browser is not compatible with tag used before noscript, it will ignore totally every kind of its informations such src, code execution plugin initializzation or other things.
In few words, noscript is a WAI-AAA but at the same time has too many limitations that are totally against the real accessibility.
In fact, (X)HTML doesn't accept a noscript tag inside head one and at the same time doesn't accept external resources inside noscript tag.
This simply means that You can't include a dedicated stylesheet or link tag inside noscript one so every navigator need to download entire page, included noscript, even if it'll never use its informations.
At the same time is not possible to run a UI dedicated style using JavaScript inside head tag, the right place to put style, link and / or script tags.
All these things mean that a page can't separe, respecting W3 standards, content for JS enabled browsers and other, simply because every navigator has to download at least two kinds of CSS, even if the biggest one, dedicated for example to render correctly YUI!, Dojo, Ext, Interface, Moo or every other client libraries that today are strongly used inside a big range of sites.
I'm obviously talking about external resources and DOM with a goal to make page smaller than ever downloading only useful resources: JS + dedicated CSS for enabled browsers, dedicated CSS for browsers without JS support.
I read about new XHTML 2.0 handler tag, but the question, now, is:
will W3 ever remove from its validator program the error about noscript inside head tag?
Can anyone explain me why noscript can't be after a script inside head and why noscript can't contain in every part of page an external resource?
Please, tell me if there's a way to solve this problem or if ignore them is the only one solution just because every browser support noscript tag inside head one and load its external resources correctly, thank You.
<head>
<script type="text/javascript"><!--//
// this file should be download only by JS enabled browsers
var link = document.createElement("link");
link.rel = "stylesheet";
link.media = "screen";
link.href = "myBigLibrary.css";
document.getElementsByTagName("head")[0].appendChild(link);
//--></script>
<noscript>
<link
title="more speed for everyone"
rel="stylesheet"
media="all"
href="myTinyPage.css"
/>
</noscript>
</head>
Friday, September 14, 2007
JavaScript namespace + using proposal
I've just uploaded inside devpro my last JavaScript proposal: a little, simple and fast namespace function, with a single static public method called using.
A namespace is "a place where everything is unobtrusive", where in this case unobtrusive means that You can't (shouldn't) modify other libraries.
Many program languages (C# / Python / Java / maybe one day PHP and others) use namespace since their first implementation (packages, from - import, using).
In JavaScript world, big (but not too) libraries use namespace too (Dojo, YUI!) while many other libraries use a sort of internal namespace (jQuery, MooTools, Prototype) to separe FX, utils and other piece of code.
It's really tiny as simple to use and You can find them in this page.
Here there's a first, basic, simple example:
Simple? You can save every kind of variable inside your namespace and You can create any kind of name, splitting them with a "." char:
There's something else interesting, a static global using function!
Function namespace.using inject your namespace scope inside a callback, sending them one or more variables:
Seems interesting ? This is last example:
So, what's new ?
Well, this way to create a dedicated namespace is the same of my old JSTONE constructor: a tested way to manage namespaces and, imho, extremely useful for every JS developer and / or library.
What's a namespace ?
A namespace is "a place where everything is unobtrusive", where in this case unobtrusive means that You can't (shouldn't) modify other libraries.
Who use a namespace ?
Many program languages (C# / Python / Java / maybe one day PHP and others) use namespace since their first implementation (packages, from - import, using).
In JavaScript world, big (but not too) libraries use namespace too (Dojo, YUI!) while many other libraries use a sort of internal namespace (jQuery, MooTools, Prototype) to separe FX, utils and other piece of code.
What about my proposal ?
It's really tiny as simple to use and You can find them in this page.
Here there's a first, basic, simple example:
// create / modify or overwrite a namespace called webreflection
// setting an object with a type key and its value
namespace("webreflection", {type:"blog"});
// create / modify or overwrite another namespace
// adding a string as value
namespace("webreflection.author", "Andrea Giammarchi");
// get created namespace
var MyBlog = namespace("webreflection");
// show saved variables
alert([MyBlog.author, MyBlog.type].join("'s "));
// Andrea Giammarchi's blog
// show just author value
alert(namespace("webreflection.author"));
// in this case Andrea Giammarchi string
Simple? You can save every kind of variable inside your namespace and You can create any kind of name, splitting them with a "." char:
var FX = namespace("this.is.my.Library.FX", function(){
// do stuff
});
var myFX = new FX;
// the same of
var myFX = new namespace("this.is.my.Library.FX");
There's something else interesting, a static global using function!
What about using ?
Function namespace.using inject your namespace scope inside a callback, sending them one or more variables:
var tellMeSomething = namespace.using("webreflection", function(){
return [
"This kind of site is a",
this.type,
"and its publisher is",
this.author
].join(" ")
});
alert(tellMeSomething);
// This kind of site is a blog and its publisher is Andrea Giammarchi
Seems interesting ? This is last example:
namespace("webreflection.utils.String", {
trim:function(str){
return str.replace(/^\s+|\s+$/g, "")
},
camel:function(str){
return str.toLowerCase().replace(/\-([a-z])/g, function(m,c){return "-"+c.toUpperCase()})
},
repeat:function(str, times){
for(var i = 0, a = new Array(times); i < times; i++)
a[i] = str;
return a.join();
}
});
alert([
namespace("webreflection.utils.String").camel("tEsT-mE"),
namespace.using("webreflection.utils.String", function(){
return this.repeat("test", 3);
}),
namespace.using("webreflection", function(){
return "[" + this.utils.String.trim(" hello ") + "]"
}),
namespace("webreflection.utils").String.repeat
].join("\n"));
So, what's new ?
Well, this way to create a dedicated namespace is the same of my old JSTONE constructor: a tested way to manage namespaces and, imho, extremely useful for every JS developer and / or library.
Thursday, September 13, 2007
JPU - JavaScript CPU Monitor
This is a little experiment, based on single threading JavaScript behaviour and for this reason not "perfect".
As You can see on top right of this blog, JPU just tell You if your operations inside this page have a cost for your CPU.
For example, try to click one mini-banner on the right side (OCS - DCS) and look at JPU monitor during fade in/out.
The better browser I've tested is Opera but FireFox and Internet Explorer seems to work nicely too :-)
If You want to add a JPU in your site, just use a script tag like this one:
If You just want to test JPU inside another site, using FireFox or uriscript compatible browser, just use this lik.
Please remember that JPU is just for fun, about 0.5 Kb and quite totally unobtrusive.
Have fun with JPU :D
Istant Update
Here You can view a demo page comparing them with your Operating System CPU monitor (not so different in my case :D)
As You can see on top right of this blog, JPU just tell You if your operations inside this page have a cost for your CPU.
For example, try to click one mini-banner on the right side (OCS - DCS) and look at JPU monitor during fade in/out.
The better browser I've tested is Opera but FireFox and Internet Explorer seems to work nicely too :-)
If You want to add a JPU in your site, just use a script tag like this one:
<script
type="text/javascript"
src="http://www.3site.eu/JPU/JPU.js"
><!--//
JPU - by WebReflection
//--></script>
If You just want to test JPU inside another site, using FireFox or uriscript compatible browser, just use this lik.
Please remember that JPU is just for fun, about 0.5 Kb and quite totally unobtrusive.
Have fun with JPU :D
Istant Update
Here You can view a demo page comparing them with your Operating System CPU monitor (not so different in my case :D)
Thursday, August 30, 2007
global scope evaluation and DOM investigation
After precedent post I prefer to write another one about global scope evaluation and kentaromiura question:
Before I post my test code that shows how a medium or big page, about 5000 divs or paragraphs, is not affected by my proposal (about 0.09 delay over 1000 evalScript interactions) I would talk about global scope evaluation.
What does it mean: global scope evaluation?
Every time we use a function to evaluate a string, temporary scope is injected into code evaluation.
While some library (in this case I talk about jQuery) uses stranges (imho) partial (wrong) solutions to remove nested scope from evaluation, I can tell You that everything You need to use a clear scope is to call another function, where this reference is just super object (window if executed inside a browser).
This is an elementary example:
If You use a setInterval or setTimeout function with delay === 0, You're not solving the problem because these functions are always asyncronous.
This mean that this example code will show 1 in every "delay 0" compatible browser (Opera doesn't accept 0 as delay):
That's why when You use timing or Ajax, callback will be executed at the end of every line of code, only modal events such alert, prompt or others will cause delayed function execution, if time was short enough.
To understand better delayed functions, please read this post that shows a really basic deadlock ... just why JavaScript, if executed inside a browser, is not multi threaded.
John Resig (jQuery author) seems to know it, He implemented these functions (setTimeout and setInterval) inside Rhino (sorry John, I don't find the link) ... but remember that His implementation is based on Java threading and not on JavaScript.
For some reason there's a function inside jQery that I can't understand, called globalEval:
Too many concept errors for a single function ... I hope jQuery team will remove or change them as soon as they can.
Returning on simple "free scope" evaluation, there's always a limit: arguments object or sent variables should be changed by code evaluation.
Since global scope evaluation should be done exactly using global scope, as script tags do, my evalScript proposal does it quite perfectly and above example will not change, using my function, recieved data or arguments variables.
For people who think that code evaluation is an obsession I can just say that my evalScript proposal was wrote to load entire scripts, as dynamic appendChild(scriptWithExtSource) does, or to evaluate a bit faster big JSON server responses.
In these cases You can't say eval is evil because there aren't different way to do that if You care about speed and dynamic script import.
This is my last sentences about code evaluation, it's always a bad practice but in rare cases, it's a must.
To complete this post, here You can see my benchmark code to test evalScript speed after created a big page (big DOM):
does your evalScript proposal cause DOM side effects?
Before I post my test code that shows how a medium or big page, about 5000 divs or paragraphs, is not affected by my proposal (about 0.09 delay over 1000 evalScript interactions) I would talk about global scope evaluation.
What does it mean: global scope evaluation?
Every time we use a function to evaluate a string, temporary scope is injected into code evaluation.
While some library (in this case I talk about jQuery) uses stranges (imho) partial (wrong) solutions to remove nested scope from evaluation, I can tell You that everything You need to use a clear scope is to call another function, where this reference is just super object (window if executed inside a browser).
This is an elementary example:
function clearScopeEvaluation(data){
return eval(data);
};
// just call them everywhere ...
(function(a){
clearScopeEvaluation("a = 2");
alert([a, window.a]);
})(1);
// shows 1,2
If You use a setInterval or setTimeout function with delay === 0, You're not solving the problem because these functions are always asyncronous.
This mean that this example code will show 1 in every "delay 0" compatible browser (Opera doesn't accept 0 as delay):
var num = 1;
setTimeout(function(){num = 2}, 0);
alert(num);
// ... or if You prefere ...
var num = 1;
setTimeout("num = 2", 0);
alert(num);
That's why when You use timing or Ajax, callback will be executed at the end of every line of code, only modal events such alert, prompt or others will cause delayed function execution, if time was short enough.
// just click OK before one second or wait more to view 2 value
var num = 1;
setTimeout(function(){num = 2}, 1000);
alert("");
alert(num);
To understand better delayed functions, please read this post that shows a really basic deadlock ... just why JavaScript, if executed inside a browser, is not multi threaded.
John Resig (jQuery author) seems to know it, He implemented these functions (setTimeout and setInterval) inside Rhino (sorry John, I don't find the link) ... but remember that His implementation is based on Java threading and not on JavaScript.
For some reason there's a function inside jQery that I can't understand, called globalEval:
// Evalulates a script in a global context
// Evaluates Async. in Safari 2 :-(
globalEval: function( data ) {
data = jQuery.trim( data );
if ( data ) {
if ( window.execScript )
window.execScript( data );
else if ( jQuery.browser.safari )
// safari doesn't provide a synchronous global eval
window.setTimeout( data, 0 );
else
eval.call( window, data );
}
}
Too many concept errors for a single function ... I hope jQuery team will remove or change them as soon as they can.
Returning on simple "free scope" evaluation, there's always a limit: arguments object or sent variables should be changed by code evaluation.
function gScope(data){
eval("data=arguments=null");
};
Since global scope evaluation should be done exactly using global scope, as script tags do, my evalScript proposal does it quite perfectly and above example will not change, using my function, recieved data or arguments variables.
For people who think that code evaluation is an obsession I can just say that my evalScript proposal was wrote to load entire scripts, as dynamic appendChild(scriptWithExtSource) does, or to evaluate a bit faster big JSON server responses.
In these cases You can't say eval is evil because there aren't different way to do that if You care about speed and dynamic script import.
This is my last sentences about code evaluation, it's always a bad practice but in rare cases, it's a must.
To complete this post, here You can see my benchmark code to test evalScript speed after created a big page (big DOM):
(evalScript = function(e){
var h = evalScript.node,
s = document.createElement("script");
s.type = "text/javascript";
s.text = e;
h.appendChild(s);
h.removeChild(s);
}).node = document.getElementsByTagName("head")[0] || document.getElementsByTagName("*")[0];
onload = function(){
function create(element, content){
document.body.appendChild(
document.createElement(element)
.appendChild(
document.createTextNode(content)
).parentNode
);
};
function randomString(){
var i = Math.ceil(Math.random() * 200),
a = new Array(i);
while(i--)
a[i] = String.fromCharCode(Math.ceil(Math.random() * 40) + 30);
return a.join("");
};
for(var i = 0; i < 5000; i++)
create(i % 2 ? "div" : "p", randomString());
for(var i = 0, j = 0; i < 1000; i++){
startTime = new Date;
evalScript('endTime = new Date - startTime');
j += endTime;
};
alert(j / 1000);
};
Wednesday, August 29, 2007
A better JavaScript code evaluation?
Yesterday Ajaxian published a benchmark using Flex and comparing them with Ajax JSON, Dojo and other way to transfer data between client and server.
Interesting point is not that kind of bench (imho) but one comment wrote by Albert Kühner:
It seems to be a simple and basic question but He was right because the answer is: yes, a script tag is generally interpreted faster than code evaluation using eval, execScript or Function constructor.
I suppose the reason is quite obvious: eval, as execScript or Function, brings temporary local scope inside evaluated code and this cause a little overhead while a script tag is always interpreted only inside global scope (window or super object).
This should be a limit for evaluation common usage (often wrong) but this was the primitive Ajax implementation to interact with server.
Example:
Now try to image server side code, in this case a really simple PHP script:
Well done, this is Ajax without Ajax ... a sort of Asyncronous JavaScript and JavaScript (could we call them Ajaj ? :D )
At this point You should agree that there's no way to inject temporary scope inside response and when You load manually or dynamically a script tag the behaviour is the same.
Is it ok? Is it clear?
Well, next step is to use script tag instead of code evaluation to perform quickly (I'm talking about milliseconds) expecially when We use Ajax to recieve a JSON string.
With JSON We usually don't need temporary scope so why We should "wait" more time to evaluate that string?
This is an elementary proposal, the function evalScript:
How to use them? It's really simple:
The only thing You need to remember is that scope is not injected inside evaluation:
So how to use evalScript ?
You can use them after one or more Ajax interaction if You're loading a script, instead of XML or (x)HTML or text, to run for example dinamically external resources.
You can use evalScript with JSON interactions too, but You should use a little trick if You don't want to be obtrusive.
The simplest solution is, in fact, this one:
... but in this web world full of different libraries this is not a good idea, so why don't use evalScript itself to store temporary results?
Since JavaScript is, at least inside browsers, single thread, there's no risk about concurrency and in this way You'll not overwrite anything different from single evalScript function.
If You don't believe this function is usually faster than eval, just try to generate a big and complex JSON notation, using every compatible kind of compatible value, so try 10 or more times to eval them or to use my evalScript proposal.
Of course, this is just for performances maniacs :P
Update
You can use evalScript to solve correctly global scope code evaluation too, sorry John (and jQuery team) but I suppose that eval.call(window) and setTimeout(f,0) aren't a "realistic" solution (first one requires this inside evaluation while second one, I suppose, is not syncronous).
Finally, if You call another function to evaluate something, its scope is just global, You don't need to use eval.call or other strategies, am I wrong?
So I probably don't understand eval.call usage and setTimeout with data ... anyone could explain me better what does jQuery do with globalEval method? Thank You :-)
Interesting point is not that kind of bench (imho) but one comment wrote by Albert Kühner:
A question about AJAX-JSON: Is there a performance difference if you dynamically create a script tag which loads a generated js file in which all objects are serialized to JavaScript objects (like JSON but without having to eval() the XHR response)?
It seems to be a simple and basic question but He was right because the answer is: yes, a script tag is generally interpreted faster than code evaluation using eval, execScript or Function constructor.
I suppose the reason is quite obvious: eval, as execScript or Function, brings temporary local scope inside evaluated code and this cause a little overhead while a script tag is always interpreted only inside global scope (window or super object).
This should be a limit for evaluation common usage (often wrong) but this was the primitive Ajax implementation to interact with server.
Example:
// specific callback to show product informations
function productInfoCallback(product){
alert(product);
}
// function to send something using GET way (query string)
function sendRequest(queryString, callback){
var s = document.createElement("script");
s.type = "text/javascript";
s.src = "interactor.php?".concat(queryString, "&callback=", callback);
(document.getElementsByTagName("head")[0] || document.getElementsByTagName("*")[0])
.appendChild(s).parentNode.removeChild(s);
};
// generic product id
var productId = 123;
// interaction
sendRequest("productId=".concat(productId), "productInfoCallback");
Now try to image server side code, in this case a really simple PHP script:
if(isset($_GET['productId'], $_GET['callback'])){
$productInfo = 'Web Reflection Blog';
//$productInfo = mysql_query ...
header('Content-Type:text/javascript');
exit($_GET['callback'].'("'.addslashes($productInfo).'")');
}
?>
Well done, this is Ajax without Ajax ... a sort of Asyncronous JavaScript and JavaScript (could we call them Ajaj ? :D )
At this point You should agree that there's no way to inject temporary scope inside response and when You load manually or dynamically a script tag the behaviour is the same.
Is it ok? Is it clear?
Well, next step is to use script tag instead of code evaluation to perform quickly (I'm talking about milliseconds) expecially when We use Ajax to recieve a JSON string.
With JSON We usually don't need temporary scope so why We should "wait" more time to evaluate that string?
This is an elementary proposal, the function evalScript:
(evalScript = function(e){
var h = evalScript.node,
s = document.createElement("script");
s.type = "text/javascript";
s.text = e;
h.appendChild(s);
h.removeChild(s);
}).node = document.getElementsByTagName("head")[0] || document.getElementsByTagName("*")[0];
How to use them? It's really simple:
// basic example
evalScript('alert("Hello World")');
The only thing You need to remember is that scope is not injected inside evaluation:
function badEvalScript(){
var string = "something";
evalScript('var string2 = string + " else"');
};
badEvalScript();
// string is not defined
// ... and string2 will be global (window.string) if string is defined
So how to use evalScript ?
You can use them after one or more Ajax interaction if You're loading a script, instead of XML or (x)HTML or text, to run for example dinamically external resources.
You can use evalScript with JSON interactions too, but You should use a little trick if You don't want to be obtrusive.
The simplest solution is, in fact, this one:
evalScript('JSONResponse = '.concat(xhr.responseText));
... but in this web world full of different libraries this is not a good idea, so why don't use evalScript itself to store temporary results?
// generic Ajax interaction ...
evalScript('evalScript.result = '.concat(xhr.responseText));
var response = evalScript.result;
Since JavaScript is, at least inside browsers, single thread, there's no risk about concurrency and in this way You'll not overwrite anything different from single evalScript function.
If You don't believe this function is usually faster than eval, just try to generate a big and complex JSON notation, using every compatible kind of compatible value, so try 10 or more times to eval them or to use my evalScript proposal.
Of course, this is just for performances maniacs :P
Update
You can use evalScript to solve correctly global scope code evaluation too, sorry John (and jQuery team) but I suppose that eval.call(window) and setTimeout(f,0) aren't a "realistic" solution (first one requires this inside evaluation while second one, I suppose, is not syncronous).
function globalScopeEvaluation(){
var testMe = "private scope";
evalScript('alert(testMe)');
};
var testMe = "global scope";
globalScopeEvaluation(); // global scope
Finally, if You call another function to evaluate something, its scope is just global, You don't need to use eval.call or other strategies, am I wrong?
function eval2(data){eval(data)};
var a = 1;
(function(a){eval2('alert(a)')})(2);
// alert 1 ...
So I probably don't understand eval.call usage and setTimeout with data ... anyone could explain me better what does jQuery do with globalEval method? Thank You :-)
Tuesday, August 28, 2007
SWF Activation using Flash Satay method
Long long IT time ago (2002) A list Apart wrote about a new W3 markup compatible way to show SWF files in a web page using a method called Satay.
This was my favourite one to create valid (x)HTML pages and this method is unobtrusive too, allowing alternative content directly inside object tag without JavaScript requirement.
This method is able to send common informations inside SWF too, using a "sentinel" file or directly full SWF to load.
Since Internet Explorer 6 add a new ActiveX control that requires at least one click before user can use SWF content many developers wrote different libraries to fix this problem, present on IE 7, Opera 9 and probably other browsers.
These libraries are good enough to solve "activation click" problem but these often offer more features we (at least me) need.
This is why I've just uploaded my last tiny library to solve this problem, compatible with IE6, 7, Opera 9, FireFox 1.5+, Safari 2+ and many other browsers.
Its size? Actually exactly1Kb (1024 bytes) 999 bytes and it seems to work correctly :-)
How to use them? Just include them externally using a script tag.
Demo page
Crazy Source (self packed)
This was my favourite one to create valid (x)HTML pages and this method is unobtrusive too, allowing alternative content directly inside object tag without JavaScript requirement.
This method is able to send common informations inside SWF too, using a "sentinel" file or directly full SWF to load.
Since Internet Explorer 6 add a new ActiveX control that requires at least one click before user can use SWF content many developers wrote different libraries to fix this problem, present on IE 7, Opera 9 and probably other browsers.
These libraries are good enough to solve "activation click" problem but these often offer more features we (at least me) need.
This is why I've just uploaded my last tiny library to solve this problem, compatible with IE6, 7, Opera 9, FireFox 1.5+, Safari 2+ and many other browsers.
Its size? Actually exactly
How to use them? Just include them externally using a script tag.
Demo page
Crazy Source (self packed)
Monday, July 30, 2007
JavaScript ElementTraversal proposal
27 July W3 announced a new Working Draft, called: ElementTraversal
This is a "new" feature but today it's not cross browser so this is my proposal to have Element Trasversal with every recent browser:
And this is a basic test:
My proposal is based on extend Function prototype, You can find them here.
Just a note about update extra method: not every browser support a defineGetter / setter method so update is a quick way to have correct properties.
If You create an instance and You modify some node, You should use:
This method returns instance itself, so You can pass them directly on other functions.
This is a "new" feature but today it's not cross browser so this is my proposal to have Element Trasversal with every recent browser:
(ElementTraversal = function(node){
this.node = node;
this.firstElementChild = this.getFirstElementChild();
this.lastElementChild = this.getLastElementChild();
this.previousElementSibling = this.getPreviousElementSibling();
this.nextElementSibling = this.getNextElementSibling();
this.childElementCount = this.getChildElementCount();
}).extend(null, {
getFirstElementChild:function(){
for(var c = this.node.childNodes,
i = 0,
j = (c && c.length) || 0,
e;
i < j;
i++
){
if(c[i].nodeType === 1)
e = c[j = i];
};
return e;
},
getLastElementChild:function(){
for(var c = this.node.childNodes,
i = ((c && c.length) || 0) - 1,
j = -1,
e;
i > j;
i--
){
if(c[i].nodeType === 1)
e = c[j = i];
};
return e;
},
getPreviousElementSibling:function(){
var e = this.node.previousSibling;
while(e && e.nodeType !== 1)
e = e.previousSibling;
return e;
},
getNextElementSibling:function(){
var e = this.node.nextSibling;
while(e && e.nodeType !== 1)
e = e.nextSibling;
return e;
},
getChildElementCount:function(){
for(var c = this.node.childNodes,
i = 0,
j = (c && c.length) || 0,
n = 0;
i < j;
i++
){
if(c[i].nodeType === 1)
++n;
};
return n;
},
update:function(){
this.constructor.call(this, this.node);
return this;
}
});
And this is a basic test:
test
test
test
testtest
My proposal is based on extend Function prototype, You can find them here.
Just a note about update extra method: not every browser support a defineGetter / setter method so update is a quick way to have correct properties.
If You create an instance and You modify some node, You should use:
ET.update();
This method returns instance itself, so You can pass them directly on other functions.
Saturday, July 28, 2007
JavaScript Blackboard
Does We really need only canvas element to draw something?
This is a basic blackboard example that uses my extend.js proposal and my setInterval and setTimeout with arguments fix for Internet Explorer.
Just draw something on Blackboard and have fun with JavaScript ;-)
This is a basic blackboard example that uses my extend.js proposal and my setInterval and setTimeout with arguments fix for Internet Explorer.
Just draw something on Blackboard and have fun with JavaScript ;-)
Thursday, July 26, 2007
625 bytes to extend JavaScript
These days I've studied (again) JavaScript prototypal inheritance and common extend functions or methods used by different libraries.
This post is a summary about my experiments and every example code is based on this script.
Probably someone is thinking about my unreadable source code, however it's self packed and quite clear, atleast for me.
The goal was to write 2 basic prototypes to extend objects or functions using "best practices" to do them using less chars as possible ... so, goal done ;-)
If You're interested about these prototypes logic please tell me, I'll try to find more time to explain better each one.
Object.prototype.extend
This is the first proposal and it's really simple to use/understand.
This is a basic example.
Extend prototype works with object itself and return them after a for in loop discarding prototyped methods.
Since extend works with object itself You can easyly add properties or methods in this way:
This prototype accepts one or more argument, so You can produce last example in this way too:
Obviously, extend prototype sets correctly toString and valueOf methods with IE too, what You just need to remember is that if extended objects have two methods with the same name, last one only will be available:
That's all, Object.prototype.extend is just what You need when You need to extend some object.
Only a last note about extend, it should work with other variables type too but please remember that for in loop doesn't always respect assignment order:
This is "a case" and not a rule so please use concat native method to extend Arrays or test for in loops before You use them with variables that are not instances or native objects.
Function.prototype.extend
This is my second prototype proposal, partially based on first one but really more powerful.
This prototype extends constructors and return them adding special features that other libraries don't use.
Its behaviour is described on this post about JavaScript prototypal inheritance but this prototype is better than simple $extend function showed on this post.
As first point, this prototype assigns correctly constructor used to create other one.
This seems to be a "natural" behaviour but I'm sure that not every other library assign them correctly.
The constructor property is not "secure" as instanceof check but first one could be easyly compared, for example, inside a swtich:
With more complex code this feature is not so unusual while instanceof requires a lot of if ... else if ... else.
This property is useful for a lot of other pieces of code too, so why We shouldn't have a correct constructor property when We create or extend another one?
This is another example that has a "not everytime" respected behaviour (using other libraries):
The second setted property, showed in last example too, is parent one, that's a referer to parent constructor if exists, undefined value otherwise.
This property should be useful as constructor to do one or more operations using parent insteadof constrcutor.
Third point about Function.prototype.extend is Super, automatically inherited extra special method.
What's Super?
Super is a method that supports multiple (cascade) inheritance, starting from instance parent and correctly respected on its parent too.
The parent property isn't always enought to support multiple parents methods.
Look at this example:
If You think that a new C instance will not crash or block your browser You're wrong!
Since apply or call methods inject temporary into another method (function) scope a different this referer, You should think about B.prototype.init one.
This method will use a C instance as this referer but C instance will have its own properties and its own methods.
Infact C instance will have a parent property too that will be exactely B constrcutor so above example, using a new C instance, will loop recursively calling as many times as it can B.prototype.init.
The solution is really simple, just use explicitally constrcutor as showed in this example:
Is it ok? Of course, it works perfectly.
However other languages have a dedicated keyword to use constructor recoursively or not and this keyword should be parent or super one.
In JavaScript the super keyword is reserved so it should be a good idea to don't use them if it's not absolutely necessary (used as string, for example), that's why I've created a Super magic method and this is how does it work:
Simple? I hope them and this way to use inheritance is quite cool (imho) ;-)
You don't need to care about constrcutor name and You don't need to use call or apply, just specify parent method name to call or, if You need to call super constructor, just use a nullable value such 0, "", undefined, false or null.
This is, for example, the Kevin Lindsey demostration code, adapted with my extend prototype:
... that in a more scriptish way should become this piece of code:
Last point is that if You don't specify a constructor (function) as first Function.prototype.extend argument You'll recieve just original one:
So do You like these 625 prototypal bytes?
This post is a summary about my experiments and every example code is based on this script.
Probably someone is thinking about my unreadable source code, however it's self packed and quite clear, atleast for me.
The goal was to write 2 basic prototypes to extend objects or functions using "best practices" to do them using less chars as possible ... so, goal done ;-)
If You're interested about these prototypes logic please tell me, I'll try to find more time to explain better each one.
Object.prototype.extend
This is the first proposal and it's really simple to use/understand.
var a = {a:"a"},
b = {b:"b"}.extend(a);
alert([b.a, b.b]); // a,b
This is a basic example.
Extend prototype works with object itself and return them after a for in loop discarding prototyped methods.
function A(value){
this.value = value;
};
A.prototype.getValue = function(){
return this.value;
};
var a = new A("a"),
b = {}.extend(a);
alert([b.value, b.getValue]); // a,undefined
Since extend works with object itself You can easyly add properties or methods in this way:
var a = {a:"a"};
a.extend({
getValue:function(){
return this.value;
},
setValue:function(value){
this.value = value
return this.getValue();
}
});
alert([a.a, a.setValue("b")]); // a,b
This prototype accepts one or more argument, so You can produce last example in this way too:
var a = {a:"a"},
b = {setValue:function(value){
this.value = value
return this.getValue();
}};
a.extend({getValue:function(){return this.value}},b);
alert([a.a, a.setValue("b")]); // a,b
Obviously, extend prototype sets correctly toString and valueOf methods with IE too, what You just need to remember is that if extended objects have two methods with the same name, last one only will be available:
var a = {a:"a"}.extend(
{
toString:function(){return "a"},
valueOf:function(){return this.a}
},
{
toString:function(){return "Object a"}
}
);
alert([a,a.valueOf()]); // Object a,a
That's all, Object.prototype.extend is just what You need when You need to extend some object.
Only a last note about extend, it should work with other variables type too but please remember that for in loop doesn't always respect assignment order:
var a = [,,,4,5,6].extend([1,2,3]);
alert(a); // 1,2,3,4,5,6
This is "a case" and not a rule so please use concat native method to extend Arrays or test for in loops before You use them with variables that are not instances or native objects.
Function.prototype.extend
This is my second prototype proposal, partially based on first one but really more powerful.
This prototype extends constructors and return them adding special features that other libraries don't use.
Its behaviour is described on this post about JavaScript prototypal inheritance but this prototype is better than simple $extend function showed on this post.
As first point, this prototype assigns correctly constructor used to create other one.
This seems to be a "natural" behaviour but I'm sure that not every other library assign them correctly.
The constructor property is not "secure" as instanceof check but first one could be easyly compared, for example, inside a swtich:
switch(genericInstance.constrcutor){
case Array://doStuff
break;
case Mine://doOtherStuff
break;
};
With more complex code this feature is not so unusual while instanceof requires a lot of if ... else if ... else.
This property is useful for a lot of other pieces of code too, so why We shouldn't have a correct constructor property when We create or extend another one?
This is another example that has a "not everytime" respected behaviour (using other libraries):
function A(){};
function B(){};
B.extend(A);
alert([
(new B).constructor === B, // true
(new B).parent === A, // true
(new B) instanceof A, // true
(new B) instanceof B, // true
(new A) instanceof B // false
].join("\n"));
The second setted property, showed in last example too, is parent one, that's a referer to parent constructor if exists, undefined value otherwise.
This property should be useful as constructor to do one or more operations using parent insteadof constrcutor.
Third point about Function.prototype.extend is Super, automatically inherited extra special method.
What's Super?
Super is a method that supports multiple (cascade) inheritance, starting from instance parent and correctly respected on its parent too.
The parent property isn't always enought to support multiple parents methods.
Look at this example:
function A(){};
A.prototype.init = function(name){
this.name = name;
return this;
};
(B = function(){}).extend(
A,
{init:function(name){
var result = this.parent.prototype.init.call(this, name);
this.name += " from B";
return result;
}}
);
C = function(){};
C.extend(
B,
{init:function(name){
this.parent.prototype.init.call(this, name);
this.name += " from C";
return this;
}
});
If You think that a new C instance will not crash or block your browser You're wrong!
Since apply or call methods inject temporary into another method (function) scope a different this referer, You should think about B.prototype.init one.
This method will use a C instance as this referer but C instance will have its own properties and its own methods.
Infact C instance will have a parent property too that will be exactely B constrcutor so above example, using a new C instance, will loop recursively calling as many times as it can B.prototype.init.
The solution is really simple, just use explicitally constrcutor as showed in this example:
function A(){};
A.prototype.init = function(name){
this.name = name;
return this;
};
(B = function(){}).extend(
A,
{init:function(name){
var result = A.prototype.init.call(this, name);
this.name += " from B";
return result;
}}
);
C = function(){};
C.extend(
B,
{init:function(name){
B.prototype.init.call(this, name);
this.name += " from C";
return this;
}
});
alert((new C).init("A").name); // A from B from C
Is it ok? Of course, it works perfectly.
However other languages have a dedicated keyword to use constructor recoursively or not and this keyword should be parent or super one.
In JavaScript the super keyword is reserved so it should be a good idea to don't use them if it's not absolutely necessary (used as string, for example), that's why I've created a Super magic method and this is how does it work:
function A(){};
A.prototype.init = function(name){
this.name = name;
return this;
};
(B = function(){}).extend(
A,
{init:function(name){
var result = this.Super("init", name);
this.name += " from B";
return result;
}}
);
C = function(){};
C.extend(
B,
{init:function(name){
this.Super("init", name);
this.name += " from C";
return this;
}
});
alert((new C).init("A").name); // A from B from C
Simple? I hope them and this way to use inheritance is quite cool (imho) ;-)
You don't need to care about constrcutor name and You don't need to use call or apply, just specify parent method name to call or, if You need to call super constructor, just use a nullable value such 0, "", undefined, false or null.
This is, for example, the Kevin Lindsey demostration code, adapted with my extend prototype:
function Person(first, last) {
this.first = first;
this.last = last;
};
Person.prototype.toString = function() {
return this.first + " " + this.last;
};
function Employee(first, last, id){
this.Super(null, first, last);
this.id = id;
};
Employee.extend(
Person,{
toString:function() {
return this.Super("toString") + ": " + this.id;
}
});
function Manager(first, last, id, department) {
this.Super(null, first, last, id);
this.department = department;
};
Manager.extend(
Employee,{
toString:function() {
return this.Super("toString") + ": " + this.department;
}
});
alert([
new Person("John", "Dough"),
new Employee("Bill", "Joi", 10),
new Manager("Bob", "Bark", 20, "Accounting")
].join("\n"));
... that in a more scriptish way should become this piece of code:
(Manager = function(first, last, id, department){
this.Super(null, first, last, id);
this.department = department;
}).extend(
(Employee = function(first, last, id){
this.Super(null, first, last);
this.id = id;
}).extend(
(Person = function(first, last){
this.first = first;
this.last = last;
}).extend(
null,
{toString:function(){return this.first + " " + this.last}}
),
{toString:function(){return this.Super("toString") + ": " + this.id}}
),
{toString:function(){return this.Super("toString") + ": " + this.department}}
);
Last point is that if You don't specify a constructor (function) as first Function.prototype.extend argument You'll recieve just original one:
var valueOf = {valueOf:function(){return this.constructor}};
A = (function(name){
this.name = name
}).extend(
null,
{toString:function(){return this.name}},
valueOf
);
alert([(new A("test")), (new A).valueOf() === A]); // test, true
So do You like these 625 prototypal bytes?