');
this.content.append(wrapper);
margin = parseInt(wrapper.css(isRtl ? 'margin-right' : 'margin-left'), 10);
wrapper.remove();
return margin;
},
_calculateTaskBorderWidth: function () {
var width;
var className = GanttView.styles.task + ' ' + GanttView.styles.taskSingle;
var task = $('
');
var computedStyle;
this.content.append(task);
computedStyle = kendo.getComputedStyles(task[0], ['border-left-width']);
width = parseFloat(computedStyle['border-left-width'], 10);
task.remove();
return width;
},
_renderTask: function (task, position) {
var taskWrapper;
var taskElement;
var editable = this.options.editable;
var progressHandleOffset;
var taskLeft = position.left;
var styles = GanttView.styles;
var wrapClassName = styles.taskWrap;
var calculatedSize = this.options.calculatedSize;
var dragHandleStyle = {};
var taskWrapAttr = {
className: wrapClassName,
style: { left: taskLeft + 'px' }
};
if (calculatedSize) {
taskWrapAttr.style.height = calculatedSize.cell + 'px';
}
if (task.summary) {
taskElement = this._renderSummary(task, position);
} else if (task.isMilestone()) {
taskElement = this._renderMilestone(task, position);
taskWrapAttr.className += ' ' + styles.taskMilestoneWrap;
} else {
taskElement = this._renderSingleTask(task, position);
}
taskWrapper = kendoDomElement('div', taskWrapAttr, [taskElement]);
if (editable) {
taskWrapper.children.push(kendoDomElement('div', { className: styles.taskDot + ' ' + styles.taskDotStart }));
taskWrapper.children.push(kendoDomElement('div', { className: styles.taskDot + ' ' + styles.taskDotEnd }));
}
if (!task.summary && !task.isMilestone() && editable && this._taskTemplate === null) {
progressHandleOffset = Math.round(position.width * task.percentComplete);
dragHandleStyle[isRtl ? 'right' : 'left'] = progressHandleOffset + 'px';
taskWrapper.children.push(kendoDomElement('div', {
className: styles.taskDragHandle,
style: dragHandleStyle
}));
}
return taskWrapper;
},
_renderSingleTask: function (task, position) {
var styles = GanttView.styles;
var progressWidth = Math.round(position.width * task.percentComplete);
var taskChildren = [];
var taskContent;
if (this._taskTemplate !== null) {
taskContent = kendoHtmlElement(this._taskTemplate(task));
} else {
taskContent = kendoTextElement(task.title);
taskChildren.push(kendoDomElement('div', {
className: styles.taskComplete,
style: { width: progressWidth + 'px' }
}));
}
var content = kendoDomElement('div', { className: styles.taskContent }, [kendoDomElement('div', { className: styles.taskTemplate }, [taskContent])]);
taskChildren.push(content);
if (this.options.editable) {
content.children.push(kendoDomElement('span', { className: styles.taskActions }, [kendoDomElement('a', {
className: styles.link + ' ' + styles.taskDelete,
href: '#'
}, [kendoDomElement('span', { className: styles.icon + ' ' + styles.iconDelete })])]));
content.children.push(kendoDomElement('span', { className: styles.taskResizeHandle + ' ' + styles.taskResizeHandleWest }));
content.children.push(kendoDomElement('span', { className: styles.taskResizeHandle + ' ' + styles.taskResizeHandleEast }));
}
var element = kendoDomElement('div', {
className: styles.task + ' ' + styles.taskSingle,
'data-uid': task.uid,
style: { width: Math.max(position.width - position.borderWidth * 2, 0) + 'px' }
}, taskChildren);
return element;
},
_renderMilestone: function (task) {
var styles = GanttView.styles;
var element = kendoDomElement('div', {
className: styles.task + ' ' + styles.taskMilestone,
'data-uid': task.uid
});
return element;
},
_renderSummary: function (task, position) {
var styles = GanttView.styles;
var progressWidth = Math.round(position.width * task.percentComplete);
var element = kendoDomElement('div', {
className: styles.task + ' ' + styles.taskSummary,
'data-uid': task.uid,
style: { width: position.width + 'px' }
}, [kendoDomElement('div', {
className: styles.taskSummaryProgress,
style: { width: progressWidth + 'px' }
}, [kendoDomElement('div', {
className: styles.taskSummaryComplete,
style: { width: position.width + 'px' }
})])]);
return element;
},
_renderResources: function (resources, className) {
var children = [];
var resource;
for (var i = 0, length = resources.length; i < length; i++) {
resource = resources[i];
children.push(kendoDomElement('span', {
className: className,
style: { 'color': resource.get('color') }
}, [kendoTextElement(resource.get('name'))]));
}
if (isRtl) {
children.reverse();
}
return children;
},
_taskPosition: function (task) {
var round = Math.round;
var startLeft = round(this._offset(isRtl ? task.end : task.start));
var endLeft = round(this._offset(isRtl ? task.start : task.end));
return {
left: startLeft,
width: endLeft - startLeft
};
},
_offset: function (date) {
var slots = this._timeSlots();
var slot;
var startOffset;
var slotDuration;
var slotOffset = 0;
var startIndex;
if (!slots.length) {
return 0;
}
startIndex = this._slotIndex('start', date);
slot = slots[startIndex];
if (slot.end < date) {
slotOffset = slot.offsetWidth;
} else if (slot.start <= date) {
startOffset = date - slot.start;
slotDuration = slot.end - slot.start;
slotOffset = startOffset / slotDuration * slot.offsetWidth;
}
if (isRtl) {
slotOffset = slot.offsetWidth + 1 - slotOffset;
}
return slot.offsetLeft + slotOffset;
},
_slotIndex: function (field, value, reverse) {
var slots = this._timeSlots();
var startIdx = 0;
var endIdx = slots.length - 1;
var middle;
if (reverse) {
slots = [].slice.call(slots).reverse();
}
do {
middle = Math.ceil((endIdx + startIdx) / 2);
if (slots[middle][field] < value) {
startIdx = middle;
} else {
if (middle === endIdx) {
middle--;
}
endIdx = middle;
}
} while (startIdx !== endIdx);
if (reverse) {
startIdx = slots.length - 1 - startIdx;
}
return startIdx;
},
_timeByPosition: function (x, snap, snapToEnd) {
var slot = this._slotByPosition(x);
if (snap) {
return snapToEnd ? slot.end : slot.start;
}
var offsetLeft = x - $(DOT + GanttView.styles.tasksTable).offset().left;
var duration = slot.end - slot.start;
var slotOffset = offsetLeft - slot.offsetLeft;
if (isRtl) {
slotOffset = slot.offsetWidth - slotOffset;
}
return new Date(slot.start.getTime() + duration * (slotOffset / slot.offsetWidth));
},
_slotByPosition: function (x) {
var offsetLeft = x - $(DOT + GanttView.styles.tasksTable).offset().left;
var slotIndex = this._slotIndex('offsetLeft', offsetLeft, isRtl);
return this._timeSlots()[slotIndex];
},
_renderDependencies: function (dependencies) {
var elements = [];
var tree = this._dependencyTree;
for (var i = 0, l = dependencies.length; i < l; i++) {
elements.push.apply(elements, this._renderDependency(dependencies[i]));
}
tree.render(elements);
},
_renderDependency: function (dependency) {
var predecessor = this._taskCoordinates[dependency.predecessorId];
var successor = this._taskCoordinates[dependency.successorId];
var elements;
var method;
if (!predecessor || !successor) {
return [];
}
method = '_render' + [
'FF',
'FS',
'SF',
'SS'
][isRtl ? 3 - dependency.type : dependency.type];
elements = this[method](predecessor, successor);
for (var i = 0, length = elements.length; i < length; i++) {
elements[i].attr['data-uid'] = dependency.uid;
}
return elements;
},
_renderFF: function (from, to) {
var lines = this._dependencyFF(from, to, false);
lines[lines.length - 1].children[0] = this._arrow(true);
return lines;
},
_renderSS: function (from, to) {
var lines = this._dependencyFF(to, from, true);
lines[0].children[0] = this._arrow(false);
return lines.reverse();
},
_renderFS: function (from, to) {
var lines = this._dependencyFS(from, to, false);
lines[lines.length - 1].children[0] = this._arrow(false);
return lines;
},
_renderSF: function (from, to) {
var lines = this._dependencyFS(to, from, true);
lines[0].children[0] = this._arrow(true);
return lines.reverse();
},
_dependencyFF: function (from, to, reverse) {
var that = this;
var lines = [];
var left = 0;
var top = 0;
var width = 0;
var height = 0;
var dir = reverse ? 'start' : 'end';
var delta;
var overlap = 2;
var arrowOverlap = 1;
var rowHeight = this._rowHeight;
var minLineWidth = 10;
var fromTop = from.rowIndex * rowHeight + Math.floor(rowHeight / 2) - 1;
var toTop = to.rowIndex * rowHeight + Math.floor(rowHeight / 2) - 1;
var styles = GanttView.styles;
var addHorizontal = function () {
lines.push(that._line(styles.line + ' ' + styles.lineHorizontal, {
left: left + 'px',
top: top + 'px',
width: width + 'px'
}));
};
var addVertical = function () {
lines.push(that._line(styles.line + ' ' + styles.lineVertical, {
left: left + 'px',
top: top + 'px',
height: height + 'px'
}));
};
left = from[dir];
top = fromTop;
width = minLineWidth;
delta = to[dir] - from[dir];
if (delta > 0 !== reverse) {
width = Math.abs(delta) + minLineWidth;
}
if (reverse) {
left -= width;
width -= arrowOverlap;
addHorizontal();
} else {
addHorizontal();
left += width - overlap;
}
if (toTop < top) {
height = top - toTop;
height += overlap;
top = toTop;
addVertical();
} else {
height = toTop - top;
height += overlap;
addVertical();
top += height - overlap;
}
width = Math.abs(left - to[dir]);
if (!reverse) {
width -= arrowOverlap;
left -= width;
}
addHorizontal();
return lines;
},
_dependencyFS: function (from, to, reverse) {
var that = this;
var lines = [];
var left = 0;
var top = 0;
var width = 0;
var height = 0;
var rowHeight = this._rowHeight;
var minLineHeight = Math.floor(rowHeight / 2);
var minLineWidth = 10;
var minDistance = 2 * minLineWidth;
var delta = to.start - from.end;
var overlap = 2;
var arrowOverlap = 1;
var fromTop = from.rowIndex * rowHeight + Math.floor(rowHeight / 2) - 1;
var toTop = to.rowIndex * rowHeight + Math.floor(rowHeight / 2) - 1;
var styles = GanttView.styles;
var addHorizontal = function () {
lines.push(that._line(styles.line + ' ' + styles.lineHorizontal, {
left: left + 'px',
top: top + 'px',
width: width + 'px'
}));
};
var addVertical = function () {
lines.push(that._line(styles.line + ' ' + styles.lineVertical, {
left: left + 'px',
top: top + 'px',
height: height + 'px'
}));
};
left = from.end;
top = fromTop;
width = minLineWidth;
if (reverse) {
left += arrowOverlap;
if (delta > minDistance) {
width = delta - (minLineWidth - overlap);
}
width -= arrowOverlap;
}
addHorizontal();
left += width - overlap;
if (delta <= minDistance) {
height = reverse ? Math.abs(toTop - fromTop) - minLineHeight : minLineHeight;
if (toTop < fromTop) {
top -= height;
height += overlap;
addVertical();
} else {
addVertical();
top += height;
}
width = from.end - to.start + minDistance;
if (width < minLineWidth) {
width = minLineWidth;
}
left -= width - overlap;
addHorizontal();
}
if (toTop < fromTop) {
height = top - toTop;
top = toTop;
height += overlap;
addVertical();
} else {
height = toTop - top;
addVertical();
top += height;
}
width = to.start - left;
if (!reverse) {
width -= arrowOverlap;
}
addHorizontal();
return lines;
},
_line: function (className, styles) {
return kendoDomElement('div', {
className: className,
style: styles
});
},
_arrow: function (direction) {
return kendoDomElement('span', { className: direction ? GanttView.styles.arrowWest : GanttView.styles.arrowEast });
},
_colgroup: function () {
var slots = this._timeSlots();
var count = slots.length;
var cols = [];
for (var i = 0; i < count; i++) {
for (var j = 0, length = slots[i].span; j < length; j++) {
cols.push(kendoDomElement('col'));
}
}
return kendoDomElement('colgroup', null, cols);
},
_createDragHint: function (element) {
this._dragHint = element.clone().addClass(GanttView.styles.dragHint).css('cursor', 'move');
element.parent().append(this._dragHint);
},
_updateDragHint: function (start) {
var left = this._offset(start);
this._dragHint.css({ 'left': left });
},
_removeDragHint: function () {
this._dragHint.remove();
this._dragHint = null;
},
_createResizeHint: function (task) {
var styles = GanttView.styles;
var taskTop = this._taskCoordinates[task.id].rowIndex * this._rowHeight;
var tooltipHeight;
var tooltipTop;
var options = this.options;
var messages = options.messages;
this._resizeHint = $(RESIZE_HINT({ styles: styles })).css({
'top': 0,
'height': this._contentHeight
});
this.content.append(this._resizeHint);
this._resizeTooltip = $(RESIZE_TOOLTIP_TEMPLATE({
styles: styles,
start: task.start,
end: task.end,
messages: messages.views,
format: options.resizeTooltipFormat
})).css({
'top': 0,
'left': 0
});
this.content.append(this._resizeTooltip);
this._resizeTooltipWidth = this._resizeTooltip.outerWidth();
tooltipHeight = this._resizeTooltip.outerHeight();
tooltipTop = taskTop - tooltipHeight;
if (tooltipTop < 0) {
tooltipTop = taskTop + this._rowHeight;
}
this._resizeTooltipTop = tooltipTop;
},
_updateResizeHint: function (start, end, resizeStart) {
var left = this._offset(isRtl ? end : start);
var right = this._offset(isRtl ? start : end);
var width = right - left;
var tooltipLeft = resizeStart !== isRtl ? left : right;
var tablesWidth = this._tableWidth - kendo.support.scrollbar();
var tooltipWidth = this._resizeTooltipWidth;
var options = this.options;
var messages = options.messages;
var tableOffset = $(DOT + GanttView.styles.tasksTable).offset().left - $(DOT + GanttView.styles.tasksWrapper).offset().left;
if (isRtl) {
left += tableOffset;
}
this._resizeHint.css({
'left': left,
'width': width
});
if (this._resizeTooltip) {
this._resizeTooltip.remove();
}
tooltipLeft -= Math.round(tooltipWidth / 2);
if (tooltipLeft < 0) {
tooltipLeft = 0;
} else if (tooltipLeft + tooltipWidth > tablesWidth) {
tooltipLeft = tablesWidth - tooltipWidth;
}
if (isRtl) {
tooltipLeft += tableOffset;
}
this._resizeTooltip = $(RESIZE_TOOLTIP_TEMPLATE({
styles: GanttView.styles,
start: start,
end: end,
messages: messages.views,
format: options.resizeTooltipFormat
})).css({
'top': this._resizeTooltipTop,
'left': tooltipLeft,
'min-width': tooltipWidth
}).appendTo(this.content);
},
_removeResizeHint: function () {
this._resizeHint.remove();
this._resizeHint = null;
this._resizeTooltip.remove();
this._resizeTooltip = null;
},
_updatePercentCompleteTooltip: function (top, left, text) {
this._removePercentCompleteTooltip();
var tooltip = this._percentCompleteResizeTooltip = $(PERCENT_RESIZE_TOOLTIP_TEMPLATE({
styles: GanttView.styles,
text: text
})).appendTo(this.element);
var tooltipMiddle = Math.round(tooltip.outerWidth() / 2);
var arrow = tooltip.find(DOT + GanttView.styles.callout);
var arrowHeight = Math.round(arrow.outerWidth() / 2);
tooltip.css({
'top': top - (tooltip.outerHeight() + arrowHeight),
'left': left - tooltipMiddle
});
arrow.css('left', tooltipMiddle - arrowHeight);
},
_removePercentCompleteTooltip: function () {
if (this._percentCompleteResizeTooltip) {
this._percentCompleteResizeTooltip.remove();
}
this._percentCompleteResizeTooltip = null;
},
_updateDependencyDragHint: function (from, to, useVML) {
this._removeDependencyDragHint();
if (useVML) {
this._creteVmlDependencyDragHint(from, to);
} else {
this._creteDependencyDragHint(from, to);
}
},
_creteDependencyDragHint: function (from, to) {
var styles = GanttView.styles;
var deltaX = to.x - from.x;
var deltaY = to.y - from.y;
var width = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var angle = Math.atan(deltaY / deltaX);
if (deltaX < 0) {
angle += Math.PI;
}
$('
').css({
'top': from.y,
'left': from.x,
'width': width,
'transform-origin': '0% 0',
'-ms-transform-origin': '0% 0',
'-webkit-transform-origin': '0% 0',
'transform': 'rotate(' + angle + 'rad)',
'-ms-transform': 'rotate(' + angle + 'rad)',
'-webkit-transform': 'rotate(' + angle + 'rad)'
}).appendTo(this.content);
},
_creteVmlDependencyDragHint: function (from, to) {
var hint = $('
').appendTo(this.content);
hint[0].outerHTML = hint[0].outerHTML;
},
_removeDependencyDragHint: function () {
this.content.find(DOT + GanttView.styles.dependencyHint).remove();
},
_createTaskTooltip: function (task, element, mouseLeft) {
var styles = GanttView.styles;
var options = this.options;
var content = this.content;
var contentOffset = content.offset();
var contentWidth = content.width();
var contentScrollLeft = kendo.scrollLeft(content);
var row = $(element).parents('tr').first();
var rowOffset = row.offset();
var template = options.tooltip && options.tooltip.template ? kendo.template(options.tooltip.template) : TASK_TOOLTIP_TEMPLATE;
var left = isRtl ? mouseLeft - (contentOffset.left + contentScrollLeft + kendo.support.scrollbar()) : mouseLeft - (contentOffset.left - contentScrollLeft);
var top = rowOffset.top + row.outerHeight() - contentOffset.top + content.scrollTop();
var tooltip = this._taskTooltip = $('
');
var tooltipWidth;
tooltip.css({
'left': left,
'top': top
}).appendTo(content).find(DOT + styles.taskContent).append(template({
styles: styles,
task: task,
messages: options.messages.views
}));
if (tooltip.outerHeight() < rowOffset.top - contentOffset.top) {
tooltip.css('top', rowOffset.top - contentOffset.top - tooltip.outerHeight() + content.scrollTop());
}
tooltipWidth = tooltip.outerWidth();
if (tooltipWidth + left - contentScrollLeft > contentWidth) {
left -= tooltipWidth;
if (left < contentScrollLeft) {
left = contentScrollLeft + contentWidth - (tooltipWidth + 17);
}
tooltip.css('left', left);
}
},
_removeTaskTooltip: function () {
if (this._taskTooltip) {
this._taskTooltip.remove();
}
this._taskTooltip = null;
},
_scrollTo: function (element) {
var elementLeft = element.offset().left;
var elementWidth = element.width();
var elementRight = elementLeft + elementWidth;
var row = element.closest('tr');
var rowTop = row.offset().top;
var rowHeight = row.height();
var rowBottom = rowTop + rowHeight;
var content = this.content;
var contentOffset = content.offset();
var contentTop = contentOffset.top;
var contentHeight = content.height();
var contentBottom = contentTop + contentHeight;
var contentLeft = contentOffset.left;
var contentWidth = content.width();
var contentRight = contentLeft + contentWidth;
var scrollbarWidth = kendo.support.scrollbar();
if (rowTop < contentTop) {
content.scrollTop(content.scrollTop() + (rowTop - contentTop));
} else if (rowBottom > contentBottom) {
content.scrollTop(content.scrollTop() + (rowBottom + scrollbarWidth - contentBottom));
}
if (elementLeft < contentLeft && elementWidth > contentWidth && elementRight < contentRight || elementRight > contentRight && elementWidth < contentWidth) {
content.scrollLeft(content.scrollLeft() + (elementRight + scrollbarWidth - contentRight));
} else if (elementRight > contentRight && elementWidth > contentWidth && elementLeft > contentLeft || elementLeft < contentLeft && elementWidth < contentWidth) {
content.scrollLeft(content.scrollLeft() + (elementLeft - contentLeft));
}
},
_timeSlots: function () {
if (!this._slots || !this._slots.length) {
return [];
}
return this._slots[this._slots.length - 1];
},
_headers: function (columnLevels) {
var rows = [];
var level;
var headers;
var column;
var headerText;
var styles = GanttView.styles;
for (var levelIndex = 0, levelCount = columnLevels.length; levelIndex < levelCount; levelIndex++) {
level = columnLevels[levelIndex];
headers = [];
for (var columnIndex = 0, columnCount = level.length; columnIndex < columnCount; columnIndex++) {
column = level[columnIndex];
headerText = kendoTextElement(column.text);
headers.push(kendoDomElement('th', {
colspan: column.span,
className: styles.header + (column.isNonWorking ? ' ' + styles.nonWorking : '')
}, [headerText]));
}
rows.push(kendoDomElement('tr', null, headers));
}
return rows;
},
_hours: function (start, end) {
var slotEnd;
var slots = [];
var options = this.options;
var workDayStart = options.workDayStart.getHours();
var workDayEnd = options.workDayEnd.getHours();
var isWorkHour;
var hours;
var hourSpan = options.hourSpan;
start = new Date(start);
end = new Date(end);
while (start < end) {
slotEnd = new Date(start);
hours = slotEnd.getHours();
isWorkHour = hours >= workDayStart && hours < workDayEnd;
slotEnd.setHours(slotEnd.getHours() + hourSpan);
if (hours == slotEnd.getHours()) {
slotEnd.setHours(slotEnd.getHours() + 2 * hourSpan);
}
if (!options.showWorkHours || isWorkHour) {
slots.push({
start: start,
end: slotEnd,
isNonWorking: !isWorkHour,
span: 1
});
}
start = slotEnd;
}
return slots;
},
_days: function (start, end) {
var slotEnd;
var slots = [];
var isWorkDay;
start = new Date(start);
end = new Date(end);
while (start < end) {
slotEnd = kendo.date.nextDay(start);
isWorkDay = this._isWorkDay(start);
if (!this.options.showWorkDays || isWorkDay) {
slots.push({
start: start,
end: slotEnd,
isNonWorking: !isWorkDay,
span: 1
});
}
start = slotEnd;
}
return slots;
},
_weeks: function (start, end) {
var slotEnd;
var slots = [];
var firstDay = this.calendarInfo().firstDay;
var daySlots;
var span;
start = new Date(start);
end = new Date(end);
while (start < end) {
slotEnd = kendo.date.dayOfWeek(kendo.date.addDays(start, 1), firstDay, 1);
if (slotEnd > end) {
slotEnd = end;
}
daySlots = this._days(start, slotEnd);
span = daySlots.length;
if (span > 0) {
slots.push({
start: daySlots[0].start,
end: daySlots[span - 1].end,
span: span
});
}
start = slotEnd;
}
return slots;
},
_months: function (start, end) {
var slotEnd;
var slots = [];
var daySlots;
var span;
start = new Date(start);
end = new Date(end);
while (start < end) {
slotEnd = new Date(start);
slotEnd.setMonth(slotEnd.getMonth() + 1);
daySlots = this._days(start, slotEnd);
span = daySlots.length;
if (span > 0) {
slots.push({
start: daySlots[0].start,
end: daySlots[span - 1].end,
span: span
});
}
start = slotEnd;
}
return slots;
},
_years: function (start, end) {
var slotEnd;
var slots = [];
start = new Date(start);
end = new Date(end);
while (start < end) {
slotEnd = new Date(start);
slotEnd.setFullYear(slotEnd.getFullYear() + 1);
slots.push({
start: start,
end: slotEnd,
span: 12
});
start = slotEnd;
}
return slots;
},
_slotHeaders: function (slots, template) {
var columns = [];
var slot;
for (var i = 0, l = slots.length; i < l; i++) {
slot = slots[i];
columns.push({
text: template(slot),
isNonWorking: !!slot.isNonWorking,
span: slot.span
});
}
return columns;
},
_isWorkDay: function (date) {
var day = date.getDay();
var workDays = this._workDays;
for (var i = 0, l = workDays.length; i < l; i++) {
if (workDays[i] === day) {
return true;
}
}
return false;
},
calendarInfo: function () {
return kendo.getCulture().calendars.standard;
},
_renderCurrentTime: function () {
var currentTime = this._getCurrentTime();
var timeOffset = this._offset(currentTime);
var element = $('
');
var viewStyles = GanttView.styles;
var tablesWrap = $(DOT + viewStyles.tasksWrapper);
var tasksTable = $(DOT + viewStyles.tasksTable);
var slot;
if (!this.content || !this._timeSlots().length) {
return;
}
this.content.find('.k-current-time').remove();
slot = this._timeSlots()[this._slotIndex('start', currentTime)];
if (currentTime < slot.start || currentTime > slot.end) {
return;
}
if (tablesWrap.length && tasksTable.length) {
timeOffset += tasksTable.offset().left - tablesWrap.offset().left;
}
element.css({
left: timeOffset + 'px',
top: '0px',
width: '1px',
height: this._contentHeight + 'px'
}).appendTo(this.content);
},
_getCurrentTime: function () {
return new Date();
},
_currentTime: function () {
var markerOptions = this.options.currentTimeMarker;
if (markerOptions !== false && markerOptions.updateInterval !== undefined) {
this._renderCurrentTime();
this._currentTimeUpdateTimer = setInterval(proxy(this._renderCurrentTime, this), markerOptions.updateInterval);
}
}
});
extend(true, GanttView, { styles: viewStyles });
kendo.ui.GanttDayView = GanttView.extend({
name: 'day',
options: {
timeHeaderTemplate: TIME_HEADER_TEMPLATE,
dayHeaderTemplate: DAY_HEADER_TEMPLATE,
resizeTooltipFormat: 'h:mm tt ddd, MMM d'
},
range: function (range) {
this.start = kendo.date.getDate(range.start);
this.end = kendo.date.getDate(range.end);
if (kendo.date.getMilliseconds(range.end) > 0 || this.end.getTime() === this.start.getTime()) {
this.end = kendo.date.addDays(this.end, 1);
}
},
_createSlots: function () {
var daySlots;
var daySlot;
var hourSlots;
var hours;
var slots = [];
daySlots = this._days(this.start, this.end);
hourSlots = [];
for (var i = 0, l = daySlots.length; i < l; i++) {
daySlot = daySlots[i];
hours = this._hours(daySlot.start, daySlot.end);
daySlot.span = hours.length;
hourSlots.push.apply(hourSlots, hours);
}
slots.push(daySlots);
slots.push(hourSlots);
return slots;
},
_layout: function () {
var rows = [];
var options = this.options;
rows.push(this._slotHeaders(this._slots[0], kendo.template(options.dayHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[1], kendo.template(options.timeHeaderTemplate)));
return rows;
}
});
kendo.ui.GanttWeekView = GanttView.extend({
name: 'week',
options: {
dayHeaderTemplate: DAY_HEADER_TEMPLATE,
weekHeaderTemplate: WEEK_HEADER_TEMPLATE,
resizeTooltipFormat: 'h:mm tt ddd, MMM d'
},
range: function (range) {
var calendarInfo = this.calendarInfo();
var firstDay = calendarInfo.firstDay;
var rangeEnd = range.end;
if (firstDay === rangeEnd.getDay()) {
rangeEnd.setDate(rangeEnd.getDate() + 7);
}
this.start = kendo.date.getDate(kendo.date.dayOfWeek(range.start, firstDay, -1));
this.end = kendo.date.getDate(kendo.date.dayOfWeek(rangeEnd, firstDay, 1));
},
_createSlots: function () {
var slots = [];
slots.push(this._weeks(this.start, this.end));
slots.push(this._days(this.start, this.end));
return slots;
},
_layout: function () {
var rows = [];
var options = this.options;
rows.push(this._slotHeaders(this._slots[0], kendo.template(options.weekHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[1], kendo.template(options.dayHeaderTemplate)));
return rows;
}
});
kendo.ui.GanttMonthView = GanttView.extend({
name: 'month',
options: {
weekHeaderTemplate: WEEK_HEADER_TEMPLATE,
monthHeaderTemplate: MONTH_HEADER_TEMPLATE,
resizeTooltipFormat: 'dddd, MMM d, yyyy'
},
range: function (range) {
this.start = kendo.date.firstDayOfMonth(range.start);
this.end = kendo.date.addDays(kendo.date.getDate(kendo.date.lastDayOfMonth(range.end)), 1);
},
_createSlots: function () {
var slots = [];
slots.push(this._months(this.start, this.end));
slots.push(this._weeks(this.start, this.end));
return slots;
},
_layout: function () {
var rows = [];
var options = this.options;
rows.push(this._slotHeaders(this._slots[0], kendo.template(options.monthHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[1], kendo.template(options.weekHeaderTemplate)));
return rows;
}
});
kendo.ui.GanttYearView = GanttView.extend({
name: 'year',
options: {
yearHeaderTemplate: YEAR_HEADER_TEMPLATE,
monthHeaderTemplate: MONTH_HEADER_TEMPLATE,
resizeTooltipFormat: 'dddd, MMM d, yyyy'
},
range: function (range) {
this.start = kendo.date.firstDayOfMonth(new Date(range.start.setMonth(0)));
this.end = kendo.date.firstDayOfMonth(new Date(range.end.setMonth(12)));
},
_createSlots: function () {
var slots = [];
var monthSlots = this._months(this.start, this.end);
$(monthSlots).each(function (index, slot) {
slot.span = 1;
});
slots.push(this._years(this.start, this.end));
slots.push(monthSlots);
return slots;
},
_layout: function () {
var rows = [];
var options = this.options;
rows.push(this._slotHeaders(this._slots[0], kendo.template(options.yearHeaderTemplate)));
rows.push(this._slotHeaders(this._slots[1], kendo.template(options.monthHeaderTemplate)));
return rows;
}
});
var timelineStyles = {
wrapper: 'k-timeline k-grid k-widget',
gridHeader: 'k-grid-header',
gridHeaderWrap: 'k-grid-header-wrap',
gridContent: 'k-grid-content',
gridContentWrap: 'k-grid-content',
tasksWrapper: 'k-gantt-tables',
dependenciesWrapper: 'k-gantt-dependencies',
task: 'k-task',
line: 'k-line',
taskResizeHandle: 'k-resize-handle',
taskResizeHandleWest: 'k-resize-w',
taskDragHandle: 'k-task-draghandle',
taskComplete: 'k-task-complete',
taskDelete: 'k-task-delete',
taskWrapActive: 'k-task-wrap-active',
taskWrap: 'k-task-wrap',
taskDot: 'k-task-dot',
taskDotStart: 'k-task-start',
taskDotEnd: 'k-task-end',
hovered: 'k-state-hover',
selected: 'k-state-selected',
origin: 'k-origin'
};
var GanttTimeline = kendo.ui.GanttTimeline = Widget.extend({
init: function (element, options) {
Widget.fn.init.call(this, element, options);
if (!this.options.views || !this.options.views.length) {
this.options.views = [
'day',
'week',
'month'
];
}
isRtl = kendo.support.isRtl(element);
this._wrapper();
this._domTrees();
this._views();
this._selectable();
this._draggable();
this._resizable();
this._percentResizeDraggable();
this._createDependencyDraggable();
this._attachEvents();
this._tooltip();
},
options: {
name: 'GanttTimeline',
messages: {
views: {
day: 'Day',
week: 'Week',
month: 'Month',
year: 'Year',
start: 'Start',
end: 'End'
}
},
snap: true,
selectable: true,
editable: true
},
destroy: function () {
Widget.fn.destroy.call(this);
clearTimeout(this._tooltipTimeout);
if (this._currentTimeUpdateTimer) {
clearInterval(this._currentTimeUpdateTimer);
}
this._unbindView(this._selectedView);
if (this._moveDraggable) {
this._moveDraggable.destroy();
}
if (this._resizeDraggable) {
this._resizeDraggable.destroy();
}
if (this._percentDraggable) {
this._percentDraggable.destroy();
}
if (this._dependencyDraggable) {
this._dependencyDraggable.destroy();
}
if (this.touch) {
this.touch.destroy();
}
this._headerTree = null;
this._taskTree = null;
this._dependencyTree = null;
this.wrapper.off(NS);
kendo.destroy(this.wrapper);
},
_wrapper: function () {
var styles = GanttTimeline.styles;
var that = this;
var options = this.options;
var calculateSize = function () {
var rowHeight = typeof options.rowHeight === STRING ? options.rowHeight : options.rowHeight + 'px';
var table = $(kendo.format(SIZE_CALCULATION_TEMPLATE, rowHeight));
var calculatedRowHeight;
var calculatedCellHeight;
var content = that.wrapper.find(DOT + styles.tasksWrapper);
content.append(table);
calculatedRowHeight = table.find('tr').outerHeight();
calculatedCellHeight = table.find('td').height();
table.remove();
return {
'row': calculatedRowHeight,
'cell': calculatedCellHeight
};
};
this.wrapper = this.element.addClass(styles.wrapper).append('
').append('
');
if (options.rowHeight) {
this._calculatedSize = calculateSize();
}
},
_domTrees: function () {
var styles = GanttTimeline.styles;
var tree = kendo.dom.Tree;
var wrapper = this.wrapper;
this._headerTree = new tree(wrapper.find(DOT + styles.gridHeaderWrap)[0]);
this._taskTree = new tree(wrapper.find(DOT + styles.tasksWrapper)[0]);
this._dependencyTree = new tree(wrapper.find(DOT + styles.dependenciesWrapper)[0]);
},
_views: function () {
var views = this.options.views;
var view;
var isSettings;
var name;
var defaultView;
var selected;
this.views = {};
for (var i = 0, l = views.length; i < l; i++) {
view = views[i];
isSettings = isPlainObject(view);
if (isSettings && view.selectable === false) {
continue;
}
name = isSettings ? typeof view.type !== 'string' ? view.title : view.type : view;
defaultView = defaultViews[name];
if (defaultView) {
if (isSettings) {
view.type = defaultView.type;
}
defaultView.title = this.options.messages.views[name];
}
view = extend({ title: name }, defaultView, isSettings ? view : {});
if (name) {
this.views[name] = view;
if (!selected || view.selected) {
selected = name;
}
}
}
if (selected) {
this._selectedViewName = selected;
}
},
view: function (name) {
if (name) {
this._selectView(name);
this.trigger('navigate', {
view: name,
action: 'changeView'
});
}
return this._selectedView;
},
_selectView: function (name) {
if (name && this.views[name]) {
if (this._selectedView) {
this._unbindView(this._selectedView);
}
this._selectedView = this._initializeView(name);
this._selectedViewName = name;
}
},
_viewByIndex: function (index) {
var view;
var views = this.views;
for (view in views) {
if (!index) {
return view;
}
index--;
}
},
_initializeView: function (name) {
var view = this.views[name];
if (view) {
var type = view.type;
if (typeof type === 'string') {
type = kendo.getter(view.type)(window);
}
if (type) {
view = new type(this.wrapper, trimOptions(extend(true, {
headerTree: this._headerTree,
taskTree: this._taskTree,
dependencyTree: this._dependencyTree,
calculatedSize: this._calculatedSize
}, view, this.options)));
} else {
throw new Error('There is no such view');
}
}
return view;
},
_unbindView: function (view) {
if (view) {
view.destroy();
}
},
_range: function (tasks) {
var startOrder = {
field: 'start',
dir: 'asc'
};
var endOrder = {
field: 'end',
dir: 'desc'
};
if (!tasks || !tasks.length) {
return {
start: new Date(),
end: new Date()
};
}
var start = new Query(tasks).sort(startOrder).toArray()[0].start || new Date();
var end = new Query(tasks).sort(endOrder).toArray()[0].end || new Date();
return {
start: new Date(start),
end: new Date(end)
};
},
_render: function (tasks) {
var view = this.view();
var range = this._range(tasks);
this._tasks = tasks;
view.range(range);
view.renderLayout();
view.render(tasks);
},
_renderDependencies: function (dependencies) {
this.view()._renderDependencies(dependencies);
},
_taskByUid: function (uid) {
var tasks = this._tasks;
var length = tasks.length;
var task;
for (var i = 0; i < length; i++) {
task = tasks[i];
if (task.uid === uid) {
return task;
}
}
},
_draggable: function () {
var that = this;
var element;
var task;
var currentStart;
var startOffset;
var snap = this.options.snap;
var styles = GanttTimeline.styles;
var cleanUp = function () {
that.view()._removeDragHint();
if (element) {
element.css('opacity', 1);
}
element = null;
task = null;
that.dragInProgress = false;
};
if (!this.options.editable) {
return;
}
this._moveDraggable = new kendo.ui.Draggable(this.wrapper, {
distance: 0,
filter: DOT + styles.task,
holdToDrag: kendo.support.mobileOS,
ignore: DOT + styles.taskResizeHandle
});
this._moveDraggable.bind('dragstart', function (e) {
var view = that.view();
element = e.currentTarget.parent();
task = that._taskByUid(e.currentTarget.attr('data-uid'));
if (that.trigger('moveStart', { task: task })) {
e.preventDefault();
return;
}
currentStart = task.start;
startOffset = view._timeByPosition(e.x.location, snap) - currentStart;
view._createDragHint(element);
element.css('opacity', 0.5);
clearTimeout(that._tooltipTimeout);
that.dragInProgress = true;
}).bind('drag', kendo.throttle(function (e) {
if (!that.dragInProgress) {
return;
}
var view = that.view();
var date = new Date(view._timeByPosition(e.x.location, snap) - startOffset);
var updateHintDate = date;
if (!that.trigger('move', {
task: task,
start: date
})) {
currentStart = date;
if (isRtl) {
updateHintDate = new Date(currentStart.getTime() + task.duration());
}
view._updateDragHint(updateHintDate);
}
}, 15)).bind('dragend', function () {
that.trigger('moveEnd', {
task: task,
start: currentStart
});
cleanUp();
}).bind('dragcancel', function () {
cleanUp();
}).userEvents.bind('select', function () {
blurActiveElement();
});
},
_resizable: function () {
var that = this;
var element;
var task;
var currentStart;
var currentEnd;
var resizeStart;
var snap = this.options.snap;
var styles = GanttTimeline.styles;
var cleanUp = function () {
that.view()._removeResizeHint();
element = null;
task = null;
that.dragInProgress = false;
};
if (!this.options.editable) {
return;
}
this._resizeDraggable = new kendo.ui.Draggable(this.wrapper, {
distance: 0,
filter: DOT + styles.taskResizeHandle,
holdToDrag: false
});
this._resizeDraggable.bind('dragstart', function (e) {
resizeStart = e.currentTarget.hasClass(styles.taskResizeHandleWest);
if (isRtl) {
resizeStart = !resizeStart;
}
element = e.currentTarget.closest(DOT + styles.task);
task = that._taskByUid(element.attr('data-uid'));
if (that.trigger('resizeStart', { task: task })) {
e.preventDefault();
return;
}
currentStart = task.start;
currentEnd = task.end;
that.view()._createResizeHint(task);
clearTimeout(that._tooltipTimeout);
that.dragInProgress = true;
}).bind('drag', kendo.throttle(function (e) {
if (!that.dragInProgress) {
return;
}
var view = that.view();
var date = view._timeByPosition(e.x.location, snap, !resizeStart);
if (resizeStart) {
if (date < currentEnd) {
currentStart = date;
} else {
currentStart = currentEnd;
}
} else {
if (date > currentStart) {
currentEnd = date;
} else {
currentEnd = currentStart;
}
}
if (!that.trigger('resize', {
task: task,
start: currentStart,
end: currentEnd
})) {
view._updateResizeHint(currentStart, currentEnd, resizeStart);
}
}, 15)).bind('dragend', function () {
that.trigger('resizeEnd', {
task: task,
resizeStart: resizeStart,
start: currentStart,
end: currentEnd
});
cleanUp();
}).bind('dragcancel', function () {
cleanUp();
}).userEvents.bind('select', function () {
blurActiveElement();
});
},
_percentResizeDraggable: function () {
var that = this;
var task;
var taskElement;
var taskElementOffset;
var timelineOffset;
var originalPercentWidth;
var maxPercentWidth;
var currentPercentComplete;
var tooltipTop;
var tooltipLeft;
var styles = GanttTimeline.styles;
var delta;
var cleanUp = function () {
that.view()._removePercentCompleteTooltip();
taskElement = null;
task = null;
that.dragInProgress = false;
};
var updateElement = function (width) {
taskElement.find(DOT + styles.taskComplete).width(width).end().siblings(DOT + styles.taskDragHandle).css(isRtl ? 'right' : 'left', width);
};
if (!this.options.editable) {
return;
}
this._percentDraggable = new kendo.ui.Draggable(this.wrapper, {
distance: 0,
filter: DOT + styles.taskDragHandle,
holdToDrag: false
});
this._percentDraggable.bind('dragstart', function (e) {
if (that.trigger('percentResizeStart')) {
e.preventDefault();
return;
}
taskElement = e.currentTarget.siblings(DOT + styles.task);
task = that._taskByUid(taskElement.attr('data-uid'));
currentPercentComplete = task.percentComplete;
taskElementOffset = taskElement.offset();
timelineOffset = this.element.offset();
originalPercentWidth = taskElement.find(DOT + styles.taskComplete).width();
maxPercentWidth = taskElement.outerWidth();
clearTimeout(that._tooltipTimeout);
that.dragInProgress = true;
}).bind('drag', kendo.throttle(function (e) {
if (!that.dragInProgress) {
return;
}
delta = isRtl ? -e.x.initialDelta : e.x.initialDelta;
var currentWidth = Math.max(0, Math.min(maxPercentWidth, originalPercentWidth + delta));
currentPercentComplete = Math.round(currentWidth / maxPercentWidth * 100);
updateElement(currentWidth);
tooltipTop = taskElementOffset.top - timelineOffset.top;
tooltipLeft = taskElementOffset.left + currentWidth - timelineOffset.left;
if (isRtl) {
tooltipLeft += maxPercentWidth - 2 * currentWidth;
}
that.view()._updatePercentCompleteTooltip(tooltipTop, tooltipLeft, currentPercentComplete);
}, 15)).bind('dragend', function () {
that.trigger('percentResizeEnd', {
task: task,
percentComplete: currentPercentComplete / 100
});
cleanUp();
}).bind('dragcancel', function () {
updateElement(originalPercentWidth);
cleanUp();
}).userEvents.bind('select', function () {
blurActiveElement();
});
},
_createDependencyDraggable: function () {
var that = this;
var originalHandle;
var hoveredHandle = $();
var hoveredTask = $();
var startX;
var startY;
var useVML = browser.msie && browser.version < 9;
var styles = GanttTimeline.styles;
var cleanUp = function () {
originalHandle.css('display', '').removeClass(styles.hovered);
originalHandle.parent().removeClass(styles.origin);
originalHandle = null;
toggleHandles(false);
hoveredTask = $();
hoveredHandle = $();
that.view()._removeDependencyDragHint();
that.dragInProgress = false;
};
var toggleHandles = function (value) {
if (!hoveredTask.hasClass(styles.origin)) {
hoveredTask.find(DOT + styles.taskDot).css('display', value ? 'block' : '');
hoveredHandle.toggleClass(styles.hovered, value);
}
};
if (!this.options.editable) {
return;
}
if (useVML && document.namespaces) {
document.namespaces.add('kvml', 'urn:schemas-microsoft-com:vml', '#default#VML');
}
this._dependencyDraggable = new kendo.ui.Draggable(this.wrapper, {
distance: 0,
filter: DOT + styles.taskDot,
holdToDrag: false
});
this._dependencyDraggable.bind('dragstart', function (e) {
if (that.trigger('dependencyDragStart')) {
e.preventDefault();
return;
}
originalHandle = e.currentTarget.css('display', 'block').addClass(styles.hovered);
originalHandle.parent().addClass(styles.origin);
var elementOffset = originalHandle.offset();
var tablesOffset = that.wrapper.find(DOT + styles.tasksWrapper).offset();
startX = Math.round(elementOffset.left - tablesOffset.left + originalHandle.outerHeight() / 2);
startY = Math.round(elementOffset.top - tablesOffset.top + originalHandle.outerWidth() / 2);
clearTimeout(that._tooltipTimeout);
that.dragInProgress = true;
}).bind('drag', kendo.throttle(function (e) {
if (!that.dragInProgress) {
return;
}
that.view()._removeDependencyDragHint();
var target = $(kendo.elementUnderCursor(e));
var tablesOffset = that.wrapper.find(DOT + styles.tasksWrapper).offset();
var currentX = e.x.location - tablesOffset.left;
var currentY = e.y.location - tablesOffset.top;
that.view()._updateDependencyDragHint({
x: startX,
y: startY
}, {
x: currentX,
y: currentY
}, useVML);
toggleHandles(false);
hoveredHandle = target.hasClass(styles.taskDot) ? target : $();
hoveredTask = target.closest(DOT + styles.taskWrap);
toggleHandles(true);
}, 15)).bind('dragend', function () {
if (hoveredHandle.length) {
var fromStart = originalHandle.hasClass(styles.taskDotStart);
var toStart = hoveredHandle.hasClass(styles.taskDotStart);
var type = fromStart ? toStart ? 3 : 2 : toStart ? 1 : 0;
var predecessor = that._taskByUid(originalHandle.siblings(DOT + styles.task).attr('data-uid'));
var successor = that._taskByUid(hoveredHandle.siblings(DOT + styles.task).attr('data-uid'));
if (predecessor !== successor) {
that.trigger('dependencyDragEnd', {
type: type,
predecessor: predecessor,
successor: successor
});
}
}
cleanUp();
}).bind('dragcancel', function () {
cleanUp();
}).userEvents.bind('select', function () {
blurActiveElement();
});
},
_selectable: function () {
var that = this;
var styles = GanttTimeline.styles;
if (this.options.selectable) {
this.wrapper.on(CLICK + NS, DOT + styles.task, function (e) {
e.stopPropagation();
if (!e.ctrlKey) {
that.trigger('select', { uid: $(this).attr('data-uid') });
} else {
that.trigger('clear');
}
}).on(CLICK + NS, DOT + styles.taskWrap, function (e) {
e.stopPropagation();
$(this).css('z-index', '0');
var target = $(document.elementFromPoint(e.clientX, e.clientY));
if (target.hasClass(styles.line)) {
target.click();
}
$(this).css('z-index', '');
}).on(CLICK + NS, DOT + styles.tasksWrapper, function () {
if (that.selectDependency().length > 0) {
that.clearSelection();
} else {
that.trigger('clear');
}
}).on(CLICK + NS, DOT + styles.line, function (e) {
e.stopPropagation();
that.selectDependency(this);
});
}
},
select: function (value) {
var element = this.wrapper.find(value);
var styles = GanttTimeline.styles;
if (element.length) {
this.clearSelection();
element.addClass(styles.selected);
if (kendo.support.mobileOS) {
element.parent().addClass(styles.taskWrapActive);
}
return;
}
return this.wrapper.find(DOT + styles.task + DOT + styles.selected);
},
selectDependency: function (value) {
var element = this.wrapper.find(value);
var uid;
var styles = GanttTimeline.styles;
if (element.length) {
this.clearSelection();
this.trigger('clear');
uid = $(element).attr('data-uid');
this.wrapper.find(DOT + styles.line + '[data-uid=\'' + uid + '\']').addClass(styles.selected);
return;
}
return this.wrapper.find(DOT + styles.line + DOT + styles.selected);
},
clearSelection: function () {
var styles = GanttTimeline.styles;
this.wrapper.find(DOT + styles.selected).removeClass(styles.selected);
if (kendo.support.mobileOS) {
this.wrapper.find(DOT + styles.taskWrapActive).removeClass(styles.taskWrapActive);
}
},
_attachEvents: function () {
var that = this;
var styles = GanttTimeline.styles;
if (this.options.editable) {
this._tabindex();
this.wrapper.on(CLICK + NS, DOT + styles.taskDelete, function (e) {
that.trigger('removeTask', { uid: $(this).closest(DOT + styles.task).attr('data-uid') });
e.stopPropagation();
e.preventDefault();
}).on(KEYDOWN + NS, function (e) {
var selectedDependency;
if (e.keyCode === keys.DELETE) {
selectedDependency = that.selectDependency();
if (selectedDependency.length) {
that.trigger('removeDependency', { uid: selectedDependency.attr('data-uid') });
that.clearSelection();
}
}
});
if (!kendo.support.mobileOS) {
this.wrapper.on(DBLCLICK + NS, DOT + styles.task, function (e) {
that.trigger('editTask', { uid: $(this).attr('data-uid') });
e.stopPropagation();
e.preventDefault();
});
} else {
this.touch = this.wrapper.kendoTouch({
filter: DOT + styles.task,
doubletap: function (e) {
that.trigger('editTask', { uid: $(e.touch.currentTarget).attr('data-uid') });
}
}).data('kendoTouch');
}
}
},
_tooltip: function () {
var that = this;
var tooltipOptions = this.options.tooltip;
var styles = GanttTimeline.styles;
var currentMousePosition;
var mouseMoveHandler = function (e) {
currentMousePosition = e.clientX;
};
if (tooltipOptions && tooltipOptions.visible === false) {
return;
}
if (!kendo.support.mobileOS) {
this.wrapper.on(MOUSEENTER + NS, DOT + styles.task, function () {
var element = this;
var task = that._taskByUid($(this).attr('data-uid'));
if (that.dragInProgress) {
return;
}
that._tooltipTimeout = setTimeout(function () {
that.view()._createTaskTooltip(task, element, currentMousePosition);
}, 800);
$(this).on(MOUSEMOVE, mouseMoveHandler);
}).on(MOUSELEAVE + NS, DOT + styles.task, function () {
clearTimeout(that._tooltipTimeout);
that.view()._removeTaskTooltip();
$(this).off(MOUSEMOVE, mouseMoveHandler);
});
} else {
this.wrapper.on(CLICK + NS, DOT + styles.taskDelete, function (e) {
e.stopPropagation();
that.view()._removeTaskTooltip();
}).on(MOUSELEAVE + NS, DOT + styles.task, function (e) {
var parents = $(e.relatedTarget).parents(DOT + styles.taskWrap, DOT + styles.task);
if (parents.length === 0) {
that.view()._removeTaskTooltip();
}
});
this.touch.bind('tap', function (e) {
var element = e.touch.target;
var task = that._taskByUid($(element).attr('data-uid'));
var currentPosition = e.touch.x.client;
if (that.view()._taskTooltip) {
that.view()._removeTaskTooltip();
}
that.view()._createTaskTooltip(task, element, currentPosition);
}).bind('doubletap', function () {
that.view()._removeTaskTooltip();
});
}
}
});
extend(true, GanttTimeline, { styles: timelineStyles });
}(window.kendo.jQuery));
return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
(a3 || a2)();
}));