').append(toggleButton).append(views).append(actionsWrap);
if (views.find('li').length > 1) {
views.prepend(VIEWBUTTONTEMPLATE({ styles: ganttStyles.toolbar }));
}
this.wrapper.prepend(toolbar);
this.toolbar = toolbar;
if (supportsMedia) {
this._mediaQueryHandler = proxy(handler, this);
this._mediaQuery = window.matchMedia('(max-width: 480px)');
this._mediaQuery.addListener(this._mediaQueryHandler);
}
toolbar.on(CLICK + NS, viewsSelector, function (e) {
e.preventDefault();
var list = that.list;
var name = $(this).attr(kendo.attr('name'));
var currentView = views.find(DOT + ganttStyles.toolbar.currentView);
if (currentView.is(':visible')) {
currentView.parent().toggleClass(ganttStyles.toolbar.expanded);
}
if (list.editable && list.editable.trigger('validate')) {
return;
}
if (!that.trigger('navigate', { view: name })) {
that.view(name);
}
}).on(CLICK + NS, pdfSelector, function (e) {
e.preventDefault();
that.saveAsPDF();
}).on(CLICK + NS, toggleSelector, function (e) {
e.preventDefault();
if (treelist.is(':visible')) {
treelist.css({
'display': 'none',
'width': '0'
});
timeline.css({
'display': 'inline-block',
'width': '100%'
});
that.refresh();
timeline.find(contentSelector).scrollTop(that.scrollTop);
} else {
timeline.css({
'display': 'none',
'width': 0
});
treelist.css({
'display': 'inline-block',
'width': '100%',
'max-width': 'none'
}).find(contentSelector).scrollTop(that.scrollTop);
}
that._resize();
});
this.wrapper.find(DOT + ganttStyles.toolbar.toolbar + ' li').hover(function () {
$(this).addClass(hoveredClassName);
}, function () {
$(this).removeClass(hoveredClassName);
});
},
_actions: function () {
var options = this.options;
var actions = options.toolbar;
var html = '';
if (!isArray(actions)) {
if (options.editable) {
actions = ['append'];
} else {
return html;
}
}
for (var i = 0, length = actions.length; i < length; i++) {
html += this._createButton(actions[i]);
}
return html;
},
_footer: function () {
if (!this.options.editable) {
return;
}
var ganttStyles = Gantt.styles.toolbar;
var messages = this.options.messages.actions;
var button = $(kendo.template(BUTTON_TEMPLATE)(extend(true, { styles: ganttStyles }, defaultCommands.append, { text: messages.append })));
var actionsWrap = $('
').append(button);
var footer = $('
').append(actionsWrap);
this.wrapper.append(footer);
this.footer = footer;
},
_createButton: function (command) {
var template = command.template || BUTTON_TEMPLATE;
var messages = this.options.messages.actions;
var commandName = typeof command === STRING ? command : command.name || command.text;
var className = defaultCommands[commandName] ? defaultCommands[commandName].className : 'k-gantt-' + (commandName || '').replace(/\s/g, '');
var options = {
iconClass: '',
action: '',
text: commandName,
className: className,
styles: Gantt.styles.toolbar
};
if (!commandName && !(isPlainObject(command) && command.template)) {
throw new Error('Custom commands should have name specified');
}
options = extend(true, options, defaultCommands[commandName], { text: messages[commandName] });
if (isPlainObject(command)) {
if (command.className && inArray(options.className, command.className.split(' ')) < 0) {
command.className += ' ' + options.className;
}
options = extend(true, options, command);
}
return kendo.template(template)(options);
},
_adjustDimensions: function () {
var element = this.element;
var ganttStyles = Gantt.styles;
var listSelector = DOT + ganttStyles.list;
var timelineSelector = DOT + ganttStyles.timeline;
var splitBarSelector = DOT + ganttStyles.splitBar;
var toolbarHeight = this.toolbar.outerHeight();
var footerHeight = this.footer ? this.footer.outerHeight() : 0;
var totalHeight = element.height();
var totalWidth = element.width();
var splitBarWidth = element.find(splitBarSelector).outerWidth();
var treeListWidth = element.find(listSelector).outerWidth();
element.children([
listSelector,
timelineSelector,
splitBarSelector
].join(',')).height(totalHeight - (toolbarHeight + footerHeight)).end().children(timelineSelector).width(totalWidth - (splitBarWidth + treeListWidth));
if (totalWidth < treeListWidth + splitBarWidth) {
element.find(listSelector).width(totalWidth - splitBarWidth);
}
},
_scrollTo: function (value) {
var view = this.timeline.view();
var list = this.list;
var attr = kendo.attr('uid');
var id = typeof value === 'string' ? value : value.closest('tr' + selector()).attr(attr);
var action;
var scrollTarget;
var scrollIntoView = function () {
if (scrollTarget.length !== 0) {
action();
}
};
if (view.content.is(':visible')) {
scrollTarget = view.content.find(selector(id));
action = function () {
view._scrollTo(scrollTarget);
};
} else {
scrollTarget = list.content.find(selector(id));
action = function () {
scrollTarget.get(0).scrollIntoView();
};
}
scrollIntoView();
},
_dropDowns: function () {
var that = this;
var actionsSelector = DOT + Gantt.styles.toolbar.actions;
var actionMessages = this.options.messages.actions;
var timeline = this.timeline;
var handler = function (e) {
var type = e.type;
var orderId;
var dataSource = that.dataSource;
var task = dataSource._createNewModel();
var selected = that.dataItem(that.select());
var parent = dataSource.taskParent(selected);
var firstSlot = timeline.view()._timeSlots()[0];
var target = type === 'add' ? selected : parent;
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
return;
}
task.set('title', 'New task');
if (target) {
task.set('parentId', target.get('id'));
task.set('start', target.get('start'));
task.set('end', target.get('end'));
} else {
task.set('start', firstSlot.start);
task.set('end', firstSlot.end);
}
if (type !== 'add') {
orderId = selected.get('orderId');
orderId = type === 'insert-before' ? orderId : orderId + 1;
}
that._createTask(task, orderId);
};
if (!this.options.editable) {
return;
}
this.footerDropDown = new TaskDropDown(this.footer.children(actionsSelector).eq(0), {
messages: { actions: actionMessages },
direction: 'up',
animation: { open: { effects: 'slideIn:up' } },
navigatable: that.options.navigatable
});
this.headerDropDown = new TaskDropDown(this.toolbar.children(actionsSelector).eq(0), {
messages: { actions: actionMessages },
navigatable: that.options.navigatable
});
this.footerDropDown.bind('command', handler);
this.headerDropDown.bind('command', handler);
},
_list: function () {
var that = this;
var navigatable = that.options.navigatable;
var ganttStyles = Gantt.styles;
var listWrapper = this.wrapper.find(DOT + ganttStyles.list);
var element = listWrapper.find('> div');
var toggleButtons = this.wrapper.find(DOT + ganttStyles.toolbar.actions + ' > button');
var options = {
columns: this.options.columns || [],
dataSource: this.dataSource,
selectable: this.options.selectable,
editable: this.options.editable,
resizable: this.options.resizable,
columnResizeHandleWidth: this.options.columnResizeHandleWidth,
listWidth: listWrapper.outerWidth(),
resourcesField: this.resources.field,
rowHeight: this.options.rowHeight
};
var columns = options.columns;
var column;
var restoreFocus = function () {
if (navigatable) {
that._current(that._cachedCurrent);
focusTable(that.list.content.find('table'), true);
}
delete that._cachedCurrent;
};
for (var i = 0; i < columns.length; i++) {
column = columns[i];
if (column.field === this.resources.field && typeof column.editor !== 'function') {
column.editor = proxy(this._createResourceEditor, this);
}
}
this.list = new kendo.ui.GanttList(element, options);
this.list.bind('render', function () {
that._navigatable();
}, true).bind('edit', function (e) {
that._cachedCurrent = e.cell;
if (that.trigger('edit', {
task: e.model,
container: e.cell
})) {
e.preventDefault();
}
}).bind('cancel', function (e) {
if (that.trigger('cancel', {
task: e.model,
container: e.cell
})) {
e.preventDefault();
}
restoreFocus();
}).bind('update', function (e) {
that._updateTask(e.task, e.updateInfo);
restoreFocus();
}).bind('change', function () {
that.trigger('change');
var selection = that.list.select();
if (selection.length) {
toggleButtons.removeAttr('data-action', 'add');
that.timeline.select('[data-uid=\'' + selection.attr('data-uid') + '\']');
} else {
toggleButtons.attr('data-action', 'add');
that.timeline.clearSelection();
}
}).bind('columnResize', function (e) {
that.trigger('columnResize', {
column: e.column,
oldWidth: e.oldWidth,
newWidth: e.newWidth
});
});
},
_timeline: function () {
var that = this;
var ganttStyles = Gantt.styles;
var options = trimOptions(extend(true, { resourcesField: this.resources.field }, this.options));
var element = this.wrapper.find(DOT + ganttStyles.timeline + ' > div');
var currentViewSelector = DOT + ganttStyles.toolbar.currentView + ' > ' + DOT + ganttStyles.toolbar.link;
this.timeline = new kendo.ui.GanttTimeline(element, options);
this.timeline.bind('navigate', function (e) {
var viewName = e.view.replace(/\./g, '\\.').toLowerCase();
var text = that.toolbar.find(DOT + ganttStyles.toolbar.views + ' > li').removeClass(ganttStyles.selected).end().find(DOT + ganttStyles.toolbar.viewButton + '-' + viewName).addClass(ganttStyles.selected).find(DOT + ganttStyles.toolbar.link).text();
that.toolbar.find(currentViewSelector).text(text);
that.refresh();
}).bind('moveStart', function (e) {
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
e.preventDefault();
return;
}
if (that.trigger('moveStart', { task: e.task })) {
e.preventDefault();
}
}).bind('move', function (e) {
var task = e.task;
var start = e.start;
var end = new Date(start.getTime() + task.duration());
if (that.trigger('move', {
task: task,
start: start,
end: end
})) {
e.preventDefault();
}
}).bind('moveEnd', function (e) {
var task = e.task;
var start = e.start;
var end = new Date(start.getTime() + task.duration());
if (!that.trigger('moveEnd', {
task: task,
start: start,
end: end
})) {
that._updateTask(that.dataSource.getByUid(task.uid), {
start: start,
end: end
});
}
}).bind('resizeStart', function (e) {
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
e.preventDefault();
return;
}
if (that.trigger('resizeStart', { task: e.task })) {
e.preventDefault();
}
}).bind('resize', function (e) {
if (that.trigger('resize', {
task: e.task,
start: e.start,
end: e.end
})) {
e.preventDefault();
}
}).bind('resizeEnd', function (e) {
var task = e.task;
var updateInfo = {};
if (e.resizeStart) {
updateInfo.start = e.start;
} else {
updateInfo.end = e.end;
}
if (!that.trigger('resizeEnd', {
task: task,
start: e.start,
end: e.end
})) {
that._updateTask(that.dataSource.getByUid(task.uid), updateInfo);
}
}).bind('percentResizeStart', function (e) {
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
e.preventDefault();
}
}).bind('percentResizeEnd', function (e) {
that._updateTask(that.dataSource.getByUid(e.task.uid), { percentComplete: e.percentComplete });
}).bind('dependencyDragStart', function (e) {
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
e.preventDefault();
}
}).bind('dependencyDragEnd', function (e) {
var dependency = that.dependencies._createNewModel({
type: e.type,
predecessorId: e.predecessor.id,
successorId: e.successor.id
});
that._createDependency(dependency);
}).bind('select', function (e) {
var editable = that.list.editable;
if (editable) {
editable.trigger('validate');
}
that.select('[data-uid=\'' + e.uid + '\']');
}).bind('editTask', function (e) {
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
return;
}
that.editTask(e.uid);
}).bind('clear', function () {
that.clearSelection();
}).bind('removeTask', function (e) {
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
return;
}
that.removeTask(that.dataSource.getByUid(e.uid));
}).bind('removeDependency', function (e) {
var editable = that.list.editable;
if (editable && editable.trigger('validate')) {
return;
}
that.removeDependency(that.dependencies.getByUid(e.uid));
});
},
_dataSource: function () {
var options = this.options;
var dataSource = options.dataSource;
dataSource = isArray(dataSource) ? { data: dataSource } : dataSource;
if (this.dataSource && this._refreshHandler) {
this.dataSource.unbind('change', this._refreshHandler).unbind('progress', this._progressHandler).unbind('error', this._errorHandler);
} else {
this._refreshHandler = proxy(this.refresh, this);
this._progressHandler = proxy(this._requestStart, this);
this._errorHandler = proxy(this._error, this);
}
this.dataSource = kendo.data.GanttDataSource.create(dataSource).bind('change', this._refreshHandler).bind('progress', this._progressHandler).bind('error', this._errorHandler);
},
_dependencies: function () {
var dependencies = this.options.dependencies || {};
var dataSource = isArray(dependencies) ? { data: dependencies } : dependencies;
if (this.dependencies && this._dependencyRefreshHandler) {
this.dependencies.unbind('change', this._dependencyRefreshHandler).unbind('error', this._dependencyErrorHandler);
} else {
this._dependencyRefreshHandler = proxy(this.refreshDependencies, this);
this._dependencyErrorHandler = proxy(this._error, this);
}
this.dependencies = kendo.data.GanttDependencyDataSource.create(dataSource).bind('change', this._dependencyRefreshHandler).bind('error', this._dependencyErrorHandler);
},
_resources: function () {
var resources = this.options.resources;
var dataSource = resources.dataSource || {};
this.resources = {
field: 'resources',
dataTextField: 'name',
dataColorField: 'color',
dataFormatField: 'format'
};
extend(this.resources, resources);
this.resources.dataSource = kendo.data.DataSource.create(dataSource);
},
_assignments: function () {
var assignments = this.options.assignments;
var dataSource = assignments.dataSource || {};
if (this.assignments) {
this.assignments.dataSource.unbind('change', this._assignmentsRefreshHandler);
} else {
this._assignmentsRefreshHandler = proxy(this.refresh, this);
}
this.assignments = {
dataTaskIdField: 'taskId',
dataResourceIdField: 'resourceId',
dataValueField: 'value'
};
extend(this.assignments, assignments);
this.assignments.dataSource = kendo.data.DataSource.create(dataSource);
this.assignments.dataSource.bind('change', this._assignmentsRefreshHandler);
},
_createEditor: function () {
var that = this;
var editor = this._editor = new PopupEditor(this.wrapper, extend({}, this.options, {
target: this,
resources: {
field: this.resources.field,
editor: proxy(this._createResourceEditor, this)
},
createButton: proxy(this._createPopupButton, this)
}));
editor.bind('cancel', function (e) {
var task = that.dataSource.getByUid(e.model.uid);
if (that.trigger('cancel', {
container: e.container,
task: task
})) {
e.preventDefault();
return;
}
that.cancelTask();
}).bind('edit', function (e) {
var task = that.dataSource.getByUid(e.model.uid);
if (that.trigger('edit', {
container: e.container,
task: task
})) {
e.preventDefault();
}
}).bind('save', function (e) {
var task = that.dataSource.getByUid(e.model.uid);
that.saveTask(task, e.updateInfo);
}).bind('remove', function (e) {
that.removeTask(e.model.uid);
});
},
_createResourceEditor: function (container, options) {
var that = this;
var model = options instanceof ObservableObject ? options : options.model;
var id = model.get('id');
var messages = this.options.messages;
var resourcesField = that.resources.field;
var editor = this._resourceEditor = new ResourceEditor(container, {
resourcesField: resourcesField,
data: this._wrapResourceData(id),
model: model,
messages: extend({}, messages.editor),
buttons: [
{
name: 'update',
text: messages.save,
className: Gantt.styles.primary
},
{
name: 'cancel',
text: messages.cancel
}
],
createButton: proxy(this._createPopupButton, this),
save: function (e) {
that._updateAssignments(e.model.get('id'), e.model.get(resourcesField));
}
});
editor.open();
},
_createPopupButton: function (command) {
var commandName = command.name || command.text;
var options = {
className: Gantt.styles.popup.button + ' k-gantt-' + (commandName || '').replace(/\s/g, ''),
text: commandName,
attr: ''
};
if (!commandName && !(isPlainObject(command) && command.template)) {
throw new Error('Custom commands should have name specified');
}
if (isPlainObject(command)) {
if (command.className) {
command.className += ' ' + options.className;
}
options = extend(true, options, command);
}
return kendo.template(COMMAND_BUTTON_TEMPLATE)(options);
},
view: function (type) {
return this.timeline.view(type);
},
dataItem: function (value) {
if (!value) {
return null;
}
var list = this.list;
var element = list.content.find(value);
return list._modelFromElement(element);
},
setDataSource: function (dataSource) {
this.options.dataSource = dataSource;
this._dataSource();
this.list._setDataSource(this.dataSource);
if (this.options.autoBind) {
dataSource.fetch();
}
},
setDependenciesDataSource: function (dependencies) {
this.options.dependencies = dependencies;
this._dependencies();
if (this.options.autoBind) {
dependencies.fetch();
}
},
items: function () {
return this.wrapper.children('.k-task');
},
_updateAssignments: function (id, resources) {
var dataSource = this.assignments.dataSource;
var taskId = this.assignments.dataTaskIdField;
var resourceId = this.assignments.dataResourceIdField;
var hasMatch = false;
var assignments = new Query(dataSource.view()).filter({
field: taskId,
operator: 'eq',
value: id
}).toArray();
var assignment;
var resource;
var value;
while (assignments.length) {
assignment = assignments[0];
for (var i = 0, length = resources.length; i < length; i++) {
resource = resources[i];
if (assignment.get(resourceId) === resource.get('id')) {
value = resources[i].get('value');
this._updateAssignment(assignment, value);
resources.splice(i, 1);
hasMatch = true;
break;
}
}
if (!hasMatch) {
this._removeAssignment(assignment);
}
hasMatch = false;
assignments.shift();
}
for (var j = 0, newLength = resources.length; j < newLength; j++) {
resource = resources[j];
this._createAssignment(resource, id);
}
dataSource.sync();
},
cancelTask: function () {
var editor = this._editor;
var container = editor.container;
if (container) {
editor.close();
}
},
editTask: function (uid) {
var task = typeof uid === 'string' ? this.dataSource.getByUid(uid) : uid;
if (!task) {
return;
}
var taskCopy = this.dataSource._createNewModel(task.toJSON());
taskCopy.uid = task.uid;
this.cancelTask();
this._editTask(taskCopy);
},
_editTask: function (task) {
this._editor.editTask(task);
},
saveTask: function (task, updateInfo) {
var editor = this._editor;
var container = editor.container;
var editable = editor.editable;
if (container && editable && editable.end()) {
this._updateTask(task, updateInfo);
}
},
_updateTask: function (task, updateInfo) {
var resourcesField = this.resources.field;
if (!this.trigger('save', {
task: task,
values: updateInfo
})) {
this._preventRefresh = true;
this.dataSource.update(task, updateInfo);
if (updateInfo[resourcesField]) {
this._updateAssignments(task.get('id'), updateInfo[resourcesField]);
}
this._syncDataSource();
}
},
_updateAssignment: function (assignment, value) {
var resourceValueField = this.assignments.dataValueField;
assignment.set(resourceValueField, value);
},
removeTask: function (uid) {
var that = this;
var task = typeof uid === 'string' ? this.dataSource.getByUid(uid) : uid;
if (!task) {
return;
}
this._taskConfirm(function (cancel) {
if (!cancel) {
that._removeTask(task);
}
}, task);
},
_createTask: function (task, index) {
if (!this.trigger('add', {
task: task,
dependency: null
})) {
var dataSource = this.dataSource;
this._preventRefresh = true;
if (index === undefined) {
dataSource.add(task);
} else {
dataSource.insert(index, task);
}
this._scrollToUid = task.uid;
this._syncDataSource();
}
},
_createDependency: function (dependency) {
if (!this.trigger('add', {
task: null,
dependency: dependency
})) {
this._preventDependencyRefresh = true;
this.dependencies.add(dependency);
this._preventDependencyRefresh = false;
this.dependencies.sync();
}
},
_createAssignment: function (resource, id) {
var assignments = this.assignments;
var dataSource = assignments.dataSource;
var taskId = assignments.dataTaskIdField;
var resourceId = assignments.dataResourceIdField;
var resourceValue = assignments.dataValueField;
var assignment = dataSource._createNewModel();
assignment[taskId] = id;
assignment[resourceId] = resource.get('id');
assignment[resourceValue] = resource.get('value');
dataSource.add(assignment);
},
removeDependency: function (uid) {
var that = this;
var dependency = typeof uid === 'string' ? this.dependencies.getByUid(uid) : uid;
if (!dependency) {
return;
}
this._dependencyConfirm(function (cancel) {
if (!cancel) {
that._removeDependency(dependency);
}
}, dependency);
},
_removeTaskDependencies: function (task, dependencies) {
this._preventDependencyRefresh = true;
for (var i = 0, length = dependencies.length; i < length; i++) {
this.dependencies.remove(dependencies[i]);
}
this._preventDependencyRefresh = false;
this.dependencies.sync();
},
_removeTaskAssignments: function (task) {
var dataSource = this.assignments.dataSource;
var assignments = dataSource.view();
var filter = {
field: this.assignments.dataTaskIdField,
operator: 'eq',
value: task.get('id')
};
assignments = new Query(assignments).filter(filter).toArray();
this._preventRefresh = true;
for (var i = 0, length = assignments.length; i < length; i++) {
dataSource.remove(assignments[i]);
}
this._preventRefresh = false;
dataSource.sync();
},
_removeTask: function (task) {
var dependencies = this.dependencies.dependencies(task.id);
if (!this.trigger('remove', {
task: task,
dependencies: dependencies
})) {
this._removeTaskDependencies(task, dependencies);
this._removeTaskAssignments(task);
this._preventRefresh = true;
if (this.dataSource.remove(task)) {
this._syncDataSource();
}
this._preventRefresh = false;
}
},
_removeDependency: function (dependency) {
if (!this.trigger('remove', {
task: null,
dependencies: [dependency]
})) {
if (this.dependencies.remove(dependency)) {
this.dependencies.sync();
}
}
},
_removeAssignment: function (assignment) {
this.assignments.dataSource.remove(assignment);
},
_taskConfirm: function (callback, task) {
var messages = this.options.messages;
this._confirm(callback, {
model: task,
text: messages.deleteTaskConfirmation,
title: messages.deleteTaskWindowTitle
});
},
_dependencyConfirm: function (callback, dependency) {
var messages = this.options.messages;
this._confirm(callback, {
model: dependency,
text: messages.deleteDependencyConfirmation,
title: messages.deleteDependencyWindowTitle
});
},
_confirm: function (callback, options) {
var editable = this.options.editable;
var messages;
var buttons;
if (editable === true || editable.confirmation !== false) {
messages = this.options.messages;
buttons = [
{
name: 'delete',
text: messages.destroy,
className: Gantt.styles.primary,
click: function () {
callback();
}
},
{
name: 'cancel',
text: messages.cancel,
click: function () {
callback(true);
}
}
];
this.showDialog(extend(true, {}, options, { buttons: buttons }));
} else {
callback();
}
},
showDialog: function (options) {
this._editor.showDialog(options);
},
refresh: function () {
if (this._preventRefresh || this.list.editable) {
return;
}
this._progress(false);
var dataSource = this.dataSource;
var taskTree = dataSource.taskTree();
var scrollToUid = this._scrollToUid;
var current;
var cachedUid;
var cachedIndex = -1;
if (this.current) {
cachedUid = this.current.closest('tr').attr(kendo.attr('uid'));
cachedIndex = this.current.index();
}
if (this.trigger('dataBinding')) {
return;
}
if (this.resources.dataSource.data().length !== 0) {
this._assignResources(taskTree);
}
if (this._editor) {
this._editor.close();
}
this.clearSelection();
this.list._render(taskTree);
this.timeline._render(taskTree);
this.timeline._renderDependencies(this.dependencies.view());
if (scrollToUid) {
this._scrollTo(scrollToUid);
this.select(selector(scrollToUid));
}
if ((scrollToUid || cachedUid) && cachedIndex >= 0) {
current = this.list.content.find('tr' + selector(scrollToUid || cachedUid) + ' > td:eq(' + cachedIndex + ')');
this._current(current);
}
this._scrollToUid = null;
this.trigger('dataBound');
},
refreshDependencies: function () {
if (this._preventDependencyRefresh) {
return;
}
if (this.trigger('dataBinding')) {
return;
}
this.timeline._renderDependencies(this.dependencies.view());
this.trigger('dataBound');
},
_assignResources: function (taskTree) {
var resources = this.resources;
var assignments = this.assignments;
var groupAssigments = function () {
var data = assignments.dataSource.view();
var group = { field: assignments.dataTaskIdField };
data = new Query(data).group(group).toArray();
return data;
};
var assigments = groupAssigments();
var applyTaskResource = function (task, action) {
var taskId = task.get('id');
kendo.setter(resources.field)(task, new ObservableArray([]));
for (var i = 0, length = assigments.length; i < length; i++) {
if (assigments[i].value === taskId) {
action(task, assigments[i].items);
}
}
};
var wrapTask = function (task, items) {
for (var j = 0, length = items.length; j < length; j++) {
var item = items[j];
var resource = resources.dataSource.get(item.get(assignments.dataResourceIdField));
var resourceValue = item.get(assignments.dataValueField);
var resourcedId = item.get(assignments.dataResourceIdField);
var valueFormat = resource.get(resources.dataFormatField) || PERCENTAGE_FORMAT;
var formatedValue = kendo.toString(resourceValue, valueFormat);
task[resources.field].push(new ObservableObject({
id: resourcedId,
name: resource.get(resources.dataTextField),
color: resource.get(resources.dataColorField),
value: resourceValue,
formatedValue: formatedValue
}));
}
};
for (var i = 0, length = taskTree.length; i < length; i++) {
applyTaskResource(taskTree[i], wrapTask);
}
},
_wrapResourceData: function (id) {
var that = this;
var result = [];
var resource;
var resources = this.resources.dataSource.view();
var assignments = this.assignments.dataSource.view();
var taskAssignments = new Query(assignments).filter({
field: that.assignments.dataTaskIdField,
operator: 'eq',
value: id
}).toArray();
var valuePerResource = function (id) {
var resourceValue = null;
new Query(taskAssignments).filter({
field: that.assignments.dataResourceIdField,
operator: 'eq',
value: id
}).select(function (assignment) {
resourceValue += assignment.get(that.assignments.dataValueField);
});
return resourceValue;
};
for (var i = 0, length = resources.length; i < length; i++) {
resource = resources[i];
result.push({
id: resource.get('id'),
name: resource.get(that.resources.dataTextField),
format: resource.get(that.resources.dataFormatField) || PERCENTAGE_FORMAT,
value: valuePerResource(resource.id)
});
}
return result;
},
_syncDataSource: function () {
this._preventRefresh = false;
this._requestStart();
this.dataSource.sync();
},
_requestStart: function () {
this._progress(true);
},
_error: function () {
this._progress(false);
},
_progress: function (toggle) {
kendo.ui.progress(this.element, toggle);
},
_resizable: function () {
var that = this;
var wrapper = this.wrapper;
var ganttStyles = Gantt.styles;
var contentSelector = DOT + ganttStyles.gridContent;
var treeListWrapper = wrapper.find(DOT + ganttStyles.list);
var timelineWrapper = wrapper.find(DOT + ganttStyles.timeline);
var treeListWidth;
var timelineWidth;
var timelineScroll;
this._resizeDraggable = wrapper.find(DOT + ganttStyles.splitBar).height(treeListWrapper.height()).hover(function () {
$(this).addClass(ganttStyles.splitBarHover);
}, function () {
$(this).removeClass(ganttStyles.splitBarHover);
}).end().kendoResizable({
orientation: 'horizontal',
handle: DOT + ganttStyles.splitBar,
'start': function () {
treeListWidth = treeListWrapper.width();
timelineWidth = timelineWrapper.width();
timelineScroll = timelineWrapper.find(contentSelector).scrollLeft();
},
'resize': function (e) {
var delta = e.x.initialDelta;
if (kendo.support.isRtl(wrapper)) {
delta *= -1;
}
if (treeListWidth + delta < 0 || timelineWidth - delta < 0) {
return;
}
treeListWrapper.width(treeListWidth + delta);
timelineWrapper.width(timelineWidth - delta);
timelineWrapper.find(contentSelector).scrollLeft(timelineScroll + delta);
that.timeline.view()._renderCurrentTime();
}
}).data('kendoResizable');
},
_scrollable: function () {
var that = this;
var ganttStyles = Gantt.styles;
var contentSelector = DOT + ganttStyles.gridContent;
var headerSelector = DOT + ganttStyles.gridHeaderWrap;
var timelineHeader = this.timeline.element.find(headerSelector);
var timelineContent = this.timeline.element.find(contentSelector);
var treeListHeader = this.list.element.find(headerSelector);
var treeListContent = this.list.element.find(contentSelector);
if (mobileOS) {
treeListContent.css('overflow-y', 'auto');
}
timelineContent.on('scroll', function () {
that.scrollTop = this.scrollTop;
timelineHeader.scrollLeft(this.scrollLeft);
treeListContent.scrollTop(this.scrollTop);
});
treeListContent.on('scroll', function () {
that.scrollTop = this.scrollTop;
treeListHeader.scrollLeft(this.scrollLeft);
timelineContent.scrollTop(this.scrollTop);
}).on('DOMMouseScroll' + NS + ' mousewheel' + NS, function (e) {
var scrollTop = timelineContent.scrollTop();
var delta = kendo.wheelDeltaY(e);
if (delta) {
e.preventDefault();
$(e.currentTarget).one('wheel' + NS, false);
timelineContent.scrollTop(scrollTop + -delta);
}
});
},
_navigatable: function () {
var that = this;
var navigatable = this.options.navigatable;
var editable = this.options.editable;
var headerTable = this.list.header.find('table');
var contentTable = this.list.content.find('table');
var ganttStyles = Gantt.styles;
var isRtl = kendo.support.isRtl(this.wrapper);
var timelineContent = this.timeline.element.find(DOT + ganttStyles.gridContent);
var tables = headerTable.add(contentTable);
var attr = selector();
var cellIndex;
var expandState = {
collapse: false,
expand: true
};
var scroll = function (reverse) {
var width = that.timeline.view()._timeSlots()[0].offsetWidth;
timelineContent.scrollLeft(timelineContent.scrollLeft() + (reverse ? -width : width));
};
var moveVertical = function (method) {
var parent = that.current.parent('tr' + selector());
var index = that.current.index();
var subling = parent[method]();
if (that.select().length !== 0) {
that.clearSelection();
}
if (subling.length !== 0) {
that._current(subling.children('td:eq(' + index + ')'));
that._scrollTo(that.current);
} else {
if (that.current.is('td') && method == 'prev') {
focusTable(headerTable);
} else if (that.current.is('th') && method == 'next') {
focusTable(contentTable);
}
}
};
var moveHorizontal = function (method) {
var subling = that.current[method]();
if (subling.length !== 0) {
that._current(subling);
cellIndex = that.current.index();
}
};
var toggleExpandedState = function (value) {
var model = that.dataItem(that.current);
if (model.summary && model.expanded !== value) {
model.set('expanded', value);
}
};
var deleteAction = function () {
if (!that.options.editable || that.list.editable) {
return;
}
var selectedTask = that.select();
var uid = kendo.attr('uid');
if (selectedTask.length) {
that.removeTask(selectedTask.attr(uid));
}
};
$(this.wrapper).on('mousedown' + NS, 'tr' + attr + ', div' + attr + ':not(' + DOT + ganttStyles.line + ')', function (e) {
var currentTarget = $(e.currentTarget);
var isInput = $(e.target).is(':button,a,:input,a>.k-icon,textarea,span.k-icon,span.k-link,.k-input,.k-multiselect-wrap');
var current;
if (e.ctrlKey) {
return;
}
if (navigatable) {
if (currentTarget.is('tr')) {
current = $(e.target).closest('td');
} else {
current = that.list.content.find('tr' + selector(currentTarget.attr(kendo.attr('uid'))) + ' > td:first');
}
that._current(current);
}
if ((navigatable || editable) && !isInput) {
that._focusTimeout = setTimeout(function () {
focusTable(that.list.content.find('table'), true);
}, 2);
}
});
if (navigatable !== true) {
contentTable.on('keydown' + NS, function (e) {
if (e.keyCode == keys.DELETE) {
deleteAction();
}
});
return;
}
tables.on('focus' + NS, function () {
var selector = this === contentTable.get(0) ? 'td' : 'th';
var selection = that.select();
var current = that.current || $(selection.length ? selection : this).find(selector + ':eq(' + (cellIndex || 0) + ')');
that._current(current);
}).on('blur' + NS, function () {
that._current();
if (this == headerTable) {
$(this).attr(TABINDEX, -1);
}
}).on('keydown' + NS, function (e) {
var key = e.keyCode;
var isCell;
if (!that.current) {
return;
}
isCell = that.current.is('td');
switch (key) {
case keys.RIGHT:
e.preventDefault();
if (e.altKey) {
scroll();
} else if (e.ctrlKey) {
toggleExpandedState(isRtl ? expandState.collapse : expandState.expand);
} else {
moveHorizontal(isRtl ? 'prev' : 'next');
}
break;
case keys.LEFT:
e.preventDefault();
if (e.altKey) {
scroll(true);
} else if (e.ctrlKey) {
toggleExpandedState(isRtl ? expandState.expand : expandState.collapse);
} else {
moveHorizontal(isRtl ? 'next' : 'prev');
}
break;
case keys.UP:
e.preventDefault();
moveVertical('prev');
break;
case keys.DOWN:
e.preventDefault();
moveVertical('next');
break;
case keys.SPACEBAR:
e.preventDefault();
if (isCell) {
that.select(that.current.closest('tr'));
}
break;
case keys.ENTER:
e.preventDefault();
if (isCell) {
if (that.options.editable) {
that._cachedCurrent = that.current;
that.list._startEditHandler(that.current);
$(this).one('keyup', function (e) {
e.stopPropagation();
});
}
} else {
that.current.children('a.k-link').click();
}
break;
case keys.ESC:
e.stopPropagation();
break;
case keys.DELETE:
if (isCell) {
deleteAction();
}
break;
default:
if (key >= 49 && key <= 57) {
that.view(that.timeline._viewByIndex(key - 49));
}
break;
}
});
},
_current: function (element) {
var ganttStyles = Gantt.styles;
var activeElement;
if (this.current && this.current.length) {
this.current.removeClass(ganttStyles.focused).removeAttr('id');
}
if (element && element.length) {
this.current = element.addClass(ganttStyles.focused).attr('id', ACTIVE_CELL);
activeElement = $(kendo._activeElement());
if (activeElement.is('table') && this.wrapper.find(activeElement).length > 0) {
activeElement.removeAttr(ARIA_DESCENDANT).attr(ARIA_DESCENDANT, ACTIVE_CELL);
}
} else {
this.current = null;
}
},
_dataBind: function () {
var that = this;
if (that.options.autoBind) {
this._preventRefresh = true;
this._preventDependencyRefresh = true;
var promises = $.map([
this.dataSource,
this.dependencies,
this.resources.dataSource,
this.assignments.dataSource
], function (dataSource) {
return dataSource.fetch();
});
$.when.apply(null, promises).done(function () {
that._preventRefresh = false;
that._preventDependencyRefresh = false;
that.refresh();
});
}
},
_resize: function () {
this._adjustDimensions();
this.timeline.view()._adjustHeight();
this.timeline.view()._renderCurrentTime();
this.list._adjustHeight();
}
});
if (kendo.PDFMixin) {
kendo.PDFMixin.extend(Gantt.fn);
Gantt.fn._drawPDF = function () {
var ganttStyles = Gantt.styles;
var listClass = '.' + ganttStyles.list;
var listWidth = this.wrapper.find(listClass).width();
var content = this.wrapper.clone();
content.find(listClass).css('width', listWidth);
return this._drawPDFShadow({ content: content }, { avoidLinks: this.options.pdf.avoidLinks });
};
}
kendo.ui.plugin(Gantt);
extend(true, Gantt, { styles: ganttStyles });
}(window.kendo.jQuery));
return window.kendo;
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
(a3 || a2)();
}));