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)