En javascript un caso que se puede dar, aunque no demasiado común, consiste en necesitar serializar llamadas Ajax asíncronas, es decir, realizar una serie de llamadas Ajax asíncronas de forma que el usuario puede seguir manejando la página pero que las llamadas se realicen en el orden en que se vayan pidiendo de forma que al servidor sólo le lleguen las llamadas una detrás de otra sin que se pueda dar el caso de realizar dos llamadas Ajax simultáneas al servidor.
Para ello, he creado un código que permite realizar esta tarea y cuya utilización es muy sencilla: una vez importado el código, para serializar las llamadas sólo hay que llamarlo de la siguiente forma:
Si estás cansado de usar el innerHTML o crear los elementos HTML a manita uno a uno con javascript mediante DOM prueba DOMBuilder. Te permite crear elementos de una forma muy sencilla e intuitiva. Por ejemplo, para crear un formulario con dos campos, email y contraseña, bastaría el siguiente código:
var html = DomBuilder.apply();
var form = html.FORM(
html.DIV(
html.INPUT({type : 'text', name : 'email'}),
html.INPUT({type : 'text', name : 'password'}),
html.INPUT({type : 'submit'}),
)
);
document.body.appendChild(form);
Lo mejor es que la librería sólo ocupa 1Kb de los cuales 500 bytes son la información legal
Si has visto alguna vez el código fuente de GMail habrás observado que el código está compactado perfectamente para ahorrar ancho de banda y tiempo de descarga a los usuarios. En esta web hay una pequeña utilidad que se maneja en la línea de comandos y que permite hacer eso mismo, compactar cualquier javascript que tengas eliminando comentarios, retornos de carro, tabuladores, espacios innecesarios…
He cogido el código fuente y lo he traducido a javascript lo cual permite que se pueda ejecutar en un entorno más “acogedor”
<html>
<body>
<script language="javascript">
<!--
var theA;
var theB;
var entrada = "";
var out = "";
function in_read() {
if (entrada.length > 0) {
var ret = entrada.charAt(0);
entrada = entrada.substr(1);
return ret;
}
return -1;
}
function in_unread(character) {
entrada = character + entrada;
}
function out_write(character) {
out = out + character;
}
function get() {
var c = in_read();
if (c >= " " || c == "\n" || c == -1) {
return c;
}
if (c == "\r") {
return "\n";
}
return " ";
}
function peek() {
var lookaheadChar = in_read();
in_unread(lookaheadChar);
return lookaheadChar;
}
function next() {
var c = get();
if (c == "/") {
switch (peek()) {
case "/":
for (;;) {
c = get();
if (c <= "\n") {
return c;
}
}
case "*":
get();
for (;;) {
switch (get()) {
case "*":
if (peek() == "/") {
get();
return " ";
}
break;
case -1:
return;
}
}
default:
return c;
}
}
return c;
}
function action(d) {
switch (d) {
case 1:
out_write(theA);
case 2:
theA = theB;
if (theA == "\"" || theA == """) {
for (;;) {
out_write(theA);
theA = get();
if (theA == theB) {
break;
}
if (theA <= "\n") {
return;
}
if (theA == "\\") {
out_write(theA);
theA = get();
}
}
}
case 3:
theB = next();
if (theB == "/" && (theA == "(" || theA == "," || theA == "=")) {
out_write(theA);
out_write(theB);
for (;;) {
theA = get();
if (theA == "/") {
break;
} else if (theA == "\\") {
out_write(theA);
theA = get();
} else if (theA <= "\n") {
throw new UnterminatedRegExpLiteralException();
}
out_write(theA);
}
theB = next();
}
}
}
function jsmin() {
entrada = document.getElementById("js_source").value;
out = "";
theA = "\n";
action(3);
while (theA != -1) {
switch (theA) {
case " ":
if (isAlphanum(theB)) {
action(1);
} else {
action(2);
} break;
case "\n":
switch (theB) {
case "{":
case "[":
case "(":
case "+":
case "-":
action(1);
break;
case " ":
action(3);
break;
default:
if (isAlphanum(theB)) {
action(1);
} else {
action(2);
}
}
break;
default:
switch (theB) {
case " ":
if (isAlphanum(theA)) {
action(1);
break;
}
action(3);
break;
case "\n":
switch (theA) {
case "}":
case "]":
case ")":
case "+":
case "-":
case """:
case "\"":
action(1);
break;
default:
if (isAlphanum(theA)) {
action(1);
} else {
action(3);
}
}
break;
default:
action(1);
break;
}
}
}
document.getElementById("js_target").value = out;
}
function isAlphanum(c) {
return ((c >= "a" && c <= "z") ||
(c >= "0" && c <= "9") ||
(c >= "A" && c <= "Z") ||
c == "_" ||
c == "$" ||
c == "\\" ||
c > 126);
}
//-->
</script>
<textarea id="js_source" cols="60" rows="10"></textarea>
<br />
<input type="button" value="Minimiza!" onclick="jsmin();return false"/>
<br />
<textarea id="js_target" cols="60" rows="10"></textarea>
</body>
</html>
Como ejemplo, éste es el javascript ya compactado por él mismo, tiene una ganancia de casi el 50% de espacio:
<html>
<body>
<script language="javascript">
<!--
var theA;var theB;var entrada="";var out="";function in_read(){if(entrada.length>0){var ret=entrada.charAt(0);entrada=entrada.substr(1);return ret;}
return-1;}
function in_unread(character){entrada=character+entrada;}
function out_write(character){out=out+character;}
function get(){var c=in_read();if(c>=" "||c=="\n"||c==-1){return c;}
if(c=="\r"){return"\n";}
return" ";}
function peek(){var lookaheadChar=in_read();in_unread(lookaheadChar);return lookaheadChar;}
function next(){var c=get();if(c=="/"){switch(peek()){case"/":for(;;){c=get();if(c<="\n"){return c;}}
case"*":get();for(;;){switch(get()){case"*":if(peek()=="/"){get();return" ";}
break;case-1:return;}}
default:return c;}}
return c;}
function action(d){switch(d){case 1:out_write(theA);case 2:theA=theB;if(theA=="\""||theA=="""){for(;;){out_write(theA);theA=get();if(theA==theB){break;}
if(theA<="\n"){return;}
if(theA=="\\"){out_write(theA);theA=get();}}}
case 3:theB=next();if(theB=="/"&&(theA=="("||theA==","||theA=="=")){out_write(theA);out_write(theB);for(;;){theA=get();if(theA=="/"){break;}else if(theA=="\\"){out_write(theA);theA=get();}else if(theA<="\n"){throw new UnterminatedRegExpLiteralException();}
out_write(theA);}
theB=next();}}}
function jsmin(){entrada=document.getElementById("js_source").value;out="";theA="\n";action(3);while(theA!=-1){switch(theA){case" ":if(isAlphanum(theB)){action(1);}else{action(2);}break;case"\n":switch(theB){case"{":case"[":case"(":case"+":case"-":action(1);break;case" ":action(3);break;default:if(isAlphanum(theB)){action(1);}else{action(2);}}
break;default:switch(theB){case" ":if(isAlphanum(theA)){action(1);break;}
action(3);break;case"\n":switch(theA){case"}":case"]":case")":case"+":case"-":case""":case"\"":action(1);break;default:if(isAlphanum(theA)){action(1);}else{action(3);}}
break;default:action(1);break;}}}
document.getElementById("js_target").value=out;}
function isAlphanum(c){return((c>="a"&&c<="z")||(c>="0"&&c<="9")||(c>="A"&&c<="Z")||c=="_"||c=="$"||c=="\\"||c>126);}//-->
</script>
<textarea id="js_source" cols="40" rows="10"></textarea>
<br />
<input type="button" value="Minimiza!" onclick="jsmin();return false"/>
<br />
<textarea id="js_target" cols="40" rows="10"></textarea>
</body>
</html>
Si quieres hacer una prueba con tu propio código lo puedes hacer aquí:
Yahoo! ha dado un campanazo lanzando una librería javascript que permite la creación de clientes web “enriquecidos” con controles como árboles, calendarios, uso de ajax de forma simplificada, …
Todavía no he podido meterle mano pero tiene una pinta estupenda además de la documentación con la que viene. Por cierto, todo está bajo licencia BSD por lo que puede ser usado en proyectos propietarios sin ningún problema.
Puedes ver la página de la librería o ir a la página de patrones en donde encontrarás trucos sobre cómo hacer drag&drop, autocompletado, … y que, según indican, irán ampliando mes a mes. Por último te puedes dar una vuelta por el blog oficial donde sacarán más información acerca de todo este sistema.