UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,420 lines (1,132 loc) 134 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ({ /***/ 0: /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1189); /***/ }), /***/ 3: /***/ (function(module, exports) { module.exports = function() { throw new Error("define cannot be used indirect"); }; /***/ }), /***/ 1015: /***/ (function(module, exports) { module.exports = require("./kendo.data"); /***/ }), /***/ 1038: /***/ (function(module, exports) { module.exports = require("./kendo.popup"); /***/ }), /***/ 1142: /***/ (function(module, exports) { module.exports = require("./kendo.resizable"); /***/ }), /***/ 1143: /***/ (function(module, exports) { module.exports = require("./kendo.window"); /***/ }), /***/ 1189: /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1015), __webpack_require__(1038), __webpack_require__(1143), __webpack_require__(1142), __webpack_require__(1190), __webpack_require__(1191), __webpack_require__(1192), __webpack_require__(1193)], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); })(function(){ var __meta__ = { // jshint ignore:line id: "gantt", name: "Gantt", category: "web", description: "The Gantt component.", depends: [ "data", "popup", "resizable", "window", "gantt.list", "gantt.timeline", "grid" ] }; (function($, undefined) { var kendo = window.kendo; var keys = $.extend({F10: 121}, kendo.keys); var supportsMedia = "matchMedia" in window; var browser = kendo.support.browser; var mobileOS = kendo.support.mobileOS; var Observable = kendo.Observable; var Widget = kendo.ui.Widget; var DataSource = kendo.data.DataSource; var ObservableObject = kendo.data.ObservableObject; var ObservableArray = kendo.data.ObservableArray; var Query = kendo.data.Query; var isArray = $.isArray; var inArray = $.inArray; var isFunction = kendo.isFunction; var proxy = $.proxy; var extend = $.extend; var isPlainObject = $.isPlainObject; var map = $.map; var outerWidth = kendo._outerWidth; var outerHeight = kendo._outerHeight; var defaultIndicatorWidth = 3; var NS = ".kendoGantt"; var PERCENTAGE_FORMAT = "p0"; var TABINDEX = "tabIndex"; var CLICK = "click"; var WIDTH = "width"; var STRING = "string"; var DIRECTIONS = { "down": { origin: "bottom left", position: "top left" }, "up": { origin: "top left", position: "bottom left" } }; var ARIA_DESCENDANT = "aria-activedescendant"; var ARIA_LABEL = "aria-label"; var ACTIVE_CELL = "gantt_active_cell"; var ACTIVE_OPTION = "action-option-focused"; var DOT = "."; var TASK_DELETE_CONFIRM = "Are you sure you want to delete this task?"; var DEPENDENCY_DELETE_CONFIRM = "Are you sure you want to delete this dependency?"; var TOGGLE_BUTTON_TEMPLATE = kendo.template('<button class="#=styles.buttonToggle#" type="button" '+ ARIA_LABEL + '="Toggle"><span class="#=styles.iconToggle#"></span></button>'); var BUTTON_TEMPLATE = '<button class="#=styles.button# #=className#" type="button" '+ '#if (action) {#' + 'data-action="#=action#"' + '#}#' + '><span class="#=iconClass#"></span><span>#=text#</span></button>'; var COMMAND_BUTTON_TEMPLATE = '<a class="#=className#" #=attr# href="\\#">#=text#</a>'; var VIEWBUTTONTEMPLATE = kendo.template('<li class="#=styles.currentView# #=styles.viewButtonDefault#"><a href="\\#" class="#=styles.link#">&nbps;</a></li>'); var HEADER_VIEWS_TEMPLATE = kendo.template('<ul class="#=styles.viewsWrapper#">' + '#for(var view in views){#' + '<li class="#=styles.viewButtonDefault# #=styles.viewButton#-#= view.toLowerCase() #" data-#=ns#name="#=view#"><a href="\\#" class="#=styles.link#">#=views[view].title#</a></li>' + '#}#' + '</ul>'); var TASK_DROPDOWN_TEMPLATE = kendo.template('<div class="#=styles.popupWrapper#">' + '<ul class="#=styles.popupList#" role="listbox">' + '#for(var i = 0, l = actions.length; i < l; i++){#' + '<li class="#=styles.item#" data-action="#=actions[i].data#" role="option">#=actions[i].text#</span>' + '#}#' + '</ul>' + '</div>'); var DATERANGEEDITOR = function(container, options) { var attr = { name: options.field, title: options.title }; var validationRules = options.model.fields[options.field].validation; if (validationRules && isPlainObject(validationRules) && validationRules.message) { attr[kendo.attr("dateCompare-msg")] = validationRules.message; } $('<input type="text" required ' + kendo.attr("type") + '="date" ' + kendo.attr("role") + '="datetimepicker" ' + kendo.attr("bind") + '="value:' + options.field +'" ' + kendo.attr("validate") + "='true' />") .attr(attr) .appendTo(container); $('<span ' + kendo.attr("for") + '="' + options.field + '" class="k-invalid-msg"/>') .hide() .appendTo(container); }; var RESOURCESEDITOR = function(container, options) { $('<a href="#" class="' + options.styles.button + '">' + options.messages.assignButton + '</a>').click(options.click).appendTo(container); }; var ganttStyles = { wrapper: "k-widget k-gantt", rowHeight: "k-gantt-rowheight", listWrapper: "k-gantt-layout k-gantt-treelist", list: "k-gantt-treelist", timelineWrapper: "k-gantt-layout k-gantt-timeline", timeline: "k-gantt-timeline", splitBarWrapper: "k-splitbar k-state-default k-splitbar-horizontal k-splitbar-draggable-horizontal k-gantt-layout", splitBar: "k-splitbar", splitBarHover: "k-splitbar-horizontal-hover", popupWrapper: "k-list-container", popupList: "k-list k-reset", resizeHandle: "k-resize-handle", icon: "k-icon", item: "k-item", line: "k-line", buttonDelete: "k-gantt-delete", buttonCancel: "k-gantt-cancel", buttonSave: "k-gantt-update", buttonToggle: "k-gantt-toggle", primary: "k-primary", hovered: "k-state-hover", selected: "k-state-selected", focused: "k-state-focused", gridHeader: "k-grid-header", gridHeaderWrap: "k-grid-header-wrap", gridContent: "k-grid-content", tasks: "k-gantt-tasks", popup: { form: "k-popup-edit-form", editForm: "k-gantt-edit-form", formContainer: "k-edit-form-container", resourcesFormContainer: "k-resources-form-container", message: "k-popup-message", buttonsContainer: "k-edit-buttons k-state-default", button: "k-button", editField: "k-edit-field", editLabel: "k-edit-label", resourcesField: "k-gantt-resources" }, toolbar: { headerWrapper: "k-floatwrap k-header k-gantt-toolbar", footerWrapper: "k-floatwrap k-header k-gantt-toolbar", toolbar: "k-gantt-toolbar", expanded: "k-state-expanded", views: "k-gantt-views", viewsWrapper: "k-reset k-header k-gantt-views", actions: "k-gantt-actions", button: "k-button k-button-icontext", buttonToggle: "k-button k-button-icon k-gantt-toggle", iconPlus: "k-icon k-i-plus", iconPdf: "k-icon k-i-file-pdf", iconToggle: "k-icon k-i-layout-1-by-4", viewButtonDefault: "k-state-default", viewButton: "k-view", currentView: "k-current-view", link: "k-link", pdfButton: "k-gantt-pdf", appendButton: "k-gantt-create" } }; function selector(uid) { return "[" + kendo.attr("uid") + (uid ? "='" + uid + "']" : "]"); } function trimOptions(options) { delete options.name; delete options.prefix; delete options.remove; delete options.edit; delete options.add; delete options.navigate; return options; } function dateCompareValidator(input) { if (input.filter("[name=end], [name=start]").length) { var field = input.attr("name"); var picker = kendo.widgetInstance(input, kendo.ui); var dates = {}; var container = input; var editable; var model; while (container !== window && !editable) { container = container.parent(); editable = container.data("kendoEditable"); } model = editable ? editable.options.model : null; if (!model) { return true; } dates.start = model.start; dates.end = model.end; dates[field] = picker ? picker.value() : kendo.parseDate(input.val()); return dates.start <= dates.end; } return true; } function focusTable(table, direct) { var wrapper = table.parents('[' + kendo.attr("role") + '="gantt"]'); var scrollPositions = []; var parents = scrollableParents(wrapper); table.attr(TABINDEX, 0); if (direct) { parents.each(function(index, parent) { scrollPositions[index] = $(parent).scrollTop(); }); } try { //The setActive method does not cause the document to scroll to the active object in the current page table[0].setActive(); } catch (e) { table[0].focus(); } if (direct) { parents.each(function(index, parent) { $(parent).scrollTop(scrollPositions[index]); }); } } function scrollableParents(element) { return $(element).parentsUntil("body") .filter(function(index, element) { var computedStyle = kendo.getComputedStyles(element, ["overflow"]); return computedStyle.overflow != "visible"; }) .add(window); } var defaultCommands; var TaskDropDown = Observable.extend({ init: function(element, options) { Observable.fn.init.call(this); this.element = element; this.options = extend(true, {}, this.options, options); this._popup(); }, options: { direction: "down", navigatable: false }, _current: function(method) { var ganttStyles = Gantt.styles; var current = this.list .find(DOT + ganttStyles.focused); var sibling = current[method](); if (sibling.length) { current .removeClass(ganttStyles.focused) .removeAttr("id"); sibling .addClass(ganttStyles.focused) .attr("id", ACTIVE_OPTION); this.list.find("ul") .removeAttr(ARIA_DESCENDANT) .attr(ARIA_DESCENDANT, ACTIVE_OPTION); } }, _popup: function() { var that = this; var ganttStyles = Gantt.styles; var itemSelector = "li" + DOT + ganttStyles.item; var appendButtonSelector = DOT + ganttStyles.toolbar.appendButton; var actions = this.options.messages.actions; var navigatable = this.options.navigatable; this.list = $(TASK_DROPDOWN_TEMPLATE({ styles: ganttStyles, actions: [ { data: "add", text: actions.addChild }, { data: "insert-before", text: actions.insertBefore }, { data: "insert-after", text: actions.insertAfter } ] })); this.element.append(this.list); this.popup = new kendo.ui.Popup(this.list, extend({ anchor: this.element.find(appendButtonSelector), open: function() { that._adjustListWidth(); }, animation: this.options.animation }, DIRECTIONS[this.options.direction]) ); this.element .on(CLICK + NS, appendButtonSelector, function(e) { var target = $(this); var action = target.attr(kendo.attr("action")); e.preventDefault(); if (action) { that.trigger("command", { type: action }); } else { that.popup.open(); if (navigatable) { that.list .find("li:first") .addClass(ganttStyles.focused) .attr("id", ACTIVE_OPTION) .end() .find("ul") .attr({ TABINDEX: 0, "aria-activedescendant": ACTIVE_OPTION }) .focus(); } } }); this.list .find(itemSelector) .hover(function() { $(this).addClass(ganttStyles.hovered); }, function() { $(this).removeClass(ganttStyles.hovered); }) .end() .on(CLICK + NS, itemSelector, function() { that.trigger("command", { type: $(this).attr(kendo.attr("action")) }); that.popup.close(); }); if (navigatable) { this.popup .bind("close", function() { that.list .find(itemSelector) .removeClass(ganttStyles.focused) .end() .find("ul") .attr(TABINDEX, 0); that.element .parents('[' + kendo.attr("role") + '="gantt"]') .find(DOT + ganttStyles.gridContent + " > table:first") .focus(); }); this.list .find("ul") .on("keydown" + NS, function(e) { var key = e.keyCode; switch (key) { case keys.UP: e.preventDefault(); that._current("prev"); break; case keys.DOWN: e.preventDefault(); that._current("next"); break; case keys.ENTER: that.list .find(DOT + ganttStyles.focused) .click(); break; case keys.ESC: e.preventDefault(); that.popup.close(); break; } }); } }, _adjustListWidth: function() { var list = this.list; var ganttStyles = Gantt.styles; var width = list[0].style.width; var wrapper = this.element.find(DOT + ganttStyles.toolbar.appendButton); var listOuterWidth = outerWidth(list); var computedStyle; var computedWidth; if (!list.data(WIDTH) && width) { return; } computedStyle = window.getComputedStyle ? window.getComputedStyle(wrapper[0], null) : 0; computedWidth = computedStyle ? parseFloat(computedStyle.width) : outerWidth(wrapper); if (computedStyle && (browser.mozilla || browser.msie)) { // getComputedStyle returns different box in FF and IE. computedWidth += parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight) + parseFloat(computedStyle.borderLeftWidth) + parseFloat(computedStyle.borderRightWidth); } if (list.css("box-sizing") !== "border-box") { width = computedWidth - (outerWidth(list) - list.width()); } else { width = computedWidth; } if (listOuterWidth > width) { width = listOuterWidth; } list.css({ fontFamily: wrapper.css("font-family"), width: width }) .data(WIDTH, width); }, destroy: function() { clearTimeout(this._focusTimeout); this.popup.destroy(); this.element.off(NS); this.list.off(NS); this.unbind(); } }); var createDataSource = function(type, name) { return function(options) { options = isArray(options) ? { data: options } : options; var dataSource = options || {}; var data = dataSource.data; dataSource.data = data; if (!(dataSource instanceof type) && dataSource instanceof DataSource) { throw new Error("Incorrect DataSource type. Only " + name + " instances are supported"); } return dataSource instanceof type ? dataSource : new type(dataSource); }; }; var GanttDependency = kendo.data.Model.define({ id: "id", fields: { id: { type: "number" }, predecessorId: { type: "number" }, successorId: { type: "number" }, type: { type: "number" } } }); var GanttDependencyDataSource = DataSource.extend({ init: function(options) { DataSource.fn.init.call(this, extend(true, {}, { schema: { modelBase: GanttDependency, model: GanttDependency } }, options)); }, successors: function(id) { return this._dependencies("predecessorId", id); }, predecessors: function(id) { return this._dependencies("successorId", id); }, dependencies: function(id) { var predecessors = this.predecessors(id); var successors = this.successors(id); predecessors.push.apply(predecessors, successors); return predecessors; }, _dependencies: function(field, id) { var data = this.view(); var filter = { field: field, operator: "eq", value: id }; data = new Query(data).filter(filter).toArray(); return data; } }); GanttDependencyDataSource.create = createDataSource(GanttDependencyDataSource, "GanttDependencyDataSource"); var GanttTask = kendo.data.Model.define({ duration: function() { var end = this.end; var start = this.start; return end - start; }, isMilestone: function() { return this.duration() === 0; }, _offset: function(value) { var field = ["start", "end"]; var newValue; for (var i = 0; i < field.length; i++) { newValue = new Date(this.get(field[i]).getTime() + value); this.set(field[i], newValue); } }, id: "id", fields: { id: { type: "number" }, parentId: { type: "number", defaultValue: null, validation: { required: true } }, orderId: { type: "number", validation: { required: true } }, title: { type: "string", defaultValue: "New task" }, start: { type: "date", validation: { required: true } }, end: { type: "date", validation: { required: true, dateCompare: dateCompareValidator, message: "End date should be after or equal to the start date" } }, percentComplete: { type: "number", validation: { required: true, min:0, max: 1, step: 0.01 } }, summary: { type: "boolean" }, expanded: { type: "boolean", defaultValue: true } } }); var GanttDataSource = DataSource.extend({ init: function(options) { DataSource.fn.init.call(this, extend(true, {}, { schema: { modelBase: GanttTask, model: GanttTask } }, options)); }, remove: function(task) { var parentId = task.get("parentId"); var children = this.taskAllChildren(task); this._removeItems(children); task = DataSource.fn.remove.call(this, task); this._childRemoved(parentId, task.get("orderId")); return task; }, add: function(task) { if (!task) { return; } task = this._toGanttTask(task); return this.insert(this.taskSiblings(task).length, task); }, insert: function(index, task) { if (!task) { return; } task = this._toGanttTask(task); task.set("orderId", index); task = DataSource.fn.insert.call(this, index, task); this._reorderSiblings(task, this.taskSiblings(task).length - 1); this._resolveSummaryFields(this.taskParent(task)); return task; }, taskChildren: function(task) { var data = this.view(); var filter = { field: "parentId", operator: "eq", value: null }; var order = (this._sort && this._sort.length) ? this._sort : { field: "orderId", dir: "asc" }; var taskId; if (!!task) { taskId = task.get("id"); if (taskId === undefined || taskId === null || taskId === "") { return []; } filter.value = taskId; } data = new Query(data).filter(filter).sort(order).toArray(); return data; }, taskAllChildren: function(task) { var data = []; var that = this; var callback = function(task) { var tasks = that.taskChildren(task); data.push.apply(data, tasks); map(tasks, callback); }; if (!!task) { callback(task); } else { data = this.view(); } return data; }, taskSiblings: function(task) { if (!task) { return null; } var parent = this.taskParent(task); return this.taskChildren(parent); }, taskParent: function(task) { if (!task || task.get("parentId") === null) { return null; } return this.get(task.parentId); }, taskLevel: function(task) { var level = 0; var parent = this.taskParent(task); while (parent !== null) { level += 1; parent = this.taskParent(parent); } return level; }, taskTree: function(task) { var data = []; var current; var tasks = this.taskChildren(task); for (var i = 0, l = tasks.length; i < l; i++) { current = tasks[i]; data.push(current); if (current.get("expanded")) { var children = this.taskTree(current); data.push.apply(data, children); } } return data; }, update: function(task, taskInfo) { var that = this; var oldValue; var offsetChildren = function(parentTask, offset) { var children = that.taskAllChildren(parentTask); for (var i = 0, l = children.length; i < l; i++) { children[i]._offset(offset); } }; var modelChangeHandler = function(e) { var field = e.field; var model = e.sender; switch (field) { case "start": that._resolveSummaryStart(that.taskParent(model)); offsetChildren(model, model.get(field).getTime() - oldValue.getTime()); break; case "end": that._resolveSummaryEnd(that.taskParent(model)); break; case "percentComplete": that._resolveSummaryPercentComplete(that.taskParent(model)); break; case "orderId": that._reorderSiblings(model, oldValue); break; } }; if (taskInfo.parentId !== undefined) { oldValue = task.get("parentId"); if (oldValue !== taskInfo.parentId) { task.set("parentId", taskInfo.parentId); that._childRemoved(oldValue, task.get("orderId")); task.set("orderId", that.taskSiblings(task).length - 1); that._resolveSummaryFields(that.taskParent(task)); } delete taskInfo.parentId; } task.bind("change", modelChangeHandler); for (var field in taskInfo) { oldValue = task.get(field); task.set(field, taskInfo[field]); } task.unbind("change", modelChangeHandler); }, _resolveSummaryFields: function(summary) { if (!summary) { return; } this._updateSummary(summary); if (!this.taskChildren(summary).length) { return; } this._resolveSummaryStart(summary); this._resolveSummaryEnd(summary); this._resolveSummaryPercentComplete(summary); }, _resolveSummaryStart: function(summary) { var that = this; var getSummaryStart = function(parentTask) { var children = that.taskChildren(parentTask); var min = children[0].start.getTime(); var currentMin; for (var i = 1, l = children.length; i < l; i++) { currentMin = children[i].start.getTime(); if (currentMin < min) { min = currentMin; } } return new Date(min); }; this._updateSummaryRecursive(summary, "start", getSummaryStart); }, _resolveSummaryEnd: function(summary) { var that = this; var getSummaryEnd = function(parentTask) { var children = that.taskChildren(parentTask); var max = children[0].end.getTime(); var currentMax; for (var i = 1, l = children.length; i < l; i++) { currentMax = children[i].end.getTime(); if (currentMax > max) { max = currentMax; } } return new Date(max); }; this._updateSummaryRecursive(summary, "end", getSummaryEnd); }, _resolveSummaryPercentComplete: function(summary) { var that = this; var getSummaryPercentComplete = function(parentTask) { var children = that.taskChildren(parentTask); var percentComplete = new Query(children).aggregate([{ field: "percentComplete", aggregate: "average" }]); return percentComplete.percentComplete.average; }; this._updateSummaryRecursive(summary, "percentComplete", getSummaryPercentComplete); }, _updateSummaryRecursive: function(summary, field, callback) { if (!summary) { return; } var value = callback(summary); summary.set(field, value); var parent = this.taskParent(summary); if (parent) { this._updateSummaryRecursive(parent, field, callback); } }, _childRemoved: function(parentId, index) { var parent = parentId === null ? null : this.get(parentId); var children = this.taskChildren(parent); for (var i = index, l = children.length; i < l; i++) { children[i].set("orderId", i); } this._resolveSummaryFields(parent); }, _reorderSiblings: function(task, oldOrderId) { var orderId = task.get("orderId"); var direction = orderId > oldOrderId; var startIndex = direction ? oldOrderId : orderId; var endIndex = direction ? orderId : oldOrderId; var newIndex = direction ? startIndex : startIndex + 1; var siblings = this.taskSiblings(task); endIndex = Math.min(endIndex, siblings.length - 1); for (var i = startIndex; i <= endIndex; i++) { if (siblings[i] === task) { continue; } siblings[i].set("orderId", newIndex); newIndex += 1; } }, _updateSummary: function(task) { if (task !== null) { var childCount = this.taskChildren(task).length; task.set("summary", childCount > 0); } }, _toGanttTask: function(task) { if (!(task instanceof GanttTask)) { var taskInfo = task; task = this._createNewModel(); task.accept(taskInfo); } return task; } }); GanttDataSource.create = createDataSource(GanttDataSource, "GanttDataSource"); extend(true, kendo.data, { GanttDataSource: GanttDataSource, GanttTask: GanttTask, GanttDependencyDataSource: GanttDependencyDataSource, GanttDependency: GanttDependency }); var editors = { desktop: { dateRange: DATERANGEEDITOR, resources: RESOURCESEDITOR } }; var Editor = kendo.Observable.extend({ init: function(element, options) { kendo.Observable.fn.init.call(this); this.element = element; this.options = extend(true, {}, this.options, options); this.createButton = this.options.createButton; }, fields: function(editors, model) { var that = this; var options = this.options; var messages = options.messages.editor; var resources = options.resources; var fields; var click = function(e) { e.preventDefault(); resources.editor(that.container.find(DOT + Gantt.styles.popup.resourcesField), model); }; if (options.editable.template) { fields = $.map(model.fields, function(value, key) { return { field: key }; }); } else { fields = [ { field: "title", title: messages.title }, { field: "start", title: messages.start, editor: editors.dateRange }, { field: "end", title: messages.end, editor: editors.dateRange }, { field: "percentComplete", title: messages.percentComplete, format: PERCENTAGE_FORMAT } ]; if (model.get(resources.field)) { fields.push({ field: resources.field, title: messages.resources, messages: messages, editor: editors.resources, click: click, styles: Gantt.styles.popup }); } } return fields; }, _buildEditTemplate: function(model, fields, editableFields) { var resources = this.options.resources; var template = this.options.editable.template; var settings = extend({}, kendo.Template, this.options.templateSettings); var paramName = settings.paramName; var popupStyles = Gantt.styles.popup; var html = ""; if (template) { if (typeof template === STRING) { template = window.unescape(template); } html += (kendo.template(template, settings))(model); } else { for (var i = 0, length = fields.length; i < length; i++) { var field = fields[i]; html += '<div class="' + popupStyles.editLabel + '"><label for="' + field.field + '">' + (field.title || field.field || "") + '</label></div>'; if (field.field === resources.field) { html += '<div class="' + popupStyles.resourcesField + '" style="display:none"></div>'; } if ((!model.editable || model.editable(field.field))) { editableFields.push(field); html += '<div ' + kendo.attr("container-for") + '="' + field.field + '" class="' + popupStyles.editField + '"></div>'; } else { var tmpl = "#:"; if (field.field) { field = kendo.expr(field.field, paramName); tmpl += field + "==null?'':" + field; } else { tmpl += "''"; } tmpl += "#"; tmpl = kendo.template(tmpl, settings); html += '<div class="' + popupStyles.editField + '">' + tmpl(model) + '</div>'; } } } return html; } }); var PopupEditor = Editor.extend({ destroy: function() { this.close(); this.unbind(); }, editTask: function(task) { this.editable = this._createPopupEditor(task); }, close: function() { var that = this; var destroy = function() { if (that.editable) { that.editable.destroy(); that.editable = null; that.container = null; } if (that.popup) { that.popup.destroy(); that.popup = null; } }; if (this.editable && this.container.is(":visible")) { that.trigger("close", { window: that.container }); this.container.data("kendoWindow").bind("deactivate", destroy).close(); } else { destroy(); } }, showDialog: function(options) { var buttons = options.buttons; var popupStyles = Gantt.styles.popup; var html = kendo.format('<div class="{0}"><div class="{1}"><p class="{2}">{3}</p><div class="{4}">', popupStyles.form, popupStyles.formContainer, popupStyles.message, options.text, popupStyles.buttonsContainer); for (var i = 0, length = buttons.length; i < length; i++) { html += this.createButton(buttons[i]); } html += '</div></div></div>'; var wrapper = this.element; if (this.popup) { this.popup.destroy(); } var popup = this.popup = $(html).appendTo(wrapper) .eq(0) .on("click", DOT + popupStyles.button, function(e) { e.preventDefault(); popup.close(); var buttonIndex = $(e.currentTarget).index(); buttons[buttonIndex].click(); }) .kendoWindow({ modal: true, autoFocus: false, resizable: false, draggable: false, title: options.title, visible: false, deactivate: function() { this.destroy(); wrapper.focus(); } }) .getKendoWindow(); popup.center().open(); popup.element.find(".k-primary").focus(); }, _createPopupEditor: function(task) { var that = this; var options = {}; var messages = this.options.messages; var ganttStyles = Gantt.styles; var popupStyles = ganttStyles.popup; var html = kendo.format('<div {0}="{1}" class="{2} {3}"><div class="{4}">', kendo.attr("uid"), task.uid, popupStyles.form, popupStyles.editForm, popupStyles.formContainer); var fields = this.fields(editors.desktop, task); var editableFields = []; html += this._buildEditTemplate(task, fields, editableFields); html += '<div class="' + popupStyles.buttonsContainer + '">'; html += this.createButton({ name: "update", text: messages.save, className: Gantt.styles.primary }); html += this.createButton({ name: "cancel", text: messages.cancel }); if (that.options.editable.destroy !== false) { html += this.createButton({ name: "delete", text: messages.destroy }); } html += '</div></div></div>'; var container = this.container = $(html).appendTo(this.element) .eq(0) .kendoWindow(extend({ modal: true, resizable: false, draggable: true, title: messages.editor.editorTitle, visible: false, close: function(e) { if (e.userTriggered) { if (that.trigger("cancel", { container: container, model: task })) { e.preventDefault(); } } } }, options)); var editableWidget = container .kendoEditable({ fields: editableFields, model: task, clearContainer: false, validateOnBlur: true, target: that.options.target }) .data("kendoEditable"); kendo.cycleForm(container); if (!this.trigger("edit", { container: container, model: task })) { container.data("kendoWindow").center().open(); container.on(CLICK + NS, DOT + ganttStyles.buttonCancel, function(e) { e.preventDefault(); e.stopPropagation(); that.trigger("cancel", { container: container, model: task }); }); container.on(CLICK + NS, DOT + ganttStyles.buttonSave, function(e) { e.preventDefault(); e.stopPropagation(); var fields = that.fields(editors.desktop, task); var updateInfo = {}; var field; for (var i = 0, length = fields.length; i < length; i++) { field = fields[i].field; updateInfo[field] = task.get(field); } that.trigger("save", { container: container, model: task, updateInfo: updateInfo }); }); container.on(CLICK + NS, DOT + ganttStyles.buttonDelete, function(e) { e.preventDefault(); e.stopPropagation(); that.trigger("remove", { container: container, model: task }); }); } else { that.trigger("cancel", { container: container, model: task }); } return editableWidget; } }); var ResourceEditor = Widget.extend({ init: function(element, options) { Widget.fn.init.call(this, element, options); this.wrapper = this.element; this.model = this.options.model; this.resourcesField = this.options.resourcesField; this.createButton = this.options.createButton; this._initContainer(); this._attachHandlers(); }, events: [ "save" ], open: function() { this.window.center().open(); }, close: function() { this.window.bind("deactivate", proxy(this.destroy, this)).close(); }, destroy: function() { this._dettachHandlers(); this.grid.destroy(); this.grid = null; this.window.destroy(); this.window = null; Widget.fn.destroy.call(this); kendo.destroy(this.wrapper); this.element = this.wrapper = null; }, _attachHandlers: function() { var ganttStyles = Gantt.styles; var grid = this.grid; var closeHandler = this._cancelProxy = proxy(this._cancel, this); this.container.on(CLICK + NS, DOT + ganttStyles.buttonCancel, this._cancelProxy); this._saveProxy = proxy(this._save, this); this.container.on(CLICK + NS, DOT + ganttStyles.buttonSave, this._saveProxy); this.window.bind("close", function(e) { if (e.userTriggered) { closeHandler(e); } }); grid.wrapper.on(CLICK + NS, "input[type='checkbox']", function() { var element = $(this); var row = $(element).closest("tr"); var model = grid.dataSource.getByUid(row.attr(kendo.attr("uid"))); var value = $(element).is(":checked") ? 1 : ""; model.set("value", value); }); }, _dettachHandlers: function() { this._cancelProxy = null; this._saveProxy = null; this.container.off(NS); this.grid.wrapper.off(); }, _cancel: function(e) { e.preventDefault(); this.close(); }, _save: function(e) { e.preventDefault(); this._updateModel(); if (!this.wrapper.is(DOT + Gantt.styles.popup.resourcesField)) { this.trigger("save", { container: this.wrapper, model: this.model }); } this.close(); }, _initContainer: function() { var that = this; var popupStyles = Gantt.styles.popup; var dom = kendo.format('<div class="{0} {1}"><div class="{2} {3}"/></div>"', popupStyles.form, popupStyles.editForm, popupStyles.formContainer, popupStyles.resourcesFormContainer); dom = $(dom); this.container = dom.find(DOT + popupStyles.resourcesFormContainer); this.window = dom.kendoWindow({ modal: true, resizable: false, draggable: true, visible: false, title: this.options.messages.resourcesEditorTitle, open: function() { that.grid.resize(true); } }).data("kendoWindow"); this._resourceGrid(); this._createButtons(); }, _resourceGrid: function() { var that = this; var messages = this.options.messages; var element = $('<div id="resources-grid"/>').appendTo(this.container); this.grid = new kendo.ui.Grid(element, { columns: [ { field: "name", title: messages.resourcesHeader, template: "<label><input type='checkbox' value='#=name#'" + "# if (value > 0 && value !== null) {#" + "c