2009-01-07 3 views
5

En essayant de rendre mon Javascript discret, j'utilise onLoad s pour ajouter des fonctionnalités à <input> s et autres. Avec Dojo, cela ressemble à quelque chose comme:Existe-t-il un équivalent Javascript de Ruby's andand?

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

Ou, environ équivalente:

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

Quelqu'un at-il écrit une implémentation de Ruby andand pour que je puisse faire ce qui suit?

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

ou

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

Répondre

2

La syntaxe exacte que vous voulez est impossible dans JavaScript. La façon dont JavaScript s'exécute devrait changer de manière assez fondamentale. Par exemple:

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 

Toutefois, JavaScript ne fonctionne pas de cette façon. Cela ne l'est tout simplement pas.

La ligne suivante réalise presque exactement ce que vous voulez.

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

Mais la lisibilité ne sera pas mise à l'échelle pour des exemples plus grands. Par exemple:

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

Et il y a l'effet secondaire de ces variables inutiles. J'utilise ces variables pour éviter la double recherche. Les variables sont déblayage le contexte, et si cela est une affaire énorme, vous pouvez utiliser les fonctions anonymes:

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

Maintenant, la variable utilisateur est nettoyé correctement, et tout le monde est heureux. Mais wow! quel tas de frappe! :)

+3

Ou utilisez [CoffeeScript] (http://jashkenas.github.com/coffee-script/#operators): regardez "la variante accesseur de l'opérateur existentiel" '? .' :) –

0

Pour autant que je sais qu'il n'y a pas une fonction JavaScript intégré qui a la même fonctionnalité. Je pense que la meilleure solution est de faire une requête par classe au lieu de id et d'utiliser dojo.forEach (...) car on vous garantira un élément non nul dans la fermeture forEach.

Vous pouvez toujours utiliser l'équivalent JavaScript:

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

La double-recherche est exactement ce que j'essaie d'éviter. Ce ne serait pas seulement pour dojo.byId; Les autres fonctions peuvent être plus lentes. –

0

Je ne l'ai jamais utilisé dojo, mais la plupart des cadres javascript (lorsqu'ils traitent avec les DOM) renvoient l'élément d'appel lorsqu'une méthode est appelée à partir de l'objet élément (Mauvaise formulation, désolé). So andand() serait implicite.

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

Sauf lorsque byId ne trouve pas l'élément demandé. Andand ne fera simplement rien, mais votre code tentera d'appeler onkeyup sur cet objet inexistant. –

1

Que diriez-vous quelque chose comme ceci:

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

Appel comme ceci:

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

Je ne sais pas Dojo, mais ne devrait pas votre premier exemple lire

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

Sinon, vous pourriez finir par essayer ng pour accéder à l'élément avant la construction du DOM.

Retour à votre question: En JavaScript, je andand() que mettre en œuvre

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

Votre exemple pourrait alors être écrit comme

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

qui est pas vraiment beaucoup plus court que d'utiliser la déclaration explicite if - alors pourquoi s'embêter?

0

Pour une liste:

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

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

Cela ne fonctionnera pas. andand est censé arrêter l'exécution si le tableau est nul. Bien sûr, si le tableau est nul, ce n'est plus un tableau. Par conséquent, la méthode andand n'est plus disponible. –

2

Vous voulez dojo.behavior.

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