2009-01-07 11 views
5

Al tratar de hacer que mi Javascript sea discreto, estoy usando onLoad s para agregar funcionalidad a <input> sy cosas por el estilo. Con Dojo, esto se ve algo como:¿Hay un equivalente en JavaScript de Ruby's andand?

var coolInput = dojo.byId('cool_input'); 
if(coolInput) { 
    dojo.addOnLoad(function() { 
    coolInput.onkeyup = function() { ... }; 
    }); 
} 

O, lo que es equivalente, aproximadamente:

dojo.addOnLoad(function() { 
    dojo.forEach(dojo.query('#cool_input'), function(elt) { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 

nadie ha escrito una implementación de Ruby andand para que yo pudiera hacer lo siguiente?

dojo.addOnLoad(function() { 
    // the input's onkeyup is set iff the input exists 
    dojo.byId('cool_input').andand().onkeyup = function() { ... }; 
}); 

o

dojo.byId('cool_input').andand(function(elt) { 
    // this function gets called with elt = the input iff it exists 
    dojo.addOnLoad(function() { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 

Respuesta

2

La sintaxis exacta que desea no es posible en JavaScript. La forma en que se ejecuta JavaScript tendría que cambiar de una manera bastante fundamental. Por ejemplo:

var name = getUserById(id).andand().name; 
//      ^
//      |------------------------------- 
// if getUserById returns null, execution MUST stop here | 
// otherwise, you'll get a "null is not an object" exception 

Sin embargo, JavaScript no funciona de esa manera. Simplemente no.

La siguiente línea realiza casi exactamente lo que desea.

var name = (var user = getUserById(id)) ? user.name : null; 

Pero la legibilidad no se escalará a ejemplos más grandes. Por ejemplo:

// this is what you want to see 
var initial = getUserById(id).andand().name.andand()[0]; 
// this is the best that JavaScript can do 
var initial = (var name = (var user = getUserById(id)) ? user.name : null) ? name[0] : null; 

Y existe el efecto secundario de esas variables innecesarias. Yo uso esas variables para evitar la doble búsqueda. Las variables están ensuciando el contexto, y si eso es un gran problema, puede utilizar funciones anónimas:

var name = (function() {return (var user = getUserById(id)) ? user.name : null;})(); 

Ahora, la variable de usuario se limpia en marcha correctamente, y todo el mundo es feliz. Pero ¡guau! ¡qué mucho tipeo! :)

+3

O use [CoffeeScript] (http://jashkenas.github.com/coffee-script/#operators): mire "la variante accesoria del operador existencial" '? .' :) –

0

Por lo que yo sé no hay una función integrada de JavaScript que tiene la misma funcionalidad. Creo que la mejor solución es consultar por clase en lugar de id y usar dojo.forEach (...) ya que se le garantizará un elemento no nulo en el cierre de forEach.

Siempre se puede utilizar el equivalente JavaScript:

dojo.byId('cool_input') && dojo.byId('cool_input').whateverYouWantToDo(...); 
+0

La doble búsqueda es exactamente lo que intento evitar. No sería solo para dojo.byId; otras funciones pueden ser mucho más lentas –

0

nunca he utilizado dojo, pero la mayoría Javascript marcos (cuando se trata de la DOM) devuelven el elemento que llama cuando un método es llamado desde el objeto elemento (Mala redacción, lo siento). Entonces andand() estaría implícito.

dojo.addOnLoad(function() { 
    dojo.byId('cool_input').onkeyup(function(evt) { /*event handler code*/ 
    }); 
}); 
+0

Excepto cuando byId no encuentra el elemento solicitado. Andand simplemente no hará nada, pero su código intentará invocar onkey en ese objeto inexistente. –

1

¿Qué tal algo como esto:

function andand(elt, f) { 
    if (elt) 
    return f(elt); 
    return null; 
} 

llamada así:

andand(dojo.byId('cool_input'), function(elt) { 
    // this function gets called with elt = the input iff it exists 
    dojo.addOnLoad(function() { 
    elt.onkeyup = function() { ... }; 
    }); 
}); 
3

No sé Dojo, pero no debe su primer ejemplo leer

dojo.addOnLoad(function() { 
    var coolInput = dojo.byId('cool_input'); 
    if(coolInput) 
     coolInput.onkeyup = function() { ... }; 
}); 

De lo contrario, podría terminar tryi ng para acceder al elemento antes de que se haya construido el DOM.

Volver a la pregunta: ¿En JavaScript, me gustaría implementar andand() como

function andand(obj, func, args) { 
    return obj && func.apply(obj, args || []); 
} 

Tu ejemplo podría entonces ser escrita como

dojo.addOnLoad(function() { 
    andand(dojo.byId('cool_input'), function() { 
     this.onkeyup = function() { ... }; 
    }); 
}); 

que no es realmente mucho más corto que el uso de la declaración explícita if - entonces, ¿por qué molestarse?

0

Para obtener una lista:

Array.prototype.andand = function(property, fn) { 

    if (this.filter(property).length > 0) this.map(fn); 
} 
+0

Esto no funcionará. y se supone que detiene la ejecución si la matriz es nula. Por supuesto, si la matriz es nula, ya no es una matriz. Por lo tanto, el método andand ya no está disponible. –

2

Quiere dojo.behavior.

dojo.behavior.add({ 
    '#cool_input': { 
     onKeyUp: function(evt) { ... } 
    } 
}); 
Cuestiones relacionadas