diff --git a/app/demo.html b/app/demo.html index 197ae0c..f72d27c 100644 --- a/app/demo.html +++ b/app/demo.html @@ -7,6 +7,7 @@ Timetable.js demo + @@ -21,8 +22,11 @@

Timetable.js demo

+
+ + - diff --git a/app/scripts/plugin-date.js b/app/scripts/plugin-date.js new file mode 100644 index 0000000..8359dfa --- /dev/null +++ b/app/scripts/plugin-date.js @@ -0,0 +1,218 @@ +/*jshint -W079*/ + +'use strict'; + +var Datetable = function() { + this.scope = { + dateStart: new Date(2016, 9, 3), + dateEnd: new Date(2016, 9, 4) + }; + this.locations = []; + this.events = []; +}; + +Datetable.Renderer = function(tt) { + if (!(tt instanceof Datetable)) { + throw new Error('Initialize renderer using a Datetable'); + } + this.datetable = tt; +}; + +(function() { + function locationExistsIn(loc, locs) { + return locs.indexOf(loc) !== -1; + } + function isValidDateRange(start, end) { + var correctTypes = start instanceof Date && end instanceof Date; + var correctOrder = start < end; + return correctTypes && correctOrder; + } + function getDuration(startDate, endDate) { + return (new Date(endDate - startDate).getTime()); + } + + Datetable.prototype = { + setScope: function(start, end) { + if (isValidDateRange(start, end)) { + this.scope.dateStart = start; + this.scope.dateEnd = end; + } else { + throw new RangeError('Datetable scope should consist of (start, end) in Date format'); + } + + return this; + }, + addLocations: function(newLocations) { + function hasProperFormat() { + return newLocations instanceof Array; + } + + var existingLocations = this.locations; + + if (hasProperFormat()) { + newLocations.forEach(function(loc) { + if (!locationExistsIn(loc, existingLocations)) { + existingLocations.push(loc); + } else { + throw new Error('Location already exists'); + } + }); + } else { + throw new Error('Tried to add locations in wrong format'); + } + + return this; + }, + addEvent: function(name, location, start, end, options) { + if (!locationExistsIn(location, this.locations)) { + throw new Error('Unknown location'); + } + if (!isValidDateRange(start, end)) { + throw new Error('Invalid date range: ' + JSON.stringify([start, end])); + } + + var optionsHasValidType = Object.prototype.toString.call(options) === '[object Object]'; + + this.events.push({ + name: name, + location: location, + startDate: start, + endDate: end, + options: optionsHasValidType ? options : undefined + }); + + return this; + } + }; + + function emptyNode(node) { + while (node.firstChild) { + node.removeChild(node.firstChild); + } + } + + function prettyFormatDate(date) { + var monthName = ['Jan', 'Feb', 'Mar', 'Apr', + 'May', 'Jun', 'Jul', 'Aug', + 'Sep', 'Oct', 'Nov', 'Dec']; + var output = monthName[date.getMonth()] + ' ' + date.getDate(); + return output; + } + + Datetable.Renderer.prototype = { + draw: function(selector) { + function checkContainerPrecondition(container) { + if (container === null) { + throw new Error('Datetable container not found'); + } + } + function appendDatetableAside(container) { + var asideNode = container.appendChild(document.createElement('aside')); + var asideULNode = asideNode.appendChild(document.createElement('ul')); + appendRowHeaders(asideULNode); + } + function appendRowHeaders(ulNode) { + for (var k=0; k= datetable.scope.dateEnd) { + liNode = headerULNode.appendChild(document.createElement('li')); + spanNode = liNode.appendChild(document.createElement('span')); + spanNode.textContent = ''; + completed = true; + } + } + } + function appendDateRows(node) { + var ulNode = node.appendChild(document.createElement('ul')); + ulNode.className = 'room-timeline'; + for (var k=0; k