daybox.js | |
---|---|
Facebook - Code Assignment Daybox API 2012 Thomas Davis thomasalwyndavis@gmail.com | |
The Daybox API is wrapped in an AMD module. We use jQuery for rendering and Underscore for utils. | define([
'jquery',
'underscore'
], function($, _){ |
We are just setting a static width for this library matching the code assignment requirements | var dayboxWidth = 620; |
This module returns a constructor which returns an object containing the
events. e.g. | var DayBox = function (options) {
this.events = options.events || [];
this.events = layOutDay(this.events);
}; |
layOutDay()
| var layOutDay = function (events) {
|
Sort the stacks by the start time, to make calculations easier | events = _.sortBy(events, function(event){ return event.start; });
var columnCount = 0;
var stacks = [];
var stack = {end: 0}; |
Loop through each event | _.each(events, function(event, index){ |
Each event gets placed in a stack. A stack remembers how many columns there are currently overlapping and the latest end time. If the current event starts after the stack, we create a new stack containing the current event. | if(event.start >= stack.end || stacks.length === 0) {
stacks.push({columns: [{end: 0}], end: 0});
stack = _.last(stacks);
columnCount = 0;
};
|
Set the currents end date to the stacks end time if it is larger | if(event.end >stack.end) {
stack.end = event.end;
} |
We keep track of what column the event should be placed in. By default it assumes there will be a new column each time there is a new event | event.column = columnCount; |
Sometimes there will be room in previous columns and a new column won't be required. We loop through the previous columns to check if any have enough room. Each column has an end time so we don't overlap them. | var foundSparePlace = _.any(stack.columns, function(currentColumn, index) {
if(columnCount !== 0 && event.start > currentColumn.end) {
event.column = index;
return true;
}
}); |
Update the columns end time to the current events end time | stack.columns[event.column] = {
end: event.end
}; |
If we found a spare place in a previous column for the event we do not need to add a new column | if(!foundSparePlace) {
columnCount++;
} |
Attach the current stack to the current event so we can run some calcs | event.stack = stack;
}); |
Now that we have all the neccesary information, let's generate the appropriate output. | _.each(events, function(event) {
event.left = dayboxWidth / event.stack.columns.length * event.column;
event.width = dayboxWidth / event.stack.columns.length;
event.top = event.start;
delete event.column;
delete event.stack;
});
return events;
}; |
Daybox RenderingAfter instantiating a new Daybox object call | DayBox.prototype.render = function (options) {
_.each(this.events, function(event, index){
var eventElement = $('<div>').css({
left: event.left + 'px',
width: event.width + 'px',
height: event.end-event.start + 'px',
top: event.top + 'px'
});
eventElement.addClass('daybox-event');
eventElement.html(options.eventTemplate);
eventElement.appendTo('.daybox-container');
});
} |
return the constructor | return DayBox;
});
|