").append(record.users[type][user_id]));
}
}
tooltip += "" + $(this.options.container).data("label-" + type) + "
" + list[0].outerHTML;
}
}
}
return tooltip;
};
// Get tooltip for bars
Kanboard.Gantt.prototype.getBarTooltip = function(record) {
var tooltip = "";
if (record.not_defined) {
tooltip = $(this.options.container).data("label-not-defined");
}
else {
if (record.type == "task") {
tooltip = "" + record.progress + "
" +
$(this.options.container).data("label-assignee") + " " + (record.assignee ? record.assignee : '') + "
";
}
tooltip += $(this.options.container).data("label-start-date") + " " + $.datepicker.formatDate('yy-mm-dd', record.start) + "
";
tooltip += $(this.options.container).data("label-end-date") + " " + $.datepicker.formatDate('yy-mm-dd', record.end);
}
return tooltip;
};
// Set bar color
Kanboard.Gantt.prototype.setBarColor = function(block, record) {
if (record.not_defined) {
block.addClass("ganttview-block-not-defined");
}
else {
block.css("background-color", record.color.background);
block.css("border-color", record.color.border);
if (record.progress != "0%") {
block.append(jQuery("", {
"css": {
"z-index": 0,
"position": "absolute",
"top": 0,
"bottom": 0,
"background-color": record.color.border,
"width": record.progress,
"opacity": 0.4
}
}));
}
}
};
// Setup jquery-ui resizable
Kanboard.Gantt.prototype.listenForBlockResize = function(startDate) {
var self = this;
jQuery("div.ganttview-block", this.options.container).resizable({
grid: this.options.cellWidth,
handles: "e,w",
delay: 300,
stop: function() {
var block = jQuery(this);
self.updateDataAndPosition(block, startDate);
self.saveRecord(block.data("record"));
}
});
};
// Setup jquery-ui drag and drop
Kanboard.Gantt.prototype.listenForBlockMove = function(startDate) {
var self = this;
jQuery("div.ganttview-block", this.options.container).draggable({
axis: "x",
delay: 300,
grid: [this.options.cellWidth, this.options.cellWidth],
stop: function() {
var block = jQuery(this);
self.updateDataAndPosition(block, startDate);
self.saveRecord(block.data("record"));
}
});
};
// Update the record data and the position on the chart
Kanboard.Gantt.prototype.updateDataAndPosition = function(block, startDate) {
var container = jQuery("div.ganttview-slide-container", this.options.container);
var scroll = container.scrollLeft();
var offset = block.offset().left - container.offset().left - 1 + scroll;
var record = block.data("record");
// Restore color for defined block
record.not_defined = false;
this.setBarColor(block, record);
// Set new start date
var daysFromStart = Math.round(offset / this.options.cellWidth);
var newStart = this.addDays(this.cloneDate(startDate), daysFromStart);
record.start = newStart;
// Set new end date
var width = block.outerWidth();
var numberOfDays = Math.round(width / this.options.cellWidth) - 1;
record.end = this.addDays(this.cloneDate(newStart), numberOfDays);
if (record.type === "task" && numberOfDays > 0) {
jQuery("div.ganttview-block-text", block).text(record.progress);
}
// Update tooltip
block.attr("title", this.getBarTooltip(record));
block.data("record", record);
// Remove top and left properties to avoid incorrect block positioning,
// set position to relative to keep blocks relative to scrollbar when scrolling
block
.css("top", "")
.css("left", "")
.css("position", "relative")
.css("margin-left", offset + "px");
};
// Creates a 3 dimensional array [year][month][day] of every day
// between the given start and end dates
Kanboard.Gantt.prototype.getDates = function(start, end) {
var dates = [];
dates[start.getFullYear()] = [];
dates[start.getFullYear()][start.getMonth()] = [start];
var last = start;
while (this.compareDate(last, end) == -1) {
var next = this.addDays(this.cloneDate(last), 1);
if (! dates[next.getFullYear()]) {
dates[next.getFullYear()] = [];
}
if (! dates[next.getFullYear()][next.getMonth()]) {
dates[next.getFullYear()][next.getMonth()] = [];
}
dates[next.getFullYear()][next.getMonth()].push(next);
last = next;
}
return dates;
};
// Convert data to Date object
Kanboard.Gantt.prototype.prepareData = function(data) {
for (var i = 0; i < data.length; i++) {
var start = new Date(data[i].start[0], data[i].start[1] - 1, data[i].start[2], 0, 0, 0, 0);
data[i].start = start;
var end = new Date(data[i].end[0], data[i].end[1] - 1, data[i].end[2], 0, 0, 0, 0);
data[i].end = end;
}
return data;
};
// Get the start and end date from the data provided
Kanboard.Gantt.prototype.getDateRange = function(minDays) {
var minStart = new Date();
var maxEnd = new Date();
for (var i = 0; i < this.data.length; i++) {
var start = new Date();
start.setTime(Date.parse(this.data[i].start));
var end = new Date();
end.setTime(Date.parse(this.data[i].end));
if (i == 0) {
minStart = start;
maxEnd = end;
}
if (this.compareDate(minStart, start) == 1) {
minStart = start;
}
if (this.compareDate(maxEnd, end) == -1) {
maxEnd = end;
}
}
// Insure that the width of the chart is at least the slide width to avoid empty
// whitespace to the right of the grid
if (this.daysBetween(minStart, maxEnd) < minDays) {
maxEnd = this.addDays(this.cloneDate(minStart), minDays);
}
// Always start one day before the minStart
minStart.setDate(minStart.getDate() - 1);
return [minStart, maxEnd];
};
// Returns the number of day between 2 dates
Kanboard.Gantt.prototype.daysBetween = function(start, end) {
if (! start || ! end) {
return 0;
}
var count = 0, date = this.cloneDate(start);
while (this.compareDate(date, end) == -1) {
count = count + 1;
this.addDays(date, 1);
}
return count;
};
// Return true if it's the weekend
Kanboard.Gantt.prototype.isWeekend = function(date) {
return date.getDay() % 6 == 0;
};
// Clone Date object
Kanboard.Gantt.prototype.cloneDate = function(date) {
return new Date(date.getTime());
};
// Add days to a Date object
Kanboard.Gantt.prototype.addDays = function(date, value) {
date.setDate(date.getDate() + value * 1);
return date;
};
/**
* Compares the first date to the second date and returns an number indication of their relative values.
*
* -1 = date1 is lessthan date2
* 0 = values are equal
* 1 = date1 is greaterthan date2.
*/
Kanboard.Gantt.prototype.compareDate = function(date1, date2) {
if (isNaN(date1) || isNaN(date2)) {
throw new Error(date1 + " - " + date2);
} else if (date1 instanceof Date && date2 instanceof Date) {
return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0;
} else {
throw new TypeError(date1 + " - " + date2);
}
};