Having fun with Mooml & Twitter

Feb 19 2010 Published by Eneko Alonso under uncategorized

Mooml is a templating engine for Mootools. With it, you can create HTML from Javascript using a very clean syntax. Plus, it is extremely useful when you have to generate repeating elements, since Mooml automatically renders arrays of data multiple times. Let’s see an example.

Searching Twitter

Nowadays there are a lot of APIs out there that support JSON or JSONP, which we can use directly from the front end using Javascript. Also, there are other APIs that return tons of JS data, like Google Maps. In this example we are going to be searching Twitter and displaying the search results in a container div, properly rendered as HTML.

The url for searching Twitter is http://search.twitter.com/search.json?q=mootools&show_user=true (searching for Mootools in this case). Check the output:

  1. {
  2.   "results":[
  3.     {
  4.       "profile_image_url":"http://a3.twimg.com/profile_images/547672997/twitterProfilePhoto_normal.jpg",
  5.       "created_at":"Fri, 19 Feb 2010 17:08:55 +0000",
  6.       "from_user":"digitalr3bel",
  7.       "to_user_id":1212494,
  8.       "text":"@davidwalshblog Hi David – im a big fan of your site! Can you recommend a good MooTools tutorial for someone who can already program? thx",
  9.       "id":9343656026,
  10.       "from_user_id":23704390,
  11.       "to_user":"davidwalshblog",
  12.       "geo":null,
  13.       "iso_language_code":"en",
  14.       "source":"<a href="http://apiwiki.twitter.com/" rel="nofollow">API</a>"
  15.     }
  16.     // More results here…
  17.   ],
  18.   "max_id":9343656026,
  19.   "since_id":0,
  20.   "refresh_url":"?since_id=9343656026&q=mootools",
  21.   "next_page":"?page=2&max_id=9343656026&q=mootools",
  22.   "results_per_page":15,
  23.   "page":1,
  24.   "completed_in":0.0352710000000001,
  25.   "query":"mootools"
  26. }

We want to render each result inside out container div. On this example, we will just render the user name, user image and message text. Here is our Mooml template:

  1. Mooml.register('twitter-search-result', function(entry) {
  2.   div({id: "tweet-" + entry.id},
  3.     img({src: entry.profile_image_url, alt: entry.from_user}),
  4.     span(entry.from_user),
  5.     p(entry.text)
  6.   );
  7. });

Since all results are returned into an array, we can pass it directly to Mooml which will render all of the elements in it:

  1. // Data is the JSON response from Twitter
  2. Mooml.render('twitter-search-result', data.results);

So, let’s do a live test. Type something you want to search for and hit the search button to see Mooml in action :)

Search:

How cool is that?

The code

Ok, so here is the whole code I have used in this post for this mini-demo:

  1. <script type="text/javascript" src="http://enekoalonso.com/lib/mootools-1.2.4-core-nc.js"></script>
  2. <script type="text/javascript" src="http://enekoalonso.com/lib/mooml.js"></script>
  3. <script type="text/javascript">
  4. Mooml.register('twitter-search-result', function(entry) {
  5.   div({id: "tweet-" + entry.id},
  6.     img({src: entry.profile_image_url, alt: entry.from_user}),
  7.     span(entry.from_user),
  8.     p(entry.text)
  9.   );
  10. });
  11.  
  12. function searchTwitter() {
  13.   new Element('script', {
  14.     type:'text/javascript',
  15.     src:'http://search.twitter.com/search.json?q={text}&show_user=true&callback=renderData'.substitute({
  16.       text:$('twitter-mooml-search').get('value')
  17.     })
  18.   }).inject(document.head);
  19. }
  20.  
  21. function renderData(data) {
  22.   $('mooml-twitter-demo').empty().adopt(Mooml.render('twitter-search-result', data.results));
  23. }
  24.  
  25. $('twitter-mooml-search-btn').addEvent('click', searchTwitter);
  26. searchTwitter();

As you can see, the code is very basic and so is the Mooml template. The coolest thing here is that you don’t need to iterate over the results to render each element.

Have fun!

No responses yet

Mooml.globalize(): Mooml template functions going global

Feb 01 2010 Published by Eneko Alonso under uncategorized

Since version 1.0.9, Mooml includes a new feature: globalize. It maybe handy for some websites to globalize all the Mooml template functions (div, a, p, span…) to the window object scope, so they can be used anywhere in the code without the need of defining or evaluating a template.

For example, in normal Mootools code we would create a div like this:

  1.  // options can have attributes, css, events and more
  2. var mydiv = new Element('div', options);

With Mooml.globalize() we can do this:

  1. Mooml.globalize(); // Only need to call this once
  2. var mydiv = div(options); // Same options as Mootools new Element()

Mooml globalized functions can also have nested elements, which makes very easy to create dom elements:

  1. var mydiv = div(options,
  2.  p('First paragraph'),
  3.  p('Second paragraph'),
  4.  div('Nested div:',
  5.   span('div content')
  6.  ),
  7.  Mooml.render('nested_template'),
  8.  'Some <b>inline</b> <em>html</em> too'
  9. );

Will generate the dom elements for this html:

  1. <div>
  2.  <p>First paragraph</p>
  3.  <p>Second paragraph</p>
  4.  <div>Nested div:
  5.   <span>div content</span>
  6.  </div>
  7.  <!– nested template here –>
  8.  Some <b>inline</b> <em>html</em> too
  9. </div>

Elements created by Mooml template functions are not automatically injected in the DOM. They are just created like when you use new Element().

Please be aware that using Mooml.globalize() feature will pollute the window object scope, overriding any methods with the same name and/or possibly conflicting with other Javascript libraries. As a tip, Mooml.tags can be edited before calling Mooml.globalize(), so only functions for those tags we are interested on will be created.

No responses yet

Dojo y yo

Jan 28 2010 Published by Eneko Alonso under uncategorized

Back in November 2008 I had a chance to work with Dojo on a project for Cisco WebEx. I didn’t like it at all. I was used to the simplicity of jQuery and Mootools and I couldn’t understand how Dojo had been designed so complicated. Well, one year later I just realized that it is not that Dojo was that complicated. It is that I wasn’t ready for it. Now it is time to give it another chance.

Some cool stuff about Dojo

Reading Dojo’s documentation I have finally understood something that I was wondering how it works. It’s nothing really complicated, but it’s actually very cool: dojo.require

Javascript requests to the server are asynchronous (not sure if synchronous request can be done). So we depend on callback functions to continue the flow of your program. That means that when we put dojo.require('somefancyjs'); on a line, the execution does not stop and it continues to the next line of code while the browser downloads that file from the server in the background.

Looks like Dojo puts those requests on some kind of array, array that is checked when you use dojo.addOnLoad() which does not execute your callback function until all elements of the array have been downloaded. That is very cool because that means you can do as many dojo.require’s as you need. The down side is that you need to put your code inside a callback function, which is not very bad when working with objects.

Next, I have to find out how goog.require works ;)

No responses yet

Happy New Year 2010

Dec 31 2009 Published by Eneko Alonso under uncategorized

  1. (function(){
  2. t=[72,97,112,112,121,32,78,101,119,32,89,101,97,114,32,50,48,49,48];
  3. alert(String.fromCharCode.apply(null, t));
  4. })()

No responses yet

Creating HTML blocks with Mootools

Sep 02 2009 Published by Eneko Alonso under uncategorized

Sometimes we need to create HTML from JS. There are multiple ways to do this, from using innerHTML to creating element by element appending child to parents, setting attributes, etc. And there are as many different opinions about what is the right way to do it.

Meanwhile, once thing I missed from jQuery, not available on Mootools, was the ability to do something like this:

  1. var element = jQuery('<div id="foo">bar</div>');

In Mootools, the equivalent should be:

  1. var element = new Element('<div id="foo">bar</div>');

But that does not work.

On the Mootools mailing list, someone was asking about how to implement this and we just found a different approach, which instead of using the Element class, extends the String class like this:

  1. String.implement({
  2.  toElement: function() {
  3.    return new Element('div', {html:this}).getFirst();
  4.  }
  5. });

Now you can do this:

  1. var element  = '<div id="foo">bar</div>'.toElement();

To try it, paste this snippet on Firebug’s console:

  1. String.implement({
  2.  toElement: function() {
  3.    return new Element('div', {html:this}).getFirst();
  4.  }
  5. });
  6. console.log('<div id="foo">bar</div>'.toElement().get('id'));

Nice, uh? Of course, the HTML can be as complex as you need and where do you get the content of the string is up to you :)

3 responses so far

Bad practices writing Javascript & good tips for everyone

Aug 17 2009 Published by Eneko Alonso under uncategorized

I found specially interesting the use of document fragments.. Didn’t know about them before :)
http://james.padolsey.com/javascript/javascript-bad-practices/

No responses yet

Setters & Getters on Mootools classes

Jul 20 2009 Published by Eneko Alonso under uncategorized

Although I haven’t need them for my classes, I thought it would be very cool to have the possibility to use them. Setters and Getters are very popular in modern programming languages, since they let you do some actions when a member/property of an object is being accessed or modified. Setters and Getters are native on Javascript objects.

  1. // Setter on plain JS
  2. var b = {
  3.   saveCount: 0,
  4.   set count (c) {
  5.     console.log('Setting count (B):' + c);
  6.     this.saveCount = c;
  7.   },
  8.   get count () {
  9.     console.log('count is being accessed (B)');
  10.     return this.saveCount;
  11.   }
  12. }
  13. b.count = 5;
  14. console.log("Count (B): " + b.count);

Well, Mootools objects created using Class do not support that syntax. Fortunately, we can use the __defineSetter__ and __defineGetter__ functions:

  1. // Setter in Mootools
  2. var A = new Class({
  3.   saveCount: 0,
  4.   initialize: function() {
  5.     this.__defineSetter__("count", this.setCount);
  6.     this.__defineGetter__("count", this.getCount);
  7.   },
  8.   setCount: function(c) {
  9.     console.log('Setting count(A):' + c);
  10.     this.saveCount = c;
  11.   },
  12.   getCount: function() {
  13.     console.log('count is being accessed (A)');
  14.     return this.saveCount;
  15.   }
  16. });
  17.  
  18. var a = new A();
  19. a.count = 5;
  20. console.log("Count(A): " + a.count);

Nice, uh?

No responses yet

iPhone 3.0 geolocation with Javascript

Jun 30 2009 Published by Eneko Alonso under uncategorized

I was watching one of the video tutorials from Apple last night about some custom JS available on Safari, only on the iPhone 3.0, that let’s you interact with the phone and obtain data like the current location, etc.

So I built a little page to see how it works. I included Mootools 1.2.3 from Google servers and the Google Maps API. And voilá, with a few lines of code we have a totally functional web based GSP navigation system. A little bit ugly, but functional. Currenlty it only centers the map on the coordinates given by the phone, and also does a reverse geolocation to obtain the address (actually city, state and country). But it could be easily extended to add markers to the map, or even paths to track the movement.

If you have an iPhone (or an iPhone simulator) go to:
http://enekoalonso.com/research/iphone/geolocation.html

The source code:

  1. var Navigator = new Class({
  2.   initialize: function() {
  3.  
  4.     // Listen for position changes
  5.     this.watchId = navigator.geolocation.watchPosition(
  6.       function(position){ this.position(position) }.bind(this),
  7.       function() {},
  8.       { enableHighAccuracy: true, timeout: 1000, maximumAge: 10000 }
  9.     );
  10.     this.infoPanel = $('info');
  11.  
  12.     // Create the Geocoder and the Map
  13.     this.geocoder = new google.maps.Geocoder();
  14.     this.map = new google.maps.Map($('map'), {
  15.       zoom: 12,
  16.       mapTypeId: google.maps.MapTypeId.ROADMAP
  17.     });
  18.   },
  19.  
  20.   position: function(position) {
  21.     // Update labels
  22.     this.infoPanel.getElement('p.date').set('text', position.timestamp);
  23.     this.infoPanel.getElement('p.coords').set('text', position.coords.latitude + ', ' + position.coords.longitude);
  24.     this.infoPanel.getElement('p.altitude').set('text', position.coords.altitude);
  25.     this.infoPanel.getElement('p.heading').set('text', position.coords.heading);
  26.     this.infoPanel.getElement('p.speed').set('text', position.coords.speed);
  27.  
  28.     // Center map
  29.     var latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
  30.     this.map.set_center(latLng);
  31.  
  32.     // Reverse geolocation (get current address)
  33.     this.geocoder.geocode({'latLng': latLng},
  34.       function(results, status) {
  35.         if (google.maps.GeocoderStatus.OK) this.showAddress(results)
  36.       }.bind(this)
  37.     );
  38.   },
  39.  
  40.   showAddress: function(results) {
  41.     // console.dir(response);
  42.     if (results[1]) {
  43.       this.infoPanel.getElement('p.location').set('text', results[1].formatted_address);
  44.     }
  45.   }
  46. });
  47.  
  48. window.addEvent('load', function() {
  49.   new Navigator();
  50. });

Enjoy.

No responses yet

Sending messages between Javascript objects

Apr 23 2009 Published by Eneko Alonso under uncategorized

When applications (or websites) get pretty big, it usually happens that a lot of different objects or classes interact with each other or, even worst, depend on each other to achieve the site functionality.

A simple example could be a Tabs manager class, which controls a set of tabs in the page. Sometimes, the content in this tabs is sensitive to when the tabs are shown or hidden. At this point you have three options: either the Tabs class needs to know about the content or you create a set of callback functions or you use custom events. Still, for every one of these options you are going to need variables referencing the instances of your classes (this is: var myTabs = new Tabs())

Personally, I don’t like having global variables for the objects I create. I think the code gets very messy and complicated.

So, after dealing with all these issues at work day after day I thought it would be very cool to have a messaging system between my classes, the same way other languages like Cocoa do (in a more simpler way, at least for now).

Sending messages between classes

Wouldn’t it be nice if the Tabs class would send a message every time a new tab is selected? Wouldn’t it be nice if the objects that are going to reside inside those tabs could listen to that message and update accordingly?

To do this, I created a Base class and a Register, where my objects will register automatically upon instantiation (thanks to the Base class).

  1. var InstanceRegister = new Class({
  2.   instances: [],
  3.   addInstance: function(object) {
  4.     this.instances.push(object);
  5.   },
  6.   broadcastMessage: function(msg) {
  7.     $A(this.instances).each(function(item, index) {
  8.       item.processMessage(msg);
  9.     });
  10.   }
  11. });
  12. var Register = new InstanceRegister();
  13.  
  14. var Base = new Class({
  15.   ClassName: 'Base',
  16.   Implements: Options,
  17.   initialize: function(options) {
  18.     this.setOptions(options);
  19.     Register.addInstance(this);
  20.   },
  21.   processMessage: function(msg) {
  22.     console.log(this.ClassName, ' msg received: ');
  23.     console.dir(msg);
  24.   },
  25.   sendMessage: function(msg) {
  26.     Register.broadcastMessage(msg);
  27.   }
  28. });

As you can see, the register is just an array of Instances. Yes, Register is a global object, but it will be the only one we will need. Meanwhile, the Base class adds the new instance to the Register automatically. For convenience, the Base class has a sendMessage method. Also, for convenience, I like to add a ClassName property to all my classes in case I need it later for logging, instance class type identification, etc.

Now, thanks to MooTools, we can create our classes and make them inherit from Base. We can override the processMessages method and act accordingly:

  1. var Tabs = new Class({
  2.  ClassName: 'Tabs',
  3.  Extends: Base,
  4.  …
  5.  activateTab: function(tab) {
  6.   …
  7.   this.sendMessage({msg:'tabActivated', data:tab});
  8.  }
  9. });
  10.  
  11. var VideoPlayer = new Class({
  12.  ClassName: 'VideoPlayer',
  13.  Extends: Base,
  14.  …
  15.  processMessage: function(msg) {
  16.   if (msg.msg == 'tabActivated' && msg.data = 'video-tab') {
  17.    // Play video
  18.   }
  19.  }
  20. });

The beautifulness of this code resides, as I mentioned before, in the absence of any object references. Tabs doesn’t know anything about the VideoPlayer class nor any other object listening to the messages. And the VideoPlayer doesn’t know anything about the Tabs class either. It only knows about the message it has to listen to. No object references, no methods, no callbacks.

Pay attention now. This is the best part! Whenever we instance our classes, no matter how many times we do, we don’t need variable references anymore:

  1. new Tabs();
  2. new VideoPlayer();

Nice, uh?

Since I implemented this class I use it a lot on every project at work. It makes my life easier, keeping my classes simple and independent from each other. It’s even better. We have got to a point where we have integrated this feature with our Flash components, so these send messages to the Register when needed and any JS object listening reacts to them as needed.

By doing this, even being unidirectional (Flash to JS only), we have achieved something great: from now on, our Flash objects don’t need to know anything about our JS objects at all. Just send a message to the register and done.

At any point, even from Firebug, you can send a message to the Register. This is very nice, even for debugging:

  1. Register.broadcastMessage({msg:'hello',data:'world'});

A listener class

I found it is very nice, while in development, to have a Listener class debugging any message received. This way I don’t need to add a console.log call on all my classes to output received messages. The Listener will do it for me:

  1. var Listener = new Class({
  2.  Extends: Base,
  3.  initialize: function() {
  4.   this.parent();
  5.   this.ignoreMessages = false;
  6.  },
  7.  processMessage: function(msg) {
  8.   if (msg.msg == 'stopListener') this.ignoreMessages = true;
  9.   if (msg.msg == 'startListener') this.ignoreMessages = false;
  10.   if (this.ignoreMessages) return;
  11.   console.log('Listener: msg received:');
  12.   console.dir(msg);
  13.  }
  14. });
  15. new Listener();

Even you can control the Listener by sending custom messages to it! Awesome!

Could this be achieved with custom events?

With Mootools, creating custom events is piece of cake. But from what I understand, custom events work only inside the object that is firing them. This is, if object A fires an event ‘customEvent’, you can only listen to it if you add a callback function when you instantiate that class:

  1. var A = new Class({
  2.   Implements: Events,
  3.   initialize: function() {
  4.     document.body.addEvent('click', function() {
  5.       console.log('A: body clicked');
  6.       this.fireEvent('bodyClicked', [this]);
  7.     }.bind(this));
  8.   }
  9. });
  10.  
  11. var B = new Class({
  12.   doSomething: function() {
  13.     console.log('B: doing something…');
  14.   }
  15. });
  16.  
  17. new A({
  18.   onBodyClicked: function() {
  19.     // Tell B to do something (you need a reference to B!)
  20.   }
  21. });
  22. new B(); // Will never do something

Ideally, B should be able to listen to the bodyClicked event without passing any info when A is instantiated. But if I’m not mistaken, this is not possible.

Revised version

I decided that it would be cool to have the Messenger as something my classes could implement, instead of inherit from (Base). Also, it would be good if one object could register for a specific message only, which would improve performance too.

  1. var NotificationServiceCenter = new Class({
  2.  instances: {},
  3.  addObserver: function(msg, instance) {
  4.   if (!this.instances[msg]) {
  5.    this.instances[msg] = [];
  6.   }
  7.   this.instances[msg].push(instance);
  8.  },
  9.  broadcastMessage: function(msg, data) {
  10.   if (this.instances[msg]) {
  11.    $A(this.instances[msg]).each(function(item, index) {
  12.     item.processMessage(msg, data);
  13.    });
  14.   }
  15.  }
  16. });
  17. var NotificationService = new NotificationServiceCenter();
  18.  
  19. var Messenger = new Class({
  20.  addMsgEvent: function(msg) {
  21.   NotificationService.addObserver(msg, this);
  22.  },
  23.  sendMessage: function(msg, data) {
  24.   NotificationService.broadcastMessage(msg, data);
  25.  },
  26.  processMessage: function(msg, data) {
  27.   // For implementation on the final Class
  28.  }
  29. });
  30.  
  31. var A = new Class({
  32.  Implements: Messenger,
  33.  initialize: function() {
  34.   document.body.addEvent('click', function(){
  35.    console.log('A: document body clicked');
  36.    this.sendMessage('documentbodyclicked', 'Hello world!');
  37.   }.bind(this));
  38.  }
  39. });
  40.  
  41. var B = new Class({
  42.  Implements: Messenger,
  43.  initialize: function() {
  44.   this.addMsgEvent('documentbodyclicked');
  45.  },
  46.  processMessage: function(msg, data) {
  47.   console.log('B: msg received: ', data);
  48.  }
  49. });
  50.  
  51. new A();
  52. new B();

Here you go!

2 responses so far

Setting up timers and intervals inside JS objects

Apr 07 2009 Published by Eneko Alonso under uncategorized

It may seem trivial but it has its tricky point. Usually, in procedural Javascript (this is, non object oriented programming), timers are set up passing the callback function on a string:

  1. function hello() {
  2.   alert("hello");
  3. }
  4. // Will execute hello() after 10 seconds
  5. setTimeout('hello()', 10000);

For this code to work, hello() has to be a global function (actually a function of the window object). Otherwise, when the timer times out, it won’t find it.

When writing object oriented code, one would like to call a function inside the object itself, not a global function. We can achieve this passing an anonymous function to the setTimeout function that calls our function:

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     setTimeout(function() { this.hello(); }, 10000); // This wont work
  4.   },
  5.   hello: function() {
  6.     alert("hello");
  7.   }
  8. });

The previous code wont work, since this inside the anonymous function points to the window object and not to our instance of MyClass. We solve this using the bind function provided by Mootools:

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     setTimeout(function() { this.hello(); }.bind(this), 10000);
  4.   },
  5.   hello: function() {
  6.     alert("hello");
  7.   }
  8. });

This code will work fine, but it still has a big problem. If we wanted to access any member or function of our instance inside the hello() function, it wouldn’t work. This is because when the timer times out, the context of our instance is lost. Inside the hello() function, this will point to the window object.

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     this.text = 'hello';
  4.     setTimeout(function() { this.hello(); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text); // This wont work
  8.   }
  9. });

There are multiple ways to solve this issue but my favorite is to use the function call() of the function object. This function let’s you pass an object while calling your function that will become this inside it.

  1. var MyClass = new Class({
  2.   initialize: function() {
  3.     this.text = 'hello';
  4.     setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text);
  8.   }
  9. });

Now we can use this inside the hello() function and everything will work fine, no matter how many instances of MyClass we create.

  1. var MyClass = new Class({
  2.   initialize: function(text) {
  3.     this.text = text;
  4.     setTimeout(function() { this.hello.call(this); }.bind(this), 10000);
  5.   },
  6.   hello: function() {
  7.     alert(this.text);
  8.   }
  9. });
  10. new MyClass('hello');
  11. new MyClass('hi there!');
  12. new MyClass('wassup?');

Enjoy :)

2 responses so far

Next »