Thursday, September 28, 2006

What an incredible compressor ... i didn't know it but seems really really a good compressor !!!I'm talking about memtronic javascript compressor that allows me to pass from about 2.7 Kb into 1.98 Kb (with comments) !!!

Sure, it's not a big difference from Dean Edward packer but now I can say that I've created an FX library in exactly 1.889 byte (without comments) ... it's hilarus for me, I didn't know that some compressor was able to reduce size in this way.

Thank you memtronic !!! Your compressor is fantastic !!!

Here you can find bytefx API page with memtronic version demo and the link under Sources:bytefx

I think this post is only for basic JS developers and shows how a simple function or a simple operation should be wrote in different ways.In this specific case, I would talk about logic used for a single function while I was optimizing bytefx.

The problemI've two numbers, x and y, I need to change x, adding or removing a "speed" value, while x is not equal to y.

This simple problem has a lot of solutions. This is probably the simplest one:

Simple ? Clear ? ... I like this way as I like ternary operator, it's a must to write compact but efficient code.However, look at this last function ... don't You see something strange ?If and else if do exactly same operations ... only plus sign and greater than are diferent.How we could create these similar operations in a single line ?Using eval, sure !

... simple ? cool ? ... no, it's not cool !Eval in this case isn't absolutely dangerous or a problem while ternary operator is.The answer is simple, we have reduced code size with a simple and fast function but we do everytime two operations.These are x + speed or x - speed in both cases duplicated.It's true, a simple addiction shouldn't be a problem for code execution, but if there's a way to use a better function, why we shouldn't use that ?

Tuesday, September 26, 2006

... less than 5.50 Kb for the un-packed version, less than 3Kb for Dean's packer compressed version (my php compressor doesn't like it ... and I need to know more about this problem !!! ).It's bytefx, naturally compatible with FireFox or JS 1.6 standard browsers, compatible with IE5.5 or greater version with my JSL.

I need some day to write the simple API, docs and FAQs ... but you can just view an alpha version in action surfing this demo page.Seems cool ? Seems another boring FX library ? Seems doesn't work with Safari or other browsers ? (I've not yet tested with Konqueror or Safari)

I think that those kind of tests are only a "point of view" and aren't comparable with real javascript usage.As I've showed on my for and while loop test, every operation is a single case to analize and every single case has not everytime the same result.

For example using a for and an <= expression with every loop should be faster in some browser and should be slower in some other.Then it's not always a good way to compare some internal loop operations because a browser should be faster to push a string inside an array but should be slower to execute that kind of for loop.

Often speed depends on garbage collector too, that should be faster in some point of execution and slower in some other.

These concept are true with every other benchmark of that site.

Math engine, as Ajax declaration, are faster with FireFox and really bad with IE because the object has a dedicated try catch for every IE browser.I usually don't use that way to declare an XMLHttpRequest then my library should be faser than Opera with IE too.If you change some piece of execution code, you can see that IE6 or 7 is even slower than FireFox with some function.

What I mean is that a real "every day" application will "never" use 4000 try catch but should use a lot of Math operations and DOM elements using many array and Ajax declarations too.Every Ajax object or class should be simple or really complex and some browser should declare it faster or slower than other one.

Another generic relevant thing is code optimizzation ... you could use "only Opera" to surf the web but if a library contains bad practices its code execution will be slow in every case.

And again, the use of "var" before every temporary variable should be slower or faster, look at the MathEngine function ... is this usefull ?is this a real application example ?

The StringFuncs has 2 operations that are only for human eyes because if you don't call those functions how can you test them ?

str.toLowerCase; // yeah! a string has a toLowerCase prototype ..str.toUpperCase; // yeah! a string has a toUpperCase prototype ..

// P.S. I think that He's just forgot it :)

A "StringBuilder" function should be a better test too because every JS developer knows that using string += something isn't a good speed practice and the use of concat instead of '+''+''+''+''+' ... is faster too.A StringBuilder operation is not different from array.push, but doesn't use sort and reverse as ArrayFuncs does.

Is a StringBuilred competition another usefull test to do ? I think that ...

Then this is what I think: these speed tests are a must only for Rhino or SpiderMonkey developers because a javascript developer doesn't need to care about performances (in this way) ... He needs to care about generic code optimizzations using lightweight code implementations without redundant operations inside a cross-browser code.That's what a developer should care about, not dedicated speed test for this or that function.

Sunday, September 24, 2006

The first line of this post is dedicated to Dean Edwards: thank you very much for your DOMContentLoaded implementation !!!Without Dean solution I'll probably never create the code I'm going to show, than thanks again Dean.

Next step is my solution code concept:if we need to write runtime a script tag, why should we use conditional comments if we could implement the solution directly with that tag for other browsers too ?

Since onreadystatechange inside a script tag is called only from IE and Safari, we could write this properties directly inside the script tag, then we don't need any anonimous function and we don't need any webkit dedicated interval too.

Then if we need to use defer with uncompatible browsers, we could set its value as generic value (I think it's more clean and elegant) and if we use our functions with the script we don't need to get it then we don't need it's id too.

This code is the base for my onContent callback, that's based on a single global object, used fromthe tag to call functions.It's time to show my lightweight function (less than 500 bytes), compatible with FireFox, Opera 9, IE5+ and Safari (thank you guidoz) and compatible with other browsers too (IE4, Opera < 9, others), using "old" window.onload method.

__onload__ is the global object used by script tag and has 2 methods and just 1 parameter.The dollar method $ is a shortcut to delete window.onload callback with every "DOMContentLoaded" compatible browser and then $ calls the callback too.

The second function, called IES, is the IE/Safari dedicated callback, used inside onreadystatechange event.This function recieves the this (window) object and then check if its readyState is "complete", then call the dollar $ function to delete onload and to call callback.The last FO parameter is dedicated to FireFox and Opera but preserve javascript errors using addEventListener only if this document method is available.In other cases, this parameter will be the string "void(0)".We don't need to care about addEventListener compatible browsers (i.e. Safari) because if they don't support the "DOMContentLoaded" event they'll necer use that listener.FireFox as Opera will use that method directly (onerror, for FireFox, and onload, for Opera, script functions have a delay and if you add DOMContentLoaded event after page is loaded (cached) this will nevver be called).

Next line is the window.onload method, used from every browser ... then if __onload__ "hack" fails, callback will be called without problems.The next line contains an if, this is necessay for Opera version older than 9 because Opera 8.5, for example, doesn't show the page if you write a script tag while page is downloading.Final line writes the script tag, adding event or void inside src, adding defer="defer" for IE and setting onreadystatechange for IE and Safari.

What about addLoadEvent for multiple onload callbacks ?I think that a single callback, if we don't use external libraries, is sufficient to call every other event on page complete or on dom ready (just calling multiple functions inside another one).However this should be a simple solution to add multiple events using onContent function.

First line calls onContent if __onload__ object doesn't exists then creates the __onload__ object too and add a callback to call an __onload__ method.callEvents is this one and it's used on page complete.It loops over every callback and calls them.Last if/else creates the __onload__.events array, adding first callback too.

Finally You could create a single function moving onContent inside addContentEvent (at the top), if addContentEvent is your favourite way to add callbacks.

The last thing ? The Example Page, where you should read event: onContent with compatible browsers (and please let me know if some browser is no compatible).

P.S. this blog doesn't require an account to reply ;)

UPDATEFor some reason Safari (at least some versionof Safari) doesn't accept an undefined source script and shows an error when this function write the script tag.To solve this problem I've changed the function that now has the same snif used by Dean Edwards plus Konqueror snif (for KDE 3.X).

This is my updated solution, now tested with a real big range of browsers with a size of 650 bytes.

Friday, September 22, 2006

What is F.A.P. ???F.A.P. is my archive preview idea, a fast way to know a title and its permanent link of each post and for each month (or date).You can view an example scrolling this page to Archieves and wait few seconds over one month just with your mouse.

How does F.A.P. work ?Blogspot is a wonderfull and free service but its server is not available to its users.There's no way (at least I've not found anyone) to implement ajax request to do some "experiment".However, we are really lucky because blogspot doesn't block external requests, then every host should read our blog content, simply calling one page.This was the key to create F.A.P. web service, that's a simple dedicated blogspot output parser.The called external page will read a built archive page, for example one of the pages you can find under the Archieves on your left or right side of your blog.After that our external requet page will produce a JSON like output usable for our scripts.

How to implement F.A.P. in your blogspot place ?The first thing to do is a class or a function that can add dinamically a javascript tag inside page's head tag.I've used this simple Class to do that

This class has only 3 public methods - add, to add one or more external javascript file - clear, to clear every external javascript file we have add - remove, to remove one or more external javascript file from pur head

The second thing to do is to create a global variable to save (or cache) requet informations.The name of this var is, obviously, webreflection :D

webreflection = {};

Now we need to add an onload event because we need to find and modify every Archive Link.

// use your favourite "addEvent" method, this is only an exampleonload = function() {

// blogspot calls UL Archive container class "archive-list" // we're interesting only to this container, that should be // the parent node of one or more LI if(li[--i].parentNode.className === "archive-list") {

// well, we have found an Archive li // then we can add a div (unobtrusive layout) // that will be used with F.A.P. li[i].innerHTML += "

"); // we can use a class name, then in our CSS div.month-ghost can be as you want

// now we need to get the link inside this LI link = li[i].childNodes[0];

// and we need to get date inside this link // stored inside the link as an un-standard parameter link.webreflection_remstring = link.href.replace(re, "$2");

// we need to save created div too, using unique id created with innerHTML link.webreflection_div = document.getElementById("month-ghost-".concat(i));

Wednesday, September 20, 2006

This post shows as is possible to set prototypes with anonymous functions.This one shows a simple anonymous function application example, a fake addEventListener.We often use directly the method with the document element, it's simple and fast, then often our preferred way to implement an event.I'm talking about this code

The attachEvent has different problems, it isn't a standard method (then IE and few other browsers supports that) and the scope inside the callback is not the element.This code, for example, doesn't work as expected:

I've implemented the addEventListener in my big dollar function but often developers doesn't like "big" external libraries (scriptacolous as prototype and Dojo are some exceptions).That's why I'm writing this simple function to add an event directly to an element, using generic on* event names.

myFunc is a function with all Function prototypes or native methods and with the same constructor of a function.Then myFunc is absolutely a function, but wich kind of function is it ? Exactly this one:

function anonymous(a, b, c) { return a + b + c;}

What's that ? That's a function that exists but you can't modify, get, or extend anyway because each new Function will produce a different referer for a different anonymous function.

As you can see, those parentheses are the key to understand the anonymous function.

Step 2, parentheses and virtual scopeAt this point we know that an anonymous functions cannot have dedicated prototypes and aren't like regular functions too.In some script you can see the use of parentheses to call runtime a function or to create one.This code, for example, is an unobtrusive way to add a personal String prototype.

Let me explain this few lines of code.If some script, before this one, has just defined a String.prototype.toArray or browser has a native String.toArray function, the anonymous function created using parentheses and directly called with (String.prototype.toArray) that accepts, if present, the base function, will assign to that prototype old version (base) or, if base is not defind, our prototype function (function(){return this.split("")}).The closed anonymous function is then a special function and its really usefull to solve a lot of problems.This is only a little example but I think you used anonymous functions every day with every scripts ;)Since the scope inside parentheses "magically disappear", but neither for itsself nor for its internal scope, we can think that those kind of functions are exactly anonymous.

Step 3, how to create a dedicate prototypeJavaScript is Object Oriented and each function is an object, then why I couldn't use "special" anonymous functions as an object ?That's why I've created a simple solution to have customizable anonymous functions, every one will be different from every other, but everyone will have our dedicate prototypes.This is the concept function

// anonymous explicit functionfunction anonymous() {

// prototype to prototype, // this function copy each a prototype (p) to other (b) function function p2p(p,a,b) {

// using prototype for b too isn't a good solution (imho) // because only new anonymous will has these prototypes for(var k in a[p])b[k] = a[p][k]; return b; };

Just a look at the last test, where is used arguments.callee instead of "this".That's simply why the "this doesn't exists" inside the function ("this" inside a function is the window object).That's all :)

The first point is ... sorry blogspot, you didn't cause any problem to JSL

The secondo point is this one: google adsense ... have you seen the code ?To find the problem and then the solution I've downloaded adsense code to look inside that after a "manual code beautifier operation".That's what I think about adsense code:

absolutely "undebuggable", to be lightweight (about 7Kb in a local file, maybe compressed on-line with gz, then 2Kb) variables and function names are really hard to understand

contains few errors, Opera as FireFox show everytime something inside the js console

The good thing is that all adsense code is inside an anonymous function, then every other script on the page will not be modified ... every but another google adsense script, because the use of window inside the script allows itself to create a big list of window.google_* variables.This shouldn't be a problem, but if you use a script that does a for in loop with the window oblect, you need to rememeber that every /^google_/.test(param) should be leave as is.It's time to view the internal function code, starting from optimizzations.As you can read on many lines, for example on line 6, every if / else if / else uses curly brackets ... even when it's not necessary (every single operation after the condition).But if you look at the line 295, someone uses correctly an "if" without braces ... who did this ? Maybe not the same developer ?Since it's correct even with single line funtions, to optimize this script a lot of braces should be removed, adding where we need a ";" char.

However I wonder when this piece of code should be usefull because google_num_0ad_slots is not present in this script, then it's maybe defined from other scripts.If this is true or not, the if,else and then if does something like this:if google_num_0ad_slots is not defined, or is null or is 0, google_num_0ad_slots should be 1, in every other case should be google_num_0ad_slots + 1 then it should be 0 if google_num_0ad_slots is less than zero.

These "if/else and then if again" I've just optimized are in different lines of the script but in some cases there is only an if else (i.e. 170 whre there's any "greater than 1" check)In these cases the code should be

Another little optimizzation should be done on function F (line 73).Since adsense code optimizzation is based on short var names I think that repeat for a lot of times the same object param prefix is not so good as a dedicated params array should be:

In this way all properties are simple to add or to remove from the list, and "b.google_" is present just one time.However if an optimized while should be slower to parse with a really big array, using o.param1=o.param2=o.paramN=null instead of "=a" for each param should be the same thing.

AdSense script uses a lot of returns in-function, that is a method I don't like very much (but it's only my opinion and using only one return isn't a better way to write functions).For example there's a "special" function I've seen that's not good enought for me, it is the x function (line 293).

If you look at the original version you can view that if z is true (then r in my version), function returns false.Then if !r (when r is not true) it's possibile to do other operations inside the first if condition.At the end of the first if you can assign a boolean value without the if and the second in-function return.Then if r is true, the final return value is false. It's true for the first check as for the second, then in every other cases, when r is not true, returned value will be true (not false).

This is the way I usually like to return a boolean value from a function or method using only a single return (cleaner, imho) at the end of the function.

We are going to the end of this post, there's only another function I've not understand ... the C function (line 286).As you can see C function recieves 3 parameters, any of these is used, A function is called and true value is returned.Do you think it's usefull ? I think that A function, that doesn't have any input parameters and doesn't return anything, should return true value and should be used directly on line 325.

b.onerror=A;

... adding return true on A function ... then anyone doesn't need the C function (but maybe it was created for future implementations).

The absolute last thing I want to tell to google AdSense script developers is this one:why do you optimize in this way the code but you use "var" for every temporary function variable ?

Look at the line 319, inside the function E ... wasn't better something like ...

Monday, September 18, 2006

I did a simple version of onmousewheel, then I add JSL and $DOM objects dependencies, then I've came back to single portable version without dependencies that's simpler than first one :D

Concept:onmousewheel isn't a window or document event, onmousewheel is a generic Element event. While a generic event as onclick, onmouseover, onmouseout is called only above the element, onmousewheel will be called only above the element too, that's all!

No more double events (onmouseover that activates onmousewheel and onmouseout that deactivates onmousewheel) ... just the event.

Dean Edwards closed comments in this page (sorry Dean) , but I wonder if there is a real example page where this alternative way to implement DOMContentLoaded doesn't work as expected (please post me one !!!).

My simple solution is this one, anonymous function with multiple callbacks after document.body is not undefined.

Just 2 simple lines of code, but for some reason it shouldn't work correctly in some case.

Then, while my test page doesn't fail this method, at least with my browsers, I'd like to know when this way shouldn't work correctly or when this way should work (I always prefere to reduce JS size then if generic cases work correctly with this method to implement DOMContentLoaded I'll prefere this one).

Saturday, September 16, 2006

Maybe the best and elegant way to get one or more document element as you know.

The $ function is used from a lot of JS developers, it's simple, fast and allow us to reduce scripts size (forget document.getElementById).

Then that's my idea: why we can't use $ to add element standards ?

Every element that's grabbed with $ function should be parsed by function to improve Element standards ... and why not, to add special features for each element.

Here there's an example: big $ function where you can view my first standard implementation, addEventListener and removeEventListener for every browser.

It's not based on attachEvent because attachEvent doesn't works with element scope (this is not the element inside an event listner function ... and it's terrible !!!) and this alpha version manages correctly whellscroll too for IE6, FireFox or Opera 9.

This function will be extended to add a lot of standard Element methods but only if this is a good solution or a good idea, then I'm waiting for some reply :)

That's another reason to base libraries or every kind of script on JSL that doesn't modify anything, if present.

JSL is an unobtrusive way to implement JS 1.6, not the unique way to use some personal prototypes.

To add my JSHighLighter, that requires JSL, in this blog I had to include external JS sources at the bottom of the blog model ... come on blogspot, trash your String.replace or encodeURIConponent implementation and use JSL :D

P.S. I don't know what was modified, I saw a redirect to an invalid url created by some blogspot script.

Friday, September 15, 2006

JavaScript 2.0 is on the air but in a lot of js oriented sites I can see every day show often the same, obvious or boring prototypes to normalize some old browser before every kind of different solution for every different problem.

Yesterday, for example, I've read about a "revolutionary" way to search a value inside an array, using an "horrible" Object solution.

If you read comments you could see that Array has a native, standard, prototype called indexOf that does exactly what that blog was talking about.

Well, why do you like to spend your time for these things ?

You like that because you don't know all JavaScript 1.6 objects methods or you don't use FireFox to develop your code and you don't have a low level code normalizer library.

However, one of the first comments shows the simplest solution for the problem, indexOf, but shows another Array.prototype normalizer function.

This is just one example of all posts that you can find on the net and everytime someone posts a Something.prototype normalizer solution for that problem, for that library.

Maybe in your 3rd part page scripts you have at least 2, 3 or more equal prototypes that normalize this, that or other library ... or recreate always the same result with a different name.

Don't you have enought ? Don't you care about sum of every script size ?

I wonder why JSL hasn't been linked from any "javascript specialist site" because to write a standard code, using for example JSLint, isn't enought to produce good, fast or optimized code.

I've talked about my JSL to Dojo developers too, to resolve a lot of common JS portability problems and to resolve encodeURIComponent or decodeURIComponent top-level function portability that are quite perfect only with JSL, as String.replace with function as second argument is.Dojo developers didn't care about JSL ... they don't need another normalizer library (but they have a propetary normalizer library ... that doesn't make JS more standard for every other lib in a 100Kb of packed code lobrary ... ).

Prototype has its normalizer proto too but these aren't standard.Array.each is not standard (while JS 1.6 has Array.forEach, that's a standard method), indexOf is not complete (and I havn't seen the String.indexOf implementation) ... then why rewr everytime the same normalizer prototype ?

Why increase every library with its normalizer prototype when JavaScript 1.6 has at least one of every normalizer proto used inside every library ?

Do you think this is a good way to depends everytime from each different library ?Do you think your library is the "only cool one" and then every developer should learn a different (but same) implementation of every different library normalizer prototypes ?

We don't like IE because it doesn't respect standards, every JS library I've seen doesn't respect ECMA standards too.

Why don't you use JSL and then ECMA Standards for JS 1.6 ?

When finally all browsers will be compatible at least with JS 1.6, remove JSL will be a simple step while using prototype or other libraries dedicated implementation of "un-standard" ECMA will not be possible.

Finally, if a lot of developers think that top 10 JS funcs should be inside a common.js, why they don't think that a low-level lib as JSL is should be a must before every every top-ten common.js ?

It's a single file, as a common.js file should be, it's lightweight, it's to develop every kind of medium or high level lib or code using standards, it's a must to write code for FireFox and use it with every other browser .... then why don't you like my JavaScript Standard Library ?