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

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="://"

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:

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.


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.


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.

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.

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.


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:

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

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:


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 exactly 1Kb (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)

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:

(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
test

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:

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

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.

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?

Quick Fix - Internet Explorer and toString problems

As You can read on precedent post I'm testing common libraries extend behaviour, both for objects or constructors.

One feature that many developers seems to ignore is IE behaviour when an object contains an explicit toString method.

Look at this simple example:

for(var key in {toString:function(){return "bye bye IE"}})
alert(key);

now test them with IE 5, 5.5, 6 or last 7 version.

What's up? ... absolutely nothing ... so what the hell?

IE doesn't recognize that toString method as explicit one but it "thinks" that's a native one.

This means that a lot of extend functions doesn't assign correctly this method if client broser is IE so every extended object will simply have native or prototyped toString method and not new explicit one.

How to fix this IE behaviour ?

// generic object/instance
var o = {
a:"a",
b:"b",
toString:function(){
return "hello IE too"
}
};

for(var key in o){
// doSttuff ... for example
alert(key);
};
/*@cc_on if(o.toString!=={}.toString){
// doStuff ... for example
alert(o.toString);
}@*/

Since only IE has this problem a conditional comment should be a good solution but this is not required, every other browser will simply check/assign one more time toString method if present.

You can use Object.prototype.toString instead of {}.toString but I think performances are not a problem in both cases.

What are libraries that don't care about this IE problem?

It seems that jQuery, MooTools and probably other libraries don't care about this IE problem while dojo, for example, does more than one check:

if(dojo.isIE &&
(typeof(props["toString"]) == "function") &&
(props["toString"] != obj["toString"]) &&
(props["toString"] != tobj["toString"])
)
obj.toString = props.toString;


Dean Edwards checked valueOf prototype too, so the complete fix should be this one:

/*@cc_on
if(o.toString!==Object.prototype.toString){
// doStuff
}
if(o.valueOf!==Object.prototype.valueOf){
// doStuff
}
@*/

Wednesday, July 25, 2007

JavaScript prototypal inheritance using known libraries

JavaScript is a "quite old" scripting language but every day there's some news about its normal behaviour or some common code ... well, today is my round :-)

There are a lot of frameworks or libraries We use every day but I think every JS developer should know atleast basic JavaScript prototypal inheritance.
It seems to be the ABC of this wonderful scripting language but if You'll read this post I suppose You'll be surprised!

Let me start with a simple example about JavaScript inheritance, a constructor A with just one prototyped method and a sort of subclass B that would be extend A one.
So, this is the A constructor:

function A(){};
A.prototype.constructorIs = function(F){return this.constructor === F};

// alert((new A).constructorIs(A)); // true

This is a basic constructor example and every instance will inherit constructorIs method.
This one will return instance.constructor and compare them with a generic constructor Function.
Well, at this point We need just another constructor that would extend A one ... and its name is, for a real fantasy example, B.

function B(){};
B.prototype = new A;

Well done, this is a simple JavaScript inheritance example.
Every B instance will be an instanceof B and an instanceof A but there's a strange JavaScript behaviour with this kind of inheritance:
every instanceof B will have a constructor property that will be exactely inherited one!

alert((new B).constructor === A); // true!!!

Since prototype inheritance works in this way, last example code shows a correct behaviour.
This is true just because if new Function inherits from Function.prototype and every Object, as prototype parameter "is", is assigned by reference and not by a copy.

However JavaScript has not an official or crossbrowser way to get last inherited instance constructor so this behaviour should be a problem when You write a bit complex code or use multiple inherited constructors (someone call them classes).

At this point if You choose to implement a generic constructor extend method or function, I suppose You should clean this behaviour adding a better one ... or if You don't think so, please don't call that function/method extend and choose another name such injecting arbitraty methods or properties!

What I mean is that native JavaScript behaviour, using A and B constructors, is this one:

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // false
a instanceof A, // true
b instanceof A, // true
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));

As I've said, this behaviour is logically correct but I suppose that every Object Oriented developer would have atleast one more true in that boolean list:
an instanceof B should have a B constructor!

This is why a lot of people wrote something about prototypal inheritance but it seems that not everyone tested correctly expected extend behaviour, that should be:

b.constructorIs(B), // TRUE

to be able to use every instance constructor to call, or apply, methods or, why not, to call or apply constructor.prototype.constructor one!

// base constructor or generic Object prototype
// to call its super (parent) while there's one
Object.prototype.SuperCall = function(method){
var parent = this.parent,
result;
if(this.parent.prototype.parent)
this.parent = this.parent.prototype.parent;
result = parent.prototype[method].apply(this, [].slice.call(arguments, 1));
this.parent = parent;
return result;
};

// base constructor
function A(){};
A.prototype.init = function(){
this.isA = true;
return this;
};

// constructor B extend A
B = $extend(A, {init:function(){
this.isB = true;
return this.SuperCall("init");
}});

// constructor C extend B
C = $extend(B, {init:function(){
this.isC = true;
return this.SuperCall("init");
}});

// A, B and C instances
var a = (new A).init(),
b = (new B).init(),
c = (new C).init();

// inheritance test
alert([
a.isA, // true
a.isB, // undefined
a.isC, // undefined
b.isA, // true
b.isB, // true
b.isC, // undefined
c.isA, // true
c.isB, // true
c.isC // true
].join("\n"));

Above example uses a parent property that should easyly be a shortcut for this.constructor.prototype.constructor.
If constructor is correctly implemented there's no reason to don't use multiple inheritance from last constructor to first extended one but this is possible only with correct extend method.

This is my humil one, self packed to stay into 205 bytes ... it's behaviour is exactly expected one and it has been used to create above example.

$extend=function(b){var p="prototype",a=[].slice.call(arguments,1),f=function(){},i=0,k;f[p]=b[p];f[p]=new f;while(i<a.length){for(k in a[i])f[p][k]=a[i][k];++i};f[p].constructor=f;f[p].parent=b;return f};


To compare extend code I've not used last example but this simplest one:

function A(){};
A.prototype.constructorIs = function(F){return this.constructor === F};

B = $extend(A);

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // true
a instanceof A, // true
b instanceof A, // true
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));

that's exactly the same I've used to do famous frameworks/lybraries tests.
Let's start with first one?



jQuery - V 1.1.3.1
One of the best library I've ever used, intuitive and powerful but it seems that jQuery didn't understand correctly what an extend function should do.
I'm talking about $.extend one, used with more than a single argument:

function A(){};
A.prototype.constructorIs = function(F){return this.constructor === F};

B = $.extend(A,{});

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // true
a instanceof A, // true
b instanceof A, // true
b instanceof B, // true
a instanceof B, // true
a instanceof Function, // false
b instanceof Function // false

].join("\n"));

quite cool John, but if I extend a constructor B starting from A, how can be an instanceof A at the same time an instanceof B???



prototype - V 1.5.1.1
This is a framework that I've never loved but I know this is a great one!
This is prototype behaviour (probably I didn't understand Object.extend usage?) :

function A(){};
A.prototype.constructorIs = function(F){return this.constructor === F};

function B(){};
B.prototype = Object.extend(B.prototype, A.prototype);

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // true
a instanceof A, // true
b instanceof A, // false
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));

Well ... I suppose that this is not a real extend public static Object method ... please change its name!



MooTools - V 1.11
Another wonderful framework, developed by a really good stuff ... but probably old prototype framework logic isn't yet totally removed? :-)

var A = new Class({
constructorIs:function(F){
return this.constructor === F
}
}),
B = A.extend();

var a = new A,
b = new B;

alert([

a.constructorIs(A), // false
b.constructorIs(B), // false
a instanceof A, // true
b instanceof A, // true
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));

Ok Valerio, I know constructor is always a sort of baseMooClass one ... but there's no way to correct this strange way to inherit functions?



dojo - V 0.9
Great dojo toolkit framework, in its new beta version, is able to produce my strange code using SuperCall method with expected constructor but an inherited instance can't return false in a "instanceof Super" check, don't You agree?

function A(){};
A.prototype.constructorIs = function(F){return this.constructor === F};

B = dojo.extend(function(){}, A.prototype);

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // true
a instanceof A, // true
b instanceof A, // false
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));

Please dojo developers confirm us that this is an expected behaviour because it seems too much strange as behaviour :P




Ok, now it's time to speak about team or developers who probably did these tests many time before me, starting from Kevin Lindsey:

// Kevin Lindsey - Article of 2006/11/12 at 17:32:30
function A(){};
A.prototype.constructorIs = function(F){return this.constructor === F};

function B(){};

KevLinDev.extend(B,A);

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // true
a instanceof A, // true
b instanceof A, // true
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));

Well done Kevin and your old article is cool too :-)



Next developer is, obviously, Dean Edwards and his even old Base proposal:

// Base - V 1.0.2 (now serving 2.X)

var A = Base.extend({
constructorIs:function(F){
return this.constructor === F
}
}),
B = A.extend();

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // true
a instanceof A, // true
b instanceof A, // true
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));


Last big library that "probably" recieved Douglas Crockford help is YUI!:

// YUI! -. V 2.2.2

function A(){};
A.prototype.constructorIs = function(F){return this.constructor === F};

function B(){};

YAHOO.extend(B, A);

var a = new A,
b = new B;

alert([

a.constructorIs(A), // true
b.constructorIs(B), // true
a instanceof A, // true
b instanceof A, // true
b instanceof B, // true
a instanceof B, // false
a instanceof Function, // false
b instanceof Function // false

].join("\n"));


Well done guys and that's all folks!

Friday, June 29, 2007

A simple JvaScript way to change element color

function gradient(id, start, end, speed, prop, callback){
var style = id.style || document.getElementById(id).style,
i = setInterval(function(){
for(var j = 0; j < 3; j++)
start[j] = gradient.run(start[j], end[j], speed);
style[prop] = gradient.color(start);
if(String(start) === String(end)) {
clearInterval(i);
if(typeof callback === "function")
callback(id);
}
}, 20);
start = gradient.rgb(start);
end = gradient.rgb(end);
speed = speed || 10;
prop = prop || "color";
return i;
};
gradient.color = function(c){return "#".concat(gradient.hex(c[0]), gradient.hex(c[1]), gradient.hex(c[2]))};
gradient.hex = function(rgb, c){return (c = rgb.toString(16)).length === 1 ? "0".concat(c) : c};
gradient.norm = function(c){return (c = c.substring(1)).length < 6 ? "".concat(c, c) : c};
gradient.rgb = function(c){return [parseInt((c = gradient.norm(c)).substr(0,2), 16), parseInt(c.substr(2,2), 16), parseInt(c.substr(4,2), 16)]};
gradient.run = function(x, y, speed) {return x < y ? Math.min(x + speed, y) : Math.max(x - speed, y)};


It's bytefx style and it could be used, for example in these ways:
onload = function(){
var div = document.createElement("div");
div.id = "test";
div.appendChild(document.createTextNode("Hello Gradient !"));
document.body.appendChild(div);
gradient("test", "#000000", "#FFFFFF", 10, "color", function(id){
gradient(id, "#FFFFFF", "#000000", 20, "backgroundColor", function(id){
gradient(id, "#FFFFFF", "#676767", 5)
})
});
};


... or in a Flash RollOver/Out style:
onload = function(){
var div = document.createElement("div");
div.id = "test";
div.appendChild(document.createTextNode("Hello Gradient !"));
document.body.appendChild(div);
div.colors = ["#000000", "#ABABAB"];
div.bgcolors = ["#FFFFFF", "#000000"];
div.newGradient = function(gradients){
if(this.gradients) {
clearInterval(this.gradients[0]);
clearInterval(this.gradients[1]);
};
this.gradients = [gradient.apply(null, gradients[0]), gradient.apply(null, gradients[1])];
};
div.onmouseover = function(){
this.newGradient([
[this.id, this.colors[0], this.colors[1]],
[this.id, this.bgcolors[0], this.bgcolors[1], 10, "backgroundColor"]
])
};
div.onmouseout = function(){
this.newGradient([
[this.id, this.colors[1], this.colors[0]],
[this.id, this.bgcolors[1], this.bgcolors[0], 10, "backgroundColor"]
])
};
};

Have fun with grandients and colors :-)

Wednesday, June 27, 2007

JSOMON, a JSON Evolution !


Have You never thought to send object methods too?
Have You never thought to drive completely your client side application from server?
Did You never try to save functions, callbacks or methods using JSON?
This is a new client/server interaction way for your Web 2.0 applications, this is JSOMON!
Another joke? Another experiment? Well, probably, but JSOMON is just ready to be tested, used and why not, to be better if You have some interesting features to add or modify and I'm waiting for your feedbacks.

Have fun with JSOMON!

Monday, June 18, 2007

FireFox 3 Password Manager? Well, check You password security :-)

This simple function returns a short number from 0 to 9, for a total of 10 points, to verify security level of your choosed password.

Score is evaluated in two different parts: one for the password length and one for character used for that password (different and alpha numeric, upper/lower case is better!).

This version is quite better than older one showed in this post: Unobtrusive Password Security Level Form

So have fun with password and take care your security :-)


function PasswordSecurityLevel(pass){
var level = 0,
length = pass.length,
re = PasswordSecurityLevel,
check = [re.all.test(pass), re.alu.test(pass), re.num.test(pass)],
i, chars, key;
switch(true){
case length > 15: level++;
case length > 11: level++;
case length > 7: level++;
case length > 5: level++;
break;
};
if(re.oth.test(pass))
level++;
if(check[0] && check[1] && check[2])
level++;
if((check[0] && check[1]) || (check[0] && check[2]) || (check[1] && check[2]))
level++;
if(level > 5) {
for(i = 0, chars = {}; i < length; i++)
chars[pass.charCodeAt(i).toString()] = true;
i = 0;
for(key in chars)
i += chars.hasOwnProperty(key) ? 1 : 0;
switch(true){
case i > 9: level++;
case i > 7: level++;
break;
};
};
return level;
};
PasswordSecurityLevel.num = /[0-9]/;
PasswordSecurityLevel.all = /[a-z]/;
PasswordSecurityLevel.alu = /[A-Z]/;
PasswordSecurityLevel.oth = /[^a-zA-Z0-9]/;

Saturday, June 16, 2007

Simple setTimeout / setInterval extra arguments IE fix

One of the coolest thing of Internet Explorer is that even version 7 doesn't respect timeouts or intervals creation functions as every other browser does!

I'm talking about extra parameters, that we need to pass inside a "temporary" (not for GC) extra function to use closures and to have same result.

Here is an example:

// i need an interval that check a variable ...
// ... and this is the way we usually do that ...
var i = setInterval((function(start){
return function(){
if(new Date - start > 990) {
alert("about 1 second: ".concat(new Date - start));
clearInterval(i);
}
}
})(new Date), 20);


Well done, two functions for our browser and boring unelegant way to code.

With FireFox, Opera, Safari and other more standard browsers, we should send directly extra arguments after delay interval.

setInterval(callback, delay, param1, param2, ..., paramN);

This means at least two things:
1 - we don't need to create a function wrapper to send arguments to callback
2 - we don't need to write many bytes to send parameter that need to be wrapper arguments that need to be sent to callback

A lot of developer uses string mode to solve this problem:
setTimeout("callback()", 20);

but as You know, eval is evil and we always prefere don't use them every time we can.

In this case, we should use "stupid" string evaluation to solve an Internet Explorer unfeaure ... but do we really need to code in this way?

Nope, and this is my simple proposal:

/*@cc_on
(function(f){
window.setTimeout =f(window.setTimeout);
window.setInterval =f(window.setInterval);
})(function(f){return function(c,t){var a=[].slice.call(arguments,2);return f(function(){c.apply(this,a)},t)}});
@*/

Of course, a conditional comment to call that anonymous function only with IE browser, every other will use native setTimeout or setInterval function without problems.

Please note that usage of window.setSomething, instead of direct setSomething assignment is a must, because if You remove window from left side IE will tell You that operation is not valid while if You remove window from righ side, IE simply will never do anything with those two functions.

About IE Performances?
A bit slower intervals, it's obvious, but why should we care about a browser that allow us to changes its native functionality with just a simple trick like that?

I don't know if someone has just talked about this problem and this solution but I hope this one will be useful for your next code.

Oooops, I forgot first example? Here it is ;-)
var i = setInterval(function(start){
if(new Date - start > 990) {
alert("about 1 second: ".concat(new Date - start));
clearInterval(i);
}
}, 20, new Date);