It was a month ago when I found about Jaml, an excellent small Javascript library created by Ed Spencer which allows generating HTML code using very nice and clean templates. At work we use Mootools in most of our projects, so I thought it would be nice to improve Jaml by taking advantage of the power of Mootools. And this is the result.
Mooml: Mootools markup language
What is Mooml? Mooml is a templating system that allows generating HTML snippets very easily, without all the ugly nested “new Element” calls or string concatenation. With Mooml you can save templates for later use or evaluate snippets on the fly.
Download: http://mootools.net/forge/p/mooml
Source: http://github.com/eneko/mooml
Let’s see an example
Required HTML:
-
<div class="node">
-
<h2>Node Title</h2>
-
<p>Node body here.</p>
-
</div>
Node title and body are variables, so let’s save them on a Json format for now.
-
var data = {
-
title: 'Node Title',
-
body: 'Node body here'
-
}
Using Mootools “new Element” we would have to code something like this:
-
var el = new Element('div', {'class': 'node'}).adopt([
-
new Element('h2', {text: data.title}),
-
new Element('p', {text: data.body})
-
]);
That code is much better than plain Javascript, but still messy. We could use the new Elements.from included in Mootools More 1.2.4, but that would require us writing the html as a string, which rapidly gets messy concatenating variables, etc.
-
var el = Elements.from('<div class="node"><h2>' + data.title + '</h2><p>' + data.body + '</p></div>');
With Mooml…
With Mooml, we can create a template for that piece of code, and reuse it later as many times as we need:
-
Mooml.register('node', function(data) {
-
div({'class': 'node'},
-
h2(data.title),
-
p(data.body)
-
)
-
});
-
document.body.grab(Mooml.render('node', data));
We can also execute the template directly as a function:
-
document.body.grab(Mooml.templates.node(data));
Finally, with Mooml we can evaluate templates on the fly, without having to store them for later:
-
document.body.grab(Mooml.evaluate(function(data) {
-
div({'class': 'node'},
-
h2(data.title),
-
p(data.body)
-
)
-
}, data));
More examples soon :)
Today I got disappointed about Dojo. I had never used it before although I had seen code and I had hear good things about it. Bad things too, but I never though it was that bad. Currently I am working on a project for a client which has decided to normalize all their websites. And they have chosen Dojo. Since the website I was building was for the iPhone I decided not to use any library. It was none or Dojo. And everything went fine, because Safari is a very good browser and does things right.
But after that I had to build a desktop page for the same project. Of course, this will have to be compatible with all browsers, including IE6. And the pain started because IE6 doesn’t support the same functions than other browsers. That’s why using frameworks is so helpful. You forget about incompatibility issues. Well, that happens if you choose a good framework.
It happens than the only thing I haven’t found how to do is to get the absolute position of an element relative to its offset parent in IE6. So I said, well… let’s give it a try and use Dojo for this. After all, it would be a single line command:
-
var position = dojo.query(myelement).coords()[0];
Well… surprise! There is a bug in Dojo that makes it return the wrong coordinates on IE6. F%$K! The one thing I needed from Dojo does not work.
Long life Mootools!
If you are working with plain Javascript but still want to have some advantajes when dealing with element classes (element.className) you can write a small $ function like this:
-
var $ = function(element) {
-
this.element = element;
-
this.getClasses = function() {
-
return this.element.className.replace(/\s+/,' ').split(' ');
-
}
-
this.hasClass = function(className) {
-
var classes = this.getClasses();
-
return (classes.indexOf(className) > -1);
-
}
-
this.addClass = function(className) {
-
if (!this.hasClass(className)) {
-
this.element.className += (this.element.className ? ' ' :'') + className;
-
}
-
}
-
this.removeClass = function(className) {
-
if (this.hasClass(className)) {
-
var classes = this.getClasses();
-
classes.splice(classes.indexOf(className), 1);
-
this.element.className = classes.join(' ');
-
}
-
}
-
return this;
-
}
Then, once you have a variable that contains a DOM element, you can use it like this:
-
$(mydomelement).addClass('test');
-
if ($(mydomelement).hasClass('test')) alert('element has class test');
-
$(mydomelement).removeClass('test');
-
var classes = $(mydomelement).getClasses();
This will let you work with elements that have multiple classes very easily.