UNPKG

@progress/kendo-ui

Version:

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

1,389 lines (1,085 loc) 103 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__(1199); /***/ }), /***/ 3: /***/ (function(module, exports) { module.exports = function() { throw new Error("define cannot be used indirect"); }; /***/ }), /***/ 1003: /***/ (function(module, exports) { module.exports = require("./kendo.dom"); /***/ }), /***/ 1061: /***/ (function(module, exports) { module.exports = require("./kendo.draganddrop"); /***/ }), /***/ 1195: /***/ (function(module, exports) { module.exports = require("./kendo.touch"); /***/ }), /***/ 1199: /***/ (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__(1003), __webpack_require__(1195), __webpack_require__(1061) ], __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.timeline", name: "Gantt Timeline", category: "web", description: "The Gantt Timeline", depends: [ "dom", "touch", "draganddrop" ], hidden: true }; (function($) { var Widget = kendo.ui.Widget; var kendoDomElement = kendo.dom.element; var kendoTextElement = kendo.dom.text; var kendoHtmlElement = kendo.dom.html; var isPlainObject = $.isPlainObject; var outerWidth = kendo._outerWidth; var outerHeight = kendo._outerHeight; var extend = $.extend; var proxy = $.proxy; var browser = kendo.support.browser; var isRtl = false; var keys = kendo.keys; var Query = kendo.data.Query; var STRING = "string"; var NS = ".kendoGanttTimeline"; var CLICK = "click"; var DBLCLICK = "dblclick"; var MOUSEMOVE = "mousemove"; var MOUSEENTER = "mouseenter"; var MOUSELEAVE = "mouseleave"; var KEYDOWN = "keydown"; var DOT = "."; var TIME_HEADER_TEMPLATE = kendo.template("#=kendo.toString(start, 't')#"); var DAY_HEADER_TEMPLATE = kendo.template("#=kendo.toString(start, 'ddd M/dd')#"); var WEEK_HEADER_TEMPLATE = kendo.template("#=kendo.toString(start, 'ddd M/dd')# - #=kendo.toString(kendo.date.addDays(end, -1), 'ddd M/dd')#"); var MONTH_HEADER_TEMPLATE = kendo.template("#=kendo.toString(start, 'MMM')#"); var YEAR_HEADER_TEMPLATE = kendo.template("#=kendo.toString(start, 'yyyy')#"); var RESIZE_HINT = kendo.template('<div class="#=styles.marquee#">' + '<div class="#=styles.marqueeColor#"></div>' + '</div>'); var RESIZE_TOOLTIP_TEMPLATE = kendo.template('<div style="z-index: 100002;" class="#=styles.tooltipWrapper#">' + '<div class="#=styles.tooltipContent#">' + '<div>#=messages.start#: #=kendo.toString(start, format)#</div>' + '<div>#=messages.end#: #=kendo.toString(end, format)#</div>' + '</div>' + '</div>'); var PERCENT_RESIZE_TOOLTIP_TEMPLATE = kendo.template('<div style="z-index: 100002;" class="#=styles.tooltipWrapper#" >' + '<div class="#=styles.tooltipContent#">#=text#%</div>' + '<div class="#=styles.tooltipCallout#" style="left:13px;"></div>' + '</div>'); var TASK_TOOLTIP_TEMPLATE = kendo.template('<div class="#=kendo.htmlEncode(styles.taskDetails)#">' + '<strong>#=kendo.htmlEncode(task.title)#</strong>' + '<div class="#=styles.taskDetailsPercent#">#=kendo.toString(task.percentComplete, "p0")#</div>' + '<ul class="#=styles.reset#">' + '<li>#=messages.start#: #=kendo.toString(task.start, "h:mm tt ddd, MMM d")#</li>' + '<li>#=messages.end#: #=kendo.toString(task.end, "h:mm tt ddd, MMM d")#</li>' + '</ul>' + '</div>'); var SIZE_CALCULATION_TEMPLATE = "<table style='visibility: hidden;'>" + "<tbody>" + "<tr style='height:{0}'>" + "<td>&nbsp;</td>" + "</tr>" + "</tbody>" + "</table>"; var defaultViews = { day: { type: "kendo.ui.GanttDayView" }, week: { type: "kendo.ui.GanttWeekView" }, month: { type: "kendo.ui.GanttMonthView" }, year: { type: "kendo.ui.GanttYearView" } }; function trimOptions(options) { delete options.name; delete options.prefix; delete options.views; return options; } function getWorkDays(options) { var workDays = []; var dayIndex = options.workWeekStart; workDays.push(dayIndex); while (options.workWeekEnd != dayIndex) { if (dayIndex > 6) { dayIndex -= 7; } else { dayIndex++; } workDays.push(dayIndex); } return workDays; } function blurActiveElement() { var activeElement = kendo._activeElement(); if (activeElement && activeElement.nodeName.toLowerCase() !== "body") { $(activeElement).blur(); } } var viewStyles = { alt: "k-alt", reset: "k-reset", nonWorking: "k-nonwork-hour", header: "k-header", gridHeader: "k-grid-header", gridHeaderWrap: "k-grid-header-wrap", gridContent: "k-grid-content", tasksWrapper: "k-gantt-tables", rowsTable: "k-gantt-rows", columnsTable: "k-gantt-columns", tasksTable: "k-gantt-tasks", dependenciesWrapper: "k-gantt-dependencies", resource: "k-resource", resourceAlt: "k-resource k-alt", task: "k-task", taskSingle: "k-task-single", taskMilestone: "k-task-milestone", taskSummary: "k-task-summary", taskWrap: "k-task-wrap", taskMilestoneWrap: "k-milestone-wrap", resourcesWrap: "k-resources-wrap", taskDot: "k-task-dot", taskDotStart: "k-task-start", taskDotEnd: "k-task-end", taskDragHandle: "k-task-draghandle", taskContent: "k-task-content", taskTemplate: "k-task-template", taskActions: "k-task-actions", taskDelete: "k-task-delete", taskComplete: "k-task-complete", taskDetails: "k-task-details", taskDetailsPercent: "k-task-pct", link: "k-link", icon: "k-icon", iconDelete: "k-i-close", taskResizeHandle: "k-resize-handle", taskResizeHandleWest: "k-resize-w", taskResizeHandleEast: "k-resize-e", taskSummaryProgress: "k-task-summary-progress", taskSummaryComplete: "k-task-summary-complete", line: "k-line", lineHorizontal: "k-line-h", lineVertical: "k-line-v", arrowWest: "k-arrow-w", arrowEast: "k-arrow-e", dragHint: "k-drag-hint", dependencyHint: "k-dependency-hint", tooltipWrapper: "k-widget k-tooltip k-popup k-group k-reset", tooltipContent: "k-tooltip-content", tooltipCallout: "k-callout k-callout-s", callout: "k-callout", marquee: "k-marquee k-gantt-marquee", marqueeColor: "k-marquee-color" }; var GanttView = kendo.ui.GanttView = Widget.extend({ init: function(element, options) { Widget.fn.init.call(this, element, options); this.title = this.options.title || this.options.name; this.header = this.element.find(DOT + GanttView.styles.gridHeader); this.content = this.element.find(DOT + GanttView.styles.gridContent); this.contentWidth = this.content.width(); this._workDays = getWorkDays(this.options); this._headerTree = options.headerTree; this._taskTree = options.taskTree; this._taskTemplate = options.taskTemplate ? kendo.template(options.taskTemplate, extend({}, kendo.Template, options.templateSettings)) : null; this._dependencyTree = options.dependencyTree; this._taskCoordinates = {}; this._currentTime(); }, destroy: function() { Widget.fn.destroy.call(this); clearTimeout(this._tooltipTimeout); this.headerRow = null; this.header = null; this.content = null; this._dragHint = null; this._resizeHint = null; this._resizeTooltip = null; this._taskTooltip = null; this._percentCompleteResizeTooltip = null; this._headerTree = null; this._taskTree = null; this._dependencyTree = null; }, options: { showWorkHours: false, showWorkDays: false, workDayStart: new Date(1980, 1, 1, 8, 0, 0), workDayEnd: new Date(1980, 1, 1, 17, 0, 0), workWeekStart: 1, workWeekEnd: 5, hourSpan: 1, slotSize: 100, currentTimeMarker: { updateInterval: 10000 } }, renderLayout: function() { this._slots = this._createSlots(); this._tableWidth = this._calculateTableWidth(); this.createLayout(this._layout()); this._slotDimensions(); this._adjustHeight(); this.content.find(DOT + GanttView.styles.dependenciesWrapper).width(this._tableWidth); }, _adjustHeight: function() { if(this.content){ this.content.height(this.element.height() - outerHeight(this.header)); } }, createLayout: function(rows) { var headers = this._headers(rows); var colgroup = this._colgroup(); var tree = this._headerTree; var header = kendoDomElement("thead", null, headers); var table = kendoDomElement("table", { style: { width: this._tableWidth + "px"} }, [colgroup, header]); tree.render([table]); this.headerRow = this.header.find("table:first tr").last(); }, _slotDimensions: function() { var headers = this.headerRow[0].children; var slots = this._timeSlots(); var slot; var header; for (var i = 0, length = headers.length; i < length; i++) { header = headers[i]; slot = slots[i]; slot.offsetLeft = header.offsetLeft; slot.offsetWidth = header.offsetWidth; } }, render: function(tasks) { var taskCount = tasks.length; var styles = GanttView.styles; var contentTable; var rowsTable = this._rowsTable(taskCount); var columnsTable = this._columnsTable(taskCount); var tasksTable = this._tasksTable(tasks); var currentTimeMarker = this.options.currentTimeMarker; var calculatedSize = this.options.calculatedSize; var totalHeight; this._taskTree.render([rowsTable, columnsTable, tasksTable]); contentTable = this.content.find(DOT + styles.rowsTable); if (calculatedSize) { totalHeight = calculatedSize.row * tasks.length; this.content.find(DOT + styles.tasksTable).height(totalHeight); contentTable.height(totalHeight); } this._contentHeight = contentTable.height(); this._rowHeight = calculatedSize ? calculatedSize.row : this._contentHeight / contentTable.find("tr").length; this.content.find(DOT + styles.columnsTable).height(this._contentHeight); if (currentTimeMarker !== false && currentTimeMarker.updateInterval !== undefined) { this._renderCurrentTime(); } }, _rowsTable: function(rowCount) { var rows = []; var row; var styles = GanttView.styles; var attributes = [null, { className: styles.alt }]; for (var i = 0; i < rowCount; i++) { row = kendoDomElement("tr", attributes[i % 2], [ kendoDomElement("td", null, [ kendoTextElement("\u00a0") ]) ]); rows.push(row); } return this._createTable(1, rows, { className: styles.rowsTable }); }, _columnsTable: function() { var cells = []; var row; var styles = GanttView.styles; var slots = this._timeSlots(); var slotsCount = slots.length; var slot; var slotSpan; var totalSpan = 0; var attributes; for (var i = 0; i < slotsCount; i++) { slot = slots[i]; attributes = {}; slotSpan = slot.span; totalSpan += slotSpan; if (slotSpan !== 1) { attributes.colspan = slotSpan; } if (slot.isNonWorking) { attributes.className = styles.nonWorking; } cells.push(kendoDomElement("td", attributes, [ kendoTextElement("\u00a0") ])); } row = kendoDomElement("tr", null, cells); return this._createTable(totalSpan, [row], { className: styles.columnsTable}); }, _tasksTable: function(tasks) { var rows = []; var row; var cell; var position; var task; var styles = GanttView.styles; var coordinates = this._taskCoordinates = {}; var size = this._calculateMilestoneWidth(); var milestoneWidth = Math.round(size.width); var resourcesField = this.options.resourcesField; var className = [styles.resource, styles.resourceAlt]; var calculatedSize = this.options.calculatedSize; var resourcesPosition; var resourcesMargin = this._calculateResourcesMargin(); var taskBorderWidth = this._calculateTaskBorderWidth(); var resourceStyle; var addCoordinates = function(rowIndex) { var taskLeft; var taskRight; taskLeft = position.left; taskRight = taskLeft + position.width; if (task.isMilestone()) { taskLeft -= milestoneWidth / 2; taskRight = taskLeft + milestoneWidth; } coordinates[task.id] = { start: taskLeft, end: taskRight, rowIndex: rowIndex }; }; for (var i = 0, l = tasks.length; i < l; i++) { task = tasks[i]; position = this._taskPosition(task); position.borderWidth = taskBorderWidth; row = kendoDomElement("tr", null); cell = kendoDomElement("td"); if (task.start <= this.end && task.end >= this.start) { cell.children.push(this._renderTask(tasks[i], position)); if (task[resourcesField] && task[resourcesField].length) { if (isRtl) { resourcesPosition = this._tableWidth - position.left; } else { resourcesPosition = Math.max((position.width || size.clientWidth), 0) + position.left; } resourceStyle = { width: (this._tableWidth - (resourcesPosition + resourcesMargin)) + "px" }; resourceStyle[isRtl ? "right" : "left"] = resourcesPosition + "px"; if (calculatedSize) { resourceStyle.height = calculatedSize.cell + "px"; } cell.children.push(kendoDomElement("div", { className: styles.resourcesWrap, style: resourceStyle }, this._renderResources(task[resourcesField], className[i % 2])) ); } addCoordinates(i); } row.children.push(cell); rows.push(row); } return this._createTable(1, rows, { className: GanttView.styles.tasksTable }); }, _createTable: function(colspan, rows, styles) { var cols = []; var colgroup; var tbody; for (var i = 0; i < colspan; i++) { cols.push(kendoDomElement("col")); } colgroup = kendoDomElement("colgroup", null, cols); tbody = kendoDomElement("tbody", null, rows); if (!styles.style) { styles.style = {}; } styles.style.width = this._tableWidth + "px"; return kendoDomElement("table", styles, [colgroup, tbody]); }, _calculateTableWidth: function() { var slots = this._timeSlots(); var maxSpan = 0; var totalSpan = 0; var currentSpan; var tableWidth; for (var i = 0, length = slots.length; i < length; i++) { currentSpan = slots[i].span; totalSpan += currentSpan; if (currentSpan > maxSpan) { maxSpan = currentSpan; } } tableWidth = Math.round((totalSpan * this.options.slotSize) / maxSpan); return tableWidth; }, _calculateMilestoneWidth: function() { var size; var className = GanttView.styles.task + " " + GanttView.styles.taskMilestone; var milestone = $("<div class='" + className + "' style='visibility: hidden; position: absolute'>"); var boundingClientRect; this.content.append(milestone); boundingClientRect = milestone[0].getBoundingClientRect(); size = { "width": boundingClientRect.right - boundingClientRect.left, "clientWidth": milestone[0].clientWidth }; milestone.remove(); return size; }, _calculateResourcesMargin: function() { var margin; var wrapper = $("<div class='" + GanttView.styles.resourcesWrap + "' style='visibility: hidden; position: absolute'>"); 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 = $("<div class='" + className + "' style='visibility: hidden; position: absolute'>"); 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 && editable.dependencyCreate !== false) { 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 && editable.dragPercentComplete !== false && editable.update !== false && 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; var editable = this.options.editable; 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 (editable) { if (editable.destroy !== false) { content.children.push(kendoDomElement("span", { className: styles.taskActions }, [ kendoDomElement("a", { className: styles.link + " " + styles.taskDelete, href: "#", "aria-label": "Delete" }, [ kendoDomElement("span", { className: styles.icon + " " + styles.iconDelete }) ]) ])); } if (editable.resize !== false && editable.update !== false) { 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; // Add one pixel for border } 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 = outerWidth(this._resizeTooltip); tooltipHeight = outerHeight(this._resizeTooltip); 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(outerWidth(tooltip) / 2); var arrow = tooltip.find(DOT + GanttView.styles.callout); var arrowHeight = Math.round(outerWidth(arrow) / 2); tooltip.css({ "top": top - (outerHeight(tooltip) + 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; } $("<div class='" + styles.line + " " + styles.lineHorizontal + " " + styles.dependencyHint + "'></div>") .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 = $("<kvml:line class='" + GanttView.styles.dependencyHint + "' style='position:absolute; top: 0px; left: 0px;' strokecolor='black' strokeweight='2px' from='" + from.x + "px," + from.y + "px' to='" + to.x + "px," + to.y + "px'" + "></kvml:line>") .appendTo(this.content); // IE8 Bug 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 + outerHeight(row) - contentOffset.top) + content.scrollTop(); var tooltip = this._taskTooltip = $('<div style="z-index: 100002;" class="' +styles.tooltipWrapper + '" >' + '<div class="' + styles.taskContent + '"></div></div>'); 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 (outerHeight(tooltip) < rowOffset.top - contentOffset.top) { tooltip.css("top", ((rowOffset.top - contentOffset.top) - outerHeight(tooltip)) + content.scrollTop()); } tooltipWidth = outerWidth(tooltip); 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 = kend