Make Your JavaScript Data Model Smarter With Object Events

As today’s web applications continue to evolve and get more complex, it has become a lot more commonplace to keep a data model present inside of your javascript. You would then write various widgets, modules, or whatever that would get their data from the model, rather than querying some other web service independently (and if you aren’t doing this, you should!). While centralizing all your data into a nice, organized model that different parts of your code can access, it’s often a challenge to integrate an efficient way to notify the code that depends on these models when the stored data is updated. Lucky for us, Ryan Johnson has created a surprisingly small library that will allow our data model to notify anything that depends on it that it has updated (or loaded, or whatever you’d like in fact).

Before we dig in to the notifications, let’s do a little work to set up an example and some assumptions we’ll be operating under for the sake of this article. First, as prototype is my weapon of choice, that’s what we’ll be using. We’ll also be using prototype as Object.Event uses it as well! Now, let’s pretend that we have a website that has some social networking aspect of some kind. We want to display a short list of who’s currently online (say the 6 most recently active people) in some sort of side bar, and perhaps a count of the total members online in a footer element. Rather than having both these elements poll the server at some interval to update their information, let’s create a little data model that these areas can use instead.

Step 1 – Create a Data Model
For the sake of brevity, this will be stubbed out in a lot of places, but we’ll create enough functionality to get the concepts across.

var WhosOnlineSummary = Class.create(
{
initialize: function initialize()
{
this.totalOnlineUsers = 0;
this.whosOnline = new Hash();
this.loading = true;

// do our initial fetch
this.fetchUsers();

// set this up to poll for new data every thirty seconds…
this.dataPoller = new PeriodicalExecuter(function(pe)
{
this.fetchUsers();
}.bind(this), 30);
},

fetchUsers: function fetchUsers()
{
// this would probably do some other stuff too

new Ajax.Request(‘/your/data/service’,
{
onComplete: function(response)
{
this.update(response.responseText);
}.bind(this)
})
},

update: function update(data)
{
// and you’d have some sort of logic
// here to update the data… here’s a stub..

// I’m assuming the data returned is a JSON object here…

if(‘totalOnlineUsers’ in data)
{
this.totalOnlineUsers = data.totalOnlineUsers;
}

// and update our “who’s online” stuff…
if(‘onlineUsers’ in data)
{
// simple way to refresh, just kill the current list 🙂
this.whosOnline = new Hash();

// pretend online users is an array of json objects here…
// [ { id: userId, name: username, etc.}, {…}, … ]
data.onlineUsers.each(function(user)
{
this.whosOnline.set(user.id, user);
}.bind(this));
}

if(this.loading)
{
this.loading = false;
}
}
});

// get this globally namespaced… we’ll just declare it here for
// the sake of keeping things easy… you probably shouldn’t do
// this in real life 😉
var whosOnline = ”;

Event.observe(window, ‘load’, function() {
whosOnline = new WhosOnlineSummary();
});
OK, as you can see, we’ve got a very simple data model that updates itself every thirty seconds, and that our other “widgets” can easily tap into for their information. I’m not going to write these widgets out to any great extent, but I will create a small stub for the total online users functionality to help us out here.

Step 2 – Create Some Widgets
Now that we have a model, let’s start leveraging it to do something meaningful. As I just mentioned, this is only a stub, but it should give you a nice idea of where we’re going…

var TotalOnlineUsers = Class.create(
{
initialize: function(element)
{
this.domElement = element;

// any other useful variables could go here…

this.parseOnlineUsers();
},

parseOnlineUsers: function parseOnlineUsers()
{
// nice and simple 😉
this.domElement.update(‘Currently ‘ + whosOnline.totalOnlineUsers + ‘ users online’);
}
});

And now we’re essentially ready to do some fun stuff. As you can see, all this looks nice, but our TotalOnlineUsers widget has no way of knowing when it needs to update the display, as there’s no way to know when the data model has changed. Enter Object.Event…

Step 3 – Make Your Data Model Smart
So, we need to get our data model publishing events that our widgets can listen for. This is actually pretty darn simple since all the heavy lifting has been done for us. Let’s go ahead and leverage the power of Object.Event (I’ll provide download links at the end of this article). The first thing we need to do is provide the data model with the “event” functionality. This is a simple one-liner that we can put right after our class declaration. It looks like this:


if(this.loading)
{
this.loading = false;
}
}
});

Object.Event.extend(WhosOnlineSummary);

That’s it! Now, all that remains for us to do is to create events inside this object that can be observed (we’ll cover the actual observing shortly). This is done through simple additions of “notify” functions. Since we’ve extended our data model class, this is also a cinch. I’ll modify the update function to include two “events”:


update: function update(data)
{
// and you’d have some sort of logic
// here to update the data… here’s a stub..

// I’m assuming the data returned is a JSON object here…

if(‘totalOnlineUsers’ in data)
{
this.totalOnlineUsers = data.totalOnlineUsers;
}

// and update our “who’s online” stuff…
if(‘onlineUsers’ in data)
{
// simple way to refresh, just kill the current list 🙂
this.whosOnline = new Hash();

// pretend online users is an array of json objects here…
// [ { id: userId, name: username, etc.}, {…}, … ]
data.onlineUsers.each(function(user)
{
this.whosOnline.set(user.id, user);
}.bind(this));
}

if(this.loading)
{
this.loading = false;
this.notify(‘whosOnlineLoaded’);
}

this.notify(‘whosOnlineUpdate’);
}
…As you can see, we can create any custom events that we want, and we can name them whatever we want. Pretty cool stuff, huh? So, there’s only one thing that remains, and that’s making our widget listen for these events.

Step 4 – Make our Widgets Listen for Events
You’ll notice I created two events in our data model, but we’re only going to use one for this example. Let’s get right to it, as there’s no real need for explanation here…

var TotalOnlineUsers = Class.create(
{
initialize: function(element)
{
this.domElement = element;

// any other useful variables could go here…

// watch for updates from the data model
whoseOnline.observe(‘whosOnlineUpdate’, function()
{
this.parseOnlineUsers()
}.bind(this));

this.parseOnlineUsers();
},

parseOnlineUsers: function parseOnlineUsers()
{
// nice and simple 😉
this.domElement.update(‘Currently ‘ + whosOnline.totalOnlineUsers + ‘ users online’);
}
});

Wrapping Up
Hopefully, you can see the huge benefit of approaching your apps this way, and integrating Object.Event. If you’ll remember, our so-called page also has a who’s online list. You could create a widget that also observes the “whosOnlineUpdate” event, so it will update whenever the model changes as well. We’ve effectively made the load on the server smaller, since we’ve only got one thing calling our data service, instead of 2 (in this case, but I’m sure there are many practical applications that would have many more somewhat redundant calls). We also know that our presentation will be in sync across all the different elements on this page, which leads to a much slicker user experience. The best part of all this? We’ve made very, very small tweaks to our code, and they were very unobtrusive as well. Enjoy, and thank Ryan for his bad-ass javascript kung-fu if you’ve got a moment!

(sursa: www.webmonkey.com)
alte resurse:
http://livepipe.net/core>Object.Event – Created by Ryan Johnson
Prototype Framework

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s