My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

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

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:

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:
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

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:

// 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.


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 have not just read anything something about DEFLATE problems too.

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 free 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.


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!!!

I didn't find a way to create a clean video, probably 450 pixels are not enought to show how does packed.it work?

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 :-)

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!

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:

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 !

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.


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.