Posts tagged "mootools"
I write a lot of Python. I also write a lot of JavaScript. As I switch between
the two (often several times in a day) I sometimes find myself trying to do
something in one using the syntax of the other. The most common example is
joining a list.
# Python
' '.join(['foo', 'bar'])
// JavaScript
['foo', 'bar'].join(' ')
Often — as is the case above — the syntactical differences are minor, but
there are times when there's no direct translation.
MooTools, for example, adds the every method to the Array object.
This makes it possible to write some rather terse conditional statements.
var numbers = [87, 33, 21, 75];
if (numbers.every(function (n) { return n % 3 == 0; })) {
window.alert('The numbers are all divisible by 3.');
}
Python lists have no comparable method, so how would one write this in Python?
numbers = [87, 33, 21, 75]
if [n for n in numbers if n % 3 == 0] == numbers:
print 'The numbers are all divisible by 3.'
This approach involves using a list comprehension to create a list of numbers
which are divisible by 3, and comparing this list to numbers. If the lists
are equal, everything in numbers is divisible by 3.
Now for something a bit more challenging
Assume that we have a list of documents, and we want to know which of the
documents contain all the terms in a list of search terms.
// (MooTools) JavaScript
var terms = ['python', 'list', 'methods'], matches = [];
documents.each(function (document) {
if (terms.every(function (term) {
return document.body.indexOf(term) != -1;
})) matches.append(document);
});
Here, we could use the list comprehension approach as before.
# Python
terms = ['python', 'list', 'methods']
matches = []
for document in documents:
if [t for t in terms if document.body.find(t) != -1] == terms:
matches.append(document)
This is reasonably succinct, but not terribly efficient since each document is
checked for every search term. Given that we're not interested in documents
that lack even a single search term, it should be possible to rewrite this code
so that we don't waste time on lost causes.
It turns out that Python has just the thing for the job: in Python, a loop
statements may have an else clause!
terms = ['python', 'list', 'methods']
matches = []
for document in documents:
for term in terms:
if document.body.find(term) == -1:
break
else: # every term was found
matches.append(document)
From 4. More Control Flow Tools:
Loop statements may have an else clause; it is executed when the
loop terminates through exhaustion of the list (with for) or when
the condition becomes false (with while), but not when the loop is
terminated by a break statement.
I'm looking forward to finding more good spots to make use of else
clauses with my Python loops. :D
I've spent the afternoon creating a custom scrollbar for a products viewer
which utilizes CSS transitions, reflections, and other goodness.
Simple arithmetic dictates how long to make the scrollbar and where to position
it, but I could not get my theoretical calculations to play out in the browser.
It turns out that I'd been calling the wrong MooTools method. I'd been doing…
element.setStyle('left', offset);
rather than…
element.setPosition({ x: offset });
Frustratingly, setStyle('left', offset) appeared to work, but its behaviour
was unpredictable. I'm still confused by this, but at least I'm no longer
stuck.
Early this year I wrote a post titled
Auto-populating input fields with Prototype. Looking at the code now,
I realize that it's not very pretty. I'm rewriting this site's JavaScript
in MooTools, and the new code is quite a bit more elegant.
// provide input hints
window.addEvent('domready', function () {
$$('input[placeholder]').addEvents({
focus: function () {
if (this.hasClass('placeholder')) {
this.removeClass('placeholder').set('value', '');
}
},
blur: function () {
if (this.get('value') === '') {
this.addClass('placeholder').set('value', this.get('placeholder'));
}
}
}).fireEvent('blur');
});
I really appreciate the fact that MooTools provides addEvents in addition
to addEvent. As a result, the code above is clearer than a well-written
Prototype equivalent.
A reasonably common task is to determine whether a particular statement
evaluates as true for every item in a collection. Take list,
for example, an Array containing several numbers:
var list = [4, -1, 3, 2, 5];
One might wish to determine whether all the numbers in list are
positive. The required logic is as follows:
- assume that all the numbers in list are positive, then…
- loop through list until the assumption is proven to be false,
or until all items in list have been tested
In plain JavaScript, this can be achieved using a for loop…
var allPositive = true;
for (var i = 0; i < list.length; i++) {
if (list[i] <= 0) {
allPositive = false;
break;
}
}
… or a while loop (which is slightly more efficient).
var allPositive = true, i = list.length;
while (i--) {
if (list[i] <= 0) {
allPositive = false;
break;
}
}
Seriously, though, who is writing vanilla JavaScript in 2010? Everyone
and their grandmothers are using JavaScript frameworks these days, and there
are plenty of good ones out there. I recently made the switch to MooTools
from Prototype, after deciding that while jQuery is fantastic, the
MooTools philosophy is more to my liking.
With MooTools, one might consider using the Array object's each method
instead of a for or while loop.
var allPositive = true;
list.each(function (item) {
if (item <= 0) {
allPositive = false;
}
});
While this gets the job done, it's suboptimal for two reasons: the positiveness
of every item is evaluated, which will often not be necessary; and, well,
it ain't pretty. ;)
Enter every
As is so often the case in programming, if something seems fiddly and difficult
there's probably a better tool for the job. In this case the Array object's
every method is the perfect tool for the job.
var allPositive = list.every(function (item) {
return item > 0;
});
This is terser than is possible with vanilla JavaScript. It reads better too,
in my opinion!