Creating a MSN Spaces Type Layout with Prototype

I’m really excited to share this bit of code with everyone, but, before I begin, let me start by saying I was planning to write a follow up to last weeks post on creating a web 2.0 form and adding IP to GEO location lookup etc, but I got distracted with Drag and Drop. I will continue that post next week.

The effect we want to create is a portal style windowed content system with drag and drop, much like MSN Spaces or now Live Spaces or the old My Yahoo! Click here to see the demo. By the end of this tutorial, you will have a good understanding on how to create this type of effect and port it into your own web application. It is not 100% complete. We will need a save layout method and a few other little things, but all in all, its not bad. Think of it like homework.

Okay, the problem. We want to display content in little windows, and give the user the ability to move the windows into any column they choose. We also want a way to provide the user the abiliy to chage the layout fron two colums to three or whatever the programmer defines. Since this isnt the 90’s, we are not going to do this from scratch. We’ll check out what libaries we could do this with, like YUI!, Dojo, or Script.aculo.us. Well, since I have focused all the other articles on Prototype, Script.aculo.us seems like the perfect choice.

Script.aculo.us provides a great drag and drop libary. We are actually going to use their sortables object, which extends the dragables object. We will basically create three lists and provide the user the ability drop onto any one of the lists.

Here we go…

We will create two objects: a layoutManager and a windowObject. The layoutManager will be responsible for creating the windows and displaying the layout or changing the layout. The windowObject will be responsible for actually rendering the window.

Lets start with the WindowObject and work backwards,


var windowObject = Class.create();

windowObject.prototype = {
initialize: function(id) {
this.id = id;
this.title = windows[id][0];
this.content = windows[id][1];
},

buildWindow: function() {
this.li = document.createElement('li');
var el = Builder.node('div',{className:'window'},[
Builder.node('span',{className:'handle'},this.title),
Builder.node('span',{className:'content'},this.content)
]);
this.li.appendChild(el);
return (this.li);
}
}

The window Object really only has one method, buildWindow. It creates a list item, a div, and two (2) spans. The actual window content is loaded in from the windows array deifined outside the object. The window is styled by the three (3) classes: window, handle, and content. As you can see, the content is loaded in here from a static variable. This should be changed to an ajax call and load in a file fragment rather then a string. Can we say homework assignment?

So this window array that defines the windows looks like this:

var windows = Array();
windows['blah'] = Array('Blah Window','Blah Content');
windows['foo'] = Array('Foo Window','Foo Content');
windows['bar'] = Array('Bar Window','Bar Content');

So we have created an associative array with three windows, and we use the ‘id’ as the key. Each element is an array and has two more elements: the windows title and the window content. This could be expanded to allow more information, such as window state, minimized, maximized, etc…

Moving along, lets break down the layoutManager Object.


layoutManager.prototype = {
initialize: function(type) {
this.type = type;
this.cols = Array();
},

// Defines the default set of windows to be displayed
addWindowSet: function(ws) {},

// Acutally writes out the layout and all the windows to the dest_id
drawLayout: function(dest_id) {},

// Used to change the layout, one paramater, a new layout type string.
changeLayout: function(type) {},

// These are helper functions, they are called from drawLayout()
makeSortable: function() {},
createColumn: function(colnum) {}

}

The constructor takes only one param, the layout type. The layout type is the type of layout we want to display, how many columns, and how big each column is (in percent). Lets take a look at that for a second. The layout type is a string that references a key in an array. I guess I could have just passed in the entire array, but I didn’t think about that until just now. Oh well… (more homework?)


var layoutTypes = Array();
layoutTypes['SymmetricTwoCol'] = Array(2,'50,50');
layoutTypes['RightHeavyTwoCol'] = Array(2,'30,70');
layoutTypes['LeftHeavyTwoCol'] = Array(2,'70,30');

var lm = new layoutManager("LeftHeavyTwoCol");

So the first method to call will be addWindowSet(ws); This is a string that defines the default set of windows to be displayed. The string will contain window id’s and be colon delimited and comma delimited. Colons delimit colums, and commas delimit windows. Here is our default window set.


var windowSet = "blah,foo:bar:blah";

Just a note here, and maybe an area for improvement. This above window set has three columns, and if we select a two column layout the third window is simply dropped.

The last thing we need to do is call the drawLayout(dest_id) method with the destination id.


lm.drawLayout('layout');

We are done. For all the little details, read through the source. If you have any questions, please comment below. If you like this article, Digg it or share it with a friend.

Download and Demo:
Click here to view the demo.
Click here to download the compete souce zip.

Leave a Reply

OpenID

Anonymous