Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a Javascript equivalent of Ruby's andand?

In trying to make my Javascript unobtrusive, I'm using onLoads to add functionality to <input>s and such. With Dojo, this looks something like:

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

Or, approximately equivalently:

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

Has anyone written an implementation of Ruby's andand so that I could do the following?

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

or

dojo.byId('cool_input').andand(function(elt) {
  // this function gets called with elt = the input iff it exists
  dojo.addOnLoad(function() {
    elt.onkeyup = function() { ... };
  });
});
like image 419
James A. Rosen Avatar asked Jan 07 '09 22:01

James A. Rosen


People also ask

Is JavaScript and Ruby similar?

JavaScript and Ruby are object-oriented, dynamic and general-purpose scripting language, which is interpreted rather than compile during runtime. JavaScript can be used as front-end and back-end language using the same language, whereas Ruby is used as a back-end programming language.

What is a ruby hash in JavaScript?

A Hash is a dictionary-like collection of unique keys and their values. Also called associative arrays, they are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type. Hashes enumerate their values in the order that the corresponding keys were inserted.


2 Answers

I don't know Dojo, but shouldn't your first example read

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

Otherwise, you might end up trying to access the element before the DOM has been built.

Back to your question: In JavaScript, I'd implement andand() as

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

Your example could then be written as

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

which isn't really that much shorter than using the explicit if statement - so why bother?

like image 66
Christoph Avatar answered Oct 12 '22 06:10

Christoph


The exact syntax you want is not possible in JavaScript. The way JavaScript executes would need to change in a pretty fundamental fashion. For example:

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

However, JavaScript doesn't work that way. It simply doesn't.

The following line performs almost exactly what you want.

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

But readability won't scale to larger examples. For example:

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

And there is the side-effect of those unnecessary variables. I use those variables to avoid the double lookup. The variables are mucking up the context, and if that's a huge deal, you can use anonymous functions:

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

Now, the user variable is cleaned-up properly, and everybody's happy. But wow! what a lot of typing! :)

like image 28
harley.333 Avatar answered Oct 12 '22 05:10

harley.333