(function(global2, factory) { typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define(["exports"], factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, factory(global2.dhtmlxgantt = {})); })(this, function(exports2) { "use strict";/** @license dhtmlxGantt v.9.1.1 Standard This version of dhtmlxGantt is distributed under GPL 2.0 license and can be legally used in GPL projects. To use dhtmlxGantt in non-GPL projects (and get Pro version of the product), please obtain Individual, Commercial, Enterprise or Ultimate license on our site https://dhtmlx.com/docs/products/dhtmlxGantt/#licensing or contact us at info@dhtmlx.com (c) XB Software */ function getNodePosition(elem) { var top = 0, left = 0, right = 0, bottom = 0; if (elem.getBoundingClientRect) { var box = elem.getBoundingClientRect(); var body = document.body; var docElem = document.documentElement || document.body.parentNode || document.body; var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop; var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft; var clientTop = docElem.clientTop || body.clientTop || 0; var clientLeft = docElem.clientLeft || body.clientLeft || 0; top = box.top + scrollTop - clientTop; left = box.left + scrollLeft - clientLeft; right = document.body.offsetWidth - box.right; bottom = document.body.offsetHeight - box.bottom; } else { while (elem) { top = top + parseInt(elem.offsetTop, 10); left = left + parseInt(elem.offsetLeft, 10); elem = elem.offsetParent; } right = document.body.offsetWidth - elem.offsetWidth - left; bottom = document.body.offsetHeight - elem.offsetHeight - top; } return { y: Math.round(top), x: Math.round(left), width: elem.offsetWidth, height: elem.offsetHeight, right: Math.round(right), bottom: Math.round(bottom) }; } function isVisible(node) { var display = false, visibility = false; if (window.getComputedStyle) { var style = window.getComputedStyle(node, null); display = style["display"]; visibility = style["visibility"]; } else if (node.currentStyle) { display = node.currentStyle["display"]; visibility = node.currentStyle["visibility"]; } return display != "none" && visibility != "hidden"; } function hasNonNegativeTabIndex(node) { return !isNaN(node.getAttribute("tabindex")) && node.getAttribute("tabindex") * 1 >= 0; } function hasHref(node) { var canHaveHref = { a: true, area: true }; if (canHaveHref[node.nodeName.loLowerCase()]) { return !!node.getAttribute("href"); } return true; } function isEnabled(node) { var canDisable = { input: true, select: true, textarea: true, button: true, object: true }; if (canDisable[node.nodeName.toLowerCase()]) { return !node.hasAttribute("disabled"); } return true; } function getFocusableNodes(root) { var nodes = root.querySelectorAll(["a[href]", "area[href]", "input", "select", "textarea", "button", "iframe", "object", "embed", "[tabindex]", "[contenteditable]"].join(", ")); var nodesArray = Array.prototype.slice.call(nodes, 0); for (var i = 0; i < nodesArray.length; i++) { nodesArray[i].$position = i; } nodesArray.sort(function(a, b) { if (a.tabIndex === 0 && b.tabIndex !== 0) { return 1; } if (a.tabIndex !== 0 && b.tabIndex === 0) { return -1; } if (a.tabIndex === b.tabIndex) { return a.$position - b.$position; } if (a.tabIndex < b.tabIndex) { return -1; } return 1; }); for (var i = 0; i < nodesArray.length; i++) { var node = nodesArray[i]; var isValid = (hasNonNegativeTabIndex(node) || isEnabled(node) || hasHref(node)) && isVisible(node); if (!isValid) { nodesArray.splice(i, 1); i--; } } return nodesArray; } function getScrollSize() { var div = document.createElement("div"); div.style.cssText = "visibility:hidden;position:absolute;left:-1000px;width:100px;padding:0px;margin:0px;height:110px;min-height:100px;overflow-y:scroll;"; document.body.appendChild(div); var width = div.offsetWidth - div.clientWidth; document.body.removeChild(div); return Math.max(width, 15); } function getClassName(node) { if (!node) return ""; var className = node.className || ""; if (className.baseVal) className = className.baseVal; if (!className.indexOf) className = ""; return _trimString(className); } function addClassName(node, className) { if (className && node.className.indexOf(className) === -1) { node.className += " " + className; } } function removeClassName(node, name) { name = name.split(" "); for (var i = 0; i < name.length; i++) { var regEx = new RegExp("\\s?\\b" + name[i] + "\\b(?![-_.])", ""); node.className = node.className.replace(regEx, ""); } } function hasClass(element, className) { if ("classList" in element) { return element.classList.contains(className); } else { return new RegExp("\\b" + className + "\\b").test(element.className); } } function toNode(node) { if (typeof node === "string") { return document.getElementById(node) || document.querySelector(node) || document.body; } return node || document.body; } var _slave; function insertNode(node, newone) { if (!_slave) { _slave = document.createElement("div"); } _slave.innerHTML = newone; var child = _slave.firstChild; node.appendChild(child); return child; } function removeNode(node) { if (node && node.parentNode) { node.parentNode.removeChild(node); } } function getChildNodes(node, css) { var ch = node.childNodes; var len = ch.length; var out = []; for (var i = 0; i < len; i++) { var obj = ch[i]; if (obj.className && obj.className.indexOf(css) !== -1) { out.push(obj); } } return out; } function getTargetNode(e) { var trg; if (e.tagName) trg = e; else { e = e || window.event; trg = e.target || e.srcElement; if (trg.shadowRoot && e.composedPath) { trg = e.composedPath()[0]; } } return trg; } function locateAttribute(e, attribute) { if (!attribute) return; var trg = getTargetNode(e); while (trg) { if (trg.getAttribute) { var test = trg.getAttribute(attribute); if (test) return trg; } trg = trg.parentNode || trg.host; } return null; } function _trimString(str) { var func = String.prototype.trim || function() { return this.replace(/^\s+|\s+$/g, ""); }; return func.apply(str); } function locateClassName(e, classname, strict) { var trg = getTargetNode(e); var css = ""; if (strict === void 0) strict = true; while (trg) { css = getClassName(trg); if (css) { var ind = css.indexOf(classname); if (ind >= 0) { if (!strict) return trg; var left = ind === 0 || !_trimString(css.charAt(ind - 1)); var right = ind + classname.length >= css.length || !_trimString(css.charAt(ind + classname.length)); if (left && right) return trg; } } trg = trg.parentNode; } return null; } function getRelativeEventPosition(ev, node) { var _a; const d = document.documentElement; const box = getNodePosition(node); const { clientX, clientY } = ((_a = ev.touches) == null ? void 0 : _a[0]) ?? ev; return { x: clientX + d.scrollLeft - d.clientLeft - box.x + node.scrollLeft, y: clientY + d.scrollTop - d.clientTop - box.y + node.scrollTop }; } function getRelativeNodePosition(child, parent) { const childPos = getNodePosition(child); const parentPos = getNodePosition(parent); return { x: childPos.x - parentPos.x, y: childPos.y - parentPos.y }; } function isChildOf(child, parent) { if (!child || !parent) { return false; } while (child && child != parent) { child = child.parentNode; } return child === parent; } function closest(element, selector) { if (element.closest) { return element.closest(selector); } else if (element.matches || element.msMatchesSelector || element.webkitMatchesSelector) { var el = element; if (!document.documentElement.contains(el)) return null; do { var method = el.matches || el.msMatchesSelector || el.webkitMatchesSelector; if (method.call(el, selector)) return el; el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; } else { console.error("Your browser is not supported"); return null; } } function getClosestSizedElement(element) { while (element) { if (element.offsetWidth > 0 && element.offsetHeight > 0) { return element; } element = element.parentElement; } return null; } function isShadowDomSupported() { return document.head.createShadowRoot || document.head.attachShadow; } function getActiveElement() { var activeElement = document.activeElement; if (activeElement.shadowRoot) { activeElement = activeElement.shadowRoot.activeElement; } if (activeElement === document.body && document.getSelection) { activeElement = document.getSelection().focusNode || document.body; } return activeElement; } function getRootNode(element) { if (!element) { return document.body; } if (!isShadowDomSupported()) { return document.body; } while (element.parentNode && (element = element.parentNode)) { if (element instanceof ShadowRoot) { return element.host; } } return document.body; } function hasShadowParent(element) { return !!getRootNode(element); } const domHelpers = Object.freeze(Object.defineProperty({ __proto__: null, addClassName, closest, getActiveElement, getChildNodes, getClassName, getClosestSizedElement, getFocusableNodes, getNodePosition, getRelativeEventPosition, getRelativeNodePosition, getRootNode, getScrollSize, getTargetNode, hasClass, hasShadowParent, insertNode, isChildOf, isShadowDomSupported, locateAttribute, locateClassName, removeClassName, removeNode, toNode }, Symbol.toStringTag, { value: "Module" })); var globalScope; if (typeof window !== "undefined") { globalScope = window; } else { globalScope = global; } const scope = globalScope; let EventsManager$1 = class EventsManager { constructor(gantt2) { this._mouseDown = false; this._touchStarts = false; this._touchActive = false; this._longTapTimer = false; this._gantt = gantt2; this._domEvents = gantt2._createDomEventScope(); } attach(selectedRegion, useKey, ignore) { const gantt2 = this._gantt; const _target = selectedRegion.getViewPort(); this._originPosition = scope.getComputedStyle(_target).display; this._restoreOriginPosition = () => { _target.style.position = this._originPosition; }; if (this._originPosition === "static") { _target.style.position = "relative"; } const state = gantt2.$services.getService("state"); state.registerProvider("clickDrag", () => { const result = { autoscroll: false }; return result; }); let scheduledDndCoordinates = null; const startDragAndDrop = () => { if (!scheduledDndCoordinates) { return; } this._mouseDown = true; selectedRegion.setStart(gantt2.copy(scheduledDndCoordinates)); selectedRegion.setPosition(gantt2.copy(scheduledDndCoordinates)); selectedRegion.setEnd(gantt2.copy(scheduledDndCoordinates)); scheduledDndCoordinates = null; }; this._domEvents.attach(_target, "mousedown", (event2) => { startDrag(event2); }); const eventElement = getRootNode(gantt2.$root) || document.body; this._domEvents.attach(eventElement, "mouseup", (event2) => { stopDrag(event2); }); this._domEvents.attach(_target, "mousemove", (event2) => { dragMove(event2); }); this._domEvents.attach(_target, "touchstart", (event2) => { this._touchStarts = true; this._longTapTimer = setTimeout(() => { if (this._touchStarts) { startDrag(getTouchEvent(event2)); this._touchStarts = false; this._touchActive = true; } }, this._gantt.config.touch_drag); }); this._domEvents.attach(eventElement, "touchend", (event2) => { this._touchStarts = false; this._touchActive = false; clearTimeout(this._longTapTimer); stopDrag(getTouchEvent(event2)); }); this._domEvents.attach(_target, "touchmove", (event2) => { if (this._touchActive) { let filterTargets = getFilterTargets(); if (filterTargets && gantt2.utils.dom.closest(event2.target, filterTargets)) { return; } dragMove(getTouchEvent(event2)); event2.preventDefault(); } else { this._touchStarts = false; clearTimeout(this._longTapTimer); } }); function getTouchEvent(event2) { const touchEvent = event2.changedTouches && event2.changedTouches[0] || event2; return touchEvent; } const getFilterTargets = () => { let filterTargets = ".gantt_task_line, .gantt_task_link"; if (ignore !== void 0) { if (ignore instanceof Array) { filterTargets = ignore.join(", "); } else { filterTargets = ignore; } } return filterTargets; }; const startDrag = (event2) => { scheduledDndCoordinates = null; let filterTargets = getFilterTargets(); if (filterTargets) { if (gantt2.utils.dom.closest(event2.target, filterTargets)) { return; } } state.registerProvider("clickDrag", () => { const result = { autoscroll: this._mouseDown }; return result; }); if (useKey && event2[useKey] !== true) { return; } scheduledDndCoordinates = this._getCoordinates(event2, selectedRegion); }; const stopDrag = (event2) => { scheduledDndCoordinates = null; if (useKey && event2[useKey] !== true) { return; } if (this._mouseDown === true) { this._mouseDown = false; const coordinates = this._getCoordinates(event2, selectedRegion); selectedRegion.dragEnd(coordinates); } }; const dragMove = (event2) => { if (useKey && event2[useKey] !== true) { return; } const dragTimeline = this._gantt.ext.clickDrag; const dragTimelineUseKey = (this._gantt.config.drag_timeline || {}).useKey; if (dragTimeline && dragTimelineUseKey) { if (!useKey && event2[dragTimelineUseKey]) { return; } } let coordinates = null; if (!this._mouseDown && scheduledDndCoordinates) { coordinates = this._getCoordinates(event2, selectedRegion); if (Math.abs(scheduledDndCoordinates.relative.left - coordinates.relative.left) > 5) { startDragAndDrop(); } return; } if (this._mouseDown === true) { coordinates = this._getCoordinates(event2, selectedRegion); selectedRegion.setEnd(coordinates); selectedRegion.render(); } }; } detach() { const gantt2 = this._gantt; this._domEvents.detachAll(); if (this._restoreOriginPosition) { this._restoreOriginPosition(); } const state = gantt2.$services.getService("state"); state.unregisterProvider("clickDrag"); } destructor() { this.detach(); } _getCoordinates(event2, selectedRegion) { const viewPort = selectedRegion.getViewPort(); const viewPortBounds = viewPort.getBoundingClientRect(); const { clientX, clientY } = event2; const result = { absolute: { left: clientX, top: clientY }, relative: { left: clientX - viewPortBounds.left + viewPort.scrollLeft, top: clientY - viewPortBounds.top + viewPort.scrollTop } }; return result; } }; var EventHost = function() { this._silent_mode = false; this.listeners = {}; }; EventHost.prototype = { _silentStart: function() { this._silent_mode = true; }, _silentEnd: function() { this._silent_mode = false; } }; var createEventStorage = function(obj) { var handlers = {}; var index = 0; var eventStorage = function() { var combinedResult = true; for (var i in handlers) { var handlerResult = handlers[i].apply(obj, arguments); combinedResult = combinedResult && handlerResult; } return combinedResult; }; eventStorage.addEvent = function(handler, settings) { if (typeof handler == "function") { var handlerId; if (settings && settings.id) { handlerId = settings.id; } else { handlerId = index; index++; } if (settings && settings.once) { var originalHandler = handler; handler = function() { originalHandler(); eventStorage.removeEvent(handlerId); }; } handlers[handlerId] = handler; return handlerId; } return false; }; eventStorage.removeEvent = function(id) { delete handlers[id]; }; eventStorage.clear = function() { handlers = {}; }; return eventStorage; }; function makeEventable(obj) { var eventHost = new EventHost(); obj.attachEvent = function(eventName, handler, settings) { eventName = "ev_" + eventName.toLowerCase(); if (!eventHost.listeners[eventName]) { eventHost.listeners[eventName] = createEventStorage(this); } if (settings && settings.thisObject) { handler = handler.bind(settings.thisObject); } var innerId = eventHost.listeners[eventName].addEvent(handler, settings); var handlerId = eventName + ":" + innerId; if (settings && settings.id) { handlerId = settings.id; } return handlerId; }; obj.attachAll = function(callback) { this.attachEvent("listen_all", callback); }; obj.callEvent = function(name, eventArguments) { if (eventHost._silent_mode) return true; var handlerName = "ev_" + name.toLowerCase(); var listeners = eventHost.listeners; if (listeners["ev_listen_all"]) { listeners["ev_listen_all"].apply(this, [name].concat(eventArguments)); } if (listeners[handlerName]) return listeners[handlerName].apply(this, eventArguments); return true; }; obj.checkEvent = function(name) { var listeners = eventHost.listeners; return !!listeners["ev_" + name.toLowerCase()]; }; obj.detachEvent = function(id) { if (id) { var listeners = eventHost.listeners; for (var i in listeners) { listeners[i].removeEvent(id); } var list = id.split(":"); var listeners = eventHost.listeners; if (list.length === 2) { var eventName = list[0]; var eventId = list[1]; if (listeners[eventName]) { listeners[eventName].removeEvent(eventId); } } } }; obj.detachAllEvents = function() { for (var name in eventHost.listeners) { eventHost.listeners[name].clear(); } }; } var units = { second: 1, minute: 60, hour: 60 * 60, day: 60 * 60 * 24, week: 60 * 60 * 24 * 7, month: 60 * 60 * 24 * 30, quarter: 60 * 60 * 24 * 30 * 3, year: 60 * 60 * 24 * 365 }; function getSecondsInUnit(unit) { return units[unit] || units.hour; } function forEach(arr, callback) { if (arr.forEach) { arr.forEach(callback); } else { var workArray = arr.slice(); for (var i = 0; i < workArray.length; i++) { callback(workArray[i], i); } } } function arrayMap(arr, callback) { if (arr.map) { return arr.map(callback); } else { var workArray = arr.slice(); var resArray = []; for (var i = 0; i < workArray.length; i++) { resArray.push(callback(workArray[i], i)); } return resArray; } } function arrayFind(arr, callback) { if (arr.find) { return arr.find(callback); } else { for (var i = 0; i < arr.length; i++) { if (callback(arr[i], i)) { return arr[i]; } } } } function arrayIncludes(arr, item) { if (arr.includes) { return arr.includes(item); } else { for (var i = 0; i < arr.length; i++) { if (arr[i] === item) { return true; } } return false; } } function isArray(obj) { if (Array.isArray) { return Array.isArray(obj); } else { return obj && obj.length !== void 0 && obj.pop && obj.push; } } function isDate(obj) { if (obj && typeof obj === "object") { return !!(obj.getFullYear && obj.getMonth && obj.getDate); } else { return false; } } function isValidDate(obj) { return isDate(obj) && !isNaN(obj.getTime()); } function arrayFilter(arr, callback) { var result = []; if (arr.filter) { return arr.filter(callback); } else { for (var i = 0; i < arr.length; i++) { if (callback(arr[i], i)) { result[result.length] = arr[i]; } } return result; } } function throttle(callback, timeout) { var wait = false; return function() { if (!wait) { callback.apply(null, arguments); wait = true; setTimeout(function() { wait = false; }, timeout); } }; } function delay(callback, timeout) { var timer; var result = function() { result.$cancelTimeout(); result.$pending = true; var args = Array.prototype.slice.call(arguments); timer = setTimeout(function() { callback.apply(this, args); result.$pending = false; }, timeout); }; result.$pending = false; result.$cancelTimeout = function() { clearTimeout(timer); result.$pending = false; }; result.$execute = function() { var args = Array.prototype.slice.call(arguments); callback.apply(this, args); result.$cancelTimeout(); }; return result; } function isEventable(obj) { return obj.attachEvent && obj.detachEvent; } function replaceValidZeroId(id, rootId) { if (checkZeroId(id) && !checkZeroId(rootId)) { id = "0"; } return id; } function checkZeroId(id) { if (id === 0) { return true; } return false; } function findBinary(array, target) { var low = 0, high = array.length - 1, i, item, prev; while (low <= high) { i = Math.floor((low + high) / 2); item = +array[i]; prev = +array[i - 1]; if (item < target) { low = i + 1; continue; } if (item > target) { if (!(!isNaN(prev) && prev < target)) { high = i - 1; continue; } else { return i - 1; } } while (+array[i] == +array[i + 1]) i++; return i; } return array.length - 1; } class SelectedRegion { constructor(config2, gantt2, view) { this._el = document.createElement("div"); this.defaultRender = (start, end) => { if (!this._el) { this._el = document.createElement("div"); } const node = this._el; const top = Math.min(start.relative.top, end.relative.top); const bottom = Math.max(start.relative.top, end.relative.top); const left = Math.min(start.relative.left, end.relative.left); const right = Math.max(start.relative.left, end.relative.left); if (this._singleRow) { const pos = this._getTaskPositionByTop(this._startPoint.relative.top); node.style.height = pos.height + "px"; node.style.top = pos.top + "px"; } else { node.style.height = Math.abs(bottom - top) + "px"; node.style.top = top + "px"; } node.style.width = Math.abs(right - left) + "px"; node.style.left = left + "px"; return node; }; this._gantt = gantt2; this._view = view; this._viewPort = config2.viewPort; this._el.classList.add(config2.className); if (typeof config2.callback === "function") { this._callback = config2.callback; } this.render = () => { let node; if (config2.render) { node = config2.render(this._startPoint, this._endPoint); } else { node = this.defaultRender(this._startPoint, this._endPoint); } if (node !== this._el) { if (this._el && this._el.parentNode) { this._el.parentNode.removeChild(this._el); } this._el = node; } if (config2.className !== "") { this._el.classList.add(config2.className); } this.draw(); }; if (!isEventable(this._viewPort)) { makeEventable(this._viewPort); } this._singleRow = config2.singleRow; this._useRequestAnimationFrame = config2.useRequestAnimationFrame; } draw() { if (this._useRequestAnimationFrame) { return requestAnimationFrame(() => { this._viewPort.appendChild(this.getElement()); }); } else { this._viewPort.appendChild(this.getElement()); } } clear() { if (this._useRequestAnimationFrame) { return requestAnimationFrame(() => { if (!this._el.parentNode) { return; } this._viewPort.removeChild(this._el); }); } else { if (!this._el.parentNode) { return; } this._viewPort.removeChild(this._el); } } getElement() { return this._el; } getViewPort() { return this._viewPort; } setStart(startPoint) { const gantt2 = this._gantt; this._startPoint = startPoint; this._startDate = gantt2.dateFromPos(this._startPoint.relative.left); this._viewPort.callEvent("onBeforeDrag", [this._startPoint]); } setEnd(endPoint) { const gantt2 = this._gantt; this._endPoint = endPoint; if (this._singleRow) { const pos = this._getTaskPositionByTop(this._startPoint.relative.top); this._endPoint.relative.top = pos.top; } this._endDate = gantt2.dateFromPos(this._endPoint.relative.left); if (this._startPoint.relative.left > this._endPoint.relative.left) { this._positionPoint = { relative: { left: this._endPoint.relative.left, top: this._positionPoint.relative.top }, absolute: { left: this._endPoint.absolute.left, top: this._positionPoint.absolute.top } }; } if (this._startPoint.relative.top > this._endPoint.relative.top) { this._positionPoint = { relative: { left: this._positionPoint.relative.left, top: this._endPoint.relative.top }, absolute: { left: this._positionPoint.absolute.left, top: this._endPoint.absolute.top } }; } this._viewPort.callEvent("onDrag", [this._startPoint, this._endPoint]); } setPosition(positionPoint) { this._positionPoint = positionPoint; } dragEnd(endPoint) { const gantt2 = this._gantt; if (endPoint.relative.left < 0) { endPoint.relative.left = 0; } this._viewPort.callEvent("onBeforeDragEnd", [this._startPoint, endPoint]); this.setEnd(endPoint); this._endDate = this._endDate || gantt2.getState().max_date; if (this._startDate.valueOf() > this._endDate.valueOf()) { [this._startDate, this._endDate] = [this._endDate, this._startDate]; } this.clear(); const tasksByTime = gantt2.getTaskByTime(this._startDate, this._endDate); const tasksByIndex = this._getTasksByTop(this._startPoint.relative.top, this._endPoint.relative.top); this._viewPort.callEvent("onDragEnd", [this._startPoint, this._endPoint]); if (this._callback) { this._callback(this._startPoint, this._endPoint, this._startDate, this._endDate, tasksByTime, tasksByIndex); } } getInBounds() { return this._singleRow; } _getTasksByTop(start, end) { const gantt2 = this._gantt; let startValue = start; let endValue = end; if (start > end) { startValue = end; endValue = start; } const startIndex = this._getTaskPositionByTop(startValue).index; const endIndex = this._getTaskPositionByTop(endValue).index; const result = []; for (let i = startIndex; i <= endIndex; i++) { const task = gantt2.getTaskByIndex(i); if (task) { result.push(gantt2.getTaskByIndex(i)); } } return result; } _getTaskPositionByTop(top) { const gantt2 = this._gantt; const view = this._view; const index = view.getItemIndexByTopPosition(top); const task = gantt2.getTaskByIndex(index); if (task) { const height = view.getItemHeight(task.id); const itemTop = view.getItemTop(task.id); return { top: itemTop || 0, height: height || 0, index }; } else { const dataHeight = view.getTotalHeight(); return { top: top > dataHeight ? dataHeight : 0, height: gantt2.config.row_height, index: top > dataHeight ? gantt2.getTaskCount() : 0 }; } } } function click_drag(gantt2) { if (!gantt2.ext) { gantt2.ext = {}; } const defaultConfig = { className: "gantt_click_drag_rect", useRequestAnimationFrame: true, callback: void 0, singleRow: false }; function setClickDrag() { const config2 = { viewPort: gantt2.$task_data, ...defaultConfig }; if (gantt2.ext.clickDrag) { gantt2.ext.clickDrag.destructor(); } gantt2.ext.clickDrag = new EventsManager$1(gantt2); const clickDrag = gantt2.config.click_drag; config2.render = clickDrag.render || defaultConfig.render; config2.className = clickDrag.className || defaultConfig.className; config2.callback = clickDrag.callback || defaultConfig.callback; config2.viewPort = clickDrag.viewPort || gantt2.$task_data; config2.useRequestAnimationFrame = clickDrag.useRequestAnimationFrame === void 0 ? defaultConfig.useRequestAnimationFrame : clickDrag.useRequestAnimationFrame; config2.singleRow = clickDrag.singleRow === void 0 ? defaultConfig.singleRow : clickDrag.singleRow; const timeline = gantt2.$ui.getView("timeline"); const selectedRegion = new SelectedRegion(config2, gantt2, timeline); gantt2.ext.clickDrag.attach(selectedRegion, clickDrag.useKey, clickDrag.ignore); } gantt2.attachEvent("onGanttReady", () => { if (gantt2.config.click_drag) { setClickDrag(); } }); gantt2.attachEvent("onGanttLayoutReady", function() { if (gantt2.$container && gantt2.config.click_drag) { gantt2.attachEvent("onGanttRender", function() { setClickDrag(); }, { once: true }); } }); gantt2.attachEvent("onDestroy", () => { if (gantt2.ext.clickDrag) { gantt2.ext.clickDrag.destructor(); } }); } let _dragInProgress = false; class EventsManager { constructor(gantt2) { this._mouseDown = false; this._calculateDirectionVector = () => { const traceSteps = 10; if (this._trace.length >= traceSteps) { const dots = this._trace.slice(this._trace.length - traceSteps); const vectors = []; for (let i = 1; i < dots.length; i++) { vectors.push({ x: dots[i].x - dots[i - 1].x, y: dots[i].y - dots[i - 1].y }); } const resultVector = { x: 0, y: 0 }; vectors.forEach((vector) => { resultVector.x += vector.x; resultVector.y += vector.y; }); const magnitude = Math.sqrt(resultVector.x * resultVector.x + resultVector.y * resultVector.y); const angleDegrees = Math.atan2(Math.abs(resultVector.y), Math.abs(resultVector.x)) * 180 / Math.PI; return { magnitude, angleDegrees }; } return null; }; this._applyDndReadyStyles = () => { this._timeline.$task.classList.add("gantt_timeline_move_available"); }; this._clearDndReadyStyles = () => { this._timeline.$task.classList.remove("gantt_timeline_move_available"); }; this._getScrollPosition = (timeline) => { const gantt3 = this._gantt; return { x: gantt3.$ui.getView(timeline.$config.scrollX).getScrollState().position, y: gantt3.$ui.getView(timeline.$config.scrollY).getScrollState().position }; }; this._countNewScrollPosition = (coords) => { const vector = this._calculateDirectionVector(); let shiftX = this._startPoint.x - coords.x; let shiftY = this._startPoint.y - coords.y; if (vector) { if (vector.angleDegrees < 15) { shiftY = 0; } else if (vector.angleDegrees > 75) { shiftX = 0; } } const result = { x: this._scrollState.x + shiftX, y: this._scrollState.y + shiftY }; return result; }; this._setScrollPosition = (timeline, coords) => { const gantt3 = this._gantt; requestAnimationFrame(() => { gantt3.scrollLayoutCell(timeline.$id, coords.x, coords.y); }); }; this._stopDrag = (event2) => { const gantt3 = this._gantt; this._trace = []; gantt3.$root.classList.remove("gantt_noselect"); if (this._originalReadonly !== void 0 && this._mouseDown) { gantt3.config.readonly = this._originalReadonly; if (gantt3.config.drag_timeline && gantt3.config.drag_timeline.render) { gantt3.render(); } } if (this._originAutoscroll !== void 0) { gantt3.config.autoscroll = this._originAutoscroll; } if (gantt3.config.drag_timeline) { const { useKey } = gantt3.config.drag_timeline; if (useKey && event2[useKey] !== true) { return; } } this._mouseDown = false; _dragInProgress = false; }; this._startDrag = (event2) => { const gantt3 = this._gantt; this._originAutoscroll = gantt3.config.autoscroll; gantt3.config.autoscroll = false; _dragInProgress = true; gantt3.$root.classList.add("gantt_noselect"); this._originalReadonly = gantt3.config.readonly; gantt3.config.readonly = true; if (gantt3.config.drag_timeline && gantt3.config.drag_timeline.render) { gantt3.render(); } this._trace = []; this._mouseDown = true; const { x, y } = this._getScrollPosition(this._timeline); this._scrollState = { x, y }; this._startPoint = { x: event2.clientX, y: event2.clientY }; this._trace.push(this._startPoint); }; this._gantt = gantt2; this._domEvents = gantt2._createDomEventScope(); this._trace = []; } static create(gantt2) { return new EventsManager(gantt2); } static _isDragInProgress() { return _dragInProgress; } destructor() { this._domEvents.detachAll(); } attach(timeline) { this._timeline = timeline; const gantt2 = this._gantt; this._domEvents.attach(timeline.$task, "mousedown", (event2) => { if (!gantt2.config.drag_timeline) { return; } const { useKey, ignore, enabled } = gantt2.config.drag_timeline; if (enabled === false) { return; } let filterTargets = ".gantt_task_line, .gantt_task_link"; if (ignore !== void 0) { if (ignore instanceof Array) { filterTargets = ignore.join(", "); } else { filterTargets = ignore; } } if (filterTargets) { if (gantt2.utils.dom.closest(event2.target, filterTargets)) { return; } } if (useKey && event2[useKey] !== true) { return; } this._startDrag(event2); }); this._domEvents.attach(document, "keydown", (event2) => { if (!gantt2.config.drag_timeline) { return; } const { useKey } = gantt2.config.drag_timeline; if (useKey && event2[useKey] === true) { this._applyDndReadyStyles(); } }); this._domEvents.attach(document, "keyup", (event2) => { if (!gantt2.config.drag_timeline) { return; } const { useKey } = gantt2.config.drag_timeline; if (useKey && event2[useKey] === false) { this._clearDndReadyStyles(); this._stopDrag(event2); } }); this._domEvents.attach(document, "mouseup", (event2) => { this._stopDrag(event2); }); this._domEvents.attach(gantt2.$root, "mouseup", (event2) => { this._stopDrag(event2); }); this._domEvents.attach(document, "mouseleave", (event2) => { this._stopDrag(event2); }); this._domEvents.attach(gantt2.$root, "mouseleave", (event2) => { this._stopDrag(event2); }); this._domEvents.attach(gantt2.$root, "mousemove", (event2) => { if (!gantt2.config.drag_timeline) { return; } const { useKey } = gantt2.config.drag_timeline; if (useKey && event2[useKey] !== true) { return; } const clickDrag = this._gantt.ext.clickDrag; const clickDragUseKey = (this._gantt.config.click_drag || {}).useKey; if (clickDrag && clickDragUseKey) { if (!useKey && event2[clickDragUseKey]) { return; } } if (this._mouseDown === true) { this._trace.push({ x: event2.clientX, y: event2.clientY }); const scrollPosition = this._countNewScrollPosition({ x: event2.clientX, y: event2.clientY }); this._setScrollPosition(timeline, scrollPosition); this._scrollState = scrollPosition; this._startPoint = { x: event2.clientX, y: event2.clientY }; } }); } } function drag_timeline(gantt2) { if (!gantt2.ext) { gantt2.ext = {}; } gantt2.ext.dragTimeline = { create: () => EventsManager.create(gantt2), _isDragInProgress: () => EventsManager._isDragInProgress }; gantt2.config.drag_timeline = { enabled: true, render: false }; } var plainObjectConstructor = {}.constructor.toString(); function isCustomType(object) { var constructorString = object.constructor.toString(); return constructorString !== plainObjectConstructor; } function isExternalType(object) { return object.$$typeof && object.$$typeof.toString().includes("react."); } function copy(object) { var i, result; if (object && typeof object == "object") { switch (true) { case isDate(object): result = new Date(object); break; case isArray(object): result = new Array(object.length); for (i = 0; i < object.length; i++) { result[i] = copy(object[i]); } break; default: if (isCustomType(object)) { result = Object.create(object); } else if (isExternalType(object)) { result = object; return result; } else { result = {}; } for (i in object) { if (Object.prototype.hasOwnProperty.apply(object, [i])) result[i] = copy(object[i]); } break; } } return result || object; } function mixin(target, source, force) { for (var f in source) if (target[f] === void 0 || force) target[f] = source[f]; return target; } function defined(obj) { return typeof obj != "undefined"; } var seed; function uid() { if (!seed) seed = (/* @__PURE__ */ new Date()).valueOf(); seed++; return seed; } function bind(functor, object) { if (functor.bind) return functor.bind(object); else return function() { return functor.apply(object, arguments); }; } function event(el, event2, handler, capture) { if (el.addEventListener) el.addEventListener(event2, handler, capture === void 0 ? false : capture); else if (el.attachEvent) el.attachEvent("on" + event2, handler); } function eventRemove(el, event2, handler, capture) { if (el.removeEventListener) el.removeEventListener(event2, handler, capture === void 0 ? false : capture); else if (el.detachEvent) el.detachEvent("on" + event2, handler); } const utils = Object.freeze(Object.defineProperty({ __proto__: null, bind, copy, defined, event, eventRemove, mixin, uid }, Symbol.toStringTag, { value: "Module" })); function ScaleHelper(gantt2) { var dateHelper = gantt2.date; gantt2.$services; return { getSum: function(sizes, from, to) { if (to === void 0) to = sizes.length - 1; if (from === void 0) from = 0; var summ = 0; for (var i = from; i <= to; i++) summ += sizes[i]; return summ; }, setSumWidth: function(sum_width, scale, from, to) { var parts = scale.width; if (to === void 0) to = parts.length - 1; if (from === void 0) from = 0; var length = to - from + 1; if (from > parts.length - 1 || length <= 0 || to > parts.length - 1) return; var oldWidth = this.getSum(parts, from, to); var diff = sum_width - oldWidth; this.adjustSize(diff, parts, from, to); this.adjustSize(-diff, parts, to + 1); scale.full_width = this.getSum(parts); }, splitSize: function(width, count) { var arr = []; for (var i = 0; i < count; i++) arr[i] = 0; this.adjustSize(width, arr); return arr; }, adjustSize: function(width, parts, from, to) { if (!from) from = 0; if (to === void 0) to = parts.length - 1; var length = to - from + 1; var full = this.getSum(parts, from, to); for (var i = from; i <= to; i++) { var share = Math.floor(width * (full ? parts[i] / full : 1 / length)); full -= parts[i]; width -= share; length--; parts[i] += share; } parts[parts.length - 1] += width; }, sortScales: function(scales) { function cellSize(unit, step) { var d = new Date(1970, 0, 1); return dateHelper.add(d, step, unit) - d; } scales.sort(function(a, b) { if (cellSize(a.unit, a.step) < cellSize(b.unit, b.step)) { return 1; } else if (cellSize(a.unit, a.step) > cellSize(b.unit, b.step)) { return -1; } else { return 0; } }); for (var i = 0; i < scales.length; i++) { scales[i].index = i; } }, _prepareScaleObject: function(scale) { var format = scale.format; if (!format) { format = scale.template || scale.date || "%d %M"; } if (typeof format === "string") { format = gantt2.date.date_to_str(format); } return { unit: scale.unit || "day", step: scale.step || 1, format, css: scale.css, projection: scale.projection || null, column_width: scale.column_width || null }; }, primaryScale: function(config2) { const scaleConfig = config2 || gantt2.config; const primaryScale = scaleConfig.scales[0]; const result = { unit: primaryScale.unit, step: primaryScale.step, template: primaryScale.template, format: primaryScale.format, date: primaryScale.date, css: primaryScale.css || gantt2.templates.scale_cell_class, projection: primaryScale.projection || null, column_width: primaryScale.column_width || null }; return this._prepareScaleObject(result); }, getAdditionalScales: function(config2) { const scaleConfig = config2 || gantt2.config; const scales = scaleConfig.scales.slice(1); return scales.map((function(scale) { return this._prepareScaleObject(scale); }).bind(this)); }, prepareConfigs: function(scales, min_coll_width, container_width, scale_height, minDate, maxDate, rtl) { var heights = this.splitSize(scale_height, scales.length); var full_width = container_width; var configs = []; for (var i = scales.length - 1; i >= 0; i--) { var main_scale = i == scales.length - 1; var cfg = this.initScaleConfig(scales[i], minDate, maxDate); if (main_scale) { this.processIgnores(cfg); } if (main_scale && cfg.column_width) { full_width = cfg.column_width * (cfg.display_count || cfg.count); } this.initColSizes(cfg, min_coll_width, full_width, heights[i]); this.limitVisibleRange(cfg); if (main_scale) { full_width = cfg.full_width; } configs.unshift(cfg); } for (var i = 0; i < configs.length - 1; i++) { this.alineScaleColumns(configs[configs.length - 1], configs[i]); } for (var i = 0; i < configs.length; i++) { if (rtl) { this.reverseScale(configs[i]); } this.setPosSettings(configs[i]); } return configs; }, reverseScale: function(scale) { scale.width = scale.width.reverse(); scale.trace_x = scale.trace_x.reverse(); var indexes = scale.trace_indexes; scale.trace_indexes = {}; scale.trace_index_transition = {}; scale.rtl = true; for (var i = 0; i < scale.trace_x.length; i++) { scale.trace_indexes[scale.trace_x[i].valueOf()] = i; scale.trace_index_transition[indexes[scale.trace_x[i].valueOf()]] = i; } return scale; }, setPosSettings: function(config2) { for (var i = 0, len = config2.trace_x.length; i < len; i++) { config2.left.push((config2.width[i - 1] || 0) + (config2.left[i - 1] || 0)); } }, _ignore_time_config: function(date2, scale) { if (gantt2.config.skip_off_time) { var skip = true; var probe = date2; for (var i = 0; i < scale.step; i++) { if (i) { probe = dateHelper.add(date2, i, scale.unit); } skip = skip && !this.isWorkTime(probe, scale.unit); } return skip; } return false; }, processIgnores: function(config2) { config2.ignore_x = {}; config2.display_count = config2.count; }, initColSizes: function(config2, min_col_width, full_width, line_height) { var cont_width = full_width; config2.height = line_height; var column_count = config2.display_count === void 0 ? config2.count : config2.display_count; if (!column_count) column_count = 1; const fixedMode = !isNaN(config2.column_width * 1) && config2.column_width * 1 > 0; if (fixedMode) { const baseCellWidth = config2.column_width * 1; config2.col_width = baseCellWidth; cont_width = baseCellWidth * column_count; } else { config2.col_width = Math.floor(cont_width / column_count); if (min_col_width) { if (config2.col_width < min_col_width) { config2.col_width = min_col_width; cont_width = config2.col_width * column_count; } } } config2.width = []; var ignores = config2.ignore_x || {}; for (var i = 0; i < config2.trace_x.length; i++) { if (ignores[config2.trace_x[i].valueOf()] || config2.display_count == config2.count) { if (fixedMode) { config2.width[i] = config2.col_width; } else { config2.width[i] = 0; } } else { var width = 1; if (config2.unit == "month") { var days = Math.round((dateHelper.add(config2.trace_x[i], config2.step, config2.unit) - config2.trace_x[i]) / (1e3 * 60 * 60 * 24)); width = days; } config2.width[i] = width; } } if (!fixedMode) { this.adjustSize(cont_width - this.getSum(config2.width), config2.width); } config2.full_width = this.getSum(config2.width); }, initScaleConfig: function(config2, min_date, max_date) { var cfg = mixin({ count: 0, col_width: 0, full_width: 0, height: 0, width: [], left: [], trace_x: [], trace_indexes: {}, min_date: new Date(min_date), max_date: new Date(max_date) }, config2); this.eachColumn(config2.unit, config2.step, min_date, max_date, function(date2) { cfg.count++; cfg.trace_x.push(new Date(date2)); cfg.trace_indexes[date2.valueOf()] = cfg.trace_x.length - 1; }); cfg.trace_x_ascending = cfg.trace_x.slice(); return cfg; }, iterateScales: function(lower_scale, upper_scale, from, to, callback) { var upper_dates = upper_scale.trace_x; var lower_dates = lower_scale.trace_x; var prev = from || 0; var end = to || lower_dates.length - 1; var prevUpper = 0; for (var up = 1; up < upper_dates.length; up++) { var target_index = lower_scale.trace_indexes[+upper_dates[up]]; if (target_index !== void 0 && target_index <= end) { if (callback) { callback.apply(this, [prevUpper, up, prev, target_index]); } prev = target_index; prevUpper = up; continue; } } }, alineScaleColumns: function(lower_scale, upper_scale, from, to) { this.iterateScales(lower_scale, upper_scale, from, to, function(upper_start, upper_end, lower_start, lower_end) { var targetWidth = this.getSum(lower_scale.width, lower_start, lower_end - 1); var actualWidth = this.getSum(upper_scale.width, upper_start, upper_end - 1); if (actualWidth != targetWidth) { this.setSumWidth(targetWidth, upper_scale, upper_start, upper_end - 1); } }); }, eachColumn: function(unit, step, min_date, max_date, callback) { var start = new Date(min_date), end = new Date(max_date); if (dateHelper[unit + "_start"]) { start = dateHelper[unit + "_start"](start); } var curr = new Date(start); if (+curr >= +end) { end = dateHelper.add(curr, step, unit); } while (+curr < +end) { callback.call(this, new Date(curr)); var tzOffset = curr.getTimezoneOffset(); curr = dateHelper.add(curr, step, unit); curr = gantt2._correct_dst_change(curr, tzOffset, step, unit); if (dateHelper[unit + "_start"]) curr = dateHelper[unit + "_start"](curr); } }, limitVisibleRange: function(cfg) { var dates = cfg.trace_x; var left = 0, right = cfg.width.length - 1; var diff = 0; if (+dates[0] < +cfg.min_date && left != right) { var width = Math.floor(cfg.width[0] * ((dates[1] - cfg.min_date) / (dates[1] - dates[0]))); diff += cfg.width[0] - width; cfg.width[0] = width; dates[0] = new Date(cfg.min_date); } var last = dates.length - 1; var lastDate = dates[last]; var outDate = dateHelper.add(lastDate, cfg.step, cfg.unit); if (+outDate > +cfg.max_date && last > 0) { var width = cfg.width[last] - Math.floor(cfg.width[last] * ((outDate - cfg.max_date) / (outDate - lastDate))); diff += cfg.width[last] - width; cfg.width[last] = width; } if (diff) { var full = this.getSum(cfg.width); var shared = 0; for (var i = 0; i < cfg.width.length; i++) { var share = Math.floor(diff * (cfg.width[i] / full)); cfg.width[i] += share; shared += share; } this.adjustSize(diff - shared, cfg.width); } } }; } function ScaleIgnoreHelper(gantt2) { var helper = new ScaleHelper(gantt2); helper.processIgnores = function(config2) { var display_count = config2.count; config2.ignore_x = {}; if (gantt2.ignore_time || gantt2.config.skip_off_time) { var ignore = gantt2.ignore_time || function() { return false; }; display_count = 0; for (var i = 0; i < config2.trace_x.length; i++) { if (ignore.call(gantt2, config2.trace_x[i]) || this._ignore_time_config.call(gantt2, config2.trace_x[i], config2)) { config2.ignore_x[config2.trace_x[i].valueOf()] = true; config2.ignored_colls = true; } else { display_count++; } } } config2.display_count = display_count; }; return helper; } function export_api(gantt2) { gantt2.ext = gantt2.ext || {}; gantt2.ext.export_api = gantt2.ext.export_api || { _apiUrl: "https://export.dhtmlx.com/gantt", _preparePDFConfigRaw(config2, type) { let previousDateRage = null; if (config2.start && config2.end) { previousDateRage = { start_date: gantt2.config.start_date, end_date: gantt2.config.end_date }; gantt2.config.start_date = gantt2.date.str_to_date(gantt2.config.date_format)(config2.start); gantt2.config.end_date = gantt2.date.str_to_date(gantt2.config.date_format)(config2.end); } config2 = gantt2.mixin(config2, { name: "gantt." + type, data: gantt2.ext.export_api._serializeHtml() }); if (previousDateRage) { gantt2.config.start_date = previousDateRage.start_date; gantt2.config.end_date = previousDateRage.end_date; } }, _prepareConfigPDF(config2, type) { config2 = gantt2.mixin(config2 || {}, { name: "gantt." + type, data: gantt2.ext.export_api._serializeAll(), config: gantt2.config }); gantt2.ext.export_api._fixColumns(config2.config.columns); return config2; }, _pdfExportRouter(config2, type) { if (config2 && config2.raw) { gantt2.ext.export_api._preparePDFConfigRaw(config2, type); } else { config2 = gantt2.ext.export_api._prepareConfigPDF(config2, type); } config2.version = gantt2.version; gantt2.ext.export_api._sendToExport(config2, type); }, exportToPDF(config2) { gantt2.ext.export_api._pdfExportRouter(config2, "pdf"); }, exportToPNG(config2) { gantt2.ext.export_api._pdfExportRouter(config2, "png"); }, exportToICal(config2) { config2 = gantt2.mixin(config2 || {}, { name: "gantt.ical", data: gantt2.ext.export_api._serializePlain().data, version: gantt2.version }); gantt2.ext.export_api._sendToExport(config2, "ical"); }, exportToExcel(config2) { config2 = config2 || {}; let tasks2; let dates = []; let state; let scroll; const smartRendering = gantt2.config.smart_rendering; if (config2.visual === "base-colors") { gantt2.config.smart_rendering = false; } if (config2.start || config2.end) { state = gantt2.getState(); dates = [gantt2.config.start_date, gantt2.config.end_date]; scroll = gantt2.getScrollState(); const convert = gantt2.date.str_to_date(gantt2.config.date_format); tasks2 = gantt2.eachTask; if (config2.start) { gantt2.config.start_date = convert(config2.start); } if (config2.end) { gantt2.config.end_date = convert(config2.end); } gantt2.render(); gantt2.config.smart_rendering = smartRendering; gantt2.eachTask = gantt2.ext.export_api._eachTaskTimed(gantt2.config.start_date, gantt2.config.end_date); } else if (config2.visual === "base-colors") { gantt2.render(); gantt2.config.smart_rendering = smartRendering; } config2 = gantt2.mixin(config2, { name: "gantt.xlsx", title: "Tasks", data: gantt2.ext.export_api._serializeTimeline(config2), columns: gantt2.ext.export_api._serializeGrid({ raw: config2.raw, rawDates: true }), version: gantt2.version }); if (config2.visual) { config2.scales = gantt2.ext.export_api._serializeScales(config2); } gantt2.ext.export_api._sendToExport(config2, "excel"); if (config2.start || config2.end) { gantt2.config.start_date = state.min_date; gantt2.config.end_date = state.max_date; gantt2.eachTask = tasks2; gantt2.render(); gantt2.scrollTo(scroll.x, scroll.y); gantt2.config.start_date = dates[0]; gantt2.config.end_date = dates[1]; } }, exportToJSON(config2) { config2 = gantt2.mixin(config2 || {}, { name: "gantt.json", data: gantt2.ext.export_api._serializeAll(), config: gantt2.config, columns: gantt2.ext.export_api._serializeGrid(), worktime: gantt2.ext.export_api._getWorktimeSettings(), version: gantt2.version }); gantt2.ext.export_api._sendToExport(config2, "json"); }, importFromExcel(config2) { try { const formData = config2.data; if (formData instanceof File) { const data2 = new FormData(); data2.append("file", formData); config2.data = data2; } } catch (error) { } gantt2.ext.export_api._sendImportAjaxExcel(config2); }, importFromMSProject(config2) { const formData = config2.data; try { if (formData instanceof File) { const data2 = new FormData(); data2.append("file", formData); config2.data = data2; } } catch (error) { } gantt2.ext.export_api._sendImportAjaxMSP(config2); }, importFromPrimaveraP6(config2) { config2.type = "primaveraP6-parse"; return gantt2.importFromMSProject(config2); }, exportToMSProject(config2) { config2 = config2 || {}; config2.skip_circular_links = config2.skip_circular_links === void 0 ? true : !!config2.skip_circular_links; const oldXmlFormat = gantt2.templates.xml_format; const oldFormatDate = gantt2.templates.format_date; const oldXmlDate = gantt2.config.xml_date; const oldDateFormat = gantt2.config.date_format; const exportServiceDateFormat = "%d-%m-%Y %H:%i:%s"; gantt2.config.xml_date = exportServiceDateFormat; gantt2.config.date_format = exportServiceDateFormat; gantt2.templates.xml_format = gantt2.date.date_to_str(exportServiceDateFormat); gantt2.templates.format_date = gantt2.date.date_to_str(exportServiceDateFormat); const data2 = gantt2.ext.export_api._serializeAll(); gantt2.ext.export_api._customProjectProperties(data2, config2); gantt2.ext.export_api._customTaskProperties(data2, config2); if (config2.skip_circular_links) { gantt2.ext.export_api._clearRecLinks(data2); } config2 = gantt2.ext.export_api._exportConfig(data2, config2); gantt2.ext.export_api._sendToExport(config2, config2.type || "msproject"); gantt2.config.xml_date = oldXmlDate; gantt2.config.date_format = oldDateFormat; gantt2.templates.xml_format = oldXmlFormat; gantt2.templates.format_date = oldFormatDate; gantt2.config.$custom_data = null; gantt2.config.custom = null; }, exportToPrimaveraP6(config2) { config2 = config2 || {}; config2.type = "primaveraP6"; return gantt2.exportToMSProject(config2); }, _fixColumns(columns) { for (let i = 0; i < columns.length; i++) { columns[i].label = columns[i].label || gantt2.locale.labels["column_" + columns[i].name]; if (typeof columns[i].width === "string") { columns[i].width = columns[i].width * 1; } } }, _xdr(url, pack, cb) { gantt2.ajax.post(url, pack, cb); }, _markColumns(base2) { const columns = base2.config.columns; if (columns) { for (let i = 0; i < columns.length; i++) { if (columns[i].template) { columns[i].$template = true; } } } }, _sendImportAjaxExcel(config2) { const url = config2.server || gantt2.ext.export_api._apiUrl; const store = config2.store || 0; const formData = config2.data; const callback = config2.callback; formData.append("type", "excel-parse"); formData.append("data", JSON.stringify({ sheet: config2.sheet || 0 })); if (store) { formData.append("store", store); } const xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(e) { if (xhr.readyState === 4 && xhr.status === 0) { if (callback) { callback(null); } } }; xhr.onload = function() { const fail = xhr.status > 400; let info = null; if (!fail) { try { info = JSON.parse(xhr.responseText); } catch (e) { } } if (callback) { callback(info); } }; xhr.open("POST", url, true); xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); xhr.send(formData); }, _ajaxToExport(data2, type, callback) { delete data2.callback; const url = data2.server || gantt2.ext.export_api._apiUrl; const pack = "type=" + type + "&store=1&data=" + encodeURIComponent(JSON.stringify(data2)); const cb = function(loader) { const xdoc = loader.xmlDoc || loader; const fail = xdoc.status > 400; let info = null; if (!fail) { try { info = JSON.parse(xdoc.responseText); } catch (e) { } } callback(info); }; gantt2.ext.export_api._xdr(url, pack, cb); }, _serializableGanttConfig(config2) { const result = gantt2.mixin({}, config2); if (result.columns) { result.columns = result.columns.map(function(col) { const copy2 = gantt2.mixin({}, col); delete copy2.editor; return copy2; }); } delete result.editor_types; return result; }, _sendToExport(data2, type) { const convert = gantt2.date.date_to_str(gantt2.config.date_format || gantt2.config.xml_date); if (!data2.skin) { data2.skin = gantt2.skin; } if (data2.config) { data2.config = gantt2.copy(gantt2.ext.export_api._serializableGanttConfig(data2.config)); gantt2.ext.export_api._markColumns(data2, type); if (data2.config.start_date && data2.config.end_date) { if (data2.config.start_date instanceof Date) { data2.config.start_date = convert(data2.config.start_date); } if (data2.config.end_date instanceof Date) { data2.config.end_date = convert(data2.config.end_date); } } } if (data2.callback) { return gantt2.ext.export_api._ajaxToExport(data2, type, data2.callback); } const form = gantt2.ext.export_api._createHiddenForm(); form.firstChild.action = data2.server || gantt2.ext.export_api._apiUrl; form.firstChild.childNodes[0].value = JSON.stringify(data2); form.firstChild.childNodes[1].value = type; form.firstChild.submit(); }, _createHiddenForm() { if (!gantt2.ext.export_api._hidden_export_form) { const t2 = gantt2.ext.export_api._hidden_export_form = document.createElement("div"); t2.style.display = "none"; t2.innerHTML = "
"; document.body.appendChild(t2); } return gantt2.ext.export_api._hidden_export_form; }, _copyObjectBase(obj) { const copy2 = { start_date: void 0, end_date: void 0, constraint_date: void 0, deadline: void 0 }; for (const key in obj) { if (key.charAt(0) === "$" || key === "baselines") { continue; } copy2[key] = obj[key]; } const formatDate = gantt2.templates.xml_format || gantt2.templates.format_date; copy2.start_date = formatDate(copy2.start_date); if (copy2.end_date) { copy2.end_date = formatDate(copy2.end_date); } if (copy2.constraint_date) { copy2.constraint_date = formatDate(copy2.constraint_date); } if (copy2.deadline) { copy2.deadline = formatDate(copy2.deadline); } return copy2; }, _color_box: null, _color_hash: {}, _getStyles(css) { if (!gantt2.ext.export_api._color_box) { gantt2.ext.export_api._color_box = document.createElement("DIV"); gantt2.ext.export_api._color_box.style.cssText = "position:absolute; display:none;"; document.body.appendChild(gantt2.ext.export_api._color_box); } if (gantt2.ext.export_api._color_hash[css]) { return gantt2.ext.export_api._color_hash[css]; } gantt2.ext.export_api._color_box.className = css; const color = gantt2.ext.export_api._getColor(gantt2.ext.export_api._color_box, "color"); const backgroundColor = gantt2.ext.export_api._getColor(gantt2.ext.export_api._color_box, "backgroundColor"); return gantt2.ext.export_api._color_hash[css] = color + ";" + backgroundColor; }, _getMinutesWorktimeSettings(parsedRanges) { const minutes = []; parsedRanges.forEach(function(range) { minutes.push(range.startMinute); minutes.push(range.endMinute); }); return minutes; }, _getWorktimeSettings() { const defaultWorkTimes = { hours: [0, 24], minutes: null, dates: { 0: true, 1: true, 2: true, 3: true, 4: true, 5: true, 6: true } }; let time; if (!gantt2.config.work_time) { time = defaultWorkTimes; } else { const wTime = gantt2._working_time_helper; if (wTime && wTime.get_calendar) { time = wTime.get_calendar(); } else if (wTime) { time = { hours: wTime.hours, minutes: null, dates: wTime.dates }; } else if (gantt2.config.worktimes && gantt2.config.worktimes.global) { const settings = gantt2.config.worktimes.global; if (settings.parsed) { const minutes = gantt2.ext.export_api._getMinutesWorktimeSettings(settings.parsed.hours); time = { hours: null, minutes, dates: {} }; for (const i in settings.parsed.dates) { if (Array.isArray(settings.parsed.dates[i])) { time.dates[i] = gantt2.ext.export_api._getMinutesWorktimeSettings(settings.parsed.dates[i]); } else { time.dates[i] = settings.parsed.dates[i]; } } } else { time = { hours: settings.hours, minutes: null, dates: settings.dates }; } } else { time = defaultWorkTimes; } } return time; }, _eachTaskTimed(start, end) { return function(code, parent, master) { parent = parent || gantt2.config.root_id; master = master || gantt2; const branch = gantt2.getChildren(parent); if (branch) { for (let i = 0; i < branch.length; i++) { const item = gantt2._pull[branch[i]]; if ((!start || item.end_date > start) && (!end || item.start_date < end)) { code.call(master, item); } if (gantt2.hasChild(item.id)) { gantt2.eachTask(code, item.id, master); } } } }; }, _originalCopyObject: gantt2.json._copyObject, _copyObjectPlainICal(task) { const text = gantt2.templates.task_text(task.start_date, task.end_date, task); const copy2 = gantt2.ext.export_api._copyObjectBase(task); copy2.text = text || copy2.text; return copy2; }, _copyObjectPlainExcel(task) { const text = gantt2.templates.task_text(task.start_date, task.end_date, task); const copy2 = gantt2.json.serializeTask(task); copy2.text = text || copy2.text; return copy2; }, _getColor(node, style) { let value = node.currentStyle ? node.currentStyle[style] : getComputedStyle(node, null)[style]; if (node.closest(".gantt_task_progress") && value === "rgba(0, 0, 0, 0.15)") { node = node.parentNode.parentNode; value = node.currentStyle ? node.currentStyle[style] : getComputedStyle(node, null)[style]; } const rgb = value.replace(/\s/g, "").match(/^rgba?\((\d+),(\d+),(\d+)/i); return (rgb && rgb.length === 4 ? ("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : value).replace("#", ""); }, _copyObjectTable(obj) { const toISOstring = gantt2.date.date_to_str("%Y-%m-%dT%H:%i:%s.000Z"); const copy2 = gantt2.ext.export_api._copyObjectColumns(obj, gantt2.ext.export_api._copyObjectPlainExcel(obj)); if (copy2.start_date) { if (typeof copy2.start_date === "string") { copy2.original_start_date = gantt2.date.str_to_date(gantt2.config.date_format)(copy2.start_date); } else { copy2.original_start_date = copy2.start_date; copy2.start_date = toISOstring(obj.start_date); } } if (copy2.end_date) { if (typeof copy2.end_date === "string") { copy2.original_end_date = gantt2.date.str_to_date(gantt2.config.date_format)(copy2.end_date); } else { copy2.original_end_date = copy2.end_date; copy2.end_date = toISOstring(obj.end_date); } } else if (copy2.original_start_date) { copy2.original_end_date = gantt2.calculateEndDate({ start_date: copy2.original_start_date, duration: copy2.duration, task: copy2 }); copy2.end_date = toISOstring(copy2.original_end_date); } return copy2; }, _generatedScales: null, _generateScales() { const state = gantt2.getState(); const scaleHelper = ScaleIgnoreHelper(gantt2); const scales = [scaleHelper.primaryScale(gantt2.config)].concat(scaleHelper.getSubScales(gantt2.config)); const scalesConfig = scaleHelper.prepareConfigs(scales, gantt2.config.min_column_width, 1e3, gantt2.config.scale_height - 1, state.min_date, state.max_date, gantt2.config.rtl); gantt2.ext.export_api._generatedScales = scalesConfig; return scalesConfig; }, _getDayIndex(scales, date2) { let days = scales.trace_indexes; if (days[+date2]) { return days[+date2]; } else { days = scales.trace_x; const state = gantt2.getState(); if (+date2 <= state.min_date) { if (gantt2.config.rtl) { return days.length; } else { return 0; } } else if (+date2 >= state.max_date) { if (gantt2.config.rtl) { return 0; } else { return days.length; } } const index = findBinary(days, +date2); return index; } }, _copyObjectColors(obj, config2) { const copy2 = gantt2.ext.export_api._copyObjectTable(obj); let startDate = copy2.original_start_date; let endDate = copy2.original_end_date; let getDayIndex = gantt2.columnIndexByDate; let scales; if (gantt2.ext.export_api._generatedScales) { const allScales = gantt2.ext.export_api._generatedScales; scales = allScales[allScales.length - 1]; copy2.$start = gantt2.ext.export_api._getDayIndex(scales, startDate); copy2.$end = gantt2.ext.export_api._getDayIndex(scales, endDate); } else { scales = gantt2.getScale(); copy2.$start = getDayIndex.call(gantt2, startDate); copy2.$end = getDayIndex.call(gantt2, endDate); } let hiddenCells = 0; const scaleCellsWidth = scales.width; if (scaleCellsWidth.indexOf(0) > -1) { let i = 0; for (i; i < copy2.$start; i++) { if (!scaleCellsWidth[i]) { hiddenCells++; } } copy2.$start -= hiddenCells; for (i; i < copy2.$end; i++) { if (!scaleCellsWidth[i]) { hiddenCells++; } } copy2.$end -= hiddenCells; } copy2.$level = obj.$level; copy2.$type = obj.$rendered_type; const tmps = gantt2.templates; copy2.$text = tmps.task_text(obj.start, obj.end_date, obj); copy2.$left = tmps.leftside_text ? tmps.leftside_text(obj.start, obj.end_date, obj) : ""; copy2.$right = tmps.rightside_text ? tmps.rightside_text(obj.start, obj.end_date, obj) : ""; const node = gantt2.getTaskNode && gantt2.getTaskNode(obj.id); if (node && node.firstChild) { let targetNode = node; if (config2.visual !== "base-colors") { targetNode = node.querySelector(".gantt_task_progress"); } let color = gantt2.ext.export_api._getColor(targetNode, "backgroundColor"); if (color === "363636") { color = gantt2.ext.export_api._getColor(node, "backgroundColor"); } copy2.$color = color; } else if (obj.color) { copy2.$color = obj.color; } else { const cellCss = gantt2.templates.task_class(obj.start, obj.end, obj); if (cellCss) { const styles = gantt2.ext.export_api._getStyles(cellCss); copy2.$color = styles.split(";")[1]; } } return copy2; }, _copyObjectColumns(obj, copy2) { for (let i = 0; i < gantt2.config.columns.length; i++) { const ct = gantt2.config.columns[i].template; if (ct) { let val = ct(obj); if (val instanceof Date) { val = gantt2.templates.date_grid(val, obj); } copy2["_" + i] = val; } } return copy2; }, _copyObjectAll(obj) { const copy2 = gantt2.ext.export_api._copyObjectBase(obj); const templates2 = ["leftside_text", "rightside_text", "task_text", "progress_text", "task_class"]; for (let i = 0; i < templates2.length; i++) { const template = gantt2.templates[templates2[i]]; if (template) { copy2["$" + i] = template(obj.start_date, obj.end_date, obj); } } gantt2.ext.export_api._copyObjectColumns(obj, copy2); copy2.open = obj.$open; return copy2; }, _serializeHtml() { const smartScales = gantt2.config.smart_scales; const smartRendering = gantt2.config.smart_rendering; if (smartScales || smartRendering) { gantt2.config.smart_rendering = false; gantt2.config.smart_scales = false; gantt2.render(); } const html = gantt2.$container.parentNode.innerHTML; if (smartScales || smartRendering) { gantt2.config.smart_scales = smartScales; gantt2.config.smart_rendering = smartRendering; gantt2.render(); } return html; }, _serializeAll() { gantt2.json._copyObject = gantt2.ext.export_api._copyObjectAll; const data2 = gantt2.ext.export_api._exportSerialize(); gantt2.json._copyObject = gantt2.ext.export_api._originalCopyObject; return data2; }, _serializePlain() { const oldXmlFormat = gantt2.templates.xml_format; const oldFormatDate = gantt2.templates.format_date; gantt2.templates.xml_format = gantt2.date.date_to_str("%Y%m%dT%H%i%s", true); gantt2.templates.format_date = gantt2.date.date_to_str("%Y%m%dT%H%i%s", true); gantt2.json._copyObject = gantt2.ext.export_api._copyObjectPlainICal; const data2 = gantt2.ext.export_api._exportSerialize(); gantt2.templates.xml_format = oldXmlFormat; gantt2.templates.format_date = oldFormatDate; gantt2.json._copyObject = gantt2.ext.export_api._originalCopyObject; delete data2.links; return data2; }, _getRaw() { const timeline = gantt2.$ui.getView("timeline"); if (timeline && gantt2.config.show_chart) { let availWidth = timeline.$config.width; if (gantt2.config.autosize === "x" || gantt2.config.autosize === "xy") { availWidth = Math.max(gantt2.config.autosize_min_width, 0); } const state = gantt2.getState(); const scales = timeline._getScales(); const minWidth = gantt2.config.min_column_width; const height = gantt2.config.scale_height - 1; const rtl = gantt2.config.rtl; return timeline.$scaleHelper.prepareConfigs(scales, minWidth, availWidth, height, state.min_date, state.max_date, rtl); } else { return gantt2.ext.export_api._generateScales(); } }, _serializeTimeline(config2) { gantt2.ext.export_api._generatedScales = null; let scales; if (config2.visual) { scales = gantt2.ext.export_api._getRaw(config2.start, config2.end); } if (config2.data) { config2.custom_dataset = true; } let tasks2 = config2.data || gantt2.serialize().data; tasks2.forEach(function(task, index) { if (config2.visual) { if (task.render == "split") { const children = []; if (config2.custom_dataset) { tasks2.forEach(function(child) { if (child.parent == task.id) { const childBar = gantt2.ext.export_api._copyObjectColors(child, config2); childBar.$split_subtask = true; children.push(childBar); } }); } else { gantt2.eachTask(function(child) { const childBar = gantt2.ext.export_api._copyObjectColors(child, config2); children.push(childBar); }, task.id); } task.split_bars = []; const skippedTasks = {}; for (let i = 0; i < children.length; i++) { const child = children[i]; for (let j = 0; j < children.length; j++) { const sibling = children[j]; if (child.id == sibling.id || skippedTasks[sibling.id]) { continue; } const overlap = +child.original_start_date < +sibling.original_start_date && +sibling.original_start_date <= +child.original_end_date; const cover = +sibling.original_start_date <= +child.original_start_date && +child.original_end_date <= +sibling.original_end_date; if (overlap) { child.original_end_date = sibling.original_start_date; child.end_date = sibling.start_date; child.$end = sibling.$start; } if (cover) { skippedTasks[child.id] = true; break; } } if (!skippedTasks[child.id]) { task.split_bars.push(child); } } tasks2[index] = task; } else if (!task.$split_subtask) { tasks2[index] = gantt2.ext.export_api._copyObjectColors(task, config2); } } else { tasks2[index] = gantt2.ext.export_api._copyObjectTable(task); } }); if (config2.raw && !config2.data) { const taskStore = gantt2.getDatastore("task"); const filteredIds = taskStore.visibleOrder; if (tasks2.length !== filteredIds.length) { const filteredDataset = []; tasks2.forEach(function(task) { if (filteredIds.indexOf(task.id) > -1) { filteredDataset.push(task); } }); tasks2 = filteredDataset; } } if (config2.cellColors) { const css = gantt2.templates.timeline_cell_class || gantt2.templates.task_cell_class; if (css) { let steps = scales[0].trace_x; for (let i = 1; i < scales.length; i++) { if (scales[i].trace_x.length > steps.length) { steps = scales[i].trace_x; } } for (let i = 0; i < tasks2.length; i++) { tasks2[i].styles = []; const task = gantt2.getTask(tasks2[i].id); for (let j = 0; j < steps.length; j++) { const date2 = steps[j]; const cellCss = css(task, date2); if (cellCss) { tasks2[i].styles.push({ index: j, styles: gantt2.ext.export_api._getStyles(cellCss) }); } } } } } return tasks2; }, _serializeScales(config2) { const scales = []; const raw = gantt2.ext.export_api._getRaw(); let min = Infinity; let max = 0; for (let i = 0; i < raw.length; i++) { min = Math.min(min, raw[i].col_width); } for (let i = 0; i < raw.length; i++) { let start = 0; let end = 0; const row = []; scales.push(row); const step = raw[i]; max = Math.max(max, step.trace_x.length); const template = step.format || step.template || gantt2.date.date_to_str(step.date); for (let j = 0; j < step.trace_x.length; j++) { const date2 = step.trace_x[j]; end = start + Math.round(step.width[j] / min); const scaleCell = { text: template(date2), start, end, styles: "" }; if (config2.cellColors) { const css = step.css || gantt2.templates.scaleCell_class; if (css) { const scaleCss = css(date2); if (scaleCss) { scaleCell.styles = gantt2.ext.export_api._getStyles(scaleCss); } } } row.push(scaleCell); start = end; } } return { width: max, height: scales.length, data: scales }; }, _serializeGrid(config2) { gantt2.exportMode = true; const columns = []; const cols = gantt2.config.columns; let ccount = 0; for (let i = 0; i < cols.length; i++) { if (cols[i].name === "add" || cols[i].name === "buttons") { continue; } if (config2 && config2.raw && cols[i].hide) { continue; } columns[ccount] = { id: cols[i].template ? "_" + i : cols[i].name, header: cols[i].label || gantt2.locale.labels["column_" + cols[i].name], width: cols[i].width ? Math.floor(cols[i].width / 4) : "", tree: cols[i].tree || false }; if (cols[i].name === "duration") { columns[ccount].type = "number"; } if (cols[i].name === "start_date" || cols[i].name === "end_date") { columns[ccount].type = "date"; if (config2 && config2.rawDates) { columns[ccount].id = cols[i].name; } } ccount++; } gantt2.exportMode = false; return columns; }, _exportSerialize() { gantt2.exportMode = true; const xmlFormat = gantt2.templates.xml_format; const formatDate = gantt2.templates.format_date; gantt2.templates.xml_format = gantt2.templates.format_date = gantt2.date.date_to_str(gantt2.config.date_format || gantt2.config.xml_date); const data2 = gantt2.serialize(); gantt2.templates.xml_format = xmlFormat; gantt2.templates.format_date = formatDate; gantt2.exportMode = false; return data2; }, _setLevel(data2) { for (let i = 0; i < data2.length; i++) { if (data2[i].parent == 0) { data2[i]._lvl = 1; } for (let j = i + 1; j < data2.length; j++) { if (data2[i].id == data2[j].parent) { data2[j]._lvl = data2[i]._lvl + 1; } } } }, _clearLevel(data2) { for (let i = 0; i < data2.length; i++) { delete data2[i]._lvl; } }, _clearRecLinks(data2) { gantt2.ext.export_api._setLevel(data2.data); const tasks2 = {}; for (let i = 0; i < data2.data.length; i++) { tasks2[data2.data[i].id] = data2.data[i]; } const links = {}; for (let i = 0; i < data2.links.length; i++) { const link = data2.links[i]; if (gantt2.isTaskExists(link.source) && gantt2.isTaskExists(link.target) && tasks2[link.source] && tasks2[link.target]) { links[link.id] = link; } } for (const j in links) { gantt2.ext.export_api._makeLinksSameLevel(links[j], tasks2); } const skippedLinks = {}; for (const j in tasks2) { gantt2.ext.export_api._clearCircDependencies(tasks2[j], links, tasks2, {}, skippedLinks, null); } if (Object.keys(links)) { gantt2.ext.export_api._clearLinksSameLevel(links, tasks2); } for (let i = 0; i < data2.links.length; i++) { if (!links[data2.links[i].id]) { data2.links.splice(i, 1); i--; } } gantt2.ext.export_api._clearLevel(data2.data); }, _clearCircDependencies(task, links, tasks2, usedTasks, skippedLinks, prevLink) { const sources = task.$_source; if (!sources) { return; } if (usedTasks[task.id]) { gantt2.ext.export_api._onCircDependencyFind(prevLink, links, usedTasks, skippedLinks); } usedTasks[task.id] = true; const targets = {}; for (let i = 0; i < sources.length; i++) { if (skippedLinks[sources[i]]) { continue; } const curLink = links[sources[i]]; const targetTask = tasks2[curLink._target]; if (targets[targetTask.id]) { gantt2.ext.export_api._onCircDependencyFind(curLink, links, usedTasks, skippedLinks); } targets[targetTask.id] = true; gantt2.ext.export_api._clearCircDependencies(targetTask, links, tasks2, usedTasks, skippedLinks, curLink); } usedTasks[task.id] = false; }, _onCircDependencyFind(link, links, usedTasks, skippedLinks) { if (link) { if (gantt2.callEvent("onExportCircularDependency", [link.id, link])) { delete links[link.id]; } delete usedTasks[link._source]; delete usedTasks[link._target]; skippedLinks[link.id] = true; } }, _makeLinksSameLevel(link, tasks2) { let task; let targetLvl; const linkT = { target: tasks2[link.target], source: tasks2[link.source] }; if (linkT.target._lvl != linkT.source._lvl) { if (linkT.target._lvl < linkT.source._lvl) { task = "source"; targetLvl = linkT.target._lvl; } else { task = "target"; targetLvl = linkT.source._lvl; } do { const parent = tasks2[linkT[task].parent]; if (!parent) { break; } linkT[task] = parent; } while (linkT[task]._lvl < targetLvl); let sourceParent = tasks2[linkT.source.parent]; let targetParent = tasks2[linkT.target.parent]; while (sourceParent && targetParent && sourceParent.id != targetParent.id) { linkT.source = sourceParent; linkT.target = targetParent; sourceParent = tasks2[linkT.source.parent]; targetParent = tasks2[linkT.target.parent]; } } link._target = linkT.target.id; link._source = linkT.source.id; if (!linkT.target.$_target) { linkT.target.$_target = []; } linkT.target.$_target.push(link.id); if (!linkT.source.$_source) { linkT.source.$_source = []; } linkT.source.$_source.push(link.id); }, _clearLinksSameLevel(links, tasks2) { for (const link in links) { delete links[link]._target; delete links[link]._source; } for (const task in tasks2) { delete tasks2[task].$_source; delete tasks2[task].$_target; } }, _customProjectProperties(data2, config2) { if (config2 && config2.project) { for (const i in config2.project) { if (!gantt2.config.$custom_data) { gantt2.config.$custom_data = {}; } gantt2.config.$custom_data[i] = typeof config2.project[i] === "function" ? config2.project[i](gantt2.config) : config2.project[i]; } delete config2.project; } }, _customTaskProperties(data2, config2) { if (config2 && config2.tasks) { data2.data.forEach(function(el) { for (const i in config2.tasks) { if (!el.$custom_data) { el.$custom_data = {}; } el.$custom_data[i] = typeof config2.tasks[i] === "function" ? config2.tasks[i](el, gantt2.config) : config2.tasks[i]; } }); delete config2.tasks; } }, _exportConfig(data2, config2) { const projectName = config2.name || "gantt.xml"; delete config2.name; gantt2.config.custom = config2; const time = gantt2.ext.export_api._getWorktimeSettings(); const projectDates = gantt2.getSubtaskDates(); if (projectDates.start_date && projectDates.end_date) { const formatDate = gantt2.templates.format_date || gantt2.templates.xml_format; gantt2.config.start_end = { start_date: formatDate(projectDates.start_date), end_date: formatDate(projectDates.end_date) }; } const autoSchedulingConfig = gantt2._getAutoSchedulingConfig(); const manual = !!autoSchedulingConfig.enabled; const res = { callback: config2.callback || null, config: gantt2.config, data: data2, manual, name: projectName, worktime: time }; for (const i in config2) { res[i] = config2[i]; } return res; }, _sendImportAjaxMSP(config2) { const url = config2.server || gantt2.ext.export_api._apiUrl; const store = config2.store || 0; const formData = config2.data; const callback = config2.callback; const settings = { durationUnit: config2.durationUnit || void 0, projectProperties: config2.projectProperties || void 0, taskProperties: config2.taskProperties || void 0 }; formData.append("type", config2.type || "msproject-parse"); formData.append("data", JSON.stringify(settings)); if (store) { formData.append("store", store); } const xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(e) { if (xhr.readyState === 4 && xhr.status === 0) { if (callback) { callback(null); } } }; xhr.onload = function() { const fail = xhr.status > 400; let info = null; if (!fail) { try { info = JSON.parse(xhr.responseText); } catch (e) { } } if (callback) { callback(info); } }; xhr.open("POST", url, true); xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); xhr.send(formData); } }; gantt2.exportToPDF = gantt2.ext.export_api.exportToPDF; gantt2.exportToPNG = gantt2.ext.export_api.exportToPNG; gantt2.exportToICal = gantt2.ext.export_api.exportToICal; gantt2.exportToExcel = gantt2.ext.export_api.exportToExcel; gantt2.exportToJSON = gantt2.ext.export_api.exportToJSON; gantt2.importFromExcel = gantt2.ext.export_api.importFromExcel; gantt2.importFromMSProject = gantt2.ext.export_api.importFromMSProject; gantt2.exportToMSProject = gantt2.ext.export_api.exportToMSProject; gantt2.importFromPrimaveraP6 = gantt2.ext.export_api.importFromPrimaveraP6; gantt2.exportToPrimaveraP6 = gantt2.ext.export_api.exportToPrimaveraP6; return gantt2.ext.export_api; } function fullscreen(gantt2) { function isExpanded() { const element = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement; return !!(element && element === document.body); } function isFullscreenAvailable() { try { return document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled; } catch (e) { console.error("Fullscreen is not available:", e); } } const state = gantt2.$services.getService("state"); state.registerProvider("fullscreen", () => { if (isFullscreenAvailable()) { return { fullscreen: isExpanded() }; } else { return void 0; } }); let backupBodyPadding = { overflow: null, padding: null, paddingTop: null, paddingRight: null, paddingBottom: null, paddingLeft: null }; const backupElementSizes = { width: null, height: null, top: null, left: null, position: null, zIndex: null, modified: false }; let backupPositioning = null; function resetParentPositioning(root) { let parent = root.parentNode; const positions = []; while (parent && parent.style) { positions.push({ element: parent, originalPositioning: parent.style.position }); parent.style.position = "static"; parent = parent.parentNode; } return positions; } function restoreParentPositioning(positions) { positions.forEach((record) => { record.element.style.position = record.originalPositioning; }); } function setFullScreenSizes() { const root = gantt2.ext.fullscreen.getFullscreenElement(); const body = document.body; updateSizes(root.style, backupElementSizes); backupBodyPadding = { overflow: body.style.overflow, padding: body.style.padding ? body.style.padding : null, paddingTop: body.style.paddingTop ? body.style.paddingTop : null, paddingRight: body.style.paddingRight ? body.style.paddingRight : null, paddingBottom: body.style.paddingBottom ? body.style.paddingBottom : null, paddingLeft: body.style.paddingLeft ? body.style.paddingLeft : null }; if (body.style.padding) { body.style.padding = "0"; } if (body.style.paddingTop) { body.style.paddingTop = "0"; } if (body.style.paddingRight) { body.style.paddingRight = "0"; } if (body.style.paddingBottom) { body.style.paddingBottom = "0"; } if (body.style.paddingLeft) { body.style.paddingLeft = "0"; } body.style.overflow = "hidden"; root.style.width = "100vw"; root.style.height = "100vh"; root.style.top = "0px"; root.style.left = "0px"; root.style.position = "absolute"; root.style.zIndex = 1; backupElementSizes.modified = true; backupPositioning = resetParentPositioning(root); } function restoreSizes() { const root = gantt2.ext.fullscreen.getFullscreenElement(); const body = document.body; if (backupElementSizes.modified) { if (backupBodyPadding.padding) { body.style.padding = backupBodyPadding.padding; } if (backupBodyPadding.paddingTop) { body.style.paddingTop = backupBodyPadding.paddingTop; } if (backupBodyPadding.paddingRight) { body.style.paddingRight = backupBodyPadding.paddingRight; } if (backupBodyPadding.paddingBottom) { body.style.paddingBottom = backupBodyPadding.paddingBottom; } if (backupBodyPadding.paddingLeft) { body.style.paddingLeft = backupBodyPadding.paddingLeft; } body.style.overflow = backupBodyPadding.overflow; backupBodyPadding = { overflow: null, padding: null, paddingTop: null, paddingRight: null, paddingBottom: null, paddingLeft: null }; updateSizes(backupElementSizes, root.style); backupElementSizes.modified = false; } restoreParentPositioning(backupPositioning); backupPositioning = null; } function updateSizes(source, target) { target.width = source.width; target.height = source.height; target.top = source.top; target.left = source.left; target.position = source.position; target.zIndex = source.zIndex; } function addDOMEvents() { gantt2.event(document, "webkitfullscreenchange", onFullScreenChange); gantt2.event(document, "mozfullscreenchange", onFullScreenChange); gantt2.event(document, "MSFullscreenChange", onFullScreenChange); gantt2.event(document, "fullscreenChange", onFullScreenChange); gantt2.event(document, "fullscreenchange", onFullScreenChange); } let expandGantt = false; function onFullScreenChange() { if (!gantt2.$container) { return; } let event2; const isBodyExpanded = isExpanded(); if (isBodyExpanded) { if (expandGantt) { event2 = "onExpand"; setFullScreenSizes(); } } else if (expandGantt) { expandGantt = false; event2 = "onCollapse"; restoreSizes(); } setTimeout(() => { gantt2.render(); }); setTimeout(() => { gantt2.callEvent(event2, [gantt2.ext.fullscreen.getFullscreenElement()]); }); } function cantFullscreen() { if (!gantt2.$container) { return true; } if (!gantt2.ext.fullscreen.getFullscreenElement()) { return true; } if (!isFullscreenAvailable()) { const method = console.warning || console.log; method("The `fullscreen` feature not being allowed, or full-screen mode not being supported"); return true; } return false; } gantt2.ext.fullscreen = { expand() { if (cantFullscreen()) { return; } if (isExpanded()) { return; } if (!gantt2.callEvent("onBeforeExpand", [this.getFullscreenElement()])) { return; } expandGantt = true; const element = document.body; const requestArguments = element.webkitRequestFullscreen ? [Element.ALLOW_KEYBOARD_INPUT] : []; const requestFullscreen = element.msRequestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.requestFullscreen; if (requestFullscreen) { requestFullscreen.apply(element, requestArguments); } }, collapse() { if (cantFullscreen()) { return; } if (!isExpanded()) { return; } if (!gantt2.callEvent("onBeforeCollapse", [this.getFullscreenElement()])) { return; } const requestExitFullscreen = document.msExitFullscreen || document.mozCancelFullScreen || document.webkitExitFullscreen || document.exitFullscreen; if (requestExitFullscreen) { requestExitFullscreen.apply(document); } }, toggle() { if (cantFullscreen()) { return; } if (!isExpanded()) { this.expand(); } else { this.collapse(); } }, getFullscreenElement() { return gantt2.$root; } }; gantt2.expand = function() { gantt2.ext.fullscreen.expand(); }; gantt2.collapse = function() { gantt2.ext.fullscreen.collapse(); }; gantt2.attachEvent("onGanttReady", addDOMEvents); } function keyboard_shortcuts(gantt2) { gantt2.$keyboardNavigation.shortcuts = { createCommand: function() { return { modifiers: { shift: false, alt: false, ctrl: false, meta: false }, keyCode: null }; }, parse: function(shortcut) { var commands = []; var expr = this.getExpressions(this.trim(shortcut)); for (var i = 0; i < expr.length; i++) { var words = this.getWords(expr[i]); var command = this.createCommand(); for (var j = 0; j < words.length; j++) { if (this.commandKeys[words[j]]) { command.modifiers[words[j]] = true; } else if (this.specialKeys[words[j]]) { command.keyCode = this.specialKeys[words[j]]; } else { command.keyCode = words[j].charCodeAt(0); } } commands.push(command); } return commands; }, getCommandFromEvent: function(domEvent) { var command = this.createCommand(); command.modifiers.shift = !!domEvent.shiftKey; command.modifiers.alt = !!domEvent.altKey; command.modifiers.ctrl = !!domEvent.ctrlKey; command.modifiers.meta = !!domEvent.metaKey; command.keyCode = domEvent.which || domEvent.keyCode; if (command.keyCode >= 96 && command.keyCode <= 105) { command.keyCode -= 48; } var printableKey = String.fromCharCode(command.keyCode); if (printableKey) { command.keyCode = printableKey.toLowerCase().charCodeAt(0); } return command; }, getHashFromEvent: function(domEvent) { return this.getHash(this.getCommandFromEvent(domEvent)); }, getHash: function(command) { var parts = []; for (var i in command.modifiers) { if (command.modifiers[i]) { parts.push(i); } } parts.push(command.keyCode); return parts.join(this.junctionChar); }, getExpressions: function(shortcut) { return shortcut.split(this.junctionChar); }, getWords: function(term) { return term.split(this.combinationChar); }, trim: function(shortcut) { return shortcut.replace(/\s/g, ""); }, junctionChar: ",", combinationChar: "+", commandKeys: { shift: 16, alt: 18, ctrl: 17, meta: true }, specialKeys: { backspace: 8, tab: 9, enter: 13, esc: 27, space: 32, up: 38, down: 40, left: 37, right: 39, home: 36, end: 35, pageup: 33, pagedown: 34, delete: 46, insert: 45, plus: 107, f1: 112, f2: 113, f3: 114, f4: 115, f5: 116, f6: 117, f7: 118, f8: 119, f9: 120, f10: 121, f11: 122, f12: 123 } }; } function eventhandler(gantt2) { gantt2.$keyboardNavigation.EventHandler = { _handlers: null, findHandler: function(command) { if (!this._handlers) this._handlers = {}; var shortcuts = gantt2.$keyboardNavigation.shortcuts; var hash = shortcuts.getHash(command); return this._handlers[hash]; }, doAction: function(command, e) { var handler = this.findHandler(command); if (handler) { var eventFacade = gantt2.$keyboardNavigation.facade; if (eventFacade.callEvent("onBeforeAction", [command, e]) === false) { return; } handler.call(this, e); if (e.preventDefault) e.preventDefault(); else e.returnValue = false; } }, bind: function(shortcut, handler) { if (!this._handlers) this._handlers = {}; var shortcuts = gantt2.$keyboardNavigation.shortcuts; var commands = shortcuts.parse(shortcut); for (var i = 0; i < commands.length; i++) { this._handlers[shortcuts.getHash(commands[i])] = handler; } }, unbind: function(shortcut) { var shortcuts = gantt2.$keyboardNavigation.shortcuts; var commands = shortcuts.parse(shortcut); for (var i = 0; i < commands.length; i++) { if (this._handlers[shortcuts.getHash(commands[i])]) { delete this._handlers[shortcuts.getHash(commands[i])]; } } }, bindAll: function(map) { for (var i in map) { this.bind(i, map[i]); } }, initKeys: function() { if (!this._handlers) this._handlers = {}; if (this.keys) { this.bindAll(this.keys); } } }; } function trap_modal_focus(gantt2) { (function() { gantt2.$keyboardNavigation.getFocusableNodes = getFocusableNodes; gantt2.$keyboardNavigation.trapFocus = function trapFocus(root, e) { if (e.keyCode != 9) return false; var focusable = gantt2.$keyboardNavigation.getFocusableNodes(root); var currentFocus = getActiveElement(); var currentIndex = -1; for (var i = 0; i < focusable.length; i++) { if (focusable[i] == currentFocus) { currentIndex = i; break; } } if (e.shiftKey) { if (currentIndex <= 0) { var lastItem = focusable[focusable.length - 1]; if (lastItem) { lastItem.focus(); e.preventDefault(); return true; } } } else { if (currentIndex >= focusable.length - 1) { var firstItem = focusable[0]; if (firstItem) { firstItem.focus(); e.preventDefault(); return true; } } } return false; }; })(); } function gantt_node(gantt2) { gantt2.$keyboardNavigation.GanttNode = function() { }; gantt2.$keyboardNavigation.GanttNode.prototype = gantt2._compose(gantt2.$keyboardNavigation.EventHandler, { focus: function() { gantt2.focus(); }, blur: function() { }, isEnabled: function() { return gantt2.$container.hasAttribute("tabindex"); }, scrollHorizontal: function scrollHorizontal(dir) { var date2 = gantt2.dateFromPos(gantt2.getScrollState().x); var scale = gantt2.getScale(); var step = dir < 0 ? -scale.step : scale.step; date2 = gantt2.date.add(date2, step, scale.unit); gantt2.scrollTo(gantt2.posFromDate(date2)); }, scrollVertical: function scrollVertical(dir) { var top = gantt2.getScrollState().y; var step = gantt2.config.row_height; gantt2.scrollTo(null, top + (dir < 0 ? -1 : 1) * step); }, keys: { "alt+left": function(e) { this.scrollHorizontal(-1); }, "alt+right": function(e) { this.scrollHorizontal(1); }, "alt+up": function(e) { this.scrollVertical(-1); }, "alt+down": function(e) { this.scrollVertical(1); }, "ctrl+z": function() { if (gantt2.undo) gantt2.undo(); }, "ctrl+r": function() { if (gantt2.redo) gantt2.redo(); } } }); gantt2.$keyboardNavigation.GanttNode.prototype.bindAll(gantt2.$keyboardNavigation.GanttNode.prototype.keys); } function nav_node(gantt2) { gantt2.$keyboardNavigation.KeyNavNode = function() { }; gantt2.$keyboardNavigation.KeyNavNode.prototype = gantt2._compose(gantt2.$keyboardNavigation.EventHandler, { isValid: function() { return true; }, fallback: function() { return null; }, moveTo: function(element) { gantt2.$keyboardNavigation.dispatcher.setActiveNode(element); }, compareTo: function(b) { if (!b) return false; for (var i in this) { if (!!this[i] != !!b[i]) return false; var canStringifyThis = !!(this[i] && this[i].toString); var canStringifyThat = !!(b[i] && b[i].toString); if (canStringifyThat != canStringifyThis) return false; if (!(canStringifyThat && canStringifyThis)) { if (b[i] != this[i]) return false; } else { if (b[i].toString() != this[i].toString()) return false; } } return true; }, getNode: function() { }, focus: function() { var node = this.getNode(); if (!node) return; var eventFacade = gantt2.$keyboardNavigation.facade; if (eventFacade.callEvent("onBeforeFocus", [node]) === false) { return; } if (node) { node.setAttribute("tabindex", "-1"); if (!node.$eventAttached) { node.$eventAttached = true; gantt2.event(node, "focus", function(e) { e.preventDefault(); return false; }, false); } if (gantt2.utils.dom.isChildOf(document.activeElement, node)) { node = document.activeElement; } if (node.focus) node.focus(); eventFacade.callEvent("onFocus", [this.getNode()]); } }, blur: function() { var node = this.getNode(); if (node) { var eventFacade = gantt2.$keyboardNavigation.facade; eventFacade.callEvent("onBlur", [node]); node.setAttribute("tabindex", "-1"); } } }); } function header_cell(gantt2) { gantt2.$keyboardNavigation.HeaderCell = function(index) { this.index = index || 0; }; gantt2.$keyboardNavigation.HeaderCell.prototype = gantt2._compose(gantt2.$keyboardNavigation.KeyNavNode, { _handlers: null, isValid: function() { if (!gantt2.config.show_grid) { if (gantt2.getVisibleTaskCount()) return false; } return !!gantt2.getGridColumns()[this.index] || !gantt2.getVisibleTaskCount(); }, fallback: function() { if (!gantt2.config.show_grid) { if (gantt2.getVisibleTaskCount()) { return new gantt2.$keyboardNavigation.TaskRow(); } return null; } var visibleColumns = gantt2.getGridColumns(); var index = this.index; while (index >= 0) { if (visibleColumns[index]) break; index--; } if (visibleColumns[index]) { return new gantt2.$keyboardNavigation.HeaderCell(index); } else { return null; } }, fromDomElement: function(el) { var cellElement = locateClassName(el, "gantt_grid_head_cell"); if (cellElement) { var index = 0; while (cellElement && cellElement.previousSibling) { cellElement = cellElement.previousSibling; index += 1; } return new gantt2.$keyboardNavigation.HeaderCell(index); } else { return null; } }, getNode: function() { const scale = gantt2.$grid_scale; if (!scale) { return null; } const cells = scale.childNodes; return cells[this.index]; }, keys: { left: function() { if (this.index > 0) { this.moveTo(new gantt2.$keyboardNavigation.HeaderCell(this.index - 1)); } }, right: function() { var columns = gantt2.getGridColumns(); if (this.index < columns.length - 1) { this.moveTo(new gantt2.$keyboardNavigation.HeaderCell(this.index + 1)); } }, down: function() { var taskRow; var rootLevel = gantt2.getChildren(gantt2.config.root_id); if (gantt2.isTaskExists(rootLevel[0])) { taskRow = rootLevel[0]; } if (taskRow) { if (gantt2.config.keyboard_navigation_cells) { this.moveTo(new gantt2.$keyboardNavigation.TaskCell(taskRow, this.index)); } else { this.moveTo(new gantt2.$keyboardNavigation.TaskRow(taskRow)); } } }, end: function() { var columns = gantt2.getGridColumns(); this.moveTo(new gantt2.$keyboardNavigation.HeaderCell(columns.length - 1)); }, home: function() { this.moveTo(new gantt2.$keyboardNavigation.HeaderCell(0)); }, "enter, space": function() { var node = getActiveElement(); node.click(); }, "ctrl+enter": function() { if (gantt2.isReadonly(this)) { return; } gantt2.createTask({}, this.taskId); } } }); gantt2.$keyboardNavigation.HeaderCell.prototype.bindAll(gantt2.$keyboardNavigation.HeaderCell.prototype.keys); } function task_row(gantt2) { gantt2.$keyboardNavigation.TaskRow = function(taskId) { if (!taskId) { var rootLevel = gantt2.getChildren(gantt2.config.root_id); if (rootLevel[0]) { taskId = rootLevel[0]; } } this.taskId = taskId; if (gantt2.isTaskExists(this.taskId)) { this.index = gantt2.getTaskIndex(this.taskId); this.globalIndex = gantt2.getGlobalTaskIndex(this.taskId); this.splitItem = !!gantt2.getTask(this.taskId).$split_subtask; this.parentId = gantt2.getParent(this.taskId); } }; gantt2.$keyboardNavigation.TaskRow.prototype = gantt2._compose(gantt2.$keyboardNavigation.KeyNavNode, { _handlers: null, isValid: function() { return gantt2.isTaskExists(this.taskId) && gantt2.getTaskIndex(this.taskId) > -1; }, fallback: function() { if (!gantt2.getVisibleTaskCount()) { var header = new gantt2.$keyboardNavigation.HeaderCell(); if (!header.isValid()) return null; else return header; } else { if (!this.splitItem) { var nextIndex = -1; if (gantt2.getTaskByIndex(this.globalIndex - 1)) { nextIndex = this.globalIndex - 1; } else if (gantt2.getTaskByIndex(this.globalIndex + 1)) { nextIndex = this.globalIndex + 1; } else { var globalIndex = this.globalIndex; while (globalIndex >= 0) { if (gantt2.getTaskByIndex(globalIndex)) { nextIndex = globalIndex; break; } globalIndex--; } } if (nextIndex > -1) { return new gantt2.$keyboardNavigation.TaskRow(gantt2.getTaskByIndex(nextIndex).id); } } else { return new gantt2.$keyboardNavigation.TaskRow(this.parentId); } } }, fromDomElement: function(el) { if (gantt2.config.keyboard_navigation_cells) { return null; } var taskId = gantt2.locate(el); if (gantt2.isTaskExists(taskId)) { return new gantt2.$keyboardNavigation.TaskRow(taskId); } else { return null; } }, getNode: function() { if (gantt2.isTaskExists(this.taskId) && gantt2.isTaskVisible(this.taskId)) { if (gantt2.config.show_grid) { return gantt2.$grid.querySelector(`.gantt_row[${gantt2.config.task_attribute}="${String(this.taskId).replaceAll('"', '\\"')}"]`); } else { return gantt2.getTaskNode(this.taskId); } } }, focus: function(keptFocus) { if (!keptFocus) { const pos = gantt2.getTaskPosition(gantt2.getTask(this.taskId)); const height = gantt2.getTaskHeight(this.taskId); const scroll = gantt2.getScrollState(); let viewWidth; if (gantt2.$task) { viewWidth = gantt2.$task.offsetWidth; } else { viewWidth = scroll.inner_width; } let viewHeight; if (gantt2.$grid_data || gantt2.$task_data) { viewHeight = (gantt2.$grid_data || gantt2.$task_data).offsetHeight; } else { viewHeight = scroll.inner_height; } const visibleTimeline = gantt2.config.show_chart && gantt2.$ui.getView("timeline"); if (pos.top < scroll.y || pos.top + height > scroll.y + viewHeight) { gantt2.scrollTo(null, pos.top - 20); } else if (gantt2.config.scroll_on_click && visibleTimeline) { if (pos.left > scroll.x + viewWidth) { gantt2.scrollTo(pos.left - gantt2.config.task_scroll_offset); } else if (pos.left + pos.width < scroll.x) { gantt2.scrollTo(pos.left + pos.width - gantt2.config.task_scroll_offset); } } } gantt2.$keyboardNavigation.KeyNavNode.prototype.focus.apply(this, [keptFocus]); scrollGrid(); function scrollGrid() { var grid = gantt2.$ui.getView("grid"); if (!grid || !grid.$grid_data) { return; } var scrollPositionX = parseInt(grid.$grid.scrollLeft); var scrollPositionY = parseInt(grid.$grid_data.scrollTop); var attachedScrollbarHorizontal = grid.$config.scrollX; if (attachedScrollbarHorizontal && grid.$config.scrollable) { var scrollbarHorizontal = gantt2.$ui.getView(attachedScrollbarHorizontal); if (scrollbarHorizontal) { scrollbarHorizontal.scrollTo(scrollPositionX, scrollPositionY); } } var attachedScrollbarVertical = grid.$config.scrollY; if (attachedScrollbarVertical) { var scrollbarVertical = gantt2.$ui.getView(attachedScrollbarVertical); if (scrollbarVertical) { scrollbarVertical.scrollTo(scrollPositionX, scrollPositionY); } } } }, keys: { pagedown: function() { if (gantt2.getVisibleTaskCount()) { this.moveTo(new gantt2.$keyboardNavigation.TaskRow(gantt2.getTaskByIndex(gantt2.getVisibleTaskCount() - 1).id)); } }, pageup: function() { if (gantt2.getVisibleTaskCount()) { this.moveTo(new gantt2.$keyboardNavigation.TaskRow(gantt2.getTaskByIndex(0).id)); } }, up: function() { var nextElement = null; var prevTask = gantt2.getPrev(this.taskId); if (!gantt2.isTaskExists(prevTask)) { nextElement = new gantt2.$keyboardNavigation.HeaderCell(); } else { nextElement = new gantt2.$keyboardNavigation.TaskRow(prevTask); } this.moveTo(nextElement); }, down: function() { var nextTask = gantt2.getNext(this.taskId); if (gantt2.isTaskExists(nextTask)) { this.moveTo(new gantt2.$keyboardNavigation.TaskRow(nextTask)); } }, "shift+down": function() { if (gantt2.hasChild(this.taskId) && !gantt2.getTask(this.taskId).$open) { gantt2.open(this.taskId); } }, "shift+up": function() { if (gantt2.hasChild(this.taskId) && gantt2.getTask(this.taskId).$open) { gantt2.close(this.taskId); } }, "shift+right": function() { if (gantt2.isReadonly(this)) { return; } var prevId = gantt2.getPrevSibling(this.taskId); if (gantt2.isTaskExists(prevId) && !gantt2.isChildOf(this.taskId, prevId)) { var parent = gantt2.getTask(prevId); parent.$open = true; var result = gantt2.moveTask(this.taskId, -1, prevId); if (result !== false) gantt2.updateTask(this.taskId); } }, "shift+left": function() { if (gantt2.isReadonly(this)) { return; } var parent = gantt2.getParent(this.taskId); if (gantt2.isTaskExists(parent)) { var result = gantt2.moveTask(this.taskId, gantt2.getTaskIndex(parent) + 1, gantt2.getParent(parent)); if (result !== false) gantt2.updateTask(this.taskId); } }, space: function(e) { if (!gantt2.isSelectedTask(this.taskId)) { gantt2.selectTask(this.taskId); } else { gantt2.unselectTask(this.taskId); } }, "ctrl+left": function(e) { gantt2.close(this.taskId); }, "ctrl+right": function(e) { gantt2.open(this.taskId); }, delete: function(e) { if (gantt2.isReadonly(this)) { return; } gantt2.$click.buttons["delete"](this.taskId); }, enter: function() { if (gantt2.isReadonly(this)) { return; } gantt2.showLightbox(this.taskId); }, "ctrl+enter": function() { if (gantt2.isReadonly(this)) { return; } gantt2.createTask({}, this.taskId); } } }); gantt2.$keyboardNavigation.TaskRow.prototype.bindAll(gantt2.$keyboardNavigation.TaskRow.prototype.keys); } function task_cell(gantt2) { gantt2.$keyboardNavigation.TaskCell = function(taskId, index) { taskId = replaceValidZeroId(taskId, gantt2.config.root_id); if (!taskId) { var rootLevel = gantt2.getChildren(gantt2.config.root_id); if (rootLevel[0]) { taskId = rootLevel[0]; } } this.taskId = taskId; this.columnIndex = index || 0; if (gantt2.isTaskExists(this.taskId)) { this.index = gantt2.getTaskIndex(this.taskId); this.globalIndex = gantt2.getGlobalTaskIndex(this.taskId); } }; gantt2.$keyboardNavigation.TaskCell.prototype = gantt2._compose(gantt2.$keyboardNavigation.TaskRow, { _handlers: null, isValid: function() { return gantt2.$keyboardNavigation.TaskRow.prototype.isValid.call(this) && !!gantt2.getGridColumns()[this.columnIndex]; }, fallback: function() { var node = gantt2.$keyboardNavigation.TaskRow.prototype.fallback.call(this); var result = node; if (node instanceof gantt2.$keyboardNavigation.TaskRow) { var visibleColumns = gantt2.getGridColumns(); var index = this.columnIndex; while (index >= 0) { if (visibleColumns[index]) break; index--; } if (visibleColumns[index]) { result = new gantt2.$keyboardNavigation.TaskCell(node.taskId, index); } } return result; }, fromDomElement: function(el) { if (!gantt2.config.keyboard_navigation_cells) { return null; } var taskId = gantt2.locate(el); if (gantt2.isTaskExists(taskId)) { var index = 0; var cellElement = locateAttribute(el, "data-column-index"); if (cellElement) { index = cellElement.getAttribute("data-column-index") * 1; } return new gantt2.$keyboardNavigation.TaskCell(taskId, index); } else { return null; } }, getNode: function() { if (gantt2.isTaskExists(this.taskId) && (gantt2.isTaskVisible(this.taskId) || gantt2.config.show_tasks_outside_timescale)) { if (gantt2.config.show_grid && gantt2.$grid) { var row = gantt2.$grid.querySelector(".gantt_row[" + gantt2.config.task_attribute + "='" + this.taskId + "']"); if (!row) return null; return row.querySelector("[data-column-index='" + this.columnIndex + "']"); } else { return gantt2.getTaskNode(this.taskId); } } }, keys: { up: function() { var nextElement = null; var prevTask = gantt2.getPrev(this.taskId); if (!gantt2.isTaskExists(prevTask)) { nextElement = new gantt2.$keyboardNavigation.HeaderCell(this.columnIndex); } else { nextElement = new gantt2.$keyboardNavigation.TaskCell(prevTask, this.columnIndex); } this.moveTo(nextElement); }, down: function() { var nextTask = gantt2.getNext(this.taskId); if (gantt2.isTaskExists(nextTask)) { this.moveTo(new gantt2.$keyboardNavigation.TaskCell(nextTask, this.columnIndex)); } }, left: function() { if (this.columnIndex > 0) { this.moveTo(new gantt2.$keyboardNavigation.TaskCell(this.taskId, this.columnIndex - 1)); } }, right: function() { var columns = gantt2.getGridColumns(); if (this.columnIndex < columns.length - 1) { this.moveTo(new gantt2.$keyboardNavigation.TaskCell(this.taskId, this.columnIndex + 1)); } }, end: function() { var columns = gantt2.getGridColumns(); this.moveTo(new gantt2.$keyboardNavigation.TaskCell(this.taskId, columns.length - 1)); }, home: function() { this.moveTo(new gantt2.$keyboardNavigation.TaskCell(this.taskId, 0)); }, pagedown: function() { if (gantt2.getVisibleTaskCount()) { this.moveTo(new gantt2.$keyboardNavigation.TaskCell(gantt2.getTaskByIndex(gantt2.getVisibleTaskCount() - 1).id, this.columnIndex)); } }, pageup: function() { if (gantt2.getVisibleTaskCount()) { this.moveTo(new gantt2.$keyboardNavigation.TaskCell(gantt2.getTaskByIndex(0).id, this.columnIndex)); } } } }); gantt2.$keyboardNavigation.TaskCell.prototype.bindAll(gantt2.$keyboardNavigation.TaskRow.prototype.keys); gantt2.$keyboardNavigation.TaskCell.prototype.bindAll(gantt2.$keyboardNavigation.TaskCell.prototype.keys); } function modals(gantt2) { (function() { var modalsStack = []; function isModal() { return !!modalsStack.length; } function afterPopup(box) { setTimeout(function() { if (!isModal()) { if (!gantt2.$destroyed) { gantt2.focus(); } } }, 1); } function startModal(box) { gantt2.eventRemove(box, "keydown", trapFocus); gantt2.event(box, "keydown", trapFocus); modalsStack.push(box); } function endModal() { var box = modalsStack.pop(); if (box) { gantt2.eventRemove(box, "keydown", trapFocus); } afterPopup(); } function isTopModal(box) { return box == modalsStack[modalsStack.length - 1]; } function trapFocus(event2) { var target = event2.currentTarget; if (!isTopModal(target)) return; gantt2.$keyboardNavigation.trapFocus(target, event2); } function traceLightbox() { startModal(gantt2.getLightbox()); } gantt2.attachEvent("onLightbox", traceLightbox); gantt2.attachEvent("onAfterLightbox", endModal); gantt2.attachEvent("onLightboxChange", function() { endModal(); traceLightbox(); }); gantt2.attachEvent("onAfterQuickInfo", function() { afterPopup(); }); gantt2.attachEvent("onMessagePopup", function(box) { saveFocus(); startModal(box); }); gantt2.attachEvent("onAfterMessagePopup", function() { endModal(); restoreFocus(); }); var focusElement = null; function saveFocus() { focusElement = gantt2.utils.dom.getActiveElement(); } function restoreFocus() { setTimeout(function() { if (focusElement && focusElement.focus) { focusElement.focus(); focusElement = null; } }, 1); } gantt2.$keyboardNavigation.isModal = isModal; })(); } function core(gantt2) { gantt2.$keyboardNavigation.dispatcher = { isActive: false, activeNode: null, globalNode: new gantt2.$keyboardNavigation.GanttNode(), enable: function() { this.isActive = true; this.setActiveNode(this.getActiveNode()); }, disable: function() { this.isActive = false; }, isEnabled: function() { return !!this.isActive; }, getDefaultNode: function() { var node; if (gantt2.config.keyboard_navigation_cells) { node = new gantt2.$keyboardNavigation.TaskCell(); } else { node = new gantt2.$keyboardNavigation.TaskRow(); } if (!node.isValid()) { node = node.fallback(); } return node; }, setDefaultNode: function() { this.setActiveNode(this.getDefaultNode()); }, getActiveNode: function() { var node = this.activeNode; if (node && !node.isValid()) { node = node.fallback(); } return node; }, fromDomElement: function(e) { var inputs = [gantt2.$keyboardNavigation.TaskRow, gantt2.$keyboardNavigation.TaskCell, gantt2.$keyboardNavigation.HeaderCell]; for (var i = 0; i < inputs.length; i++) { if (inputs[i].prototype.fromDomElement) { var node = inputs[i].prototype.fromDomElement(e); if (node) return node; } } return null; }, focusGlobalNode: function() { this.blurNode(this.globalNode); this.focusNode(this.globalNode); }, setActiveNode: function(el) { var focusChanged = true; if (this.activeNode) { if (this.activeNode.compareTo(el)) { focusChanged = false; } } if (this.isEnabled()) { if (focusChanged) this.blurNode(this.activeNode); this.activeNode = el; this.focusNode(this.activeNode, !focusChanged); } }, focusNode: function(el, keptFocus) { if (el && el.focus) { el.focus(keptFocus); } }, blurNode: function(el) { if (el && el.blur) { el.blur(); } }, keyDownHandler: function(e) { if (gantt2.$keyboardNavigation.isModal()) return; if (!this.isEnabled()) return; if (e.defaultPrevented) { return; } var ganttNode = this.globalNode; var command = gantt2.$keyboardNavigation.shortcuts.getCommandFromEvent(e); var activeElement = this.getActiveNode(); var eventFacade = gantt2.$keyboardNavigation.facade; if (eventFacade.callEvent("onKeyDown", [command, e]) === false) { return; } if (!activeElement) { this.setDefaultNode(); } else if (activeElement.findHandler(command)) { activeElement.doAction(command, e); } else if (ganttNode.findHandler(command)) { ganttNode.doAction(command, e); } }, _timeout: null, awaitsFocus: function() { return this._timeout !== null; }, delay: function(callback, delay2) { clearTimeout(this._timeout); this._timeout = setTimeout(gantt2.bind(function() { this._timeout = null; callback(); }, this), delay2 || 1); }, clearDelay: function() { clearTimeout(this._timeout); } }; } function keyboard_navigation(gantt2) { function setupKeyNav(gantt3) { gantt3.config.keyboard_navigation = true; gantt3.config.keyboard_navigation_cells = false; gantt3.$keyboardNavigation = {}; gantt3._compose = function() { var parts = Array.prototype.slice.call(arguments, 0); var res = {}; for (var i = 0; i < parts.length; i++) { var obj = parts[i]; if (typeof obj == "function") { obj = new obj(); } for (var p in obj) { res[p] = obj[p]; } } return res; }; keyboard_shortcuts(gantt3); eventhandler(gantt3); trap_modal_focus(gantt3); gantt_node(gantt3); nav_node(gantt3); header_cell(gantt3); task_row(gantt3); task_cell(gantt3); modals(gantt3); core(gantt3); (function() { var dispatcher = gantt3.$keyboardNavigation.dispatcher; dispatcher.isTaskFocused = function(id) { var node = dispatcher.activeNode; if (node instanceof gantt3.$keyboardNavigation.TaskRow || node instanceof gantt3.$keyboardNavigation.TaskCell) { if (node.taskId == id) { return true; } } return false; }; var keyDownHandler = function(e) { if (!gantt3.config.keyboard_navigation) return; if (!gantt3.config.keyboard_navigation_cells && isInlineEditorCell(e)) return; if (isNoKeyboardNavigationElement(e) || isLightboxElement(e)) { return; } return dispatcher.keyDownHandler(e); }; var focusHandler = function(e) { if (dispatcher.$preventDefault) { e.preventDefault(); gantt3.$container.blur(); return false; } else if (!dispatcher.awaitsFocus()) { dispatcher.focusGlobalNode(); } }; var reFocusActiveNode = function() { if (!dispatcher.isEnabled()) return; const outsideGantt = !isChildOf(document.activeElement, gantt3.$container) && document.activeElement.localName != "body"; var activeNode = dispatcher.getActiveNode(); if (!activeNode || outsideGantt) return; var domElement = activeNode.getNode(); var top, left; if (domElement && domElement.parentNode) { top = domElement.parentNode.scrollTop; left = domElement.parentNode.scrollLeft; } activeNode.focus(true); if (domElement && domElement.parentNode) { domElement.parentNode.scrollTop = top; domElement.parentNode.scrollLeft = left; } }; gantt3.attachEvent("onDataRender", function() { if (!gantt3.config.keyboard_navigation) return; reFocusActiveNode(); }); gantt3.attachEvent("onGanttRender", function() { if (!gantt3.$root) return; gantt3.eventRemove(gantt3.$root, "keydown", keyDownHandler); gantt3.eventRemove(gantt3.$container, "focus", focusHandler); gantt3.eventRemove(gantt3.$container, "mousedown", mousedownHandler); if (gantt3.config.keyboard_navigation) { gantt3.event(gantt3.$root, "keydown", keyDownHandler); gantt3.event(gantt3.$container, "focus", focusHandler); gantt3.event(gantt3.$container, "mousedown", mousedownHandler); gantt3.$container.setAttribute("tabindex", "0"); } else { gantt3.$container.removeAttribute("tabindex"); } }); function getTaskNodeConstructor() { if (gantt3.config.keyboard_navigation_cells) { return gantt3.$keyboardNavigation.TaskCell; } else { return gantt3.$keyboardNavigation.TaskRow; } } function isInlineEditorCell(e) { return !!closest(e.target, ".gantt_grid_editor_placeholder"); } function isNoKeyboardNavigationElement(e) { return !!closest(e.target, ".no_keyboard_navigation"); } function isLightboxElement(e) { return !!closest(e.target, ".gantt_cal_light"); } function mousedownHandler(e) { if (!gantt3.config.keyboard_navigation) return true; if (!gantt3.config.keyboard_navigation_cells && isInlineEditorCell(e)) return true; if (isNoKeyboardNavigationElement(e)) { return; } var focusNode; var locateTask = dispatcher.fromDomElement(e); if (locateTask) { if (dispatcher.activeNode instanceof gantt3.$keyboardNavigation.TaskCell && isChildOf(e.target, gantt3.$task)) { locateTask = new gantt3.$keyboardNavigation.TaskCell(locateTask.taskId, dispatcher.activeNode.columnIndex); } focusNode = locateTask; const visibleGrid = gantt3.config.show_grid && gantt3.$ui.getView("grid"); if (visibleGrid && gantt3.config.keyboard_navigation_cells) { const taskRow = e.target.classList.contains("gantt_row"); const taskBar = e.target.closest(".gantt_task_line"); const gridLeft = gantt3.utils.dom.getNodePosition(gantt3.$grid).x; const gridRight = gridLeft + gantt3.$grid.offsetWidth; const nodePosition = gantt3.utils.dom.getNodePosition(document.activeElement).x; const nodeHidden = nodePosition < gridLeft || gridRight < nodePosition; if (taskRow || taskBar && nodeHidden) { let scrollPosition = gantt3.$grid.scrollLeft; const rightPosition = scrollPosition + gantt3.$grid.offsetWidth; let positionX = 0; if (taskRow) { scrollPosition = gantt3.utils.dom.getRelativeEventPosition(e, gantt3.$grid).x; } for (let i = 0; i < gantt3.config.columns.length; i++) { const column = gantt3.config.columns[i]; if (column.hide) { continue; } positionX += column.width; if (scrollPosition < positionX) { if (rightPosition < positionX) { positionX -= column.width; } focusNode.columnIndex = i; break; } } } } } if (focusNode) { if (!dispatcher.isEnabled()) { dispatcher.activeNode = focusNode; } else { dispatcher.delay(function() { dispatcher.setActiveNode(focusNode); }); } } else { dispatcher.$preventDefault = true; setTimeout(function() { dispatcher.$preventDefault = false; }, 300); } } var onReady = gantt3.attachEvent("onGanttReady", function() { gantt3.detachEvent(onReady); gantt3.$data.tasksStore.attachEvent("onStoreUpdated", function(id) { if (gantt3.config.keyboard_navigation && dispatcher.isEnabled()) { const currentNode = dispatcher.getActiveNode(); const grid = gantt3.$ui.getView("grid"); if (!grid || !grid.$grid_data) { return; } const top = grid.getItemTop(id); const gridDataTopScroll = grid.$grid_data.scrollTop; const gridDataBottomScroll = gridDataTopScroll + grid.$grid_data.getBoundingClientRect().height; if (currentNode && currentNode.taskId == id) { if (gridDataTopScroll <= top && gridDataBottomScroll >= top) { reFocusActiveNode(); } } } }); if (gantt3._smart_render) { var updateRender = gantt3._smart_render._redrawTasks; gantt3._smart_render._redrawTasks = function(renderers, items) { if (gantt3.config.keyboard_navigation && dispatcher.isEnabled()) { var currentNode = dispatcher.getActiveNode(); if (currentNode && currentNode.taskId !== void 0) { var focusedItemVisible = false; for (var i = 0; i < items.length; i++) { if (items[i].id == currentNode.taskId && items[i].start_date) { focusedItemVisible = true; break; } } if (!focusedItemVisible) { items.push(gantt3.getTask(currentNode.taskId)); } } } var res = updateRender.apply(this, arguments); return res; }; } }); let createdTaskId = null; let keepFocusOnNewTask = false; gantt3.attachEvent("onTaskCreated", function(task) { createdTaskId = task.id; return true; }); gantt3.attachEvent("onAfterTaskAdd", function(id, item) { if (!gantt3.config.keyboard_navigation) return true; if (dispatcher.isEnabled()) { if (id == createdTaskId) { keepFocusOnNewTask = true; setTimeout(() => { keepFocusOnNewTask = false; createdTaskId = null; }); } if (keepFocusOnNewTask && item.type == gantt3.config.types.placeholder) { return; } var columnIndex = 0; var node = dispatcher.activeNode; if (node instanceof gantt3.$keyboardNavigation.TaskCell) { columnIndex = node.columnIndex; } var nodeConstructor = getTaskNodeConstructor(); if (item.type == gantt3.config.types.placeholder && gantt3.config.placeholder_task.focusOnCreate === false) ; else { dispatcher.setActiveNode(new nodeConstructor(id, columnIndex)); } } }); gantt3.attachEvent("onTaskIdChange", function(oldId, newId) { if (!gantt3.config.keyboard_navigation) return true; var node = dispatcher.activeNode; if (dispatcher.isTaskFocused(oldId)) { node.taskId = newId; } return true; }); var interval = setInterval(function() { if (!gantt3.config.keyboard_navigation) return; if (!dispatcher.isEnabled()) { dispatcher.enable(); } return; }, 500); gantt3.attachEvent("onDestroy", function() { clearInterval(interval); }); function getScopeName(obj) { if (obj instanceof gantt3.$keyboardNavigation.GanttNode) { return "gantt"; } else if (obj instanceof gantt3.$keyboardNavigation.HeaderCell) { return "headerCell"; } else if (obj instanceof gantt3.$keyboardNavigation.TaskRow) { return "taskRow"; } else if (obj instanceof gantt3.$keyboardNavigation.TaskCell) { return "taskCell"; } return null; } function getScope(mode) { var scopes = { gantt: gantt3.$keyboardNavigation.GanttNode, headerCell: gantt3.$keyboardNavigation.HeaderCell, taskRow: gantt3.$keyboardNavigation.TaskRow, taskCell: gantt3.$keyboardNavigation.TaskCell }; return scopes[mode] || scopes.gantt; } function findVisibleColumnIndex(columnName) { var columns = gantt3.getGridColumns(); for (var i = 0; i < columns.length; i++) { if (columns[i].name == columnName) { return i; } } return 0; } var keyNavFacade = {}; makeEventable(keyNavFacade); gantt3.mixin(keyNavFacade, { addShortcut: function(shortcut, handler, scope2) { var scopeObject = getScope(scope2); if (scopeObject) { scopeObject.prototype.bind(shortcut, handler); } }, getShortcutHandler: function(shortcut, scope2) { var commands = gantt3.$keyboardNavigation.shortcuts.parse(shortcut); if (commands.length) { return keyNavFacade.getCommandHandler(commands[0], scope2); } }, getCommandHandler: function(command, scope2) { var scopeObject = getScope(scope2); if (scopeObject) { if (command) { return scopeObject.prototype.findHandler(command); } } }, removeShortcut: function(shortcut, scope2) { var scopeObject = getScope(scope2); if (scopeObject) { scopeObject.prototype.unbind(shortcut); } }, focus: function(config2) { var type = config2 ? config2.type : null; var constructor = getScope(type); var node; switch (type) { case "taskCell": node = new constructor(config2.id, findVisibleColumnIndex(config2.column)); break; case "taskRow": node = new constructor(config2.id); break; case "headerCell": node = new constructor(findVisibleColumnIndex(config2.column)); break; } dispatcher.delay(function() { if (node) { dispatcher.setActiveNode(node); } else { dispatcher.enable(); if (!dispatcher.getActiveNode()) { dispatcher.setDefaultNode(); } else { if (!dispatcher.awaitsFocus()) { dispatcher.enable(); } } } }); }, getActiveNode: function() { if (dispatcher.isEnabled()) { var node = dispatcher.getActiveNode(); var scope2 = getScopeName(node); var columns = gantt3.getGridColumns(); switch (scope2) { case "taskCell": return { type: "taskCell", id: node.taskId, column: columns[node.columnIndex].name }; case "taskRow": return { type: "taskRow", id: node.taskId }; case "headerCell": return { type: "headerCell", column: columns[node.index].name }; } } return null; } }); gantt3.$keyboardNavigation.facade = keyNavFacade; gantt3.ext.keyboardNavigation = keyNavFacade; gantt3.focus = function() { keyNavFacade.focus(); }; gantt3.addShortcut = keyNavFacade.addShortcut; gantt3.getShortcutHandler = keyNavFacade.getShortcutHandler; gantt3.removeShortcut = keyNavFacade.removeShortcut; })(); } setupKeyNav(gantt2); } function marker(gantt2) { if (!gantt2._markers) { gantt2._markers = gantt2.createDatastore({ name: "marker", initItem: function(marker2) { marker2.id = marker2.id || gantt2.uid(); return marker2; } }); } gantt2.config.show_markers = true; function render_marker(marker2) { if (!gantt2.config.show_markers) return false; if (!marker2.start_date) return false; var state = gantt2.getState(); if (+marker2.start_date > +state.max_date) return; if ((!marker2.end_date || +marker2.end_date < +state.min_date) && +marker2.start_date < +state.min_date) return; var div = document.createElement("div"); div.setAttribute("data-marker-id", marker2.id); var css = "gantt_marker"; if (gantt2.templates.marker_class) css += " " + gantt2.templates.marker_class(marker2); if (marker2.css) { css += " " + marker2.css; } if (gantt2.templates.marker_class) css += " " + gantt2.templates.marker_class(marker2); if (marker2.title) { div.title = marker2.title; } div.className = css; var start = gantt2.posFromDate(marker2.start_date); div.style.left = start + "px"; let markerHeight = Math.max(gantt2.getRowTop(gantt2.getVisibleTaskCount()), 0) + "px"; if (gantt2.config.timeline_placeholder && gantt2.$task_data) { markerHeight = gantt2.$task_data.scrollHeight + "px"; } div.style.height = markerHeight; if (marker2.end_date) { var end = gantt2.posFromDate(marker2.end_date); div.style.width = Math.max(end - start, 0) + "px"; } if (marker2.text) { let content = null; if (typeof marker2.text === "function") { content = marker2.text(marker2); } else { content = marker2.text; } if (content) { if (gantt2.config.external_render && gantt2.config.external_render.isElement(content)) { div.innerHTML = "
"; gantt2.config.external_render.renderElement(content, div.querySelector(".gantt_marker_content")); } else { div.innerHTML = "
" + marker2.text + "
"; } } } return div; } function initMarkerArea() { if (!gantt2.$task_data || !gantt2.$root.contains(gantt2.$task_data)) { gantt2.$marker_area = null; return; } if (gantt2.$marker_area && gantt2.$task_data.contains(gantt2.$marker_area)) { return; } var markerArea = document.createElement("div"); markerArea.className = "gantt_marker_area"; gantt2.$task_data.appendChild(markerArea); gantt2.$marker_area = markerArea; } gantt2.attachEvent("onBeforeGanttRender", function() { if (!gantt2.$marker_area) initMarkerArea(); }); gantt2.attachEvent("onDataRender", function() { if (!gantt2.$marker_area) { initMarkerArea(); gantt2.renderMarkers(); } }); gantt2.attachEvent("onGanttLayoutReady", function() { gantt2.attachEvent("onBeforeGanttRender", function() { if (gantt2.$marker_area) { gantt2.$marker_area.innerHTML = ""; } initMarkerArea(); var layers = gantt2.$services.getService("layers"); var markerRenderer = layers.createDataRender({ name: "marker", defaultContainer: function() { return gantt2.$marker_area; } }); markerRenderer.addLayer(render_marker); }, { once: true }); }); gantt2.getMarker = function(id) { if (!this._markers) return null; return this._markers.getItem(id); }; gantt2.addMarker = function(marker2) { return this._markers.addItem(marker2); }; gantt2.deleteMarker = function(id) { if (!this._markers.exists(id)) return false; this._markers.removeItem(id); return true; }; gantt2.updateMarker = function(id) { this._markers.refresh(id); }; gantt2._getMarkers = function() { return this._markers.getItems(); }; gantt2.renderMarkers = function() { this._markers.refresh(); }; } function multiselect(gantt2) { gantt2.config.multiselect = true; gantt2.config.multiselect_one_level = false; gantt2._multiselect = { _selected: {}, _one_level: false, _active: true, _first_selected_when_shift: null, getDefaultSelected: function() { var selected = this.getSelected(); return selected.length ? selected[selected.length - 1] : null; }, setFirstSelected: function(id) { this._first_selected_when_shift = id; }, getFirstSelected: function() { return this._first_selected_when_shift; }, isActive: function() { this.updateState(); return this._active; }, updateState: function() { this._one_level = gantt2.config.multiselect_one_level; var active = this._active; this._active = gantt2.config.select_task; if (this._active != active) { this.reset(); } }, reset: function() { this._selected = {}; }, setLastSelected: function(id) { gantt2.$data.tasksStore.silent(function() { var store = gantt2.$data.tasksStore; if (id) store.select(id + ""); else store.unselect(null); }); }, getLastSelected: function() { var last = gantt2.$data.tasksStore.getSelectedId(); if (last && gantt2.isTaskExists(last)) return last; return null; }, select: function(id, e) { if (id && gantt2.callEvent("onBeforeTaskMultiSelect", [id, true, e]) && gantt2.callEvent("onBeforeTaskSelected", [id])) { this._selected[id] = true; this.setLastSelected(id); this.afterSelect(id); gantt2.callEvent("onTaskMultiSelect", [id, true, e]); gantt2.callEvent("onTaskSelected", [id]); return true; } return false; }, toggle: function(id, e) { if (this._selected[id]) { this.unselect(id, e); } else { this.select(id, e); } }, unselect: function(id, e) { if (id && gantt2.callEvent("onBeforeTaskMultiSelect", [id, false, e])) { this._selected[id] = false; if (this.getLastSelected() == id) this.setLastSelected(this.getDefaultSelected()); this.afterSelect(id); gantt2.callEvent("onTaskMultiSelect", [id, false, e]); gantt2.callEvent("onTaskUnselected", [id]); } }, isSelected: function(id) { return !!(gantt2.isTaskExists(id) && this._selected[id]); }, getSelected: function() { var res = []; for (var i in this._selected) { if (this._selected[i] && gantt2.isTaskExists(i)) { res.push(i); } else { this._selected[i] = false; } } res.sort(function(a, b) { return gantt2.getGlobalTaskIndex(a) > gantt2.getGlobalTaskIndex(b) ? 1 : -1; }); return res; }, forSelected: function(callback) { var selected = this.getSelected(); for (var i = 0; i < selected.length; i++) { callback(selected[i]); } }, isSameLevel: function(id) { if (!this._one_level) return true; var last = this.getLastSelected(); if (!last) return true; if (!(gantt2.isTaskExists(last) && gantt2.isTaskExists(id))) return true; return !!(gantt2.calculateTaskLevel(gantt2.getTask(last)) == gantt2.calculateTaskLevel(gantt2.getTask(id))); }, afterSelect: function(id) { if (gantt2.isTaskExists(id)) { gantt2._quickRefresh(function() { gantt2.refreshTask(id); }); } }, doSelection: function(e) { if (!this.isActive()) return false; if (gantt2._is_icon_open_click(e)) return false; var target_ev = gantt2.locate(e); if (!target_ev) return false; if (!gantt2.callEvent("onBeforeMultiSelect", [e])) return false; var selected = this.getSelected(); var defaultLast = this.getFirstSelected(); var isLast = false; var last = this.getLastSelected(); var multiSelect = gantt2.config.multiselect; var singleSelection = (function() { const controller = gantt2.ext.inlineEditors; if (controller && controller.getState) { const state = controller.getState(); const cell = controller.locateCell(e.target); if (gantt2.config.inline_editors_multiselect_open && cell && controller.getEditorConfig(cell.columnName)) { if (controller.isVisible() && state.id == cell.id && state.columnName == cell.columnName) ; else { controller.startEdit(cell.id, cell.columnName); } } } this.setFirstSelected(target_ev); if (!this.isSelected(target_ev)) { this.select(target_ev, e); } selected = this.getSelected(); for (var i = 0; i < selected.length; i++) { if (selected[i] !== target_ev) { this.unselect(selected[i], e); } } }).bind(this); var blockSelection = (function() { if (!last) last = target_ev; else if (target_ev) { var first_indx = gantt2.getGlobalTaskIndex(this.getFirstSelected()); var target_indx = gantt2.getGlobalTaskIndex(target_ev); var last_indx = gantt2.getGlobalTaskIndex(last); if (first_indx == -1 || last_indx == -1) { first_indx = target_indx; this.reset(); } var tmp = last; while (gantt2.getGlobalTaskIndex(tmp) !== first_indx) { this.unselect(tmp, e); tmp = first_indx > last_indx ? gantt2.getNext(tmp) : gantt2.getPrev(tmp); } tmp = target_ev; while (gantt2.getGlobalTaskIndex(tmp) !== first_indx) { if (this.select(tmp, e) && !isLast) { isLast = true; defaultLast = tmp; } tmp = first_indx > target_indx ? gantt2.getNext(tmp) : gantt2.getPrev(tmp); } } }).bind(this); if (multiSelect && (e.ctrlKey || e.metaKey)) { if (!this.isSelected(target_ev)) this.setFirstSelected(target_ev); if (target_ev) { this.toggle(target_ev, e); } } else if (multiSelect && e.shiftKey) { if (!gantt2.isTaskExists(this.getFirstSelected()) || this.getFirstSelected() === null) { this.setFirstSelected(target_ev); } if (selected.length) { blockSelection(); } else { singleSelection(); } } else { singleSelection(); } if (this.isSelected(target_ev)) { this.setLastSelected(target_ev); } else if (defaultLast) { if (target_ev == last) this.setLastSelected(e.shiftKey ? defaultLast : this.getDefaultSelected()); } else { this.setLastSelected(null); } if (!this.getSelected().length) this.setLastSelected(null); if (!this.getLastSelected() || !this.isSelected(this.getFirstSelected())) this.setFirstSelected(this.getLastSelected()); return true; } }; (function() { var old_selectTask = gantt2.selectTask; gantt2.selectTask = function(id) { id = replaceValidZeroId(id, this.config.root_id); if (!id) return false; var multiselect2 = gantt2._multiselect; var res = id; if (multiselect2.isActive()) { if (multiselect2.select(id, null)) { multiselect2.setLastSelected(id); } multiselect2.setFirstSelected(multiselect2.getLastSelected()); } else { res = old_selectTask.call(this, id); } return res; }; var old_unselectTask = gantt2.unselectTask; gantt2.unselectTask = function(id) { var multiselect2 = gantt2._multiselect; var isActive = multiselect2.isActive(); id = id || multiselect2.getLastSelected(); if (id && isActive) { multiselect2.unselect(id, null); if (id == multiselect2.getLastSelected()) multiselect2.setLastSelected(null); gantt2.refreshTask(id); multiselect2.setFirstSelected(multiselect2.getLastSelected()); } var res = id; if (!isActive) res = old_unselectTask.call(this, id); return res; }; gantt2.toggleTaskSelection = function(id) { var multiselect2 = gantt2._multiselect; if (id && multiselect2.isActive()) { multiselect2.toggle(id); multiselect2.setFirstSelected(multiselect2.getLastSelected()); } }; gantt2.getSelectedTasks = function() { var multiselect2 = gantt2._multiselect; multiselect2.isActive(); return multiselect2.getSelected(); }; gantt2.eachSelectedTask = function(callback) { return this._multiselect.forSelected(callback); }; gantt2.isSelectedTask = function(id) { return this._multiselect.isSelected(id); }; gantt2.getLastSelectedTask = function() { return this._multiselect.getLastSelected(); }; gantt2.attachEvent("onGanttReady", function() { var old_isSelected = gantt2.$data.tasksStore.isSelected; gantt2.$data.tasksStore.isSelected = function(id) { if (gantt2._multiselect.isActive()) { return gantt2._multiselect.isSelected(id); } return old_isSelected.call(this, id); }; }); })(); gantt2.attachEvent("onTaskIdChange", function(id, new_id) { var multiselect2 = gantt2._multiselect; if (!multiselect2.isActive()) return true; if (gantt2.isSelectedTask(id)) { multiselect2.unselect(id, null); multiselect2.select(new_id, null); } }); gantt2.attachEvent("onAfterTaskDelete", function(id, item) { var multiselect2 = gantt2._multiselect; if (!multiselect2.isActive()) return true; if (multiselect2._selected[id]) { multiselect2._selected[id] = false; multiselect2.setLastSelected(multiselect2.getDefaultSelected()); } multiselect2.forSelected(function(task_id) { if (!gantt2.isTaskExists(task_id)) multiselect2.unselect(task_id, null); }); }); gantt2.attachEvent("onBeforeTaskMultiSelect", function(id, state, e) { const multiselect2 = gantt2._multiselect; if (state && multiselect2.isActive()) { let oldSelectedId = gantt2.getSelectedId(); let oldSelectedTask = null; if (oldSelectedId) { oldSelectedTask = gantt2.getTask(oldSelectedId); } let newSelectedTask = gantt2.getTask(id); let differentTreeLevel = false; if (oldSelectedTask && oldSelectedTask.$level != newSelectedTask.$level) { differentTreeLevel = true; } if (gantt2.config.multiselect_one_level && differentTreeLevel && !e.ctrlKey && !e.shiftKey) { return true; } if (multiselect2._one_level) { return multiselect2.isSameLevel(id); } } return true; }); gantt2.attachEvent("onTaskClick", function(id, e) { if (gantt2._multiselect.doSelection(e)) gantt2.callEvent("onMultiSelect", [e]); return true; }); } class QuickInfo { constructor(gantt2) { this.show = (id, y) => { if (y === void 0) { this._showForTask(id); } else { this._showAtCoordinates(id, y); } }; this.hide = (forced) => { const gantt3 = this._gantt; const qi = this._quickInfoBox; this._quickInfoBoxId = 0; const taskId = this._quickInfoTask; this._quickInfoTask = null; if (qi && qi.parentNode) { if (gantt3.config.quick_info_detached) { gantt3.callEvent("onAfterQuickInfo", [taskId]); return qi.parentNode.removeChild(qi); } qi.className += " gantt_qi_hidden"; if (qi.style.right === "auto") { qi.style.left = "-350px"; } else { qi.style.right = "-350px"; } if (forced) { qi.style.left = qi.style.right = ""; qi.parentNode.removeChild(qi); } gantt3.callEvent("onAfterQuickInfo", [taskId]); } }; this.getNode = () => { if (this._quickInfoBox) { return this._quickInfoBox; } return null; }; this.setContainer = (container) => { if (container) { this._container = typeof container === "string" ? document.getElementById(container) : container; } }; this.setContent = (content) => { const gantt3 = this._gantt; const defaultContent = { taskId: null, header: { title: "", date: "" }, content: "", buttons: gantt3.config.quickinfo_buttons }; if (!content) { content = defaultContent; } if (!content.taskId) { content.taskId = defaultContent.taskId; } if (!content.header) { content.header = defaultContent.header; } if (!content.header.title) { content.header.title = defaultContent.header.title; } if (!content.header.date) { content.header.date = defaultContent.header.date; } if (!content.content) { content.content = defaultContent.content; } if (!content.buttons) { content.buttons = defaultContent.buttons; } let qi = this.getNode(); if (!qi) { qi = this._createQuickInfoElement(); } if (content.taskId) { this._quickInfoBoxId = content.taskId; } const titleBox = qi.querySelector(".gantt_cal_qi_title"); const titleContent = titleBox.querySelector(".gantt_cal_qi_tcontent"); const titleDate = titleBox.querySelector(".gantt_cal_qi_tdate"); const main = qi.querySelector(".gantt_cal_qi_content"); const controls = qi.querySelector(".gantt_cal_qi_controls"); gantt3._waiAria.quickInfoHeader(qi, [content.header.title, content.header.date].join(" ")); titleContent.innerHTML = content.header.title; titleDate.innerHTML = content.header.date; if (!content.header.title && !content.header.date) { titleBox.style.display = "none"; } else { titleBox.style.display = ""; } main.innerHTML = content.content; const buttons = content.buttons; if (!buttons.length) { controls.style.display = "none"; } else { controls.style.display = ""; } let html = ""; for (let i = 0; i < buttons.length; i++) { const ariaAttr = gantt3._waiAria.quickInfoButtonAttrString(gantt3.locale.labels[buttons[i]]); html += `
${gantt3.locale.labels[buttons[i]]}
`; } controls.innerHTML = html; gantt3.eventRemove(qi, "click", this._qiButtonClickHandler); gantt3.eventRemove(qi, "keypress", this._qiKeyPressHandler); gantt3.event(qi, "click", this._qiButtonClickHandler); gantt3.event(qi, "keypress", this._qiKeyPressHandler); }; this._qiButtonClickHandler = (ev) => { this._qi_button_click(ev.target); }; this._qiKeyPressHandler = (e) => { const code = e.which; if (code === 13 || code === 32) { setTimeout(() => { this._qi_button_click(e.target); }, 1); } }; this._gantt = gantt2; } _showAtCoordinates(x, y) { this.hide(true); this._quickInfoBoxId = 0; this._quickInfoTask = null; if (!this._quickInfoBox) { this._createQuickInfoElement(); this.setContent(); } this._appendAtCoordinates(x, y); this._gantt.callEvent("onQuickInfo", [null]); } _showForTask(id) { const gantt2 = this._gantt; if (id === this._quickInfoBoxId && gantt2.utils.dom.isChildOf(this._quickInfoBox, document.body) || !gantt2.config.show_quick_info) { return; } this.hide(true); const offset = 6; const container = this._getContainer(); const pos = this._get_event_counter_part(id, offset, container.xViewport, container.yViewport); if (pos) { this._quickInfoBox = this._init_quick_info(id); this._quickInfoTask = id; this._quickInfoBox.className = this._prepare_quick_info_classname(id); this._fill_quick_data(id); this._show_quick_info(pos, offset); gantt2.callEvent("onQuickInfo", [id]); } } _get_event_counter_part(id, offset, xViewport, yViewport) { const gantt2 = this._gantt; let domEv = gantt2.getTaskNode(id); if (!domEv) { domEv = gantt2.getTaskRowNode(id); if (!domEv) { return null; } } let left = 0; const top = offset + domEv.offsetTop + domEv.offsetHeight; let node = domEv; if (gantt2.utils.dom.isChildOf(node, xViewport)) { while (node && node !== xViewport) { left += node.offsetLeft; node = node.offsetParent; } } const scroll = gantt2.getScrollState(); if (node) { const dx = left + domEv.offsetWidth / 2 - scroll.x > xViewport.offsetWidth / 2 ? 1 : 0; const dy = top + domEv.offsetHeight / 2 - scroll.y > yViewport.offsetHeight / 2 ? 1 : 0; return { left, top, dx, dy, width: domEv.offsetWidth, height: domEv.offsetHeight }; } return null; } _createQuickInfoElement() { const gantt2 = this._gantt; const qi = document.createElement("div"); qi.className += "gantt_cal_quick_info"; gantt2._waiAria.quickInfoAttr(qi); const ariaAttr = gantt2._waiAria.quickInfoHeaderAttrString(); var html = `
`; html += '
'; html += "
"; qi.innerHTML = html; if (gantt2.config.quick_info_detached) { const container = this._getContainer(); gantt2.event(container.parent, "scroll", () => { this.hide(); }); } this._quickInfoBox = qi; return qi; } _init_quick_info(id) { const gantt2 = this._gantt; const task = gantt2.getTask(id); if (typeof this._quickInfoReadonly === "boolean") { if (gantt2.isReadonly(task) !== this._quickInfoReadonly) { this.hide(true); this._quickInfoBox = null; } } this._quickInfoReadonly = gantt2.isReadonly(task); if (!this._quickInfoBox) { this._quickInfoBox = this._createQuickInfoElement(); } return this._quickInfoBox; } _prepare_quick_info_classname(id) { const gantt2 = this._gantt; const task = gantt2.getTask(id); const taskType = gantt2.getTaskType(task); let css = `gantt_cal_quick_info gantt_${taskType}`; const template = gantt2.templates.quick_info_class(task.start_date, task.end_date, task); if (template) { css += " " + template; } return css; } _fill_quick_data(id) { const gantt2 = this._gantt; const ev = gantt2.getTask(id); this._quickInfoBoxId = id; let allowedButtons = []; if (this._quickInfoReadonly) { const buttons = gantt2.config.quickinfo_buttons; const isEditor = { icon_delete: true, icon_edit: true }; for (let i = 0; i < buttons.length; i++) { if (this._quickInfoReadonly && isEditor[buttons[i]]) { continue; } allowedButtons.push(buttons[i]); } } else { allowedButtons = gantt2.config.quickinfo_buttons; } this.setContent({ header: { title: gantt2.templates.quick_info_title(ev.start_date, ev.end_date, ev), date: gantt2.templates.quick_info_date(ev.start_date, ev.end_date, ev) }, content: gantt2.templates.quick_info_content(ev.start_date, ev.end_date, ev), buttons: allowedButtons }); } _appendAtCoordinates(x, y) { const qi = this._quickInfoBox; const container = this._getContainer(); if (!qi.parentNode || qi.parentNode.nodeName.toLowerCase() === "#document-fragment") { container.parent.appendChild(qi); } qi.style.left = x + "px"; qi.style.top = y + "px"; } _show_quick_info(pos, offset) { const gantt2 = this._gantt; const qi = this._quickInfoBox; if (gantt2.config.quick_info_detached) { const container = this._getContainer(); if (!qi.parentNode || qi.parentNode.nodeName.toLowerCase() === "#document-fragment") { container.parent.appendChild(qi); } const width = qi.offsetWidth; const popupHeight = qi.offsetHeight; const scrolls = gantt2.getScrollState(); const xViewport = container.xViewport; const yViewport = container.yViewport; const screenWidth = xViewport.offsetWidth + scrolls.x - width; const relativePopupTop = pos.top - scrolls.y; const relativePopupBottom = relativePopupTop + popupHeight; let top = pos.top; if (relativePopupBottom > yViewport.offsetHeight / 2) { top = pos.top - (popupHeight + pos.height + 2 * offset); if (top < scrolls.y && relativePopupBottom <= yViewport.offsetHeight) { top = pos.top; } } if (top < scrolls.y) { top = scrolls.y; } const x = Math.min(Math.max(scrolls.x, pos.left - pos.dx * (width - pos.width)), screenWidth); const y = top; this._appendAtCoordinates(x, y); } else { qi.style.top = "20px"; if (pos.dx === 1) { qi.style.right = "auto"; qi.style.left = "-300px"; setTimeout(() => { qi.style.left = "10px"; }, 1); } else { qi.style.left = "auto"; qi.style.right = "-300px"; setTimeout(() => { qi.style.right = "10px"; }, 1); } qi.className += " gantt_qi_" + (pos.dx === 1 ? "left" : "right"); gantt2.$root.appendChild(qi); } } _qi_button_click(node) { const gantt2 = this._gantt; const box = this._quickInfoBox; if (!node || node === box) { return; } if (node.closest(".gantt_cal_qi_close_btn")) { this.hide(); return; } const mask = node.className; if (mask.indexOf("_icon") !== -1) { const id = this._quickInfoBoxId; gantt2.$click.buttons[mask.split(" ")[1].replace("icon_", "")](id); } else { this._qi_button_click(node.parentNode); } } _getContainer() { const gantt2 = this._gantt; let container = this._container ? this._container : gantt2.$task_data; if (container && container.offsetHeight && container.offsetWidth) { return { parent: container, xViewport: gantt2.$task, yViewport: gantt2.$task_data }; } container = this._container ? this._container : gantt2.$grid_data; if (container && container.offsetHeight && container.offsetWidth) { return { parent: container, xViewport: gantt2.$grid, yViewport: gantt2.$grid_data }; } return { parent: this._container ? this._container : gantt2.$layout, xViewport: gantt2.$layout, yViewport: gantt2.$layout }; } } function quick_info(gantt2) { if (!gantt2.ext) { gantt2.ext = {}; } gantt2.ext.quickInfo = new QuickInfo(gantt2); gantt2.config.quickinfo_buttons = ["icon_edit", "icon_delete"]; gantt2.config.quick_info_detached = true; gantt2.config.show_quick_info = true; gantt2.templates.quick_info_title = function(start, end, ev) { return ev.text.substr(0, 50); }; gantt2.templates.quick_info_content = function(start, end, ev) { return ev.details || ev.text; }; gantt2.templates.quick_info_date = function(start, end, ev) { return gantt2.templates.task_time(start, end, ev); }; gantt2.templates.quick_info_class = function(start, end, task) { return ""; }; gantt2.attachEvent("onTaskClick", function(id, e) { const addButton = gantt2.utils.dom.closest(e.target, ".gantt_add"); const collapseButton = gantt2.utils.dom.closest(e.target, ".gantt_close"); const expandButton = gantt2.utils.dom.closest(e.target, ".gantt_open"); const showQuickInfo = !addButton && !collapseButton && !expandButton; if (showQuickInfo) { setTimeout(function() { gantt2.ext.quickInfo.show(id); }, 0); } return true; }); const events = ["onViewChange", "onLightbox", "onBeforeTaskDelete", "onBeforeDrag"]; const hidingFunction = function() { gantt2.ext.quickInfo.hide(); return true; }; for (let i = 0; i < events.length; i++) { gantt2.attachEvent(events[i], hidingFunction); } gantt2.attachEvent("onEmptyClick", function(e) { let hideQuickInfo = true; const parent = document.querySelector(".gantt_cal_quick_info"); if (parent) { const quickInfoClick = gantt2.utils.dom.isChildOf(e.target, parent); if (quickInfoClick) { hideQuickInfo = false; } } if (hideQuickInfo) { hidingFunction(); } }); function clearQuickInfo() { gantt2.ext.quickInfo.hide(); gantt2.ext.quickInfo._quickInfoBox = null; return true; } gantt2.attachEvent("onGanttReady", clearQuickInfo); gantt2.attachEvent("onDestroy", clearQuickInfo); gantt2.event(window, "keydown", function(e) { if (e.keyCode === 27) { gantt2.ext.quickInfo.hide(); } }); gantt2.showQuickInfo = function() { gantt2.ext.quickInfo.show.apply(gantt2.ext.quickInfo, arguments); }; gantt2.hideQuickInfo = function() { gantt2.ext.quickInfo.hide.apply(gantt2.ext.quickInfo, arguments); }; } function createScope(addEvent, removeEvent) { addEvent = addEvent || event; removeEvent = removeEvent || eventRemove; var handlers = []; var eventScope = { attach: function(el, event2, callback, capture) { handlers.push({ element: el, event: event2, callback, capture }); addEvent(el, event2, callback, capture); }, detach: function(el, event2, callback, capture) { removeEvent(el, event2, callback, capture); for (var i = 0; i < handlers.length; i++) { var handler = handlers[i]; if (handler.element === el && handler.event === event2 && handler.callback === callback && handler.capture === capture) { handlers.splice(i, 1); i--; } } }, detachAll: function() { var staticArray = handlers.slice(); for (var i = 0; i < staticArray.length; i++) { var handler = staticArray[i]; eventScope.detach(handler.element, handler.event, handler.callback, handler.capture); eventScope.detach(handler.element, handler.event, handler.callback, void 0); eventScope.detach(handler.element, handler.event, handler.callback, false); eventScope.detach(handler.element, handler.event, handler.callback, true); } handlers.splice(0, handlers.length); }, extend: function() { return createScope(this.event, this.eventRemove); } }; return eventScope; } class Tooltip { constructor(gantt2) { this._gantt = gantt2; } getNode() { const gantt2 = this._gantt; if (!this._tooltipNode) { this._tooltipNode = document.createElement("div"); this._tooltipNode.className = "gantt_tooltip"; gantt2._waiAria.tooltipAttr(this._tooltipNode); } return this._tooltipNode; } setViewport(node) { this._root = node; return this; } show(left, top) { const gantt2 = this._gantt; const container = document.body; const node = this.getNode(); if (!isChildOf(node, container)) { this.hide(); node.style.top = node.style.top || "0px"; node.style.left = node.style.left || "0px"; container.appendChild(node); } if (this._isLikeMouseEvent(left)) { const position = this._calculateTooltipPosition(left); top = position.top; left = position.left; } node.style.top = top + "px"; node.style.left = left + "px"; gantt2._waiAria.tooltipVisibleAttr(node); return this; } hide() { const gantt2 = this._gantt; const node = this.getNode(); if (node && node.parentNode) { node.parentNode.removeChild(node); } gantt2._waiAria.tooltipHiddenAttr(node); return this; } setContent(html) { const node = this.getNode(); node.innerHTML = html; return this; } _isLikeMouseEvent(event2) { if (!event2 || typeof event2 !== "object") { return false; } return "clientX" in event2 && "clientY" in event2; } _getViewPort() { return this._root || document.body; } _calculateTooltipPosition(event2) { const gantt2 = this._gantt; const viewport = this._getViewPortSize(); const tooltipNode = this.getNode(); const tooltip2 = { top: 0, left: 0, width: tooltipNode.offsetWidth, height: tooltipNode.offsetHeight, bottom: 0, right: 0 }; const offsetX = gantt2.config.tooltip_offset_x; const offsetY = gantt2.config.tooltip_offset_y; const container = document.body; const mouse = getRelativeEventPosition(event2, container); const containerPos = getNodePosition(container); mouse.y += containerPos.y; tooltip2.top = mouse.y; tooltip2.left = mouse.x; tooltip2.top += offsetY; tooltip2.left += offsetX; tooltip2.bottom = tooltip2.top + tooltip2.height; tooltip2.right = tooltip2.left + tooltip2.width; const scrollTop = window.scrollY + container.scrollTop; if (tooltip2.top < viewport.top - scrollTop) { tooltip2.top = viewport.top; tooltip2.bottom = tooltip2.top + tooltip2.height; } else if (tooltip2.bottom > viewport.bottom) { tooltip2.bottom = viewport.bottom; tooltip2.top = tooltip2.bottom - tooltip2.height; } if (tooltip2.left < viewport.left) { tooltip2.left = viewport.left; tooltip2.right = viewport.left + tooltip2.width; } else if (tooltip2.right > viewport.right) { tooltip2.right = viewport.right; tooltip2.left = tooltip2.right - tooltip2.width; } if (mouse.x >= tooltip2.left && mouse.x <= tooltip2.right) { tooltip2.left = mouse.x - tooltip2.width - offsetX; tooltip2.right = tooltip2.left + tooltip2.width; } if (mouse.y >= tooltip2.top && mouse.y <= tooltip2.bottom) { tooltip2.top = mouse.y - tooltip2.height - offsetY; tooltip2.bottom = tooltip2.top + tooltip2.height; } if (tooltip2.left < 0) { tooltip2.left = 0; } if (tooltip2.right < 0) { tooltip2.right = 0; } return tooltip2; } _getViewPortSize() { const gantt2 = this._gantt; const container = this._getViewPort(); let viewport = container; let scrollTop = window.scrollY + document.body.scrollTop; let scrollLeft = window.scrollX + document.body.scrollLeft; let pos; if (container === gantt2.$task_data) { viewport = gantt2.$task; scrollTop = 0; scrollLeft = 0; pos = getNodePosition(gantt2.$task); } else { pos = getNodePosition(viewport); } return { left: pos.x + scrollLeft, top: pos.y + scrollTop, width: pos.width, height: pos.height, bottom: pos.y + pos.height + scrollTop, right: pos.x + pos.width + scrollLeft }; } } class TooltipManager { constructor(gantt2) { this._listeners = {}; this.tooltip = new Tooltip(gantt2); this._gantt = gantt2; this._domEvents = createScope(); this._initDelayedFunctions(); } destructor() { this.tooltip.hide(); this._domEvents.detachAll(); } hideTooltip() { this.delayHide(); } attach(config2) { let root = document.body; const gantt2 = this._gantt; if (!config2.global) { root = gantt2.$root; } let watchableTarget = null; const handler = (event2) => { const eventTarget = getTargetNode(event2); const targetNode = closest(eventTarget, config2.selector); if (isChildOf(eventTarget, this.tooltip.getNode())) { return; } const doOnMouseEnter = () => { watchableTarget = targetNode; config2.onmouseenter(event2, targetNode); }; if (watchableTarget) { if (targetNode && targetNode === watchableTarget) { config2.onmousemove(event2, targetNode); } else { config2.onmouseleave(event2, watchableTarget); watchableTarget = null; if (targetNode && targetNode !== watchableTarget) { doOnMouseEnter(); } } } else { if (targetNode) { doOnMouseEnter(); } } }; this.detach(config2.selector); this._domEvents.attach(root, "mousemove", handler); this._listeners[config2.selector] = { node: root, handler }; } detach(selector) { const listener = this._listeners[selector]; if (listener) { this._domEvents.detach(listener.node, "mousemove", listener.handler); } } tooltipFor(config2) { const cloneDomEvent = (event2) => { let clone = event2; if (document["createEventObject"] && !document.createEvent) { clone = document["createEventObject"](event2); } return clone; }; this._initDelayedFunctions(); this.attach({ selector: config2.selector, global: config2.global, onmouseenter: (event2, node) => { const html = config2.html(event2, node); if (html) { this.delayShow(cloneDomEvent(event2), html); } }, onmousemove: (event2, node) => { const html = config2.html(event2, node); if (html) { this.delayShow(cloneDomEvent(event2), html); } else { this.delayShow.$cancelTimeout(); this.delayHide(); } }, onmouseleave: () => { this.delayShow.$cancelTimeout(); this.delayHide(); } }); } _initDelayedFunctions() { const gantt2 = this._gantt; if (this.delayShow) { this.delayShow.$cancelTimeout(); } if (this.delayHide) { this.delayHide.$cancelTimeout(); } this.tooltip.hide(); this.delayShow = delay((event2, html) => { if (gantt2.callEvent("onBeforeTooltip", [event2]) === false) { this.tooltip.hide(); } else { this.tooltip.setContent(html); this.tooltip.show(event2); } }, gantt2.config.tooltip_timeout || 1); this.delayHide = delay(() => { this.delayShow.$cancelTimeout(); this.tooltip.hide(); }, gantt2.config.tooltip_hide_timeout || 1); } } function tooltip(gantt2) { gantt2.config.tooltip_timeout = 30; gantt2.config.tooltip_offset_y = 20; gantt2.config.tooltip_offset_x = 10; gantt2.config.tooltip_hide_timeout = 30; const tooltipManager = new TooltipManager(gantt2); gantt2.ext.tooltips = tooltipManager; gantt2.attachEvent("onGanttReady", function() { if (!gantt2.$root) return; tooltipManager.tooltipFor({ selector: "[" + gantt2.config.task_attribute + "]:not(.gantt_task_row)", html: (event2) => { if (gantt2.config.touch && !gantt2.config.touch_tooltip) { return; } const targetTaskId = gantt2.locate(event2); if (gantt2.isTaskExists(targetTaskId)) { const task = gantt2.getTask(targetTaskId); return gantt2.templates.tooltip_text(task.start_date, task.end_date, task); } return null; }, global: false }); }); gantt2.attachEvent("onDestroy", function() { tooltipManager.destructor(); }); gantt2.attachEvent("onLightbox", function() { tooltipManager.hideTooltip(); }); const isLinkCreate = () => { const state = gantt2.getState(); return !!state.link_source_id; }; gantt2.attachEvent("onBeforeTooltip", function() { if (isLinkCreate()) { return false; } }); gantt2.attachEvent("onGanttScroll", function() { tooltipManager.hideTooltip(); }); } const noTrack = { onBeforeUndo: "onAfterUndo", onBeforeRedo: "onAfterRedo" }; const batchActions = ["onTaskDragStart", "onAfterTaskUpdate", "onAfterParentExpand", "onAfterTaskDelete", "onBeforeBatchUpdate"]; class Monitor { constructor(undo2, gantt2) { this._batchAction = null; this._batchMode = false; this._ignore = false; this._ignoreMoveEvents = false; this._initialTasks = {}; this._initialLinks = {}; this._nestedTasks = {}; this._nestedLinks = {}; this._undo = undo2; this._gantt = gantt2; this._attachEvents(); } store(id, type, overwrite = false) { if (type === this._gantt.config.undo_types.task) { return this._storeTask(id, overwrite); } if (type === this._gantt.config.undo_types.link) { return this._storeLink(id, overwrite); } return false; } isMoveEventsIgnored() { return this._ignoreMoveEvents; } toggleIgnoreMoveEvents(newValue) { this._ignoreMoveEvents = newValue || false; } startIgnore() { this._ignore = true; } stopIgnore() { this._ignore = false; } startBatchAction() { if (!this._timeout) { this._timeout = setTimeout(() => { this.stopBatchAction(); this._timeout = null; }, 10); } if (this._ignore || this._batchMode) { return; } this._batchMode = true; this._batchAction = this._undo.action.create(); } stopBatchAction() { if (this._ignore) { return; } const undo2 = this._undo; if (this._batchAction) { undo2.logAction(this._batchAction); } this._batchMode = false; this._batchAction = null; } onTaskAdded(task) { if (!this._ignore) { this._storeTaskCommand(task, this._undo.command.type.add); } } onTaskUpdated(task) { if (!this._ignore) { this._storeTaskCommand(task, this._undo.command.type.update); } } onTaskMoved(task) { if (!this._ignore) { task.$local_index = this._gantt.getTaskIndex(task.id); this._storeEntityCommand(task, this.getInitialTask(task.id), this._undo.command.type.move, this._undo.command.entity.task); } } onTaskDeleted(task) { if (!this._ignore) { this._storeTaskCommand(task, this._undo.command.type.remove); if (this._nestedTasks[task.id]) { const children = this._nestedTasks[task.id]; for (let i = 0; i < children.length; i++) { this._storeTaskCommand(children[i], this._undo.command.type.remove); } } if (this._nestedLinks[task.id]) { const childrenLinks = this._nestedLinks[task.id]; for (let i = 0; i < childrenLinks.length; i++) { this._storeLinkCommand(childrenLinks[i], this._undo.command.type.remove); } } } } onLinkAdded(link) { if (!this._ignore) { this._storeLinkCommand(link, this._undo.command.type.add); } } onLinkUpdated(link) { if (!this._ignore) { this._storeLinkCommand(link, this._undo.command.type.update); } } onLinkDeleted(link) { if (!this._ignore) { this._storeLinkCommand(link, this._undo.command.type.remove); } } setNestedTasks(id, taskIds) { const gantt2 = this._gantt; let task = null; const tasks2 = []; let linkIds = this._getLinks(gantt2.getTask(id)); for (let i = 0; i < taskIds.length; i++) { task = this.setInitialTask(taskIds[i]); linkIds = linkIds.concat(this._getLinks(task)); tasks2.push(task); } const uniqueLinks = {}; for (let i = 0; i < linkIds.length; i++) { uniqueLinks[linkIds[i]] = true; } const links = []; for (const i in uniqueLinks) { links.push(this.setInitialLink(i)); } this._nestedTasks[id] = tasks2; this._nestedLinks[id] = links; } setInitialTask(id, overwrite) { const gantt2 = this._gantt; if (overwrite || (!this._initialTasks[id] || !this._batchMode)) { const task = gantt2.copy(gantt2.getTask(id)); task.$index = gantt2.getGlobalTaskIndex(id); task.$local_index = gantt2.getTaskIndex(id); this.setInitialTaskObject(id, task); } return this._initialTasks[id]; } getInitialTask(id) { return this._initialTasks[id]; } clearInitialTasks() { this._initialTasks = {}; } setInitialTaskObject(id, object) { this._initialTasks[id] = object; } setInitialLink(id, overwrite) { if (!this._initialLinks[id] || !this._batchMode) { this._initialLinks[id] = this._gantt.copy(this._gantt.getLink(id)); } return this._initialLinks[id]; } getInitialLink(id) { return this._initialLinks[id]; } clearInitialLinks() { this._initialLinks = {}; } _attachEvents() { let deleteCacheCooldown = null; const gantt2 = this._gantt; const saveInitialAll = () => { if (!deleteCacheCooldown) { deleteCacheCooldown = setTimeout(() => { deleteCacheCooldown = null; }); this.clearInitialTasks(); gantt2.eachTask((task) => { this.setInitialTask(task.id); }); this.clearInitialLinks(); gantt2.getLinks().forEach((link) => { this.setInitialLink(link.id); }); } }; const getMoveObjectByTaskId = (id) => gantt2.copy(gantt2.getTask(id)); for (const i in noTrack) { gantt2.attachEvent(i, () => { this.startIgnore(); return true; }); gantt2.attachEvent(noTrack[i], () => { this.stopIgnore(); return true; }); } for (let i = 0; i < batchActions.length; i++) { gantt2.attachEvent(batchActions[i], () => { this.startBatchAction(); return true; }); } gantt2.attachEvent("onParse", () => { this._undo.clearUndoStack(); this._undo.clearRedoStack(); saveInitialAll(); }); gantt2.attachEvent("onAfterTaskAdd", (id, task) => { this.setInitialTask(id, true); this.onTaskAdded(task); }); gantt2.attachEvent("onAfterTaskUpdate", (id, task) => { this.onTaskUpdated(task); }); gantt2.attachEvent("onAfterParentExpand", (id, task) => { this.onTaskUpdated(task); }); gantt2.attachEvent("onAfterTaskDelete", (id, task) => { this.onTaskDeleted(task); }); gantt2.attachEvent("onAfterLinkAdd", (id, link) => { this.setInitialLink(id, true); this.onLinkAdded(link); }); gantt2.attachEvent("onAfterLinkUpdate", (id, link) => { this.onLinkUpdated(link); }); gantt2.attachEvent("onAfterLinkDelete", (id, link) => { this.onLinkDeleted(link); }); gantt2.attachEvent("onRowDragEnd", (id, target) => { this.onTaskMoved(getMoveObjectByTaskId(id)); this.toggleIgnoreMoveEvents(); return true; }); gantt2.attachEvent("onBeforeTaskDelete", (id) => { this.store(id, gantt2.config.undo_types.task); const nested = []; saveInitialAll(); gantt2.eachTask((task) => { nested.push(task.id); }, id); this.setNestedTasks(id, nested); return true; }); const datastore = gantt2.getDatastore("task"); datastore.attachEvent("onBeforeItemMove", (id, parent, tindex) => { if (!this.isMoveEventsIgnored()) { saveInitialAll(); } return true; }); datastore.attachEvent("onAfterItemMove", (id, parent, tindex) => { if (!this.isMoveEventsIgnored()) { this.onTaskMoved(getMoveObjectByTaskId(id)); } return true; }); gantt2.attachEvent("onRowDragStart", (id, target, e) => { this.toggleIgnoreMoveEvents(true); saveInitialAll(); return true; }); let dragId = null; let projectDrag = false; gantt2.attachEvent("onBeforeTaskDrag", (taskId) => { dragId = gantt2.getState().drag_id; if (dragId === taskId) { const task = gantt2.getTask(taskId); if (gantt2.isSummaryTask(task) && gantt2.config.drag_project) { projectDrag = true; } } if (gantt2.plugins().multiselect) { const selectedIds = gantt2.getSelectedTasks(); if (selectedIds.length > 1) { selectedIds.forEach((id) => { this.store(id, gantt2.config.undo_types.task, true); }); } } return this.store(taskId, gantt2.config.undo_types.task); }); gantt2.attachEvent("onAfterTaskDrag", (taskId) => { const multipleDrag = projectDrag || gantt2.plugins().multiselect && gantt2.getSelectedTasks().length > 1; if (multipleDrag && dragId === taskId) { projectDrag = false; dragId = null; this.stopBatchAction(); } this.store(taskId, gantt2.config.undo_types.task, true); }); gantt2.attachEvent("onLightbox", (taskId) => this.store(taskId, gantt2.config.undo_types.task)); gantt2.attachEvent("onBeforeTaskAutoSchedule", (task) => { this.store(task.id, gantt2.config.undo_types.task, true); return true; }); if (gantt2.ext.inlineEditors) { let onBeforeEditStartId = null; let onEditStart = null; gantt2.attachEvent("onGanttLayoutReady", () => { if (onBeforeEditStartId) { gantt2.ext.inlineEditors.detachEvent(onBeforeEditStartId); } if (onEditStart) { gantt2.ext.inlineEditors.detachEvent(onEditStart); } onEditStart = gantt2.ext.inlineEditors.attachEvent("onEditStart", (state) => { if (gantt2.$data.tempAssignmentsStore && gantt2._lightbox_id) { return; } this.store(state.id, gantt2.config.undo_types.task); }); onBeforeEditStartId = gantt2.ext.inlineEditors.attachEvent("onBeforeEditStart", (state) => { this.stopBatchAction(); return true; }); }); } } _storeCommand(command) { const undo2 = this._undo; undo2.updateConfigs(); if (!undo2.undoEnabled) { return; } if (this._batchMode) { this._batchAction.commands.push(command); } else { const action = undo2.action.create([command]); undo2.logAction(action); } } _storeEntityCommand(obj, old, actionType, entityType) { const undo2 = this._undo; const command = undo2.command.create(obj, old, actionType, entityType); this._storeCommand(command); } _storeTaskCommand(obj, type) { if (this._gantt.isTaskExists(obj.id)) { obj.$local_index = this._gantt.getTaskIndex(obj.id); } this._storeEntityCommand(obj, this.getInitialTask(obj.id), type, this._undo.command.entity.task); } _storeLinkCommand(obj, type) { this._storeEntityCommand(obj, this.getInitialLink(obj.id), type, this._undo.command.entity.link); } _getLinks(task) { return task.$source.concat(task.$target); } _storeTask(taskId, overwrite = false) { const gantt2 = this._gantt; this.setInitialTask(taskId, overwrite); gantt2.eachTask((child) => { this.setInitialTask(child.id); }, taskId); return true; } _storeLink(linkId, overwrite = false) { this.setInitialLink(linkId, overwrite); return true; } } const MAX_UNDO_STEPS = 100; class Undo { constructor(gantt2) { this.maxSteps = MAX_UNDO_STEPS; this.undoEnabled = true; this.redoEnabled = true; this.action = { create: (commands) => ({ commands: commands ? commands.slice() : [] }), invert: (action) => { const gantt3 = this._gantt; const revert = gantt3.copy(action); const commands = this.command; for (let i = 0; i < action.commands.length; i++) { const command = revert.commands[i] = commands.invert(revert.commands[i]); if (command.type === commands.type.update || command.type === commands.type.move) { [command.value, command.oldValue] = [command.oldValue, command.value]; } } return revert; } }; this.command = { entity: null, type: null, create: (value, oldValue, type, entity) => { const gantt3 = this._gantt; return { entity, type, value: gantt3.copy(value), oldValue: gantt3.copy(oldValue || value) }; }, invert: (command) => { const gantt3 = this._gantt; const revert = gantt3.copy(command); revert.type = this.command.inverseCommands(command.type); return revert; }, inverseCommands: (command) => { const gantt3 = this._gantt; const types = this.command.type; switch (command) { case types.update: return types.update; case types.remove: return types.add; case types.add: return types.remove; case types.move: return types.move; default: gantt3.assert(false, "Invalid command " + command); return null; } } }; this._undoStack = []; this._redoStack = []; this._gantt = gantt2; } getUndoStack() { return this._undoStack; } setUndoStack(stack) { this._undoStack = stack; } getRedoStack() { return this._redoStack; } setRedoStack(stack) { this._redoStack = stack; } clearUndoStack() { this._undoStack = []; } clearRedoStack() { this._redoStack = []; } updateConfigs() { const gantt2 = this._gantt; this.maxSteps = gantt2.config.undo_steps || MAX_UNDO_STEPS; this.command.entity = gantt2.config.undo_types; this.command.type = gantt2.config.undo_actions; this.undoEnabled = !!gantt2.config.undo; this.redoEnabled = !!gantt2.config.redo; } undo() { const gantt2 = this._gantt; this.updateConfigs(); if (!this.undoEnabled) { return; } const action = this._pop(this._undoStack); if (action) { this._reorderCommands(action); } if (gantt2.callEvent("onBeforeUndo", [action]) !== false) { if (action) { this._applyAction(this.action.invert(action)); this._push(this._redoStack, gantt2.copy(action)); gantt2.callEvent("onAfterUndo", [action]); return; } } gantt2.callEvent("onAfterUndo", [null]); } redo() { const gantt2 = this._gantt; this.updateConfigs(); if (!this.redoEnabled) { return; } const action = this._pop(this._redoStack); if (action) { this._reorderCommands(action); } if (gantt2.callEvent("onBeforeRedo", [action]) !== false) { if (action) { this._applyAction(action); this._push(this._undoStack, gantt2.copy(action)); gantt2.callEvent("onAfterRedo", [action]); return; } } gantt2.callEvent("onAfterRedo", [null]); } logAction(action) { this._push(this._undoStack, action); this._redoStack = []; } _push(stack, action) { const gantt2 = this._gantt; if (!action.commands.length) { return; } const event2 = stack === this._undoStack ? "onBeforeUndoStack" : "onBeforeRedoStack"; if (gantt2.callEvent(event2, [action]) === false) { return; } if (!action.commands.length) { return; } stack.push(action); while (stack.length > this.maxSteps) { stack.shift(); } return action; } _pop(stack) { return stack.pop(); } _reorderCommands(action) { const weights = { any: 0, link: 1, task: 2 }; const actionWeights = { move: 1, any: 0 }; action.commands.sort(function(a, b) { if (a.entity === "task" && b.entity === "task") { if (a.type !== b.type) { return (actionWeights[b.type] || 0) - (actionWeights[a.type] || 0); } else if (a.type === "move" && a.oldValue && b.oldValue && b.oldValue.parent === a.oldValue.parent) { return a.oldValue.$index - b.oldValue.$index; } else { return 0; } } else { const weightA = weights[a.entity] || weights.any; const weightB = weights[b.entity] || weights.any; return weightB - weightA; } }); } _applyAction(action) { let command = null; const entities = this.command.entity; const actions = this.command.type; const gantt2 = this._gantt; const methods = {}; methods[entities.task] = { add: "addTask", get: "getTask", update: "updateTask", remove: "deleteTask", move: "moveTask", isExists: "isTaskExists" }; methods[entities.link] = { add: "addLink", get: "getLink", update: "updateLink", remove: "deleteLink", isExists: "isLinkExists" }; gantt2.batchUpdate(function() { for (let i = 0; i < action.commands.length; i++) { command = action.commands[i]; const method = methods[command.entity][command.type]; const getMethod = methods[command.entity].get; const check = methods[command.entity].isExists; if (command.type === actions.add) { gantt2[method](command.oldValue, command.oldValue.parent, command.oldValue.$local_index); } else if (command.type === actions.remove) { if (gantt2[check](command.value.id)) { gantt2[method](command.value.id); } } else if (command.type === actions.update) { const item = gantt2[getMethod](command.value.id); for (const prop in command.value) { const internalProperty = prop.startsWith("$") || prop.startsWith("_"); const whitelist = ["$open"]; let copyProperty = !internalProperty; if (whitelist.indexOf(prop) > -1) { copyProperty = true; } if (copyProperty) { item[prop] = command.value[prop]; } } gantt2[method](command.value.id); } else if (command.type === actions.move) { gantt2[method](command.value.id, command.value.$local_index, command.value.parent); gantt2.callEvent("onRowDragEnd", [command.value.id]); } } }); } } function undo(gantt2) { const _undo = new Undo(gantt2); const monitor = new Monitor(_undo, gantt2); gantt2.config.undo = true; gantt2.config.redo = true; gantt2.config.undo_types = { link: "link", task: "task" }; gantt2.config.undo_actions = { update: "update", remove: "remove", add: "add", move: "move" }; if (!gantt2.ext) { gantt2.ext = {}; } gantt2.ext.undo = { undo: () => _undo.undo(), redo: () => _undo.redo(), getUndoStack: () => _undo.getUndoStack(), setUndoStack: (stack) => _undo.setUndoStack(stack), getRedoStack: () => _undo.getRedoStack(), setRedoStack: (stack) => _undo.setRedoStack(stack), clearUndoStack: () => _undo.clearUndoStack(), clearRedoStack: () => _undo.clearRedoStack(), saveState: (id, type) => monitor.store(id, type, true), getInitialState: (id, type) => { if (type === gantt2.config.undo_types.link) { return monitor.getInitialLink(id); } else { return monitor.getInitialTask(id); } } }; gantt2.undo = gantt2.ext.undo.undo; gantt2.redo = gantt2.ext.undo.redo; gantt2.getUndoStack = gantt2.ext.undo.getUndoStack; gantt2.getRedoStack = gantt2.ext.undo.getRedoStack; gantt2.clearUndoStack = gantt2.ext.undo.clearUndoStack; gantt2.clearRedoStack = gantt2.ext.undo.clearRedoStack; function isEqualIds2(first, second) { return String(first) === String(second); } function updTask(task, oldId, newId) { if (!task) { return; } if (isEqualIds2(task.id, oldId)) { task.id = newId; } if (isEqualIds2(task.parent, oldId)) { task.parent = newId; } } function changeTaskCommandId(command, oldId, newId) { updTask(command.value, oldId, newId); updTask(command.oldValue, oldId, newId); } function updLink(link, oldTaskId, newTaskId) { if (!link) { return; } if (isEqualIds2(link.source, oldTaskId)) { link.source = newTaskId; } if (isEqualIds2(link.target, oldTaskId)) { link.target = newTaskId; } } function changeLinkCommandId(command, oldId, newId) { updLink(command.value, oldId, newId); updLink(command.oldValue, oldId, newId); } function updateTasksIds(log, oldId, newId) { const undo2 = _undo; for (let i = 0; i < log.length; i++) { const entry = log[i]; for (let j = 0; j < entry.commands.length; j++) { if (entry.commands[j].entity === undo2.command.entity.task) { changeTaskCommandId(entry.commands[j], oldId, newId); } else if (entry.commands[j].entity === undo2.command.entity.link) { changeLinkCommandId(entry.commands[j], oldId, newId); } } } } function updateLinksIds(log, oldId, newId) { const undo2 = _undo; for (let i = 0; i < log.length; i++) { const entry = log[i]; for (let j = 0; j < entry.commands.length; j++) { const command = entry.commands[j]; if (command.entity === undo2.command.entity.link) { if (command.value && command.value.id === oldId) { command.value.id = newId; } if (command.oldValue && command.oldValue.id === oldId) { command.oldValue.id = newId; } } } } } gantt2.attachEvent("onTaskIdChange", (oldId, newId) => { const undo2 = _undo; updateTasksIds(undo2.getUndoStack(), oldId, newId); updateTasksIds(undo2.getRedoStack(), oldId, newId); }); gantt2.attachEvent("onLinkIdChange", (oldId, newId) => { const undo2 = _undo; updateLinksIds(undo2.getUndoStack(), oldId, newId); updateLinksIds(undo2.getRedoStack(), oldId, newId); }); gantt2.attachEvent("onGanttReady", () => { _undo.updateConfigs(); }); } const extensions = { click_drag, drag_timeline, fullscreen, keyboard_navigation, quick_info, tooltip, undo, marker, multiselect, export_api }; const constants = { KEY_CODES: { UP: 38, DOWN: 40, LEFT: 37, RIGHT: 39, SPACE: 32, ENTER: 13, DELETE: 46, ESC: 27, TAB: 9 } }; class ExtensionsManager { constructor(config2) { this.addExtension = (name, ext) => { this._extensions[name] = ext; }; this.getExtension = (name) => this._extensions[name]; this._extensions = {}; for (const i in config2) { this._extensions[i] = config2[i]; } } } function services() { var services2 = {}; function register(name, getter) { services2[name] = getter; } function getService(name) { if (!services2[name]) { return null; } return services2[name](); } function dropService(name) { if (services2[name]) { delete services2[name]; } } var servicesEnum = {}; return { services: servicesEnum, setService: register, getService, dropService, destructor: function() { for (var i in services2) { if (services2[i]) { var service = services2[i]; if (service && service.destructor) { service.destructor(); } } } services2 = null; } }; } const config = () => { const result = { layout: { css: "gantt_container", rows: [{ cols: [{ view: "grid", scrollX: "scrollHor", scrollY: "scrollVer" }, { resizer: true, width: 1 }, { view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer" }, { view: "scrollbar", id: "scrollVer" }] }, { view: "scrollbar", id: "scrollHor", height: 20 }] }, links: { finish_to_start: "0", start_to_start: "1", finish_to_finish: "2", start_to_finish: "3" }, types: { task: "task", project: "project", milestone: "milestone" }, auto_types: false, duration_unit: "day", work_time: false, correct_work_time: false, skip_off_time: false, cascade_delete: true, autosize: false, autosize_min_width: 0, autoscroll: true, autoscroll_speed: 30, deepcopy_on_parse: false, show_links: true, show_task_cells: true, static_background: false, static_background_cells: true, branch_loading: false, branch_loading_property: "$has_child", show_loading: false, show_chart: true, show_grid: true, min_duration: 60 * 60 * 1e3, date_format: "%d-%m-%Y %H:%i", xml_date: void 0, start_on_monday: true, server_utc: false, show_progress: true, fit_tasks: false, select_task: true, scroll_on_click: true, smart_rendering: true, preserve_scroll: true, readonly: false, container_resize_timeout: 20, deadlines: true, date_grid: "%Y-%m-%d", drag_links: true, drag_progress: true, drag_resize: true, drag_project: false, drag_move: true, drag_mode: { resize: "resize", progress: "progress", move: "move", ignore: "ignore" }, round_dnd_dates: true, link_wrapper_width: 20, link_arrow_size: 12, root_id: 0, autofit: false, columns: [{ name: "text", tree: true, width: "*", resize: true }, { name: "start_date", align: "center", resize: true }, { name: "duration", align: "center" }, { name: "add", width: 44 }], scale_offset_minimal: true, inherit_scale_class: false, scales: [{ unit: "day", step: 1, date: "%d %M" }], time_step: 60, duration_step: 1, task_date: "%d %F %Y", time_picker: "%H:%i", task_attribute: "data-task-id", link_attribute: "data-link-id", layer_attribute: "data-layer", buttons_left: ["gantt_save_btn", "gantt_cancel_btn"], _migrate_buttons: { dhx_save_btn: "gantt_save_btn", dhx_cancel_btn: "gantt_cancel_btn", dhx_delete_btn: "gantt_delete_btn" }, buttons_right: ["gantt_delete_btn"], lightbox: { sections: [{ name: "description", height: 70, map_to: "text", type: "textarea", focus: true }, { name: "time", type: "duration", map_to: "auto" }], project_sections: [{ name: "description", height: 70, map_to: "text", type: "textarea", focus: true }, { name: "type", type: "typeselect", map_to: "type" }, { name: "time", type: "duration", readonly: true, map_to: "auto" }], milestone_sections: [{ name: "description", height: 70, map_to: "text", type: "textarea", focus: true }, { name: "type", type: "typeselect", map_to: "type" }, { name: "time", type: "duration", single_date: true, map_to: "auto" }] }, drag_lightbox: true, sort: false, details_on_create: true, details_on_dblclick: true, initial_scroll: true, task_scroll_offset: 100, order_branch: false, order_branch_free: false, task_height: void 0, bar_height: "full", bar_height_padding: 9, min_column_width: 70, min_grid_column_width: 70, grid_resizer_column_attribute: "data-column-index", keep_grid_width: false, grid_resize: false, grid_elastic_columns: false, show_tasks_outside_timescale: false, show_unscheduled: true, resize_rows: false, task_grid_row_resizer_attribute: "data-row-index", min_task_grid_row_height: 30, row_height: 36, readonly_property: "readonly", editable_property: "editable", calendar_property: "calendar_id", resource_calendars: {}, dynamic_resource_calendars: false, inherit_calendar: false, type_renderers: {}, open_tree_initially: false, optimize_render: true, prevent_default_scroll: false, show_errors: true, wai_aria_attributes: true, smart_scales: true, rtl: false, placeholder_task: false, horizontal_scroll_key: "shiftKey", drag_timeline: { useKey: void 0, ignore: ".gantt_task_line, .gantt_task_link", render: false }, drag_multiple: true, csp: "auto", auto_scheduling: {} }; return result; }; var isWindowAwailable = typeof window !== "undefined"; const nav = typeof navigator !== "undefined" ? navigator : { userAgent: "" }; const env = { isIE: isWindowAwailable && (nav.userAgent.indexOf("MSIE") >= 0 || nav.userAgent.indexOf("Trident") >= 0), isOpera: isWindowAwailable && (nav.userAgent.indexOf("Opera") >= 0 || nav.userAgent.indexOf("OPR") >= 0), isChrome: isWindowAwailable && nav.userAgent.indexOf("Chrome") >= 0, isSafari: isWindowAwailable && (nav.userAgent.indexOf("Safari") >= 0 || nav.userAgent.indexOf("Konqueror") >= 0), isFF: isWindowAwailable && nav.userAgent.indexOf("Firefox") >= 0, isIPad: isWindowAwailable && nav.userAgent.search(/iPad/gi) >= 0, isEdge: isWindowAwailable && nav.userAgent.indexOf("Edge") != -1, isNode: !isWindowAwailable || typeof navigator == "undefined" || false === "test", isSalesforce: isWindowAwailable && (!!scope["Sfdc"] || !!scope["$A"] || scope["Aura"]) }; function serialize(data2) { if (typeof data2 === "string" || typeof data2 === "number") { return data2; } let result = ""; for (const key in data2) { let serialized = ""; if (data2.hasOwnProperty(key)) { if (typeof data2[key] === "string") { serialized = encodeURIComponent(data2[key]); } else if (typeof data2[key] === "number") { serialized = String(data2[key]); } else { serialized = encodeURIComponent(JSON.stringify(data2[key])); } serialized = key + "=" + serialized; if (result.length) { serialized = "&" + serialized; } result += serialized; } } return result; } function createConfig(method, args) { var result = { method }; if (args.length === 0) { throw new Error("Arguments list of query is wrong."); } if (args.length === 1) { if (typeof args[0] === "string") { result.url = args[0]; result.async = true; } else { result.url = args[0].url; result.async = args[0].async || true; result.callback = args[0].callback; result.headers = args[0].headers; } { if (args[0].data) { if (typeof args[0].data !== "string") { result.data = serialize(args[0].data); } else { result.data = args[0].data; } } else { result.data = ""; } } return result; } result.url = args[0]; switch (method) { case "GET": case "DELETE": result.callback = args[1]; result.headers = args[2]; break; case "POST": case "PUT": if (args[1]) { if (typeof args[1] !== "string") { result.data = serialize(args[1]); } else { result.data = args[1]; } } else { result.data = ""; } result.callback = args[2]; result.headers = args[3]; break; } return result; } function ajax(gantt2) { return { cache: true, method: "get", parse: function(data2) { if (typeof data2 !== "string") return data2; var obj; data2 = data2.replace(/^[\s]+/, ""); if (typeof DOMParser !== "undefined" && !env.isIE) { obj = new DOMParser().parseFromString(data2, "text/xml"); } else if (typeof scope.ActiveXObject !== "undefined") { obj = new scope.ActiveXObject("Microsoft.XMLDOM"); obj.async = "false"; obj.loadXML(data2); } return obj; }, xmltop: function(tagname, xhr, obj) { if (typeof xhr.status == "undefined" || xhr.status < 400) { var xml = !xhr.responseXML ? this.parse(xhr.responseText || xhr) : xhr.responseXML || xhr; if (xml && xml.documentElement !== null && !xml.getElementsByTagName("parsererror").length) { return xml.getElementsByTagName(tagname)[0]; } } if (obj !== -1) gantt2.callEvent("onLoadXMLError", ["Incorrect XML", arguments[1], obj]); return document.createElement("DIV"); }, xpath: function(xpathExp, docObj) { if (!docObj.nodeName) docObj = docObj.responseXML || docObj; if (env.isIE) { return docObj.selectNodes(xpathExp) || []; } else { var rows = []; var first; var col = (docObj.ownerDocument || docObj).evaluate(xpathExp, docObj, null, XPathResult.ANY_TYPE, null); while (true) { first = col.iterateNext(); if (first) { rows.push(first); } else { break; } } return rows; } }, query: function(config2) { return this._call(config2.method || "GET", config2.url, config2.data || "", config2.async || true, config2.callback, config2.headers); }, get: function(url, onLoad, headers) { var config2 = createConfig("GET", arguments); return this.query(config2); }, getSync: function(url, headers) { var config2 = createConfig("GET", arguments); config2.async = false; return this.query(config2); }, put: function(url, postData, onLoad, headers) { var config2 = createConfig("PUT", arguments); return this.query(config2); }, del: function(url, onLoad, headers) { var config2 = createConfig("DELETE", arguments); return this.query(config2); }, post: function(url, postData, onLoad, headers) { if (arguments.length == 1) { postData = ""; } else if (arguments.length == 2 && typeof postData == "function") { onLoad = postData; postData = ""; } var config2 = createConfig("POST", arguments); return this.query(config2); }, postSync: function(url, postData, headers) { postData = postData === null ? "" : String(postData); var config2 = createConfig("POST", arguments); config2.async = false; return this.query(config2); }, _call: function(method, url, postData, async, onLoad, headers) { return new gantt2.Promise(function(resolve, reject) { var t2 = typeof XMLHttpRequest !== void 0 ? new XMLHttpRequest() : new scope.ActiveXObject("Microsoft.XMLHTTP"); var isQt = navigator.userAgent.match(/AppleWebKit/) !== null && navigator.userAgent.match(/Qt/) !== null && navigator.userAgent.match(/Safari/) !== null; if (!!async) { t2.onreadystatechange = function() { if (t2.readyState == 4 || isQt && t2.readyState == 3) { const errorStatus = t2.status < 200 || t2.status > 299; if (errorStatus || t2.responseText === "") { if (!gantt2.callEvent("onAjaxError", [t2])) return; } setTimeout(function() { if (typeof onLoad == "function") { onLoad.apply(scope, [{ xmlDoc: t2, filePath: url }]); } resolve(t2); if (typeof onLoad == "function") { onLoad = null; t2 = null; } }, 0); } }; } var noCache = !this || !this.cache; if (method == "GET" && noCache) { url += (url.indexOf("?") >= 0 ? "&" : "?") + "dhxr" + (/* @__PURE__ */ new Date()).getTime() + "=1"; } t2.open(method, url, async); if (headers) { for (var key in headers) t2.setRequestHeader(key, headers[key]); } else if (method.toUpperCase() == "POST" || method == "PUT" || method == "DELETE") { t2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } else if (method == "GET") { postData = null; } t2.setRequestHeader("X-Requested-With", "XMLHttpRequest"); t2.send(postData); if (!async) return { xmlDoc: t2, filePath: url }; }); }, urlSeparator: function(str) { if (str.indexOf("?") != -1) return "&"; else return "?"; } }; } const dateToStr$1 = (format, utc, gantt2) => { format = format.replace(/%[a-zA-Z]/g, (a) => { switch (a) { case "%d": return `"+to_fixed(date.get${utc ? "UTC" : ""}Date())+"`; case "%m": return `"+to_fixed((date.get${utc ? "UTC" : ""}Month()+1))+"`; case "%j": return `"+date.get${utc ? "UTC" : ""}Date()+"`; case "%n": return `"+(date.get${utc ? "UTC" : ""}Month()+1)+"`; case "%y": return `"+to_fixed(date.get${utc ? "UTC" : ""}FullYear()%100)+"`; case "%Y": return `"+date.get${utc ? "UTC" : ""}FullYear()+"`; case "%D": return `"+locale.date.day_short[date.get${utc ? "UTC" : ""}Day()]+"`; case "%l": return `"+locale.date.day_full[date.get${utc ? "UTC" : ""}Day()]+"`; case "%M": return `"+locale.date.month_short[date.get${utc ? "UTC" : ""}Month()]+"`; case "%F": return `"+locale.date.month_full[date.get${utc ? "UTC" : ""}Month()]+"`; case "%h": return `"+to_fixed((date.get${utc ? "UTC" : ""}Hours()+11)%12+1)+"`; case "%g": return `"+((date.get${utc ? "UTC" : ""}Hours()+11)%12+1)+"`; case "%G": return `"+date.get${utc ? "UTC" : ""}Hours()+"`; case "%H": return `"+to_fixed(date.get${utc ? "UTC" : ""}Hours())+"`; case "%i": return `"+to_fixed(date.get${utc ? "UTC" : ""}Minutes())+"`; case "%a": return `"+(date.get${utc ? "UTC" : ""}Hours()>11?"pm":"am")+"`; case "%A": return `"+(date.get${utc ? "UTC" : ""}Hours()>11?"PM":"AM")+"`; case "%s": return `"+to_fixed(date.get${utc ? "UTC" : ""}Seconds())+"`; case "%W": return `"+to_fixed(getISOWeek(date))+"`; case "%w": return `"+to_fixed(getWeek(date))+"`; default: return a; } }); const dateToStrFn = new Function("date", "to_fixed", "locale", "getISOWeek", "getWeek", `return "${format}";`); return (date2) => dateToStrFn(date2, gantt2.date.to_fixed, gantt2.locale, gantt2.date.getISOWeek, gantt2.date.getWeek); }; const strToDate$1 = (format, utc, gantt2) => { let splt = "var temp=date.match(/[a-zA-Z]+|[0-9]+/g);"; const mask = format.match(/%[a-zA-Z]/g); for (let i = 0; i < mask.length; i++) { switch (mask[i]) { case "%j": case "%d": splt += `set[2]=temp[${i}]||1;`; break; case "%n": case "%m": splt += `set[1]=(temp[${i}]||1)-1;`; break; case "%y": splt += `set[0]=temp[${i}]*1+(temp[${i}]>50?1900:2000);`; break; case "%g": case "%G": case "%h": case "%H": splt += `set[3]=temp[${i}]||0;`; break; case "%i": splt += `set[4]=temp[${i}]||0;`; break; case "%Y": splt += `set[0]=temp[${i}]||0;`; break; case "%a": case "%A": splt += `set[3]=set[3]%12+((temp[${i}]||'').toLowerCase()=='am'?0:12);`; break; case "%s": splt += `set[5]=temp[${i}]||0;`; break; case "%M": splt += `set[1]=locale.date.month_short_hash[temp[${i}]]||0;`; break; case "%F": splt += `set[1]=locale.date.month_full_hash[temp[${i}]]||0;`; break; } } let code = "set[0],set[1],set[2],set[3],set[4],set[5]"; if (utc) { code = ` Date.UTC(${code})`; } const strToDateFn = new Function("date", "locale", `var set=[0,0,1,0,0,0]; ${splt} return new Date(${code});`); return (dateString) => strToDateFn(dateString, gantt2.locale); }; const fastVersion = { date_to_str: dateToStr$1, str_to_date: strToDate$1 }; const dateToStr = (format, utc, gantt2) => (date2) => format.replace(/%[a-zA-Z]/g, (a) => { switch (a) { case "%d": return utc ? gantt2.date.to_fixed(date2.getUTCDate()) : gantt2.date.to_fixed(date2.getDate()); case "%m": return utc ? gantt2.date.to_fixed(date2.getUTCMonth() + 1) : gantt2.date.to_fixed(date2.getMonth() + 1); case "%j": return utc ? date2.getUTCDate() : date2.getDate(); case "%n": return utc ? date2.getUTCMonth() + 1 : date2.getMonth() + 1; case "%y": return utc ? gantt2.date.to_fixed(date2.getUTCFullYear() % 100) : gantt2.date.to_fixed(date2.getFullYear() % 100); case "%Y": return utc ? date2.getUTCFullYear() : date2.getFullYear(); case "%D": return utc ? gantt2.locale.date.day_short[date2.getUTCDay()] : gantt2.locale.date.day_short[date2.getDay()]; case "%l": return utc ? gantt2.locale.date.day_full[date2.getUTCDay()] : gantt2.locale.date.day_full[date2.getDay()]; case "%M": return utc ? gantt2.locale.date.month_short[date2.getUTCMonth()] : gantt2.locale.date.month_short[date2.getMonth()]; case "%F": return utc ? gantt2.locale.date.month_full[date2.getUTCMonth()] : gantt2.locale.date.month_full[date2.getMonth()]; case "%h": return utc ? gantt2.date.to_fixed((date2.getUTCHours() + 11) % 12 + 1) : gantt2.date.to_fixed((date2.getHours() + 11) % 12 + 1); case "%g": return utc ? (date2.getUTCHours() + 11) % 12 + 1 : (date2.getHours() + 11) % 12 + 1; case "%G": return utc ? date2.getUTCHours() : date2.getHours(); case "%H": return utc ? gantt2.date.to_fixed(date2.getUTCHours()) : gantt2.date.to_fixed(date2.getHours()); case "%i": return utc ? gantt2.date.to_fixed(date2.getUTCMinutes()) : gantt2.date.to_fixed(date2.getMinutes()); case "%a": return utc ? date2.getUTCHours() > 11 ? "pm" : "am" : date2.getHours() > 11 ? "pm" : "am"; case "%A": return utc ? date2.getUTCHours() > 11 ? "PM" : "AM" : date2.getHours() > 11 ? "PM" : "AM"; case "%s": return utc ? gantt2.date.to_fixed(date2.getUTCSeconds()) : gantt2.date.to_fixed(date2.getSeconds()); case "%W": return utc ? gantt2.date.to_fixed(gantt2.date.getUTCISOWeek(date2)) : gantt2.date.to_fixed(gantt2.date.getISOWeek(date2)); case "%w": return gantt2.date.to_fixed(gantt2.date.getWeek(date2)); default: return a; } }); const strToDate = (format, utc, gantt2) => (date2) => { const set = [0, 0, 1, 0, 0, 0]; const temp = date2.match(/[a-zA-Z]+|[0-9]+/g); const mask = format.match(/%[a-zA-Z]/g); for (let i = 0; i < mask.length; i++) { switch (mask[i]) { case "%j": case "%d": set[2] = temp[i] || 1; break; case "%n": case "%m": set[1] = (temp[i] || 1) - 1; break; case "%y": set[0] = temp[i] * 1 + (temp[i] > 50 ? 1900 : 2e3); break; case "%g": case "%G": case "%h": case "%H": set[3] = temp[i] || 0; break; case "%i": set[4] = temp[i] || 0; break; case "%Y": set[0] = temp[i] || 0; break; case "%a": case "%A": set[3] = set[3] % 12 + ((temp[i] || "").toLowerCase() === "am" ? 0 : 12); break; case "%s": set[5] = temp[i] || 0; break; case "%M": set[1] = gantt2.locale.date.month_short_hash[temp[i]] || 0; break; case "%F": set[1] = gantt2.locale.date.month_full_hash[temp[i]] || 0; break; } } if (utc) { return new Date(Date.UTC(set[0], set[1], set[2], set[3], set[4], set[5])); } return new Date(set[0], set[1], set[2], set[3], set[4], set[5]); }; const cspVersion = { date_to_str: dateToStr, str_to_date: strToDate }; function date(gantt2) { var canUseCsp = null; function cspAutoCheck() { try { new Function("canUseCsp = false;"); } catch (e) { canUseCsp = true; } } function useCsp() { var result = false; if (gantt2.config.csp === "auto") { if (canUseCsp === null) { cspAutoCheck(); } result = canUseCsp; } else { result = gantt2.config.csp; } return result; } var dateHelper = { init: function() { var locale2 = gantt2.locale; var s = locale2.date.month_short; var t2 = locale2.date.month_short_hash = {}; for (var i = 0; i < s.length; i++) t2[s[i]] = i; var s = locale2.date.month_full; var t2 = locale2.date.month_full_hash = {}; for (var i = 0; i < s.length; i++) t2[s[i]] = i; }, date_part: function(date2) { var old = new Date(date2); date2.setHours(0); this.hour_start(date2); if (date2.getHours() && (date2.getDate() < old.getDate() || date2.getMonth() < old.getMonth() || date2.getFullYear() < old.getFullYear())) date2.setTime(date2.getTime() + 60 * 60 * 1e3 * (24 - date2.getHours())); return date2; }, time_part: function(date2) { return (date2.valueOf() / 1e3 - date2.getTimezoneOffset() * 60) % 86400; }, week_start: function(date2) { var shift = date2.getDay(); if (gantt2.config.start_on_monday) { if (shift === 0) shift = 6; else shift--; } return this.date_part(this.add(date2, -1 * shift, "day")); }, month_start: function(date2) { date2.setDate(1); return this.date_part(date2); }, quarter_start: function(date2) { this.month_start(date2); var m = date2.getMonth(), res_month; if (m >= 9) { res_month = 9; } else if (m >= 6) { res_month = 6; } else if (m >= 3) { res_month = 3; } else { res_month = 0; } date2.setMonth(res_month); return date2; }, year_start: function(date2) { date2.setMonth(0); return this.month_start(date2); }, day_start: function(date2) { return this.date_part(date2); }, hour_start: function(date2) { if (date2.getMinutes()) date2.setMinutes(0); this.minute_start(date2); return date2; }, minute_start: function(date2) { if (date2.getSeconds()) date2.setSeconds(0); if (date2.getMilliseconds()) date2.setMilliseconds(0); return date2; }, _add_days: function(modifiedDate, inc, originalDate) { modifiedDate.setDate(modifiedDate.getDate() + inc); var incCondition = inc >= 0; var getHoursCondition = !originalDate.getHours() && modifiedDate.getHours(); var getDateCondition = modifiedDate.getDate() <= originalDate.getDate() || modifiedDate.getMonth() < originalDate.getMonth() || modifiedDate.getFullYear() < originalDate.getFullYear(); if (incCondition && getHoursCondition && getDateCondition) { modifiedDate.setTime(modifiedDate.getTime() + 60 * 60 * 1e3 * (24 - modifiedDate.getHours())); } var worktimeCalculation = inc > 1; if (worktimeCalculation && getHoursCondition) { modifiedDate.setHours(0); } return modifiedDate; }, add: function(date2, inc, mode) { var ndate = new Date(date2.valueOf()); switch (mode) { case "day": ndate = this._add_days(ndate, inc, date2); break; case "week": ndate = this._add_days(ndate, inc * 7, date2); break; case "month": ndate.setMonth(ndate.getMonth() + inc); break; case "year": ndate.setYear(ndate.getFullYear() + inc); break; case "hour": ndate.setTime(ndate.getTime() + inc * 60 * 60 * 1e3); break; case "minute": ndate.setTime(ndate.getTime() + inc * 60 * 1e3); break; default: return this["add_" + mode](date2, inc, mode); } return ndate; }, add_quarter: function(date2, inc) { return this.add(date2, inc * 3, "month"); }, to_fixed: function(num) { if (num < 10) return "0" + num; return num; }, copy: function(date2) { return new Date(date2.valueOf()); }, date_to_str: function(format, utc) { var result = fastVersion; if (useCsp()) { result = cspVersion; } return result.date_to_str(format, utc, gantt2); }, str_to_date: function(format, utc) { var result = fastVersion; if (useCsp()) { result = cspVersion; } return result.str_to_date(format, utc, gantt2); }, getISOWeek: function(ndate) { return gantt2.date._getWeekNumber(ndate, true); }, _getWeekNumber: function(ndate, isoWeek) { if (!ndate) return false; var nday = ndate.getDay(); if (isoWeek) { if (nday === 0) { nday = 7; } } var first_thursday = new Date(ndate.valueOf()); first_thursday.setDate(ndate.getDate() + (4 - nday)); var year_number = first_thursday.getFullYear(); var ordinal_date = Math.round((first_thursday.getTime() - new Date(year_number, 0, 1).getTime()) / 864e5); var week_number = 1 + Math.floor(ordinal_date / 7); return week_number; }, getWeek: function(ndate) { return gantt2.date._getWeekNumber(ndate, gantt2.config.start_on_monday); }, getUTCISOWeek: function(ndate) { return gantt2.date.getISOWeek(ndate); }, convert_to_utc: function(date2) { return new Date(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate(), date2.getUTCHours(), date2.getUTCMinutes(), date2.getUTCSeconds()); }, parseDate: function(date2, format) { if (date2 && !date2.getFullYear) { if (typeof format !== "function") { if (typeof format === "string") { if (format === "parse_date" || format === "xml_date") { format = gantt2.defined(gantt2.templates.xml_date) ? gantt2.templates.xml_date : gantt2.templates.parse_date; } else { format = gantt2.defined(gantt2.templates[format]) ? gantt2.templates[format] : gantt2.date.str_to_date(format); } } else { format = gantt2.defined(gantt2.templates.xml_date) ? gantt2.templates.xml_date : gantt2.templates.parse_date; } } if (date2) { date2 = format(date2); } else { date2 = null; } } return date2; } }; return dateHelper; } class t { constructor(t2) { const { url: e, token: s } = t2; this._url = e, this._token = s, this._mode = 1, this._seed = 1, this._queue = [], this.data = {}, this.api = {}, this._events = {}; } headers() { return { Accept: "application/json", "Content-Type": "application/json", "Remote-Token": this._token }; } fetch(t2, e) { const s = { credentials: "include", headers: this.headers() }; return e && (s.method = "POST", s.body = e), fetch(t2, s).then((t3) => t3.json()); } load(t2) { return t2 && (this._url = t2), this.fetch(this._url).then((t3) => this.parse(t3)); } parse(t2) { const { key: e, websocket: s } = t2; e && (this._token = t2.key); for (const e2 in t2.data) this.data[e2] = t2.data[e2]; for (const e2 in t2.api) { const s2 = this.api[e2] = {}, i = t2.api[e2]; for (const t3 in i) s2[t3] = this._wrapper(e2 + "." + t3); } return s && this.connect(), this; } connect() { const t2 = this._socket; t2 && (this._socket = null, t2.onclose = function() { }, t2.close()), this._mode = 2, this._socket = function(t3, e, s, i) { let n = e; "/" === n[0] && (n = document.location.protocol + "//" + document.location.host + e); n = n.replace(/^http(s|):/, "ws$1:"); const o = -1 != n.indexOf("?") ? "&" : "?"; n = `${n}${o}token=${s}&ws=1`; const r = new WebSocket(n); return r.onclose = () => setTimeout(() => t3.connect(), 2e3), r.onmessage = (e2) => { const s2 = JSON.parse(e2.data); switch (s2.action) { case "result": t3.result(s2.body, []); break; case "event": t3.fire(s2.body.name, s2.body.value); break; case "start": i(); break; default: t3.onError(s2.data); } }, r; }(this, this._url, this._token, () => (this._mode = 3, this._send(), this._resubscribe(), this)); } _wrapper(t2) { return (function() { const e = [].slice.call(arguments); let s = null; const i = new Promise((i2, n) => { s = { data: { id: this._uid(), name: t2, args: e }, status: 1, resolve: i2, reject: n }, this._queue.push(s); }); return this.onCall(s, i), 3 === this._mode ? this._send(s) : setTimeout(() => this._send(), 1), i; }).bind(this); } _uid() { return (this._seed++).toString(); } _send(t2) { if (2 == this._mode) return void setTimeout(() => this._send(), 100); const e = t2 ? [t2] : this._queue.filter((t3) => 1 === t3.status); if (!e.length) return; const s = e.map((t3) => (t3.status = 2, t3.data)); 3 !== this._mode ? this.fetch(this._url, JSON.stringify(s)).catch((t3) => this.onError(t3)).then((t3) => this.result(t3, s)) : this._socket.send(JSON.stringify({ action: "call", body: s })); } result(t2, e) { const s = {}; if (t2) for (let e2 = 0; e2 < t2.length; e2++) s[t2[e2].id] = t2[e2]; else for (let t3 = 0; t3 < e.length; t3++) s[e[t3].id] = { id: e[t3].id, error: "Network Error", data: null }; for (let t3 = this._queue.length - 1; t3 >= 0; t3--) { const e2 = this._queue[t3], i = s[e2.data.id]; i && (this.onResponse(e2, i), i.error ? e2.reject(i.error) : e2.resolve(i.data), this._queue.splice(t3, 1)); } } on(t2, e) { const s = this._uid(); let i = this._events[t2]; const n = !!i; return n || (i = this._events[t2] = []), i.push({ id: s, handler: e }), n || 3 != this._mode || this._socket.send(JSON.stringify({ action: "subscribe", name: t2 })), { name: t2, id: s }; } _resubscribe() { if (3 == this._mode) for (const t2 in this._events) this._socket.send(JSON.stringify({ action: "subscribe", name: t2 })); } detach(t2) { if (!t2) { if (3 == this._mode) for (const t3 in this._events) this._socket.send(JSON.stringify({ action: "unsubscribe", key: t3 })); return void (this._events = {}); } const { id: e, name: s } = t2, i = this._events[s]; if (i) { const t3 = i.filter((t4) => t4.id != e); t3.length ? this._events[s] = t3 : (delete this._events[s], 3 == this._mode && this._socket.send(JSON.stringify({ action: "unsubscribe", name: s }))); } } fire(t2, e) { const s = this._events[t2]; if (s) for (let t3 = 0; t3 < s.length; t3++) s[t3].handler(e); } onError(t2) { return null; } onCall(t2, e) { } onResponse(t2, e) { } } const remoteEvents$1 = function(url, token) { const remote = new t({ url, token }); remote.fetch = function(url2, body) { const req = { headers: this.headers() }; if (body) { req.method = "POST"; req.body = body; } return fetch(url2, req).then((res) => res.json()); }; this._ready = remote.load().then((back) => this._remote = back); function ready() { return this._ready; } function on(name, handler) { this.ready().then((back) => { if (typeof name === "string") back.on(name, handler); else { for (const key in name) { back.on(key, name[key]); } } }); } this.ready = ready; this.on = on; }; function checkTimeout(host, updPerSecond) { if (!updPerSecond) return true; if (host._on_timeout) return false; var timeout = Math.ceil(1e3 / updPerSecond); if (timeout < 2) return true; setTimeout(function() { delete host._on_timeout; }, timeout); host._on_timeout = true; return true; } function DnD(gantt2) { function copyDomEvent(e) { return { target: e.target || e.srcElement, pageX: e.pageX, pageY: e.pageY, clientX: e.clientX, clientY: e.clientY, metaKey: e.metaKey, shiftKey: e.shiftKey, ctrlKey: e.ctrlKey, altKey: e.altKey }; } function DnD2(obj, config2) { this._obj = obj; this._settings = config2 || {}; makeEventable(this); var inputMethods = this.getInputMethods(); this._drag_start_timer = null; gantt2.attachEvent("onGanttScroll", bind(function(left, top) { this.clearDragTimer(); }, this)); var lastDown = 0; var eventParams = { passive: false }; for (var i = 0; i < inputMethods.length; i++) { bind(function(input) { gantt2.event(obj, input.down, bind(function(e) { if (!input.accessor(e)) { return; } if (typeof e.button !== "undefined" && e.button !== 0) { return; } if (config2.preventDefault && config2.selector && closest(e.target, config2.selector)) { e.preventDefault(); } if (gantt2.config.touch && e.timeStamp && e.timeStamp - lastDown < 300) { return; } this._settings.original_target = copyDomEvent(e); this._settings.original_element_sizes = { ...getRelativeEventPosition(e, getClosestSizedElement(obj)), width: e.target.offsetWidth, height: e.target.offsetHeight }; if (gantt2.config.touch) { this.clearDragTimer(); this._drag_start_timer = setTimeout(bind(function() { if (gantt2.getState().lightbox) { return; } this.dragStart(obj, e, input); }, this), gantt2.config.touch_drag); } else { this.dragStart(obj, e, input); } }, this), eventParams); var eventElement = document.body; gantt2.event(eventElement, input.up, bind(function(e) { if (!input.accessor(e)) { return; } this.clearDragTimer(); }, this), eventParams); }, this)(inputMethods[i]); } } DnD2.prototype = { traceDragEvents: function(domElement, inputMethod) { var mousemove = bind(function(e) { return this.dragMove(domElement, e, inputMethod.accessor); }, this); bind(function(e) { return this.dragScroll(domElement, e); }, this); var limited_mousemove = bind(function(e) { if (this.config.started && defined(this.config.updates_per_second)) { if (!checkTimeout(this, this.config.updates_per_second)) return; } var dndActive = mousemove(e); if (dndActive) { try { if (e && e.preventDefault && e.cancelable) { e.preventDefault(); } } catch (e2) { } } return dndActive; }, this); var eventElement = getRootNode(gantt2.$root); var mousemoveContainer = this.config.mousemoveContainer || getRootNode(gantt2.$root); var eventParams = { passive: false }; var mouseup = bind(function(e) { gantt2.eventRemove(mousemoveContainer, inputMethod.move, limited_mousemove); gantt2.eventRemove(eventElement, inputMethod.up, mouseup, eventParams); return this.dragEnd(domElement); }, this); gantt2.event(mousemoveContainer, inputMethod.move, limited_mousemove, eventParams); gantt2.event(eventElement, inputMethod.up, mouseup, eventParams); }, checkPositionChange: function(pos) { var diff_x = pos.x - this.config.pos.x; var diff_y = pos.y - this.config.pos.y; var distance = Math.sqrt(Math.pow(Math.abs(diff_x), 2) + Math.pow(Math.abs(diff_y), 2)); if (distance > this.config.sensitivity) { return true; } else { return false; } }, initDnDMarker: function() { var marker2 = this.config.marker = document.createElement("div"); marker2.className = "gantt_drag_marker"; marker2.innerHTML = ""; document.body.appendChild(marker2); }, backupEventTarget: function(domEvent, getEvent) { if (!gantt2.config.touch) { return; } var e = getEvent(domEvent); var el = e.target || e.srcElement; var copy2 = el.cloneNode(true); this.config.original_target = copyDomEvent(e); this.config.original_target.target = copy2; this.config.backup_element = el; el.parentNode.appendChild(copy2); el.style.display = "none"; var mousemoveContainer = this.config.mousemoveContainer || document.body; mousemoveContainer.appendChild(el); }, getInputMethods: function() { var inputMethods = []; inputMethods.push({ move: "mousemove", down: "mousedown", up: "mouseup", accessor: function(e) { return e; } }); if (gantt2.config.touch) { const touchEventsSupported = !gantt2.env.isIE || !!scope.maxTouchPoints; if (touchEventsSupported) { inputMethods.push({ move: "touchmove", down: "touchstart", up: "touchend", accessor: function(ev) { if (ev.touches && ev.touches.length > 1) return null; if (ev.touches[0]) return { target: document.elementFromPoint(ev.touches[0].clientX, ev.touches[0].clientY), pageX: ev.touches[0].pageX, pageY: ev.touches[0].pageY, clientX: ev.touches[0].clientX, clientY: ev.touches[0].clientY }; else return ev; } }); } else if (scope.PointerEvent) { inputMethods.push({ move: "pointermove", down: "pointerdown", up: "pointerup", accessor: function(ev) { if (ev.pointerType == "mouse") return null; return ev; } }); } } return inputMethods; }, clearDragTimer: function() { if (this._drag_start_timer) { clearTimeout(this._drag_start_timer); this._drag_start_timer = null; } }, dragStart: function(obj, e, inputMethod) { if (this.config && this.config.started) { return; } this.config = { obj, marker: null, started: false, pos: this.getPosition(e), sensitivity: 4 }; if (this._settings) mixin(this.config, this._settings, true); this.traceDragEvents(obj, inputMethod); gantt2._prevent_touch_scroll = true; if (e.target.closest(".gantt_row") && !gantt2.config.order_branch) { gantt2._prevent_touch_scroll = false; } document.body.classList.add("gantt_noselect"); if (gantt2.config.touch) { this.dragMove(obj, e, inputMethod.accessor); } }, dragMove: function(obj, e, getEvent) { var source = getEvent(e); if (!source) return false; if (!this.config.marker && !this.config.started) { var pos = this.getPosition(source); if (gantt2.config.touch || this.checkPositionChange(pos)) { this.config.started = true; this.config.ignore = false; gantt2._touch_drag = true; if (this.callEvent("onBeforeDragStart", [obj, this.config.original_target]) === false) { this.config.ignore = true; return false; } this.backupEventTarget(e, getEvent); this.initDnDMarker(); gantt2._touch_feedback(); this.callEvent("onAfterDragStart", [obj, this.config.original_target]); } else { this.config.ignore = true; } } if (!this.config.ignore) { if (e.targetTouches && !source.target) return; source.pos = this.getPosition(source); this.config.marker.style.left = source.pos.x + "px"; this.config.marker.style.top = source.pos.y + "px"; this.callEvent("onDragMove", [obj, source]); return true; } return false; }, dragEnd: function(obj) { var target = this.config.backup_element; if (target && target.parentNode) { target.parentNode.removeChild(target); } gantt2._prevent_touch_scroll = false; if (this.config.marker) { this.config.marker.parentNode.removeChild(this.config.marker); this.config.marker = null; this.callEvent("onDragEnd", []); } this.config.started = false; gantt2._touch_drag = false; document.body.classList.remove("gantt_noselect"); }, getPosition: function(e) { var x = 0, y = 0; if (e.pageX || e.pageY) { x = e.pageX; y = e.pageY; } else if (e.clientX || e.clientY) { x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } return { x, y }; } }; return DnD2; } function templates(gantt2) { var regTemplates = {}; function initTemplate(name, initial, template_name) { template_name = template_name || name; var config2 = gantt2.config, templates2 = gantt2.templates; if (gantt2.config[name] && regTemplates[template_name] != config2[name]) { if (!(initial && templates2[template_name])) { templates2[template_name] = gantt2.date.date_to_str(config2[name]); regTemplates[template_name] = config2[name]; } } } function initTemplates() { var date2 = gantt2.date; var d = date2.date_to_str; var c = gantt2.config; var format_date = d(c.xml_date || c.date_format, c.server_utc); var parse_date = date2.str_to_date(c.xml_date || c.date_format, c.server_utc); initTemplate("date_scale", true, void 0, gantt2.config, gantt2.templates); initTemplate("date_grid", true, "grid_date_format", gantt2.config, gantt2.templates); initTemplate("task_date", true, void 0, gantt2.config, gantt2.templates); gantt2.mixin(gantt2.templates, { xml_format: void 0, format_date, xml_date: void 0, parse_date, progress_text: function(start, end, task) { return ""; }, grid_header_class: function(column, config2) { return ""; }, task_text: function(start, end, task) { return task.text; }, task_class: function(start, end, task) { return ""; }, task_end_date: function(date3) { return gantt2.templates.task_date(date3); }, grid_row_class: function(start, end, task) { return ""; }, task_row_class: function(start, end, task) { return ""; }, timeline_cell_class: function(item, date3) { return ""; }, timeline_cell_content: function(item, date3) { return ""; }, scale_cell_class: function(date3) { return ""; }, scale_row_class: function(date3) { return ""; }, grid_indent: function(item) { return "
"; }, grid_folder: function(item) { return "
"; }, grid_file: function(item) { return "
"; }, grid_open: function(item) { return "
"; }, grid_blank: function(item) { return "
"; }, date_grid: function(date3, item, column) { if (item && gantt2.isUnscheduledTask(item) && gantt2.config.show_unscheduled) { return gantt2.templates.task_unscheduled_time(item); } else { return gantt2.templates.grid_date_format(date3, column); } }, task_time: function(start, end, ev) { if (gantt2.isUnscheduledTask(ev) && gantt2.config.show_unscheduled) { return gantt2.templates.task_unscheduled_time(ev); } else { return gantt2.templates.task_date(start) + " - " + gantt2.templates.task_end_date(end); } }, task_unscheduled_time: function(task) { return ""; }, time_picker: d(c.time_picker), link_class: function(link) { return ""; }, link_description: function(link) { var from = gantt2.getTask(link.source), to = gantt2.getTask(link.target); return "" + from.text + "" + to.text + ""; }, drag_link: function(from, from_start, to, to_start) { from = gantt2.getTask(from); var labels = gantt2.locale.labels; var text = "" + from.text + " " + (from_start ? labels.link_start : labels.link_end) + "
"; if (to) { to = gantt2.getTask(to); text += " " + to.text + " " + (to_start ? labels.link_start : labels.link_end) + "
"; } return text; }, drag_link_class: function(from, from_start, to, to_start) { var add = ""; if (from && to) { var allowed = gantt2.isLinkAllowed(from, to, from_start, to_start); add = " " + (allowed ? "gantt_link_allow" : "gantt_link_deny"); } return "gantt_link_tooltip" + add; }, tooltip_date_format: date2.date_to_str("%Y-%m-%d"), tooltip_text: function(start, end, event2) { return `
Task: ${event2.text}
Start date: ${gantt2.templates.tooltip_date_format(start)}
End date: ${gantt2.templates.tooltip_date_format(end)}
`; }, baseline_text: function(task, baseline, index) { return ""; } }); } return { initTemplates, initTemplate }; } var StateService = function() { var stateProviders = {}; function getState(name) { var provider = stateProviders[name]; if (provider) { return stateProviders[name].method(); } else { var res = {}; for (var i in stateProviders) { if (!stateProviders[i].internal) mixin(res, stateProviders[i].method(), true); } return res; } } function registerProvider(name, provider, internal) { stateProviders[name] = { method: provider, internal }; } function unregisterProvider(name) { delete stateProviders[name]; } return { getState, registerProvider, unregisterProvider }; }; const Promise$1 = Promise; var createTasksDatastoreFacade = function() { return { getTask: function(id) { id = replaceValidZeroId(id, this.config.root_id); this.assert(id, "Invalid argument for gantt.getTask"); var task = this.$data.tasksStore.getItem(id); this.assert(task, "Task not found id=" + id); return task; }, getTaskByTime: function(from, to) { var p = this.$data.tasksStore.getItems(); var res = []; if (!(from || to)) { res = p; } else { from = +from || -Infinity; to = +to || Infinity; for (var t2 = 0; t2 < p.length; t2++) { var task = p[t2]; if (+task.start_date < to && +task.end_date > from) res.push(task); } } return res; }, isTaskExists: function(id) { if (!this.$data || !this.$data.tasksStore) { return false; } return this.$data.tasksStore.exists(id); }, updateTask: function(id, item) { if (!defined(item)) item = this.getTask(id); this.$data.tasksStore.updateItem(id, item); if (this.isTaskExists(id)) this.refreshTask(id); }, addTask: function(item, parent, index) { if (!defined(item.id)) item.id = uid(); if (this.isTaskExists(item.id)) { var task = this.getTask(item.id); if (task.$index != item.$index) { if (item.start_date && typeof item.start_date === "string") { item.start_date = this.date.parseDate(item.start_date, "parse_date"); } if (item.end_date && typeof item.end_date === "string") { item.end_date = this.date.parseDate(item.end_date, "parse_date"); } return this.$data.tasksStore.updateItem(item.id, item); } } if (!defined(parent)) parent = this.getParent(item) || 0; if (!this.isTaskExists(parent)) parent = this.config.root_id; this.setParent(item, parent); if (this.getState().lightbox && this.isTaskExists(parent)) { var parentObj = this.getTask(parent); this.callEvent("onAfterParentExpand", [parent, parentObj]); } return this.$data.tasksStore.addItem(item, index, parent); }, deleteTask: function(id) { id = replaceValidZeroId(id, this.config.root_id); return this.$data.tasksStore.removeItem(id); }, getTaskCount: function() { return this.$data.tasksStore.count(); }, getVisibleTaskCount: function() { return this.$data.tasksStore.countVisible(); }, getTaskIndex: function(id) { return this.$data.tasksStore.getBranchIndex(id); }, getGlobalTaskIndex: function(id) { id = replaceValidZeroId(id, this.config.root_id); this.assert(id, "Invalid argument"); return this.$data.tasksStore.getIndexById(id); }, eachTask: function(code, parent, master) { return this.$data.tasksStore.eachItem(bind(code, master || this), parent); }, eachParent: function(callback, startTask, master) { return this.$data.tasksStore.eachParent(bind(callback, master || this), startTask); }, changeTaskId: function(oldid, newid) { this.$data.tasksStore.changeId(oldid, newid); var task = this.$data.tasksStore.getItem(newid); var links = []; if (task.$source) { links = links.concat(task.$source); } if (task.$target) { links = links.concat(task.$target); } for (var i = 0; i < links.length; i++) { var link = this.getLink(links[i]); if (link.source == oldid) { link.source = newid; } if (link.target == oldid) { link.target = newid; } } }, calculateTaskLevel: function(item) { return this.$data.tasksStore.calculateItemLevel(item); }, getNext: function(id) { return this.$data.tasksStore.getNext(id); }, getPrev: function(id) { return this.$data.tasksStore.getPrev(id); }, getParent: function(id) { return this.$data.tasksStore.getParent(id); }, setParent: function(task, new_pid, silent) { return this.$data.tasksStore.setParent(task, new_pid, silent); }, getSiblings: function(id) { return this.$data.tasksStore.getSiblings(id).slice(); }, getNextSibling: function(id) { return this.$data.tasksStore.getNextSibling(id); }, getPrevSibling: function(id) { return this.$data.tasksStore.getPrevSibling(id); }, getTaskByIndex: function(index) { var id = this.$data.tasksStore.getIdByIndex(index); if (this.isTaskExists(id)) { return this.getTask(id); } else { return null; } }, getChildren: function(id) { if (!this.hasChild(id)) { return []; } else { return this.$data.tasksStore.getChildren(id).slice(); } }, hasChild: function(id) { return this.$data.tasksStore.hasChild(id); }, open: function(id) { this.$data.tasksStore.open(id); }, close: function(id) { this.$data.tasksStore.close(id); }, moveTask: function(sid, tindex, parent) { parent = replaceValidZeroId(parent, this.config.root_id); return this.$data.tasksStore.move.apply(this.$data.tasksStore, arguments); }, sort: function(field, desc, parent, silent) { var render = !silent; this.$data.tasksStore.sort(field, desc, parent); this.callEvent("onAfterSort", [field, desc, parent]); if (render) { this.render(); } } }; }; var createLinksStoreFacade = function() { return { getLinkCount: function() { return this.$data.linksStore.count(); }, getLink: function(id) { return this.$data.linksStore.getItem(id); }, getLinks: function() { return this.$data.linksStore.getItems(); }, isLinkExists: function(id) { return this.$data.linksStore.exists(id); }, addLink: function(link) { return this.$data.linksStore.addItem(link); }, updateLink: function(id, data2) { if (!defined(data2)) data2 = this.getLink(id); this.$data.linksStore.updateItem(id, data2); }, deleteLink: function(id) { return this.$data.linksStore.removeItem(id); }, changeLinkId: function(oldid, newid) { return this.$data.linksStore.changeId(oldid, newid); } }; }; var $powerArray = { $create: function(array) { return mixin(array || [], this); }, $removeAt: function(pos, len) { if (pos >= 0) this.splice(pos, len || 1); }, $remove: function(value) { this.$removeAt(this.$find(value)); }, $insertAt: function(data2, pos) { if (!pos && pos !== 0) this.push(data2); else { var b = this.splice(pos, this.length - pos); this[pos] = data2; this.push.apply(this, b); } }, $find: function(data2) { for (var i = 0; i < this.length; i++) if (data2 == this[i]) return i; return -1; }, $each: function(functor, master) { for (var i = 0; i < this.length; i++) functor.call(master || this, this[i]); }, $map: function(functor, master) { for (var i = 0; i < this.length; i++) this[i] = functor.call(master || this, this[i]); return this; }, $filter: function(functor, master) { for (var i = 0; i < this.length; i++) if (!functor.call(master || this, this[i])) { this.splice(i, 1); i--; } return this; } }; function isPlaceholderTask(id, gantt2, store, config2) { var config2 = gantt2 ? gantt2.config : config2; if (config2 && config2.placeholder_task) { if (store.exists(id)) { var item = store.getItem(id); return item.type === config2.types.placeholder; } } return false; } var DataStore = function(config2) { this.pull = {}; this.$initItem = config2.initItem; this.visibleOrder = $powerArray.$create(); this.fullOrder = $powerArray.$create(); this._skip_refresh = false; this._filterRule = null; this._searchVisibleOrder = {}; this._indexRangeCache = {}; this._getItemsCache = null; this.$config = config2; makeEventable(this); this._attachDataChange(function() { this._indexRangeCache = {}; this._getItemsCache = null; return true; }); return this; }; DataStore.prototype = { _attachDataChange: function(callback) { this.attachEvent("onClearAll", callback); this.attachEvent("onBeforeParse", callback); this.attachEvent("onBeforeUpdate", callback); this.attachEvent("onBeforeDelete", callback); this.attachEvent("onBeforeAdd", callback); this.attachEvent("onParse", callback); this.attachEvent("onBeforeFilter", callback); }, _parseInner: function(data2) { var item = null, loaded = []; for (var i = 0, len = data2.length; i < len; i++) { item = data2[i]; if (this.$initItem) { if (this.$config.copyOnParse()) { item = copy(item); } item = this.$initItem(item); } if (this.callEvent("onItemLoading", [item])) { if (!this.pull.hasOwnProperty(item.id)) { this.fullOrder.push(item.id); } loaded.push(item); this.pull[item.id] = item; } } return loaded; }, parse: function(data2) { if (!this.isSilent()) { this.callEvent("onBeforeParse", [data2]); } var loaded = this._parseInner(data2); if (!this.isSilent()) { this.refresh(); this.callEvent("onParse", [loaded]); } }, getItem: function(id) { return this.pull[id]; }, _updateOrder: function(code) { code.call(this.visibleOrder); code.call(this.fullOrder); }, updateItem: function(id, item) { if (!defined(item)) item = this.getItem(id); if (!this.isSilent()) { if (this.callEvent("onBeforeUpdate", [item.id, item]) === false) return false; } mixin(this.pull[id], item, true); if (!this.isSilent()) { this.callEvent("onAfterUpdate", [item.id, item]); this.callEvent("onStoreUpdated", [item.id, item, "update"]); } }, _removeItemInner: function(id) { this._updateOrder(function() { this.$remove(id); }); delete this.pull[id]; }, removeItem: function(id) { var obj = this.getItem(id); if (!this.isSilent()) { if (this.callEvent("onBeforeDelete", [obj.id, obj]) === false) return false; } this.callEvent("onAfterDeleteConfirmed", [obj.id, obj]); this._removeItemInner(id); if (this.isSilent()) { this.callEvent("onAfterSilentDelete", [obj.id, obj]); } if (!this.isSilent()) { this.filter(); this.callEvent("onAfterDelete", [obj.id, obj]); this.callEvent("onStoreUpdated", [obj.id, obj, "delete"]); } }, _addItemInner: function(item, index) { if (this.exists(item.id)) { this.silent(function() { this.updateItem(item.id, item); }); } else { var order = this.visibleOrder; var data_size = order.length; if (!defined(index) || index < 0) index = data_size; if (index > data_size) { index = Math.min(order.length, index); } } this.pull[item.id] = item; this._updateOrder(function() { if (this.$find(item.id) === -1) this.$insertAt(item.id, index); }); this.filter(); }, isVisible: function(id) { return this.visibleOrder.$find(id) > -1; }, getVisibleItems: function() { return this.getIndexRange(); }, addItem: function(item, index) { if (!defined(item.id)) item.id = uid(); if (this.$initItem) { item = this.$initItem(item); } if (!this.isSilent()) { if (this.callEvent("onBeforeAdd", [item.id, item]) === false) return false; } this._addItemInner(item, index); if (!this.isSilent()) { this.callEvent("onAfterAdd", [item.id, item]); this.callEvent("onStoreUpdated", [item.id, item, "add"]); } else { if (this.sync_link) { this.sync_link(item); } } return item.id; }, _changeIdInner: function(oldId, newId) { if (this.pull[oldId]) this.pull[newId] = this.pull[oldId]; var visibleOrder = this._searchVisibleOrder[oldId]; this.pull[newId].id = newId; this._updateOrder(function() { this[this.$find(oldId)] = newId; }); this._searchVisibleOrder[newId] = visibleOrder; delete this._searchVisibleOrder[oldId]; delete this.pull[oldId]; }, changeId: function(oldId, newId) { this._changeIdInner(oldId, newId); this.callEvent("onIdChange", [oldId, newId]); }, exists: function(id) { return !!this.pull[id]; }, _moveInner: function(sindex, tindex) { var id = this.getIdByIndex(sindex); this._updateOrder(function() { this.$removeAt(sindex); this.$insertAt(id, Math.min(this.length, tindex)); }); }, move: function(sindex, tindex) { var id = this.getIdByIndex(sindex); var obj = this.getItem(id); this._moveInner(sindex, tindex); if (!this.isSilent()) { this.callEvent("onStoreUpdated", [obj.id, obj, "move"]); } }, clearAll: function() { if (this.$destroyed) { return; } this.silent(function() { this.unselect(); }); this.pull = {}; this.visibleOrder = $powerArray.$create(); this.fullOrder = $powerArray.$create(); if (this.isSilent()) return; this.callEvent("onClearAll", []); this.refresh(); }, silent: function(code, master) { var alreadySilent = false; if (this.isSilent()) { alreadySilent = true; } this._skip_refresh = true; code.call(master || this); if (!alreadySilent) { this._skip_refresh = false; } }, isSilent: function() { return !!this._skip_refresh; }, arraysEqual: function(arr1, arr2) { if (arr1.length !== arr2.length) return false; for (var i = 0; i < arr1.length; i++) { if (arr1[i] !== arr2[i]) return false; } return true; }, refresh: function(id, quick) { if (this.$destroyed) { return; } if (this.isSilent()) return; var item; if (id) { item = this.getItem(id); } var args; if (id) { args = [id, item, "paint"]; } else { args = [null, null, null]; } if (this.callEvent("onBeforeStoreUpdate", args) === false) { return; } var skipFilter = this._quick_refresh && !this._mark_recompute; this._mark_recompute = false; if (id) { if (!quick && !skipFilter) { var oldOrder = this.visibleOrder; this.filter(); if (!this.arraysEqual(oldOrder, this.visibleOrder)) { id = void 0; } } } else if (!skipFilter) { this.filter(); } if (id) { args = [id, item, "paint"]; } else { args = [null, null, null]; } this.callEvent("onStoreUpdated", args); }, count: function() { return this.fullOrder.length; }, countVisible: function() { return this.visibleOrder.length; }, sort: function(sort) { }, serialize: function() { }, eachItem: function(code) { for (var i = 0; i < this.fullOrder.length; i++) { var item = this.getItem(this.fullOrder[i]); code.call(this, item); } }, find: function(filter) { var result = []; this.eachItem(function(item) { if (filter(item)) { result.push(item); } }); return result; }, filter: function(rule) { if (!this.isSilent()) { this.callEvent("onBeforeFilter", []); } this.callEvent("onPreFilter", []); var filteredOrder = $powerArray.$create(); var placeholderIds = []; this.eachItem(function(item) { if (this.callEvent("onFilterItem", [item.id, item])) { if (isPlaceholderTask(item.id, null, this, this._ganttConfig)) { placeholderIds.push(item.id); } else { filteredOrder.push(item.id); } } }); for (var i = 0; i < placeholderIds.length; i++) { filteredOrder.push(placeholderIds[i]); } this.visibleOrder = filteredOrder; this._searchVisibleOrder = {}; for (var i = 0; i < this.visibleOrder.length; i++) { this._searchVisibleOrder[this.visibleOrder[i]] = i; } if (!this.isSilent()) { this.callEvent("onFilter", []); } }, getIndexRange: function(from, to) { var max = Math.min(to || Infinity, this.countVisible() - 1); var min = from || 0; var cacheKey = min + "-" + max; if (this._indexRangeCache[cacheKey]) { return this._indexRangeCache[cacheKey].slice(); } var ret = []; for (var i = min; i <= max; i++) ret.push(this.getItem(this.visibleOrder[i])); this._indexRangeCache[cacheKey] = ret.slice(); return ret; }, getItems: function() { if (this._getItemsCache) { return this._getItemsCache.slice(); } var res = []; for (var i in this.pull) { res.push(this.pull[i]); } this._getItemsCache = res.slice(); return res; }, getIdByIndex: function(index) { return this.visibleOrder[index]; }, getIndexById: function(id) { var res = this._searchVisibleOrder[id]; if (res === void 0) { res = -1; } return res; }, _getNullIfUndefined: function(value) { if (value === void 0) { return null; } else { return value; } }, getFirst: function() { return this._getNullIfUndefined(this.visibleOrder[0]); }, getLast: function() { return this._getNullIfUndefined(this.visibleOrder[this.visibleOrder.length - 1]); }, getNext: function(id) { return this._getNullIfUndefined(this.visibleOrder[this.getIndexById(id) + 1]); }, getPrev: function(id) { return this._getNullIfUndefined(this.visibleOrder[this.getIndexById(id) - 1]); }, destructor: function() { this.callEvent("onDestroy", []); this.detachAllEvents(); this.$destroyed = true; this.pull = null; this.$initItem = null; this.visibleOrder = null; this.fullOrder = null; this._skip_refresh = null; this._filterRule = null; this._searchVisibleOrder = null; this._indexRangeCache = {}; } }; class SplitTasksHelper { constructor(datastore) { this._datastore = null; this.isSplitItem = (item) => item.render == "split" && this._datastore.hasChild(item.id); this.isSubrowSplitItem = (item) => item.split_placement == "subrow"; this.isDefaultSplitItem = (item) => item.split_placement == "auto" || item.split_placement === void 0; this.isInlineSplitItem = (item) => item.split_placement == "inline"; this._datastore = datastore; } } var TreeDataStore = function(config2) { DataStore.apply(this, [config2]); this._branches = {}; this._splitTaskHelper = new SplitTasksHelper(this); this.pull = {}; this.$initItem = function(item) { var loadedItem = item; if (config2.initItem) { loadedItem = config2.initItem(loadedItem); } var existingItem = this.getItem(item.id); if (existingItem && !isEqualIds(existingItem.parent, loadedItem.parent)) { this.move(loadedItem.id, loadedItem.$index || -1, loadedItem.parent || this._ganttConfig.root_id); } return loadedItem; }; this.$parentProperty = config2.parentProperty || "parent"; if (typeof config2.rootId !== "function") { this.$getRootId = /* @__PURE__ */ function(val) { return function() { return val; }; }(config2.rootId || 0); } else { this.$getRootId = config2.rootId; } this.$openInitially = config2.openInitially; this.visibleOrder = $powerArray.$create(); this.fullOrder = $powerArray.$create(); this._searchVisibleOrder = {}; this._indexRangeCache = {}; this._eachItemMainRangeCache = null; this._getItemsCache = null; this._skip_refresh = false; this._ganttConfig = null; if (config2.getConfig) { this._ganttConfig = config2.getConfig(); } var splitParents = {}; var splitItems = {}; var taskOpenState = {}; var taskVisibility = {}; var haveSplitItems = false; this._attachDataChange(function() { this._indexRangeCache = {}; this._eachItemMainRangeCache = null; this._getItemsCache = null; return true; }); this.attachEvent("onPreFilter", function() { this._indexRangeCache = {}; this._eachItemMainRangeCache = null; splitParents = {}; splitItems = {}; taskOpenState = {}; taskVisibility = {}; haveSplitItems = false; this.eachItem(function(item) { var parent = this.getParent(item.id); if (item.$open && taskOpenState[parent] !== false) { taskOpenState[item.id] = true; } else { taskOpenState[item.id] = false; } if (this._isSplitItem(item)) { haveSplitItems = true; splitParents[item.id] = true; splitItems[item.id] = true; } if (haveSplitItems && splitItems[parent]) { if (this._isDefaultItem(item) || this._isInlineChildItem(item)) splitItems[item.id] = true; } if (taskOpenState[parent] || taskOpenState[parent] === void 0 || this._isInlineChildItem(item)) { taskVisibility[item.id] = true; } else { taskVisibility[item.id] = false; } }); }); this.attachEvent("onFilterItem", function(id, item) { var canOpenSplitTasks = false; if (this._ganttConfig) { var canOpenSplitTasks = this._ganttConfig.open_split_tasks; } var open = taskVisibility[item.id]; if (haveSplitItems) { if (open && splitItems[item.id] && !splitParents[item.id]) { open = !!canOpenSplitTasks; } if (splitItems[item.id] && !splitParents[item.id]) { if (!this._isSplitChildItem(item)) item.$split_subtask = true; } } item.$expanded_branch = !!taskVisibility[item.id]; if (this._isInlineChildItem(item)) { open = false; } return !!open; }); this.attachEvent("onFilter", function() { splitParents = {}; splitItems = {}; taskOpenState = {}; taskVisibility = {}; }); return this; }; TreeDataStore.prototype = mixin({ _buildTree: function(data2) { var item = null; var rootId = this.$getRootId(); for (var i = 0, len = data2.length; i < len; i++) { item = data2[i]; this.setParent(item, replaceValidZeroId(this.getParent(item), rootId) || rootId); } for (var i = 0, len = data2.length; i < len; i++) { item = data2[i]; this._add_branch(item); item.$level = this.calculateItemLevel(item); item.$local_index = this.getBranchIndex(item.id); if (!defined(item.$open)) { item.$open = defined(item.open) ? item.open : this.$openInitially(); } } this._updateOrder(); }, _isSplitItem: function(item) { return this._splitTaskHelper.isSplitItem(item); }, _isSplitChildItem: function(item) { return this._splitTaskHelper.isSubrowSplitItem(item); }, _isDefaultItem: function(item) { return this._splitTaskHelper.isDefaultSplitItem(item); }, _isInlineChildItem: function(item) { return this._splitTaskHelper.isInlineSplitItem(item); }, parse: function(data2) { if (!this._skip_refresh) { this.callEvent("onBeforeParse", [data2]); } var loaded = this._parseInner(data2); this._buildTree(loaded); this.filter(); if (!this._skip_refresh) { this.callEvent("onParse", [loaded]); } }, _addItemInner: function(item, index) { var parent = this.getParent(item); if (!defined(parent)) { parent = this.$getRootId(); this.setParent(item, parent); } var parentIndex = this.getIndexById(parent); var targetIndex = parentIndex + Math.min(Math.max(index, 0), this.visibleOrder.length); if (targetIndex * 1 !== targetIndex) { targetIndex = void 0; } DataStore.prototype._addItemInner.call(this, item, targetIndex); this.setParent(item, parent); if (item.hasOwnProperty("$rendered_parent")) { this._move_branch(item, item.$rendered_parent); } this._add_branch(item, index); }, _changeIdInner: function(oldId, newId) { var children = this.getChildren(oldId); var visibleOrder = this._searchVisibleOrder[oldId]; DataStore.prototype._changeIdInner.call(this, oldId, newId); var parent = this.getParent(newId); this._replace_branch_child(parent, oldId, newId); if (this._branches[oldId]) { this._branches[newId] = this._branches[oldId]; } for (var i = 0; i < children.length; i++) { var child = this.getItem(children[i]); child[this.$parentProperty] = newId; child.$rendered_parent = newId; } this._searchVisibleOrder[newId] = visibleOrder; delete this._branches[oldId]; }, _traverseBranches: function(code, parent) { if (!defined(parent)) { parent = this.$getRootId(); } var branch = this._branches[parent]; if (branch) { for (var i = 0; i < branch.length; i++) { var itemId = branch[i]; code.call(this, itemId); if (this._branches[itemId]) this._traverseBranches(code, itemId); } } }, _updateOrder: function(code) { this.fullOrder = $powerArray.$create(); this._traverseBranches(function(taskId) { this.fullOrder.push(taskId); }); if (code) DataStore.prototype._updateOrder.call(this, code); }, _removeItemInner: function(id) { var items = []; this.eachItem(function(child) { items.push(child); }, id); items.push(this.getItem(id)); for (var i = 0; i < items.length; i++) { this._move_branch(items[i], this.getParent(items[i]), null); DataStore.prototype._removeItemInner.call(this, items[i].id); this._move_branch(items[i], this.getParent(items[i]), null); } }, move: function(sid, tindex, parent) { var id = arguments[3]; var config2 = this._ganttConfig || {}; var root_id = config2.root_id || 0; id = replaceValidZeroId(id, root_id); if (id) { if (id === sid) return; parent = this.getParent(id); tindex = this.getBranchIndex(id); } if (isEqualIds(sid, parent)) { return; } if (!defined(parent)) { parent = this.$getRootId(); } var source = this.getItem(sid); var source_pid = this.getParent(source.id); var tbranch = this.getChildren(parent); if (tindex == -1) tindex = tbranch.length + 1; if (isEqualIds(source_pid, parent)) { var sindex = this.getBranchIndex(sid); if (sindex == tindex) return; } if (this.callEvent("onBeforeItemMove", [sid, parent, tindex]) === false) return false; var placeholderIds = []; for (var i = 0; i < tbranch.length; i++) { if (isPlaceholderTask(tbranch[i], null, this, this._ganttConfig)) { placeholderIds.push(tbranch[i]); tbranch.splice(i, 1); i--; } } this._replace_branch_child(source_pid, sid); tbranch = this.getChildren(parent); var tid = tbranch[tindex]; tid = replaceValidZeroId(tid, root_id); if (!tid) tbranch.push(sid); else tbranch = tbranch.slice(0, tindex).concat([sid]).concat(tbranch.slice(tindex)); if (placeholderIds.length) { tbranch = tbranch.concat(placeholderIds); } if (!isEqualIds(source.$rendered_parent, source_pid) && !isEqualIds(source_pid, parent)) { source.$rendered_parent = source_pid; } this.setParent(source, parent); this._branches[parent] = tbranch; var diff = this.calculateItemLevel(source) - source.$level; source.$level += diff; this.eachItem(function(item) { item.$level += diff; }, source.id, this); this._moveInner(this.getIndexById(sid), this.getIndexById(parent) + tindex); this.callEvent("onAfterItemMove", [sid, parent, tindex]); this.refresh(); }, getBranchIndex: function(id) { var branch = this.getChildren(this.getParent(id)); let index = branch.indexOf(id + ""); if (index == -1) { index = branch.indexOf(+id); } return index; }, hasChild: function(id) { var branch = this._branches[id]; return branch && branch.length; }, getChildren: function(id) { var branch = this._branches[id]; return branch ? branch : $powerArray.$create(); }, isChildOf: function(childId, parentId) { if (!this.exists(childId)) return false; if (parentId === this.$getRootId()) return true; if (!this.hasChild(parentId)) return false; var item = this.getItem(childId); var pid = this.getParent(childId); var parent = this.getItem(parentId); if (parent.$level >= item.$level) { return false; } while (item && this.exists(pid)) { item = this.getItem(pid); if (item && isEqualIds(item.id, parentId)) return true; pid = this.getParent(item); } return false; }, getSiblings: function(id) { if (!this.exists(id)) { return $powerArray.$create(); } var parent = this.getParent(id); return this.getChildren(parent); }, getNextSibling: function(id) { var siblings = this.getSiblings(id); for (var i = 0, len = siblings.length; i < len; i++) { if (isEqualIds(siblings[i], id)) { var nextSibling = siblings[i + 1]; if (nextSibling === 0 && i > 0) { nextSibling = "0"; } return nextSibling || null; } } return null; }, getPrevSibling: function(id) { var siblings = this.getSiblings(id); for (var i = 0, len = siblings.length; i < len; i++) { if (isEqualIds(siblings[i], id)) { var previousSibling = siblings[i - 1]; if (previousSibling === 0 && i > 0) { previousSibling = "0"; } return previousSibling || null; } } return null; }, getParent: function(id) { var item = null; if (id.id !== void 0) { item = id; } else { item = this.getItem(id); } var parent; if (item) { parent = item[this.$parentProperty]; } else { parent = this.$getRootId(); } return parent; }, clearAll: function() { this._branches = {}; DataStore.prototype.clearAll.call(this); }, calculateItemLevel: function(item) { var level = 0; this.eachParent(function() { level++; }, item); return level; }, _setParentInner: function(item, new_pid, silent) { if (!silent) { if (item.hasOwnProperty("$rendered_parent")) { this._move_branch(item, item.$rendered_parent, new_pid); } else { this._move_branch(item, item[this.$parentProperty], new_pid); } } }, setParent: function(item, new_pid, silent) { this._setParentInner(item, new_pid, silent); item[this.$parentProperty] = new_pid; }, _eachItemCached: function(code, cache) { for (var i = 0, len = cache.length; i < len; i++) { code.call(this, cache[i]); } }, _eachItemIterate: function(code, startId, cache) { var itemsStack = this.getChildren(startId); if (itemsStack.length) { itemsStack = itemsStack.slice().reverse(); } while (itemsStack.length) { var itemId = itemsStack.pop(); var item = this.getItem(itemId); code.call(this, item); if (cache) { cache.push(item); } if (this.hasChild(item.id)) { var children = this.getChildren(item.id); var len = children.length; for (var i = len - 1; i >= 0; i--) { itemsStack.push(children[i]); } } } }, eachItem: function(code, parent) { var rootId = this.$getRootId(); if (!defined(parent)) { parent = rootId; } var startId = replaceValidZeroId(parent, rootId) || rootId; var useCache = false; var buildCache = false; var cache = null; if (startId === rootId) { if (this._eachItemMainRangeCache) { useCache = true; cache = this._eachItemMainRangeCache; } else { buildCache = true; cache = this._eachItemMainRangeCache = []; } } if (useCache) { this._eachItemCached(code, cache); } else { this._eachItemIterate(code, startId, buildCache ? cache : null); } }, eachParent: function(code, startItem) { var parentsHash = {}; var item = startItem; var parent = this.getParent(item); while (this.exists(parent)) { if (parentsHash[parent]) { throw new Error("Invalid tasks tree. Cyclic reference has been detected on task " + parent); } parentsHash[parent] = true; item = this.getItem(parent); code.call(this, item); parent = this.getParent(item); } }, _add_branch: function(item, index, parent) { var pid = parent === void 0 ? this.getParent(item) : parent; if (!this.hasChild(pid)) this._branches[pid] = $powerArray.$create(); var branch = this.getChildren(pid); var added_already = branch.indexOf(item.id + "") > -1 || branch.indexOf(+item.id) > -1; if (!added_already) { if (index * 1 == index) { branch.splice(index, 0, item.id); } else { branch.push(item.id); } item.$rendered_parent = pid; } }, _move_branch: function(item, old_parent, new_parent) { this._eachItemMainRangeCache = null; this._replace_branch_child(old_parent, item.id); if (this.exists(new_parent) || isEqualIds(new_parent, this.$getRootId())) { this._add_branch(item, void 0, new_parent); } else { delete this._branches[item.id]; } item.$level = this.calculateItemLevel(item); this.eachItem(function(child) { child.$level = this.calculateItemLevel(child); }, item.id); }, _replace_branch_child: function(node, old_id, new_id) { var branch = this.getChildren(node); if (branch && node !== void 0) { var newbranch = $powerArray.$create(); let index = branch.indexOf(old_id + ""); if (index == -1 && !isNaN(+old_id)) { index = branch.indexOf(+old_id); } if (index > -1) { if (new_id) { branch.splice(index, 1, new_id); } else { branch.splice(index, 1); } } newbranch = branch; this._branches[node] = newbranch; } }, sort: function(field, desc, parent) { if (!this.exists(parent)) { parent = this.$getRootId(); } if (!field) field = "order"; var criteria = typeof field == "string" ? function(a, b) { if (a[field] == b[field] || isDate(a[field]) && isDate(b[field]) && a[field].valueOf() == b[field].valueOf()) { return 0; } var result = a[field] > b[field]; return result ? 1 : -1; } : field; if (desc) { var original_criteria = criteria; criteria = function(a, b) { return original_criteria(b, a); }; } var els = this.getChildren(parent); if (els) { var temp = []; for (var i = els.length - 1; i >= 0; i--) temp[i] = this.getItem(els[i]); temp.sort(criteria); for (var i = 0; i < temp.length; i++) { els[i] = temp[i].id; this.sort(field, desc, els[i]); } } }, filter: function(rule) { for (let i in this.pull) { const renderedParent = this.pull[i].$rendered_parent; const actualParent = this.getParent(this.pull[i]); if (!isEqualIds(renderedParent, actualParent)) { this._move_branch(this.pull[i], renderedParent, actualParent); } } return DataStore.prototype.filter.apply(this, arguments); }, open: function(id) { if (this.exists(id)) { this.getItem(id).$open = true; this._skipTaskRecalculation = true; this.callEvent("onItemOpen", [id]); } }, close: function(id) { if (this.exists(id)) { this.getItem(id).$open = false; this._skipTaskRecalculation = true; this.callEvent("onItemClose", [id]); } }, destructor: function() { DataStore.prototype.destructor.call(this); this._branches = null; this._indexRangeCache = {}; this._eachItemMainRangeCache = null; } }, DataStore.prototype); function isEqualIds(first, second) { return String(first) === String(second); } function createDataStoreSelectMixin(store) { var selectedId = null; var deleteItem = store._removeItemInner; function unselect(id) { selectedId = null; this.callEvent("onAfterUnselect", [id]); } store._removeItemInner = function(id) { if (selectedId == id) { unselect.call(this, id); } if (selectedId && this.eachItem) { this.eachItem(function(subItem) { if (subItem.id == selectedId) { unselect.call(this, subItem.id); } }, id); } return deleteItem.apply(this, arguments); }; store.attachEvent("onIdChange", function(oldId, newId) { if (store.getSelectedId() == oldId) { store.silent(function() { store.unselect(oldId); store.select(newId); }); } }); return { select: function(id) { if (id) { if (selectedId == id) return selectedId; if (!this._skip_refresh) { if (!this.callEvent("onBeforeSelect", [id])) { return false; } } this.unselect(); selectedId = id; if (!this._skip_refresh) { this.refresh(id); this.callEvent("onAfterSelect", [id]); } } return selectedId; }, getSelectedId: function() { return selectedId; }, isSelected: function(id) { return id == selectedId; }, unselect: function(id) { var id = id || selectedId; if (!id) return; selectedId = null; if (!this._skip_refresh) { this.refresh(id); unselect.call(this, id); } } }; } function isHeadless(gantt2) { return env.isNode || !gantt2.$root; } const storeRenderCreator = function(name, gantt2) { const store = gantt2.getDatastore(name); const itemRepainter = { renderItem: function(id, renderer) { const renders = renderer.getLayers(); const item = store.getItem(id); if (item && store.isVisible(id)) { for (let i = 0; i < renders.length; i++) renders[i].render_item(item); } }, renderItems: function(renderer) { const renderers = renderer.getLayers(); for (let i = 0; i < renderers.length; i++) { renderers[i].clear(); } let allData = null; const loadedRanges = {}; for (let i = 0; i < renderers.length; i++) { const layer = renderers[i]; let layerData; if (layer.get_visible_range) { var range = layer.get_visible_range(store); if (range.start !== void 0 && range.end !== void 0) { var key = range.start + " - " + range.end; if (loadedRanges[key]) { layerData = loadedRanges[key]; } else { layerData = store.getIndexRange(range.start, range.end); loadedRanges[key] = layerData; } } else if (range.ids !== void 0) { layerData = range.ids.map(function(id) { return store.getItem(id); }); } else { throw new Error("Invalid range returned from 'getVisibleRange' of the layer"); } } else { if (!allData) { allData = store.getVisibleItems(); } layerData = allData; } if (layer.prepare_data) { layer.prepare_data(layerData); } renderers[i].render_items(layerData); } }, updateItems: function(layer) { if (layer.update_items) { let data2 = []; if (layer.get_visible_range) { var range = layer.get_visible_range(store); if (range.start !== void 0 && range.end !== void 0) { data2 = store.getIndexRange(range.start, range.end); } if (range.ids !== void 0) { let extraDataArr = range.ids.map(function(id) { return store.getItem(id); }); if (extraDataArr.length > 0) { extraDataArr = extraDataArr.filter((element) => element !== void 0); data2 = data2.concat(extraDataArr); } } if ((range.start == void 0 || range.end == void 0) && range.ids == void 0) { throw new Error("Invalid range returned from 'getVisibleRange' of the layer"); } } else { data2 = store.getVisibleItems(); } if (layer.prepare_data) { layer.prepare_data(data2, layer); } layer.update_items(data2); } } }; store.attachEvent("onStoreUpdated", function(id, item, action) { if (isHeadless(gantt2)) { return true; } const renderer = gantt2.$services.getService("layers").getDataRender(name); if (renderer) { renderer.onUpdateRequest = function(layer) { itemRepainter.updateItems(layer); }; } }); function skipRepaint(gantt3) { const state = gantt3.$services.getService("state"); if (state.getState("batchUpdate").batch_update) { return true; } else { return false; } } store.attachEvent("onStoreUpdated", function(id, item, action) { if (skipRepaint(gantt2)) { return; } if (!id || action == "move" || action == "delete") { store.callEvent("onBeforeRefreshAll", []); store.callEvent("onAfterRefreshAll", []); } else { store.callEvent("onBeforeRefreshItem", [item.id]); store.callEvent("onAfterRefreshItem", [item.id]); } }); store.attachEvent("onAfterRefreshAll", function() { if (isHeadless(gantt2)) { return true; } const renderer = gantt2.$services.getService("layers").getDataRender(name); if (renderer && !skipRepaint(gantt2)) { itemRepainter.renderItems(renderer); } }); store.attachEvent("onAfterRefreshItem", function(id) { if (isHeadless(gantt2)) { return true; } const renderer = gantt2.$services.getService("layers").getDataRender(name); if (renderer) { itemRepainter.renderItem(id, renderer); } }); store.attachEvent("onItemOpen", function() { if (isHeadless(gantt2) || store.isSilent()) { return true; } gantt2.render(); }); store.attachEvent("onItemClose", function() { if (isHeadless(gantt2) || store.isSilent()) { return true; } gantt2.render(); }); function refreshId(renders, oldId, newId, item) { for (let i = 0; i < renders.length; i++) { renders[i].change_id(oldId, newId); } } store.attachEvent("onIdChange", function(oldId, newId) { if (isHeadless(gantt2)) { return true; } store.callEvent("onBeforeIdChange", [oldId, newId]); if (skipRepaint(gantt2)) { return; } if (!store.isSilent()) { const renderer = gantt2.$services.getService("layers").getDataRender(name); if (renderer) { refreshId(renderer.getLayers(), oldId, newId, store.getItem(newId)); itemRepainter.renderItem(newId, renderer); } else { gantt2.render(); } } }); }; const datastoreRender = { bindDataStore: storeRenderCreator }; function getDatastores() { var storeNames = this.$services.getService("datastores"); var res = []; for (var i = 0; i < storeNames.length; i++) { var store = this.getDatastore(storeNames[i]); if (!store.$destroyed) { res.push(store); } } return res; } var createDatastoreFacade = function() { return { createDatastore: function(config2) { var $StoreType = (config2.type || "").toLowerCase() == "treedatastore" ? TreeDataStore : DataStore; if (config2) { var self2 = this; config2.openInitially = function() { return self2.config.open_tree_initially; }; config2.copyOnParse = function() { return self2.config.deepcopy_on_parse; }; } var store = new $StoreType(config2); this.mixin(store, createDataStoreSelectMixin(store)); if (config2.name) { var servicePrefix = "datastore:"; var storeAccessName = servicePrefix + config2.name; store.attachEvent("onDestroy", (function() { this.$services.dropService(storeAccessName); var storeList2 = this.$services.getService("datastores"); for (var i = 0; i < storeList2.length; i++) { if (storeList2[i] === config2.name) { storeList2.splice(i, 1); break; } } }).bind(this)); this.$services.dropService(storeAccessName); this.$services.setService(storeAccessName, function() { return store; }); var storeList = this.$services.getService("datastores"); if (!storeList) { storeList = []; this.$services.setService("datastores", function() { return storeList; }); storeList.push(config2.name); } else if (storeList.indexOf(config2.name) < 0) { storeList.push(config2.name); } datastoreRender.bindDataStore(config2.name, this); } return store; }, getDatastore: function(name) { return this.$services.getService("datastore:" + name); }, _getDatastores: getDatastores, refreshData: function() { var scrollState; if (!isHeadless(this)) { scrollState = this.getScrollState(); } this.callEvent("onBeforeDataRender", []); var stores = getDatastores.call(this); for (var i = 0; i < stores.length; i++) { stores[i].refresh(); } if (this.config.preserve_scroll && !isHeadless(this)) { if (scrollState.x || scrollState.y) { this.scrollTo(scrollState.x, scrollState.y); } const scrollbarsInfo = this.$layout.getScrollbarsInfo(); scrollbarsInfo.forEach((scroll_info) => { const scroll = this.$ui.getView(scroll_info.id); if (!scroll) return; const scrollbarNodeVisible = this.utils.dom.isChildOf(scroll.$view, this.$container); scroll_info.boundViews.forEach((viewName) => { const view = this.$ui.getView(viewName); if (scroll_info.y) { if (view && !scrollbarNodeVisible) { view.scrollTo(void 0, 0); } } }); }); } this.callEvent("onDataRender", []); }, isChildOf: function(childId, parentId) { return this.$data.tasksStore.isChildOf(childId, parentId); }, refreshTask: function(taskId, refresh_links) { var task = this.getTask(taskId); var self2 = this; function refreshLinks() { if (refresh_links !== void 0 && !refresh_links) return; for (var i = 0; i < task.$source.length; i++) { self2.refreshLink(task.$source[i]); } for (var i = 0; i < task.$target.length; i++) { self2.refreshLink(task.$target[i]); } } if (task && this.isTaskVisible(taskId)) { this.$data.tasksStore.refresh(taskId, !!this.getState("tasksDnd").drag_id || refresh_links === false); refreshLinks(); } else if (this.isTaskExists(taskId) && this.isTaskExists(this.getParent(taskId)) && !this._bulk_dnd) { this.refreshTask(this.getParent(taskId)); var hasSplitParent = false; this.eachParent(function(parent) { if (hasSplitParent || this.isSplitTask(parent)) { hasSplitParent = true; } }, taskId); if (hasSplitParent) { refreshLinks(); } } }, refreshLink: function(linkId) { this.$data.linksStore.refresh(linkId, !!this.getState("tasksDnd").drag_id); }, silent: function(code) { var gantt2 = this; gantt2.$data.tasksStore.silent(function() { gantt2.$data.linksStore.silent(function() { code(); }); }); }, clearAll: function() { var stores = getDatastores.call(this); for (var i = 0; i < stores.length; i++) { stores[i].silent(function() { stores[i].clearAll(); }); } for (var i = 0; i < stores.length; i++) { stores[i].clearAll(); } this._update_flags(); this.userdata = {}; this.callEvent("onClear", []); this.render(); }, _clear_data: function() { this.$data.tasksStore.clearAll(); this.$data.linksStore.clearAll(); this._update_flags(); this.userdata = {}; }, selectTask: function(id) { var store = this.$data.tasksStore; if (!this.config.select_task) return false; id = replaceValidZeroId(id, this.config.root_id); if (id) { let oldSelectId = this.getSelectedId(); store._skipResourceRepaint = true; store.select(id); store._skipResourceRepaint = false; if (oldSelectId && store.pull[oldSelectId].$split_subtask && oldSelectId != id) { this.refreshTask(oldSelectId); } if (store.pull[id].$split_subtask && oldSelectId != id) { this.refreshTask(id); } } return store.getSelectedId(); }, unselectTask: function(id) { var store = this.$data.tasksStore; store.unselect(id); if (id && store.pull[id].$split_subtask) { this.refreshTask(id); } }, isSelectedTask: function(id) { return this.$data.tasksStore.isSelected(id); }, getSelectedId: function() { return this.$data.tasksStore.getSelectedId(); } }; }; function createFacade() { var res = mixin({}, createDatastoreFacade()); mixin(res, createTasksDatastoreFacade()); mixin(res, createLinksStoreFacade()); return res; } const facadeFactory = { create: createFacade }; function resolveConfigRange(unit, gantt2) { var range = { start_date: null, end_date: null }; if (gantt2.config.start_date && gantt2.config.end_date) { range.start_date = gantt2.date[unit + "_start"](new Date(gantt2.config.start_date)); var end = new Date(gantt2.config.end_date); var start_interval = gantt2.date[unit + "_start"](new Date(end)); if (+end != +start_interval) { end = gantt2.date.add(start_interval, 1, unit); } else { end = start_interval; } range.end_date = end; } return range; } function _scale_range_unit(gantt2) { const primaryScale = new ScaleHelper(gantt2).primaryScale(); let unit = primaryScale.unit; let step = primaryScale.step; if (gantt2.config.scale_offset_minimal) { const helper = new ScaleHelper(gantt2); const scales = [helper.primaryScale()].concat(helper.getAdditionalScales()); helper.sortScales(scales); unit = scales[scales.length - 1].unit; step = scales[scales.length - 1].step || 1; } return { unit, step }; } function _init_tasks_range(gantt2) { var cfg = _scale_range_unit(gantt2); var unit = cfg.unit, step = cfg.step; var range = resolveConfigRange(unit, gantt2); if (!(range.start_date && range.end_date)) { var onlyProjectTasks = true; var tasks2 = gantt2.getTaskByTime(); for (var i = 0; i < tasks2.length; i++) { var task = tasks2[i]; if (task.type !== gantt2.config.types.project) { onlyProjectTasks = false; break; } } if (tasks2.length && onlyProjectTasks) { var start_date = tasks2[0].start_date; var end_date = gantt2.date.add(start_date, 1, gantt2.config.duration_unit); range = { start_date: new Date(start_date), end_date: new Date(end_date) }; } else { range = gantt2.getSubtaskDates(); } if (!range.start_date || !range.end_date) { range = { start_date: /* @__PURE__ */ new Date(), end_date: /* @__PURE__ */ new Date() }; } gantt2.eachTask(function(task2) { if (gantt2.config.deadlines && task2.deadline) { extendRangeForDates(range, task2.deadline, task2.deadline); } if (task2.constraint_date && task2.constraint_type) { if (gantt2._getAutoSchedulingConfig().apply_constraints && gantt2.config.constraint_types && task2.constraint_type !== gantt2.config.constraint_types.ASAP && task2.constraint_type !== gantt2.config.constraint_types.ALAP) { extendRangeForDates(range, task2.constraint_date, task2.constraint_date); } } if (gantt2.config.baselines && task2.baselines) { task2.baselines.forEach(function(baseline) { extendRangeForDates(range, baseline.start_date, baseline.end_date); }); } }); range.start_date = gantt2.date[unit + "_start"](range.start_date); range.start_date = gantt2.calculateEndDate({ start_date: gantt2.date[unit + "_start"](range.start_date), duration: -1, unit, step }); range.end_date = gantt2.date[unit + "_start"](range.end_date); range.end_date = gantt2.calculateEndDate({ start_date: range.end_date, duration: 2, unit, step }); } gantt2._min_date = range.start_date; gantt2._max_date = range.end_date; } function extendRangeForDates(range, start_date, end_date) { if (start_date < range.start_date) { range.start_date = new Date(start_date); } if (end_date > range.end_date) { range.end_date = new Date(end_date); } } function _adjust_scales(gantt2) { if (gantt2.config.fit_tasks) { var old_min = +gantt2._min_date, old_max = +gantt2._max_date; if (+gantt2._min_date != old_min || +gantt2._max_date != old_max) { gantt2.render(); gantt2.callEvent("onScaleAdjusted", []); return true; } } return false; } function updateTasksRange(gantt2) { _init_tasks_range(gantt2); _adjust_scales(gantt2); } function copyLinkIdsArray(gantt2, linkIds, targetHash) { for (var i = 0; i < linkIds.length; i++) { if (gantt2.isLinkExists(linkIds[i])) { targetHash[linkIds[i]] = gantt2.getLink(linkIds[i]); } } } function copyLinkIds(gantt2, task, targetHash) { copyLinkIdsArray(gantt2, task.$source, targetHash); copyLinkIdsArray(gantt2, task.$target, targetHash); } function getSubtreeLinks(gantt2, rootId) { var res = {}; if (gantt2.isTaskExists(rootId)) { copyLinkIds(gantt2, gantt2.getTask(rootId), res); } gantt2.eachTask(function(child) { copyLinkIds(gantt2, child, res); }, rootId); return res; } function getSubtreeTasks(gantt2, rootId) { var res = {}; gantt2.eachTask(function(child) { res[child.id] = child; }, rootId); return res; } const treeHelper = { getSubtreeLinks, getSubtreeTasks }; function initDataStores(gantt2) { var facade = facadeFactory.create(); mixin(gantt2, facade); var tasksStore = gantt2.createDatastore({ name: "task", type: "treeDatastore", rootId: function() { return gantt2.config.root_id; }, initItem: bind(_init_task, gantt2), getConfig: function() { return gantt2.config; } }); var linksStore = gantt2.createDatastore({ name: "link", initItem: bind(_init_link, gantt2) }); gantt2.attachEvent("onDestroy", function() { tasksStore.destructor(); linksStore.destructor(); }); gantt2.attachEvent("onLinkValidation", function(link) { if (gantt2.isLinkExists(link.id) || link.id === "predecessor_generated") { return true; } var source = gantt2.getTask(link.source); var taskLinks = source.$source; for (var i = 0; i < taskLinks.length; i++) { var existingLink = gantt2.getLink(taskLinks[i]); var sourceMatch = link.source == existingLink.source; var targetMatch = link.target == existingLink.target; var typeMatch = link.type == existingLink.type; if (sourceMatch && targetMatch && typeMatch) { return false; } } return true; }); tasksStore.attachEvent("onBeforeRefreshAll", function() { if (tasksStore._skipTaskRecalculation) { return; } var order = tasksStore.getVisibleItems(); for (var i = 0; i < order.length; i++) { var item = order[i]; item.$index = i; item.$local_index = gantt2.getTaskIndex(item.id); gantt2.resetProjectDates(item); } }); tasksStore.attachEvent("onFilterItem", function(id, task) { if (gantt2.config.show_tasks_outside_timescale) { return true; } var min = null, max = null; if (gantt2.config.start_date && gantt2.config.end_date) { if (gantt2._isAllowedUnscheduledTask(task)) return true; min = gantt2.config.start_date.valueOf(); max = gantt2.config.end_date.valueOf(); if (+task.start_date > max || +task.end_date < +min) return false; } return true; }); tasksStore.attachEvent("onIdChange", function(oldId, newId) { gantt2._update_flags(oldId, newId); var changedTask = gantt2.getTask(newId); if (!tasksStore.isSilent()) { if (changedTask.$split_subtask || changedTask.rollup) { gantt2.eachParent(function(parent) { gantt2.refreshTask(parent.id); }, newId); } } }); tasksStore.attachEvent("onAfterUpdate", function(id) { gantt2._update_parents(id); if (gantt2.getState("batchUpdate").batch_update) { return true; } var task = tasksStore.getItem(id); if (!task.$source) task.$source = []; for (var i = 0; i < task.$source.length; i++) { linksStore.refresh(task.$source[i]); } if (!task.$target) task.$target = []; for (var i = 0; i < task.$target.length; i++) { linksStore.refresh(task.$target[i]); } }); tasksStore.attachEvent("onBeforeItemMove", function(sid, parent, tindex) { if (isPlaceholderTask(sid, gantt2, tasksStore)) { console.log("The placeholder task cannot be moved to another position."); return false; } return true; }); tasksStore.attachEvent("onAfterItemMove", function(sid, parent, tindex) { var source = gantt2.getTask(sid); if (this.getNextSibling(sid) !== null) { source.$drop_target = this.getNextSibling(sid); } else if (this.getPrevSibling(sid) !== null) { source.$drop_target = "next:" + this.getPrevSibling(sid); } else { source.$drop_target = "next:null"; } }); tasksStore.attachEvent("onStoreUpdated", function(id, item, action) { if (action == "delete") { gantt2._update_flags(id, null); } var state = gantt2.$services.getService("state"); if (state.getState("batchUpdate").batch_update) { return; } if (gantt2.config.fit_tasks && action !== "paint") { var oldState = gantt2.getState(); updateTasksRange(gantt2); var newState = gantt2.getState(); if (+oldState.min_date != +newState.min_date || +oldState.max_date != +newState.max_date) { gantt2.render(); gantt2.callEvent("onScaleAdjusted", []); return true; } } if (action == "add" || action == "move" || action == "delete") { if (gantt2.$layout) { if (this.$config.name == "task" && (action == "add" || action == "delete")) { if (this._skipTaskRecalculation != "lightbox") { this._skipTaskRecalculation = true; } } gantt2.$layout.resize(); } } else if (!id) { linksStore.refresh(); } }); linksStore.attachEvent("onAfterAdd", function(id, link) { linksStore.sync_link(link); }); linksStore.attachEvent("onAfterUpdate", function(id, link) { sync_links(); }); linksStore.attachEvent("onAfterDelete", function(id, link) { sync_link_delete(link); }); linksStore.attachEvent("onAfterSilentDelete", function(id, link) { sync_link_delete(link); }); linksStore.attachEvent("onBeforeIdChange", function(oldId, newId) { sync_link_delete(gantt2.mixin({ id: oldId }, gantt2.$data.linksStore.getItem(newId))); linksStore.sync_link(gantt2.$data.linksStore.getItem(newId)); }); function checkLinkedTaskVisibility(taskId) { var isVisible2 = gantt2.isTaskVisible(taskId); if (!isVisible2 && gantt2.isTaskExists(taskId)) { var parent = gantt2.getParent(taskId); if (gantt2.isTaskExists(parent) && gantt2.isTaskVisible(parent)) { parent = gantt2.getTask(parent); if (gantt2.isSplitTask(parent)) { isVisible2 = true; } } } return isVisible2; } linksStore.attachEvent("onFilterItem", function(id, link) { if (!gantt2.config.show_links) { return false; } var sourceVisible = checkLinkedTaskVisibility(link.source); var targetVisible = checkLinkedTaskVisibility(link.target); if (!(sourceVisible && targetVisible) || gantt2._isAllowedUnscheduledTask(gantt2.getTask(link.source)) || gantt2._isAllowedUnscheduledTask(gantt2.getTask(link.target))) return false; return gantt2.callEvent("onBeforeLinkDisplay", [id, link]); }); (function() { var deletedLinks = {}; gantt2.attachEvent("onBeforeTaskDelete", function(id, item) { deletedLinks[id] = treeHelper.getSubtreeLinks(gantt2, id); return true; }); gantt2.attachEvent("onAfterTaskDelete", function(id, item) { if (deletedLinks[id]) { gantt2.$data.linksStore.silent(function() { for (var i in deletedLinks[id]) { if (gantt2.isLinkExists(i)) { gantt2.$data.linksStore.removeItem(i); } sync_link_delete(deletedLinks[id][i]); } deletedLinks[id] = null; }); } }); })(); gantt2.attachEvent("onAfterLinkDelete", function(id, link) { if (gantt2.isTaskExists(link.source)) { gantt2.refreshTask(link.source); } if (gantt2.isTaskExists(link.target)) { gantt2.refreshTask(link.target); } }); gantt2.attachEvent("onParse", sync_links); mapEvents({ source: linksStore, target: gantt2, events: { onItemLoading: "onLinkLoading", onBeforeAdd: "onBeforeLinkAdd", onAfterAdd: "onAfterLinkAdd", onBeforeUpdate: "onBeforeLinkUpdate", onAfterUpdate: "onAfterLinkUpdate", onBeforeDelete: "onBeforeLinkDelete", onAfterDelete: "onAfterLinkDelete", onIdChange: "onLinkIdChange" } }); mapEvents({ source: tasksStore, target: gantt2, events: { onItemLoading: "onTaskLoading", onBeforeAdd: "onBeforeTaskAdd", onAfterAdd: "onAfterTaskAdd", onBeforeUpdate: "onBeforeTaskUpdate", onAfterUpdate: "onAfterTaskUpdate", onBeforeDelete: "onBeforeTaskDelete", onAfterDelete: "onAfterTaskDelete", onIdChange: "onTaskIdChange", onBeforeItemMove: "onBeforeTaskMove", onAfterItemMove: "onAfterTaskMove", onFilterItem: "onBeforeTaskDisplay", onItemOpen: "onTaskOpened", onItemClose: "onTaskClosed", onBeforeSelect: "onBeforeTaskSelected", onAfterSelect: "onTaskSelected", onAfterUnselect: "onTaskUnselected" } }); gantt2.$data = { tasksStore, linksStore }; linksStore.sync_link = function(link) { if (gantt2.isTaskExists(link.source)) { var sourceTask = gantt2.getTask(link.source); sourceTask.$source = sourceTask.$source || []; if (noDuplicateIds(link.id, sourceTask.$source)) { sourceTask.$source.push(link.id); } } if (gantt2.isTaskExists(link.target)) { var targetTask = gantt2.getTask(link.target); targetTask.$target = targetTask.$target || []; if (noDuplicateIds(link.id, targetTask.$target)) { targetTask.$target.push(link.id); } } }; function noDuplicateIds(id, array) { return array.indexOf(String(id)) === -1 && array.indexOf(Number(id)) === -1; } function sync_link_delete(link) { if (gantt2.isTaskExists(link.source)) { var sourceTask = gantt2.getTask(link.source); for (var i = 0; i < sourceTask.$source.length; i++) { if (sourceTask.$source[i] == link.id) { sourceTask.$source.splice(i, 1); break; } } } if (gantt2.isTaskExists(link.target)) { var targetTask = gantt2.getTask(link.target); for (var i = 0; i < targetTask.$target.length; i++) { if (targetTask.$target[i] == link.id) { targetTask.$target.splice(i, 1); break; } } } } function sync_links() { var task = null; var tasks2 = gantt2.$data.tasksStore.getItems(); for (var i = 0, len = tasks2.length; i < len; i++) { task = tasks2[i]; task.$source = []; task.$target = []; } var links = gantt2.$data.linksStore.getItems(); for (var i = 0, len = links.length; i < len; i++) { var link = links[i]; linksStore.sync_link(link); } } function mapEvents(conf) { var mapFrom = conf.source; var mapTo = conf.target; for (var i in conf.events) { (function(sourceEvent, targetEvent) { mapFrom.attachEvent(sourceEvent, function() { return mapTo.callEvent(targetEvent, Array.prototype.slice.call(arguments)); }, targetEvent); })(i, conf.events[i]); } } function _init_task(task) { if (!this.defined(task.id)) task.id = this.uid(); if (task.start_date) task.start_date = gantt2.date.parseDate(task.start_date, "parse_date"); if (task.end_date) task.end_date = gantt2.date.parseDate(task.end_date, "parse_date"); var duration = null; if (task.duration || task.duration === 0) { task.duration = duration = task.duration * 1; } if (duration) { if (task.start_date && !task.end_date) { task.end_date = this.calculateEndDate(task); } else if (!task.start_date && task.end_date) { task.start_date = this.calculateEndDate({ start_date: task.end_date, duration: -task.duration, task }); } } if (gantt2.config.deadlines !== false && task.deadline) { task.deadline = gantt2.date.parseDate(task.deadline, "parse_date"); } task.progress = Number(task.progress) || 0; if (this._isAllowedUnscheduledTask(task)) { this._set_default_task_timing(task); } this._init_task_timing(task); if (task.start_date && task.end_date) this.correctTaskWorkTime(task); task.$source = []; task.$target = []; var originalTask = this.$data.tasksStore.getItem(task.id); if (originalTask && !defined(task.open)) { task.$open = originalTask.$open; } if (task.parent === void 0) { task.parent = this.config.root_id; } if (task.open) { task.$open = true; } return task; } function _init_link(link) { if (!this.defined(link.id)) link.id = this.uid(); return link; } } class DataProcessorEvents { constructor(gantt2, dp) { this.$gantt = gantt2; this.$dp = dp; this._dataProcessorHandlers = []; } attach() { const dp = this.$dp; const gantt2 = this.$gantt; const cascadeDelete = {}; const clientSideDelete = (id) => this.clientSideDelete(id, dp, gantt2); function getTaskLinks(task) { let _links = []; if (task.$source) { _links = _links.concat(task.$source); } if (task.$target) { _links = _links.concat(task.$target); } return _links; } this._dataProcessorHandlers.push(gantt2.attachEvent("onAfterTaskAdd", function(id, item) { if (gantt2.isTaskExists(id)) { dp.setGanttMode("tasks"); dp.setUpdated(id, true, "inserted"); } })); this._dataProcessorHandlers.push(gantt2.attachEvent("onAfterTaskUpdate", function(id, item) { if (gantt2.isTaskExists(id)) { dp.setGanttMode("tasks"); dp.setUpdated(id, true); if (gantt2._sendTaskOrder) { gantt2._sendTaskOrder(id, item); } } })); this._dataProcessorHandlers.push(gantt2.attachEvent("onBeforeTaskDelete", function(id, item) { if (gantt2.config.cascade_delete) { cascadeDelete[id] = { tasks: treeHelper.getSubtreeTasks(gantt2, id), links: treeHelper.getSubtreeLinks(gantt2, id) }; } if (dp.deleteAfterConfirmation) { dp.setGanttMode("tasks"); dp.setUpdated(id, true, "deleted"); return false; } return true; })); this._dataProcessorHandlers.push(gantt2.attachEvent("onAfterTaskDelete", function(id, item) { dp.setGanttMode("tasks"); const needDbDelete = !clientSideDelete(id); const needCascadeDelete = gantt2.config.cascade_delete && cascadeDelete[id]; if (!needDbDelete && !needCascadeDelete) { return; } if (needCascadeDelete) { const dpMode = dp.updateMode; dp.setUpdateMode("off"); const cascade = cascadeDelete[id]; for (const i in cascade.tasks) { if (!clientSideDelete(i)) { dp.storeItem(cascade.tasks[i]); dp.setUpdated(i, true, "deleted"); } } dp.setGanttMode("links"); for (const i in cascade.links) { if (!clientSideDelete(i)) { dp.storeItem(cascade.links[i]); dp.setUpdated(i, true, "deleted"); } } cascadeDelete[id] = null; if (dpMode !== "off") { dp.sendAllData(); } dp.setGanttMode("tasks"); dp.setUpdateMode(dpMode); } if (needDbDelete) { dp.storeItem(item); if (!dp.deleteAfterConfirmation) { dp.setUpdated(id, true, "deleted"); } } if (dp.updateMode !== "off" && !dp._tSend) { dp.sendAllData(); } })); this._dataProcessorHandlers.push(gantt2.attachEvent("onAfterLinkUpdate", function(id, item) { if (gantt2.isLinkExists(id)) { dp.setGanttMode("links"); dp.setUpdated(id, true); } })); this._dataProcessorHandlers.push(gantt2.attachEvent("onAfterLinkAdd", function(id, item) { if (gantt2.isLinkExists(id)) { dp.setGanttMode("links"); dp.setUpdated(id, true, "inserted"); } })); this._dataProcessorHandlers.push(gantt2.attachEvent("onAfterLinkDelete", function(id, item) { dp.setGanttMode("links"); const needDbDelete = !clientSideDelete(id); if (!needDbDelete) { return; } dp.storeItem(item); dp.setUpdated(id, true, "deleted"); })); this._dataProcessorHandlers.push(gantt2.attachEvent("onRowDragEnd", function(id, target) { gantt2._sendTaskOrder(id, gantt2.getTask(id)); })); let tasks2 = null; let links = null; this._dataProcessorHandlers.push(gantt2.attachEvent("onTaskIdChange", function(oldId, newId) { if (!dp._waitMode) { return; } const children = gantt2.getChildren(newId); if (children.length) { tasks2 = tasks2 || {}; for (let i = 0; i < children.length; i++) { const ch = this.getTask(children[i]); tasks2[ch.id] = ch; } } const item = this.getTask(newId); const itemLinks = getTaskLinks(item); if (itemLinks.length) { links = links || {}; for (let i = 0; i < itemLinks.length; i++) { const link = this.getLink(itemLinks[i]); links[link.id] = link; } } })); dp.attachEvent("onAfterUpdateFinish", function() { if (tasks2 || links) { gantt2.batchUpdate(function() { for (const id in tasks2) { gantt2.updateTask(tasks2[id].id); } for (const id in links) { gantt2.updateLink(links[id].id); } tasks2 = null; links = null; }); if (tasks2) { gantt2._dp.setGanttMode("tasks"); } else { gantt2._dp.setGanttMode("links"); } } }); dp.attachEvent("onBeforeDataSending", function() { if (this._tMode === "CUSTOM") { return true; } let url = this._serverProcessor; if (this._tMode === "REST-JSON" || this._tMode === "REST") { const mode = this._ganttMode; url = url.substring(0, url.indexOf("?") > -1 ? url.indexOf("?") : url.length); this.serverProcessor = url + (url.slice(-1) === "/" ? "" : "/") + mode; } else { const pluralizedMode = this._ganttMode + "s"; this.serverProcessor = url + gantt2.ajax.urlSeparator(url) + "gantt_mode=" + pluralizedMode; } return true; }); dp.attachEvent("insertCallback", function insertCallback(upd, id, parent, mode) { const data2 = upd.data || gantt2.xml._xmlNodeToJSON(upd.firstChild); const methods = { add: gantt2.addTask, isExist: gantt2.isTaskExists }; if (mode === "links") { methods.add = gantt2.addLink; methods.isExist = gantt2.isLinkExists; } if (methods.isExist.call(gantt2, id)) { return; } data2.id = id; methods.add.call(gantt2, data2); }); dp.attachEvent("updateCallback", function updateCallback(upd, id) { const data2 = upd.data || gantt2.xml._xmlNodeToJSON(upd.firstChild); if (!gantt2.isTaskExists(id)) { return; } const objData = gantt2.getTask(id); for (const key in data2) { let property = data2[key]; switch (key) { case "id": continue; case "start_date": case "end_date": property = gantt2.defined(gantt2.templates.xml_date) ? gantt2.templates.xml_date(property) : gantt2.templates.parse_date(property); break; case "duration": objData.end_date = gantt2.calculateEndDate({ start_date: objData.start_date, duration: property, task: objData }); break; } objData[key] = property; } gantt2.updateTask(id); gantt2.refreshData(); }); dp.attachEvent("deleteCallback", function deleteCallback(upd, id, parent, mode) { const methods = { delete: gantt2.deleteTask, isExist: gantt2.isTaskExists }; if (mode === "links") { methods.delete = gantt2.deleteLink; methods.isExist = gantt2.isLinkExists; } else if (mode === "assignment") { methods.delete = function(val) { gantt2.$data.assignmentsStore.remove(val); }; methods.isExist = function(val) { return gantt2.$data.assignmentsStore.exists(val); }; } if (methods.isExist.call(gantt2, id)) { methods.delete.call(gantt2, id); } }); this.handleResourceCRUD(dp, gantt2); this.handleResourceAssignmentCRUD(dp, gantt2); this.handleBaselineCRUD(dp, gantt2); } clientSideDelete(id, dp, gantt2) { const updated = dp.updatedRows.slice(); let clientOnly = false; if (gantt2.getUserData(id, "!nativeeditor_status", dp._ganttMode) === "true_deleted") { clientOnly = true; dp.setUpdated(id, false); } for (let i = 0; i < updated.length && !dp._in_progress[id]; i++) { if (updated[i] === id) { if (gantt2.getUserData(id, "!nativeeditor_status", dp._ganttMode) === "inserted") { clientOnly = true; } dp.setUpdated(id, false); } } return clientOnly; } handleResourceAssignmentCRUD(dp, gantt2) { if (!gantt2.config.resources || gantt2.config.resources.dataprocessor_assignments !== true) { return; } const assignmentsStore = gantt2.getDatastore(gantt2.config.resource_assignment_store); const insertedTasks = {}; const pendingAssignments = {}; gantt2.attachEvent("onBeforeTaskAdd", function(id, task) { insertedTasks[id] = true; return true; }); function putAssignmentToQueue(item) { pendingAssignments[item.id] = item; insertedTasks[item.task_id] = true; } function insertResourceAssignment(assignment) { const id = assignment.id; if (assignmentsStore.exists(id)) { dp.setGanttMode("assignment"); dp.setUpdated(id, true, "inserted"); } delete pendingAssignments[id]; } gantt2.attachEvent("onTaskIdChange", function(id, newId) { delete insertedTasks[id]; }); assignmentsStore.attachEvent("onAfterAdd", (id, item) => { if (insertedTasks[item.task_id]) { putAssignmentToQueue(item); } else { insertResourceAssignment(item); } }); assignmentsStore.attachEvent("onAfterUpdate", (id, item) => { if (assignmentsStore.exists(id)) { if (pendingAssignments[id]) { insertResourceAssignment(item); } else { dp.setGanttMode("assignment"); dp.setUpdated(id, true); } } }); assignmentsStore.attachEvent("onAfterDelete", (id, item) => { dp.setGanttMode("assignment"); const needDbDelete = !this.clientSideDelete(id, dp, gantt2); if (!needDbDelete) { return; } dp.storeItem(item); dp.setUpdated(id, true, "deleted"); }); } handleResourceCRUD(dp, gantt2) { if (!gantt2.config.resources || gantt2.config.resources.dataprocessor_resources !== true) { return; } const resourcesStore = gantt2.getDatastore(gantt2.config.resource_store); function insertResource(resource) { const id = resource.id; if (resourcesStore.exists(id)) { dp.setGanttMode("resource"); dp.setUpdated(id, true, "inserted"); } } resourcesStore.attachEvent("onAfterAdd", (id, item) => { insertResource(item); }); resourcesStore.attachEvent("onAfterUpdate", (id, item) => { if (resourcesStore.exists(id)) { dp.setGanttMode("resource"); dp.setUpdated(id, true); } }); resourcesStore.attachEvent("onAfterDelete", (id, item) => { dp.setGanttMode("resource"); const needDbDelete = !this.clientSideDelete(id, dp, gantt2); if (!needDbDelete) { return; } dp.storeItem(item); dp.setUpdated(id, true, "deleted"); }); } handleBaselineCRUD(dp, gantt2) { if (!gantt2.config.baselines || gantt2.config.baselines.dataprocessor_baselines !== true) { return; } const baselineStore = gantt2.getDatastore(gantt2.config.baselines.datastore); function insertResource(resource) { const id = resource.id; if (baselineStore.exists(id)) { dp.setGanttMode("baseline"); dp.setUpdated(id, true, "inserted"); } } baselineStore.attachEvent("onAfterAdd", (id, item) => { insertResource(item); }); baselineStore.attachEvent("onAfterUpdate", (id, item) => { if (baselineStore.exists(id)) { dp.setGanttMode("baseline"); dp.setUpdated(id, true); } }); baselineStore.attachEvent("onAfterDelete", (id, item) => { dp.setGanttMode("baseline"); const needDbDelete = !this.clientSideDelete(id, dp, gantt2); if (!needDbDelete) { return; } dp.storeItem(item); dp.setUpdated(id, true, "deleted"); }); } detach() { forEach(this._dataProcessorHandlers, (e) => { this.$gantt.detachEvent(e); }); this._dataProcessorHandlers = []; } } function extendGantt(gantt2, dp) { gantt2.getUserData = function(id, name, store) { if (!this.userdata) { this.userdata = {}; } this.userdata[store] = this.userdata[store] || {}; if (this.userdata[store][id] && this.userdata[store][id][name]) { return this.userdata[store][id][name]; } return ""; }; gantt2.setUserData = function(id, name, value, store) { if (!this.userdata) { this.userdata = {}; } this.userdata[store] = this.userdata[store] || {}; this.userdata[store][id] = this.userdata[store][id] || {}; this.userdata[store][id][name] = value; }; gantt2._change_id = function(oldId, newId) { switch (this._dp._ganttMode) { case "task": this.changeTaskId(oldId, newId); break; case "link": this.changeLinkId(oldId, newId); break; case "assignment": this.$data.assignmentsStore.changeId(oldId, newId); break; case "resource": this.$data.resourcesStore.changeId(oldId, newId); break; case "baseline": this.$data.baselineStore.changeId(oldId, newId); break; default: throw new Error(`Invalid mode of the dataProcessor after database id is received: ${this._dp._ganttMode}, new id: ${newId}`); } }; gantt2._row_style = function(rowId, classname) { if (this._dp._ganttMode !== "task") { return; } if (!gantt2.isTaskExists(rowId)) { return; } const task = gantt2.getTask(rowId); task.$dataprocessor_class = classname; gantt2.refreshTask(rowId); }; gantt2._delete_task = function(rowId, node) { }; gantt2._sendTaskOrder = function(id, item) { if (item.$drop_target) { this._dp.setGanttMode("task"); this.getTask(id).target = item.$drop_target; this._dp.setUpdated(id, true, "order"); delete this.getTask(id).$drop_target; } }; gantt2.setDp = function() { this._dp = dp; }; gantt2.setDp(); } const _SimpleStorage = class _SimpleStorage { constructor() { this.clear = () => { this._storage = {}; }; this.storeItem = (item) => { this._storage[item.id] = copy(item); }; this.getStoredItem = (id) => this._storage[id] || null; this._storage = {}; } }; _SimpleStorage.create = () => new _SimpleStorage(); let SimpleStorage = _SimpleStorage; function createDataProcessor(config2) { let router; let tMode; let headers; if (config2 instanceof Function) { router = config2; } else if (config2.hasOwnProperty("router")) { router = config2.router; } else if (config2.hasOwnProperty("assignment") || config2.hasOwnProperty("baseline") || config2.hasOwnProperty("link") || config2.hasOwnProperty("task")) { router = config2; } else if (config2.hasOwnProperty("headers")) { headers = config2.headers; } if (router) { tMode = "CUSTOM"; } else { tMode = config2.mode || "REST-JSON"; } const gantt2 = this; const dp = new DataProcessor$1(config2.url); dp.init(gantt2); dp.setTransactionMode({ mode: tMode, router, headers }, config2.batchUpdate); if (config2.deleteAfterConfirmation) { dp.deleteAfterConfirmation = config2.deleteAfterConfirmation; } return dp; } let DataProcessor$1 = class DataProcessor { constructor(serverProcessorURL) { this.serverProcessor = serverProcessorURL; this.action_param = "!nativeeditor_status"; this.updatedRows = []; this.autoUpdate = true; this.updateMode = "cell"; this._headers = null; this._payload = null; this._postDelim = "_"; this._routerParametersFormat = "parameters"; this._waitMode = 0; this._in_progress = {}; this._storage = SimpleStorage.create(); this._invalid = {}; this.messages = []; this.styles = { updated: "font-weight:bold;", inserted: "font-weight:bold;", deleted: "text-decoration : line-through;", invalid: "background-color:FFE0E0;", invalid_cell: "border-bottom:2px solid red;", error: "color:red;", clear: "font-weight:normal;text-decoration:none;" }; this.enableUTFencoding(true); makeEventable(this); } setTransactionMode(mode, total) { if (typeof mode === "object") { this._tMode = mode.mode || this._tMode; if (defined(mode.headers)) { this._headers = mode.headers; } if (defined(mode.payload)) { this._payload = mode.payload; } this._tSend = !!total; } else { this._tMode = mode; this._tSend = total; } if (this._tMode === "REST") { this._tSend = false; } if (this._tMode === "JSON" || this._tMode === "REST-JSON") { this._tSend = false; this._serializeAsJson = true; this._headers = this._headers || {}; this._headers["Content-Type"] = "application/json"; } else { if (this._headers && !this._headers["Content-Type"]) { this._headers["Content-Type"] = "application/x-www-form-urlencoded"; } } if (this._tMode === "CUSTOM") { this._tSend = false; this._router = mode.router; } } escape(data2) { if (this._utf) { return encodeURIComponent(data2); } else { return escape(data2); } } enableUTFencoding(mode) { this._utf = !!mode; } getSyncState() { return !this.updatedRows.length; } setUpdateMode(mode, dnd) { this.autoUpdate = mode === "cell"; this.updateMode = mode; this.dnd = dnd; } ignore(code, master) { this._silent_mode = true; code.call(master || scope); this._silent_mode = false; } setUpdated(rowId, state, mode) { if (this._silent_mode) { return; } const ind = this.findRow(rowId); mode = mode || "updated"; const existing = this.$gantt.getUserData(rowId, this.action_param, this._ganttMode); if (existing && mode === "updated") { mode = existing; } if (state) { this.set_invalid(rowId, false); this.updatedRows[ind] = rowId; this.$gantt.setUserData(rowId, this.action_param, mode, this._ganttMode); if (this._in_progress[rowId]) { this._in_progress[rowId] = "wait"; } } else { if (!this.is_invalid(rowId)) { this.updatedRows.splice(ind, 1); this.$gantt.setUserData(rowId, this.action_param, "", this._ganttMode); } } this.markRow(rowId, state, mode); if (state && this.autoUpdate) { this.sendData(rowId); } } markRow(id, state, mode) { let str = ""; const invalid = this.is_invalid(id); if (invalid) { str = this.styles[invalid]; state = true; } if (this.callEvent("onRowMark", [id, state, mode, invalid])) { str = this.styles[state ? mode : "clear"] + " " + str; this.$gantt[this._methods[0]](id, str); if (invalid && invalid.details) { str += this.styles[invalid + "_cell"]; for (let i = 0; i < invalid.details.length; i++) { if (invalid.details[i]) { this.$gantt[this._methods[1]](id, i, str); } } } } } getActionByState(state) { if (state === "inserted") { return "create"; } if (state === "updated") { return "update"; } if (state === "deleted") { return "delete"; } return "update"; } getState(id) { return this.$gantt.getUserData(id, this.action_param, this._ganttMode); } is_invalid(id) { return this._invalid[id]; } set_invalid(id, mode, details) { if (details) { mode = { value: mode, details, toString: function() { return this.value.toString(); } }; } this._invalid[id] = mode; } checkBeforeUpdate(rowId) { return true; } sendData(rowId) { if (this.$gantt.editStop) { this.$gantt.editStop(); } if (typeof rowId === "undefined" || this._tSend) { const pendingUpdateModes = []; if (this.modes) { const knownModes = ["task", "link", "assignment", "baseline"]; knownModes.forEach((mode) => { if (this.modes[mode] && this.modes[mode].updatedRows.length) { pendingUpdateModes.push(mode); } }); } if (pendingUpdateModes.length) { for (let i = 0; i < pendingUpdateModes.length; i++) { this.setGanttMode(pendingUpdateModes[i]); this.sendAllData(); } return; } else { return this.sendAllData(); } } if (this._in_progress[rowId]) { return false; } this.messages = []; if (!this.checkBeforeUpdate(rowId) && this.callEvent("onValidationError", [rowId, this.messages])) { return false; } this._beforeSendData(this._getRowData(rowId), rowId); } serialize(data2, id) { if (this._serializeAsJson) { return this._serializeAsJSON(data2); } if (typeof data2 === "string") { return data2; } if (typeof id !== "undefined") { return this.serialize_one(data2, ""); } else { const stack = []; const keys = []; for (const key in data2) { if (data2.hasOwnProperty(key)) { stack.push(this.serialize_one(data2[key], key + this._postDelim)); keys.push(key); } } stack.push("ids=" + this.escape(keys.join(","))); if (this.$gantt.security_key) { stack.push("dhx_security=" + this.$gantt.security_key); } return stack.join("&"); } } serialize_one(data2, pref) { if (typeof data2 === "string") { return data2; } const stack = []; let serialized = ""; for (const key in data2) if (data2.hasOwnProperty(key)) { if ((key === "id" || key == this.action_param) && this._tMode === "REST") { continue; } if (typeof data2[key] === "string" || typeof data2[key] === "number") { serialized = String(data2[key]); } else { serialized = JSON.stringify(data2[key]); } stack.push(this.escape((pref || "") + key) + "=" + this.escape(serialized)); } return stack.join("&"); } sendAllData() { if (!this.updatedRows.length) { return; } this.messages = []; let valid = true; this._forEachUpdatedRow(function(rowId) { valid = valid && this.checkBeforeUpdate(rowId); }); if (!valid && !this.callEvent("onValidationError", ["", this.messages])) { return false; } if (this._tSend) { this._sendData(this._getAllData()); } else { this._forEachUpdatedRow(function(rowId) { if (!this._in_progress[rowId]) { if (this.is_invalid(rowId)) { return; } this._beforeSendData(this._getRowData(rowId), rowId); } }); } } findRow(pattern) { let i = 0; for (i = 0; i < this.updatedRows.length; i++) { if (pattern == this.updatedRows[i]) { break; } } return i; } defineAction(name, handler) { if (!this._uActions) { this._uActions = {}; } this._uActions[name] = handler; } afterUpdateCallback(sid, tid, action, btag, ganttMode) { if (!this.$gantt) { return; } this.setGanttMode(ganttMode); const marker2 = sid; const correct = action !== "error" && action !== "invalid"; if (!correct) { this.set_invalid(sid, action); } if (this._uActions && this._uActions[action] && !this._uActions[action](btag)) { return delete this._in_progress[marker2]; } if (this._in_progress[marker2] !== "wait") { this.setUpdated(sid, false); } const originalSid = sid; switch (action) { case "inserted": case "insert": if (tid != sid) { this.setUpdated(sid, false); this.$gantt[this._methods[2]](sid, tid); sid = tid; } break; case "delete": case "deleted": if (!this.deleteAfterConfirmation || this._ganttMode !== "task") { this.$gantt.setUserData(sid, this.action_param, "true_deleted", this._ganttMode); this.$gantt[this._methods[3]](sid); delete this._in_progress[marker2]; return this.callEvent("onAfterUpdate", [sid, action, tid, btag]); } else { if (this._ganttMode === "task" && this.$gantt.isTaskExists(sid)) { this.$gantt.setUserData(sid, this.action_param, "true_deleted", this._ganttMode); const task = this.$gantt.getTask(sid); this.$gantt.silent(() => { this.$gantt.deleteTask(sid); }); this.$gantt.callEvent("onAfterTaskDelete", [sid, task]); this.$gantt.render(); delete this._in_progress[marker2]; } return this.callEvent("onAfterUpdate", [sid, action, tid, btag]); } } if (this._in_progress[marker2] !== "wait") { if (correct) { this.$gantt.setUserData(sid, this.action_param, "", this._ganttMode); } delete this._in_progress[marker2]; } else { delete this._in_progress[marker2]; this.setUpdated(tid, true, this.$gantt.getUserData(sid, this.action_param, this._ganttMode)); } this.callEvent("onAfterUpdate", [originalSid, action, tid, btag]); } afterUpdate(that, xml, id) { let _xml; if (arguments.length === 3) { _xml = arguments[1]; } else { _xml = arguments[4]; } let mode = this.getGanttMode(); const reqUrl = _xml.filePath || _xml.url; if (this._tMode !== "REST" && this._tMode !== "REST-JSON") { if (reqUrl.indexOf("gantt_mode=links") !== -1) { mode = "link"; } else if (reqUrl.indexOf("gantt_mode=assignments") !== -1) { mode = "assignment"; } else if (reqUrl.indexOf("gantt_mode=baselines") !== -1) { mode = "baseline"; } else { mode = "task"; } } else { if (reqUrl.indexOf("/link") >= 0) { mode = "link"; } else if (reqUrl.indexOf("/assignment") >= 0) { mode = "assignment"; } else if (reqUrl.indexOf("/baseline") >= 0) { mode = "baseline"; } else { mode = "task"; } } this.setGanttMode(mode); const ajax2 = this.$gantt.ajax; let tag; try { tag = JSON.parse(xml.xmlDoc.responseText); } catch (e) { if (!xml.xmlDoc.responseText.length) { tag = {}; } } const processCallback = (itemId) => { const action = tag.action || this.getState(itemId) || "updated"; const sid = tag.sid || itemId[0]; const tid = tag.tid || itemId[0]; that.afterUpdateCallback(sid, tid, action, tag, mode); }; if (tag) { if (Array.isArray(id) && id.length > 1) { id.forEach((taskId) => processCallback(taskId)); } else { processCallback(id); } that.finalizeUpdate(); this.setGanttMode(mode); return; } const top = ajax2.xmltop("data", xml.xmlDoc); if (!top) { return this.cleanUpdate(id); } const atag = ajax2.xpath("//data/action", top); if (!atag.length) { return this.cleanUpdate(id); } for (let i = 0; i < atag.length; i++) { const btag = atag[i]; const action = btag.getAttribute("type"); const sid = btag.getAttribute("sid"); const tid = btag.getAttribute("tid"); that.afterUpdateCallback(sid, tid, action, btag, mode); } that.finalizeUpdate(); } cleanUpdate(id) { if (id) { for (let i = 0; i < id.length; i++) { delete this._in_progress[id[i]]; } } } finalizeUpdate() { if (this._waitMode) { this._waitMode--; } this.callEvent("onAfterUpdateFinish", []); if (!this.updatedRows.length) { this.callEvent("onFullSync", []); } } init(gantt2) { if (this._initialized) { return; } this.$gantt = gantt2; if (this.$gantt._dp_init) { this.$gantt._dp_init(this); } this._setDefaultTransactionMode(); this.styles = { updated: "gantt_updated", order: "gantt_updated", inserted: "gantt_inserted", deleted: "gantt_deleted", delete_confirmation: "gantt_deleted", invalid: "gantt_invalid", error: "gantt_error", clear: "" }; this._methods = ["_row_style", "setCellTextStyle", "_change_id", "_delete_task"]; extendGantt(this.$gantt, this); const dataProcessorEvents = new DataProcessorEvents(this.$gantt, this); dataProcessorEvents.attach(); this.attachEvent("onDestroy", function() { delete this.setGanttMode; delete this._getRowData; delete this.$gantt._dp; delete this.$gantt._change_id; delete this.$gantt._row_style; delete this.$gantt._delete_task; delete this.$gantt._sendTaskOrder; delete this.$gantt; dataProcessorEvents.detach(); }); this.$gantt.callEvent("onDataProcessorReady", [this]); this._initialized = true; } setOnAfterUpdate(handler) { this.attachEvent("onAfterUpdate", handler); } setOnBeforeUpdateHandler(handler) { this.attachEvent("onBeforeDataSending", handler); } setAutoUpdate(interval, user) { interval = interval || 2e3; this._user = user || (/* @__PURE__ */ new Date()).valueOf(); this._needUpdate = false; this._updateBusy = false; this.attachEvent("onAfterUpdate", this.afterAutoUpdate); this.attachEvent("onFullSync", this.fullSync); setInterval(() => { this.loadUpdate(); }, interval); } afterAutoUpdate(sid, action, tid, xml_node) { if (action === "collision") { this._needUpdate = true; return false; } else { return true; } } fullSync() { if (this._needUpdate) { this._needUpdate = false; this.loadUpdate(); } return true; } getUpdates(url, callback) { const ajax2 = this.$gantt.ajax; if (this._updateBusy) { return false; } else { this._updateBusy = true; } ajax2.get(url, callback); } loadUpdate() { const ajax2 = this.$gantt.ajax; const version = this.$gantt.getUserData(0, "version", this._ganttMode); let url = this.serverProcessor + ajax2.urlSeparator(this.serverProcessor) + ["dhx_user=" + this._user, "dhx_version=" + version].join("&"); url = url.replace("editing=true&", ""); this.getUpdates(url, (xml) => { const vers = ajax2.xpath("//userdata", xml); this.$gantt.setUserData(0, "version", this._getXmlNodeValue(vers[0]), this._ganttMode); const updates = ajax2.xpath("//update", xml); if (updates.length) { this._silent_mode = true; for (let i = 0; i < updates.length; i++) { const status = updates[i].getAttribute("status"); const id = updates[i].getAttribute("id"); const parent = updates[i].getAttribute("parent"); switch (status) { case "inserted": this.callEvent("insertCallback", [updates[i], id, parent]); break; case "updated": this.callEvent("updateCallback", [updates[i], id, parent]); break; case "deleted": this.callEvent("deleteCallback", [updates[i], id, parent]); break; } } this._silent_mode = false; } this._updateBusy = false; }); } destructor() { this.callEvent("onDestroy", []); this.detachAllEvents(); this.updatedRows = []; this._in_progress = {}; this._invalid = {}; this._storage.clear(); this._storage = null; this._headers = null; this._payload = null; delete this._initialized; } setGanttMode(mode) { if (mode === "tasks") { mode = "task"; } else if (mode === "links") { mode = "link"; } const modes = this.modes || {}; const ganttMode = this.getGanttMode(); if (ganttMode) { modes[ganttMode] = { _in_progress: this._in_progress, _invalid: this._invalid, _storage: this._storage, updatedRows: this.updatedRows }; } let newState = modes[mode]; if (!newState) { newState = modes[mode] = { _in_progress: {}, _invalid: {}, _storage: SimpleStorage.create(), updatedRows: [] }; } this._in_progress = newState._in_progress; this._invalid = newState._invalid; this._storage = newState._storage; this.updatedRows = newState.updatedRows; this.modes = modes; this._ganttMode = mode; } getGanttMode() { return this._ganttMode; } storeItem(item) { this._storage.storeItem(item); } url(url) { this.serverProcessor = this._serverProcessor = url; } _beforeSendData(data2, rowId) { if (!this.callEvent("onBeforeUpdate", [rowId, this.getState(rowId), data2])) { return false; } this._sendData(data2, rowId); } _serializeAsJSON(data2) { if (typeof data2 === "string") { return data2; } const copy$1 = copy(data2); if (this._tMode === "REST-JSON") { delete copy$1.id; delete copy$1[this.action_param]; } return JSON.stringify(copy$1); } _applyPayload(url) { const ajax2 = this.$gantt.ajax; if (this._payload) { for (const key in this._payload) { url = url + ajax2.urlSeparator(url) + this.escape(key) + "=" + this.escape(this._payload[key]); } } return url; } _cleanupArgumentsBeforeSend(dataToSend) { let processedData; if (dataToSend[this.action_param] === void 0) { processedData = {}; for (const i in dataToSend) { processedData[i] = this._cleanupArgumentsBeforeSend(dataToSend[i]); } } else { processedData = this._cleanupItemBeforeSend(dataToSend); } return processedData; } _cleanupItemBeforeSend(updatedItem) { let output = null; if (updatedItem) { if (updatedItem[this.action_param] === "deleted") { output = {}; output.id = updatedItem.id; output[this.action_param] = updatedItem[this.action_param]; } else { output = updatedItem; } } return output; } _sendData(dataToSend, rowId) { if (!dataToSend) { return; } if (!this.callEvent("onBeforeDataSending", rowId ? [rowId, this.getState(rowId), dataToSend] : [null, null, dataToSend])) { return false; } if (rowId) { this._in_progress[rowId] = (/* @__PURE__ */ new Date()).valueOf(); } const ajax2 = this.$gantt.ajax; if (this._tMode === "CUSTOM") { const taskState = this.getState(rowId); const taskAction = this.getActionByState(taskState); delete dataToSend[this.action_param]; const ganttMode = this.getGanttMode(); const _onResolvedCreateUpdate = (tag) => { let action = taskState || "updated"; let sid = rowId; let tid = rowId; if (tag) { action = tag.action || taskState; sid = tag.sid || sid; tid = tag.id || tag.tid || tid; } this.afterUpdateCallback(sid, tid, action, tag, ganttMode); }; let actionPromise; if (this._router instanceof Function) { if (this._routerParametersFormat === "object") { const obj = { entity: ganttMode, action: taskAction, data: dataToSend, id: rowId }; actionPromise = this._router(obj); } else { actionPromise = this._router(ganttMode, taskAction, dataToSend, rowId); } } else if (this._router[ganttMode] instanceof Function) { actionPromise = this._router[ganttMode](taskAction, dataToSend, rowId); } else { const errorMsgStart = "Incorrect configuration of gantt.createDataProcessor"; const errorMsgEnd = ` You need to either add missing properties to the dataProcessor router object or to use a router function. See https://docs.dhtmlx.com/gantt/desktop__server_side.html#customrouting and https://docs.dhtmlx.com/gantt/api__gantt_createdataprocessor.html for details.`; if (!this._router[ganttMode]) { throw new Error(`${errorMsgStart}: router for the **${ganttMode}** entity is not defined. ${errorMsgEnd}`); } switch (taskState) { case "inserted": if (!this._router[ganttMode].create) { throw new Error(`${errorMsgStart}: **create** action for the **${ganttMode}** entity is not defined. ${errorMsgEnd}`); } actionPromise = this._router[ganttMode].create(dataToSend); break; case "deleted": if (!this._router[ganttMode].delete) { throw new Error(`${errorMsgStart}: **delete** action for the **${ganttMode}** entity is not defined. ${errorMsgEnd}`); } actionPromise = this._router[ganttMode].delete(rowId); break; default: if (!this._router[ganttMode].update) { throw new Error(`${errorMsgStart}: **update**" action for the **${ganttMode}** entity is not defined. ${errorMsgEnd}`); } actionPromise = this._router[ganttMode].update(dataToSend, rowId); break; } } if (actionPromise) { if (!actionPromise.then && (actionPromise.id === void 0 && actionPromise.tid === void 0 && actionPromise.action === void 0)) { throw new Error("Incorrect router return value. A Promise or a response object is expected"); } if (actionPromise.then) { actionPromise.then(_onResolvedCreateUpdate).catch((error) => { if (error && error.action) { _onResolvedCreateUpdate(error); } else { _onResolvedCreateUpdate({ action: "error", value: error }); } }); } else { _onResolvedCreateUpdate(actionPromise); } } else { _onResolvedCreateUpdate(null); } return; } let queryParams; queryParams = { callback: (xml) => { const ids = []; if (rowId) { ids.push(rowId); } else if (dataToSend) { for (const key in dataToSend) { ids.push(key); } } return this.afterUpdate(this, xml, ids); }, headers: this._headers }; const dhxVersion = "dhx_version=" + this.$gantt.getUserData(0, "version", this._ganttMode); const urlParams = this.serverProcessor + (this._user ? ajax2.urlSeparator(this.serverProcessor) + ["dhx_user=" + this._user, dhxVersion].join("&") : ""); let url = this._applyPayload(urlParams); let data2; switch (this._tMode) { case "GET": data2 = this._cleanupArgumentsBeforeSend(dataToSend); queryParams.url = url + ajax2.urlSeparator(url) + this.serialize(data2, rowId); queryParams.method = "GET"; break; case "POST": data2 = this._cleanupArgumentsBeforeSend(dataToSend); queryParams.url = url; queryParams.method = "POST"; queryParams.data = this.serialize(data2, rowId); break; case "JSON": data2 = {}; const preprocessedData = this._cleanupItemBeforeSend(dataToSend); for (const key in preprocessedData) { if (key === this.action_param || key === "id" || key === "gr_id") { continue; } data2[key] = preprocessedData[key]; } queryParams.url = url; queryParams.method = "POST"; queryParams.data = JSON.stringify({ id: rowId, action: dataToSend[this.action_param], data: data2 }); break; case "REST": case "REST-JSON": url = urlParams.replace(/(&|\?)editing=true/, ""); data2 = ""; switch (this.getState(rowId)) { case "inserted": queryParams.method = "POST"; queryParams.data = this.serialize(dataToSend, rowId); break; case "deleted": queryParams.method = "DELETE"; url = url + (url.slice(-1) === "/" ? "" : "/") + rowId; break; default: queryParams.method = "PUT"; queryParams.data = this.serialize(dataToSend, rowId); url = url + (url.slice(-1) === "/" ? "" : "/") + rowId; break; } queryParams.url = this._applyPayload(url); break; } this._waitMode++; return ajax2.query(queryParams); } _forEachUpdatedRow(code) { const updatedRows = this.updatedRows.slice(); for (let i = 0; i < updatedRows.length; i++) { const rowId = updatedRows[i]; if (this.$gantt.getUserData(rowId, this.action_param, this._ganttMode)) { code.call(this, rowId); } } } _setDefaultTransactionMode() { if (this.serverProcessor) { this.setTransactionMode("POST", true); this.serverProcessor += (this.serverProcessor.indexOf("?") !== -1 ? "&" : "?") + "editing=true"; this._serverProcessor = this.serverProcessor; } } _getXmlNodeValue(node) { if (node.firstChild) { return node.firstChild.nodeValue; } return ""; } _getAllData() { const out = {}; let hasOne = false; this._forEachUpdatedRow(function(id) { if (this._in_progress[id] || this.is_invalid(id)) { return; } const row = this._getRowData(id); if (!this.callEvent("onBeforeUpdate", [id, this.getState(id), row])) { return; } out[id] = row; hasOne = true; this._in_progress[id] = (/* @__PURE__ */ new Date()).valueOf(); }); return hasOne ? out : null; } _prepareDate(value) { return this.$gantt.defined(this.$gantt.templates.xml_format) ? this.$gantt.templates.xml_format(value) : this.$gantt.templates.format_date(value); } _prepareArray(value, traversedObjects) { traversedObjects.push(value); return value.map((item) => { if (isDate(item)) { return this._prepareDate(item); } else if (Array.isArray(item) && !arrayIncludes(traversedObjects, item)) { return this._prepareArray(item, traversedObjects); } else if (item && typeof item === "object" && !arrayIncludes(traversedObjects, item)) { return this._prepareObject(item, traversedObjects); } else { return item; } }); } _prepareObject(rawItem, traversedObjects) { const processedItem = {}; traversedObjects.push(rawItem); for (const key in rawItem) { if (key.substr(0, 1) === "$") { continue; } const value = rawItem[key]; if (isDate(value)) { processedItem[key] = this._prepareDate(value); } else if (value === null) { processedItem[key] = ""; } else if (Array.isArray(value) && !arrayIncludes(traversedObjects, value)) { processedItem[key] = this._prepareArray(value, traversedObjects); } else if (value && typeof value === "object" && !arrayIncludes(traversedObjects, value)) { processedItem[key] = this._prepareObject(value, traversedObjects); } else { processedItem[key] = value; } } return processedItem; } _prepareDataItem(rawItem) { const processedItem = this._prepareObject(rawItem, []); processedItem[this.action_param] = this.$gantt.getUserData(rawItem.id, this.action_param, this._ganttMode); return processedItem; } getStoredItem(id) { return this._storage.getStoredItem(id); } _getRowData(id) { let dataItem; const gantt2 = this.$gantt; if (this.getGanttMode() === "task") { if (gantt2.isTaskExists(id)) { dataItem = this.$gantt.getTask(id); } } else if (this.getGanttMode() === "assignment") { if (this.$gantt.$data.assignmentsStore.exists(id)) { dataItem = this.$gantt.$data.assignmentsStore.getItem(id); } } else if (this.getGanttMode() === "baseline") { if (this.$gantt.$data.baselineStore.exists(id)) { dataItem = this.$gantt.$data.baselineStore.getItem(id); } } else { if (gantt2.isLinkExists(id)) { dataItem = this.$gantt.getLink(id); } } if (!dataItem) { dataItem = this.getStoredItem(id); } if (!dataItem) { dataItem = { id }; } return this._prepareDataItem(dataItem); } }; const DataProcessor = { DEPRECATED_api: function(server) { return new DataProcessor$1(server); }, createDataProcessor }; function createMethod(gantt2) { var methods = {}; var isActive = false; function disableMethod(methodName, dummyMethod) { dummyMethod = typeof dummyMethod == "function" ? dummyMethod : function() { }; if (!methods[methodName]) { methods[methodName] = this[methodName]; this[methodName] = dummyMethod; } } function restoreMethod(methodName) { if (methods[methodName]) { this[methodName] = methods[methodName]; methods[methodName] = null; } } function disableMethods(methodsHash) { for (var i in methodsHash) { disableMethod.call(this, i, methodsHash[i]); } } function restoreMethods() { for (var i in methods) { restoreMethod.call(this, i); } } function batchUpdatePayload(callback) { try { callback(); } catch (e) { scope.console.error(e); } } var state = gantt2.$services.getService("state"); state.registerProvider("batchUpdate", function() { return { batch_update: isActive }; }, false); return function batchUpdate(callback, noRedraw) { if (isActive) { batchUpdatePayload(callback); return; } var call_dp = this._dp && this._dp.updateMode != "off"; var dp_mode; if (call_dp) { dp_mode = this._dp.updateMode; this._dp.setUpdateMode("off"); } var resetProjects = {}; var methods2 = { render: true, refreshData: true, refreshTask: true, refreshLink: true, resetProjectDates: function(task) { resetProjects[task.id] = task; } }; disableMethods.call(this, methods2); isActive = true; this.callEvent("onBeforeBatchUpdate", []); batchUpdatePayload(callback); this.callEvent("onAfterBatchUpdate", []); restoreMethods.call(this); for (var i in resetProjects) { this.resetProjectDates(resetProjects[i]); } isActive = false; if (!noRedraw) { this.render(); } if (call_dp) { this._dp.setUpdateMode(dp_mode); this._dp.setGanttMode("task"); this._dp.sendData(); this._dp.setGanttMode("link"); this._dp.sendData(); } }; } function batch_update(gantt2) { gantt2.batchUpdate = createMethod(gantt2); } const createWbs = function(gantt2) { return { _needRecalc: true, reset: function() { this._needRecalc = true; }, _isRecalcNeeded: function() { return !this._isGroupSort() && this._needRecalc; }, _isGroupSort: function() { return !!gantt2.getState().group_mode; }, _getWBSCode: function(task) { if (!task) return ""; if (this._isRecalcNeeded()) { this._calcWBS(); } if (task.$virtual) return ""; if (this._isGroupSort()) return task.$wbs || ""; if (!task.$wbs) { this.reset(); this._calcWBS(); } return task.$wbs; }, _setWBSCode: function(task, value) { task.$wbs = value; }, getWBSCode: function(task) { return this._getWBSCode(task); }, getByWBSCode: function(code) { let parts = code.split("."); let currentNode = gantt2.config.root_id; for (let i = 0; i < parts.length; i++) { const children = gantt2.getChildren(currentNode); let index = parts[i] * 1 - 1; if (gantt2.isTaskExists(children[index])) { currentNode = children[index]; } else { return null; } } if (gantt2.isTaskExists(currentNode)) { return gantt2.getTask(currentNode); } else { return null; } }, _calcWBS: function() { if (!this._isRecalcNeeded()) return; let _isFirst = true; gantt2.eachTask(function(ch) { if (ch.type == gantt2.config.types.placeholder) return; if (_isFirst) { _isFirst = false; this._setWBSCode(ch, "1"); return; } const _prevSibling = this._getPrevNonPlaceholderSibling(ch.id); if (_prevSibling !== null) { this._increaseWBS(ch, _prevSibling); } else { let _parent = gantt2.getParent(ch.id); this._setWBSCode(ch, gantt2.getTask(_parent).$wbs + ".1"); } }, gantt2.config.root_id, this); this._needRecalc = false; }, _increaseWBS: function(task, siblingiId) { let _wbs = gantt2.getTask(siblingiId).$wbs; if (_wbs) { _wbs = _wbs.split("."); _wbs[_wbs.length - 1]++; this._setWBSCode(task, _wbs.join(".")); } }, _getPrevNonPlaceholderSibling: function(childId) { let prevSibling; let currentId = childId; do { prevSibling = gantt2.getPrevSibling(currentId); currentId = prevSibling; } while (prevSibling !== null && gantt2.getTask(prevSibling).type == gantt2.config.types.placeholder); return prevSibling; } }; }; function wbs(gantt2) { const wbs2 = createWbs(gantt2); gantt2.getWBSCode = function getWBSCode(task) { return wbs2.getWBSCode(task); }; gantt2.getTaskByWBSCode = function(code) { return wbs2.getByWBSCode(code); }; function resetCache() { wbs2.reset(); return true; } gantt2.attachEvent("onAfterTaskMove", resetCache); gantt2.attachEvent("onBeforeParse", resetCache); gantt2.attachEvent("onAfterTaskDelete", resetCache); gantt2.attachEvent("onAfterTaskAdd", resetCache); gantt2.attachEvent("onAfterSort", resetCache); } function createResourceMethods(gantt2) { var resourceTaskCache = {}; var singleResourceCacheBuilt = false; gantt2.$data.tasksStore.attachEvent("onStoreUpdated", function() { resourceTaskCache = {}; singleResourceCacheBuilt = false; }); gantt2.attachEvent("onBeforeGanttRender", function() { resourceTaskCache = {}; }); function getTaskBy(propertyName, propertyValue, typeFilter) { if (typeof propertyName == "function") { return filterResourceTasks(propertyName); } else { if (isArray(propertyValue)) { return getResourceTasks(propertyName, propertyValue, typeFilter); } else { return getResourceTasks(propertyName, [propertyValue], typeFilter); } } } function filterResourceTasks(filter) { var res = []; gantt2.eachTask(function(task) { if (filter(task)) { res.push(task); } }); return res; } var falsyValuePrefix = String(Math.random()); function resourceHashFunction(value) { if (value === null) { return falsyValuePrefix + String(value); } return String(value); } function getCacheKey(resourceIds, property, typeFilter) { if (Array.isArray(resourceIds)) { return resourceIds.map(function(value) { return resourceHashFunction(value); }).join("_") + `_${property}_${typeFilter}`; } else { return resourceHashFunction(resourceIds) + `_${property}_${typeFilter}`; } } function getResourceTasks(property, resourceIds, typeFilter) { var res; var cacheKey = getCacheKey(resourceIds, property, JSON.stringify(typeFilter)); var matchingResources = {}; forEach(resourceIds, function(resourceId) { matchingResources[resourceHashFunction(resourceId)] = true; }); if (!resourceTaskCache[cacheKey]) { res = resourceTaskCache[cacheKey] = []; gantt2.eachTask(function(task) { if (typeFilter) { if (!typeFilter[gantt2.getTaskType(task)]) { return; } } else if (task.type == gantt2.config.types.project) { return; } if (property in task) { var resourceValue; if (!isArray(task[property])) { resourceValue = [task[property]]; } else { resourceValue = task[property]; } forEach(resourceValue, function(value) { var resourceValue2 = value && value.resource_id ? value.resource_id : value; if (matchingResources[resourceHashFunction(resourceValue2)]) { res.push(task); } else if (!singleResourceCacheBuilt) { var key = getCacheKey(value, property); if (!resourceTaskCache[key]) { resourceTaskCache[key] = []; } resourceTaskCache[key].push(task); } }); } }); singleResourceCacheBuilt = true; } else { res = resourceTaskCache[cacheKey]; } return res; } function selectAssignments(resourceId, taskId, result) { var property = gantt2.config.resource_property; var owners = []; if (gantt2.getDatastore("task").exists(taskId)) { var task = gantt2.getTask(taskId); owners = task[property] || []; } if (!Array.isArray(owners)) { owners = [owners]; } for (var i = 0; i < owners.length; i++) { if (owners[i].resource_id == resourceId) { result.push({ task_id: task.id, resource_id: owners[i].resource_id, value: owners[i].value }); } } } function getResourceAssignments(resourceId, taskId) { var assignments = []; var property = gantt2.config.resource_property; if (taskId !== void 0) { selectAssignments(resourceId, taskId, assignments); } else { var tasks2 = gantt2.getTaskBy(property, resourceId); tasks2.forEach(function(task) { selectAssignments(resourceId, task.id, assignments); }); } return assignments; } return { getTaskBy, getResourceAssignments }; } function createHelper$1(gantt2) { const resourcePlugin = { renderEditableLabel: function(start_date, end_date, resource, tasks2, assignments) { const editable = gantt2.config.readonly ? "" : "contenteditable"; if (start_date < resource.end_date && end_date > resource.start_date) { for (let i = 0; i < assignments.length; i++) { const a = assignments[i]; return "
" + a.value + "
"; } return "
-
"; } return ""; }, renderSummaryLabel: function(start_date, end_date, resource, tasks2, assignments) { let sum = assignments.reduce(function(total, assignment) { return total + Number(assignment.value); }, 0); if (sum % 1) { sum = Math.round(sum * 10) / 10; } if (sum) { return "
" + sum + "
"; } return ""; }, editableResourceCellTemplate: function(start_date, end_date, resource, tasks2, assignments) { if (resource.$role === "task") { return resourcePlugin.renderEditableLabel(start_date, end_date, resource, tasks2, assignments); } else { return resourcePlugin.renderSummaryLabel(start_date, end_date, resource, tasks2, assignments); } }, editableResourceCellClass: function(start_date, end_date, resource, tasks2, assignments) { const css = []; css.push("resource_marker"); if (resource.$role === "task") { css.push("task_cell"); } else { css.push("resource_cell"); } const sum = assignments.reduce(function(total, assignment) { return total + Number(assignment.value); }, 0); let capacity = Number(resource.capacity); if (isNaN(capacity)) { capacity = 8; } if (sum <= capacity) { css.push("workday_ok"); } else { css.push("workday_over"); } return css.join(" "); }, getSummaryResourceAssignments: function getResourceAssignments(resourceId) { let assignments; const store = gantt2.getDatastore(gantt2.config.resource_store); const resource = store.getItem(resourceId); if (resource.$role === "task") { assignments = gantt2.getResourceAssignments(resource.$resource_id, resource.$task_id); } else { assignments = gantt2.getResourceAssignments(resourceId); if (store.eachItem) { store.eachItem(function(childResource) { if (childResource.$role !== "task") { assignments = assignments.concat(gantt2.getResourceAssignments(childResource.id)); } }, resourceId); } } return assignments; }, initEditableDiagram: function() { gantt2.config.resource_render_empty_cells = true; (function() { let timeoutId = null; function makeEditable() { if (timeoutId) { cancelAnimationFrame(timeoutId); } timeoutId = requestAnimationFrame(function() { if (gantt2.$container) { var cells = Array.prototype.slice.call(gantt2.$container.querySelectorAll(".resourceTimeline_cell [data-assignment-cell]")); cells.forEach(function(cell) { cell.contentEditable = true; }); } }); return true; } gantt2.attachEvent("onGanttReady", function() { gantt2.getDatastore(gantt2.config.resource_assignment_store).attachEvent("onStoreUpdated", makeEditable); gantt2.getDatastore(gantt2.config.resource_store).attachEvent("onStoreUpdated", makeEditable); }, { once: true }); gantt2.attachEvent("onGanttLayoutReady", function() { const ganttViews = gantt2.$layout.getCellsByType("viewCell"); ganttViews.forEach(function(view) { if (view.$config && view.$config.view === "resourceTimeline" && view.$content) { view.$content.attachEvent("onScroll", makeEditable); } }); }); })(); let currentFocusIndex = null; function setNextFocus() { setTimeout(function() { var _a; const focusableElementsAfterRender = getFocusableNodes(gantt2.$container); if (currentFocusIndex > -1) { (_a = focusableElementsAfterRender[currentFocusIndex + 1]) == null ? void 0 : _a.focus(); } }, 300); } function handleAssignmentEdit(e, elem) { let target = elem || e.target.closest(".resourceTimeline_cell [data-assignment-cell]"); if (target) { let strValue = (target.innerText || "").trim(); if (strValue == "-") { strValue = "0"; } let value = Number(strValue); let rowId = target.getAttribute("data-row-id"); let assignmentId = target.getAttribute("data-assignment-id"); let taskId = target.getAttribute("data-task"); let resourceId = target.getAttribute("data-resource-id"); let startDate = gantt2.templates.parse_date(target.getAttribute("data-start-date")); let endDate = gantt2.templates.parse_date(target.getAttribute("data-end-date")); const assignmentStore = gantt2.getDatastore(gantt2.config.resource_assignment_store); if (isNaN(value)) { gantt2.getDatastore(gantt2.config.resource_store).refresh(rowId); } else { const task = gantt2.getTask(taskId); if (assignmentId) { if (gantt2.plugins().undo) { gantt2.ext.undo.saveState(taskId, "task"); } const assignment = assignmentStore.getItem(assignmentId); if (!assignment || value === assignment.value) { return; } if (assignment.start_date.valueOf() === startDate.valueOf() && assignment.end_date.valueOf() === endDate.valueOf()) { assignment.value = value; if (!value) { assignmentStore.removeItem(assignment.id); } else { assignmentStore.updateItem(assignment.id); } } else { if (assignment.end_date.valueOf() > endDate.valueOf()) { const nextChunk = gantt2.copy(assignment); nextChunk.id = gantt2.uid(); nextChunk.start_date = endDate; nextChunk.duration = gantt2.calculateDuration({ start_date: nextChunk.start_date, end_date: nextChunk.end_date, task }); nextChunk.delay = gantt2.calculateDuration({ start_date: task.start_date, end_date: nextChunk.start_date, task }); nextChunk.mode = assignment.mode || "default"; if (nextChunk.duration !== 0) { assignmentStore.addItem(nextChunk); } } if (assignment.start_date.valueOf() < startDate.valueOf()) { assignment.end_date = startDate; assignment.duration = gantt2.calculateDuration({ start_date: assignment.start_date, end_date: assignment.end_date, task }); assignment.mode = "fixedDuration"; if (assignment.duration === 0) { assignmentStore.removeItem(assignment.id); } else { assignmentStore.updateItem(assignment.id); } } else { assignmentStore.removeItem(assignment.id); } if (value) { assignmentStore.addItem({ task_id: assignment.task_id, resource_id: assignment.resource_id, value, start_date: startDate, end_date: endDate, duration: gantt2.calculateDuration({ start_date: startDate, end_date: endDate, task }), delay: gantt2.calculateDuration({ start_date: task.start_date, end_date: startDate, task }), mode: "fixedDuration" }); } } gantt2.updateTaskAssignments(task.id); gantt2.updateTask(task.id); } else if (value) { let assignment = { task_id: taskId, resource_id: resourceId, value, start_date: startDate, end_date: endDate, duration: gantt2.calculateDuration({ start_date: startDate, end_date: endDate, task }), delay: gantt2.calculateDuration({ start_date: task.start_date, end_date: startDate, task }), mode: "fixedDuration" }; assignmentStore.addItem(assignment); gantt2.updateTaskAssignments(task.id); gantt2.updateTask(task.id); } } } } gantt2.attachEvent("onGanttReady", function() { let editedElem = null; gantt2.event(gantt2.$container, "keypress", function(e) { let target = e.target.closest(".resourceTimeline_cell [data-assignment-cell]"); if (target) { if (e.keyCode === 13 || e.keyCode === 27) { target.blur(); handleAssignmentEdit(e); } editedElem = e.target; } }); gantt2.event(gantt2.$container, "keydown", function(event2) { if (event2.key === "Tab") { const focusableElements = getFocusableNodes(gantt2.$container); currentFocusIndex = focusableElements.indexOf(document.activeElement); handleAssignmentEdit(event2); setNextFocus(); } }); gantt2.event(gantt2.$container, "click", function(e) { if (editedElem) { handleAssignmentEdit(e, editedElem); editedElem = null; if (e.target.hasAttribute("data-assignment-id")) { const focusableElements = gantt2.$container.querySelectorAll("[contenteditable='true']"); const target = Array.from(focusableElements).find((elem) => elem.getAttribute("data-start-date") == e.target.getAttribute("data-start-date") && elem.getAttribute("data-assignment-id") == e.target.getAttribute("data-assignment-id")); setTimeout(() => { const focusableElementsAfterUpdate = gantt2.$container.querySelectorAll("[contenteditable='true']"); const targetAfterUpdate = Array.from(focusableElementsAfterUpdate).find((elem) => elem.getAttribute("data-start-date") == target.getAttribute("data-start-date") && elem.getAttribute("data-row-id") == target.getAttribute("data-row-id")); if (targetAfterUpdate) { targetAfterUpdate.focus(); } }, 400); } } }); }, { once: true }); } }; return resourcePlugin; } function resources(gantt2) { var methods = createResourceMethods(gantt2); gantt2.ext.resources = createHelper$1(gantt2); gantt2.config.resources = { dataprocessor_assignments: false, dataprocessor_resources: false, editable_resource_diagram: false, resource_store: { type: "treeDataStore", fetchTasks: false, initItem: function(item) { item.parent = item.parent || gantt2.config.root_id; item[gantt2.config.resource_property] = item.parent; item.open = true; return item; } }, lightbox_resources: function selectResourceControlOptions(resources2) { const lightboxOptions = []; const store = gantt2.getDatastore(gantt2.config.resource_store); resources2.forEach(function(res) { if (!store.hasChild(res.id)) { const copy2 = gantt2.copy(res); copy2.key = res.id; copy2.label = res.text; lightboxOptions.push(copy2); } }); return lightboxOptions; } }; gantt2.attachEvent("onBeforeGanttReady", function() { if (gantt2.getDatastore(gantt2.config.resource_store)) { return; } const resourceStoreConfig = gantt2.config.resources ? gantt2.config.resources.resource_store : void 0; let fetchTasks = resourceStoreConfig ? resourceStoreConfig.fetchTasks : void 0; if (gantt2.config.resources && gantt2.config.resources.editable_resource_diagram) { fetchTasks = true; } let initItems = function(item) { item.parent = item.parent || gantt2.config.root_id; item[gantt2.config.resource_property] = item.parent; item.open = true; return item; }; if (resourceStoreConfig && resourceStoreConfig.initItem) { initItems = resourceStoreConfig.initItem; } const storeType = resourceStoreConfig && resourceStoreConfig.type ? resourceStoreConfig.type : "treeDatastore"; gantt2.$resourcesStore = gantt2.createDatastore({ name: gantt2.config.resource_store, type: storeType, fetchTasks: fetchTasks !== void 0 ? fetchTasks : false, initItem: initItems }); gantt2.$data.resourcesStore = gantt2.$resourcesStore; gantt2.$resourcesStore.attachEvent("onParse", function() { function selectResourceControlOptions(resources2) { const lightboxOptions = []; resources2.forEach(function(res) { const copy2 = gantt2.copy(res); copy2.key = res.id; copy2.label = res.text; lightboxOptions.push(copy2); }); return lightboxOptions; } let lightboxOptionsFnc = selectResourceControlOptions; let options; if (gantt2.config.resources && gantt2.config.resources.lightbox_resources) { lightboxOptionsFnc = gantt2.config.resources.lightbox_resources; } if (gantt2.config.resources && gantt2.config.resources.editable_resource_diagram) { const resources2 = gantt2.$resourcesStore.getItems(); const filteredResources = resources2.filter((resource) => { let assignments = gantt2.getResourceAssignments(resource.id); if (!gantt2.$resourcesStore.hasChild(resource.id) || assignments && assignments.length) { if (resource.$resource_id && resource.$task_id) { return false; } return true; } }); options = lightboxOptionsFnc(filteredResources); } else { options = lightboxOptionsFnc(gantt2.$resourcesStore.getItems()); } gantt2.updateCollection("resourceOptions", options); }); }); gantt2.getTaskBy = methods.getTaskBy; gantt2.getResourceAssignments = methods.getResourceAssignments; gantt2.config.resource_property = "owner_id"; gantt2.config.resource_store = "resource"; gantt2.config.resource_render_empty_cells = false; gantt2.templates.histogram_cell_class = function(start_date, end_date, resource, tasks2, assignments) { }; gantt2.templates.histogram_cell_label = function(start_date, end_date, resource, tasks2, assignments) { return tasks2.length + "/3"; }; gantt2.templates.histogram_cell_allocated = function(start_date, end_date, resource, tasks2, assignments) { return tasks2.length / 3; }; gantt2.templates.histogram_cell_capacity = function(start_date, end_date, resource, tasks2, assignments) { return 0; }; const defaultResourceCellClass = function(start, end, resource, tasks2, assignments) { var css = ""; if (tasks2.length <= 1) { css = "gantt_resource_marker_ok"; } else { css = "gantt_resource_marker_overtime"; } return css; }; const defaultResourceCellTemplate = function(start, end, resource, tasks2, assignments) { return tasks2.length * 8; }; gantt2.templates.resource_cell_value = defaultResourceCellTemplate; gantt2.templates.resource_cell_class = defaultResourceCellClass; gantt2.attachEvent("onBeforeGanttReady", function() { if (gantt2.config.resources && gantt2.config.resources.editable_resource_diagram) { gantt2.config.resource_render_empty_cells = true; if (gantt2.templates.resource_cell_value === defaultResourceCellTemplate) { gantt2.templates.resource_cell_value = gantt2.ext.resources.editableResourceCellTemplate; } if (gantt2.templates.resource_cell_class === defaultResourceCellClass) { gantt2.templates.resource_cell_class = gantt2.ext.resources.editableResourceCellClass; } gantt2.ext.resources.initEditableDiagram(gantt2); } }); } function resource_assignments(gantt2) { var resourceAssignmentsProperty = "$resourceAssignments"; gantt2.config.resource_assignment_store = "resourceAssignments"; gantt2.config.process_resource_assignments = true; var resourceAssignmentFormats = { auto: "auto", singleValue: "singleValue", valueArray: "valueArray", resourceValueArray: "resourceValueArray", assignmentsArray: "assignmentsArray" }; var resourceAssignmentFormat = resourceAssignmentFormats.auto; var assignmentModes = { fixedDates: "fixedDates", fixedDuration: "fixedDuration", default: "default" }; function initAssignmentFields(item, task) { if (item.start_date) { item.start_date = gantt2.date.parseDate(item.start_date, "parse_date"); } else { item.start_date = null; } if (item.end_date) { item.end_date = gantt2.date.parseDate(item.end_date, "parse_date"); } else { item.end_date = null; } var delay2 = Number(item.delay); var initDelay = false; if (!isNaN(delay2)) { item.delay = delay2; } else { item.delay = 0; initDelay = true; } if (!gantt2.defined(item.value)) { item.value = null; } if (!item.task_id || !item.resource_id) { return false; } item.mode = item.mode || assignmentModes.default; if (item.mode === assignmentModes.fixedDuration) { if (isNaN(Number(item.duration))) { task = task || gantt2.getTask(item.task_id); item.duration = gantt2.calculateDuration({ start_date: item.start_date, end_date: item.end_date, id: task }); } if (initDelay) { task = task || gantt2.getTask(item.task_id); item.delay = gantt2.calculateDuration({ start_date: task.start_date, end_date: item.start_date, id: task }); } } if (item.mode !== assignmentModes.fixedDates && (task || gantt2.isTaskExists(item.task_id))) { task = task || gantt2.getTask(item.task_id); var timing = _assignmentTimeFromTask(item, task); item.start_date = timing.start_date; item.end_date = timing.end_date; item.duration = timing.duration; } } var resourceAssignmentsStore = gantt2.createDatastore({ name: gantt2.config.resource_assignment_store, initItem: function(item) { if (!item.id) { item.id = gantt2.uid(); } initAssignmentFields(item); return item; } }); gantt2.$data.assignmentsStore = resourceAssignmentsStore; function _assignmentTimeFromTask(assignment, task) { if (assignment.mode === assignmentModes.fixedDates) { return { start_date: assignment.start_date, end_date: assignment.end_date, duration: assignment.duration }; } else { var start = assignment.delay ? gantt2.calculateEndDate({ start_date: task.start_date, duration: assignment.delay, task }) : new Date(task.start_date); var end; var duration; if (assignment.mode === assignmentModes.fixedDuration) { end = gantt2.calculateEndDate({ start_date: start, duration: assignment.duration, task }); duration = assignment.duration; } else { end = new Date(task.end_date); duration = task.duration - assignment.delay; } } return { start_date: start, end_date: end, duration }; } function _makeAssignmentsFromTask(task) { const property = gantt2.config.resource_property; let assignments = task[property]; const resourceAssignments = []; let detectFormat = resourceAssignmentFormat === resourceAssignmentFormats.auto; if (gantt2.defined(assignments) && assignments) { if (!Array.isArray(assignments)) { assignments = [assignments]; if (detectFormat) { resourceAssignmentFormat = resourceAssignmentFormats.singleValue; detectFormat = false; } } const usedIds = {}; assignments.forEach(function(res) { if (!res.resource_id) { res = { resource_id: res }; if (detectFormat) { resourceAssignmentFormat = resourceAssignmentFormats.valueArray; detectFormat = false; } } if (detectFormat) { if (res.id && res.resource_id) { resourceAssignmentFormat = resourceAssignmentFormats.assignmentsArray; detectFormat = false; } else { resourceAssignmentFormat = resourceAssignmentFormats.resourceValueArray; detectFormat = false; } } let defaultMode = assignmentModes.default; if (!res.mode) { if (res.start_date && res.end_date || res.start_date && res.duration) { defaultMode = assignmentModes.fixedDuration; } } let id; if (!res.id && res.$id && !usedIds[res.$id]) { id = res.$id; } else if (res.id && !usedIds[res.id]) { id = res.id; } else { id = gantt2.uid(); } usedIds[id] = true; const assignment = { id, start_date: res.start_date, duration: res.duration, end_date: res.end_date, delay: res.delay, task_id: task.id, resource_id: res.resource_id, value: res.value, mode: res.mode || defaultMode }; Object.keys(res).forEach((key) => { if (key != "$id") { assignment[key] = res[key]; } }); if (!(assignment.start_date && assignment.start_date.getMonth && assignment.end_date && assignment.end_date.getMonth && typeof assignment.duration === "number")) { initAssignmentFields(assignment, task); } resourceAssignments.push(assignment); }); } return resourceAssignments; } function _updateTaskBack(taskId) { if (!gantt2.isTaskExists(taskId)) { return; } var task = gantt2.getTask(taskId); var assignments = gantt2.getTaskAssignments(task.id); _assignAssignments(task, assignments); } function _assignAssignments(task, assignments) { assignments.sort(function(a, b) { if (a.start_date && b.start_date && a.start_date.valueOf() != b.start_date.valueOf()) { return a.start_date - b.start_date; } else { return 0; } }); if (resourceAssignmentFormat == resourceAssignmentFormats.assignmentsArray) { task[gantt2.config.resource_property] = assignments; } else if (resourceAssignmentFormat == resourceAssignmentFormats.resourceValueArray) { task[gantt2.config.resource_property] = assignments.map(function(a) { return { $id: a.id, start_date: a.start_date, duration: a.duration, end_date: a.end_date, delay: a.delay, resource_id: a.resource_id, value: a.value, mode: a.mode }; }); } task[resourceAssignmentsProperty] = assignments; } function _loadAssignmentsFromTask(task) { var assignments = _makeAssignmentsFromTask(task); assignments.forEach(function(a) { a.id = a.id || gantt2.uid(); }); return assignments; } function diffAssignments(taskValues, assignmentsStoreValues) { var result = { inBoth: [], inTaskNotInStore: [], inStoreNotInTask: [] }; if (resourceAssignmentFormat == resourceAssignmentFormats.singleValue) { var taskOwner = taskValues[0]; var ownerId = taskOwner ? taskOwner.resource_id : null; var foundOwnerAssignment = false; assignmentsStoreValues.forEach(function(a) { if (a.resource_id != ownerId) { result.inStoreNotInTask.push(a); } else if (a.resource_id == ownerId) { result.inBoth.push({ store: a, task: taskOwner }); foundOwnerAssignment = true; } }); if (!foundOwnerAssignment && taskOwner) { result.inTaskNotInStore.push(taskOwner); } } else if (resourceAssignmentFormat == resourceAssignmentFormats.valueArray) { var taskSearch = {}; var storeSearch = {}; var processedIds = {}; taskValues.forEach(function(a) { taskSearch[a.resource_id] = a; }); assignmentsStoreValues.forEach(function(a) { storeSearch[a.resource_id] = a; }); taskValues.concat(assignmentsStoreValues).forEach(function(a) { if (processedIds[a.resource_id]) { return; } processedIds[a.resource_id] = true; var inTask = taskSearch[a.resource_id]; var inStore = storeSearch[a.resource_id]; if (inTask && inStore) { result.inBoth.push({ store: inStore, task: inTask }); } else if (inTask && !inStore) { result.inTaskNotInStore.push(inTask); } else if (!inTask && inStore) { result.inStoreNotInTask.push(inStore); } }); } else if (resourceAssignmentFormat == resourceAssignmentFormats.assignmentsArray || resourceAssignmentFormat == resourceAssignmentFormats.resourceValueArray) { var taskSearch = {}; var storeSearch = {}; var processedIds = {}; taskValues.forEach(function(a) { taskSearch[a.id || a.$id] = a; }); assignmentsStoreValues.forEach(function(a) { storeSearch[a.id] = a; }); taskValues.concat(assignmentsStoreValues).forEach(function(a) { var id = a.id || a.$id; if (processedIds[id]) { return; } processedIds[id] = true; var inTask = taskSearch[id]; var inStore = storeSearch[id]; if (inTask && inStore) { result.inBoth.push({ store: inStore, task: inTask }); } else if (inTask && !inStore) { result.inTaskNotInStore.push(inTask); } else if (!inTask && inStore) { result.inStoreNotInTask.push(inStore); } }); } return result; } function assignmentHasChanged(source, target) { var ignoreFields = { id: true }; for (var i in source) { if (!ignoreFields[i]) { if (String(source[i]) !== String(target[i])) { return true; } } } return false; } function updateAssignment(source, target) { var ignoreFields = { id: true }; for (var i in source) { if (!ignoreFields[i]) { target[i] = source[i]; } } } function _syncAssignments(task, storeAssignments) { var tasksAssignments = _makeAssignmentsFromTask(task); var diff = diffAssignments(tasksAssignments, storeAssignments); diff.inStoreNotInTask.forEach(function(a) { resourceAssignmentsStore.removeItem(a.id); }); diff.inTaskNotInStore.forEach(function(a) { resourceAssignmentsStore.addItem(a); }); diff.inBoth.forEach(function(a) { if (assignmentHasChanged(a.task, a.store)) { updateAssignment(a.task, a.store); resourceAssignmentsStore.updateItem(a.store.id); } else { if (a.task.start_date && a.task.end_date && a.task.mode !== assignmentModes.fixedDates) { var timing = _assignmentTimeFromTask(a.store, task); if (a.store.start_date.valueOf() != timing.start_date.valueOf() || a.store.end_date.valueOf() != timing.end_date.valueOf()) { a.store.start_date = timing.start_date; a.store.end_date = timing.end_date; a.store.duration = timing.duration; resourceAssignmentsStore.updateItem(a.store.id); } } } }); _updateTaskBack(task.id); } function _syncOnTaskUpdate(task) { var storeAssignments = task[resourceAssignmentsProperty] || resourceAssignmentsStore.find(function(a) { return a.task_id == task.id; }); _syncAssignments(task, storeAssignments); } function _syncOnTaskDelete(ids) { var idsSearch = {}; ids.forEach(function(id) { idsSearch[id] = true; }); var taskResources = resourceAssignmentsStore.find(function(a) { return idsSearch[a.task_id]; }); taskResources.forEach(function(a) { resourceAssignmentsStore.removeItem(a.id); }); } gantt2.attachEvent("onGanttReady", function() { if (gantt2.config.process_resource_assignments) { gantt2.attachEvent("onParse", function() { gantt2.silent(function() { resourceAssignmentsStore.clearAll(); var totalAssignments = []; gantt2.eachTask(function(task) { if (task.type === gantt2.config.types.project) { return; } var assignments = _loadAssignmentsFromTask(task); _assignAssignments(task, assignments); assignments.forEach(function(a) { totalAssignments.push(a); }); }); resourceAssignmentsStore.parse(totalAssignments); }); }); var batchUpdate = false; var needUpdate = false; var needUpdateFor = {}; var undoBatchCancel = false; gantt2.attachEvent("onBeforeBatchUpdate", function() { batchUpdate = true; }); gantt2.attachEvent("onAfterBatchUpdate", function() { if (needUpdate) { var assignmentsHash = {}; for (var i in needUpdateFor) { assignmentsHash[i] = gantt2.getTaskAssignments(needUpdateFor[i].id); } if (gantt2.config.process_resource_assignments && resourceAssignmentFormat === "resourceValueArray") { taskAssignmentsCache = null; } for (var i in needUpdateFor) { _syncAssignments(needUpdateFor[i], assignmentsHash[i]); } } needUpdate = false; batchUpdate = false; needUpdateFor = {}; }); gantt2.attachEvent("onTaskCreated", function(item) { var assignments = _loadAssignmentsFromTask(item); resourceAssignmentsStore.parse(assignments); _assignAssignments(item, assignments); return true; }); gantt2.attachEvent("onAfterTaskUpdate", function(id, item) { if (batchUpdate) { needUpdate = true; needUpdateFor[id] = item; } else if (!item.unscheduled) { _syncOnTaskUpdate(item); } }); gantt2.attachEvent("onAfterTaskAdd", function(id, item) { if (batchUpdate) { needUpdate = true; needUpdateFor[id] = item; } else { _syncOnTaskUpdate(item); } }); gantt2.attachEvent("onRowDragEnd", function(id) { _syncOnTaskUpdate(gantt2.getTask(id)); }); gantt2.$data.tasksStore.attachEvent("onAfterDeleteConfirmed", function(id, item) { var deleteIds = [id]; gantt2.eachTask(function(task) { deleteIds.push(task.id); }, id); _syncOnTaskDelete(deleteIds); }); gantt2.$data.tasksStore.attachEvent("onClearAll", function() { resourceAssignmentsCache = null; resourceTaskAssignmentsCache = null; taskAssignmentsCache = null; resourceAssignmentsStore.clearAll(); return true; }); gantt2.attachEvent("onTaskIdChange", function(id, new_id) { var taskResources = resourceAssignmentsStore.find(function(a) { return a.task_id == id; }); taskResources.forEach(function(a) { a.task_id = new_id; resourceAssignmentsStore.updateItem(a.id); }); _updateTaskBack(new_id); }); gantt2.attachEvent("onBeforeUndo", function(action) { undoBatchCancel = true; return true; }); gantt2.attachEvent("onAfterUndo", function(action) { undoBatchCancel = true; }); var resourceAssignmentsCache = null; var resourceTaskAssignmentsCache = null; var taskAssignmentsCache = null; resourceAssignmentsStore.attachEvent("onStoreUpdated", function resetCache() { if (batchUpdate && !undoBatchCancel) { return true; } resourceAssignmentsCache = null; resourceTaskAssignmentsCache = null; taskAssignmentsCache = null; return true; }); gantt2.getResourceAssignments = function(resourceId, taskId) { var searchTaskId = gantt2.defined(taskId) && taskId !== null; if (resourceAssignmentsCache === null) { resourceAssignmentsCache = {}; resourceTaskAssignmentsCache = {}; resourceAssignmentsStore.eachItem(function(a) { if (!resourceAssignmentsCache[a.resource_id]) { resourceAssignmentsCache[a.resource_id] = []; } resourceAssignmentsCache[a.resource_id].push(a); var resourceTaskCacheKey = a.resource_id + "-" + a.task_id; if (!resourceTaskAssignmentsCache[resourceTaskCacheKey]) { resourceTaskAssignmentsCache[resourceTaskCacheKey] = []; } resourceTaskAssignmentsCache[resourceTaskCacheKey].push(a); }); } if (searchTaskId) { return (resourceTaskAssignmentsCache[resourceId + "-" + taskId] || []).slice(); } else { return (resourceAssignmentsCache[resourceId] || []).slice(); } }; gantt2.getTaskAssignments = function(taskId) { if (taskAssignmentsCache === null) { var result = []; taskAssignmentsCache = {}; resourceAssignmentsStore.eachItem(function(a) { if (!taskAssignmentsCache[a.task_id]) { taskAssignmentsCache[a.task_id] = []; } taskAssignmentsCache[a.task_id].push(a); if (a.task_id == taskId) { result.push(a); } }); } return (taskAssignmentsCache[taskId] || []).slice(); }; gantt2.getTaskResources = function(taskId) { const store = gantt2.getDatastore("resource"); const assignments = gantt2.getTaskAssignments(taskId); const uniqueResources = {}; assignments.forEach(function(a) { if (!uniqueResources[a.resource_id]) { uniqueResources[a.resource_id] = a.resource_id; } }); const resources2 = []; for (const i in uniqueResources) { const res = store.getItem(uniqueResources[i]); if (res) { resources2.push(res); } } return resources2; }; gantt2.updateTaskAssignments = _updateTaskBack; } }, { once: true }); } function addPlaceholder(gantt2) { function isEnabled2() { return gantt2.config.placeholder_task; } function callIfEnabled(callback) { return function() { if (!isEnabled2()) { return true; } return callback.apply(this, arguments); }; } function silenceDataProcessor(dataProcessor) { if (dataProcessor && !dataProcessor._silencedPlaceholder) { dataProcessor._silencedPlaceholder = true; dataProcessor.attachEvent("onBeforeUpdate", callIfEnabled(function(id, state, data2) { if (data2.type == gantt2.config.types.placeholder) { dataProcessor.setUpdated(id, false); return false; } return true; })); } } function insertPlaceholder() { var placeholders = gantt2.getTaskBy("type", gantt2.config.types.placeholder); if (!placeholders.length || !gantt2.isTaskExists(placeholders[0].id)) { var placeholder = { unscheduled: true, type: gantt2.config.types.placeholder, duration: 0, text: gantt2.locale.labels.new_task }; if (gantt2.callEvent("onTaskCreated", [placeholder]) === false) { return; } gantt2.addTask(placeholder); } } function afterEdit(id) { var item = gantt2.getTask(id); if (item.type == gantt2.config.types.placeholder) { if (item.start_date && item.end_date && item.unscheduled) { item.unscheduled = false; } gantt2.batchUpdate(function() { var newTask = gantt2.copy(item); gantt2.silent(function() { gantt2.deleteTask(item.id); }); delete newTask["!nativeeditor_status"]; newTask.type = gantt2.config.types.task; newTask.id = gantt2.uid(); gantt2.addTask(newTask); }); } } gantt2.config.types.placeholder = "placeholder"; gantt2.attachEvent("onDataProcessorReady", callIfEnabled(silenceDataProcessor)); var ready = false; gantt2.attachEvent("onGanttReady", function() { if (ready) { return; } ready = true; gantt2.attachEvent("onAfterTaskUpdate", callIfEnabled(afterEdit)); gantt2.attachEvent("onAfterTaskAdd", callIfEnabled(function(id, task) { if (task.type != gantt2.config.types.placeholder) { var placeholders = gantt2.getTaskBy("type", gantt2.config.types.placeholder); placeholders.forEach(function(p) { gantt2.silent(function() { if (gantt2.isTaskExists(p.id)) gantt2.deleteTask(p.id); }); }); insertPlaceholder(); } })); gantt2.attachEvent("onParse", callIfEnabled(insertPlaceholder)); }); function isPlaceholderTask2(taskId) { if (gantt2.config.types.placeholder && gantt2.isTaskExists(taskId)) { var task = gantt2.getTask(taskId); if (task.type == gantt2.config.types.placeholder) { return true; } } return false; } function isPlaceholderLink(link) { if (isPlaceholderTask2(link.source) || isPlaceholderTask2(link.target)) { return true; } return false; } gantt2.attachEvent("onLinkValidation", function(link) { if (isPlaceholderLink(link)) { return false; } return true; }); gantt2.attachEvent("onBeforeLinkAdd", function(id, link) { if (isPlaceholderLink(link)) { return false; } return true; }); gantt2.attachEvent("onBeforeUndoStack", function(action) { for (var i = 0; i < action.commands.length; i++) { var command = action.commands[i]; if (command.entity === "task" && command.value.type === gantt2.config.types.placeholder) { action.commands.splice(i, 1); i--; } } return true; }); } function auto_task_types(gantt2) { function isEnabled2() { return gantt2.config.auto_types && gantt2.getTaskType(gantt2.config.types.project) == gantt2.config.types.project; } function callIfEnabled(callback) { return function() { if (!isEnabled2()) { return true; } return callback.apply(this, arguments); }; } function checkTaskType(id, changedTypes) { var task = gantt2.getTask(id); var targetType = getTaskTypeToUpdate(task); if (targetType !== false && gantt2.getTaskType(task) !== targetType) { changedTypes.$needsUpdate = true; changedTypes[task.id] = { task, type: targetType }; } } function getUpdatedTypes(id, changedTypes) { changedTypes = changedTypes || {}; checkTaskType(id, changedTypes); gantt2.eachParent(function(parent) { checkTaskType(parent.id, changedTypes); }, id); return changedTypes; } function applyChanges(changedTypes) { for (var i in changedTypes) { if (changedTypes[i] && changedTypes[i].task) { var task = changedTypes[i].task; task.type = changedTypes[i].type; gantt2.updateTask(task.id); } } } function updateParentTypes(startId) { if (gantt2.getState().group_mode) { return; } var changedTypes = getUpdatedTypes(startId); if (changedTypes.$needsUpdate) { gantt2.batchUpdate(function() { applyChanges(changedTypes); }); } } var delTaskParent; function updateTaskType(task, targetType) { if (!gantt2.getState().group_mode) { task.type = targetType; gantt2.updateTask(task.id); } } function getTaskTypeToUpdate(task) { var allTypes = gantt2.config.types; var hasChildren = gantt2.hasChild(task.id); var taskType = gantt2.getTaskType(task.type); if (hasChildren && taskType === allTypes.task) { return allTypes.project; } if (!hasChildren && taskType === allTypes.project) { return allTypes.task; } return false; } var isParsingDone = true; gantt2.attachEvent("onParse", callIfEnabled(function() { isParsingDone = false; if (gantt2.getState().group_mode) { return; } gantt2.batchUpdate(function() { gantt2.eachTask(function(task) { var targetType = getTaskTypeToUpdate(task); if (targetType !== false) { updateTaskType(task, targetType); } }); }); isParsingDone = true; })); gantt2.attachEvent("onAfterTaskAdd", callIfEnabled(function(id) { if (isParsingDone) { updateParentTypes(id); } })); gantt2.attachEvent("onAfterTaskUpdate", callIfEnabled(function(id) { if (isParsingDone) { updateParentTypes(id); } })); function updateAfterRemoveChild(id) { if (id != gantt2.config.root_id && gantt2.isTaskExists(id)) { updateParentTypes(id); } } gantt2.attachEvent("onBeforeTaskDelete", callIfEnabled(function(id, task) { delTaskParent = gantt2.getParent(id); return true; })); gantt2.attachEvent("onAfterTaskDelete", callIfEnabled(function(id, task) { updateAfterRemoveChild(delTaskParent); })); var originalRowDndParent; gantt2.attachEvent("onRowDragStart", callIfEnabled(function(id, target, e) { originalRowDndParent = gantt2.getParent(id); return true; })); gantt2.attachEvent("onRowDragEnd", callIfEnabled(function(id, target) { updateAfterRemoveChild(originalRowDndParent); updateParentTypes(id); })); var originalMoveTaskParent; gantt2.attachEvent("onBeforeTaskMove", callIfEnabled(function(sid, parent, tindex) { originalMoveTaskParent = gantt2.getParent(sid); return true; })); gantt2.attachEvent("onAfterTaskMove", callIfEnabled(function(id, parent, tindex) { if (document.querySelector(".gantt_drag_marker")) { return; } updateAfterRemoveChild(originalMoveTaskParent); updateParentTypes(id); })); } const _DurationFormatterNumeric = class _DurationFormatterNumeric { constructor() { this.canParse = (value) => !isNaN(this.parse(value)); this.format = (value) => String(value); this.parse = (value) => parseInt(value, 10); } }; _DurationFormatterNumeric.create = (settings = null) => new _DurationFormatterNumeric(); let DurationFormatterNumeric = _DurationFormatterNumeric; const _LinkFormatterSimple = class _LinkFormatterSimple { constructor(gantt2) { this.format = (link) => { const wbs2 = this._getWBSCode(link.source); return wbs2; }; this.canParse = (value) => this._linkReg.test(value); this.parse = (value) => { if (!this.canParse(value)) { return null; } const linkPart = this._linkReg.exec(value)[0].trim(); const source = this._findSource(linkPart) || null; return { id: void 0, source, target: null, type: this._gantt.config.links.finish_to_start, lag: 0 }; }; this._getWBSCode = (source) => { const pred = this._gantt.getTask(source); return this._gantt.getWBSCode(pred); }; this._findSource = (value) => { const reqTemplate = new RegExp("^[0-9.]+", "i"); if (reqTemplate.exec(value)) { const wbs2 = reqTemplate.exec(value)[0]; const task = this._gantt.getTaskByWBSCode(wbs2); if (task) { return task.id; } } return null; }; this._linkReg = /^[0-9\.]+/; this._gantt = gantt2; } }; _LinkFormatterSimple.create = (settings = null, gantt2) => new _LinkFormatterSimple(gantt2); let LinkFormatterSimple = _LinkFormatterSimple; function formatters(gantt2) { gantt2.ext.formatters = { durationFormatter: function(settings) { if (!settings) { settings = {}; } if (!settings.store) { settings.store = gantt2.config.duration_unit; } if (!settings.enter) { settings.enter = gantt2.config.duration_unit; } return DurationFormatterNumeric.create(settings, gantt2); }, linkFormatter: function(settings) { return LinkFormatterSimple.create(settings, gantt2); } }; } function empty_state_screen(gantt2) { gantt2.ext = gantt2.ext || {}; gantt2.config.show_empty_state = false; gantt2.ext.emptyStateElement = gantt2.ext.emptyStateElement || { isEnabled() { return gantt2.config.show_empty_state === true; }, isGanttEmpty() { return !gantt2.getTaskByTime().length; }, renderContent(container) { const placeholderTextElement = `
${gantt2.locale.labels.empty_state_text_description}
`; const placeholderImageElement = "
"; const placeholderContainer = `
${placeholderImageElement}${placeholderTextElement}
`; container.innerHTML = placeholderContainer; }, clickEvents: [], attachAddTaskEvent() { const id = gantt2.attachEvent("onEmptyClick", function(e) { const domHelpers2 = gantt2.utils.dom; const gridPlaceholder = domHelpers2.closest(e.target, "[data-empty-state-create-task]"); if (gridPlaceholder) { gantt2.createTask({ id: gantt2.uid(), text: "New Task" }); } }); this.clickEvents.push(id); }, detachAddTaskEvents() { this.clickEvents.forEach(function(event2) { gantt2.detachEvent(event2); }); this.clickEvents = []; }, getContainer() { if (gantt2.$container) { const domHelpers2 = gantt2.utils.dom; if (gantt2.$container.contains(gantt2.$grid_data)) { return domHelpers2.closest(gantt2.$grid_data, ".gantt_layout_content"); } if (gantt2.$container.contains(gantt2.$task_data)) { return domHelpers2.closest(gantt2.$task_data, ".gantt_layout_content"); } } return null; }, getNode() { const container = this.getContainer(); if (!container) { return null; } const emptyStateElementNode = container.querySelector(".gantt_empty_state_wrapper"); return emptyStateElementNode; }, show() { const container = this.getContainer(); if (!container && this.isGanttEmpty()) { return null; } const wrapper = document.createElement("div"); wrapper.className = "gantt_empty_state_wrapper"; wrapper.style.marginTop = gantt2.config.scale_height - container.offsetHeight + "px"; const oldNodes = gantt2.$container.querySelectorAll(".gantt_empty_state_wrapper"); Array.prototype.forEach.call(oldNodes, function(node) { node.parentNode.removeChild(node); }); this.detachAddTaskEvents(); this.attachAddTaskEvent(); container.appendChild(wrapper); this.renderContent(wrapper); }, hide() { const emptyStateElementNode = this.getNode(); if (emptyStateElementNode) { emptyStateElementNode.parentNode.removeChild(emptyStateElementNode); } else { return false; } }, init() { } }; gantt2.attachEvent("onDataRender", function() { const emptyStateElement = gantt2.ext.emptyStateElement; if (emptyStateElement.isEnabled() && emptyStateElement.isGanttEmpty()) { emptyStateElement.show(); } else { emptyStateElement.hide(); } }); } const hasBaselinesBelow = function(gantt2, task) { const baselines2 = task.baselines && task.baselines.length; const baselinesOnDifferentRow = gantt2.config.baselines.render_mode == "separateRow" || gantt2.config.baselines.render_mode == "individualRow"; if (baselines2 && baselinesOnDifferentRow) { return true; } }; const childrenHaveBaselines = function(gantt2, taskId) { let hasBaselines = false; gantt2.eachTask(function(child) { if (hasBaselines) { return; } hasBaselines = hasBaselinesBelow(gantt2, child); }, taskId); return hasBaselines; }; const isSplitParent = function(task) { return task.render && task.render == "split" && !task.$open; }; const getMaxParentHeight = function(gantt2, view, task, heightLimit) { let maxHeight = heightLimit || view.$task_data.scrollHeight; let shrinkHeight = false; let splitChild = false; gantt2.eachParent(function(parent) { if (isSplitParent(parent)) { splitChild = true; const parentSizes = view.getItemPosition(parent); const parentHeight = parentSizes.rowHeight; if (parentHeight < maxHeight) { maxHeight = parentHeight; shrinkHeight = true; } } }, task.id); return { maxHeight, shrinkHeight, splitChild }; }; function baselines(gantt2) { gantt2.config.baselines = { datastore: "baselines", render_mode: false, dataprocessor_baselines: false, row_height: 16, bar_height: 8 }; function initBaselineFields(item, task) { if (!item.task_id || !item.start_date && !item.end_date) { return false; } if (item.start_date) { item.start_date = gantt2.date.parseDate(item.start_date, "parse_date"); } else { item.start_date = null; } if (item.end_date) { item.end_date = gantt2.date.parseDate(item.end_date, "parse_date"); } else { item.end_date = null; } item.duration = item.duration || 1; if (item.start_date && !item.end_date) { item.end_date = gantt2.calculateEndDate(item.start_date, item.duration); } else if (item.end_date && !item.start_date) { item.start_date = gantt2.calculateEndDate(item.end_date, -item.duration); } } const baselineStore = gantt2.createDatastore({ name: gantt2.config.baselines.datastore, initItem: function(item) { if (!item.id) { item.id = gantt2.uid(); } initBaselineFields(item); return item; } }); gantt2.$data.baselineStore = baselineStore; function _syncBaselines(task) { let shouldRepaint = false; const iteratedBaselines = {}; const taskBaselines = task.baselines || []; const exisingBaselines = gantt2.getTaskBaselines(task.id); if (taskBaselines.length != exisingBaselines.length) { shouldRepaint = true; } taskBaselines.forEach(function(baseline) { iteratedBaselines[baseline.id] = true; const exisingBaseline = baselineStore.getItem(baseline.id); if (exisingBaseline) { const start = +exisingBaseline.start_date !== +baseline.start_date; const end = +exisingBaseline.end_date !== +baseline.end_date; if (start || end) { baselineStore.updateItem(baseline.id, baseline); } } else { baselineStore.addItem(baseline); } }); exisingBaselines.forEach(function(baseline) { if (!iteratedBaselines[baseline.id]) { baselineStore.removeItem(baseline.id); } }); if (shouldRepaint) { if (isSplitParent(task)) { _adjustSplitParentHeight(task); } else { gantt2.adjustTaskHeightForBaselines(task); } gantt2.render(); } } function _deleteOrphanBaselines() { baselineStore.eachItem(function(baseline) { if (!gantt2.isTaskExists(baseline.task_id)) { baselineStore.removeItem(baseline.id); } }); } function _adjustSplitParentHeight(task) { let maxParentHeight = 0; gantt2.adjustTaskHeightForBaselines(task); gantt2.eachTask(function(child) { let childHeight = child.row_height || gantt2.config.row_height; maxParentHeight = maxParentHeight || childHeight; if (childHeight > maxParentHeight) { maxParentHeight = childHeight; } }, task.id); if (task.row_height < maxParentHeight) { task.row_height = maxParentHeight; } } gantt2.adjustTaskHeightForBaselines = function(task) { let height, baselineSize; let margins = 2; let baselineAmount = task.baselines && task.baselines.length || 0; const subrowHeight = gantt2.config.baselines.row_height; const timelineView = gantt2.getLayoutView("timeline"); if (!timelineView || !gantt2.config.show_chart) { return; } switch (gantt2.config.baselines.render_mode) { case "taskRow": task.row_height = task.bar_height + 8; break; case "separateRow": height = timelineView.getBarHeight(task.id); if (baselineAmount) { task.bar_height = task.bar_height || height; if (task.bar_height > height) { height = task.bar_height; } task.row_height = height + subrowHeight; } else if (task.bar_height) { task.row_height = task.bar_height + 4; } _increaseSplitParentHeight(task); break; case "individualRow": height = timelineView.getBarHeight(task.id); if (baselineAmount) { task.bar_height = task.bar_height || height; if (task.bar_height > height) { height = task.bar_height; } baselineSize = subrowHeight * baselineAmount; task.row_height = height + baselineSize + margins; } else if (task.bar_height) { task.row_height = task.bar_height + 4; } _increaseSplitParentHeight(task); break; default: task.row_height = task.bar_height + 8; break; } }; function _increaseSplitParentHeight(task) { gantt2.eachParent(function(parent) { if (isSplitParent(parent)) { const parentHeight = parent.row_height || gantt2.getLayoutView("timeline").getBarHeight(parent.id); let maxHeight = task.row_height; const subtasks = gantt2.getChildren(parent.id); subtasks.forEach(function(subtaskId) { const subtask = gantt2.getTask(subtaskId); if (subtask.id == task.id) { return; } const subtaskHeight = subtask.row_height || gantt2.getLayoutView("timeline").getBarHeight(subtask.id); maxHeight = maxHeight || subtaskHeight; if (subtaskHeight > maxHeight) { maxHeight = subtaskHeight; } }); parent.row_height = maxHeight; parent.bar_height = parent.bar_height || parentHeight; } }, task.id); } gantt2.attachEvent("onGanttReady", function() { if (!gantt2.config.baselines) { return; } gantt2.attachEvent("onParse", function() { baselineStore.eachItem(function(baseline) { const taskId = baseline.task_id; if (gantt2.isTaskExists(taskId)) { const task = gantt2.getTask(taskId); task.baselines = task.baselines || []; let newBaseline = true; for (let i = 0; i < task.baselines.length; i++) { let existingBaseline = task.baselines[i]; if (existingBaseline.id == baseline.id) { newBaseline = false; gantt2.mixin(existingBaseline, baseline, true); break; } } if (newBaseline) { task.baselines.push(baseline); } if (!isHeadless(gantt2)) { if (isSplitParent(task)) { _adjustSplitParentHeight(task); } else { gantt2.adjustTaskHeightForBaselines(task); } } } }); }); gantt2.attachEvent("onBeforeTaskUpdate", function(id, task) { _syncBaselines(task); return true; }); gantt2.attachEvent("onAfterUndo", function(action) { const baselinesRenderedBelow = gantt2.config.baselines.render_mode == "separateRow" || gantt2.config.baselines.render_mode == "individualRow"; if (baselinesRenderedBelow && action) { let repaint = false; action.commands.forEach(function(command) { if (command.entity == "task") { const taskId = command.value.id; if (gantt2.isTaskExists(taskId)) { const task = gantt2.getTask(taskId); if (task.parent && gantt2.isTaskExists(task.parent)) { const parent = gantt2.getTask(task.parent); if (isSplitParent(parent)) { _adjustSplitParentHeight(parent); repaint = true; } } } } }); if (repaint) { gantt2.render(); } } }); gantt2.attachEvent("onAfterTaskDelete", function(id, task) { if (hasBaselinesBelow) { if (task.parent && gantt2.isTaskExists(task.parent)) { const parent = gantt2.getTask(task.parent); if (isSplitParent(parent)) { _adjustSplitParentHeight(parent); } } } _deleteOrphanBaselines(); }); gantt2.getTaskBaselines = function(taskId) { const baselines2 = []; baselineStore.eachItem(function(baseline) { if (baseline.task_id == taskId) { baselines2.push(baseline); } }); return baselines2; }; gantt2.$data.baselineStore.attachEvent("onClearAll", function() { gantt2.eachTask(function(task) { if (task.baselines) { delete task.baselines; } }); return true; }); gantt2.$data.tasksStore.attachEvent("onClearAll", function() { baselineStore.clearAll(); return true; }); gantt2.attachEvent("onTaskIdChange", function(id, new_id) { const baselines2 = baselineStore.find(function(a) { return a.task_id == id; }); baselines2.forEach(function(a) { a.task_id = new_id; baselineStore.updateItem(a.id); }); }); }, { once: true }); } class RemoteEvents { constructor(url, token) { const remote = new t({ url, token }); remote.fetch = function(url2, body) { const req = { headers: this.headers() }; if (body) { req.method = "POST"; req.body = body; } return fetch(url2, req).then((res) => res.json()); }; this._ready = remote.load().then((back) => this._remote = back); } ready() { return this._ready; } on(name, handler) { this.ready().then((back) => { if (typeof name === "string") back.on(name, handler); else { for (const key in name) { back.on(key, name[key]); } } }); } } function createHandlers(gantt2) { let updateQueue = []; let updateTimeout = null; const UPDATE_DELAY = 50; function remoteUpdates(message) { var _a, _b; if (!message || !message.type || !(((_a = message.task) == null ? void 0 : _a.id) || ((_b = message.link) == null ? void 0 : _b.id))) { console.error("Invalid message format:", message); return; } const { type, task, link } = message; if (task && gantt2._dp._in_progress[task.id] || link && gantt2._dp._in_progress[link.id]) { return; } if (type === "add-task") { for (const id in gantt2._dp._in_progress) { if (gantt2._dp.getState(id) === "inserted") { gantt2._dp.attachEvent("onFullSync", function() { if (!gantt2.isTaskExists(task.id)) { processUpdate(message); } }, { once: true }); return; } } } updateQueue.push(message); if (updateTimeout) clearTimeout(updateTimeout); updateTimeout = setTimeout(processQueue, UPDATE_DELAY); } function processQueue() { if (updateQueue.length === 0) { return; } if (updateQueue.length === 1) { processUpdate(updateQueue[0]); } else { gantt2.batchUpdate(function() { updateQueue.forEach((message) => { processUpdate(message); }); }); } updateQueue = []; } function processUpdate(message) { const { type, task, link } = message; switch (type) { case "add-task": handleAddTask(task); break; case "update-task": handleUpdateTask(task); break; case "delete-task": handleDeleteTask(task); break; case "add-link": handleAddLink(link); break; case "update-link": handleUpdateLink(link); break; case "delete-link": handleDeleteLink(link); break; } } function ignore(code) { if (gantt2._dp) { gantt2._dp.ignore(code); } else { code(); } } function handleAddTask(taskData) { if (gantt2.isTaskExists(taskData.id)) { console.warn(`Task with ID ${taskData.id} already exists. Skipping add.`); return; } taskData.start_date = gantt2.templates.parse_date(taskData.start_date); if (taskData.end_date) taskData.end_date = gantt2.templates.parse_date(taskData.end_date); ignore(() => { gantt2.addTask(taskData); }); } function handleUpdateTask(taskData) { const sid = taskData.id; if (!gantt2.getTask(sid)) { console.warn(`Task with ID ${sid} does not exist. Skipping update.`); return; } const initTask = gantt2.getDatastore("task").$initItem.bind(gantt2.getDatastore("task")); const existingTask = gantt2.getTask(sid); ignore(() => { const remoteTask = initTask(taskData); for (let key in remoteTask) { existingTask[key] = remoteTask[key]; } if (!remoteTask.end_date) { existingTask.end_date = gantt2.calculateEndDate(existingTask); } gantt2.updateTask(sid); if (sid !== taskData.id) { gantt2.changeTaskId(sid, taskData.id); } }); } function handleDeleteTask(taskData) { const sid = taskData.id; if (!gantt2.isTaskExists(sid)) { return; } ignore(() => { const task = gantt2.getTask(sid); if (task) { if (gantt2.getState().lightbox_id == sid) { taskData.id = this._lightbox_id; gantt2.getTask(this._lightbox_id); } gantt2.deleteTask(sid, true); } }); } function handleAddLink(linkData) { if (gantt2.isLinkExists(linkData.id)) { console.warn(`Link with ID ${linkData.id} already exists. Skipping add.`); return; } ignore(() => { gantt2.addLink(linkData); }); } function handleUpdateLink(linkData) { const sid = linkData.id; if (!gantt2.isLinkExists(sid)) { console.warn(`Link with ID ${sid} does not exist. Skipping update.`); return; } const existingLink = gantt2.getLink(sid); ignore(() => { Object.assign(existingLink, linkData); gantt2.updateLink(sid); if (sid !== linkData.id) { gantt2.changeLinkId(sid, linkData.id); } }); } function handleDeleteLink(linkData) { const sid = linkData.id; if (!gantt2.getLink(sid)) { return; } ignore(() => { const task = gantt2.getLink(sid); if (task) { if (gantt2.getState().lightbox_id == sid) { linkData.id = this._lightbox_id; gantt2.getLink(this._lightbox_id); } gantt2.deleteLink(sid, true); } }); } return { tasks: remoteUpdates, links: remoteUpdates }; } function remoteEvents(gantt2) { if (!gantt2.ext) { gantt2.ext = {}; } gantt2.ext.liveUpdates = { RemoteEvents, remoteUpdates: createHandlers(gantt2) }; } function auto_scheduling_config(gantt2) { function getDefaultAutoSchedulingConfig() { return { enabled: false, apply_constraints: false, gap_behavior: "preserve", descendant_links: false, schedule_on_parse: true, move_projects: true, use_progress: false, schedule_from_end: false, project_constraint: false, show_constraints: false }; } function getAutoSchedulingConfig() { const config2 = gantt2.config; if (typeof config2.auto_scheduling === "object") { const schedulingConfig = { ...getDefaultAutoSchedulingConfig(), ...config2.auto_scheduling }; if (schedulingConfig.mode) { schedulingConfig.apply_constraints = schedulingConfig.mode === "constraints"; delete schedulingConfig.mode; } if (schedulingConfig.strict !== void 0) { schedulingConfig.gap_behavior = schedulingConfig.strict ? "compress" : "preserve"; delete schedulingConfig.strict; } if (schedulingConfig.move_asap_tasks !== void 0) { schedulingConfig.gap_behavior = schedulingConfig.move_asap_tasks ? "compress" : "preserve"; delete schedulingConfig.move_asap_tasks; } return schedulingConfig; } const enabled = !!config2.auto_scheduling; return { ...getDefaultAutoSchedulingConfig(), ...{ enabled, apply_constraints: config2.auto_scheduling_compatibility ?? false, gap_behavior: config2.auto_scheduling_strict !== true ? "preserve" : "compress", descendant_links: config2.auto_scheduling_descendant_links ?? false, schedule_on_parse: config2.auto_scheduling_initial ?? true, move_projects: config2.auto_scheduling_move_projects ?? true, use_progress: config2.auto_scheduling_use_progress ?? false, schedule_from_end: config2.schedule_from_end ?? false, project_constraint: config2.auto_scheduling_project_constraint ?? false, show_constraints: false } }; } return { getDefaultAutoSchedulingConfig, getAutoSchedulingConfig }; } function plugins$1(gantt2) { if (!gantt2.ext) { gantt2.ext = {}; } var modules = [batch_update, wbs, resources, resource_assignments, addPlaceholder, auto_task_types, formatters, empty_state_screen, baselines, remoteEvents]; for (var i = 0; i < modules.length; i++) { if (modules[i]) modules[i](gantt2); } const { getAutoSchedulingConfig } = auto_scheduling_config(gantt2); gantt2._getAutoSchedulingConfig = getAutoSchedulingConfig; } function grid_column_api(gantt2) { gantt2.getGridColumn = function(name) { var columns = gantt2.config.columns; for (var i = 0; i < columns.length; i++) { if (columns[i].name == name) return columns[i]; } return null; }; gantt2.getGridColumns = function() { return gantt2.config.columns.slice(); }; } function tasks(gantt2) { gantt2.isReadonly = function(item) { if ((typeof item == "number" || typeof item == "string") && gantt2.isTaskExists(item)) { item = gantt2.getTask(item); } if (item && item[this.config.editable_property]) { return false; } else { return item && item[this.config.readonly_property] || this.config.readonly; } }; } function parsing(gantt2) { gantt2.load = function() { throw new Error("gantt.load() method is not available in the node.js, use gantt.parse() instead"); }; gantt2.parse = function(data2, type) { this.on_load({ xmlDoc: { responseText: data2 } }, type); }; gantt2.serialize = function(type) { type = type || "json"; return this[type].serialize(); }; gantt2.on_load = function(resp, type) { if (resp.xmlDoc && resp.xmlDoc.status === 404) { this.assert(false, "Failed to load the data from " + resp.xmlDoc.responseURL + ", server returns 404"); return; } if (gantt2.$destroyed) { return; } this.callEvent("onBeforeParse", []); if (!type) type = "json"; this.assert(this[type], "Invalid data type:'" + type + "'"); var raw = resp.xmlDoc.responseText; var data2 = this[type].parse(raw, resp); this._process_loading(data2); }; function attachAssignmentsToTasks(tasks2, assignments) { const assignmentsByTasks = {}; assignments.forEach((a) => { if (!assignmentsByTasks[a.task_id]) { assignmentsByTasks[a.task_id] = []; } assignmentsByTasks[a.task_id].push(a); }); tasks2.forEach((t2) => { t2[gantt2.config.resource_property] = assignmentsByTasks[t2.id] || []; }); } gantt2._process_loading = function(data2) { if (data2.collections) this._load_collections(data2.collections); if (data2.resources && this.$data.resourcesStore) { this.$data.resourcesStore.parse(data2.resources); } if (gantt2.config.baselines && data2.baselines && this.$data.baselineStore) { this.$data.baselineStore.parse(data2.baselines); } const tasks2 = data2.data || data2.tasks; if (data2.assignments) { attachAssignmentsToTasks(tasks2 && tasks2.length ? tasks2 : gantt2.getTasksByTime(), data2.assignments); } if (tasks2) { this.$data.tasksStore.parse(tasks2); } var links = data2.links || (data2.collections && data2.collections.links ? data2.collections.links : []); this.$data.linksStore.parse(links); this.callEvent("onParse", []); this.render(); }; gantt2._load_collections = function(collections) { var collections_loaded = false; for (var key in collections) { if (collections.hasOwnProperty(key)) { collections_loaded = true; var collection = collections[key]; this.serverList[key] = this.serverList[key] || []; var arr = this.serverList[key]; if (!arr) continue; arr.splice(0, arr.length); for (var j = 0; j < collection.length; j++) { var option = collection[j]; var obj = this.copy(option); obj.key = obj.value; for (var option_key in option) { if (option.hasOwnProperty(option_key)) { if (option_key == "value" || option_key == "label") continue; obj[option_key] = option[option_key]; } } arr.push(obj); } } } if (collections_loaded) this.callEvent("onOptionsLoad", []); }; gantt2.attachEvent("onBeforeTaskDisplay", function(id, task) { return !task.$ignore; }); function jsonParseError(data2) { gantt2.assert(false, "Can't parse data: incorrect value of gantt.parse or gantt.load method. Actual argument value: " + JSON.stringify(data2)); throw new Error("Invalid argument for gantt.parse or gantt.load. An object or a JSON string of format https://docs.dhtmlx.com/gantt/desktop__supported_data_formats.html#json is expected. Actual argument value: " + JSON.stringify(data2)); } gantt2.json = { parse: function(data2) { if (!data2) { jsonParseError(data2); } if (typeof data2 == "string") { if (typeof JSON != void 0) { try { data2 = JSON.parse(data2); } catch (e) { jsonParseError(data2); } } else { gantt2.assert(false, "JSON is not supported"); } } if (data2.dhx_security) gantt2.security_key = data2.dhx_security; return data2; }, serializeTask: function(task) { return this._copyObject(task); }, serializeLink: function(link) { return this._copyLink(link); }, _copyLink: function(obj) { var copy2 = {}; for (var key in obj) copy2[key] = obj[key]; return copy2; }, _copyObject: function(obj) { var copy2 = {}; for (var key in obj) { if (key.charAt(0) == "$") continue; copy2[key] = obj[key]; if (isDate(copy2[key])) { copy2[key] = gantt2.defined(gantt2.templates.xml_format) ? gantt2.templates.xml_format(copy2[key]) : gantt2.templates.format_date(copy2[key]); } } return copy2; }, serialize: function() { var tasks2 = []; var links = []; let baselines2 = []; gantt2.eachTask(function(obj) { gantt2.resetProjectDates(obj); tasks2.push(this.serializeTask(obj)); }, gantt2.config.root_id, this); var rawLinks = gantt2.getLinks(); for (var i = 0; i < rawLinks.length; i++) { links.push(this.serializeLink(rawLinks[i])); } const baselineStore = gantt2.getDatastore("baselines"); baselineStore.eachItem(function(baseline) { const baselineCopy = gantt2.json.serializeTask(baseline); baselines2.push(baselineCopy); }); return { data: tasks2, links, baselines: baselines2 }; } }; function xmlParseError(data2) { gantt2.assert(false, "Can't parse data: incorrect value of gantt.parse or gantt.load method. Actual argument value: " + JSON.stringify(data2)); throw new Error("Invalid argument for gantt.parse or gantt.load. An XML of format https://docs.dhtmlx.com/gantt/desktop__supported_data_formats.html#xmldhtmlxgantt20 is expected. Actual argument value: " + JSON.stringify(data2)); } gantt2.xml = { _xmlNodeToJSON: function(node, attrs_only) { var t2 = {}; for (var i = 0; i < node.attributes.length; i++) t2[node.attributes[i].name] = node.attributes[i].value; if (!attrs_only) { for (var i = 0; i < node.childNodes.length; i++) { var child = node.childNodes[i]; if (child.nodeType == 1) t2[child.tagName] = child.firstChild ? child.firstChild.nodeValue : ""; } if (!t2.text) t2.text = node.firstChild ? node.firstChild.nodeValue : ""; } return t2; }, _getCollections: function(loader) { var collection = {}; var opts = gantt2.ajax.xpath("//coll_options", loader); for (var i = 0; i < opts.length; i++) { var bind2 = opts[i].getAttribute("for"); var arr = collection[bind2] = []; var itms = gantt2.ajax.xpath(".//item", opts[i]); for (var j = 0; j < itms.length; j++) { var itm = itms[j]; var attrs = itm.attributes; var obj = { key: itms[j].getAttribute("value"), label: itms[j].getAttribute("label") }; for (var k = 0; k < attrs.length; k++) { var attr = attrs[k]; if (attr.nodeName == "value" || attr.nodeName == "label") continue; obj[attr.nodeName] = attr.nodeValue; } arr.push(obj); } } return collection; }, _getXML: function(text, loader, toptag) { toptag = toptag || "data"; if (!loader.getXMLTopNode) { loader = gantt2.ajax.parse(loader); } var xml = gantt2.ajax.xmltop(toptag, loader.xmlDoc); if (!xml || xml.tagName != toptag) { xmlParseError(text); } var skey = xml.getAttribute("dhx_security"); if (skey) gantt2.security_key = skey; return xml; }, parse: function(text, loader) { loader = this._getXML(text, loader); var data2 = {}; var evs = data2.data = []; var xml = gantt2.ajax.xpath("//task", loader); for (var i = 0; i < xml.length; i++) evs[i] = this._xmlNodeToJSON(xml[i]); data2.collections = this._getCollections(loader); return data2; }, _copyLink: function(obj) { return ""; }, _copyObject: function(obj) { return ""; }, serialize: function() { var tasks2 = []; var links = []; var json = gantt2.json.serialize(); for (var i = 0, len = json.data.length; i < len; i++) { tasks2.push(this._copyObject(json.data[i])); } for (var i = 0, len = json.links.length; i < len; i++) { links.push(this._copyLink(json.links[i])); } return "" + tasks2.join("") + "" + links.join("") + ""; } }; gantt2.oldxml = { parse: function(text, loader) { loader = gantt2.xml._getXML(text, loader, "projects"); var data2 = { collections: { links: [] } }; var evs = data2.data = []; var xml = gantt2.ajax.xpath("//task", loader); for (var i = 0; i < xml.length; i++) { evs[i] = gantt2.xml._xmlNodeToJSON(xml[i]); var parent = xml[i].parentNode; if (parent.tagName == "project") evs[i].parent = "project-" + parent.getAttribute("id"); else evs[i].parent = parent.parentNode.getAttribute("id"); } xml = gantt2.ajax.xpath("//project", loader); for (var i = 0; i < xml.length; i++) { var ev = gantt2.xml._xmlNodeToJSON(xml[i], true); ev.id = "project-" + ev.id; evs.push(ev); } for (var i = 0; i < evs.length; i++) { var ev = evs[i]; ev.start_date = ev.startdate || ev.est; ev.end_date = ev.enddate; ev.text = ev.name; ev.duration = ev.duration / 8; ev.open = 1; if (!ev.duration && !ev.end_date) ev.duration = 1; if (ev.predecessortasks) data2.collections.links.push({ target: ev.id, source: ev.predecessortasks, type: gantt2.config.links.finish_to_start }); } return data2; }, serialize: function() { gantt2.message("Serialization to 'old XML' is not implemented"); } }; gantt2.serverList = function(name, array) { if (array) { this.serverList[name] = array.slice(0); } else if (!this.serverList[name]) { this.serverList[name] = []; } return this.serverList[name]; }; } function IsWorkTimeArgument(date2, unit, task, id, calendar) { this.date = date2; this.unit = unit; this.task = task; this.id = id; this.calendar = calendar; return this; } function ClosestWorkTimeArgument(date2, dir, unit, task, id, calendar) { this.date = date2; this.dir = dir; this.unit = unit; this.task = task; this.id = id; this.calendar = calendar; return this; } function CalculateEndDateArgument(start_date, duration, unit, step, task, id, calendar) { this.start_date = start_date; this.duration = duration; this.unit = unit; this.step = step; this.task = task; this.id = id; this.calendar = calendar; return this; } function GetDurationArgument(start, end, task, calendar) { this.start_date = start; this.end_date = end; this.task = task; this.calendar = calendar; this.unit = null; this.step = null; return this; } var calendarArgumentsHelper = function(gantt2) { return { getWorkHoursArguments: function() { var config2 = arguments[0]; if (isDate(config2)) { config2 = { date: config2 }; } else { config2 = mixin({}, config2); } if (!isValidDate(config2.date)) { gantt2.assert(false, "Invalid date argument for getWorkHours method"); throw new Error("Invalid date argument for getWorkHours method"); } return config2; }, setWorkTimeArguments: function() { return arguments[0]; }, unsetWorkTimeArguments: function() { return arguments[0]; }, isWorkTimeArguments: function() { var config2 = arguments[0]; if (config2 instanceof IsWorkTimeArgument) { return config2; } var processedConfig; if (!config2.date) { processedConfig = new IsWorkTimeArgument(arguments[0], arguments[1], arguments[2], null, arguments[3]); } else { processedConfig = new IsWorkTimeArgument(config2.date, config2.unit, config2.task, null, config2.calendar); } processedConfig.unit = processedConfig.unit || gantt2.config.duration_unit; if (!isValidDate(processedConfig.date)) { gantt2.assert(false, "Invalid date argument for isWorkTime method"); throw new Error("Invalid date argument for isWorkTime method"); } return processedConfig; }, getClosestWorkTimeArguments: function(arg) { var config2 = arguments[0]; if (config2 instanceof ClosestWorkTimeArgument) return config2; var processedConfig; if (isDate(config2)) { processedConfig = new ClosestWorkTimeArgument(config2); } else { processedConfig = new ClosestWorkTimeArgument(config2.date, config2.dir, config2.unit, config2.task, null, config2.calendar); } if (config2.id) { processedConfig.task = config2; } processedConfig.dir = config2.dir || "any"; processedConfig.unit = config2.unit || gantt2.config.duration_unit; if (!isValidDate(processedConfig.date)) { gantt2.assert(false, "Invalid date argument for getClosestWorkTime method"); throw new Error("Invalid date argument for getClosestWorkTime method"); } return processedConfig; }, _getStartEndConfig: function(param) { var argumentType = GetDurationArgument; var config2; if (param instanceof argumentType) return param; if (isDate(param)) { config2 = new argumentType(arguments[0], arguments[1], arguments[2], arguments[3]); } else { config2 = new argumentType(param.start_date, param.end_date, param.task); if (param.id !== null && param.id !== void 0) { config2.task = param; } } config2.unit = config2.unit || gantt2.config.duration_unit; config2.step = config2.step || gantt2.config.duration_step; config2.start_date = config2.start_date || config2.start || config2.date; if (!isValidDate(config2.start_date)) { gantt2.assert(false, "Invalid start_date argument for getDuration method"); throw new Error("Invalid start_date argument for getDuration method"); } if (!isValidDate(config2.end_date)) { gantt2.assert(false, "Invalid end_date argument for getDuration method"); throw new Error("Invalid end_date argument for getDuration method"); } return config2; }, getDurationArguments: function(start, end, unit, step) { return this._getStartEndConfig.apply(this, arguments); }, hasDurationArguments: function(start, end, unit, step) { return this._getStartEndConfig.apply(this, arguments); }, calculateEndDateArguments: function(start, duration, unit, step) { var config2 = arguments[0]; if (config2 instanceof CalculateEndDateArgument) return config2; var processedConfig; if (isDate(config2)) { processedConfig = new CalculateEndDateArgument(arguments[0], arguments[1], arguments[2], void 0, arguments[3], void 0, arguments[4]); } else { processedConfig = new CalculateEndDateArgument(config2.start_date, config2.duration, config2.unit, config2.step, config2.task, null, config2.calendar); } if (config2.id !== null && config2.id !== void 0) { processedConfig.task = config2; processedConfig.unit = null; processedConfig.step = null; } processedConfig.unit = processedConfig.unit || gantt2.config.duration_unit; processedConfig.step = processedConfig.step || gantt2.config.duration_step; if (!isValidDate(processedConfig.start_date)) { gantt2.assert(false, "Invalid start_date argument for calculateEndDate method"); throw new Error("Invalid start_date argument for calculateEndDate method"); } return processedConfig; } }; }; function WorkTimeCalendarMerger() { } WorkTimeCalendarMerger.prototype = { _getIntervals: function(hoursArray) { var result = []; for (var i = 0; i < hoursArray.length; i += 2) { result.push({ start: hoursArray[i], end: hoursArray[i + 1] }); } return result; }, _toHoursArray: function(intervalsArray) { var result = []; function toFixed(value) { var str = String(value); if (str.length < 2) { str = "0" + str; } return str; } function formatHHMM(secondsValue) { var hours = Math.floor(secondsValue / (60 * 60)); var minutePart = secondsValue - hours * 60 * 60; var minutes = Math.floor(minutePart / 60); return hours + ":" + toFixed(minutes); } for (var i = 0; i < intervalsArray.length; i++) { result.push(formatHHMM(intervalsArray[i].start) + "-" + formatHHMM(intervalsArray[i].end)); } return result; }, _intersectHourRanges: function(first, second) { var result = []; var baseArray = first.length > second.length ? first : second; var overridesArray = first === baseArray ? second : first; baseArray = baseArray.slice(); overridesArray = overridesArray.slice(); var result = []; for (var i = 0; i < baseArray.length; i++) { var base2 = baseArray[i]; for (var j = 0; j < overridesArray.length; j++) { var current = overridesArray[j]; if (current.start < base2.end && current.end > base2.start) { result.push({ start: Math.max(base2.start, current.start), end: Math.min(base2.end, current.end) }); if (base2.end > current.end) { overridesArray.splice(j, 1); j--; i--; } } } } return result; }, _mergeAdjacentIntervals: function(parts) { var result = parts.slice(); result.sort(function(a, b) { return a.start - b.start; }); var base2 = result[0]; for (var i = 1; i < result.length; i++) { var current = result[i]; if (current.start <= base2.end) { if (current.end > base2.end) { base2.end = current.end; } result.splice(i, 1); i--; } else { base2 = current; } } return result; }, _mergeHoursConfig: function(firstHours, secondHours) { return this._mergeAdjacentIntervals(this._intersectHourRanges(firstHours, secondHours)); }, merge: function(first, second) { const firstCalendar = copy(first.getConfig()); const secondCalendar = copy(second.getConfig()); const firstConfig = firstCalendar.parsed; const secondConfig = secondCalendar.parsed; firstConfig.customWeeks = firstCalendar.customWeeks; secondConfig.customWeeks = secondCalendar.customWeeks; var mergedSettings = { hours: this._toHoursArray(this._mergeHoursConfig(firstConfig.hours, secondConfig.hours)), dates: {}, customWeeks: {} }; const processCalendar = (config1, config2) => { for (let i2 in config1.dates) { const date1 = config1.dates[i2]; if (+i2 > 1e3) { mergedSettings.dates[i2] = false; } for (const key in config2.dates) { const date2 = config2.dates[key]; if (key == i2) { mergedSettings.dates[i2] = !!(date1 && date2); } if (Array.isArray(date1)) { const hours2 = Array.isArray(date2) ? date2 : config2.hours; mergedSettings.dates[i2] = this._toHoursArray(this._mergeHoursConfig(date1, hours2)); } } } }; processCalendar(firstConfig, secondConfig); processCalendar(secondConfig, firstConfig); if (firstConfig.customWeeks) { for (var i in firstConfig.customWeeks) { mergedSettings.customWeeks[i] = firstConfig.customWeeks[i]; } } if (secondConfig.customWeeks) { for (var i in secondConfig.customWeeks) { if (mergedSettings.customWeeks[i]) { mergedSettings.customWeeks[i + "_second"] = secondConfig.customWeeks[i]; } else { mergedSettings.customWeeks[i] = secondConfig.customWeeks[i]; } } } return mergedSettings; } }; class WorkUnitsMapCache { constructor() { this.clear(); } getItem(unit, timestamp, value) { if (this._cache.has(unit)) { const unitCache = this._cache.get(unit); const subCache = unitCache[value.getFullYear()]; if (subCache && subCache.has(timestamp)) { return subCache.get(timestamp); } } return -1; } setItem(unit, timestamp, value, rawValue) { if (!unit || !timestamp) { return; } const cache = this._cache; const year = rawValue.getFullYear(); let unitCache; if (!cache.has(unit)) { unitCache = []; cache.set(unit, unitCache); } else { unitCache = cache.get(unit); } let yearCache = unitCache[year]; if (!yearCache) { yearCache = unitCache[year] = /* @__PURE__ */ new Map(); } yearCache.set(timestamp, value); } clear() { this._cache = /* @__PURE__ */ new Map(); } } class WorkUnitsObjectCache { constructor() { this.clear(); } getItem(unit, timestamp, value) { const cache = this._cache; if (cache && cache[unit]) { const units2 = cache[unit]; if (units2 === void 0) { return -1; } const subCache = units2[value.getFullYear()]; if (subCache && subCache[timestamp] !== void 0) { return subCache[timestamp]; } } return -1; } setItem(unit, timestamp, value, rawValue) { if (!unit || !timestamp) { return; } const cache = this._cache; if (!cache) { return; } if (!cache[unit]) { cache[unit] = []; } const unitCache = cache[unit]; const year = rawValue.getFullYear(); let yearCache = unitCache[year]; if (!yearCache) { yearCache = unitCache[year] = {}; } yearCache[timestamp] = value; } clear() { this._cache = {}; } } class LargerUnitsCache { constructor(calendar) { this.getMinutesPerWeek = (weekStart) => { const key = weekStart.valueOf(); if (this._weekCache.has(key)) { return this._weekCache.get(key); } const calendar2 = this._calendar; const gantt2 = this._calendar.$gantt; let minutesPerWeek = 0; let start = gantt2.date.week_start(new Date(weekStart)); for (let i = 0; i < 7; i++) { minutesPerWeek += calendar2.getHoursPerDay(start) * 60; start = gantt2.date.add(start, 1, "day"); } this._weekCache.set(key, minutesPerWeek); return minutesPerWeek; }; this.getMinutesPerMonth = (monthStart) => { const key = monthStart.valueOf(); if (this._monthCache.has(key)) { return this._monthCache.get(key); } const calendar2 = this._calendar; const gantt2 = this._calendar.$gantt; let minutesPerMonth = 0; let start = gantt2.date.week_start(new Date(monthStart)); const nextMonth = gantt2.date.add(start, 1, "month").valueOf(); while (start.valueOf() < nextMonth) { minutesPerMonth += calendar2.getHoursPerDay(start) * 60; start = gantt2.date.add(start, 1, "day"); } this._monthCache.set(key, minutesPerMonth); return minutesPerMonth; }; this.clear = () => { this._weekCache = /* @__PURE__ */ new Map(); this._monthCache = /* @__PURE__ */ new Map(); }; this.clear(); this._calendar = calendar; } } function createCacheObject() { if (typeof Map !== "undefined") { return new WorkUnitsMapCache(); } else { return new WorkUnitsObjectCache(); } } class DateDurationCache { constructor() { this.clear(); } _getCacheObject(startDate, unit, step) { const cache = this._cache; if (!cache[unit]) { cache[unit] = []; } let unitCache = cache[unit]; if (!unitCache) { unitCache = cache[unit] = {}; } let stepCache = unitCache[step]; if (!stepCache) { stepCache = unitCache[step] = {}; } const year = startDate.getFullYear(); let yearCache = stepCache[year]; if (!yearCache) { yearCache = stepCache[year] = { durations: {}, endDates: {} }; } return yearCache; } _endDateCacheKey(startDate, duration) { return String(startDate) + "-" + String(duration); } _durationCacheKey(startDate, endDate) { return String(startDate) + "-" + String(endDate); } getEndDate(startDate, duration, unit, step, compute) { const cache = this._getCacheObject(startDate, unit, step); const startDateTimestamp = startDate.valueOf(); const key = this._endDateCacheKey(startDateTimestamp, duration); let endDate; if (cache.endDates[key] === void 0) { const result = compute(); const resultTimestamp = result.valueOf(); cache.endDates[key] = resultTimestamp; cache.durations[this._durationCacheKey(startDateTimestamp, resultTimestamp)] = duration; endDate = result; } else { endDate = new Date(cache.endDates[key]); } return endDate; } getDuration(startDate, endDate, unit, step, compute) { const cache = this._getCacheObject(startDate, unit, step); const startDateTimestamp = startDate.valueOf(); const endDateTimestamp = endDate.valueOf(); const key = this._durationCacheKey(startDateTimestamp, endDateTimestamp); let duration; if (cache.durations[key] === void 0) { const result = compute(); cache.durations[key] = result.valueOf(); duration = result; } else { duration = cache.durations[key]; } return duration; } clear() { this._cache = {}; } } function CalendarWorkTimeStrategy(gantt2, argumentsHelper) { this.argumentsHelper = argumentsHelper; this.$gantt = gantt2; this._workingUnitsCache = createCacheObject(); this._largeUnitsCache = new LargerUnitsCache(this); this._dateDurationCache = new DateDurationCache(); this._worktime = null; this._cached_timestamps = {}; this._cached_timestamps_count = 0; } CalendarWorkTimeStrategy.prototype = { units: ["year", "month", "week", "day", "hour", "minute"], _clearCaches: function() { this._workingUnitsCache.clear(); this._largeUnitsCache.clear(); this._dateDurationCache.clear(); }, _getUnitOrder: function(unit) { for (var i = 0, len = this.units.length; i < len; i++) { if (this.units[i] == unit) return i; } }, _resetTimestampCache: function() { this._cached_timestamps = {}; this._cached_timestamps_count = 0; }, _timestamp: function(settings) { if (this._cached_timestamps_count > 1e6) { this._resetTimestampCache(); } var timestamp = null; if (settings.day || settings.day === 0) { timestamp = settings.day; } else if (settings.date) { var value = String(settings.date.valueOf()); if (this._cached_timestamps[value]) { timestamp = this._cached_timestamps[value]; } else { timestamp = Date.UTC(settings.date.getFullYear(), settings.date.getMonth(), settings.date.getDate()); this._cached_timestamps[value] = timestamp; this._cached_timestamps_count++; } } return timestamp; }, _checkIfWorkingUnit: function(date2, unit) { if (!this["_is_work_" + unit]) { const from = this.$gantt.date[`${unit}_start`](new Date(date2)); const to = this.$gantt.date.add(from, 1, unit); return this.hasDuration(from, to); } return this["_is_work_" + unit](date2); }, _is_work_day: function(date2) { var val = this._getWorkHours(date2); if (Array.isArray(val)) { return val.length > 0; } return false; }, _is_work_hour: function(date2) { var hours = this._getWorkHours(date2); var value = date2.getHours(); for (var i = 0; i < hours.length; i++) { if (value >= hours[i].startHour && value < hours[i].endHour) { return true; } } return false; }, _getTimeOfDayStamp: function(date2, dayEnd) { var hours = date2.getHours(); if (!date2.getHours() && !date2.getMinutes() && dayEnd) { hours = 24; } return hours * 60 * 60 + date2.getMinutes() * 60; }, _is_work_minute: function(date2) { var hours = this._getWorkHours(date2); var checkTime = this._getTimeOfDayStamp(date2); for (var i = 0; i < hours.length; i++) { if (checkTime >= hours[i].start && checkTime < hours[i].end) { return true; } } return false; }, _nextDate: function(start, unit, step) { return this.$gantt.date.add(start, step, unit); }, _getWorkUnitsBetweenGeneric: function(from, to, unit, step) { var dateHelper = this.$gantt.date; var start = new Date(from), end = new Date(to); step = step || 1; var units2 = 0; var next = null; var stepStart, stepEnd; var checkFirst = false; stepStart = dateHelper[unit + "_start"](new Date(start)); if (stepStart.valueOf() != start.valueOf()) { checkFirst = true; } var checkLast = false; stepEnd = dateHelper[unit + "_start"](new Date(to)); if (stepEnd.valueOf() != to.valueOf()) { checkLast = true; } var isLastStep = false; while (start.valueOf() < end.valueOf()) { next = this._nextDate(start, unit, step); isLastStep = next.valueOf() > end.valueOf(); if (this._isWorkTime(start, unit)) { if (checkFirst || checkLast && isLastStep) { stepStart = dateHelper[unit + "_start"](new Date(start)); stepEnd = dateHelper.add(stepStart, step, unit); } if (checkFirst) { checkFirst = false; next = this._nextDate(stepStart, unit, step); units2 += (stepEnd.valueOf() - start.valueOf()) / (stepEnd.valueOf() - stepStart.valueOf()); } else if (checkLast && isLastStep) { checkLast = false; units2 += (end.valueOf() - start.valueOf()) / (stepEnd.valueOf() - stepStart.valueOf()); } else { units2++; } } else { var unitOrder = this._getUnitOrder(unit); var biggerTimeUnit = this.units[unitOrder - 1]; if (biggerTimeUnit && !this._isWorkTime(start, biggerTimeUnit)) { next = this._getClosestWorkTimeFuture(start, biggerTimeUnit); } } start = next; } return units2; }, _getMinutesPerHour: function(date2) { var hourStart = this._getTimeOfDayStamp(date2); var hourEnd = this._getTimeOfDayStamp(this._nextDate(date2, "hour", 1)); if (hourEnd === 0) { hourEnd = 24 * 60 * 60; } var worktimes = this._getWorkHours(date2); for (var i = 0; i < worktimes.length; i++) { var interval = worktimes[i]; if (hourStart >= interval.start && hourEnd <= interval.end) { return 60; } else if (hourStart < interval.end && hourEnd > interval.start) { var duration = Math.min(hourEnd, interval.end) - Math.max(hourStart, interval.start); return duration / 60; } } return 0; }, _getMinutesPerDay: function(date2) { var hours = this._getWorkHours(date2); var res = 0; hours.forEach(function(interval) { res += interval.durationMinutes; }); return res; }, getHoursPerDay: function(date2) { var hours = this._getWorkHours(date2); var res = 0; hours.forEach(function(interval) { res += interval.durationHours; }); return res; }, _getWorkUnitsForRange: function(from, to, unit, step) { var total = 0; var start = new Date(from), end = new Date(to); var getUnitsPerDay; if (unit == "minute") { getUnitsPerDay = bind(this._getMinutesPerDay, this); } else { getUnitsPerDay = bind(this.getHoursPerDay, this); } while (start.valueOf() < end.valueOf()) { if (end - start > 1e3 * 60 * 60 * 24 * 32 && start.getDate() === 0) { var units2 = this._largeUnitsCache.getMinutesPerMonth(start); if (unit == "hour") { units2 = units2 / 60; } total += units2; start = this.$gantt.date.add(start, 1, "month"); continue; } else if (end - start > 1e3 * 60 * 60 * 24 * 16) { var weekStart = this.$gantt.date.week_start(new Date(start)); if (start.valueOf() === weekStart.valueOf()) { var units2 = this._largeUnitsCache.getMinutesPerWeek(start); if (unit == "hour") { units2 = units2 / 60; } total += units2; start = this.$gantt.date.add(start, 7, "day"); continue; } } total += getUnitsPerDay(start); start = this._nextDate(start, "day", 1); } return total / step; }, _getMinutesBetweenSingleDay: function(from, to) { var range = this._getIntervalTimestamp(from, to); var worktimes = this._getWorkHours(from); var result = 0; for (var i = 0; i < worktimes.length; i++) { var interval = worktimes[i]; if (range.end >= interval.start && range.start <= interval.end) { var minuteFrom = Math.max(interval.start, range.start); var minuteTo = Math.min(interval.end, range.end); result += (minuteTo - minuteFrom) / 60; range.start = minuteTo; } } return Math.floor(result); }, _getMinutesBetween: function(from, to, unit, step) { var start = new Date(from), end = new Date(to); step = step || 1; var firstDayStart = new Date(start); var firstDayEnd = this.$gantt.date.add(this.$gantt.date.day_start(new Date(start)), 1, "day"); if (end.valueOf() <= firstDayEnd.valueOf()) { return this._getMinutesBetweenSingleDay(from, to); } else { var lastDayStart = this.$gantt.date.day_start(new Date(end)); var lastDayEnd = end; var startPart = this._getMinutesBetweenSingleDay(firstDayStart, firstDayEnd); var endPart = this._getMinutesBetweenSingleDay(lastDayStart, lastDayEnd); var rangePart = this._getWorkUnitsForRange(firstDayEnd, lastDayStart, unit, step); var total = startPart + rangePart + endPart; return total; } }, _getHoursBetween: function(from, to, unit, step) { var start = new Date(from), end = new Date(to); step = step || 1; var firstDayStart = new Date(start); var firstDayEnd = this.$gantt.date.add(this.$gantt.date.day_start(new Date(start)), 1, "day"); if (end.valueOf() <= firstDayEnd.valueOf()) { return Math.round(this._getMinutesBetweenSingleDay(from, to) / 60); } else { var lastDayStart = this.$gantt.date.day_start(new Date(end)); var lastDayEnd = end; var startPart = this._getMinutesBetweenSingleDay(firstDayStart, firstDayEnd, unit, step) / 60; var endPart = this._getMinutesBetweenSingleDay(lastDayStart, lastDayEnd, unit, step) / 60; var rangePart = this._getWorkUnitsForRange(firstDayEnd, lastDayStart, unit, step); var total = startPart + rangePart + endPart; return Math.round(total); } }, getConfig: function() { return this._worktime; }, _setConfig: function(settings) { this._worktime = settings; this._parseSettings(); this._clearCaches(); }, _parseSettings: function() { var settings = this.getConfig(); settings.parsed = { dates: {}, hours: null, haveCustomWeeks: false, customWeeks: {}, customWeeksRangeStart: null, customWeeksRangeEnd: null, customWeeksBoundaries: [] }; settings.parsed.hours = this._parseHours(settings.hours); for (var i in settings.dates) { settings.parsed.dates[i] = this._parseHours(settings.dates[i]); } if (settings.customWeeks) { var minCustomRangeStart = null; var maxCustomRangeEnd = null; for (var i in settings.customWeeks) { var customTime = settings.customWeeks[i]; if (customTime.from && customTime.to) { var rangeStart = customTime.from; var rangeEnd = customTime.to; if (!minCustomRangeStart || minCustomRangeStart > rangeStart.valueOf()) { minCustomRangeStart = rangeStart.valueOf(); } if (!maxCustomRangeEnd || maxCustomRangeEnd < rangeEnd.valueOf()) { maxCustomRangeEnd = rangeEnd.valueOf(); } settings.parsed.customWeeksBoundaries.push({ from: rangeStart.valueOf(), fromReadable: new Date(rangeStart), to: rangeEnd.valueOf(), toReadable: new Date(rangeEnd), name: i }); settings.parsed.haveCustomWeeks = true; var currentWeek = settings.parsed.customWeeks[i] = { from: customTime.from, to: customTime.to, hours: this._parseHours(customTime.hours), dates: {} }; if (customTime.days && !customTime.dates) { customTime.dates = customTime.dates || {}; for (var i = 0; i < customTime.days.length; i++) { customTime.dates[i] = customTime.days[i]; if (!(customTime.days[i] instanceof Array)) { customTime.dates[i] = !!customTime.days[i]; } } delete customTime.days; } for (var d in customTime.dates) { currentWeek.dates[d] = this._parseHours(customTime.dates[d]); } } } settings.parsed.customWeeksRangeStart = minCustomRangeStart; settings.parsed.customWeeksRangeEnd = maxCustomRangeEnd; } }, _tryChangeCalendarSettings: function(payload) { var backup = JSON.stringify(this.getConfig()); payload(); if (!this.hasWorkTime()) { this._setConfig(JSON.parse(backup)); this._clearCaches(); return false; } return true; }, _arraysEqual: function(a, b) { if (a === b) return true; if (!a || !b) return false; if (a.length != b.length) return false; for (var i = 0; i < a.length; ++i) { if (a[i] !== b[i]) return false; } return true; }, _compareSettings: function(mySettings, thatSettings) { if (!this._arraysEqual(mySettings.hours, thatSettings.hours)) { return false; } var myDays = Object.keys(mySettings.dates); var otherDates = Object.keys(thatSettings.dates); myDays.sort(); otherDates.sort(); if (!this._arraysEqual(myDays, otherDates)) { return false; } for (var i = 0; i < myDays.length; i++) { var timestamp = myDays[i]; var myHours = mySettings.dates[timestamp]; var otherHours = mySettings.dates[timestamp]; if (myHours !== otherHours && !(Array.isArray(myHours) && Array.isArray(otherHours) && this._arraysEqual(myHours, otherHours))) { return false; } } return true; }, equals: function(calendar) { if (!(calendar instanceof CalendarWorkTimeStrategy)) { return false; } var mySettings = this.getConfig(); var thatSettings = calendar.getConfig(); if (!this._compareSettings(mySettings, thatSettings)) { return false; } if (mySettings.parsed.haveCustomWeeks && thatSettings.parsed.haveCustomWeeks) { if (mySettings.parsed.customWeeksBoundaries.length != thatSettings.parsed.customWeeksBoundaries.length) { return false; } for (var i in mySettings.parsed.customWeeks) { var myWeek = mySettings.parsed.customWeeks[i]; var thatWeek = thatSettings.parsed.customWeeks[i]; if (!thatWeek) { return false; } if (!this._compareSettings(myWeek, thatWeek)) { return false; } } } else if (mySettings.parse.haveCustomWeeks !== thatSettings.parsed.haveCustomWeeks) { return false; } return true; }, getWorkHours: function() { var config2 = this.argumentsHelper.getWorkHoursArguments.apply(this.argumentsHelper, arguments); return this._getWorkHours(config2.date, false); }, _getWorkHours: function(date2, parsed) { var calendar = this.getConfig(); if (parsed !== false) { calendar = calendar.parsed; } if (!date2) { return calendar.hours; } const dayStartDate = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); var dateValue = this._timestamp({ date: dayStartDate }); if (calendar.haveCustomWeeks) { if (calendar.customWeeksRangeStart <= dateValue && calendar.customWeeksRangeEnd > dateValue) { for (var i = 0; i < calendar.customWeeksBoundaries.length; i++) { if (calendar.customWeeksBoundaries[i].from <= dateValue && calendar.customWeeksBoundaries[i].to > dateValue) { calendar = calendar.customWeeks[calendar.customWeeksBoundaries[i].name]; break; } } } } var hours = true; if (calendar.dates[dateValue] !== void 0) { hours = calendar.dates[dateValue]; } else if (calendar.dates[date2.getDay()] !== void 0) { hours = calendar.dates[date2.getDay()]; } if (hours === true) { return calendar.hours; } else if (hours) { return hours; } return []; }, _getIntervalTimestamp: function(from, to) { var res = { start: 0, end: 0 }; res.start = from.getHours() * 60 * 60 + from.getMinutes() * 60 + from.getSeconds(); var endHours = to.getHours(); if (!endHours && !to.getMinutes() && !to.getSeconds() && from.valueOf() < to.valueOf()) { endHours = 24; } res.end = endHours * 60 * 60 + to.getMinutes() * 60 + to.getSeconds(); return res; }, _parseHours: function(hours) { if (Array.isArray(hours)) { var timestampRanges = []; hours.forEach(function(hour) { if (typeof hour === "number") { timestampRanges.push(hour * 60 * 60); } else if (typeof hour === "string") { hour.split("-").map(function(time) { return time.trim(); }).forEach(function(part) { var parsed = part.split(":").map(function(time) { return time.trim(); }); var value = parseInt(parsed[0] * 60 * 60); if (parsed[1]) { value += parseInt(parsed[1] * 60); } if (parsed[2]) { value += parseInt(parsed[2]); } timestampRanges.push(value); }); } }); var timerangeConfig = []; for (var i = 0; i < timestampRanges.length; i += 2) { var start = timestampRanges[i]; var end = timestampRanges[i + 1]; var duration = end - start; timerangeConfig.push({ start, end, startHour: Math.floor(start / (60 * 60)), startMinute: Math.floor(start / 60), endHour: Math.ceil(end / (60 * 60)), endMinute: Math.ceil(end / 60), durationSeconds: duration, durationMinutes: duration / 60, durationHours: duration / (60 * 60) }); } return timerangeConfig; } else { return hours; } }, setWorkTime: function(settings) { return this._tryChangeCalendarSettings(bind(function() { var hours = settings.hours !== void 0 ? settings.hours : true; var timestamp = this._timestamp(settings); var calendarConfig = this.getConfig(); if (timestamp !== null) { calendarConfig.dates[timestamp] = hours; } else if (!settings.customWeeks) { calendarConfig.hours = hours; } if (settings.customWeeks) { if (!calendarConfig.customWeeks) { calendarConfig.customWeeks = {}; } if (typeof settings.customWeeks == "string") { if (timestamp !== null) { calendarConfig.customWeeks[settings.customWeeks].dates[timestamp] = hours; } else if (!settings.customWeeks) { calendarConfig.customWeeks[settings.customWeeks].hours = hours; } } else if (typeof settings.customWeeks === "object" && settings.customWeeks.constructor === Object) { for (var i in settings.customWeeks) { calendarConfig.customWeeks[i] = settings.customWeeks[i]; } } } this._parseSettings(); this._clearCaches(); }, this)); }, unsetWorkTime: function(settings) { return this._tryChangeCalendarSettings(bind(function() { if (!settings) { this.reset_calendar(); } else { var timestamp = this._timestamp(settings); if (timestamp !== null) { delete this.getConfig().dates[timestamp]; } } this._parseSettings(); this._clearCaches(); }, this)); }, _isWorkTime: function(date2, unit) { var isWorkUnit = -1; var dateKey = null; { dateKey = String(date2.valueOf()); isWorkUnit = this._workingUnitsCache.getItem(unit, dateKey, date2); } if (isWorkUnit == -1) { isWorkUnit = this._checkIfWorkingUnit(date2, unit); { this._workingUnitsCache.setItem(unit, dateKey, isWorkUnit, date2); } } return isWorkUnit; }, isWorkTime: function() { var config2 = this.argumentsHelper.isWorkTimeArguments.apply(this.argumentsHelper, arguments); return this._isWorkTime(config2.date, config2.unit); }, calculateDuration: function() { var config2 = this.argumentsHelper.getDurationArguments.apply(this.argumentsHelper, arguments); if (!config2.unit) { return false; } var self2 = this; return this._dateDurationCache.getDuration(config2.start_date, config2.end_date, config2.unit, config2.step, function() { return self2._calculateDuration(config2.start_date, config2.end_date, config2.unit, config2.step); }); }, _calculateDuration: function(from, to, unit, step) { var res = 0; var sign = 1; if (from.valueOf() > to.valueOf()) { var tmp = to; to = from; from = tmp; sign = -1; } if (unit == "hour" && step == 1) { res = this._getHoursBetween(from, to, unit, step); } else if (unit == "minute" && step == 1) { res = this._getMinutesBetween(from, to, unit, step); } else { res = this._getWorkUnitsBetweenGeneric(from, to, unit, step); } return sign * Math.round(res); }, hasDuration: function() { var config2 = this.argumentsHelper.getDurationArguments.apply(this.argumentsHelper, arguments); var from = config2.start_date, to = config2.end_date, unit = config2.unit, step = config2.step; if (!unit) { return false; } var start = new Date(from), end = new Date(to); step = step || 1; while (start.valueOf() < end.valueOf()) { if (this._isWorkTime(start, unit)) return true; start = this._nextDate(start, unit, step); } return false; }, calculateEndDate: function() { var config2 = this.argumentsHelper.calculateEndDateArguments.apply(this.argumentsHelper, arguments); var from = config2.start_date, duration = config2.duration, unit = config2.unit, step = config2.step; if (!unit) return false; var mult = config2.duration >= 0 ? 1 : -1; duration = Math.abs(duration * 1); var self2 = this; return this._dateDurationCache.getEndDate(from, duration, unit, step * mult, function() { return self2._calculateEndDate(from, duration, unit, step * mult); }); }, _calculateEndDate: function(from, duration, unit, step) { if (!unit) return false; if (step == 1 && unit == "minute") { return this._calculateMinuteEndDate(from, duration, step); } else if (step == -1 && unit == "minute") { return this._subtractMinuteDate(from, duration, step); } else if (step == 1 && unit == "hour") { return this._calculateHourEndDate(from, duration, step); } else { var interval = this._addInterval(from, duration, unit, step, null); return interval.end; } }, _addInterval: function(start, duration, unit, step, stopAction) { var added = 0; var current = start; var dstShift = false; while (added < duration && !(stopAction && stopAction(current))) { var next = this._nextDate(current, unit, step); if (unit == "day") { dstShift = dstShift || !current.getHours() && next.getHours(); if (dstShift) { next.setHours(0); if (next.getHours()) ; else { dstShift = false; } } } var dateValue = new Date(next.valueOf() + 1); if (step > 0) { dateValue = new Date(next.valueOf() - 1); } var workTimeCheck = this._isWorkTime(dateValue, unit); if (workTimeCheck && !dstShift) { added++; } current = next; } return { end: current, start, added }; }, _addHoursUntilDayEnd: function(from, duration) { var dayEnd = this.$gantt.date.add(this.$gantt.date.day_start(new Date(from)), 1, "day"); var added = 0; var left = duration; var range = this._getIntervalTimestamp(from, dayEnd); var worktimes = this._getWorkHours(from); for (var i = 0; i < worktimes.length && added < duration; i++) { var interval = worktimes[i]; if (range.end >= interval.start && range.start <= interval.end) { var minuteFrom = Math.max(interval.start, range.start); var minuteTo = Math.min(interval.end, range.end); var rangeHours = (minuteTo - minuteFrom) / (60 * 60); if (rangeHours > left) { rangeHours = left; minuteTo = minuteFrom + left * 60 * 60; } var addHours = Math.round((minuteTo - minuteFrom) / (60 * 60)); added += addHours; left -= addHours; range.start = minuteTo; } } var intervalEnd = dayEnd; if (added === duration) { intervalEnd = new Date(from.getFullYear(), from.getMonth(), from.getDate(), 0, 0, range.start); } return { added, end: intervalEnd }; }, _calculateHourEndDate: function(from, duration, step) { var start = new Date(from), added = 0; step = step || 1; duration = Math.abs(duration * 1); var interval = this._addHoursUntilDayEnd(start, duration); added = interval.added; start = interval.end; var durationLeft = duration - added; if (durationLeft) { var current = start; while (added < duration) { var next = this._nextDate(current, "day", step); next.setHours(0); next.setMinutes(0); next.setSeconds(0); var hoursPerDay = 0; if (step > 0) { hoursPerDay = this.getHoursPerDay(new Date(next.valueOf() - 1)); } else { hoursPerDay = this.getHoursPerDay(new Date(next.valueOf() + 1)); } if (added + hoursPerDay >= duration) { break; } else { added += hoursPerDay; } current = next; } start = current; } if (added < duration) { var durationLeft = duration - added; interval = this._addHoursUntilDayEnd(start, durationLeft); start = interval.end; } return start; }, _addMinutesUntilHourEnd: function(from, duration) { if (from.getMinutes() === 0) { return { added: 0, end: new Date(from) }; } var hourEnd = this.$gantt.date.add(this.$gantt.date.hour_start(new Date(from)), 1, "hour"); var added = 0; var left = duration; var range = this._getIntervalTimestamp(from, hourEnd); var worktimes = this._getWorkHours(from); for (var i = 0; i < worktimes.length && added < duration; i++) { var interval = worktimes[i]; if (range.end >= interval.start && range.start <= interval.end) { var minuteFrom = Math.max(interval.start, range.start); var minuteTo = Math.min(interval.end, range.end); var rangeMinutes = (minuteTo - minuteFrom) / 60; if (rangeMinutes > left) { rangeMinutes = left; minuteTo = minuteFrom + left * 60; } var addMinutes = Math.round((minuteTo - minuteFrom) / 60); left -= addMinutes; added += addMinutes; range.start = minuteTo; } } var intervalEnd = hourEnd; if (added === duration) { intervalEnd = new Date(from.getFullYear(), from.getMonth(), from.getDate(), 0, 0, range.start); } return { added, end: intervalEnd }; }, _subtractMinutesUntilHourStart: function(from, duration) { var hourStart = this.$gantt.date.hour_start(new Date(from)); var added = 0; var left = duration; var hourStartTimestamp = hourStart.getHours() * 60 * 60 + hourStart.getMinutes() * 60 + hourStart.getSeconds(); var initialDateTimestamp = from.getHours() * 60 * 60 + from.getMinutes() * 60 + from.getSeconds(); var worktimes = this._getWorkHours(from); for (var i = worktimes.length - 1; i >= 0 && added < duration; i--) { var interval = worktimes[i]; if (initialDateTimestamp > interval.start && hourStartTimestamp <= interval.end) { var minuteFrom = Math.min(initialDateTimestamp, interval.end); var minuteTo = Math.max(hourStartTimestamp, interval.start); var rangeMinutes = (minuteFrom - minuteTo) / 60; if (rangeMinutes > left) { rangeMinutes = left; minuteTo = minuteFrom - left * 60; } var addMinutes = Math.abs(Math.round((minuteFrom - minuteTo) / 60)); left -= addMinutes; added += addMinutes; initialDateTimestamp = minuteTo; } } var intervalEnd = hourStart; if (added === duration) { intervalEnd = new Date(from.getFullYear(), from.getMonth(), from.getDate(), 0, 0, initialDateTimestamp); } return { added, end: intervalEnd }; }, _subtractMinuteDate: function(from, duration, step) { var start = this.getClosestWorkTime({ date: from, dir: "past", unit: "minute" }), added = 0; step = step || -1; duration = Math.abs(duration * 1); duration = Math.round(duration); const minutePrecision = this._isMinutePrecision(start); let addedInterval = this._subtractMinutesUntilHourStart(start, duration); added += addedInterval.added; start = addedInterval.end; var calculatedDay = 0; var daySchedule = []; var minutesInDay = 0; while (added < duration) { var dayStart = this.$gantt.date.day_start(new Date(start)); var iterateFromDayEnd = false; if (start.valueOf() === dayStart.valueOf()) { dayStart = this.$gantt.date.add(dayStart, -1, "day"); iterateFromDayEnd = true; } var dayEnd = new Date(dayStart.getFullYear(), dayStart.getMonth(), dayStart.getDate(), 23, 59, 59, 999).valueOf(); if (dayEnd !== calculatedDay) { daySchedule = this._getWorkHours(dayStart); minutesInDay = this._getMinutesPerDay(dayStart); calculatedDay = dayEnd; } var left = duration - added; var timestamp = this._getTimeOfDayStamp(start, iterateFromDayEnd); if (!daySchedule.length || !minutesInDay) { start = this.$gantt.date.add(start, -1, "day"); continue; } if (daySchedule[daySchedule.length - 1].end <= timestamp) { if (left > minutesInDay) { added += minutesInDay; start = this.$gantt.date.add(start, -1, "day"); continue; } } var isWorkHour = false; var workInterval = null; var prevInterval = null; for (var i = daySchedule.length - 1; i >= 0; i--) { if (daySchedule[i].start < timestamp - 1 && daySchedule[i].end >= timestamp - 1) { isWorkHour = true; workInterval = daySchedule[i]; prevInterval = daySchedule[i - 1]; break; } } if (isWorkHour) { if (timestamp === workInterval.end && left >= workInterval.durationMinutes) { added += workInterval.durationMinutes; start = this.$gantt.date.add(start, -workInterval.durationMinutes, "minute"); } else if (!minutePrecision && left <= timestamp / 60 - workInterval.startMinute) { added += left; start = this.$gantt.date.add(start, -left, "minute"); } else if (minutePrecision) { if (left <= timestamp / 60 - workInterval.startMinute) { added += left; start = this.$gantt.date.add(start, -left, "minute"); } else { added += timestamp / 60 - workInterval.startMinute; if (prevInterval) { start = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, prevInterval.end); } else { start = this.$gantt.date.day_start(start); } } } else { var minutesInHour = this._getMinutesPerHour(start); if (minutesInHour <= left) { added += minutesInHour; start = this._nextDate(start, "hour", step); } else { addedInterval = this._subtractMinutesUntilHourStart(start, left); added += addedInterval.added; start = addedInterval.end; } } } else { if (start.getHours() === 0 && start.getMinutes() === 0 && start.getSeconds() === 0) { var prev = this._getClosestWorkTimePast(start, "hour"); if (prev.valueOf() === start.valueOf()) { var prev = this.$gantt.date.add(start, -1, "day"); var times = this._getWorkHours(prev); if (times.length) { var lastInterval = times[times.length - 1]; prev.setSeconds(lastInterval.durationSeconds); } } start = prev; } else { start = this._getClosestWorkTimePast(new Date(start - 1), "hour"); } } } if (added < duration) { var durationLeft = duration - added; addedInterval = this._subtractMinutesUntilHourStart(start, durationLeft); added += addedInterval.added; start = addedInterval.end; } return start; }, _calculateMinuteEndDate: function(from, duration, step) { var start = new Date(from), added = 0; step = step || 1; duration = Math.abs(duration * 1); duration = Math.round(duration); var addedInterval = this._addMinutesUntilHourEnd(start, duration); added += addedInterval.added; start = addedInterval.end; var calculatedDay = 0; var daySchedule = []; var minutesInDay = 0; var minutePrecision = this._isMinutePrecision(start); while (added < duration) { var dayStart = this.$gantt.date.day_start(new Date(start)).valueOf(); if (dayStart !== calculatedDay) { daySchedule = this._getWorkHours(start); minutesInDay = this._getMinutesPerDay(start); calculatedDay = dayStart; } var left = duration - added; var timestamp = this._getTimeOfDayStamp(start); if (!daySchedule.length || !minutesInDay) { start = this.$gantt.date.add(this.$gantt.date.day_start(start), 1, "day"); continue; } if (daySchedule[0].start >= timestamp) { if (left >= minutesInDay) { added += minutesInDay; if (left == minutesInDay) { start = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, daySchedule[daySchedule.length - 1].end); break; } else { start = this.$gantt.date.add(start, 1, "day"); start = this.$gantt.date.day_start(start); } continue; } } var isWorkHour = false; var workInterval = null; for (var i = 0; i < daySchedule.length; i++) { if (daySchedule[i].start <= timestamp && daySchedule[i].end > timestamp) { isWorkHour = true; workInterval = daySchedule[i]; break; } } if (isWorkHour) { if (timestamp === workInterval.start && left >= workInterval.durationMinutes) { added += workInterval.durationMinutes; start = this.$gantt.date.add(start, workInterval.durationMinutes, "minute"); } else if (left <= workInterval.endMinute - timestamp / 60) { added += left; start = this.$gantt.date.add(start, left, "minute"); } else { var minutesInHour = this._getMinutesPerHour(start); if (minutesInHour <= left) { added += minutesInHour; if (minutePrecision) { start = this.$gantt.date.add(start, minutesInHour, "minute"); } else { start = this._nextDate(start, "hour", step); } } else { addedInterval = this._addMinutesUntilHourEnd(start, left); added += addedInterval.added; start = addedInterval.end; } } } else { start = this._getClosestWorkTimeFuture(start, "hour"); } } if (added < duration) { var durationLeft = duration - added; addedInterval = this._addMinutesUntilHourEnd(start, durationLeft); added += addedInterval.added; start = addedInterval.end; } return start; }, getClosestWorkTime: function() { var settings = this.argumentsHelper.getClosestWorkTimeArguments.apply(this.argumentsHelper, arguments); return this._getClosestWorkTime(settings.date, settings.unit, settings.dir); }, _getClosestWorkTime: function(inputDate, unit, direction) { var result = new Date(inputDate); if (this._isWorkTime(result, unit)) { return result; } result = this.$gantt.date[unit + "_start"](result); if (direction == "any" || !direction) { var closestFuture = this._getClosestWorkTimeFuture(result, unit); var closestPast = this._getClosestWorkTimePast(result, unit); if (Math.abs(closestFuture - inputDate) <= Math.abs(inputDate - closestPast)) { result = closestFuture; } else { result = closestPast; } } else if (direction == "past") { result = this._getClosestWorkTimePast(result, unit); } else { result = this._getClosestWorkTimeFuture(result, unit); } return result; }, _getClosestWorkTimeFuture: function(date2, unit) { return this._getClosestWorkTimeGeneric(date2, unit, 1); }, _getClosestWorkTimePast: function(date2, unit) { var result = this._getClosestWorkTimeGeneric(date2, unit, -1); return this.$gantt.date.add(result, 1, unit); }, _findClosestTimeInDay: function(date2, direction, worktimes) { var start = new Date(date2); var resultDate = null; var fromDayEnd = false; if (!this._getWorkHours(start).length) { start = this._getClosestWorkTime(start, "day", direction < 0 ? "past" : "future"); if (direction < 0) { start = new Date(start.valueOf() - 1); fromDayEnd = true; } worktimes = this._getWorkHours(start); } var value = this._getTimeOfDayStamp(start); if (fromDayEnd) { value = this._getTimeOfDayStamp(new Date(start.valueOf() + 1), fromDayEnd); } if (direction > 0) { for (var i = 0; i < worktimes.length; i++) { if (worktimes[i].start >= value) { resultDate = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, worktimes[i].start); break; } } } else { for (var i = worktimes.length - 1; i >= 0; i--) { if (worktimes[i].end <= value) { resultDate = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, worktimes[i].end); break; } else if (worktimes[i].end > value && worktimes[i].start <= value) { resultDate = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, value); break; } } } return resultDate; }, _getClosestWorkMinute: function(date2, unit, direction) { var start = new Date(date2); var worktimes = this._getWorkHours(start); var resultDate = this._findClosestTimeInDay(start, direction, worktimes); if (!resultDate) { if (direction > 0) { start = this.calculateEndDate(start, direction, unit); start = this.$gantt.date.day_start(start); } else { start = this.calculateEndDate(start, direction, "day"); start = this.$gantt.date.day_start(start); start = this.$gantt.date.add(start, 1, "day"); start = new Date(start.valueOf() - 1); } worktimes = this._getWorkHours(start); resultDate = this._findClosestTimeInDay(start, direction, worktimes); } if (direction < 0) { resultDate = this.$gantt.date.add(resultDate, -1, unit); } return resultDate; }, _getClosestWorkTimeGeneric: function(date2, unit, increment) { if (unit === "hour" || unit === "minute") { return this._getClosestWorkMinute(date2, unit, increment); } var unitOrder = this._getUnitOrder(unit), biggerTimeUnit = this.units[unitOrder - 1]; var result = date2; var maximumLoop = 3e3, count = 0; while (!this._isWorkTime(result, unit)) { if (biggerTimeUnit && !this._isWorkTime(result, biggerTimeUnit)) { if (increment > 0) { result = this._getClosestWorkTimeFuture(result, biggerTimeUnit); } else { result = this._getClosestWorkTimePast(result, biggerTimeUnit); } if (this._isWorkTime(result, unit)) { break; } } count++; if (count > maximumLoop) { this.$gantt.assert(false, "Invalid working time check"); return false; } var tzOffset = result.getTimezoneOffset(); result = this.$gantt.date.add(result, increment, unit); result = this.$gantt._correct_dst_change(result, tzOffset, increment, unit); if (this.$gantt.date[unit + "_start"]) { result = this.$gantt.date[unit + "_start"](result); } } return result; }, hasWorkTime: function() { var worktime = this.getConfig(); var dates = worktime.dates; var daysOfWeek = [0, 1, 2, 3, 4, 5, 6]; for (var i in worktime.dates) { } var hasRegularHours = this._checkWorkHours(worktime.hours); var result = false; daysOfWeek.forEach((function(day) { if (result) { return; } var dayConfig = dates[day]; if (dayConfig === true) { result = hasRegularHours; } else if (Array.isArray(dayConfig)) { result = this._checkWorkHours(dayConfig); } }).bind(this)); return result; }, _checkWorkHours: function(hoursArray) { if (hoursArray.length === 0) { return false; } var result = false; for (var i = 0; i < hoursArray.length; i += 2) { if (hoursArray[i] !== hoursArray[i + 1]) { result = true; } } return result; }, _isMinutePrecision: function(date2) { let minutePrecision = false; this._getWorkHours(date2).forEach(function(interval) { if (interval.startMinute % 60 || interval.endMinute % 60) { minutePrecision = true; } }); return minutePrecision; } }; const legacyResourceCalendarConfig = { isLegacyResourceCalendarFormat: function(resourceCalendarsProperty) { if (!resourceCalendarsProperty) { return false; } for (var i in resourceCalendarsProperty) { if (resourceCalendarsProperty[i] && typeof resourceCalendarsProperty[i] === "object") { return true; } } return false; }, getResourceProperty: function(config2) { var resourceCalendarsConfig = config2.resource_calendars; var propertyName = config2.resource_property; if (this.isLegacyResourceCalendarFormat(resourceCalendarsConfig)) { for (var i in config2) { propertyName = i; break; } } return propertyName; }, getCalendarIdFromLegacyConfig: function(task, config2) { if (config2) { for (var field in config2) { var resource = config2[field]; if (task[field]) { var calendarId = resource[task[field]]; if (calendarId) { return calendarId; } } } } return null; } }; function dynamicResourceCalendarsFactory() { function getResourcesCalendarKey(resourceAssignments) { return resourceAssignments.map(function(res) { if (res && res.resource_id) { return res.resource_id; } else { return res; } }).sort().join("-"); } var dynamicCalendars = {}; function mergeResourceCalendars(resourceAssignments, manager) { return manager.mergeCalendars(resourceAssignments.map(function(assignment) { var resourceId = assignment && assignment.resource_id ? assignment.resource_id : assignment; return manager.getResourceCalendar(resourceId); })); } function getCalendarIdFromMultipleResources(resourceAssignments, manager) { var key = getResourcesCalendarKey(resourceAssignments); if (!resourceAssignments.length) { return null; } else if (resourceAssignments.length === 1) { return manager.getResourceCalendar(key).id; } else if (dynamicCalendars[key]) { return dynamicCalendars[key].id; } else { var tempCalendar = mergeResourceCalendars(resourceAssignments, manager); dynamicCalendars[key] = tempCalendar; return manager.addCalendar(tempCalendar); } } return { getCalendarIdFromMultipleResources }; } const dynamicResourceCalendars = dynamicResourceCalendarsFactory(); function CalendarManager(gantt2) { this.$gantt = gantt2; this._calendars = {}; this._legacyConfig = void 0; this.$gantt.attachEvent("onGanttReady", (function() { if (this.$gantt.config.resource_calendars) { this._isLegacyConfig = legacyResourceCalendarConfig.isLegacyResourceCalendarFormat(this.$gantt.config.resource_calendars); } }).bind(this)); this.$gantt.attachEvent("onBeforeGanttReady", (function() { this.createDefaultCalendars(); }).bind(this)); this.$gantt.attachEvent("onBeforeGanttRender", (function() { this.createDefaultCalendars(); }).bind(this)); } CalendarManager.prototype = { _calendars: {}, _convertWorkTimeSettings: function(settings) { const days = settings.days; if (typeof days === "object" && !Array.isArray(days) && days !== null) { const datesConfig = {}; if (days == null ? void 0 : days.weekdays) { for (let i = 0; i < 7; i++) { datesConfig[i] = days.weekdays[i]; } } if (days == null ? void 0 : days.dates) { Object.entries(days.dates).forEach(([date2, setting]) => { datesConfig[new Date(date2).valueOf()] = setting; }); } Object.entries(datesConfig).forEach(([key, setting]) => { if (!(setting instanceof Array)) { datesConfig[key] = !!setting; } }); settings = { ...settings, dates: datesConfig }; } else if (days && !settings.dates) { settings.dates = settings.dates || {}; for (let i = 0; i < days.length; i++) { settings.dates[i] = days[i]; if (!(days[i] instanceof Array)) { settings.dates[i] = !!days[i]; } } } delete settings.days; return settings; }, mergeCalendars: function() { var calendars = []; var args = arguments; if (Array.isArray(args[0])) { calendars = args[0].slice(); } else { for (var i = 0; i < arguments.length; i++) { calendars.push(arguments[i]); } } var mergeHelper = new WorkTimeCalendarMerger(); var result; calendars.forEach((function(calendar) { if (!result) { result = calendar; } else { result = this._createCalendarFromConfig(mergeHelper.merge(result, calendar)); } }).bind(this)); return this.createCalendar(result); }, _createCalendarFromConfig: function(config2) { var apiCore = new CalendarWorkTimeStrategy(this.$gantt, calendarArgumentsHelper(this.$gantt)); apiCore.id = String(uid()); var preparedConfig = this._convertWorkTimeSettings(config2); if (preparedConfig.customWeeks) { for (var i in preparedConfig.customWeeks) { preparedConfig.customWeeks[i] = this._convertWorkTimeSettings(preparedConfig.customWeeks[i]); } } apiCore._setConfig(preparedConfig); return apiCore; }, createCalendar: function(parentCalendar) { var settings; if (!parentCalendar) { parentCalendar = {}; } if (parentCalendar.getConfig) { settings = copy(parentCalendar.getConfig()); } else if (parentCalendar.worktime) { settings = copy(parentCalendar.worktime); } else { settings = copy(parentCalendar); } var defaults = copy(this.defaults.fulltime.worktime); mixin(settings, defaults); return this._createCalendarFromConfig(settings); }, getCalendar: function(id) { id = id || "global"; var calendar = this._calendars[id]; if (!calendar) { this.createDefaultCalendars(); calendar = this._calendars[id]; } return calendar; }, getCalendars: function() { var res = []; for (var i in this._calendars) { res.push(this.getCalendar(i)); } return res; }, _getOwnCalendar: function(task) { var config2 = this.$gantt.config; if (task[config2.calendar_property]) { return this.getCalendar(task[config2.calendar_property]); } if (config2.resource_calendars) { var calendar; var calendarId; var resourceProperty; if (this._legacyConfig === false) { resourceProperty = config2.resource_property; } else { resourceProperty = legacyResourceCalendarConfig.getResourceProperty(config2); } if (Array.isArray(task[resourceProperty]) && task[resourceProperty].length) { if (config2.dynamic_resource_calendars) { calendarId = dynamicResourceCalendars.getCalendarIdFromMultipleResources(task[resourceProperty], this); } else { calendar = this.getResourceCalendar(task[resourceProperty]); } } else { if (this._legacyConfig === void 0) { this._legacyConfig = legacyResourceCalendarConfig.isLegacyResourceCalendarFormat(config2.resource_calendars); } if (this._legacyConfig) { var calendarId = legacyResourceCalendarConfig.getCalendarIdFromLegacyConfig(task, config2.resource_calendars); } else if (resourceProperty && task[resourceProperty] && config2.resource_calendars[task[resourceProperty]]) { var calendar = this.getResourceCalendar(task[resourceProperty]); } } if (calendarId) { calendar = this.getCalendar(calendarId); } if (calendar) { return calendar; } } return null; }, getResourceCalendar: function(resource) { if (resource === null || resource === void 0) { return this.getCalendar(); } var resourceId = null; if (typeof resource === "number" || typeof resource === "string") { resourceId = resource; } else { resourceId = resource.id || resource.key; } var config2 = this.$gantt.config; var calendarsConfig = config2.resource_calendars; var calendarId = null; if (Array.isArray(resource)) { if (resource.length === 1) { if (typeof resource[0] === "object") { resourceId = resource[0].resource_id; } else { resourceId = resource[0]; } } } if (calendarsConfig) { if (this._legacyConfig === void 0) { this._legacyConfig = legacyResourceCalendarConfig.isLegacyResourceCalendarFormat(config2.resource_calendars); } if (this._legacyConfig) { for (var field in calendarsConfig) { if (calendarsConfig[field][resourceId]) { calendarId = calendarsConfig[field][resourceId]; break; } } } else { var calendarId = calendarsConfig[resourceId]; } if (calendarId) { return this.getCalendar(calendarId); } } return this.getCalendar(); }, getTaskCalendar: function(task) { var gantt2 = this.$gantt; var taskObject; if (task === null || task === void 0) { return this.getCalendar(); } if ((typeof task === "number" || typeof task === "string") && gantt2.isTaskExists(task)) { taskObject = gantt2.getTask(task); } else { taskObject = task; } if (!taskObject) { return this.getCalendar(); } var calendar = this._getOwnCalendar(taskObject); var groupMode = !!gantt2.getState().group_mode; if (!calendar && gantt2.config.inherit_calendar && gantt2.isTaskExists(taskObject.parent)) { var currentTask = taskObject; while (gantt2.isTaskExists(currentTask.parent)) { currentTask = gantt2.getTask(currentTask.parent); if (gantt2.isSummaryTask(currentTask)) { calendar = this._getOwnCalendar(currentTask); if (calendar) { break; } } } if (groupMode && !calendar) { if (task.$effective_calendar) { calendar = this.getCalendar(task.$effective_calendar); } } } return calendar || this.getCalendar(); }, addCalendar: function(calendar) { if (!this.isCalendar(calendar)) { var id = calendar.id; calendar = this.createCalendar(calendar); calendar.id = id; } if (!calendar._tryChangeCalendarSettings(function() { })) { this.$gantt.callEvent("onCalendarError", [{ message: "Invalid calendar settings, no worktime available" }, calendar]); return null; } else { var config2 = this.$gantt.config; calendar.id = calendar.id || uid(); this._calendars[calendar.id] = calendar; if (!config2.worktimes) config2.worktimes = {}; config2.worktimes[calendar.id] = calendar.getConfig(); return calendar.id; } }, deleteCalendar: function(calendar) { var config2 = this.$gantt.config; if (!calendar) return false; if (this._calendars[calendar]) { delete this._calendars[calendar]; if (config2.worktimes && config2.worktimes[calendar]) delete config2.worktimes[calendar]; return true; } else { return false; } }, restoreConfigCalendars: function(configs) { for (var i in configs) { if (this._calendars[i]) continue; var settings = configs[i]; var calendar = this.createCalendar(settings); calendar.id = i; this.addCalendar(calendar); } }, defaults: { global: { id: "global", worktime: { hours: [8, 12, 13, 17], days: [0, 1, 1, 1, 1, 1, 0] } }, fulltime: { id: "fulltime", worktime: { hours: [0, 24], days: [1, 1, 1, 1, 1, 1, 1] } } }, createDefaultCalendars: function() { var config2 = this.$gantt.config; this.restoreConfigCalendars(this.defaults); this.restoreConfigCalendars(config2.worktimes); }, isCalendar: function(possibleCalendar) { var props = [possibleCalendar.isWorkTime, possibleCalendar.setWorkTime, possibleCalendar.getWorkHours, possibleCalendar.unsetWorkTime, possibleCalendar.getClosestWorkTime, possibleCalendar.calculateDuration, possibleCalendar.hasDuration, possibleCalendar.calculateEndDate]; return props.every(function(entry) { return entry instanceof Function; }); } }; function CalendarDisabledTimeStrategy(gantt2, argumentsHelper) { this.argumentsHelper = argumentsHelper; this.$gantt = gantt2; } CalendarDisabledTimeStrategy.prototype = { getWorkHours: function() { return [0, 24]; }, setWorkTime: function() { return true; }, unsetWorkTime: function() { return true; }, isWorkTime: function() { return true; }, getClosestWorkTime: function(config2) { var config2 = this.argumentsHelper.getClosestWorkTimeArguments.apply(this.argumentsHelper, arguments); return config2.date; }, calculateDuration: function() { var config2 = this.argumentsHelper.getDurationArguments.apply(this.argumentsHelper, arguments); var from = config2.start_date, to = config2.end_date, unit = config2.unit, step = config2.step; return this._calculateDuration(from, to, unit, step); }, _calculateDuration: function(start, end, unit, step) { var dateHelper = this.$gantt.date; var fixedUnits = { week: 1e3 * 60 * 60 * 24 * 7, day: 1e3 * 60 * 60 * 24, hour: 1e3 * 60 * 60, minute: 1e3 * 60 }; var res = 0; if (fixedUnits[unit]) { res = Math.round((end - start) / (step * fixedUnits[unit])); } else { var from = new Date(start), to = new Date(end); while (from.valueOf() < to.valueOf()) { res += 1; from = dateHelper.add(from, step, unit); } if (from.valueOf() != end.valueOf()) { res += (to - from) / (dateHelper.add(from, step, unit) - from); } } return Math.round(res); }, hasDuration: function() { var config2 = this.argumentsHelper.getDurationArguments.apply(this.argumentsHelper, arguments); var from = config2.start_date, to = config2.end_date, unit = config2.unit; if (!unit) { return false; } from = new Date(from); to = new Date(to); return from.valueOf() < to.valueOf(); }, hasWorkTime: function() { return true; }, equals: function(calendar) { if (!(calendar instanceof CalendarDisabledTimeStrategy)) { return false; } return true; }, calculateEndDate: function() { var config2 = this.argumentsHelper.calculateEndDateArguments.apply(this.argumentsHelper, arguments); var start = config2.start_date, duration = config2.duration, unit = config2.unit, step = config2.step; return this.$gantt.date.add(start, step * duration, unit); } }; function TimeCalculator(calendarManager) { this.$gantt = calendarManager.$gantt; this.argumentsHelper = calendarArgumentsHelper(this.$gantt); this.calendarManager = calendarManager; this.$disabledCalendar = new CalendarDisabledTimeStrategy(this.$gantt, this.argumentsHelper); } TimeCalculator.prototype = { _getCalendar: function(config2) { var calendar; if (!this.$gantt.config.work_time) { calendar = this.$disabledCalendar; } else { var manager = this.calendarManager; if (config2.task) { calendar = manager.getTaskCalendar(config2.task); } else if (config2.id) { calendar = manager.getTaskCalendar(config2); } else if (config2.calendar) { calendar = config2.calendar; } if (!calendar) { calendar = manager.getTaskCalendar(); } } return calendar; }, getWorkHours: function(config2) { config2 = this.argumentsHelper.getWorkHoursArguments.apply(this.argumentsHelper, arguments); var calendar = this._getCalendar(config2); return calendar.getWorkHours(config2.date); }, setWorkTime: function(config2, calendar) { config2 = this.argumentsHelper.setWorkTimeArguments.apply(this.argumentsHelper, arguments); if (!calendar) calendar = this.calendarManager.getCalendar(); return calendar.setWorkTime(config2); }, unsetWorkTime: function(config2, calendar) { config2 = this.argumentsHelper.unsetWorkTimeArguments.apply(this.argumentsHelper, arguments); if (!calendar) calendar = this.calendarManager.getCalendar(); return calendar.unsetWorkTime(config2); }, isWorkTime: function(date2, unit, task, calendar) { var config2 = this.argumentsHelper.isWorkTimeArguments.apply(this.argumentsHelper, arguments); calendar = this._getCalendar(config2); return calendar.isWorkTime(config2); }, getClosestWorkTime: function(config2) { config2 = this.argumentsHelper.getClosestWorkTimeArguments.apply(this.argumentsHelper, arguments); var calendar = this._getCalendar(config2); return calendar.getClosestWorkTime(config2); }, calculateDuration: function() { var config2 = this.argumentsHelper.getDurationArguments.apply(this.argumentsHelper, arguments); var calendar = this._getCalendar(config2); return calendar.calculateDuration(config2); }, hasDuration: function() { var config2 = this.argumentsHelper.hasDurationArguments.apply(this.argumentsHelper, arguments); var calendar = this._getCalendar(config2); return calendar.hasDuration(config2); }, calculateEndDate: function(config2) { var config2 = this.argumentsHelper.calculateEndDateArguments.apply(this.argumentsHelper, arguments); var calendar = this._getCalendar(config2); return calendar.calculateEndDate(config2); } }; var createWorkTimeFacade = function(calendarManager, timeCalculator) { return { getWorkHours: function(date2) { return timeCalculator.getWorkHours(date2); }, setWorkTime: function(config2) { return timeCalculator.setWorkTime(config2); }, unsetWorkTime: function(config2) { timeCalculator.unsetWorkTime(config2); }, isWorkTime: function(date2, unit, task) { return timeCalculator.isWorkTime(date2, unit, task); }, getClosestWorkTime: function(config2) { return timeCalculator.getClosestWorkTime(config2); }, calculateDuration: function(start_date, end_date, task) { return timeCalculator.calculateDuration(start_date, end_date, task); }, _hasDuration: function(start_date, end_date, task) { return timeCalculator.hasDuration(start_date, end_date, task); }, calculateEndDate: function(start, duration, unit, task) { return timeCalculator.calculateEndDate(start, duration, unit, task); }, mergeCalendars: bind(calendarManager.mergeCalendars, calendarManager), createCalendar: bind(calendarManager.createCalendar, calendarManager), addCalendar: bind(calendarManager.addCalendar, calendarManager), getCalendar: bind(calendarManager.getCalendar, calendarManager), getCalendars: bind(calendarManager.getCalendars, calendarManager), getResourceCalendar: bind(calendarManager.getResourceCalendar, calendarManager), getTaskCalendar: bind(calendarManager.getTaskCalendar, calendarManager), deleteCalendar: bind(calendarManager.deleteCalendar, calendarManager) }; }; const worktimeFacadeFactory = { create: createWorkTimeFacade }; function work_time(gantt2) { var manager = new CalendarManager(gantt2), timeCalculator = new TimeCalculator(manager); var facade = worktimeFacadeFactory.create(manager, timeCalculator); mixin(gantt2, facade); } function data(gantt2) { gantt2.isUnscheduledTask = function(task) { gantt2.assert(task && task instanceof Object, "Invalid argument task=" + task + " of gantt.isUnscheduledTask. Task object was expected"); return !!task.unscheduled || !task.start_date; }; gantt2._isAllowedUnscheduledTask = function(task) { return !!(task.unscheduled && gantt2.config.show_unscheduled); }; gantt2._isTaskInTimelineLimits = function(task) { var taskStart = task.start_date ? task.start_date.valueOf() : null; var taskEnd = task.end_date ? task.end_date.valueOf() : null; return !!(taskStart && taskEnd && taskStart <= this._max_date.valueOf() && taskEnd >= this._min_date.valueOf()); }; gantt2.isTaskVisible = function(id) { if (!this.isTaskExists(id)) { return false; } var task = this.getTask(id); if (!(this._isAllowedUnscheduledTask(task) || this._isTaskInTimelineLimits(task))) { return false; } return !!(this.getGlobalTaskIndex(id) >= 0); }; gantt2._getProjectEnd = function() { if (gantt2.config.project_end) { return gantt2.config.project_end; } else { var tasks2 = gantt2.getTaskByTime(); tasks2 = tasks2.sort(function(a, b) { return +a.end_date > +b.end_date ? 1 : -1; }); return tasks2.length ? tasks2[tasks2.length - 1].end_date : null; } }; gantt2._getProjectStart = function() { if (gantt2.config.project_start) { return gantt2.config.project_start; } if (gantt2.config.start_date) { return gantt2.config.start_date; } if (gantt2.getState().min_date) { return gantt2.getState().min_date; } var tasks2 = gantt2.getTaskByTime(); tasks2 = tasks2.sort(function(a, b) { return +a.start_date > +b.start_date ? 1 : -1; }); return tasks2.length ? tasks2[0].start_date : null; }; var getDefaultTaskDate = function(item, parent_id) { var parentExists = parent_id && parent_id != gantt2.config.root_id && gantt2.isTaskExists(parent_id); var parent = parentExists ? gantt2.getTask(parent_id) : false, startDate = null; if (parent) { if (gantt2._getAutoSchedulingConfig().schedule_from_end) { startDate = gantt2.calculateEndDate({ start_date: parent.end_date, duration: -gantt2.config.duration_step, task: item }); } else { if (!parent.start_date) { return getDefaultTaskDate(parent, gantt2.getParent(parent)); } startDate = parent.start_date; } } else if (gantt2._getAutoSchedulingConfig().schedule_from_end) { startDate = gantt2.calculateEndDate({ start_date: gantt2._getProjectEnd(), duration: -gantt2.config.duration_step, task: item }); } else { const first = gantt2.getTaskByIndex(0); const minDate = gantt2.config.start_date || gantt2.getState().min_date; if (first) { if (first.start_date) { startDate = first.start_date; } else if (first.end_date) { startDate = gantt2.calculateEndDate({ start_date: first.end_date, duration: -gantt2.config.duration_step, task: item }); } else { startDate = minDate; } } else { startDate = minDate; } } gantt2.assert(startDate, "Invalid dates"); return new Date(startDate); }; gantt2._set_default_task_timing = function(task) { task.start_date = task.start_date || getDefaultTaskDate(task, gantt2.getParent(task)); task.duration = task.duration || gantt2.config.duration_step; task.end_date = task.end_date || gantt2.calculateEndDate(task); }; gantt2.createTask = function(item, parent, index) { item = item || {}; if (!gantt2.defined(item.id)) item.id = gantt2.uid(); if (!item.start_date) { item.start_date = getDefaultTaskDate(item, parent); } if (item.text === void 0) { item.text = gantt2.locale.labels.new_task; } if (item.duration === void 0) { item.duration = 1; } if (this.isTaskExists(parent)) { this.setParent(item, parent, true); var parentObj = this.getTask(parent); parentObj.$open = true; if (!this.config.details_on_create) { this.callEvent("onAfterParentExpand", [parent, parentObj]); } } if (!this.callEvent("onTaskCreated", [item])) { return null; } if (this.config.details_on_create) { if (gantt2.isTaskExists(item.id)) { var task = gantt2.getTask(item.id); if (task.$index != item.$index) { if (item.start_date && typeof item.start_date === "string") { item.start_date = this.date.parseDate(item.start_date, "parse_date"); } if (item.end_date && typeof item.end_date === "string") { item.end_date = this.date.parseDate(item.end_date, "parse_date"); } this.$data.tasksStore.updateItem(item.id, item); } } else { item.$new = true; this.silent(function() { gantt2.$data.tasksStore.addItem(item, index); }); } this.selectTask(item.id); this.refreshData(); this.showLightbox(item.id); } else { if (this.addTask(item, parent, index)) { this.showTask(item.id); this.selectTask(item.id); } } return item.id; }; gantt2._update_flags = function(oldid, newid) { var store = gantt2.$data.tasksStore; if (oldid === void 0) { this._lightbox_id = null; store.silent(function() { store.unselect(); }); if (this.getSelectedTasks) { this._multiselect.reset(); } if (this._tasks_dnd && this._tasks_dnd.drag) { this._tasks_dnd.drag.id = null; } } else { if (this._lightbox_id == oldid) this._lightbox_id = newid; if (store.getSelectedId() == oldid) { store.silent(function() { store.unselect(oldid); store.select(newid); }); } if (this._tasks_dnd && this._tasks_dnd.drag && this._tasks_dnd.drag.id == oldid) { this._tasks_dnd.drag.id = newid; } } }; var getTaskTimingMode = function(task, force) { var task_type = gantt2.getTaskType(task.type); var state = { type: task_type, $no_start: false, $no_end: false, scheduled_summary: false }; if (task_type === gantt2.config.types.project && task.auto_scheduling === false) { state.scheduled_summary = true; } if (!force && task_type == task.$rendered_type) { state.$no_start = task.$no_start; state.$no_end = task.$no_end; return state; } if (task_type == gantt2.config.types.project) { state.$no_end = state.$no_start = true; } else if (task_type != gantt2.config.types.milestone) { state.$no_end = !(task.end_date || task.duration); state.$no_start = !task.start_date; if (gantt2._isAllowedUnscheduledTask(task)) { state.$no_end = state.$no_start = false; } } return state; }; gantt2._init_task_timing = function(task) { var task_mode = getTaskTimingMode(task, true); var dirty = task.$rendered_type != task_mode.type; var task_type = task_mode.type; if (dirty) { task.$no_start = task_mode.$no_start; task.$no_end = task_mode.$no_end; task.$rendered_type = task_mode.type; } if (dirty && task_type != this.config.types.milestone) { if (task_type == this.config.types.project) { this._set_default_task_timing(task); task.$calculate_duration = false; } } if (task_type == this.config.types.milestone) { task.end_date = task.start_date; } if (task.start_date && task.end_date && task.$calculate_duration !== false) { task.duration = this.calculateDuration(task); } if (!task.$calculate_duration) { task.$calculate_duration = true; } if (!task.end_date) { task.end_date = task.start_date; } task.duration = task.duration || 0; if (this.config.min_duration === 0 && task.duration === 0) { task.$no_end = false; if (task.type === gantt2.config.types.project && gantt2.hasChild(task.id)) { task.$no_end = true; } } var effectiveCalendar = this.getTaskCalendar(task); if (task.$effective_calendar && task.$effective_calendar !== effectiveCalendar.id) { updateTaskTiming(task); if (this.config.inherit_calendar && this.isSummaryTask(task)) { this.eachTask(function(child) { updateTaskTiming(child); }, task.id); } } task.$effective_calendar = effectiveCalendar.id; }; function updateTaskTiming(task) { task.$effective_calendar = gantt2.getTaskCalendar(task).id; task.start_date = gantt2.getClosestWorkTime({ dir: "future", date: task.start_date, unit: gantt2.config.duration_unit, task }); task.end_date = gantt2.calculateEndDate(task); } gantt2.isSummaryTask = function(task) { gantt2.assert(task && task instanceof Object, "Invalid argument task=" + task + " of gantt.isSummaryTask. Task object was expected"); var mode = getTaskTimingMode(task); return !!(mode.$no_end || mode.$no_start); }; gantt2.resetProjectDates = function(task) { var taskMode = getTaskTimingMode(task); if (taskMode.$no_end || taskMode.$no_start) { var info = getSubtaskInfo(task.id); assignProjectDates.call(this, task, taskMode, info.start_date, info.end_date); task.$rollup = info.rollup; task.$inlineSplit = info.splitItems; } }; function assignProjectDates(task, taskTiming, from, to) { const summaryDateFields = { start: "start_date", end: "end_date" }; const manuallyScheduledSummaryDateFields = { start: "$auto_start_date", end: "$auto_end_date" }; let dateFields; if (task.type === gantt2.config.types.project && task.auto_scheduling === false) { dateFields = manuallyScheduledSummaryDateFields; } else { dateFields = summaryDateFields; } if (taskTiming.$no_start) { if (from) { task[dateFields.start] = new Date(from); } else { task[dateFields.start] = getDefaultTaskDate(task, this.getParent(task)); } } if (taskTiming.$no_end) { if (to) { task[dateFields.end] = new Date(to); } else { task[dateFields.end] = this.calculateEndDate({ start_date: task[dateFields.start], duration: this.config.duration_step, task }); } } if (taskTiming.$no_start || taskTiming.$no_end) { this._init_task_timing(task); } } gantt2.getSubtaskDuration = function(taskId) { var res = 0, root = taskId !== void 0 ? taskId : gantt2.config.root_id; this.eachTask(function(child) { if (this.getTaskType(child.type) == gantt2.config.types.project || this.isUnscheduledTask(child)) return; res += child.duration; }, root); return res; }; function getSubtaskInfo(taskId) { let min = null; let max = null; let root = taskId !== void 0 ? taskId : gantt2.config.root_id; const rollup = []; const inlineSplit = []; let rootTask = null; if (gantt2.isTaskExists(root)) { rootTask = gantt2.getTask(root); } gantt2.eachTask(function(child) { const isScheduledSummary = gantt2.getTaskType(child.type) == gantt2.config.types.project && child.auto_scheduling === false; if (gantt2.getTaskType(child.type) == gantt2.config.types.project && !isScheduledSummary || gantt2.isUnscheduledTask(child)) return; if (child.rollup) { rollup.push(child.id); } if (child.start_date && (!child.$no_start || isScheduledSummary) && (!min || min > child.start_date.valueOf())) min = child.start_date.valueOf(); if (child.end_date && (!child.$no_end || isScheduledSummary) && (!max || max < child.end_date.valueOf())) max = child.end_date.valueOf(); if (rootTask && rootTask.render == "split") { if (child.split_placement === "inline") { inlineSplit.push(child); } else if (child.split_placement !== "subrow" && (!rootTask.$open || !gantt2.config.open_split_tasks)) { inlineSplit.push(child); } } }, root); return { start_date: min ? new Date(min) : null, end_date: max ? new Date(max) : null, rollup, splitItems: inlineSplit }; } gantt2.getSubtaskDates = function(task_id) { var info = getSubtaskInfo(task_id); return { start_date: info.start_date, end_date: info.end_date }; }; gantt2._update_parents = function(taskId, silent, updateAll) { if (!taskId) return; var task = this.getTask(taskId); if (task.rollup) { updateAll = true; } var pid = this.getParent(task); var taskTiming = getTaskTimingMode(task); var has_changed = true; if (updateAll || task.start_date && task.end_date && (taskTiming.$no_start || taskTiming.$no_end)) { const startDateField = task.$auto_start_date ? "$auto_start_date" : "start_date"; const endDateField = task.$auto_end_date ? "$auto_end_date" : "end_date"; var oldStart = task[startDateField].valueOf(), oldEnd = task[endDateField].valueOf(); gantt2.resetProjectDates(task); if (!updateAll && oldStart == task[startDateField].valueOf() && oldEnd == task[endDateField].valueOf()) { has_changed = false; } if (has_changed && !silent) { this.refreshTask(task.id, true); } if (taskTiming.scheduled_summary) { has_changed = true; } } if (has_changed && pid && this.isTaskExists(pid)) { this._update_parents(pid, silent, updateAll); } }; gantt2.roundDate = function(config2) { var scale = gantt2.getScale(); if (isDate(config2)) { config2 = { date: config2, unit: scale ? scale.unit : gantt2.config.duration_unit, step: scale ? scale.step : gantt2.config.duration_step }; } var date2 = config2.date, steps = config2.step, unit = config2.unit; if (!scale) { return date2; } var upper, lower, colIndex; if (unit == scale.unit && steps == scale.step && +date2 >= +scale.min_date && +date2 <= +scale.max_date) { colIndex = Math.floor(gantt2.columnIndexByDate(date2)); if (!scale.trace_x[colIndex]) { colIndex -= 1; if (scale.rtl) { colIndex = 0; } } lower = new Date(scale.trace_x[colIndex]); upper = gantt2.date.add(lower, steps, unit); } else { colIndex = Math.floor(gantt2.columnIndexByDate(date2)); upper = gantt2.date[unit + "_start"](new Date(scale.min_date)); if (scale.trace_x[colIndex]) { upper = gantt2.date[unit + "_start"](scale.trace_x[colIndex]); } while (+upper < +date2) { upper = gantt2.date[unit + "_start"](gantt2.date.add(upper, steps, unit)); var tzOffset = upper.getTimezoneOffset(); upper = gantt2._correct_dst_change(upper, tzOffset, upper, unit); if (gantt2.date[unit + "_start"]) upper = gantt2.date[unit + "_start"](upper); } lower = gantt2.date.add(upper, -1 * steps, unit); } if (config2.dir && config2.dir == "future") return upper; if (config2.dir && config2.dir == "past") return lower; if (Math.abs(date2 - lower) < Math.abs(upper - date2)) { return lower; } else { return upper; } }; gantt2.correctTaskWorkTime = function(task) { if (gantt2.config.work_time && gantt2.config.correct_work_time) { if (!this.isWorkTime(task.start_date, void 0, task)) { task.start_date = this.getClosestWorkTime({ date: task.start_date, dir: "future", task }); task.end_date = this.calculateEndDate(task); } else if (!this.isWorkTime(new Date(+task.end_date - 1), void 0, task)) { task.end_date = this.calculateEndDate(task); } } }; gantt2.attachEvent("onBeforeTaskUpdate", function(id, task) { gantt2._init_task_timing(task); return true; }); gantt2.attachEvent("onBeforeTaskAdd", function(id, task) { gantt2._init_task_timing(task); return true; }); gantt2.attachEvent("onAfterTaskMove", function(id, parent, tindex) { gantt2._init_task_timing(gantt2.getTask(id)); return true; }); } function data_task_types(gantt2) { gantt2.getTaskType = function(type) { return "task"; }; } function cached_functions(gantt2) { gantt2._cached_functions = { cache: {}, mode: false, critical_path_mode: false, wrap_methods: function(methods, object) { if (object._prefetch_originals) { for (var i in object._prefetch_originals) { object[i] = object._prefetch_originals[i]; } } object._prefetch_originals = {}; for (var i = 0; i < methods.length; i++) this.prefetch(methods[i], object); }, prefetch: function(methodname, host) { var original = host[methodname]; if (original) { var optimizer = this; host._prefetch_originals[methodname] = original; host[methodname] = function get_prefetched_value() { var argumentsArray = new Array(arguments.length); for (var i = 0, l = arguments.length; i < l; i++) { argumentsArray[i] = arguments[i]; } if (optimizer.active) { var args = optimizer.get_arguments_hash(Array.prototype.slice.call(argumentsArray)); if (!optimizer.cache[methodname]) { optimizer.cache[methodname] = {}; } var cached_values = optimizer.cache[methodname]; if (optimizer.has_cached_value(cached_values, args)) { return optimizer.get_cached_value(cached_values, args); } else { var value = original.apply(this, argumentsArray); optimizer.cache_value(cached_values, args, value); return value; } } return original.apply(this, argumentsArray); }; } return original; }, cache_value: function(cache, arguments_hash, value) { if (this.is_date(value)) value = new Date(value); cache[arguments_hash] = value; }, has_cached_value: function(cache, arguments_hash) { return cache.hasOwnProperty(arguments_hash); }, get_cached_value: function(cache, arguments_hash) { var data2 = cache[arguments_hash]; if (this.is_date(data2)) { data2 = new Date(data2); } return data2; }, is_date: function(value) { return value && value.getUTCDate; }, get_arguments_hash: function(args) { var values = []; for (var i = 0; i < args.length; i++) { values.push(this.stringify_argument(args[i])); } return "(" + values.join(";") + ")"; }, stringify_argument: function(value) { var ret = ""; if (value.id) { ret = value.id; } else if (this.is_date(value)) { ret = value.valueOf(); } else { ret = value; } return ret + ""; }, activate: function() { this.clear(); this.active = true; }, deactivate: function() { this.clear(); this.active = false; }, clear: function() { this.cache = {}; }, setup: function(gantt3) { var override_gantt = []; var gantt_methods = ["_isProjectEnd", "_getProjectEnd", "_getSlack"]; if (this.mode == "auto") { if (gantt3.config.highlight_critical_path) { override_gantt = gantt_methods; } } else if (this.mode === true) { override_gantt = gantt_methods; } this.wrap_methods(override_gantt, gantt3); }, update_if_changed: function(gantt3) { var changed = this.critical_path_mode != gantt3.config.highlight_critical_path || this.mode !== gantt3.config.optimize_render; if (changed) { this.critical_path_mode = gantt3.config.highlight_critical_path; this.mode = gantt3.config.optimize_render; this.setup(gantt3); } } }; function activate() { gantt2._cached_functions.update_if_changed(gantt2); if (!gantt2._cached_functions.active) { gantt2._cached_functions.activate(); } return true; } gantt2.attachEvent("onBeforeGanttRender", activate); gantt2.attachEvent("onBeforeDataRender", activate); gantt2.attachEvent("onBeforeSmartRender", function() { activate(); }); gantt2.attachEvent("onBeforeParse", activate); gantt2.attachEvent("onDataRender", function() { gantt2._cached_functions.deactivate(); }); var deactivTimeout = null; gantt2.attachEvent("onSmartRender", function() { if (deactivTimeout) clearTimeout(deactivTimeout); deactivTimeout = setTimeout(function() { gantt2._cached_functions.deactivate(); }, 1e3); }); gantt2.attachEvent("onBeforeGanttReady", function() { gantt2._cached_functions.update_if_changed(gantt2); return true; }); } function addResizeListener(gantt2) { var containerStyles = window.getComputedStyle(gantt2.$root); if (containerStyles.getPropertyValue("position") == "static") { gantt2.$root.style.position = "relative"; } var resizeWatcher = document.createElement("iframe"); resizeWatcher.className = "gantt_container_resize_watcher"; resizeWatcher.tabIndex = -1; if (gantt2.config.wai_aria_attributes) { resizeWatcher.setAttribute("role", "none"); resizeWatcher.setAttribute("aria-hidden", true); } if (gantt2.env.isSalesforce) { gantt2.config.container_resize_method = "timeout"; } gantt2.$root.appendChild(resizeWatcher); if (resizeWatcher.contentWindow) { listenWindowResize(gantt2, resizeWatcher.contentWindow); } else { gantt2.$root.removeChild(resizeWatcher); listenWindowResize(gantt2, window); } } function listenWindowResize(gantt2, window2) { var resizeTimeout = gantt2.config.container_resize_timeout || 20; var resizeDelay; let previousSize = getContainerSize(gantt2); if (gantt2.config.container_resize_method == "timeout") { lowlevelResizeWatcher(); } else { try { gantt2.event(window2, "resize", function() { if (gantt2.$scrollbarRepaint) { gantt2.$scrollbarRepaint = null; } else { let currentSize = getContainerSize(gantt2); if (previousSize.x == currentSize.x && previousSize.y == currentSize.y) { return; } previousSize = currentSize; repaintGantt(); } }); } catch (e) { lowlevelResizeWatcher(); } } function repaintGantt() { clearTimeout(resizeDelay); resizeDelay = setTimeout(function() { if (!gantt2.$destroyed) { gantt2.render(); } }, resizeTimeout); } var previousHeight = gantt2.$root.offsetHeight; var previousWidth = gantt2.$root.offsetWidth; function lowlevelResizeWatcher() { if (gantt2.$root.offsetHeight != previousHeight || gantt2.$root.offsetWidth != previousWidth) { repaintGantt(); } previousHeight = gantt2.$root.offsetHeight; previousWidth = gantt2.$root.offsetWidth; setTimeout(lowlevelResizeWatcher, resizeTimeout); } } function getContainerSize(gantt2) { return { x: gantt2.$root.offsetWidth, y: gantt2.$root.offsetHeight }; } function assert(gantt2) { return function assert2(check, message) { if (!check) { if (gantt2.config.show_errors && gantt2.callEvent("onError", [message]) !== false) { if (gantt2.message) { gantt2.message({ type: "error", text: message, expire: -1 }); } else { console.log(message); } debugger; } } }; } function gantt_core(gantt2) { gantt2.assert = assert(gantt2); function isHTMLElement(node) { try { node.cloneNode(false); } catch (e) { return false; } return true; } var invalidContainerMessage = "Invalid value of the first argument of `gantt.init`. Supported values: HTMLElement, String (element id).This error means that either invalid object is passed into `gantt.init` or that the element with the specified ID doesn't exist on the page when `gantt.init` is called."; function validateNode(node) { if (!node || typeof node == "string" && document.getElementById(node)) return true; if (isHTMLElement(node)) return true; gantt2.assert(false, invalidContainerMessage); throw new Error(invalidContainerMessage); } gantt2.init = function(node, from, to) { if (gantt2.env.isNode) { node = null; } else { validateNode(node); } if (from && to) { this.config.start_date = this._min_date = new Date(from); this.config.end_date = this._max_date = new Date(to); } this.date.init(); this.init = function(node2) { if (gantt2.env.isNode) { node2 = null; } else { validateNode(node2); } if (this.$container && this.$container.parentNode) { this.$container.parentNode.removeChild(this.$container); this.$container = null; } if (this.$layout) { this.$layout.clear(); } this._reinit(node2); }; this._reinit(node); }; gantt2._quickRefresh = function(code) { var stores = this._getDatastores.call(this); for (var i = 0; i < stores.length; i++) { stores[i]._quick_refresh = true; } code(); for (var i = 0; i < stores.length; i++) { stores[i]._quick_refresh = false; } }; var dropLayout = (function dropLayout2() { if (this._clearTaskLayers) { this._clearTaskLayers(); } if (this._clearLinkLayers) { this._clearLinkLayers(); } if (this.$layout) { this.$layout.destructor(); this.$layout = null; this.$ui.reset(); } }).bind(gantt2); var rebuildLayout = (function rebuildLayout2() { if (isHeadless(gantt2)) { return; } this.$root.innerHTML = ""; this.$root.gantt = this; updateTasksRange(this); this.config.layout.id = "main"; this.$layout = this.$ui.createView("layout", this.$root, this.config.layout); this.$layout.attachEvent("onBeforeResize", function() { var storeNames = gantt2.$services.getService("datastores"); for (var i = 0; i < storeNames.length; i++) { gantt2.getDatastore(storeNames[i]).filter(); if (gantt2.$data.tasksStore._skipTaskRecalculation) { if (gantt2.$data.tasksStore._skipTaskRecalculation != "lightbox") { gantt2.$data.tasksStore._skipTaskRecalculation = false; } } else { gantt2.getDatastore(storeNames[i]).callEvent("onBeforeRefreshAll", []); } } }); this.$layout.attachEvent("onResize", function() { gantt2._quickRefresh(function() { gantt2.refreshData(); }); }); this.callEvent("onGanttLayoutReady", []); this.$layout.render(); this.$container = this.$layout.$container.firstChild; addResizeListener(this); }).bind(gantt2); gantt2.resetLayout = function() { dropLayout(); rebuildLayout(); this.render(); }; gantt2._reinit = function(node) { this.callEvent("onBeforeGanttReady", []); this._update_flags(); var config2 = this.$services.getService("templateLoader"); config2.initTemplates(this); dropLayout(); this.$root = null; if (node) { this.$root = toNode(node); rebuildLayout(); this.$mouseEvents.reset(this.$root); addMinimalSizes(gantt2); } this.callEvent("onTemplatesReady", []); this.callEvent("onGanttReady", []); this.render(); }; function addMinimalSizes(gantt3) { if (gantt3.$container && !gantt3.config.autosize) { if (gantt3.$root.offsetHeight < 50) { console.warn(`The Gantt container has a small height, so you cannot see its content. If it is not intended, you need to set the 'height' style rule to the container: https://docs.dhtmlx.com/gantt/faq.html#theganttchartisntrenderedcorrectly`); } } } gantt2.$click = { buttons: { edit: function(id) { if (gantt2.isReadonly(gantt2.getTask(id))) { return; } gantt2.showLightbox(id); }, delete: function(id) { var task = gantt2.getTask(id); if (gantt2.isReadonly(task)) { return; } var question = gantt2.locale.labels.confirm_deleting; var title = gantt2.locale.labels.confirm_deleting_title; gantt2._delete_task_confirm({ task, message: question, title, callback: function() { if (!gantt2.isTaskExists(id)) { gantt2.hideLightbox(); return; } if (task.$new) { gantt2.$data.tasksStore._skipTaskRecalculation = "lightbox"; gantt2.silent(function() { gantt2.deleteTask(id, true); }); gantt2.$data.tasksStore._skipTaskRecalculation = false; gantt2.refreshData(); } else { gantt2.$data.tasksStore._skipTaskRecalculation = true; gantt2.deleteTask(id); } gantt2.hideLightbox(); } }); } } }; gantt2.render = function() { this.callEvent("onBeforeGanttRender", []); var visibleDate; if (!isHeadless(gantt2)) { if (!this.config.sort && this._sort) { this._sort = void 0; } if (this.$root) { if (this.config.rtl) { this.$root.classList.add("gantt_rtl"); this.$root.firstChild.classList.add("gantt_rtl"); } else { this.$root.classList.remove("gantt_rtl"); this.$root.firstChild.classList.remove("gantt_rtl"); } } var pos = this.getScrollState(); var posX = pos ? pos.x : 0; if (this._getHorizontalScrollbar()) { var scrollbar = this._getHorizontalScrollbar(); posX = scrollbar.$config.codeScrollLeft || posX || 0; } visibleDate = null; if (posX) { visibleDate = gantt2.dateFromPos(posX + this.config.task_scroll_offset); } } updateTasksRange(this); if (!isHeadless(gantt2)) { this.$layout.$config.autosize = this.config.autosize; var preserveScroll = this.config.preserve_scroll; this.config.preserve_scroll = false; this.$layout.resize(); this.config.preserve_scroll = preserveScroll; if (this.config.preserve_scroll && pos) { const zoom = gantt2.ext.zoom._initialized; if ((posX || pos.y) && !zoom) { var new_pos = gantt2.getScrollState(); var new_date = gantt2.dateFromPos(new_pos.x); if (!(+visibleDate == +new_date && new_pos.y == pos.y)) { var posX = null; var posY = null; if (visibleDate) { var posX = Math.max(gantt2.posFromDate(visibleDate) - gantt2.config.task_scroll_offset, 0); } if (pos.y) { posY = pos.y; } gantt2.scrollTo(posX, posY); } } const scrollbarsInfo = this.$layout.getScrollbarsInfo(); scrollbarsInfo.forEach((scroll_info) => { const scroll = gantt2.$ui.getView(scroll_info.id); const scrollbarNodeVisible = gantt2.utils.dom.isChildOf(scroll.$view, gantt2.$container); scroll_info.boundViews.forEach((viewName) => { const view = gantt2.$ui.getView(viewName); if (scroll_info.y && scroll_info.y != pos.y) { if (view && !scrollbarNodeVisible) { view.scrollTo(void 0, 0); } } if (scroll_info.x_pos && scroll_info.x_pos != pos.x) { if (view && scrollbarNodeVisible) { view.scrollTo(scroll_info.x_pos, void 0); } } }); }); } } else { gantt2.refreshData(); } this.callEvent("onGanttRender", []); }; gantt2.setSizes = gantt2.render; gantt2.getTaskRowNode = function(id) { var els = this.$grid_data.childNodes; var attribute = this.config.task_attribute; for (var i = 0; i < els.length; i++) { if (els[i].getAttribute) { var value = els[i].getAttribute(attribute); if (value == id) return els[i]; } } return null; }; gantt2.changeLightboxType = function(type) { if (this.getLightboxType() == type) return true; gantt2._silent_redraw_lightbox(type); }; gantt2._get_link_type = function(from_start, to_start) { var type = null; if (from_start && to_start) { type = gantt2.config.links.start_to_start; } else if (!from_start && to_start) { type = gantt2.config.links.finish_to_start; } else if (!from_start && !to_start) { type = gantt2.config.links.finish_to_finish; } else if (from_start && !to_start) { type = gantt2.config.links.start_to_finish; } return type; }; gantt2.isLinkAllowed = function(from, to, from_start, to_start) { var link = null; if (typeof from == "object") { link = from; } else { link = { source: from, target: to, type: this._get_link_type(from_start, to_start) }; } if (!link) return false; if (!(link.source && link.target && link.type)) return false; if (link.source == link.target) return false; var res = true; if (this.checkEvent("onLinkValidation")) res = this.callEvent("onLinkValidation", [link]); return res; }; gantt2._correct_dst_change = function(date2, prevOffset, step, unit) { var time_unit = getSecondsInUnit(unit) * step; if (time_unit > 60 * 60 && time_unit < 60 * 60 * 24) { var offsetChanged = date2.getTimezoneOffset() - prevOffset; if (offsetChanged) { date2 = gantt2.date.add(date2, offsetChanged, "minute"); } } return date2; }; gantt2.isSplitTask = function(task) { gantt2.assert(task && task instanceof Object, "Invalid argument task=" + task + " of gantt.isSplitTask. Task object was expected"); return this.$data.tasksStore._isSplitItem(task); }; gantt2._is_icon_open_click = function(e) { if (!e) return false; var target = e.target || e.srcElement; if (!(target && target.className)) return false; var className = getClassName(target); if (className.indexOf("gantt_tree_icon") !== -1 && (className.indexOf("gantt_close") !== -1 || className.indexOf("gantt_open") !== -1)) return true; return false; }; } function extend(gantt2) { gantt2.destructor = function() { this.clearAll(); this.callEvent("onDestroy", []); this._getDatastores().forEach(function(store) { store.destructor(); }); if (this.$root) { delete this.$root.gantt; } if (this._eventRemoveAll) { this._eventRemoveAll(); } if (this.$layout) { this.$layout.destructor(); } if (this.resetLightbox) { this.resetLightbox(); } if (this.ext.inlineEditors && this.ext.inlineEditors.destructor) { this.ext.inlineEditors.destructor(); } if (this._dp && this._dp.destructor) { this._dp.destructor(); } this.$services.destructor(); this.detachAllEvents(); for (var i in this) { if (i.indexOf("$") === 0) { delete this[i]; } } this.$destroyed = true; }; } const locale$v = { date: { month_full: ["كانون الثاني", "شباط", "آذار", "نيسان", "أيار", "حزيران", "تموز", "آب", "أيلول", "تشرين الأول", "تشرين الثاني", "كانون الأول"], month_short: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"], day_full: ["الأحد", "الأثنين", "ألثلاثاء", "الأربعاء", "ألحميس", "ألجمعة", "السبت"], day_short: ["احد", "اثنين", "ثلاثاء", "اربعاء", "خميس", "جمعة", "سبت"] }, labels: { new_task: "مهمة جديد", icon_save: "اخزن", icon_cancel: "الغاء", icon_details: "تفاصيل", icon_edit: "تحرير", icon_delete: "حذف", confirm_closing: "التغييرات سوف تضيع, هل انت متأكد؟", confirm_deleting: "الحدث سيتم حذفها نهائيا ، هل أنت متأكد؟", section_description: "الوصف", section_time: "الفترة الزمنية", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "الغاء", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$u = { date: { month_full: ["Студзень", "Люты", "Сакавік", "Красавік", "Maй", "Чэрвень", "Ліпень", "Жнівень", "Верасень", "Кастрычнік", "Лістапад", "Снежань"], month_short: ["Студз", "Лют", "Сак", "Крас", "Maй", "Чэр", "Ліп", "Жнів", "Вер", "Каст", "Ліст", "Снеж"], day_full: ["Нядзеля", "Панядзелак", "Аўторак", "Серада", "Чацвер", "Пятніца", "Субота"], day_short: ["Нд", "Пн", "Аўт", "Ср", "Чцв", "Пт", "Сб"] }, labels: { new_task: "Новае заданне", icon_save: "Захаваць", icon_cancel: "Адмяніць", icon_details: "Дэталі", icon_edit: "Змяніць", icon_delete: "Выдаліць", confirm_closing: "", confirm_deleting: "Падзея будзе выдалена незваротна, працягнуць?", section_description: "Апісанне", section_time: "Перыяд часу", section_type: "Тып", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "ІСР", column_text: "Задача", column_start_date: "Пачатак", column_duration: "Працяг", column_add: "", link: "Сувязь", confirm_link_deleting: "будзе выдалена", link_start: "(пачатак)", link_end: "(канец)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Хвiлiна", hours: "Гадзiна", days: "Дзень", weeks: "Тыдзень", months: "Месяц", years: "Год", message_ok: "OK", message_cancel: "Адмяніць", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$t = { date: { month_full: ["Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre"], month_short: ["Gen", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Oct", "Nov", "Des"], day_full: ["Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte"], day_short: ["Dg", "Dl", "Dm", "Dc", "Dj", "Dv", "Ds"] }, labels: { new_task: "Nova tasca", icon_save: "Guardar", icon_cancel: "Cancel·lar", icon_details: "Detalls", icon_edit: "Editar", icon_delete: "Esborrar", confirm_closing: "", confirm_deleting: "L'esdeveniment s'esborrarà definitivament, continuar ?", section_description: "Descripció", section_time: "Periode de temps", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Cancel·lar", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$s = { date: { month_full: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], day_full: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], day_short: ["日", "一", "二", "三", "四", "五", "六"] }, labels: { new_task: "新任務", icon_save: "保存", icon_cancel: "关闭", icon_details: "详细", icon_edit: "编辑", icon_delete: "删除", confirm_closing: "请确认是否撤销修改!", confirm_deleting: "是否删除日程?", section_description: "描述", section_time: "时间范围", section_type: "类型", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "工作分解结构", column_text: "任务名", column_start_date: "开始时间", column_duration: "持续时间", column_add: "", link: "关联", confirm_link_deleting: "将被删除", link_start: " (开始)", link_end: " (结束)", type_task: "任务", type_project: "项目", type_milestone: "里程碑", minutes: "分钟", hours: "小时", days: "天", weeks: "周", months: "月", years: "年", message_ok: "OK", message_cancel: "关闭", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$r = { date: { month_full: ["Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"], month_short: ["Led", "Ún", "Bře", "Dub", "Kvě", "Čer", "Čec", "Srp", "Září", "Říj", "List", "Pro"], day_full: ["Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota"], day_short: ["Ne", "Po", "Út", "St", "Čt", "Pá", "So"] }, labels: { new_task: "Nová práce", icon_save: "Uložit", icon_cancel: "Zpět", icon_details: "Detail", icon_edit: "Edituj", icon_delete: "Smazat", confirm_closing: "", confirm_deleting: "Událost bude trvale smazána, opravdu?", section_description: "Poznámky", section_time: "Doba platnosti", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Zpět", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$q = { date: { month_full: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"], month_short: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], day_full: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"], day_short: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"] }, labels: { new_task: "Ny opgave", icon_save: "Gem", icon_cancel: "Fortryd", icon_details: "Detaljer", icon_edit: "Tilret", icon_delete: "Slet", confirm_closing: "Dine rettelser vil gå tabt.. Er dy sikker?", confirm_deleting: "Bigivenheden vil blive slettet permanent. Er du sikker?", section_description: "Beskrivelse", section_time: "Tidsperiode", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Fortryd", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$p = { date: { month_full: [" Januar", " Februar", " März ", " April", " Mai", " Juni", " Juli", " August", " September ", " Oktober", " November ", " Dezember"], month_short: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], day_full: ["Sonntag", "Montag", "Dienstag", " Mittwoch", " Donnerstag", "Freitag", "Samstag"], day_short: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"] }, labels: { new_task: "Neue Aufgabe", icon_save: "Speichern", icon_cancel: "Abbrechen", icon_details: "Details", icon_edit: "Ändern", icon_delete: "Löschen", confirm_closing: "", confirm_deleting: "Der Eintrag wird gelöscht", section_description: "Beschreibung", section_time: "Zeitspanne", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "PSP", column_text: "Task-Namen", column_start_date: "Startzeit", column_duration: "Dauer", column_add: "", link: "Link", confirm_link_deleting: "werden gelöscht", link_start: "(starten)", link_end: "(ende)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minuten", hours: "Stunden", days: "Tage", weeks: "Wochen", months: "Monate", years: "Jahre", message_ok: "OK", message_cancel: "Abbrechen", section_constraint: "Regel", constraint_type: "Regel", constraint_date: "Regel - Datum", asap: "So bald wie möglich", alap: "So spät wie möglich", snet: "Beginn nicht vor", snlt: "Beginn nicht später als", fnet: "Fertigstellung nicht vor", fnlt: "Fertigstellung nicht später als", mso: "Muss beginnen am", mfo: "Muss fertig sein am", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$o = { date: { month_full: ["Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάϊος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος"], month_short: ["ΙΑΝ", "ΦΕΒ", "ΜΑΡ", "ΑΠΡ", "ΜΑΙ", "ΙΟΥΝ", "ΙΟΥΛ", "ΑΥΓ", "ΣΕΠ", "ΟΚΤ", "ΝΟΕ", "ΔΕΚ"], day_full: ["Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Κυριακή"], day_short: ["ΚΥ", "ΔΕ", "ΤΡ", "ΤΕ", "ΠΕ", "ΠΑ", "ΣΑ"] }, labels: { new_task: "Νέα εργασία", icon_save: "Αποθήκευση", icon_cancel: "Άκυρο", icon_details: "Λεπτομέρειες", icon_edit: "Επεξεργασία", icon_delete: "Διαγραφή", confirm_closing: "", confirm_deleting: "Το έργο θα διαγραφεί οριστικά. Θέλετε να συνεχίσετε;", section_description: "Περιγραφή", section_time: "Χρονική περίοδος", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Άκυρο", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$n = { date: { month_full: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], month_short: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], day_full: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], day_short: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] }, labels: { new_task: "New task", icon_save: "Save", icon_cancel: "Cancel", icon_details: "Details", icon_edit: "Edit", icon_delete: "Delete", confirm_closing: "", confirm_deleting: "Task will be deleted permanently, are you sure?", section_description: "Description", section_time: "Time period", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Cancel", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$m = { date: { month_full: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], month_short: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"], day_full: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"], day_short: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb"] }, labels: { new_task: "Nueva tarea", icon_save: "Guardar", icon_cancel: "Cancelar", icon_details: "Detalles", icon_edit: "Editar", icon_delete: "Eliminar", confirm_closing: "", confirm_deleting: "El evento se borrará definitivamente, ¿continuar?", section_description: "Descripción", section_time: "Período", section_type: "Tipo", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "EDT", column_text: "Tarea", column_start_date: "Inicio", column_duration: "Duración", column_add: "", link: "Enlace", confirm_link_deleting: "será borrada", link_start: " (inicio)", link_end: " (fin)", type_task: "Tarea", type_project: "Proyecto", type_milestone: "Hito", minutes: "Minutos", hours: "Horas", days: "Días", weeks: "Semanas", months: "Meses", years: "Años", message_ok: "OK", message_cancel: "Cancelar", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$l = { date: { month_full: ["ژانویه", "فوریه", "مارس", "آوریل", "مه", "ژوئن", "ژوئیه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "دسامبر"], month_short: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], day_full: ["يکشنبه", "دوشنبه", "سه‌شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه"], day_short: ["ی", "د", "س", "چ", "پ", "ج", "ش"] }, labels: { new_task: "وظیفه جدید", icon_save: "ذخیره", icon_cancel: "لغو", icon_details: "جزییات", icon_edit: "ویرایش", icon_delete: "حذف", confirm_closing: "تغییرات شما ازدست خواهد رفت، آیا مطمئن هستید؟", confirm_deleting: "این مورد برای همیشه حذف خواهد شد، آیا مطمئن هستید؟", section_description: "توضیحات", section_time: "مدت زمان", section_type: "نوع", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "عنوان", column_start_date: "زمان شروع", column_duration: "مدت", column_add: "", link: "ارتباط", confirm_link_deleting: "حذف خواهد شد", link_start: " (آغاز)", link_end: " (پایان)", type_task: "وظیفه", type_project: "پروژه", type_milestone: "نگارش", minutes: "دقایق", hours: "ساعات", days: "روزها", weeks: "هفته", months: "ماه‌ها", years: "سال‌ها", message_ok: "تایید", message_cancel: "لغو", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$k = { date: { month_full: ["Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu"], month_short: ["Tam", "Hel", "Maa", "Huh", "Tou", "Kes", "Hei", "Elo", "Syy", "Lok", "Mar", "Jou"], day_full: ["Sunnuntai", "Maanantai", "Tiistai", "Keskiviikko", "Torstai", "Perjantai", "Lauantai"], day_short: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"] }, labels: { new_task: "Uusi tehtävä", icon_save: "Tallenna", icon_cancel: "Peru", icon_details: "Tiedot", icon_edit: "Muokkaa", icon_delete: "Poista", confirm_closing: "", confirm_deleting: "Haluatko varmasti poistaa tapahtuman?", section_description: "Kuvaus", section_time: "Aikajakso", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Peru", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$j = { date: { month_full: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], month_short: ["Jan", "Fév", "Mar", "Avr", "Mai", "Juin", "Juil", "Aoû", "Sep", "Oct", "Nov", "Déc"], day_full: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"], day_short: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"] }, labels: { new_task: "Nouvelle tâche", icon_save: "Enregistrer", icon_cancel: "Annuler", icon_details: "Détails", icon_edit: "Modifier", icon_delete: "Effacer", confirm_closing: "", confirm_deleting: "L'événement sera effacé sans appel, êtes-vous sûr ?", section_description: "Description", section_time: "Période", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "OTP", column_text: "Nom de la tâche", column_start_date: "Date initiale", column_duration: "Durée", column_add: "", link: "Le lien", confirm_link_deleting: "sera supprimé", link_start: "(début)", link_end: "(fin)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Heures", days: "Jours", weeks: "Semaines", months: "Mois", years: "Années", message_ok: "OK", message_cancel: "Annuler", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$i = { date: { month_full: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"], month_short: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"], day_full: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"], day_short: ["א", "ב", "ג", "ד", "ה", "ו", "ש"] }, labels: { new_task: "משימה חדש", icon_save: "שמור", icon_cancel: "בטל", icon_details: "פרטים", icon_edit: "ערוך", icon_delete: "מחק", confirm_closing: "", confirm_deleting: "ארוע ימחק סופית.להמשיך?", section_description: "הסבר", section_time: "תקופה", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "בטל", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$h = { date: { month_full: ["Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"], month_short: ["Sij", "Velj", "Ožu", "Tra", "Svi", "Lip", "Srp", "Kol", "Ruj", "Lis", "Stu", "Pro"], day_full: ["Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"], day_short: ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"] }, labels: { new_task: "Novi Zadatak", icon_save: "Spremi", icon_cancel: "Odustani", icon_details: "Detalji", icon_edit: "Izmjeni", icon_delete: "Obriši", confirm_closing: "", confirm_deleting: "Zadatak će biti trajno izbrisan, jeste li sigurni?", section_description: "Opis", section_time: "Vremenski Period", section_type: "Tip", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Naziv Zadatka", column_start_date: "Početno Vrijeme", column_duration: "Trajanje", column_add: "", link: "Poveznica", confirm_link_deleting: "će biti izbrisan", link_start: " (početak)", link_end: " (kraj)", type_task: "Zadatak", type_project: "Projekt", type_milestone: "Milestone", minutes: "Minute", hours: "Sati", days: "Dani", weeks: "Tjedni", months: "Mjeseci", years: "Godine", message_ok: "OK", message_cancel: "Odustani", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$g = { date: { month_full: ["Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"], month_short: ["Jan", "Feb", "Már", "Ápr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"], day_full: ["Vasárnap", "Hétfõ", "Kedd", "Szerda", "Csütörtök", "Péntek", "szombat"], day_short: ["Va", "Hé", "Ke", "Sze", "Csü", "Pé", "Szo"] }, labels: { new_task: "Új feladat", icon_save: "Mentés", icon_cancel: "Mégse", icon_details: "Részletek", icon_edit: "Szerkesztés", icon_delete: "Törlés", confirm_closing: "", confirm_deleting: "Az esemény törölve lesz, biztosan folytatja?", section_description: "Leírás", section_time: "Idõszak", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Mégse", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$f = { date: { month_full: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"], month_short: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"], day_full: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"], day_short: ["Ming", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"] }, labels: { new_task: "Tugas baru", icon_save: "Simpan", icon_cancel: "Batal", icon_details: "Detail", icon_edit: "Edit", icon_delete: "Hapus", confirm_closing: "", confirm_deleting: "Acara akan dihapus", section_description: "Keterangan", section_time: "Periode", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Batal", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$e = { date: { month_full: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], month_short: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"], day_full: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"], day_short: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"] }, labels: { new_task: "Nuovo compito", icon_save: "Salva", icon_cancel: "Chiudi", icon_details: "Dettagli", icon_edit: "Modifica", icon_delete: "Elimina", confirm_closing: "", confirm_deleting: "Sei sicuro di confermare l'eliminazione?", section_description: "Descrizione", section_time: "Periodo di tempo", section_type: "Tipo", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Nome Attività", column_start_date: "Inizio", column_duration: "Durata", column_add: "", link: "Link", confirm_link_deleting: "sarà eliminato", link_start: " (inizio)", link_end: " (fine)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minuti", hours: "Ore", days: "Giorni", weeks: "Settimane", months: "Mesi", years: "Anni", message_ok: "OK", message_cancel: "Chiudi", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$d = { date: { month_full: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], month_short: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], day_full: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"], day_short: ["日", "月", "火", "水", "木", "金", "土"] }, labels: { new_task: "新しい仕事", icon_save: "保存", icon_cancel: "キャンセル", icon_details: "詳細", icon_edit: "編集", icon_delete: "削除", confirm_closing: "", confirm_deleting: "イベント完全に削除されます、宜しいですか?", section_description: "デスクリプション", section_time: "期間", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "キャンセル", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$c = { date: { month_full: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"], month_short: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"], day_full: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"], day_short: ["일", "월", "화", "수", "목", "금", "토"] }, labels: { new_task: "이름없는 작업", icon_save: "저장", icon_cancel: "취소", icon_details: "세부 사항", icon_edit: "수정", icon_delete: "삭제", confirm_closing: "", confirm_deleting: "작업을 삭제하시겠습니까?", section_description: "설명", section_time: "기간", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "작업명", column_start_date: "시작일", column_duration: "기간", column_add: "", link: "전제", confirm_link_deleting: "삭제 하시겠습니까?", link_start: " (start)", link_end: " (end)", type_task: "작업", type_project: "프로젝트", type_milestone: "마일스톤", minutes: "분", hours: "시간", days: "일", weeks: "주", months: "달", years: "년", message_ok: "OK", message_cancel: "취소", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; class LocaleManager { constructor(config2) { this.addLocale = (name, locale2) => { this._locales[name] = locale2; }; this.getLocale = (name) => this._locales[name]; this._locales = {}; for (const i in config2) { this._locales[i] = config2[i]; } } } const locale$b = { date: { month_full: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], month_short: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"], day_full: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"], day_short: ["Søn", "Mon", "Tir", "Ons", "Tor", "Fre", "Lør"] }, labels: { new_task: "Ny oppgave", icon_save: "Lagre", icon_cancel: "Avbryt", icon_details: "Detaljer", icon_edit: "Rediger", icon_delete: "Slett", confirm_closing: "", confirm_deleting: "Hendelsen vil bli slettet permanent. Er du sikker?", section_description: "Beskrivelse", section_time: "Tidsperiode", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Avbryt", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$a = { date: { month_full: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], month_short: ["Jan", "Feb", "mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], day_full: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"], day_short: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za"] }, labels: { new_task: "Nieuwe taak", icon_save: "Opslaan", icon_cancel: "Annuleren", icon_details: "Details", icon_edit: "Bewerken", icon_delete: "Verwijderen", confirm_closing: "", confirm_deleting: "Item zal permanent worden verwijderd, doorgaan?", section_description: "Beschrijving", section_time: "Tijd periode", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Taak omschrijving", column_start_date: "Startdatum", column_duration: "Duur", column_add: "", link: "Koppeling", confirm_link_deleting: "zal worden verwijderd", link_start: " (start)", link_end: " (eind)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "minuten", hours: "uren", days: "dagen", weeks: "weken", months: "maanden", years: "jaren", message_ok: "OK", message_cancel: "Annuleren", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$9 = { date: { month_full: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], month_short: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"], day_full: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"], day_short: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"] }, labels: { new_task: "Ny oppgave", icon_save: "Lagre", icon_cancel: "Avbryt", icon_details: "Detaljer", icon_edit: "Endre", icon_delete: "Slett", confirm_closing: "Endringer blir ikke lagret, er du sikker?", confirm_deleting: "Oppføringen vil bli slettet, er du sikker?", section_description: "Beskrivelse", section_time: "Tidsperiode", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Avbryt", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$8 = { date: { month_full: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], month_short: ["Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru"], day_full: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"], day_short: ["Nie", "Pon", "Wto", "Śro", "Czw", "Pią", "Sob"] }, labels: { new_task: "Nowe zadanie", icon_save: "Zapisz", icon_cancel: "Anuluj", icon_details: "Szczegóły", icon_edit: "Edytuj", icon_delete: "Usuń", confirm_closing: "", confirm_deleting: "Zdarzenie zostanie usunięte na zawsze, kontynuować?", section_description: "Opis", section_time: "Okres czasu", section_type: "Typ", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Nazwa zadania", column_start_date: "Początek", column_duration: "Czas trwania", column_add: "", link: "Link", confirm_link_deleting: "zostanie usunięty", link_start: " (początek)", link_end: " (koniec)", type_task: "Zadanie", type_project: "Projekt", type_milestone: "Milestone", minutes: "Minuty", hours: "Godziny", days: "Dni", weeks: "Tydzień", months: "Miesiące", years: "Lata", message_ok: "OK", message_cancel: "Anuluj", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$7 = { date: { month_full: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], month_short: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], day_full: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"], day_short: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"] }, labels: { new_task: "Nova tarefa", icon_save: "Salvar", icon_cancel: "Cancelar", icon_details: "Detalhes", icon_edit: "Editar", icon_delete: "Excluir", confirm_closing: "", confirm_deleting: "As tarefas serão excluidas permanentemente, confirme?", section_description: "Descrição", section_time: "Período", section_type: "Tipo", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "EAP", column_text: "Nome tarefa", column_start_date: "Data início", column_duration: "Duração", column_add: "", link: "Link", confirm_link_deleting: "Será excluído!", link_start: " (início)", link_end: " (fim)", type_task: "Task", type_project: "Projeto", type_milestone: "Marco", minutes: "Minutos", hours: "Horas", days: "Dias", weeks: "Semanas", months: "Meses", years: "Anos", message_ok: "OK", message_cancel: "Cancelar", section_constraint: "Restrição", constraint_type: "Tipo Restrição", constraint_date: "Data restrição", asap: "Mais breve possível", alap: "Mais tarde possível", snet: "Não começar antes de", snlt: "Não começar depois de", fnet: "Não terminar antes de", fnlt: "Não terminar depois de", mso: "Precisa começar em", mfo: "Precisa terminar em", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$6 = { date: { month_full: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "November", "December"], month_short: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"], day_full: ["Duminica", "Luni", "Marti", "Miercuri", "Joi", "Vineri", "Sambata"], day_short: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sa"] }, labels: { new_task: "Sarcina noua", icon_save: "Salveaza", icon_cancel: "Anuleaza", icon_details: "Detalii", icon_edit: "Editeaza", icon_delete: "Sterge", confirm_closing: "Schimbarile nu vor fi salvate, esti sigur?", confirm_deleting: "Evenimentul va fi sters permanent, esti sigur?", section_description: "Descriere", section_time: "Interval", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Anuleaza", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$5 = { date: { month_full: ["Январь", "Февраль", "Март", "Апрель", "Maй", "Июнь", "Июль", "Август", "Сентябрь", "Oктябрь", "Ноябрь", "Декабрь"], month_short: ["Янв", "Фев", "Maр", "Aпр", "Maй", "Июн", "Июл", "Aвг", "Сен", "Окт", "Ноя", "Дек"], day_full: ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"], day_short: ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"] }, labels: { new_task: "Новое задание", icon_save: "Сохранить", icon_cancel: "Отменить", icon_details: "Детали", icon_edit: "Изменить", icon_delete: "Удалить", confirm_closing: "", confirm_deleting: "Событие будет удалено безвозвратно, продолжить?", section_description: "Описание", section_time: "Период времени", section_type: "Тип", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "ИСР", column_text: "Задача", column_start_date: "Начало", column_duration: "Длительность", column_add: "", link: "Связь", confirm_link_deleting: "будет удалена", link_start: " (начало)", link_end: " (конец)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Минута", hours: "Час", days: "День", weeks: "Неделя", months: "Месяц", years: "Год", message_ok: "OK", message_cancel: "Отменить", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$4 = { date: { month_full: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"], month_short: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], day_full: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota"], day_short: ["Ned", "Pon", "Tor", "Sre", "Čet", "Pet", "Sob"] }, labels: { new_task: "Nova naloga", icon_save: "Shrani", icon_cancel: "Prekliči", icon_details: "Podrobnosti", icon_edit: "Uredi", icon_delete: "Izbriši", confirm_closing: "", confirm_deleting: "Dogodek bo izbrisan. Želite nadaljevati?", section_description: "Opis", section_time: "Časovni okvir", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Prekliči", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$3 = { date: { month_full: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"], month_short: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sept", "Okt", "Nov", "Dec"], day_full: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota"], day_short: ["Ne", "Po", "Ut", "St", "Št", "Pi", "So"] }, labels: { new_task: "Nová úloha", icon_save: "Uložiť", icon_cancel: "Späť", icon_details: "Detail", icon_edit: "Edituj", icon_delete: "Zmazať", confirm_closing: "Vaše zmeny nebudú uložené. Skutočne?", confirm_deleting: "Udalosť bude natrvalo vymazaná. Skutočne?", section_description: "Poznámky", section_time: "Doba platnosti", section_type: "Type", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Späť", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$2 = { date: { month_full: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"], month_short: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], day_full: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"], day_short: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"] }, labels: { new_task: "Ny uppgift", icon_save: "Spara", icon_cancel: "Avbryt", icon_details: "Detajer", icon_edit: "Ändra", icon_delete: "Ta bort", confirm_closing: "", confirm_deleting: "Är du säker på att du vill ta bort händelsen permanent?", section_description: "Beskrivning", section_time: "Tid", section_type: "Typ", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Uppgiftsnamn", column_start_date: "Starttid", column_duration: "Varaktighet", column_add: "", link: "Länk", confirm_link_deleting: "kommer tas bort", link_start: " (start)", link_end: " (slut)", type_task: "Uppgift", type_project: "Projekt", type_milestone: "Milstolpe", minutes: "Minuter", hours: "Timmar", days: "Dagar", weeks: "Veckor", months: "Månader", years: "År", message_ok: "OK", message_cancel: "Avbryt", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale$1 = { date: { month_full: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"], month_short: ["Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"], day_full: ["Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi"], day_short: ["Paz", "Pzt", "Sal", "Çar", "Per", "Cum", "Cmt"] }, labels: { new_task: "Yeni görev", icon_save: "Kaydet", icon_cancel: "İptal", icon_details: "Detaylar", icon_edit: "Düzenle", icon_delete: "Sil", confirm_closing: "", confirm_deleting: "Görev silinecek, emin misiniz?", section_description: "Açıklama", section_time: "Zaman Aralığı", section_type: "Tip", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Görev Adı", column_start_date: "Başlangıç", column_duration: "Süre", column_add: "", link: "Bağlantı", confirm_link_deleting: "silinecek", link_start: " (başlangıç)", link_end: " (bitiş)", type_task: "Görev", type_project: "Proje", type_milestone: "Kilometretaşı", minutes: "Dakika", hours: "Saat", days: "Gün", weeks: "Hafta", months: "Ay", years: "Yıl", message_ok: "OK", message_cancel: "Ýptal", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; const locale = { date: { month_full: ["Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"], month_short: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"], day_full: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота"], day_short: ["Нед", "Пон", "Вів", "Сер", "Чет", "Птн", "Суб"] }, labels: { new_task: "Нове завдання", icon_save: "Зберегти", icon_cancel: "Відміна", icon_details: "Деталі", icon_edit: "Редагувати", icon_delete: "Вилучити", confirm_closing: "", confirm_deleting: "Подія вилучиться назавжди. Ви впевнені?", section_description: "Опис", section_time: "Часовий проміжок", section_type: "Тип", section_deadline: "Deadline", section_baselines: "Baselines", section_new_resources: "Resources", column_wbs: "WBS", column_text: "Task name", column_start_date: "Start time", column_duration: "Duration", column_add: "", link: "Link", confirm_link_deleting: "will be deleted", link_start: " (start)", link_end: " (end)", type_task: "Task", type_project: "Project", type_milestone: "Milestone", minutes: "Minutes", hours: "Hours", days: "Days", weeks: "Week", months: "Months", years: "Years", message_ok: "OK", message_cancel: "Відміна", section_constraint: "Constraint", constraint_type: "Constraint type", constraint_date: "Constraint date", asap: "As Soon As Possible", alap: "As Late As Possible", snet: "Start No Earlier Than", snlt: "Start No Later Than", fnet: "Finish No Earlier Than", fnlt: "Finish No Later Than", mso: "Must Start On", mfo: "Must Finish On", resources_add_button: "Add Assignment", resources_filter_placeholder: "Search...", resources_filter_label: "hide empty", resources_section_placeholder: "Nothing assigned yet. Click 'Add Assignment' to assign resources.", empty_state_text_link: "Click here", empty_state_text_description: "to create your first task", baselines_section_placeholder: "Start adding a new baseline", baselines_add_button: "Add Baseline", baselines_remove_button: "Remove", baselines_remove_all_button: "Remove All", deadline_enable_button: "Set", deadline_disable_button: "Remove" } }; function i18nFactory() { return new LocaleManager({ en: locale$n, ar: locale$v, be: locale$u, ca: locale$t, cn: locale$s, cs: locale$r, da: locale$q, de: locale$p, el: locale$o, es: locale$m, fa: locale$l, fi: locale$k, fr: locale$j, he: locale$i, hr: locale$h, hu: locale$g, id: locale$f, it: locale$e, jp: locale$d, kr: locale$c, nb: locale$b, nl: locale$a, no: locale$9, pl: locale$8, pt: locale$7, ro: locale$6, ru: locale$5, si: locale$4, sk: locale$3, sv: locale$2, tr: locale$1, ua: locale }); } function DHXGantt() { this.constants = constants; this.version = "9.1.1"; this.license = "gpl"; this.templates = {}; this.ext = {}; this.keys = { edit_save: this.constants.KEY_CODES.ENTER, edit_cancel: this.constants.KEY_CODES.ESC }; } function factory(supportedExtensions) { var gantt2 = new DHXGantt(); var extensionManager = new ExtensionsManager(supportedExtensions); var activePlugins = {}; gantt2.plugins = function(config2) { for (var i in config2) { if (config2[i] && !activePlugins[i]) { var plugin = extensionManager.getExtension(i); if (plugin) { plugin(gantt2); activePlugins[i] = true; } } } return activePlugins; }; gantt2.$services = services(); gantt2.config = config(); gantt2.ajax = ajax(gantt2); gantt2.date = date(gantt2); gantt2.RemoteEvents = remoteEvents$1; var dnd = DnD(gantt2); gantt2.$services.setService("dnd", function() { return dnd; }); var templatesLoader = templates(gantt2); gantt2.$services.setService("templateLoader", function() { return templatesLoader; }); makeEventable(gantt2); var stateService = new StateService(); stateService.registerProvider("global", function() { var res = { min_date: gantt2._min_date, max_date: gantt2._max_date, selected_task: null }; if (gantt2.$data && gantt2.$data.tasksStore) { res.selected_task = gantt2.$data.tasksStore.getSelectedId(); } return res; }); gantt2.getState = stateService.getState; gantt2.$services.setService("state", function() { return stateService; }); mixin(gantt2, utils); gantt2.Promise = Promise$1; gantt2.env = env; initDataStores(gantt2); gantt2.dataProcessor = DataProcessor.DEPRECATED_api; gantt2.createDataProcessor = DataProcessor.createDataProcessor; plugins$1(gantt2); grid_column_api(gantt2); tasks(gantt2); parsing(gantt2); work_time(gantt2); data(gantt2); data_task_types(gantt2); cached_functions(gantt2); gantt_core(gantt2); extend(gantt2); var i18n = i18nFactory(); gantt2.i18n = { addLocale: i18n.addLocale, setLocale: function(locale2) { if (typeof locale2 === "string") { var localeObject = i18n.getLocale(locale2); if (!localeObject) { localeObject = i18n.getLocale("en"); } gantt2.locale = localeObject; } else if (locale2) { if (!gantt2.locale) { gantt2.locale = locale2; } else { for (var i in locale2) { if (locale2[i] && typeof locale2[i] === "object") { if (!gantt2.locale[i]) { gantt2.locale[i] = {}; } gantt2.mixin(gantt2.locale[i], locale2[i], true); } else { gantt2.locale[i] = locale2[i]; } } } } const labels = gantt2.locale.labels; labels.gantt_save_btn = labels.gantt_save_btn || labels.icon_save; labels.gantt_cancel_btn = labels.gantt_cancel_btn || labels.icon_cancel; labels.gantt_delete_btn = labels.gantt_delete_btn || labels.icon_delete; }, getLocale: i18n.getLocale }; gantt2.i18n.setLocale("en"); return gantt2; } function messages(gantt2) { var boxAttribute = "data-dhxbox"; var _dhx_msg_cfg = null; function callback(config2, result) { var usercall = config2.callback; modalBox.hide(config2.box); _dhx_msg_cfg = config2.box = null; if (usercall) usercall(result); } function modal_key(event2) { if (_dhx_msg_cfg) { var code = event2.which || event2.keyCode; var preventDefault = false; if (messageBox.keyboard) { if (code == 13 || code == 32) { var target = event2.target || event2.srcElement; if (getClassName(target).indexOf("gantt_popup_button") > -1 && target.click) { target.click(); } else { callback(_dhx_msg_cfg, true); preventDefault = true; } } if (code == 27) { callback(_dhx_msg_cfg, false); preventDefault = true; } } if (preventDefault) { if (event2.preventDefault) { event2.preventDefault(); } return !(event2.cancelBubble = true); } return; } } var eventElement = getRootNode(gantt2.$root) || document; gantt2.event(eventElement, "keydown", modal_key, true); function modality(mode) { if (!modality.cover) { modality.cover = document.createElement("div"); modality.cover.onkeydown = modal_key; modality.cover.className = "dhx_modal_cover"; document.body.appendChild(modality.cover); } modality.cover.style.display = mode ? "inline-block" : "none"; } function button(text, className, result) { var buttonAriaAttrs = gantt2._waiAria.messageButtonAttrString(text); var name = className.toLowerCase().replace(/ /g, "_"); var button_css = "gantt_" + name + "_button"; return "
" + text + "
"; } function info(text) { if (!messageBox.area) { messageBox.area = document.createElement("div"); messageBox.area.className = "gantt_message_area"; messageBox.area.style[messageBox.position] = "5px"; } if (!isChildOf(messageBox.area, document.body)) { document.body.appendChild(messageBox.area); } messageBox.hide(text.id); var message = document.createElement("div"); message.innerHTML = "
" + text.text + "
"; message.className = "gantt-info gantt-" + text.type; message.onclick = function() { messageBox.hide(text.id); text = null; }; gantt2._waiAria.messageInfoAttr(message); if (messageBox.position == "bottom" && messageBox.area.firstChild) messageBox.area.insertBefore(message, messageBox.area.firstChild); else messageBox.area.appendChild(message); if (text.expire > 0) messageBox.timers[text.id] = window.setTimeout(function() { if (messageBox) messageBox.hide(text.id); }, text.expire); messageBox.pull[text.id] = message; message = null; return text.id; } function getFirstDefined() { var values = [].slice.apply(arguments, [0]); for (var i = 0; i < values.length; i++) { if (values[i]) { return values[i]; } } } function _boxStructure(config2, ok, cancel) { var box = document.createElement("div"); var contentId = uid(); gantt2._waiAria.messageModalAttr(box, contentId); box.className = " gantt_modal_box gantt-" + config2.type; box.setAttribute(boxAttribute, 1); var inner = ""; if (config2.width) box.style.width = config2.width; if (config2.height) box.style.height = config2.height; if (config2.title) inner += '
' + config2.title + "
"; inner += '
' + (config2.content ? "" : config2.text) + '
'; if (ok) inner += button(getFirstDefined(config2.ok, gantt2.locale.labels.message_ok, "OK"), "ok", true); if (cancel) inner += button(getFirstDefined(config2.cancel, gantt2.locale.labels.message_cancel, "Cancel"), "cancel", false); if (config2.buttons) { for (var i = 0; i < config2.buttons.length; i++) { var btn = config2.buttons[i]; if (typeof btn == "object") { var label = btn.label; var css = btn.css || "gantt_" + btn.label.toLowerCase() + "_button"; var value = btn.value || i; inner += button(label, css, value); } else { inner += button(btn, btn, i); } } } inner += "
"; box.innerHTML = inner; if (config2.content) { var node = config2.content; if (typeof node == "string") node = document.getElementById(node); if (node.style.display == "none") node.style.display = ""; box.childNodes[config2.title ? 1 : 0].appendChild(node); } box.onclick = function(event2) { var source = event2.target || event2.srcElement; if (!source.className) source = source.parentNode; if (closest(source, ".gantt_popup_button")) { var result = source.getAttribute("data-result"); result = result == "true" || (result == "false" ? false : result); callback(config2, result); } }; config2.box = box; if (ok || cancel) _dhx_msg_cfg = config2; return box; } function _createBox(config2, ok, cancel) { var box = config2.tagName ? config2 : _boxStructure(config2, ok, cancel); if (!config2.hidden) modality(true); document.body.appendChild(box); var x = Math.abs(Math.floor(((window.innerWidth || document.documentElement.offsetWidth) - box.offsetWidth) / 2)); var y = Math.abs(Math.floor(((window.innerHeight || document.documentElement.offsetHeight) - box.offsetHeight) / 2)); if (config2.position == "top") box.style.top = "-3px"; else box.style.top = y + "px"; box.style.left = x + "px"; box.onkeydown = modal_key; modalBox.focus(box); if (config2.hidden) modalBox.hide(box); gantt2.callEvent("onMessagePopup", [box]); return box; } function alertPopup(config2) { return _createBox(config2, true, false); } function confirmPopup(config2) { return _createBox(config2, true, true); } function boxPopup(config2) { return _createBox(config2); } function box_params(text, type, callback2) { if (typeof text != "object") { if (typeof type == "function") { callback2 = type; type = ""; } text = { text, type, callback: callback2 }; } return text; } function params(text, type, expire, id) { if (typeof text != "object") text = { text, type, expire, id }; text.id = text.id || uid(); text.expire = text.expire || messageBox.expire; return text; } var alertBox = function() { var text = box_params.apply(this, arguments); text.type = text.type || "confirm"; return alertPopup(text); }; var confirmBox = function() { var text = box_params.apply(this, arguments); text.type = text.type || "alert"; return confirmPopup(text); }; var modalBox = function() { var text = box_params.apply(this, arguments); text.type = text.type || "alert"; return boxPopup(text); }; modalBox.hide = function(node) { while (node && node.getAttribute && !node.getAttribute(boxAttribute)) node = node.parentNode; if (node) { node.parentNode.removeChild(node); modality(false); gantt2.callEvent("onAfterMessagePopup", [node]); } }; modalBox.focus = function(node) { setTimeout(function() { var focusable = getFocusableNodes(node); if (focusable.length) { if (focusable[0].focus) focusable[0].focus(); } }, 1); }; var messageBox = function(text, type, expire, id) { text = params.apply(this, arguments); text.type = text.type || "info"; var subtype = text.type.split("-")[0]; switch (subtype) { case "alert": return alertPopup(text); case "confirm": return confirmPopup(text); case "modalbox": return boxPopup(text); default: return info(text); } }; messageBox.seed = (/* @__PURE__ */ new Date()).valueOf(); messageBox.uid = uid; messageBox.expire = 4e3; messageBox.keyboard = true; messageBox.position = "top"; messageBox.pull = {}; messageBox.timers = {}; messageBox.hideAll = function() { for (var key in messageBox.pull) messageBox.hide(key); }; messageBox.hide = function(id) { var obj = messageBox.pull[id]; if (obj && obj.parentNode) { window.setTimeout(function() { obj.parentNode.removeChild(obj); obj = null; }, 2e3); obj.className += " hidden"; if (messageBox.timers[id]) window.clearTimeout(messageBox.timers[id]); delete messageBox.pull[id]; } }; var popups = []; gantt2.attachEvent("onMessagePopup", function(box) { popups.push(box); }); gantt2.attachEvent("onAfterMessagePopup", function(box) { for (var i = 0; i < popups.length; i++) { if (popups[i] === box) { popups.splice(i, 1); i--; } } }); gantt2.attachEvent("onDestroy", function() { if (modality.cover && modality.cover.parentNode) { modality.cover.parentNode.removeChild(modality.cover); } for (var i = 0; i < popups.length; i++) { if (popups[i].parentNode) { popups[i].parentNode.removeChild(popups[i]); } } popups = null; if (messageBox.area && messageBox.area.parentNode) { messageBox.area.parentNode.removeChild(messageBox.area); } messageBox = null; }); return { alert: alertBox, confirm: confirmBox, message: messageBox, modalbox: modalBox }; } function extendSettings(store, parentSettings) { var own = this.$config[store]; if (own) { if (!own.$extendedConfig) { own.$extendedConfig = true; Object.setPrototypeOf(own, parentSettings); } return own; } else { return parentSettings; } } var configurable = function(parentView) { var parentConfig, parentTemplates; return { $getConfig: function() { if (!parentConfig) { parentConfig = parentView ? parentView.$getConfig() : this.$gantt.config; } if (!this.$config.config) { return parentConfig; } else { return extendSettings.call(this, "config", parentConfig); } }, $getTemplates: function() { if (!parentTemplates) { parentTemplates = parentView ? parentView.$getTemplates() : this.$gantt.templates; } if (!this.$config.templates) { return parentTemplates; } else { return extendSettings.call(this, "templates", parentTemplates); } } }; }; function configurable$1(obj, parent) { mixin(obj, configurable(parent)); } var uiFactory = function createFactory(gantt2) { var views = {}; function ui2(cell, parentView) { var content; var view = "cell"; if (cell.view) { view = "viewcell"; } else if (cell.resizer) { view = "resizer"; } else if (cell.rows || cell.cols) { view = "layout"; } else if (cell.views) { view = "multiview"; } content = createView.call(this, view, null, cell, parentView); return content; } var createdViews = {}; function createView(name, parent, config2, parentView) { var creator = views[name]; if (!creator || !creator.create) return false; if (name == "resizer" && !config2.mode) { if (parentView.$config.cols) { config2.mode = "x"; } else { config2.mode = "y"; } } if (name == "viewcell" && config2.view == "scrollbar" && !config2.scroll) { if (parentView.$config.cols) { config2.scroll = "y"; } else { config2.scroll = "x"; } } var config2 = copy(config2); if (!config2.id && !createdViews[config2.view]) { config2.id = config2.view; } if (config2.id && !config2.css) { config2.css = config2.id + "_cell"; } var view = new creator.create(parent, config2, this, gantt2); if (creator.configure) { creator.configure(view); } configurable$1(view, parentView); if (!view.$id) { view.$id = config2.id || gantt2.uid(); } if (!view.$parent && typeof parent == "object") { view.$parent = parent; } if (!view.$config) { view.$config = config2; } if (createdViews[view.$id]) { view.$id = gantt2.uid(); } createdViews[view.$id] = view; return view; } function reset() { createdViews = {}; } function register(name, viewConstructor, configure) { views[name] = { create: viewConstructor, configure }; } function getView(id) { return createdViews[id]; } var factory2 = { initUI: ui2, reset, registerView: register, createView, getView }; return factory2; }; const uiFactory$1 = { createFactory: uiFactory }; var createMouseHandler = /* @__PURE__ */ function(domHelpers2) { return function(gantt2) { var eventHandlers = { click: {}, doubleclick: {}, contextMenu: {} }; function addEventTarget(event2, className, handler, root) { if (!eventHandlers[event2][className]) { eventHandlers[event2][className] = []; } eventHandlers[event2][className].push({ handler, root }); } function callHandler(eventName, className, root, args) { var handlers = eventHandlers[eventName][className]; if (handlers) { for (var i = 0; i < handlers.length; i++) { if (!(root || handlers[i].root) || handlers[i].root === root) { handlers[i].handler.apply(this, args); } } } } function onClick(e) { e = e || window.event; var id = gantt2.locate(e); var handlers = findEventHandlers(e, eventHandlers.click); var res = true; if (id !== null) { res = !gantt2.checkEvent("onTaskClick") || gantt2.callEvent("onTaskClick", [id, e]); } else { gantt2.callEvent("onEmptyClick", [e]); } if (res) { var default_action = callEventHandlers(handlers, e, id); if (!default_action) return; switch (e.target.nodeName) { case "SELECT": case "INPUT": return; } if (id && gantt2.getTask(id) && !gantt2._multiselect && gantt2.config.select_task) { gantt2.selectTask(id); } } } function onContextMenu(e) { e = e || window.event; var src = e.target || e.srcElement, taskId = gantt2.locate(src), linkId = gantt2.locate(src, gantt2.config.link_attribute); var res = !gantt2.checkEvent("onContextMenu") || gantt2.callEvent("onContextMenu", [taskId, linkId, e]); if (!res) { if (e.preventDefault) e.preventDefault(); else e.returnValue = false; } return res; } function findEventHandlers(e, hash) { var trg = e.target || e.srcElement; var handlers = []; while (trg) { var css = domHelpers2.getClassName(trg); if (css) { css = css.split(" "); for (var i = 0; i < css.length; i++) { if (!css[i]) continue; if (hash[css[i]]) { var delegateHandlers = hash[css[i]]; for (var h = 0; h < delegateHandlers.length; h++) { if (delegateHandlers[h].root) { if (!domHelpers2.isChildOf(trg, delegateHandlers[h].root)) { continue; } } handlers.push(delegateHandlers[h].handler); } } } } trg = trg.parentNode; } return handlers; } function callEventHandlers(handlers, e, id) { var res = true; for (var i = 0; i < handlers.length; i++) { var handlerResult = handlers[i].call(gantt2, e, id, e.target || e.srcElement); res = res && !(typeof handlerResult != "undefined" && handlerResult !== true); } return res; } function onDoubleClick(e) { e = e || window.event; var id = gantt2.locate(e); var handlers = findEventHandlers(e, eventHandlers.doubleclick); var res = !gantt2.checkEvent("onTaskDblClick") || id === null || gantt2.callEvent("onTaskDblClick", [id, e]); if (res) { var default_action = callEventHandlers(handlers, e, id); if (!default_action) return; if (id !== null && gantt2.getTask(id)) { if (res && gantt2.config.details_on_dblclick && !gantt2.isReadonly(id)) { gantt2.showLightbox(id); } } } } function onMouseMove(e) { if (gantt2.checkEvent("onMouseMove")) { var id = gantt2.locate(e); gantt2._last_move_event = e; gantt2.callEvent("onMouseMove", [id, e]); } } function detach(eventName, className, handler, root) { if (eventHandlers[eventName] && eventHandlers[eventName][className]) { var handlers = eventHandlers[eventName]; var elementHandlers = handlers[className]; for (var i = 0; i < elementHandlers.length; i++) { if (elementHandlers[i].root == root) { elementHandlers.splice(i, 1); i--; } } if (!elementHandlers.length) { delete handlers[className]; } } } var domEvents = gantt2._createDomEventScope(); function reset(node) { domEvents.detachAll(); if (node) { domEvents.attach(node, "click", onClick); domEvents.attach(node, "dblclick", onDoubleClick); domEvents.attach(node, "mousemove", onMouseMove); domEvents.attach(node, "contextmenu", onContextMenu); } } return { reset, global: function(event2, classname, handler) { addEventTarget(event2, classname, handler, null); }, delegate: addEventTarget, detach, callHandler, onDoubleClick, onMouseMove, onContextMenu, onClick, destructor: function() { reset(); eventHandlers = null; domEvents = null; } }; }; }(domHelpers); const mouseEvents = { init: createMouseHandler }; function genericViewPortChecker(viewport, box, gantt2) { if (!box) { return false; } if (box.left > viewport.x_end || box.left + box.width < viewport.x) { return false; } if (box.top > viewport.y_end || box.top + box.height < viewport.y) { return false; } return true; } function isLegacyRender(gantt2) { return gantt2.config.smart_rendering && gantt2._smart_render; } function getRowRectangle(item, view, config2) { return { top: view.getItemTop(item.id), height: view.getItemHeight(item.id), left: 0, right: Infinity }; } function getVisibleTasksRange(gantt2, view, config2, datastore, viewport) { var buffer = 1; var start = view.getItemIndexByTopPosition(viewport.y) || 0; var end = view.getItemIndexByTopPosition(viewport.y_end) || datastore.count(); var indexStart = Math.max(0, start - buffer); var indexEnd = Math.min(datastore.count(), end + buffer); const extraTasksIds = []; if (gantt2.config.keyboard_navigation && gantt2.getSelectedId()) { let task = gantt2.getTask(gantt2.getSelectedId()); if (task.$expanded_branch && !task.$split_subtask) { extraTasksIds.push(gantt2.getSelectedId()); } } if (gantt2.$ui.getView("grid") && gantt2.ext.inlineEditors && gantt2.ext.inlineEditors.getState().id) { let inlineEditorId = gantt2.ext.inlineEditors.getState().id; if (datastore.exists(inlineEditorId)) { extraTasksIds.push(inlineEditorId); } } return { start: indexStart, end: indexEnd, ids: extraTasksIds }; } var rendererFactory = function(gantt2) { var task_area_pulls = {}, task_area_renderers = {}; function getView(layer) { var view = null; if (typeof layer.view === "string") { view = gantt2.$ui.getView(layer.view); } else if (layer.view) { view = layer.view; } return view; } function getRenderer(id, layer, node) { if (task_area_renderers[id]) return task_area_renderers[id]; if (!layer.renderer) gantt2.assert(false, "Invalid renderer call"); var renderMethod = null; var updateMethod = null; var getRectangle2 = null; var renderCallbackMethod = null; var specializedViewPortChecker = null; if (typeof layer.renderer === "function") { renderMethod = layer.renderer; getRectangle2 = getRowRectangle; } else { renderMethod = layer.renderer.render; updateMethod = layer.renderer.update; renderCallbackMethod = layer.renderer.onrender; if (layer.renderer.isInViewPort) { specializedViewPortChecker = layer.renderer.isInViewPort; } else { getRectangle2 = layer.renderer.getRectangle; } if (!getRectangle2 && getRectangle2 !== null) { getRectangle2 = getRowRectangle; } } var filter = layer.filter; if (node) node.setAttribute(gantt2.config.layer_attribute, true); task_area_renderers[id] = { render_item: function(item, container, viewPort, layerView, viewConfig) { container = container || node; if (filter) { if (!filter(item)) { this.remove_item(item.id); return; } } var view = layerView || getView(layer); var config2 = viewConfig || (view ? view.$getConfig() : null); var rendererViewPort = viewPort; if (!rendererViewPort && config2 && config2.smart_rendering) { rendererViewPort = view.getViewPort(); } var dom = null; if (!isLegacyRender(gantt2) && (getRectangle2 || specializedViewPortChecker) && rendererViewPort) { var isVisible2 = false; if (specializedViewPortChecker) { isVisible2 = specializedViewPortChecker(item, rendererViewPort, view, config2, gantt2); } else { isVisible2 = genericViewPortChecker(rendererViewPort, getRectangle2(item, view, config2, gantt2)); } if (isVisible2) { dom = renderMethod.call(gantt2, item, view, config2, rendererViewPort); } } else { dom = renderMethod.call(gantt2, item, view, config2, rendererViewPort); } this.append(item, dom, container); var useBuffer = container.nodeType == 11; if (renderCallbackMethod && !useBuffer && dom) { renderCallbackMethod.call(gantt2, item, dom, view); } }, clear: function(container) { this.rendered = task_area_pulls[id] = {}; if (!layer.append) this.clear_container(container); }, clear_container: function(container) { container = container || node; if (container) { container.innerHTML = ""; } }, get_visible_range: function(datastore) { var view = getView(layer); var viewport; var viewConfig = view ? view.$getConfig() : null; if (viewConfig && viewConfig.smart_rendering) { viewport = view.getViewPort(); } var range; if (view && viewport) { if (typeof layer.renderer === "function") { range = getVisibleTasksRange(gantt2, view, viewConfig, datastore, viewport); } else if (layer.renderer && layer.renderer.getVisibleRange) { range = layer.renderer.getVisibleRange(gantt2, view, viewConfig, datastore, viewport); } } if (!range) { range = { start: 0, end: datastore.count() }; } return range; }, prepare_data: function(items) { if (layer.renderer && layer.renderer.prepareData) { return layer.renderer.prepareData(items, gantt2, layer); } }, render_items: function(items, container) { container = container || node; var buffer = document.createDocumentFragment(); this.clear(container); var viewPort = null; var view = getView(layer); var viewConfig = view ? view.$getConfig() : null; if (viewConfig && viewConfig.smart_rendering) { viewPort = view.getViewPort(); } for (var i = 0, vis = items.length; i < vis; i++) { this.render_item(items[i], buffer, viewPort, view, viewConfig); } container.appendChild(buffer, container); var itemsSearch = {}; items.forEach(function(item) { itemsSearch[item.id] = item; }); var renderedItems = {}; if (renderCallbackMethod) { var newElements = {}; for (var i in this.rendered) { if (!renderedItems[i]) { newElements[i] = this.rendered[i]; renderCallbackMethod.call(gantt2, itemsSearch[i], this.rendered[i], view); } } } }, update_items: function(items, container) { var view = getView(layer); var viewConfig = view ? view.$getConfig() : null; if (!view || !view.$getConfig().smart_rendering || isLegacyRender(gantt2)) { return; } if (!this.rendered) { return; } if (!(getRectangle2 || specializedViewPortChecker)) { return; } container = container || node; var buffer = document.createDocumentFragment(); var viewPort = null; if (view) { viewPort = view.getViewPort(); } var itemsSearch = {}; items.forEach(function(item2) { itemsSearch[item2.id] = item2; }); var renderedItems = {}; var nodesToRemove = {}; for (var i in this.rendered) { nodesToRemove[i] = true; renderedItems[i] = true; } var renderCalledFor = {}; for (var i = 0, vis = items.length; i < vis; i++) { var item = items[i]; var itemNode = this.rendered[item.id]; nodesToRemove[item.id] = false; if (itemNode && itemNode.parentNode) { var isVisible2 = false; if (specializedViewPortChecker) { isVisible2 = specializedViewPortChecker(item, viewPort, view, viewConfig, gantt2); } else { isVisible2 = genericViewPortChecker(viewPort, getRectangle2(item, view, viewConfig, gantt2)); } if (!isVisible2) { nodesToRemove[item.id] = true; } else { if (updateMethod) { updateMethod.call(gantt2, item, itemNode, view, viewConfig, viewPort); } this.restore(item, buffer); } } else { renderCalledFor[items[i].id] = true; this.render_item(items[i], buffer, viewPort, view, viewConfig); } } for (var i in nodesToRemove) { if (nodesToRemove[i]) { this.hide(i); } } if (buffer.childNodes.length) { container.appendChild(buffer, container); } if (renderCallbackMethod) { var newElements = {}; for (var i in this.rendered) { if (!renderedItems[i] || renderCalledFor[i]) { newElements[i] = this.rendered[i]; renderCallbackMethod.call(gantt2, itemsSearch[i], this.rendered[i], view); } } } }, append: function(item, node2, container) { if (!this.rendered) { return; } if (!node2) { if (this.rendered[item.id]) { this.remove_item(item.id); } return; } if (this.rendered[item.id] && this.rendered[item.id].parentNode) { this.replace_item(item.id, node2); } else { container.appendChild(node2); } this.rendered[item.id] = node2; }, replace_item: function(item_id, newNode) { var item = this.rendered[item_id]; if (item && item.parentNode) { item.parentNode.replaceChild(newNode, item); } this.rendered[item_id] = newNode; }, remove_item: function(item_id) { this.hide(item_id); delete this.rendered[item_id]; }, hide: function(item_id) { var item = this.rendered[item_id]; if (item && item.parentNode) { item.parentNode.removeChild(item); } delete this.rendered[item_id]; }, restore: function(item, container) { var dom = this.rendered[item.id]; if (dom) { if (!dom.parentNode) { this.append(item, dom, container || node); } } else { this.render_item(item, container || node); } }, change_id: function(oldid, newid) { this.rendered[newid] = this.rendered[oldid]; delete this.rendered[oldid]; }, rendered: task_area_pulls[id], node, destructor: function() { this.clear(); delete task_area_renderers[id]; delete task_area_pulls[id]; } }; return task_area_renderers[id]; } function clearRenderers() { for (var i in task_area_renderers) { getRenderer(i).destructor(); } } return { getRenderer, clearRenderers }; }; var layerFactory = function(gantt2) { var renderFactory = rendererFactory(gantt2); return { createGroup: function(getContainer, relativeRoot, defaultFilters, initLayer2) { var renderGroup = { tempCollection: [], renderers: {}, container: getContainer, filters: [], getLayers: function() { this._add(); var res = []; for (var i in this.renderers) { res.push(this.renderers[i]); } return res; }, getLayer: function(id) { return this.renderers[id]; }, _add: function(layer) { if (layer) { layer.id = layer.id || uid(); this.tempCollection.push(layer); } const container = this.container(); const pending = this.tempCollection; for (let i = 0; i < pending.length; i++) { layer = pending[i]; if (!this.container() && !(layer && layer.container && layer.container.isConnected)) continue; let node = layer.container, id = layer.id, topmost = layer.topmost; if (!node.parentNode) { if (topmost) { container.appendChild(node); } else { let rel = relativeRoot ? relativeRoot() : container.firstChild; if (rel && rel.parentNode == container) container.insertBefore(node, rel); else container.appendChild(node); } } this.renderers[id] = renderFactory.getRenderer(id, layer, node); if (initLayer2) { initLayer2(layer, gantt2); } this.tempCollection.splice(i, 1); i--; } }, addLayer: function(config2) { if (config2) { if (typeof config2 == "function") { config2 = { renderer: config2 }; } if (config2.filter === void 0) { config2.filter = mergeFilters(defaultFilters || []); } else if (config2.filter instanceof Array) { config2.filter.push(defaultFilters); config2.filter = mergeFilters(config2.filter); } if (!config2.container) { config2.container = document.createElement("div"); } var self2 = this; config2.requestUpdate = function() { if (gantt2.config.smart_rendering && !isLegacyRender(gantt2)) { if (self2.renderers[config2.id]) { self2.onUpdateRequest(self2.renderers[config2.id]); } } }; } this._add(config2); return config2 ? config2.id : void 0; }, onUpdateRequest: function(layer) { }, eachLayer: function(code) { for (var i in this.renderers) { code(this.renderers[i]); } }, removeLayer: function(id) { if (!this.renderers[id]) return; this.renderers[id].destructor(); delete this.renderers[id]; }, clear: function() { for (var i in this.renderers) { this.renderers[i].destructor(); } this.renderers = {}; } }; gantt2.attachEvent("onDestroy", function() { renderGroup.clear(); renderGroup = null; }); return renderGroup; } }; }; function mergeFilters(filter_methods) { if (!(filter_methods instanceof Array)) { filter_methods = Array.prototype.slice.call(arguments, 0); } return function(obj) { var res = true; for (var i = 0, len = filter_methods.length; i < len; i++) { var filter_method = filter_methods[i]; if (filter_method) { res = res && filter_method(obj.id, obj) !== false; } } return res; }; } function barRectangle(item, view, config2) { if (!item.start_date || !item.end_date) { return null; } var padding = 200; var startCoord = view.posFromDate(item.start_date, view._getPositioningContext ? view._getPositioningContext(item) : null); var endCoord = view.posFromDate(item.end_date, view._getPositioningContext ? view._getPositioningContext(item) : null); var left = Math.min(startCoord, endCoord) - padding; var right = Math.max(startCoord, endCoord) + padding; return { top: view.getItemTop(item.id), height: view.getItemHeight(item.id), left, width: right - left }; } function getLinkBox(item, view, config2, gantt2) { if (!gantt2.isTaskExists(item.source)) { return null; } if (!gantt2.isTaskExists(item.target)) { return null; } var sourceBox = barRectangle(gantt2.getTask(item.source), view); var targetBox = barRectangle(gantt2.getTask(item.target), view); if (!sourceBox || !targetBox) { return null; } var padding = 100; var left = Math.min(sourceBox.left, targetBox.left) - padding; var right = Math.max(sourceBox.left + sourceBox.width, targetBox.left + targetBox.width) + padding; var top = Math.min(sourceBox.top, targetBox.top) - padding; var bottom = Math.max(sourceBox.top + sourceBox.height, targetBox.top + targetBox.height) + padding; return { top, height: bottom - top, bottom, left, width: right - left, right }; } function getVisibleRange() { var coordinates = []; var calculated = false; function clearCache() { coordinates = []; calculated = false; } function buildCache(datastore, view, gantt2) { var config2 = view.$getConfig(); var visibleItems = datastore.getVisibleItems(); visibleItems.forEach(function(link) { var rec = getLinkBox(link, view, config2, gantt2); if (!rec) { return; } coordinates.push({ id: link.id, rec }); }); coordinates.sort(function(a, b) { if (a.rec.right < b.rec.right) { return -1; } else { return 1; } }); calculated = true; } var initialized = false; function init(datastore) { if (initialized) { return; } initialized = true; datastore.attachEvent("onPreFilter", clearCache); datastore.attachEvent("onStoreUpdated", clearCache); datastore.attachEvent("onClearAll", clearCache); datastore.attachEvent("onBeforeStoreUpdate", clearCache); } return function getVisibleLinksRange(gantt2, view, config2, datastore, viewport) { init(datastore); if (!calculated) { buildCache(datastore, view, gantt2); } var visibleBoxes = []; for (var i = 0; i < coordinates.length; i++) { var item = coordinates[i]; var box = item.rec; if (box.right < viewport.x) { continue; } if (box.left < viewport.x_end && box.right > viewport.x && box.top < viewport.y_end && box.bottom > viewport.y) { visibleBoxes.push(item.id); } } return { ids: visibleBoxes }; }; } function isLinkInViewPort(item, viewport, view, config2, gantt2) { var source = view.$gantt.getTask(item.source); var target = view.$gantt.getTask(item.target); var sourceTop = view.getItemTop(source.id); var sourceHeight = view.getItemHeight(source.id); var targetTop = view.getItemTop(target.id); var targetHeight = view.getItemHeight(target.id); if (viewport.y > sourceTop + sourceHeight && viewport.y > targetTop + targetHeight) { return false; } if (viewport.y_end < targetTop && viewport.y_end < sourceTop) { return false; } var padding = 100; var sourceLeft = view.posFromDate(source.start_date, view._getPositioningContext ? view._getPositioningContext(item) : null); var sourceRight = view.posFromDate(source.end_date, view._getPositioningContext ? view._getPositioningContext(item) : null); var targetLeft = view.posFromDate(target.start_date, view._getPositioningContext ? view._getPositioningContext(item) : null); var targetRight = view.posFromDate(target.end_date, view._getPositioningContext ? view._getPositioningContext(item) : null); if (sourceLeft > sourceRight) { var tmp = sourceRight; sourceRight = sourceLeft; sourceLeft = tmp; } if (targetLeft > targetRight) { var tmp = targetRight; targetRight = targetLeft; targetLeft = tmp; } sourceLeft += -100; sourceRight += padding; targetLeft += -100; targetRight += padding; if (viewport.x > sourceRight && viewport.x > targetRight) { return false; } if (viewport.x_end < sourceLeft && viewport.x_end < targetLeft) { return false; } return true; } function initLayer(layer, gantt2) { if (!layer.view) { return; } var view = layer.view; if (typeof view === "string") { view = gantt2.$ui.getView(view); } if (view && view.attachEvent) { view.attachEvent("onScroll", function() { var state = gantt2.$services.getService("state"); if (!state.getState("batchUpdate").batch_update && !view.$config.$skipSmartRenderOnScroll) { if (layer.requestUpdate) { layer.requestUpdate(); } } }); } } var createLayerEngine = function(gantt2) { var factory2 = layerFactory(gantt2); return { getDataRender: function(name) { return gantt2.$services.getService("layer:" + name) || null; }, createDataRender: function(config2) { var name = config2.name, defaultContainer = config2.defaultContainer, previusSiblingContainer = config2.defaultContainerSibling; var layers = factory2.createGroup(defaultContainer, previusSiblingContainer, function(itemId, item) { if (layers.filters) { for (var i = 0; i < layers.filters.length; i++) { if (layers.filters[i](itemId, item) === false) { return false; } } } else { return true; } }, initLayer); gantt2.$services.setService("layer:" + name, function() { return layers; }); gantt2.attachEvent("onGanttReady", function() { layers.addLayer(); }); return layers; }, init: function() { var taskLayers2 = this.createDataRender({ name: "task", defaultContainer: function() { if (gantt2.$task_data) { return gantt2.$task_data; } else if (gantt2.$ui.getView("timeline")) { return gantt2.$ui.getView("timeline").$task_data; } }, defaultContainerSibling: function() { if (gantt2.$task_links) { return gantt2.$task_links; } else if (gantt2.$ui.getView("timeline")) { return gantt2.$ui.getView("timeline").$task_links; } }, filter: function(item) { } }, gantt2); var linkLayers = this.createDataRender({ name: "link", defaultContainer: function() { if (gantt2.$task_data) { return gantt2.$task_data; } else if (gantt2.$ui.getView("timeline")) { return gantt2.$ui.getView("timeline").$task_data; } } }, gantt2); return { addTaskLayer: function(config2) { const rangeFunction = getVisibleTasksRange; if (typeof config2 === "function") { config2 = { renderer: { render: config2, getVisibleRange: rangeFunction } }; } else { if (config2.renderer && !config2.renderer.getVisibleRange) { config2.renderer.getVisibleRange = rangeFunction; } } config2.view = "timeline"; return taskLayers2.addLayer(config2); }, _getTaskLayers: function() { return taskLayers2.getLayers(); }, removeTaskLayer: function(id) { taskLayers2.removeLayer(id); }, _clearTaskLayers: function() { taskLayers2.clear(); }, addLinkLayer: function(config2) { const rangeFunction = getVisibleRange(); if (typeof config2 === "function") { config2 = { renderer: { render: config2, getVisibleRange: rangeFunction } }; } else { if (config2.renderer && !config2.renderer.getVisibleRange) { config2.renderer.getVisibleRange = rangeFunction; } } config2.view = "timeline"; if (config2 && config2.renderer) { if (!config2.renderer.getRectangle && !config2.renderer.isInViewPort) { config2.renderer.isInViewPort = isLinkInViewPort; } } return linkLayers.addLayer(config2); }, _getLinkLayers: function() { return linkLayers.getLayers(); }, removeLinkLayer: function(id) { linkLayers.removeLayer(id); }, _clearLinkLayers: function() { linkLayers.clear(); } }; } }; }; var Cell = function() { function Cell2(parent, config2, factory2, gantt2) { if (parent) { this.$container = toNode(parent); this.$parent = parent; } this.$config = mixin(config2, { headerHeight: 33 }); this.$gantt = gantt2; this.$domEvents = gantt2._createDomEventScope(); this.$id = config2.id || "c" + uid(); this.$name = "cell"; this.$factory = factory2; this.$externalComponent = null; makeEventable(this); } Cell2.prototype.destructor = function() { this.$parent = this.$container = this.$view = null; var mouse = this.$gantt.$services.getService("mouseEvents"); mouse.detach("click", "gantt_header_arrow", this._headerClickHandler); this.$domEvents.detachAll(); this.callEvent("onDestroy", []); this.detachAllEvents(); }; Cell2.prototype.cell = function(id) { return null; }; Cell2.prototype.scrollTo = function(left, top) { var cell = this.$view; if (this.$config.html) cell = this.$view.firstChild; if (left * 1 == left) { cell.scrollLeft = left; } if (top * 1 == top) { cell.scrollTop = top; } }; Cell2.prototype.clear = function() { this.getNode().innerHTML = ""; this.getNode().className = "gantt_layout_content"; this.getNode().style.padding = "0"; }; Cell2.prototype.resize = function(final) { if (this.$parent) { return this.$parent.resize(final); } if (final === false) { this.$preResize = true; } var topCont = this.$container; var x = topCont.offsetWidth; var y = topCont.offsetHeight; var topSize = this.getSize(); if (topCont === document.body) { x = document.body.offsetWidth; y = document.body.offsetHeight; } if (x < topSize.minWidth) { x = topSize.minWidth; } if (x > topSize.maxWidth) { x = topSize.maxWidth; } if (y < topSize.minHeight) { y = topSize.minHeight; } if (y > topSize.maxHeight) { y = topSize.maxHeight; } this.setSize(x, y); if (!this.$preResize) ; this.$preResize = false; }; Cell2.prototype.hide = function() { this._hide(true); this.resize(); }; Cell2.prototype.show = function(force) { this._hide(false); if (force && this.$parent) { this.$parent.show(); } this.resize(); }; Cell2.prototype._hide = function(mode) { if (mode === true && this.$view.parentNode) { this.$view.parentNode.removeChild(this.$view); } else if (mode === false && !this.$view.parentNode) { var index = this.$parent.cellIndex(this.$id); this.$parent.moveView(this, index); } this.$config.hidden = mode; }; Cell2.prototype.$toHTML = function(content, css) { if (content === void 0) { content = ""; } css = [css || "", this.$config.css || ""].join(" "); var obj = this.$config; var header = ""; if (obj.raw) { content = typeof obj.raw === "string" ? obj.raw : ""; } else { if (!content) { let renderedElement = null; if (typeof obj.html === "function") { renderedElement = obj.html(); } else { renderedElement = obj.html; } if (this.$gantt.config.external_render && this.$gantt.config.external_render.isElement(renderedElement)) { this.$externalComponent = renderedElement; renderedElement = null; } content = "
" + (renderedElement || "") + "
"; } if (obj.header) { var collapseIcon = obj.canCollapse ? "
" : ""; header = "
" + collapseIcon + "
" + obj.header + "
"; } } return "
" + header + content + "
"; }; Cell2.prototype.$fill = function(node, parent) { this.$view = node; this.$parent = parent; this.init(); }; Cell2.prototype.getNode = function() { return this.$view.querySelector("gantt_layout_cell") || this.$view; }; Cell2.prototype.init = function() { var self2 = this; this._headerClickHandler = function(e) { var cellId = locateAttribute(e, "data-cell-id"); if (cellId == self2.$id) { self2.toggle(); } }; var mouse = this.$gantt.$services.getService("mouseEvents"); mouse.delegate("click", "gantt_header_arrow", this._headerClickHandler); this.callEvent("onReady", []); }; Cell2.prototype.toggle = function() { this.$config.collapsed = !this.$config.collapsed; this.resize(); }; Cell2.prototype.getSize = function() { var size = { height: this.$config.height || 0, width: this.$config.width || 0, gravity: this.$config.gravity || 1, minHeight: this.$config.minHeight || 0, minWidth: this.$config.minWidth || 0, maxHeight: this.$config.maxHeight || 1e11, maxWidth: this.$config.maxWidth || 1e11 }; if (this.$config.collapsed) { var mode = this.$config.mode === "x"; size[mode ? "width" : "height"] = size[mode ? "maxWidth" : "maxHeight"] = this.$config.headerHeight; } return size; }; Cell2.prototype.getContentSize = function() { var width = this.$lastSize.contentX; if (width !== width * 1) { width = this.$lastSize.width; } var height = this.$lastSize.contentY; if (height !== height * 1) { height = this.$lastSize.height; } return { width, height }; }; Cell2.prototype._getBorderSizes = function() { var borders = { top: 0, right: 0, bottom: 0, left: 0, horizontal: 0, vertical: 0 }; if (this._currentBorders) { if (this._currentBorders[this._borders.left]) { borders.left = 1; borders.horizontal++; } if (this._currentBorders[this._borders.right]) { borders.right = 1; borders.horizontal++; } if (this._currentBorders[this._borders.top]) { borders.top = 1; borders.vertical++; } if (this._currentBorders[this._borders.bottom]) { borders.bottom = 1; borders.vertical++; } } return borders; }; Cell2.prototype.setSize = function(x, y) { this.$view.style.width = x + "px"; this.$view.style.height = y + "px"; var borders = this._getBorderSizes(); var contentY = y - borders.vertical; var contentX = x - borders.horizontal; this.$lastSize = { x, y, contentX, contentY }; if (this.$config.header) { this._sizeHeader(); } else { this._sizeContent(); } }; Cell2.prototype._borders = { left: "gantt_layout_cell_border_left", right: "gantt_layout_cell_border_right", top: "gantt_layout_cell_border_top", bottom: "gantt_layout_cell_border_bottom" }; Cell2.prototype._setBorders = function(css, view) { if (!view) { view = this; } var node = view.$view; for (var i in this._borders) { removeClassName(node, this._borders[i]); } if (typeof css == "string") { css = [css]; } var cssHash = {}; for (var i = 0; i < css.length; i++) { addClassName(node, css[i]); cssHash[css[i]] = true; } view._currentBorders = cssHash; }; Cell2.prototype._sizeContent = function() { var content = this.$view.childNodes[0]; if (content && content.className == "gantt_layout_content") { content.style.height = this.$lastSize.contentY + "px"; } }; Cell2.prototype._sizeHeader = function() { var size = this.$lastSize; size.contentY -= this.$config.headerHeight; var header = this.$view.childNodes[0]; var content = this.$view.childNodes[1]; var xLayout = this.$config.mode === "x"; if (this.$config.collapsed) { content.style.display = "none"; if (xLayout) { header.className = "gantt_layout_header collapsed_x"; header.style.width = size.y + "px"; var d = Math.floor(size.y / 2 - size.x / 2); header.style.transform = "rotate(90deg) translate(" + d + "px, " + d + "px)"; content.style.display = "none"; } else { header.className = "gantt_layout_header collapsed_y"; } } else { if (xLayout) { header.className = "gantt_layout_header"; } else { header.className = "gantt_layout_header vertical"; } header.style.width = "auto"; header.style.transform = ""; content.style.display = ""; content.style.height = size.contentY + "px"; } header.style.height = this.$config.headerHeight + "px"; }; return Cell2; }(); function __extends(d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var Layout = function(_super) { __extends(Layout2, _super); function Layout2(parent, config2, factory2) { var _this = _super.apply(this, arguments) || this; if (parent) _this.$root = true; _this._parseConfig(config2); _this.$name = "layout"; return _this; } Layout2.prototype.destructor = function() { if (this.$container && this.$view) { removeNode(this.$view); } for (var i = 0; i < this.$cells.length; i++) { var child = this.$cells[i]; child.destructor(); } this.$cells = []; _super.prototype.destructor.call(this); }; Layout2.prototype._resizeScrollbars = function(autosize, scrollbars) { var scrollChanged = false; var visibleScrollbars = [], hiddenScrollbars = []; const scrollbarsToHide = []; function showScrollbar(scrollbar2) { scrollbar2.$parent.show(); scrollChanged = true; visibleScrollbars.push(scrollbar2); } function hideScrollbar(scrollbar2) { scrollbar2.$parent.hide(); scrollChanged = true; hiddenScrollbars.push(scrollbar2); } var scrollbar; for (var i = 0; i < scrollbars.length; i++) { scrollbar = scrollbars[i]; if (autosize[scrollbar.$config.scroll]) { hideScrollbar(scrollbar); } else if (scrollbar.shouldHide()) { scrollbarsToHide.push(scrollbar); } else if (scrollbar.shouldShow()) { showScrollbar(scrollbar); } else { if (scrollbar.isVisible()) { visibleScrollbars.push(scrollbar); } else { hiddenScrollbars.push(scrollbar); } } } var visibleGroups = {}; for (var i = 0; i < visibleScrollbars.length; i++) { if (visibleScrollbars[i].$config.group) { visibleGroups[visibleScrollbars[i].$config.group] = true; } } scrollbarsToHide.forEach(function(scrollbar2) { if (!(scrollbar2.$config.group && visibleGroups[scrollbar2.$config.group])) { hideScrollbar(scrollbar2); } }); for (var i = 0; i < hiddenScrollbars.length; i++) { scrollbar = hiddenScrollbars[i]; if (scrollbar.$config.group && visibleGroups[scrollbar.$config.group]) { showScrollbar(scrollbar); for (var j = 0; j < visibleScrollbars.length; j++) { if (visibleScrollbars[j] == scrollbar) { this.$gantt.$scrollbarRepaint = true; break; } } } } return scrollChanged; }; Layout2.prototype.getScrollbarsInfo = function() { const scrollbars = this.getCellsByType("scroller"); const scrollbarsInfo = []; scrollbars.forEach((scrollbar) => { let obj = {}; const { visible, direction, size, scrollSize, position } = scrollbar.getScrollState(); let linkedViews = scrollbar._getLinkedViews(); let boundViews = linkedViews.map((view) => view.$config.id); obj.id = scrollbar.$id; obj.visible = visible; obj.boundViews = boundViews; if (direction === "x") { obj.x = size; obj.x_inner = scrollSize; obj.x_pos = position || 0; } else { obj.y = size; obj.y_inner = scrollSize; obj.y_pos = position || 0; } scrollbarsInfo.push(obj); }); return scrollbarsInfo; }; Layout2.prototype._syncCellSizes = function(groupName, newSize) { if (!groupName) return; var groups = {}; this._eachChild(function(cell) { if (cell.$config.group && cell.$name != "scrollbar" && cell.$name != "resizer") { if (!groups[cell.$config.group]) { groups[cell.$config.group] = []; } groups[cell.$config.group].push(cell); } }); if (groups[groupName]) { this._syncGroupSize(groups[groupName], newSize); } return groups[groupName]; }; Layout2.prototype._syncGroupSize = function(cells, newSize) { if (!cells.length) return; var property = cells[0].$parent._xLayout ? "width" : "height"; var direction = cells[0].$parent.getNextSibling(cells[0].$id) ? 1 : -1; var newSizeValue = newSize.value; var isGravity = newSize.isGravity; for (var i = 0; i < cells.length; i++) { var ownSize = cells[i].getSize(); var resizeSibling = direction > 0 ? cells[i].$parent.getNextSibling(cells[i].$id) : cells[i].$parent.getPrevSibling(cells[i].$id); if (resizeSibling.$name == "resizer") { resizeSibling = direction > 0 ? resizeSibling.$parent.getNextSibling(resizeSibling.$id) : resizeSibling.$parent.getPrevSibling(resizeSibling.$id); } var siblingSize = resizeSibling.getSize(); if (!isGravity) { if (resizeSibling[property]) { var totalGravity = ownSize.gravity + siblingSize.gravity; var totalSize = ownSize[property] + siblingSize[property]; var k = totalGravity / totalSize; cells[i].$config.gravity = k * newSizeValue; resizeSibling.$config[property] = totalSize - newSizeValue; resizeSibling.$config.gravity = totalGravity - k * newSizeValue; } else { cells[i].$config[property] = newSizeValue; } } else { cells[i].$config.gravity = newSizeValue; } var mainGrid = this.$gantt.$ui.getView("grid"); if (mainGrid && cells[i].$content === mainGrid && !mainGrid.$config.scrollable && !isGravity) { this.$gantt.config.grid_width = newSizeValue; } } }; Layout2.prototype.resize = function(startStage) { var mainCall = false; if (this.$root && !this._resizeInProgress) { this.callEvent("onBeforeResize", []); mainCall = true; this._resizeInProgress = true; } _super.prototype.resize.call(this, true); _super.prototype.resize.call(this, false); if (mainCall) { var contentViews = []; contentViews = contentViews.concat(this.getCellsByType("viewCell")); contentViews = contentViews.concat(this.getCellsByType("viewLayout")); contentViews = contentViews.concat(this.getCellsByType("hostCell")); var scrollbars = this.getCellsByType("scroller"); for (var i = 0; i < contentViews.length; i++) { if (!contentViews[i].$config.hidden) contentViews[i].setContentSize(); } var autosize = this._getAutosizeMode(this.$config.autosize); var scrollChanged = this._resizeScrollbars(autosize, scrollbars); if (this.$config.autosize) { this.autosize(this.$config.autosize); contentViews.forEach(function(view) { const parent = view.$parent; const sizes = parent.getContentSize(autosize); if (autosize.x) { if (!parent.$config.$originalWidthStored) { parent.$config.$originalWidthStored = true; parent.$config.$originalWidth = parent.$config.width; } parent.$config.width = sizes.width; } if (autosize.y) { if (!parent.$config.$originalHeightStored) { parent.$config.$originalHeightStored = true; parent.$config.$originalHeight = parent.$config.height; } parent.$config.height = sizes.height; } }); scrollChanged = true; } if (scrollChanged) { this.resize(); for (var i = 0; i < contentViews.length; i++) { if (!contentViews[i].$config.hidden) contentViews[i].setContentSize(); } } this.callEvent("onResize", []); } if (mainCall) { this._resizeInProgress = false; } }; Layout2.prototype._eachChild = function(code, cell) { cell = cell || this; code(cell); if (cell.$cells) { for (var i = 0; i < cell.$cells.length; i++) { this._eachChild(code, cell.$cells[i]); } } }; Layout2.prototype.isChild = function(view) { var res = false; this._eachChild(function(child) { if (child === view || child.$content === view) { res = true; } }); return res; }; Layout2.prototype.getCellsByType = function(type) { var res = []; if (type === this.$name) { res.push(this); } if (this.$content && this.$content.$name == type) { res.push(this.$content); } if (this.$cells) { for (var i = 0; i < this.$cells.length; i++) { var children = Layout2.prototype.getCellsByType.call(this.$cells[i], type); if (children.length) { res.push.apply(res, children); } } } return res; }; Layout2.prototype.getNextSibling = function(cellId) { var index = this.cellIndex(cellId); if (index >= 0 && this.$cells[index + 1]) { return this.$cells[index + 1]; } else { return null; } }; Layout2.prototype.getPrevSibling = function(cellId) { var index = this.cellIndex(cellId); if (index >= 0 && this.$cells[index - 1]) { return this.$cells[index - 1]; } else { return null; } }; Layout2.prototype.cell = function(id) { for (var i = 0; i < this.$cells.length; i++) { var child = this.$cells[i]; if (child.$id === id) { return child; } var sub = child.cell(id); if (sub) { return sub; } } }; Layout2.prototype.cellIndex = function(id) { for (var i = 0; i < this.$cells.length; i++) { if (this.$cells[i].$id === id) { return i; } } return -1; }; Layout2.prototype.moveView = function(view, ind) { if (this.$cells[ind] !== view) { return window.alert("Not implemented"); } else { ind += this.$config.header ? 1 : 0; var node = this.$view; if (ind >= node.childNodes.length) { node.appendChild(view.$view); } else { node.insertBefore(view.$view, node.childNodes[ind]); } } }; Layout2.prototype._parseConfig = function(config2) { this.$cells = []; this._xLayout = !config2.rows; var cells = config2.rows || config2.cols || config2.views; for (var i = 0; i < cells.length; i++) { var cell = cells[i]; cell.mode = this._xLayout ? "x" : "y"; var $content = this.$factory.initUI(cell, this); if (!$content) { cells.splice(i, 1); i--; } else { $content.$parent = this; this.$cells.push($content); } } }; Layout2.prototype.getCells = function() { return this.$cells; }; Layout2.prototype.render = function() { var view = insertNode(this.$container, this.$toHTML()); this.$fill(view, null); const gantt2 = this.$gantt; this._eachChild((cell) => { if (cell.$externalComponent) { gantt2.config.external_render.renderElement(cell.$externalComponent, cell.$view.querySelector(".gantt_layout_content")); cell.$externalComponent = null; } }); this.callEvent("onReady", []); this.resize(); this.render = this.resize; }; Layout2.prototype.$fill = function(node, parent) { this.$view = node; this.$parent = parent; var cells = getChildNodes(node, "gantt_layout_cell"); for (var i = cells.length - 1; i >= 0; i--) { var sub = this.$cells[i]; sub.$fill(cells[i], this); if (sub.$config.hidden) { sub.$view.parentNode.removeChild(sub.$view); } } }; Layout2.prototype.$toHTML = function() { var mode = this._xLayout ? "x" : "y"; var html = []; for (var i = 0; i < this.$cells.length; i++) { html.push(this.$cells[i].$toHTML()); } return _super.prototype.$toHTML.call(this, html.join(""), (this.$root ? "gantt_layout_root " : "") + "gantt_layout gantt_layout_" + mode); }; Layout2.prototype.getContentSize = function(mode) { var contentWidth = 0, contentHeight = 0; var cellSize, cell, borders; for (var i = 0; i < this.$cells.length; i++) { cell = this.$cells[i]; if (cell.$config.hidden) continue; cellSize = cell.getContentSize(mode); if (cell.$config.view === "scrollbar" && mode[cell.$config.scroll]) { cellSize.height = 0; cellSize.width = 0; } if (cell.$config.resizer) { if (this._xLayout) { cellSize.height = 0; } else { cellSize.width = 0; } } borders = cell._getBorderSizes(); if (this._xLayout) { contentWidth += cellSize.width + borders.horizontal; contentHeight = Math.max(contentHeight, cellSize.height + borders.vertical); } else { contentWidth = Math.max(contentWidth, cellSize.width + borders.horizontal); contentHeight += cellSize.height + borders.vertical; } } borders = this._getBorderSizes(); contentWidth += borders.horizontal; contentHeight += borders.vertical; return { width: contentWidth, height: contentHeight }; }; Layout2.prototype._cleanElSize = function(value) { return (value || "").toString().replace("px", "") * 1 || 0; }; Layout2.prototype._getBoxStyles = function(div) { var computed = null; if (window.getComputedStyle) { computed = window.getComputedStyle(div, null); } else { computed = { width: div.clientWidth, height: div.clientHeight }; } var properties = ["width", "height", "paddingTop", "paddingBottom", "paddingLeft", "paddingRight", "borderLeftWidth", "borderRightWidth", "borderTopWidth", "borderBottomWidth"]; var styles = { boxSizing: computed.boxSizing == "border-box" }; if (computed.MozBoxSizing) { styles.boxSizing = computed.MozBoxSizing == "border-box"; } for (var i = 0; i < properties.length; i++) { styles[properties[i]] = computed[properties[i]] ? this._cleanElSize(computed[properties[i]]) : 0; } var box = { horPaddings: styles.paddingLeft + styles.paddingRight + styles.borderLeftWidth + styles.borderRightWidth, vertPaddings: styles.paddingTop + styles.paddingBottom + styles.borderTopWidth + styles.borderBottomWidth, borderBox: styles.boxSizing, innerWidth: styles.width, innerHeight: styles.height, outerWidth: styles.width, outerHeight: styles.height }; if (box.borderBox) { box.innerWidth -= box.horPaddings; box.innerHeight -= box.vertPaddings; } else { box.outerWidth += box.horPaddings; box.outerHeight += box.vertPaddings; } return box; }; Layout2.prototype._getAutosizeMode = function(config2) { var res = { x: false, y: false }; if (config2 === "xy") { res.x = res.y = true; } else if (config2 === "y" || config2 === true) { res.y = true; } else if (config2 === "x") { res.x = true; } return res; }; Layout2.prototype.autosize = function(mode) { var res = this._getAutosizeMode(mode); var boxSizes = this._getBoxStyles(this.$container); var contentSizes = this.getContentSize(mode); var node = this.$container; if (res.x) { if (boxSizes.borderBox) { contentSizes.width += boxSizes.horPaddings; } node.style.width = contentSizes.width + "px"; } if (res.y) { if (boxSizes.borderBox) { contentSizes.height += boxSizes.vertPaddings; } node.style.height = contentSizes.height + "px"; } }; Layout2.prototype.getSize = function() { this._sizes = []; var width = 0; var minWidth = 0; var maxWidth = 1e11; var height = 0; var maxHeight = 1e11; var minHeight = 0; for (var i = 0; i < this.$cells.length; i++) { var size = this._sizes[i] = this.$cells[i].getSize(); if (this.$cells[i].$config.hidden) { continue; } if (this._xLayout) { if (!size.width && size.minWidth) { width += size.minWidth; } else { width += size.width; } maxWidth += size.maxWidth; minWidth += size.minWidth; height = Math.max(height, size.height); maxHeight = Math.min(maxHeight, size.maxHeight); minHeight = Math.max(minHeight, size.minHeight); } else { if (!size.height && size.minHeight) { height += size.minHeight; } else { height += size.height; } maxHeight += size.maxHeight; minHeight += size.minHeight; width = Math.max(width, size.width); maxWidth = Math.min(maxWidth, size.maxWidth); minWidth = Math.max(minWidth, size.minWidth); } } var self2 = _super.prototype.getSize.call(this); if (self2.maxWidth >= 1e5) { self2.maxWidth = maxWidth; } if (self2.maxHeight >= 1e5) { self2.maxHeight = maxHeight; } self2.minWidth = self2.minWidth !== self2.minWidth ? 0 : self2.minWidth; self2.minHeight = self2.minHeight !== self2.minHeight ? 0 : self2.minHeight; if (this._xLayout) { self2.minWidth += this.$config.margin * this.$cells.length || 0; self2.minWidth += this.$config.padding * 2 || 0; self2.minHeight += this.$config.padding * 2 || 0; } else { self2.minHeight += this.$config.margin * this.$cells.length || 0; self2.minHeight += this.$config.padding * 2 || 0; } return self2; }; Layout2.prototype._calcFreeSpace = function(s, cell, xLayout) { var min = xLayout ? cell.minWidth : cell.minHeight; var max = xLayout ? cell.maxWidth : cell.maxWidth; var side = s; if (!side) { side = Math.floor(this._free / this._gravity * cell.gravity); if (side > max) { side = max; this._free -= side; this._gravity -= cell.gravity; } if (side < min) { side = min; this._free -= side; this._gravity -= cell.gravity; } } else { if (side > max) { side = max; } if (side < min) { side = min; } this._free -= side; } return side; }; Layout2.prototype._calcSize = function(s, size, xLayout) { var side = s; var min = xLayout ? size.minWidth : size.minHeight; var max = xLayout ? size.maxWidth : size.maxHeight; if (!side) { side = Math.floor(this._free / this._gravity * size.gravity); } if (side > max) { side = max; } if (side < min) { side = min; } return side; }; Layout2.prototype._configureBorders = function() { if (this.$root) { this._setBorders([this._borders.left, this._borders.top, this._borders.right, this._borders.bottom], this); } var borderClass = this._xLayout ? this._borders.right : this._borders.bottom; var cells = this.$cells; var lastVisibleIndex = cells.length - 1; for (var i = lastVisibleIndex; i >= 0; i--) { if (!cells[i].$config.hidden) { lastVisibleIndex = i; break; } } for (var i = 0; i < cells.length; i++) { if (cells[i].$config.hidden) { continue; } var lastCell = i >= lastVisibleIndex; var borderColorClass = ""; if (!lastCell && cells[i + 1]) { if (cells[i + 1].$config.view == "scrollbar") { if (this._xLayout) { lastCell = true; } else { borderColorClass = "gantt_layout_cell_border_transparent"; } } } this._setBorders(lastCell ? [] : [borderClass, borderColorClass], cells[i]); } }; Layout2.prototype._updateCellVisibility = function() { var oldVisibleCells = this._visibleCells || {}; var firstCall = !this._visibleCells; var visibleCells = {}; var cell = null; var parentVisibility = []; for (var i = 0; i < this._sizes.length; i++) { cell = this.$cells[i]; if (cell.$config.hide_empty) { parentVisibility.push(cell); } if (!firstCall && cell.$config.hidden && oldVisibleCells[cell.$id]) { cell._hide(true); } else if (!cell.$config.hidden && !oldVisibleCells[cell.$id]) { cell._hide(false); } if (!cell.$config.hidden) { visibleCells[cell.$id] = true; } } this._visibleCells = visibleCells; for (var i = 0; i < parentVisibility.length; i++) { var cell = parentVisibility[i]; var children = cell.$cells; var hideCell = true; children.forEach(function(child) { if (!child.$config.hidden && !child.$config.resizer) { hideCell = false; } }); cell.$config.hidden = hideCell; } }; Layout2.prototype.setSize = function(x, y) { this._configureBorders(); _super.prototype.setSize.call(this, x, y); y = this.$lastSize.contentY; x = this.$lastSize.contentX; var padding = this.$config.padding || 0; this.$view.style.padding = padding + "px"; this._gravity = 0; this._free = this._xLayout ? x : y; this._free -= padding * 2; var cell, size; this._updateCellVisibility(); for (var i = 0; i < this._sizes.length; i++) { cell = this.$cells[i]; if (cell.$config.hidden) { continue; } var margin = this.$config.margin || 0; if (cell.$name == "resizer" && !margin) { margin = -1; } var cellView = cell.$view; var marginSide = this._xLayout ? "marginRight" : "marginBottom"; if (i !== this.$cells.length - 1) { cellView.style[marginSide] = margin + "px"; this._free -= margin; } size = this._sizes[i]; if (this._xLayout) { if (!size.width) { this._gravity += size.gravity; } } else { if (!size.height) { this._gravity += size.gravity; } } } for (var i = 0; i < this._sizes.length; i++) { cell = this.$cells[i]; if (cell.$config.hidden) { continue; } size = this._sizes[i]; var width = size.width; var height = size.height; if (this._xLayout) { this._calcFreeSpace(width, size, true); } else { this._calcFreeSpace(height, size, false); } } for (var i = 0; i < this.$cells.length; i++) { cell = this.$cells[i]; if (cell.$config.hidden) { continue; } size = this._sizes[i]; var dx = void 0; var dy = void 0; if (this._xLayout) { dx = this._calcSize(size.width, size, true); dy = y - padding * 2; } else { dx = x - padding * 2; dy = this._calcSize(size.height, size, false); } cell.setSize(dx, dy); } }; return Layout2; }(Cell); var ViewLayout = function(_super) { __extends(ViewLayout2, _super); function ViewLayout2(parent, config2, factory2) { var _this = _super.apply(this, arguments) || this; for (var i = 0; i < _this.$cells.length; i++) { _this.$cells[i].$config.hidden = i !== 0; } _this.$cell = _this.$cells[0]; _this.$name = "viewLayout"; return _this; } ViewLayout2.prototype.cell = function(id) { var cell = _super.prototype.cell.call(this, id); if (!cell.$view) { this.$fill(null, this); } return cell; }; ViewLayout2.prototype.moveView = function(view) { var body = this.$view; if (this.$cell) { this.$cell.$config.hidden = true; body.removeChild(this.$cell.$view); } this.$cell = view; body.appendChild(view.$view); }; ViewLayout2.prototype.setSize = function(x, y) { Cell.prototype.setSize.call(this, x, y); }; ViewLayout2.prototype.setContentSize = function() { var size = this.$lastSize; this.$cell.setSize(size.contentX, size.contentY); }; ViewLayout2.prototype.getSize = function() { var sizes = _super.prototype.getSize.call(this); if (this.$cell) { var cellSize = this.$cell.getSize(); if (this.$config.byMaxSize) { for (var i = 0; i < this.$cells.length; i++) { var otherCell = this.$cells[i].getSize(); for (var cell in cellSize) { cellSize[cell] = Math.max(cellSize[cell], otherCell[cell]); } } } for (var size in sizes) { sizes[size] = sizes[size] || cellSize[size]; } sizes.gravity = Math.max(sizes.gravity, cellSize.gravity); } return sizes; }; return ViewLayout2; }(Layout); var ViewCell = function(_super) { __extends(ViewCell2, _super); function ViewCell2(parent, config2, factory2) { var _this = _super.apply(this, arguments) || this; if (config2.view) { if (config2.id) { this.$id = uid(); } var childConfig = copy(config2); delete childConfig.config; delete childConfig.templates; this.$content = this.$factory.createView(config2.view, this, childConfig, this); if (!this.$content) return false; } _this.$name = "viewCell"; return _this; } ViewCell2.prototype.destructor = function() { this.clear(); _super.prototype.destructor.call(this); }; ViewCell2.prototype.clear = function() { this.$initialized = false; if (this.$content) { var method = this.$content.unload || this.$content.destructor; if (method) { method.call(this.$content); } } _super.prototype.clear.call(this); }; ViewCell2.prototype.scrollTo = function(left, top) { if (this.$content && this.$content.scrollTo) { this.$content.scrollTo(left, top); } else { _super.prototype.scrollTo.call(this, left, top); } }; ViewCell2.prototype._setContentSize = function(x, y) { var borders = this._getBorderSizes(); if (typeof x === "number") { var outerX = x + borders.horizontal; this.$config.width = outerX; } if (typeof y === "number") { var outerY = y + borders.vertical; this.$config.height = outerY; } }; ViewCell2.prototype.setSize = function(x, y) { _super.prototype.setSize.call(this, x, y); if (!this.$preResize && this.$content) { if (!this.$initialized) { this.$initialized = true; var header = this.$view.childNodes[0]; var content = this.$view.childNodes[1]; if (!content) content = header; this.$content.init(content); } } }; ViewCell2.prototype.setContentSize = function() { if (!this.$preResize && this.$content) { if (this.$initialized) { this.$content.setSize(this.$lastSize.contentX, this.$lastSize.contentY); } } }; ViewCell2.prototype.getContentSize = function() { var size = _super.prototype.getContentSize.call(this); if (this.$content && this.$initialized) { var childSize = this.$content.getSize(); size.width = childSize.contentX === void 0 ? childSize.width : childSize.contentX; size.height = childSize.contentY === void 0 ? childSize.height : childSize.contentY; } var borders = this._getBorderSizes(); size.width += borders.horizontal; size.height += borders.vertical; return size; }; return ViewCell2; }(Cell); const Resizer = null; var ScrollbarCell = function(_super) { var SCROLL_MODIFIER_KEYS = ["altKey", "shiftKey", "metaKey"]; __extends(ScrollbarCell2, _super); function ScrollbarCell2(parent, config2, factory2, gantt2) { var _this = _super.apply(this, arguments) || this; this.$config = mixin(config2, { scroll: "x" }); _this._scrollHorizontalHandler = bind(_this._scrollHorizontalHandler, _this); _this._scrollVerticalHandler = bind(_this._scrollVerticalHandler, _this); _this._outerScrollVerticalHandler = bind(_this._outerScrollVerticalHandler, _this); _this._outerScrollHorizontalHandler = bind(_this._outerScrollHorizontalHandler, _this); _this._mouseWheelHandler = bind(_this._mouseWheelHandler, _this); this.$config.hidden = true; var size = gantt2.config.scroll_size; if (gantt2.env.isIE) { size += 1; } if (this._isHorizontal()) { _this.$config.height = size; _this.$parent.$config.height = size; } else { _this.$config.width = size; _this.$parent.$config.width = size; } this.$config.scrollPosition = 0; _this.$name = "scroller"; return _this; } ScrollbarCell2.prototype.init = function(container) { container.innerHTML = this.$toHTML(); this.$view = container.firstChild; if (!this.$view) { this.init(); } if (this._isVertical()) { this._initVertical(); } else { this._initHorizontal(); } this._initMouseWheel(); this._initLinkedViews(); }; ScrollbarCell2.prototype.$toHTML = function() { var className = this._isHorizontal() ? "gantt_hor_scroll" : "gantt_ver_scroll"; return "
"; }; ScrollbarCell2.prototype._getRootParent = function() { var parent = this.$parent; while (parent && parent.$parent) { parent = parent.$parent; } if (parent) { return parent; } }; function eachCell(root, res) { res.push(root); if (root.$cells) { for (var i = 0; i < root.$cells.length; i++) { eachCell(root.$cells[i], res); } } } ScrollbarCell2.prototype._eachView = function() { var res = []; eachCell(this._getRootParent(), res); return res; }; ScrollbarCell2.prototype._getLinkedViews = function() { var views = this._eachView(); var res = []; for (var i = 0; i < views.length; i++) { if (views[i].$config && (this._isVertical() && views[i].$config.scrollY == this.$id || this._isHorizontal() && views[i].$config.scrollX == this.$id)) { res.push(views[i]); } } return res; }; ScrollbarCell2.prototype._initHorizontal = function() { this.$scroll_hor = this.$view; this.$domEvents.attach(this.$view, "scroll", this._scrollHorizontalHandler); }; ScrollbarCell2.prototype._initLinkedViews = function() { var views = this._getLinkedViews(); var css = this._isVertical() ? "gantt_layout_outer_scroll gantt_layout_outer_scroll_vertical" : "gantt_layout_outer_scroll gantt_layout_outer_scroll_horizontal"; for (var i = 0; i < views.length; i++) { addClassName(views[i].$view || views[i].getNode(), css); } }; ScrollbarCell2.prototype._initVertical = function() { this.$scroll_ver = this.$view; this.$domEvents.attach(this.$view, "scroll", this._scrollVerticalHandler); }; ScrollbarCell2.prototype._updateLinkedViews = function() { }; ScrollbarCell2.prototype._initMouseWheel = function() { var ff = env.isFF; if (ff) this.$domEvents.attach(this._getRootParent().$view, "wheel", this._mouseWheelHandler, { passive: false }); else this.$domEvents.attach(this._getRootParent().$view, "mousewheel", this._mouseWheelHandler, { passive: false }); }; ScrollbarCell2.prototype.scrollHorizontally = function(left) { if (this._scrolling) return; this._scrolling = true; this.$scroll_hor.scrollLeft = left; this.$config.codeScrollLeft = left; left = this.$scroll_hor.scrollLeft; var views = this._getLinkedViews(); for (var i = 0; i < views.length; i++) { if (views[i].scrollTo) { views[i].scrollTo(left, void 0); } } var oldSize = this.$config.scrollPosition; this.$config.scrollPosition = left; this.callEvent("onScroll", [oldSize, left, this.$config.scroll]); this._scrolling = false; }; ScrollbarCell2.prototype.scrollVertically = function(top) { if (this._scrolling) return; this._scrolling = true; this.$scroll_ver.scrollTop = top; top = this.$scroll_ver.scrollTop; var views = this._getLinkedViews(); for (var i = 0; i < views.length; i++) { if (views[i].scrollTo) { views[i].scrollTo(void 0, top); } } var oldSize = this.$config.scrollPosition; this.$config.scrollPosition = top; this.callEvent("onScroll", [oldSize, top, this.$config.scroll]); this._scrolling = false; }; ScrollbarCell2.prototype._isVertical = function() { return this.$config.scroll == "y"; }; ScrollbarCell2.prototype._isHorizontal = function() { return this.$config.scroll == "x"; }; ScrollbarCell2.prototype._scrollHorizontalHandler = function(e) { if (this._isVertical() || this._scrolling) { return; } if (/* @__PURE__ */ new Date() - (this._wheel_time || 0) < 100) return true; var left = this.$scroll_hor.scrollLeft; this.scrollHorizontally(left); this._oldLeft = this.$scroll_hor.scrollLeft; }; ScrollbarCell2.prototype._outerScrollHorizontalHandler = function(e) { if (this._isVertical()) { return; } }; ScrollbarCell2.prototype.show = function() { this.$parent.show(); }; ScrollbarCell2.prototype.hide = function() { this.$parent.hide(); }; ScrollbarCell2.prototype._getScrollSize = function() { var scrollSize = 0; var outerSize = 0; var isHorizontal = this._isHorizontal(); var linked = this._getLinkedViews(); var view; var scrollProperty = isHorizontal ? "scrollWidth" : "scrollHeight", innerSizeProperty = isHorizontal ? "contentX" : "contentY"; var outerProperty = isHorizontal ? "x" : "y"; var offset = this._getScrollOffset(); for (var i = 0; i < linked.length; i++) { view = linked[i]; if (!(view && view.$content && view.$content.getSize && !view.$config.hidden)) continue; var sizes = view.$content.getSize(); var cellScrollSize; if (sizes.hasOwnProperty(scrollProperty)) { cellScrollSize = sizes[scrollProperty]; } else { cellScrollSize = sizes[innerSizeProperty]; } if (offset) { if (sizes[innerSizeProperty] > sizes[outerProperty] && sizes[innerSizeProperty] > scrollSize && cellScrollSize > sizes[outerProperty] - offset + 2) { scrollSize = cellScrollSize + (isHorizontal ? 0 : 2); outerSize = sizes[outerProperty]; } } else { var nonScrollableSize = Math.max(sizes[innerSizeProperty] - cellScrollSize, 0); var scrollableViewPortSize = Math.max(sizes[outerProperty] - nonScrollableSize, 0); cellScrollSize = cellScrollSize + nonScrollableSize; if (cellScrollSize > scrollableViewPortSize && cellScrollSize > scrollSize) { scrollSize = cellScrollSize; outerSize = sizes[outerProperty]; } } } return { outerScroll: outerSize, innerScroll: scrollSize }; }; ScrollbarCell2.prototype.scroll = function(position) { if (this._isHorizontal()) { this.scrollHorizontally(position); } else { this.scrollVertically(position); } }; ScrollbarCell2.prototype.getScrollState = function() { return { visible: this.isVisible(), direction: this.$config.scroll, size: this.$config.outerSize, scrollSize: this.$config.scrollSize || 0, position: this.$config.scrollPosition || 0 }; }; ScrollbarCell2.prototype.setSize = function(width, height) { _super.prototype.setSize.apply(this, arguments); var scrollSizes = this._getScrollSize(); var ownSize = (this._isVertical() ? height : width) - this._getScrollOffset() + (this._isHorizontal() ? 1 : 0); if (scrollSizes.innerScroll && ownSize > scrollSizes.outerScroll) { scrollSizes.innerScroll += ownSize - scrollSizes.outerScroll; } this.$config.scrollSize = scrollSizes.innerScroll; this.$config.width = width; this.$config.height = height; this._setScrollSize(scrollSizes.innerScroll); }; ScrollbarCell2.prototype.isVisible = function() { return !!(this.$parent && this.$parent.$view.parentNode); }; ScrollbarCell2.prototype.shouldShow = function() { var scrollSizes = this._getScrollSize(); if (!scrollSizes.innerScroll && (this.$parent && this.$parent.$view.parentNode)) { return false; } else if (scrollSizes.innerScroll && !(this.$parent && this.$parent.$view.parentNode)) { return true; } else { return false; } }; ScrollbarCell2.prototype.shouldHide = function() { var scrollSizes = this._getScrollSize(); if (!scrollSizes.innerScroll && (this.$parent && this.$parent.$view.parentNode)) { return true; } else { return false; } }; ScrollbarCell2.prototype.toggleVisibility = function() { if (this.shouldHide()) { this.hide(); } else if (this.shouldShow()) { this.show(); } }; ScrollbarCell2.prototype._getScaleOffset = function(view) { var offset = 0; if (view && (view.$config.view == "timeline" || view.$config.view == "grid")) { offset = view.$content.$getConfig().scale_height; } return offset; }; ScrollbarCell2.prototype._getScrollOffset = function() { var offset = 0; if (this._isVertical()) { var parentLayout = this.$parent.$parent; offset = Math.max(this._getScaleOffset(parentLayout.getPrevSibling(this.$parent.$id)), this._getScaleOffset(parentLayout.getNextSibling(this.$parent.$id))); } else { var linked = this._getLinkedViews(); for (var i = 0; i < linked.length; i++) { var view = linked[i], vparent = view.$parent; var cells = vparent.$cells; var last = cells[cells.length - 1]; if (last && last.$config.view == "scrollbar" && last.$config.hidden === false) { offset = last.$config.width; break; } } } return offset || 0; }; ScrollbarCell2.prototype._setScrollSize = function(size) { var property = this._isHorizontal() ? "width" : "height"; var scrollbar = this._isHorizontal() ? this.$scroll_hor : this.$scroll_ver; var offset = this._getScrollOffset(); var node = scrollbar.firstChild; if (offset) { if (this._isVertical()) { this.$config.outerSize = this.$config.height - offset + 3; scrollbar.style.height = this.$config.outerSize + "px"; scrollbar.style.top = offset - 1 + "px"; addClassName(scrollbar, this.$parent._borders.top); addClassName(scrollbar.parentNode, "gantt_task_vscroll"); } else { this.$config.outerSize = this.$config.width - offset + 1; scrollbar.style.width = this.$config.outerSize + "px"; } } else { scrollbar.style.top = "auto"; removeClassName(scrollbar, this.$parent._borders.top); removeClassName(scrollbar.parentNode, "gantt_task_vscroll"); this.$config.outerSize = this.$config.height; } node.style[property] = size + "px"; }; ScrollbarCell2.prototype._scrollVerticalHandler = function(e) { if (this._scrollHorizontalHandler() || this._scrolling) { return; } var top = this.$scroll_ver.scrollTop; var prev = this._oldTop; if (top == prev) return; this.scrollVertically(top); this._oldTop = this.$scroll_ver.scrollTop; }; ScrollbarCell2.prototype._outerScrollVerticalHandler = function(e) { if (this._scrollHorizontalHandler()) { return; } }; ScrollbarCell2.prototype._checkWheelTarget = function(targetNode) { var connectedViews = this._getLinkedViews().concat(this); for (var i = 0; i < connectedViews.length; i++) { var node = connectedViews[i].$view; if (isChildOf(targetNode, node)) { return true; } } return false; }; ScrollbarCell2.prototype._mouseWheelHandler = function(e) { var target = e.target || e.srcElement; if (!this._checkWheelTarget(target)) return; this._wheel_time = /* @__PURE__ */ new Date(); var res = {}; var wheelSpeed = { x: 1, y: 1 }; var wheelSpeedConfig = this.$gantt.config.wheel_scroll_sensitivity; if (typeof wheelSpeedConfig == "number" && !!wheelSpeedConfig) { wheelSpeed = { x: wheelSpeedConfig, y: wheelSpeedConfig }; } else if ({}.toString.apply(wheelSpeedConfig) == "[object Object]") { wheelSpeed = { x: wheelSpeedConfig.x, y: wheelSpeedConfig.y }; } var ff = env.isFF; var deltaX = ff ? e.deltaX : e.wheelDeltaX; var deltaY = ff ? e.deltaY : e.wheelDelta; var multiplier = -20; if (ff) { const version = parseInt(navigator.userAgent.split("Firefox/")[1]); if (version <= 87) { if (e.deltaMode !== 0) { multiplier = -40; } else { multiplier = -10; } } else if (version <= 90) { multiplier = -3; } else if (version <= 96) { multiplier = -1.5; } else { multiplier = -1; } } var wx = ff ? deltaX * multiplier * wheelSpeed.x : deltaX * 2 * wheelSpeed.x; var wy = ff ? deltaY * multiplier * wheelSpeed.y : deltaY * wheelSpeed.y; var horizontalScrollModifier = this.$gantt.config.horizontal_scroll_key; if (horizontalScrollModifier !== false) { if (SCROLL_MODIFIER_KEYS.indexOf(horizontalScrollModifier) >= 0) { if (e[horizontalScrollModifier] && !(e.deltaX || e.wheelDeltaX)) { wx = wy * 2; wy = 0; } } } if (wx && Math.abs(wx) > Math.abs(wy)) { if (this._isVertical()) { return; } if (res.x) return true; if (!this.$scroll_hor || !this.$scroll_hor.offsetWidth) return true; var dir = wx / -40; var oldLeft = this._oldLeft; var left = oldLeft + dir * 30; this.scrollHorizontally(left); this.$scroll_hor.scrollLeft = left; if (oldLeft == this.$scroll_hor.scrollLeft) { return true; } this._oldLeft = this.$scroll_hor.scrollLeft; } else { if (this._isHorizontal()) { return; } if (res.y) return true; if (!this.$scroll_ver || !this.$scroll_ver.offsetHeight) return true; var dir = wy / -40; if (typeof wy == "undefined") dir = e.detail; var oldTop = this._oldTop; var top = this.$scroll_ver.scrollTop + dir * 30; this.scrollVertically(top); this.$scroll_ver.scrollTop = top; if (oldTop == this.$scroll_ver.scrollTop) { return true; } this._oldTop = this.$scroll_ver.scrollTop; } if (e.preventDefault) e.preventDefault(); e.cancelBubble = true; return false; }; return ScrollbarCell2; }(Cell); function createHelper(view) { var cachedRowHeight = -1; var canUseSimpleCalc = -1; return { resetCache: function() { cachedRowHeight = -1; canUseSimpleCalc = -1; }, _getRowHeight: function() { if (cachedRowHeight === -1) { cachedRowHeight = view.$getConfig().row_height; } return cachedRowHeight; }, _refreshState: function() { this.resetCache(); canUseSimpleCalc = true; var store = view.$config.rowStore; if (!store) { return; } var globalRowHeight = this._getRowHeight(); for (var i = 0; i < store.fullOrder.length; i++) { var item = store.getItem(store.fullOrder[i]); if (!item) { continue; } if (item.row_height && item.row_height !== globalRowHeight) { canUseSimpleCalc = false; break; } } }, canUseSimpleCalculation: function() { if (canUseSimpleCalc === -1) { this._refreshState(); } return canUseSimpleCalc; }, getRowTop: function(index) { var store = view.$config.rowStore; if (!store) { return 0; } return index * this._getRowHeight(); }, getItemHeight: function(itemId) { return this._getRowHeight(); }, getTotalHeight: function() { if (view.$config.rowStore) { var store = view.$config.rowStore; return store.countVisible() * this._getRowHeight(); } else { return 0; } }, getItemIndexByTopPosition: function(top) { if (view.$config.rowStore) { return Math.floor(top / this._getRowHeight()); } else { return 0; } } }; } function createMixin$1(view) { var getItemTopCache = {}; var getRowTopCache = {}; var getItemHeightCache = null; var totalHeightCache = -1; var getItemHeightCacheState = null; var quickPosition = createHelper(view); return { _resetTopPositionHeight: function() { getItemTopCache = {}; getRowTopCache = {}; quickPosition.resetCache(); }, _resetHeight: function() { var store = this.$config.rowStore; var newState = this.getCacheStateTotalHeight(store); if (!getItemHeightCacheState) { getItemHeightCacheState = newState; } else if (this.shouldClearHeightCache(getItemHeightCacheState, newState)) { getItemHeightCacheState = newState; getItemHeightCache = null; } totalHeightCache = -1; quickPosition.resetCache(); }, getRowTop: function(index) { if (quickPosition.canUseSimpleCalculation()) { return quickPosition.getRowTop(index); } var store = this.$config.rowStore; if (!store) { return 0; } if (getRowTopCache[index] !== void 0) { return getRowTopCache[index]; } else { var all = store.getIndexRange(); var top = 0; var result = 0; for (var i = 0; i < all.length; i++) { getRowTopCache[i] = top; top += this.getItemHeight(all[i].id); if (i < index) { result = top; } } return result; } }, getItemTop: function(taskId) { if (this.$config.rowStore) { if (getItemTopCache[taskId] !== void 0) { return getItemTopCache[taskId]; } var store = this.$config.rowStore; if (!store) return 0; var itemIndex = store.getIndexById(taskId); if (itemIndex === -1 && store.getParent && store.exists(taskId)) { var parentId = store.getParent(taskId); if (store.exists(parentId)) { var parent = store.getItem(parentId); if (this.$gantt.isSplitTask(parent)) { return this.getItemTop(parentId); } } } getItemTopCache[taskId] = this.getRowTop(itemIndex); return getItemTopCache[taskId]; } else { return 0; } }, getItemHeight: function(itemId) { if (quickPosition.canUseSimpleCalculation()) { return quickPosition.getItemHeight(itemId); } if (!getItemHeightCache && this.$config.rowStore) { this._fillHeightCache(this.$config.rowStore); } if (getItemHeightCache[itemId] !== void 0) { return getItemHeightCache[itemId]; } var defaultHeight = this.$getConfig().row_height; if (this.$config.rowStore) { var store = this.$config.rowStore; if (!store) return defaultHeight; var item = store.getItem(itemId); return getItemHeightCache[itemId] = item && item.row_height || defaultHeight; } else { return defaultHeight; } }, _fillHeightCache: function(store) { if (!store) { return; } getItemHeightCache = {}; var defaultHeight = this.$getConfig().row_height; store.eachItem(function(item) { return getItemHeightCache[item.id] = item && item.row_height || defaultHeight; }); }, getCacheStateTotalHeight: function(store) { var globalHeight = this.$getConfig().row_height; var itemHeightCache = {}; var items = []; var sumHeight = 0; if (store) { store.eachItem(function(item) { items.push(item); itemHeightCache[item.id] = item.row_height; sumHeight += item.row_height || globalHeight; }); } return { globalHeight, items, count: items.length, sumHeight }; }, shouldClearHeightCache: function(oldState, newState) { if (oldState.count != newState.count) { return true; } if (oldState.globalHeight != newState.globalHeight) { return true; } if (oldState.sumHeight != newState.sumHeight) { return true; } for (var i in oldState.items) { var newValue = newState.items[i]; if (newValue !== void 0 && newValue != oldState.items[i]) { return true; } } return false; }, getTotalHeight: function() { if (quickPosition.canUseSimpleCalculation()) { return quickPosition.getTotalHeight(); } if (totalHeightCache != -1) { return totalHeightCache; } if (this.$config.rowStore) { var store = this.$config.rowStore; this._fillHeightCache(store); var getHeight = this.getItemHeight.bind(this); var visibleItems = store.getVisibleItems(); var totalHeight = 0; visibleItems.forEach(function(item) { totalHeight += getHeight(item.id); }); totalHeightCache = totalHeight; return totalHeight; } else { return 0; } }, getItemIndexByTopPosition: function(top) { if (this.$config.rowStore) { if (quickPosition.canUseSimpleCalculation()) { return quickPosition.getItemIndexByTopPosition(top); } var store = this.$config.rowStore; for (var i = 0; i < store.countVisible(); i++) { var current = this.getRowTop(i); var next = this.getRowTop(i + 1); if (!next) { var taskId = store.getIdByIndex(i); next = current + this.getItemHeight(taskId); } if (top >= current && top < next) { return i; } } return store.countVisible() + 2; } else { return 0; } } }; } var createStaticBgHelper = function() { return { render: function() { }, destroy: function() { } }; }; const canvasRender = { create: function() { return createStaticBgHelper(); } }; function createLayerConfig() { var self2 = this; var taskFilter = function() { return self2.isVisible(); }; var barVisible = function(id, task) { return !task.hide_bar; }; this.$gantt; var taskLayers2 = [{ expose: true, renderer: this.$gantt.$ui.layers.taskBar(), container: this.$task_bars, filter: [taskFilter, barVisible] }]; taskLayers2.push({ renderer: this.$gantt.$ui.layers.taskBg(), container: this.$task_bg, filter: [taskFilter] }); var linkLayers = [{ expose: true, renderer: this.$gantt.$ui.layers.link(), container: this.$task_links, filter: [taskFilter] }]; return { tasks: taskLayers2, links: linkLayers }; } var Timeline = function(parent, config2, factory2, gantt2) { this.$config = mixin({}, config2 || {}); this.$scaleHelper = new ScaleHelper(gantt2); this.$gantt = gantt2; this._posFromDateCache = {}; this._posFromWorkTimeCache = {}; this._timelineDragScroll = null; mixin(this, createMixin$1(this)); makeEventable(this); }; Timeline.prototype = { init: function(container) { container.innerHTML += "
"; this.$task = container.childNodes[0]; this.$task.innerHTML = "
"; this.$task_scale = this.$task.childNodes[0]; this.$task_data = this.$task.childNodes[1]; const taskBg = "
"; const links = ""; const taskBars = "
"; const taskConstraints = "
"; const taskDeadlines = "
"; const taskBaselines = "
"; this.$task_data.innerHTML = taskBg + taskBaselines + links + taskBars + taskConstraints + taskDeadlines; this.$task_bg = this.$task_data.childNodes[0]; this.$task_baselines = this.$task_data.childNodes[1]; this.$task_links = this.$task_data.childNodes[2]; this.$task_bars = this.$task_data.childNodes[3]; this.$task_constraints = this.$task_data.childNodes[4]; this.$task_deadlines = this.$task_data.childNodes[5]; this._tasks = { col_width: 0, width: [], full_width: 0, trace_x: [], rendered: {} }; var config2 = this.$getConfig(); var attr = config2[this.$config.bind + "_attribute"]; var linksAttr = config2[this.$config.bindLinks + "_attribute"]; if (!attr && this.$config.bind) { attr = "data-" + this.$config.bind + "-id"; } if (!linksAttr && this.$config.bindLinks) { linksAttr = "data-" + this.$config.bindLinks + "-id"; } this.$config.item_attribute = attr || null; this.$config.link_attribute = linksAttr || null; var layers = this._createLayerConfig(); if (!this.$config.layers) { this.$config.layers = layers.tasks; } if (!this.$config.linkLayers) { this.$config.linkLayers = layers.links; } this._attachLayers(this.$gantt); this.callEvent("onReady", []); if (this.$gantt.ext.dragTimeline) { this._timelineDragScroll = this.$gantt.ext.dragTimeline.create(); this._timelineDragScroll.attach(this); } }, setSize: function(width, height) { var config2 = this.$getConfig(); if (width * 1 === width) { this.$config.width = width; } if (height * 1 === height) { this.$config.height = height; var dataHeight = Math.max(this.$config.height - config2.scale_height); this.$task_data.style.height = dataHeight + "px"; } this.refresh(); this.$task_bg.style.backgroundImage = ""; if (config2.smart_rendering && this.$config.rowStore) { this.$task_bg.style.height = this.getTotalHeight() + "px"; } else { this.$task_bg.style.height = ""; } var scale = this._tasks; var data_els = this.$task_data.childNodes; for (var i = 0, len = data_els.length; i < len; i++) { var el = data_els[i]; if (el.hasAttribute("data-layer") && el.style) el.style.width = scale.full_width + "px"; } }, isVisible: function() { if (this.$parent && this.$parent.$config) { return !this.$parent.$config.hidden; } else { return this.$task.offsetWidth; } }, getSize: function() { var config2 = this.$getConfig(); var store = this.$config.rowStore; var contentHeight = store ? this.getTotalHeight() : 0, contentWidth = this.isVisible() ? this._tasks.full_width : 0; return { x: this.isVisible() ? this.$config.width : 0, y: this.isVisible() ? this.$config.height : 0, contentX: this.isVisible() ? contentWidth : 0, contentY: this.isVisible() ? config2.scale_height + contentHeight : 0, scrollHeight: this.isVisible() ? contentHeight : 0, scrollWidth: this.isVisible() ? contentWidth : 0 }; }, scrollTo: function(left, top) { if (!this.isVisible()) return; var scrolled = false; this.$config.scrollTop = this.$config.scrollTop || 0; this.$config.scrollLeft = this.$config.scrollLeft || 0; if (top * 1 === top) { this.$config.scrollTop = top; this.$task_data.scrollTop = this.$config.scrollTop; scrolled = true; } if (left * 1 === left) { this.$task.scrollLeft = left; this.$config.scrollLeft = this.$task.scrollLeft; this._refreshScales(); scrolled = true; } if (scrolled) { this.callEvent("onScroll", [this.$config.scrollLeft, this.$config.scrollTop]); } }, _refreshScales: function _refreshScales() { if (!this.isVisible()) return; var config2 = this.$getConfig(); if (!config2.smart_scales) return; var viewPort = this.getViewPort(); var scales = this._scales; this.$task_scale.innerHTML = this._getScaleChunkHtml(scales, viewPort.x, viewPort.x_end); }, getViewPort: function() { var scrollLeft = this.$config.scrollLeft || 0; var scrollTop = this.$config.scrollTop || 0; var height = this.$config.height || 0; var width = this.$config.width || 0; return { y: scrollTop, y_end: scrollTop + height, x: scrollLeft, x_end: scrollLeft + width, height, width }; }, _createLayerConfig: createLayerConfig, _attachLayers: function(gantt2) { this._taskLayers = []; this._linkLayers = []; var self2 = this; var layers = this.$gantt.$services.getService("layers"); if (this.$config.bind) { this._bindStore(); var taskRenderer = layers.getDataRender(this.$config.bind); if (!taskRenderer) { taskRenderer = layers.createDataRender({ name: this.$config.bind, defaultContainer: function() { return self2.$task_data; } }); } taskRenderer.container = function() { return self2.$task_data; }; var taskLayers2 = this.$config.layers; for (var i = 0; taskLayers2 && i < taskLayers2.length; i++) { var layer = taskLayers2[i]; if (typeof layer == "string") { layer = this.$gantt.$ui.layers[layer](); } if (typeof layer == "function" || layer && layer.render && layer.update) { layer = { renderer: layer }; } layer.view = this; var bar_layer = taskRenderer.addLayer(layer); this._taskLayers.push(bar_layer); if (layer.expose) { this._taskRenderer = taskRenderer.getLayer(bar_layer); } } this._initStaticBackgroundRender(); } if (this.$config.bindLinks) { self2.$config.linkStore = self2.$gantt.getDatastore(self2.$config.bindLinks); var linkRenderer = layers.getDataRender(this.$config.bindLinks); if (!linkRenderer) { linkRenderer = layers.createDataRender({ name: this.$config.bindLinks, defaultContainer: function() { return self2.$task_data; } }); } var linkLayers = this.$config.linkLayers; for (var i = 0; linkLayers && i < linkLayers.length; i++) { if (typeof layer == "string") { layer = this.$gantt.$ui.layers[layer](); } var layer = linkLayers[i]; layer.view = this; var linkLayer = linkRenderer.addLayer(layer); this._taskLayers.push(linkLayer); if (linkLayers[i].expose) { this._linkRenderer = linkRenderer.getLayer(linkLayer); } } } }, _initStaticBackgroundRender: function() { var self2 = this; var staticRender = canvasRender.create(); var store = self2.$config.rowStore; if (!store) return; this._staticBgHandler = store.attachEvent("onStoreUpdated", function(id, item, mode) { if (id !== null) { return; } if (!self2.isVisible()) return; var config2 = self2.$getConfig(); if (config2.static_background || config2.timeline_placeholder) { var store2 = self2.$gantt.getDatastore(self2.$config.bind); var staticBgContainer = self2.$task_bg_static; if (!staticBgContainer) { staticBgContainer = document.createElement("div"); staticBgContainer.className = "gantt_task_bg"; self2.$task_bg_static = staticBgContainer; if (self2.$task_bg.nextSibling) { self2.$task_data.insertBefore(staticBgContainer, self2.$task_bg.nextSibling); } else { self2.$task_data.appendChild(staticBgContainer); } } if (store2) { var staticBackgroundHeight = self2.getTotalHeight(); if (config2.timeline_placeholder) { staticBackgroundHeight = config2.timeline_placeholder.height || self2.$task_data.offsetHeight || 99999; } staticRender.render(staticBgContainer, config2, self2.getScale(), staticBackgroundHeight, self2.getItemHeight(item ? item.id : null)); } } else if (config2.static_background) { if (self2.$task_bg_static && self2.$task_bg_static.parentNode) { self2.$task_bg_static.parentNode.removeChild(self2.$task_bg_static); } } }); this.attachEvent("onDestroy", function() { }); this._initStaticBackgroundRender = function() { }; }, _clearLayers: function(gantt2) { var layers = this.$gantt.$services.getService("layers"); var taskRenderer = layers.getDataRender(this.$config.bind); var linkRenderer = layers.getDataRender(this.$config.bindLinks); if (this._taskLayers) { for (var i = 0; i < this._taskLayers.length; i++) { taskRenderer.removeLayer(this._taskLayers[i]); } } if (this._linkLayers) { for (var i = 0; i < this._linkLayers.length; i++) { linkRenderer.removeLayer(this._linkLayers[i]); } } this._linkLayers = []; this._taskLayers = []; }, _render_tasks_scales: function _render_tasks_scales() { var _a; var config2 = this.$getConfig(); var scales_html = "", outer_width = 0, scale_height = 0; var state = this.$gantt.getState(); if (this.isVisible()) { var helpers = this.$scaleHelper; var scales = this._getScales(); scale_height = config2.scale_height; var availWidth = this.$config.width; if (config2.autosize == "x" || config2.autosize == "xy") { availWidth = Math.max(config2.autosize_min_width, 0); } var cfgs = helpers.prepareConfigs(scales, config2.min_column_width, availWidth, scale_height - 1, state.min_date, state.max_date, config2.rtl); var cfg = this._tasks = cfgs[cfgs.length - 1]; this._scales = cfgs; this._posFromDateCache = {}; this._posFromWorkTimeCache = {}; if (this._tasks.projection && ((_a = this._tasks.projection) == null ? void 0 : _a.source) === "fixedHours") { const calendarId = "timescale-projection-calendar"; if (gantt.getCalendar(calendarId)) { gantt.deleteCalendar(calendarId); } let { hours } = this._tasks.projection; gantt.addCalendar({ id: calendarId, worktime: { hours: hours || gantt.getCalendar("global")._worktime.hours.slice(), days: [1, 1, 1, 1, 1, 1, 1] } }); } scales_html = this._getScaleChunkHtml(cfgs, 0, this.$config.width); outer_width = cfg.full_width + "px"; scale_height += "px"; } this.$task_scale.style.height = scale_height; this.$task_data.style.width = this.$task_scale.style.width = outer_width; this.$task_scale.innerHTML = scales_html; }, _getScaleChunkHtml: function _get_scale_chunk_html(scales, fromPos, toPos) { var templates2 = this.$gantt.templates; var html = []; var css = templates2.scale_row_class; for (var i = 0; i < scales.length; i++) { var cssClass = "gantt_scale_line"; var tplClass = css(scales[i]); if (tplClass) { cssClass += " " + tplClass; } html.push('
' + this._prepareScaleHtml(scales[i], fromPos, toPos, i) + "
"); } return html.join(""); }, _prepareScaleHtml: function _prepare_scale_html(config2, fromPos, toPos, index) { var globalConfig = this.$getConfig(); var globalTemplates = this.$gantt.templates; var cells = []; var date2 = null, css = null; var content = config2.format || config2.template || config2.date; if (typeof content === "string") { content = this.$gantt.date.date_to_str(content); } var startIndex = 0, endIndex = config2.count; if (globalConfig.smart_scales && (!isNaN(fromPos) && !isNaN(toPos))) { startIndex = findBinary(config2.left, fromPos); endIndex = findBinary(config2.left, toPos) + 1; } css = config2.css || function() { }; if (!config2.css && globalConfig.inherit_scale_class) { css = globalTemplates.scale_cell_class; } for (var i = startIndex; i < endIndex; i++) { if (!config2.trace_x[i]) break; date2 = new Date(config2.trace_x[i]); var value = content.call(this, date2), width = config2.width[i]; config2.height; var left = config2.left[i], style = "", template = "", cssclass = ""; if (width) { var position = globalConfig.smart_scales ? "position:absolute;left:" + left + "px" : ""; style = "width:" + width + "px;" + position; const viewPort = this.getViewPort(); const floatConfig = (globalConfig.scales[index] || {}).sticky; let labelPosition = ""; const approxLabelWidth = 70; if (floatConfig !== false && width > approxLabelWidth || floatConfig === true) { if (left < viewPort.x && left + width / 2 - approxLabelWidth / 2 < viewPort.x) { labelPosition = ` style='position:absolute;left: ${viewPort.x - left + 10}px;' `; } else if (left + width / 2 + approxLabelWidth / 2 > viewPort.x_end && width > approxLabelWidth) { let labelPos = viewPort.x_end - left - 10; let translateValue = "-100%"; if (labelPos < approxLabelWidth) { labelPos = approxLabelWidth; translateValue = `-${labelPos}px`; } labelPosition = ` style='position:absolute;left: ${labelPos}px;transform: translate(${translateValue},0);' `; } } cssclass = "gantt_scale_cell" + (i == config2.count - 1 ? " gantt_last_cell" : ""); template = css.call(this, date2); if (template) cssclass += " " + template; var ariaAttr = this.$gantt._waiAria.getTimelineCellAttr(value); var cell = `
${value}
`; cells.push(cell); } } return cells.join(""); }, _getPositioningContext: function(task) { if (this._tasks.unit === this.$gantt.config.duration_unit) { return null; } if (this._tasks.unit !== "day" && this._tasks.unit !== "week") { return null; } if (!this._tasks.projection) { return null; } const { source } = this._tasks.projection || {}; if (source === "taskCalendar") { if (!task) { return { calendar: gantt.getCalendar("global") }; } return { calendar: gantt.getTaskCalendar(task) }; } if (source === "fixedHours") { return { calendar: gantt.getCalendar("timescale-projection-calendar") }; } return null; }, dateFromPos: function dateFromPos(x, context) { var scale = this._tasks; if (x < 0 || x > scale.full_width || !scale.full_width) { return null; } var ind = findBinary(this._tasks.left, x); var summ = this._tasks.left[ind]; var col_width = scale.width[ind] || scale.col_width; var part = 0; if (col_width) { part = (x - summ) / col_width; if (scale.rtl) { part = 1 - part; } } const calendar = (context ? context.calendar : null) || null; var unit = 0; if (part) { unit = this._getColumnDuration(scale, scale.trace_x[ind]); } const cellStartDate = scale.trace_x[ind]; const absolutePositionDate = new Date(scale.trace_x[ind].valueOf() + Math.round(part * unit)); if (!calendar) { return absolutePositionDate; } const { start: trimStartSec, end: cellEnd, duration: cellDuration, intervals } = this._getWorkTrimForCell(cellStartDate, calendar); if (cellDuration <= 0) { return absolutePositionDate; } const secondsInsideTrim = Math.round(part * cellDuration); const mappedTimestampMs = cellStartDate.valueOf() + (trimStartSec + secondsInsideTrim) * 1e3; return new Date(mappedTimestampMs); }, posFromDate: function posFromDate(date2, context) { if (!this.isVisible()) return 0; if (!date2) { return 0; } if (context && context.calendar) { return this.posFromWorkTime(date2, context); } var dateValue = String(date2.valueOf()); if (this._posFromDateCache[dateValue] !== void 0) { return this._posFromDateCache[dateValue]; } var ind = this.columnIndexByDate(date2); this.$gantt.assert(ind >= 0, "Invalid day index"); var wholeCells = Math.floor(ind); var partCell = ind % 1; var pos = this._tasks.left[Math.min(wholeCells, this._tasks.width.length - 1)]; if (wholeCells == this._tasks.width.length) pos += this._tasks.width[this._tasks.width.length - 1]; if (partCell) { if (wholeCells < this._tasks.width.length) { pos += this._tasks.width[wholeCells] * (partCell % 1); } else { pos += 1; } } var roundPos = Math.round(pos); this._posFromDateCache[dateValue] = roundPos; return Math.round(roundPos); }, _getWorkTrimForCell: function(cellStartDate, calendar) { const cellDurationMs = this._getColumnDuration(this._tasks, cellStartDate); const cellEndDate = new Date(cellStartDate.valueOf() + cellDurationMs); let earliestWorkSecondInCell = null; let latestWorkSecondInCell = null; const intervalsSinceCellStart = []; for (let dayDate = new Date(cellStartDate), dayIndex = 0; dayDate < cellEndDate; dayDate = this.$gantt.date.add(dayDate, 1, "day"), dayIndex++) { const dayIntervals = calendar._getWorkHours(dayDate) || []; const dayStartOffsetSeconds = Math.round((dayDate - cellStartDate) / 1e3); for (let i = 0; i < dayIntervals.length; i++) { const absoluteStartSeconds = dayStartOffsetSeconds + dayIntervals[i].start; const absoluteEndSeconds = dayStartOffsetSeconds + dayIntervals[i].end; intervalsSinceCellStart.push({ start: absoluteStartSeconds, end: absoluteEndSeconds }); if (earliestWorkSecondInCell === null || absoluteStartSeconds < earliestWorkSecondInCell) { earliestWorkSecondInCell = absoluteStartSeconds; } if (latestWorkSecondInCell === null || absoluteEndSeconds > latestWorkSecondInCell) { latestWorkSecondInCell = absoluteEndSeconds; } } } if (earliestWorkSecondInCell === null || latestWorkSecondInCell === null || latestWorkSecondInCell <= earliestWorkSecondInCell) { return { start: 0, end: 0, duration: 0, intervals: [] }; } return { start: earliestWorkSecondInCell, end: latestWorkSecondInCell, duration: latestWorkSecondInCell - earliestWorkSecondInCell, intervals: intervalsSinceCellStart }; }, posFromWorkTime: function(date2, { calendar }) { if (!this.isVisible()) return 0; if (!date2) { return 0; } if (!calendar) { return this.posFromDate(date2); } const cacheKey = (calendar ? calendar.id : "") + String(date2.valueOf()); if (this._posFromWorkTimeCache[cacheKey] !== void 0) { return this._posFromWorkTimeCache[cacheKey]; } const index = this.columnIndexByDate(date2); this.$gantt.assert(index >= 0, "Invalid day index"); const dayIndex = Math.floor(index); const wholeCells = dayIndex; const cellStartDate = this._tasks.trace_x[dayIndex]; new Date(cellStartDate.valueOf() + this._getColumnDuration(this._tasks, cellStartDate)); const { start: workintervalStart, end: workintervalEnd, duration: cellDuration } = this._getWorkTrimForCell(date2, calendar); if (cellDuration === 0) { const result = this.posFromDate(date2); return result; } const cellStart = this._tasks.trace_x[dayIndex]; const dateOffset = (date2 - cellStart) / 1e3; let fraction = 0; if (dateOffset <= workintervalStart) { fraction = 0; } else if (dateOffset >= workintervalEnd) { fraction = 1; } else { fraction = (dateOffset - workintervalStart) / cellDuration; } if (this._tasks.rtl) { fraction = 1 - fraction; } const posLeft = this._tasks.left[Math.min(wholeCells, this._tasks.width.length - 1)]; const cellWidth = wholeCells < this._tasks.width.length ? this._tasks.width[wholeCells] : this._tasks.width[this._tasks.width.length - 1]; const pos = Math.round(posLeft + cellWidth * fraction); return pos; }, _getNextVisibleColumn: function(startIndex, columns, ignores) { var date2 = +columns[startIndex]; var visibleDateIndex = startIndex; while (ignores[date2]) { visibleDateIndex++; date2 = +columns[visibleDateIndex]; } return visibleDateIndex; }, _getPrevVisibleColumn: function(startIndex, columns, ignores) { var date2 = +columns[startIndex]; var visibleDateIndex = startIndex; while (ignores[date2]) { visibleDateIndex--; date2 = +columns[visibleDateIndex]; } return visibleDateIndex; }, _getClosestVisibleColumn: function(startIndex, columns, ignores) { var visibleDateIndex = this._getNextVisibleColumn(startIndex, columns, ignores); if (!columns[visibleDateIndex]) { visibleDateIndex = this._getPrevVisibleColumn(startIndex, columns, ignores); } return visibleDateIndex; }, columnIndexByDate: function columnIndexByDate(date2) { var pos = new Date(date2).valueOf(); var days = this._tasks.trace_x_ascending, ignores = this._tasks.ignore_x; var state = this.$gantt.getState(); if (pos <= state.min_date) { if (this._tasks.rtl) { return days.length; } else { return 0; } } if (pos >= state.max_date) { if (this._tasks.rtl) { return 0; } else { return days.length; } } var dateIndex = findBinary(days, pos); var visibleIndex = this._getClosestVisibleColumn(dateIndex, days, ignores); var visibleDate = days[visibleIndex]; var transition = this._tasks.trace_index_transition; if (!visibleDate) { if (transition) { return transition[0]; } else { return 0; } } var part = (date2 - days[visibleIndex]) / this._getColumnDuration(this._tasks, days[visibleIndex]); if (transition) { return transition[visibleIndex] + (1 - part); } else { return visibleIndex + part; } }, getItemPosition: function(task, start_date, end_date) { var xLeft, xRight, width; let displayStart = start_date || task.start_date || task.$auto_start_date; let displayEnd = end_date || task.end_date || task.$auto_end_date; const context = this._getPositioningContext(task); if (context && context.calendar) { if (this._tasks.rtl) { xRight = this.posFromWorkTime(displayStart, context); xLeft = this.posFromWorkTime(displayEnd, context); } else { xLeft = this.posFromWorkTime(displayStart, context); xRight = this.posFromWorkTime(displayEnd, context); } } else { if (this._tasks.rtl) { xRight = this.posFromDate(displayStart); xLeft = this.posFromDate(displayEnd); } else { xLeft = this.posFromDate(displayStart); xRight = this.posFromDate(displayEnd); } } width = Math.max(xRight - xLeft, 0); var y = this.getItemTop(task.id); var height = this.getBarHeight(task.id); var rowHeight = this.getItemHeight(task.id); return { left: xLeft, top: y, height, width, rowHeight }; }, getBarHeight: function(taskId, isMilestoneRender) { var config2 = this.$getConfig(); var task = this.$config.rowStore.getItem(taskId); var height = task.task_height || task.bar_height || config2.bar_height || config2.task_height; var rowHeight = this.getItemHeight(taskId); if (height == "full") { var offset = config2.bar_height_padding || 3; height = rowHeight - offset; } height = Math.min(height, rowHeight); if (isMilestoneRender) { height = Math.round(height / Math.sqrt(2)); } return Math.max(height, 0); }, getScale: function() { return this._tasks; }, _getScales: function _get_scales() { var config2 = this.$getConfig(); var helpers = this.$scaleHelper; var scales = [helpers.primaryScale(config2)].concat(helpers.getAdditionalScales(config2)); helpers.sortScales(scales); return scales; }, _getColumnDuration: function _get_coll_duration(scale, date2) { return this.$gantt.date.add(date2, scale.step, scale.unit) - date2; }, _bindStore: function() { if (this.$config.bind) { var rowStore = this.$gantt.getDatastore(this.$config.bind); this.$config.rowStore = rowStore; if (rowStore && !rowStore._timelineCacheAttached) { var self2 = this; rowStore._timelineCacheAttached = rowStore.attachEvent("onBeforeFilter", function() { self2._resetTopPositionHeight(); }); } } }, _unbindStore: function() { if (this.$config.bind) { var rowStore = this.$gantt.getDatastore(this.$config.bind); if (rowStore && rowStore._timelineCacheAttached) { rowStore.detachEvent(rowStore._timelineCacheAttached); rowStore._timelineCacheAttached = false; } } }, refresh: function() { this._bindStore(); if (this.$config.bindLinks) { this.$config.linkStore = this.$gantt.getDatastore(this.$config.bindLinks); } this._resetTopPositionHeight(); this._resetHeight(); this._initStaticBackgroundRender(); this._render_tasks_scales(); }, destructor: function() { var gantt2 = this.$gantt; this._clearLayers(gantt2); this._unbindStore(); this.$task = null; this.$task_scale = null; this.$task_data = null; this.$task_bg = null; this.$task_links = null; this.$task_bars = null; this.$gantt = null; if (this.$config.rowStore) { this.$config.rowStore.detachEvent(this._staticBgHandler); this.$config.rowStore = null; } if (this.$config.linkStore) { this.$config.linkStore = null; } if (this._timelineDragScroll) { this._timelineDragScroll.destructor(); this._timelineDragScroll = null; } this.callEvent("onDestroy", []); this.detachAllEvents(); } }; function createResizer(gantt2, grid) { return { init: function() { }, doOnRender: function() { } }; } function createRowResizer(gantt2, grid) { var _task_grid_row_resize = { row_before_start: gantt2.bind(function(dnd, obj, e) { var config2 = grid.$getConfig(); var store = grid.$config.rowStore; var el = locateAttribute(e, config2.task_grid_row_resizer_attribute); if (!el) return false; var row_id = this.locate(e, config2.task_grid_row_resizer_attribute), row = store.getItem(row_id); if (grid.callEvent("onBeforeRowResize", [row]) === false) return false; }, gantt2), row_after_start: gantt2.bind(function(dnd, obj, e) { var config2 = grid.$getConfig(); var row_id = this.locate(e, config2.task_grid_row_resizer_attribute); dnd.config.marker.innerHTML = ""; dnd.config.marker.className += " gantt_row_grid_resize_area"; dnd.config.marker.style.width = grid.$grid.offsetWidth + "px"; dnd.config.drag_id = row_id; }, gantt2), row_drag_move: gantt2.bind(function(dnd, obj, e) { var store = grid.$config.rowStore; var config2 = grid.$getConfig(); var dd = dnd.config; var id = dd.drag_id, itemHeight = grid.getItemHeight(id), itemTop = grid.getItemTop(id) - obj.scrollTop; var pos = getNodePosition(grid.$grid_data), pointerPosition = parseInt(dd.marker.style.top, 10), markerStartPosition = itemTop + pos.y, marker_height = 0, minPointerPosition = config2.min_task_grid_row_height; marker_height = pointerPosition - markerStartPosition; if (marker_height < minPointerPosition) { marker_height = minPointerPosition; } dd.marker.style.left = pos.x + "px"; dd.marker.style.top = markerStartPosition - 1 + "px"; dd.marker.style.height = Math.abs(marker_height) + 1 + "px"; dd.marker_height = marker_height; grid.callEvent("onRowResize", [id, store.getItem(id), marker_height + itemHeight]); return true; }, gantt2), row_drag_end: gantt2.bind(function(dnd, obj, e) { var store = grid.$config.rowStore; var dd = dnd.config; var id = dd.drag_id, item = store.getItem(id), oldItemHeight = grid.getItemHeight(id); var finalHeight = dd.marker_height; if (grid.callEvent("onBeforeRowResizeEnd", [id, item, finalHeight]) === false) return; if (item.row_height == finalHeight) return; item.row_height = finalHeight; store.updateItem(id); grid.callEvent("onAfterRowResize", [id, item, oldItemHeight, finalHeight]); this.render(); }, gantt2) }; var _init_resize = function() { var DnD2 = gantt2.$services.getService("dnd"); var config2 = grid.$getConfig(); var dnd = new DnD2(grid.$grid_data, { updates_per_second: 60 }); if (gantt2.defined(config2.dnd_sensitivity)) dnd.config.sensitivity = config2.dnd_sensitivity; dnd.attachEvent("onBeforeDragStart", function(obj, e) { return _task_grid_row_resize.row_before_start(dnd, obj, e); }); dnd.attachEvent("onAfterDragStart", function(obj, e) { return _task_grid_row_resize.row_after_start(dnd, obj, e); }); dnd.attachEvent("onDragMove", function(obj, e) { return _task_grid_row_resize.row_drag_move(dnd, obj, e); }); dnd.attachEvent("onDragEnd", function(obj, e) { return _task_grid_row_resize.row_drag_end(dnd, obj, e); }); }; return { init: _init_resize }; } const SENSITIVITY = 20; const TIMEOUT = 50; const SCROLLSTEP = 10; class ScrollableGrid { constructor(params) { this._scrollOrder = 0; const { gantt: gantt2, grid, dnd, getCurrentX } = params; this.$gantt = gantt2; this.$grid = grid; this._dnd = dnd; this.getCurrentX = getCurrentX; this._scrollView = this.$gantt.$ui.getView(this.$grid.$config.scrollX); this.attachEvents(); } attachEvents() { if (this.isScrollable()) { this._dnd.attachEvent("onDragMove", (obj, e) => { const gridBoundingRect = this.$grid.$grid.getBoundingClientRect(); const maxLeft = gridBoundingRect.right; const minLeft = gridBoundingRect.left; const currentX = this.getCurrentX(e.clientX); if (currentX >= maxLeft - SENSITIVITY) { this.autoscrollRight(); this.autoscrollStart(); } if (currentX <= minLeft + SENSITIVITY) { this.autoscrollLeft(); this.autoscrollStart(); } if (currentX < maxLeft - SENSITIVITY && currentX > minLeft + SENSITIVITY) { this.autoscrollStop(); } return true; }); this._dnd.attachEvent("onDragEnd", () => { this.autoscrollStop(); }); } } autoscrollStart() { if (this._scrollOrder === 0) { return; } const scrollStep = SCROLLSTEP * this._scrollOrder; const scrollState = this._scrollView.getScrollState(); this._scrollView.scrollTo(scrollState.position + scrollStep); setTimeout(() => { this.autoscrollStart(); }, TIMEOUT); } autoscrollRight() { this._scrollOrder = 1; } autoscrollLeft() { this._scrollOrder = -1; } autoscrollStop() { this._scrollOrder = 0; } getCorrection() { if (!this.isScrollable()) { return 0; } return this._scrollView.getScrollState().position; } isScrollable() { return !!this.$grid.$config.scrollable; } } const COLUMN_ID_ATTR_NAME = "data-column-id"; class ColumnsGridDnd { constructor(gantt2, grid) { this._targetMarker = null; this.calculateCurrentPosition = (eventX) => { const gridBoundingRect = this.$grid.$grid.getBoundingClientRect(); const maxLeft = gridBoundingRect.right; const minLeft = gridBoundingRect.left; let x = eventX; if (x > maxLeft) { x = maxLeft; } if (x < minLeft) { x = minLeft; } return x; }; this.$gantt = gantt2; this.$grid = grid; } init() { const DND = this.$gantt.$services.getService("dnd"); this._dnd = new DND(this.$grid.$grid_scale, { updates_per_second: 60 }); this._scrollableGrid = new ScrollableGrid({ gantt: this.$gantt, grid: this.$grid, dnd: this._dnd, getCurrentX: this.calculateCurrentPosition }); this.attachEvents(); } attachEvents() { this._dnd.attachEvent("onBeforeDragStart", (obj, e) => { this._draggedCell = this.$gantt.utils.dom.closest(e.target, ".gantt_grid_head_cell"); if (!this._draggedCell) { return; } const columns = this.$grid.$getConfig().columns; const columnName = this._draggedCell.getAttribute(COLUMN_ID_ATTR_NAME); let draggedColumn; let draggedIndex; columns.map(function(column, index) { if (column.name === columnName) { draggedColumn = column; draggedIndex = index; } }); if (this.$grid.callEvent("onBeforeColumnDragStart", [{ draggedColumn, draggedIndex }]) === false) { return false; } if (!this._draggedCell || !draggedColumn) { return false; } this._gridConfig = this.$grid.$getConfig(); this._originAutoscroll = this.$gantt.config.autoscroll; this.$gantt.config.autoscroll = false; return true; }); this._dnd.attachEvent("onAfterDragStart", (obj, e) => { if (!this._draggedCell) { return; } this._dnd.config.column = this._draggedCell.getAttribute(COLUMN_ID_ATTR_NAME); this._dnd.config.marker.innerHTML = this._draggedCell.outerHTML; this._dnd.config.marker.classList.add("gantt_column_drag_marker"); this._dnd.config.marker.style.height = this._gridConfig.scale_height + "px"; this._dnd.config.marker.style.lineHeight = this._gridConfig.scale_height + "px"; this._draggedCell.classList.add("gantt_grid_head_cell_dragged"); }); this._dnd.attachEvent("onDragMove", (obj, e) => { if (!this._draggedCell) { return; } this._dragX = e.clientX; const x = this.calculateCurrentPosition(e.clientX); const columnIndexes = this.findColumnsIndexes(); this.setMarkerPosition(x); this.drawTargetMarker(columnIndexes); return true; }); this._dnd.attachEvent("onDragEnd", () => { if (!this._draggedCell) { return; } const columnIndexes = this.findColumnsIndexes(); const targetIndex = columnIndexes.targetIndex; const draggedIndex = columnIndexes.draggedIndex; const columns = this.$grid.$getConfig().columns; const draggedColumn = columns[draggedIndex]; const targetColumn = columns[targetIndex]; if (this.$grid.callEvent("onColumnDragMove", [{ draggedColumn, targetColumn, draggedIndex, targetIndex }]) === false) { this.cleanTargetMarker(); this.$gantt.render(); return; } this.$gantt.config.autoscroll = this._originAutoscroll; this._draggedCell.classList.remove("gantt_grid_head_cell_dragged"); this.cleanTargetMarker(); this.reorderColumns(); }); } reorderColumns() { const { targetIndex, draggedIndex } = this.findColumnsIndexes(); const columns = this.$grid.$getConfig().columns; const draggedColumn = columns[draggedIndex]; const targetColumn = columns[targetIndex]; if (this.$grid.callEvent("onBeforeColumnReorder", [{ draggedColumn, targetColumn, draggedIndex, targetIndex }]) === false) { return; } if (targetIndex === draggedIndex) { return; } columns.splice(draggedIndex, 1); columns.splice(targetIndex, 0, draggedColumn); this.$gantt.render(); this.$grid.callEvent("onAfterColumnReorder", [{ draggedColumn, targetColumn, draggedIndex, targetIndex }]); } findColumnsIndexes() { const draggedId = this._dnd.config.column; const columns = this.$grid.$getConfig().columns; let targetIndex; let draggedIndex; let xBefore; let xAfter; const currentColumn = { startX: 0, endX: 0 }; let start = 0; let end = columns.length - 1; let compare = (a, b) => a <= b; let next = (index) => ++index; if (this.$gantt.config.rtl) { start = columns.length - 1; end = 0; compare = (a, b) => a >= b; next = (index) => --index; } let columnRelativePos; const relativeX = this._dragX - this.$grid.$grid.getBoundingClientRect().left + this._scrollableGrid.getCorrection(); for (let i = start; compare(i, end); i = next(i)) { if (targetIndex !== void 0 && draggedIndex !== void 0) { break; } if (!columns[i].hide) { currentColumn.startX = currentColumn.endX; currentColumn.endX += columns[i].width; if (relativeX >= currentColumn.startX && (relativeX <= currentColumn.endX || !compare(next(i), end))) { targetIndex = i; xBefore = currentColumn.startX; xAfter = currentColumn.endX; columnRelativePos = (relativeX - currentColumn.startX) / (currentColumn.endX - currentColumn.startX); } if (draggedId === columns[i].name) { draggedIndex = i; } } } return { targetIndex, draggedIndex, xBefore, xAfter, columnRelativePos }; } setMarkerPosition(x, y = 10) { const { marker: marker2 } = this._dnd.config; const gridOffset = this._dnd._obj.getBoundingClientRect(); marker2.style.top = `${gridOffset.y + y}px`; marker2.style.left = `${x}px`; } drawTargetMarker({ targetIndex, draggedIndex, xBefore, xAfter, columnRelativePos }) { if (!this._targetMarker) { this._targetMarker = document.createElement("div"); addClassName(this._targetMarker, "gantt_grid_target_marker"); this._targetMarker.style.display = "none"; this._targetMarker.style.height = `${this._gridConfig.scale_height}px`; } if (!this._targetMarker.parentNode) { this.$grid.$grid_scale.appendChild(this._targetMarker); } let nextPosition; if (targetIndex > draggedIndex) { nextPosition = xAfter; } else if (targetIndex < draggedIndex) { nextPosition = xBefore; } else { if (columnRelativePos > 0.5) { nextPosition = xAfter; } else { nextPosition = xBefore; } } this._targetMarker.style.left = `${nextPosition}px`; this._targetMarker.style.display = "block"; } cleanTargetMarker() { if (this._targetMarker && this._targetMarker.parentNode) { this.$grid.$grid_scale.removeChild(this._targetMarker); } this._targetMarker = null; } } function create$1(gantt2) { var events = []; return { delegate: function(event2, className, handler, root) { events.push([event2, className, handler, root]); var helper = gantt2.$services.getService("mouseEvents"); helper.delegate(event2, className, handler, root); }, destructor: function() { var mouseEvents2 = gantt2.$services.getService("mouseEvents"); for (var i = 0; i < events.length; i++) { var h = events[i]; mouseEvents2.detach(h[0], h[1], h[2], h[3]); } events = []; } }; } var Grid = function(parent, config2, factory2, gantt2) { this.$config = mixin({}, config2 || {}); this.$gantt = gantt2; this.$parent = parent; makeEventable(this); this.$state = {}; mixin(this, createMixin$1(this)); }; Grid.prototype = { init: function(container) { var gantt2 = this.$gantt; var gridAriaAttr = gantt2._waiAria.gridAttrString(); var gridDataAriaAttr = gantt2._waiAria.gridDataAttrString(); var _ganttConfig = this.$getConfig(); var reorderColumns = _ganttConfig.reorder_grid_columns || false; if (this.$config.reorder_grid_columns !== void 0) { reorderColumns = this.$config.reorder_grid_columns; } container.innerHTML = "
"; this.$grid = container.childNodes[0]; this.$grid.innerHTML = "
"; this.$grid_scale = this.$grid.childNodes[0]; this.$grid_data = this.$grid.childNodes[1]; var attr = _ganttConfig[this.$config.bind + "_attribute"]; if (!attr && this.$config.bind) { attr = "data-" + this.$config.bind + "-id"; } this.$config.item_attribute = attr || null; if (!this.$config.layers) { var layers = this._createLayerConfig(); this.$config.layers = layers; } var resizer = createResizer(); this._renderHeaderResizers = resizer.doOnRender; this._mouseDelegates = create$1(gantt2); var resizerrow = createRowResizer(gantt2, this); resizerrow.init(); this._addLayers(this.$gantt); this._initEvents(); if (reorderColumns) { this._columnDND = new ColumnsGridDnd(gantt2, this); this._columnDND.init(); } this.callEvent("onReady", []); }, _validateColumnWidth: function(column, property) { var value = column[property]; if (value && value != "*") { var gantt2 = this.$gantt; var numericWidth = value * 1; if (isNaN(numericWidth)) { gantt2.assert(false, "Wrong " + property + " value of column " + column.name); } else { column[property] = numericWidth; } } }, setSize: function(width, height) { this.$config.width = this.$state.width = width; this.$config.height = this.$state.height = height; var columns = this.getGridColumns(), innerWidth = 0; var config2 = this.$getConfig(); var elasticColumns = config2.grid_elastic_columns; for (var i = 0, l = columns.length; i < l; i++) { this._validateColumnWidth(columns[i], "min_width"); this._validateColumnWidth(columns[i], "max_width"); this._validateColumnWidth(columns[i], "width"); innerWidth += columns[i].width * 1; } var outerWidth; if (isNaN(innerWidth) || !this.$config.scrollable) { outerWidth = this._setColumnsWidth(width + 1); innerWidth = outerWidth; } if (this.$config.scrollable && elasticColumns && !isNaN(innerWidth)) { let columnProperty = "width"; if (elasticColumns == "min_width") { columnProperty = "min_width"; } let newColumnWidth = 0; columns.forEach(function(col) { newColumnWidth += col[columnProperty] || config2.min_grid_column_width; }); var columnsWidth = Math.max(newColumnWidth, width); innerWidth = this._setColumnsWidth(columnsWidth); outerWidth = width; } if (this.$config.scrollable) { this.$grid_scale.style.width = innerWidth + "px"; this.$grid_data.style.width = innerWidth + "px"; } else { this.$grid_scale.style.width = "inherit"; this.$grid_data.style.width = "inherit"; } this.$config.width -= 1; var config2 = this.$getConfig(); if (outerWidth !== width) { if (outerWidth !== void 0) { config2.grid_width = outerWidth; this.$config.width = outerWidth - 1; } else { if (!isNaN(innerWidth)) { this._setColumnsWidth(innerWidth); config2.grid_width = innerWidth; this.$config.width = innerWidth - 1; } } } var dataHeight = Math.max(this.$state.height - config2.scale_height, 0); this.$grid_data.style.height = dataHeight + "px"; this.refresh(); }, getSize: function() { var config2 = this.$getConfig(); var store = this.$config.rowStore; var contentHeight = store ? this.getTotalHeight() : 0, contentWidth = this._getGridWidth(); var size = { x: this.$state.width, y: this.$state.height, contentX: this.isVisible() ? contentWidth : 0, contentY: this.isVisible() ? config2.scale_height + contentHeight : 0, scrollHeight: this.isVisible() ? contentHeight : 0, scrollWidth: this.isVisible() ? contentWidth : 0 }; return size; }, _bindStore: function() { if (this.$config.bind) { var rowStore = this.$gantt.getDatastore(this.$config.bind); this.$config.rowStore = rowStore; if (rowStore && !rowStore._gridCacheAttached) { var self2 = this; rowStore._gridCacheAttached = rowStore.attachEvent("onBeforeFilter", function() { self2._resetTopPositionHeight(); }); } } }, _unbindStore: function() { if (this.$config.bind) { var rowStore = this.$gantt.getDatastore(this.$config.bind); if (rowStore && rowStore._gridCacheAttached) { rowStore.detachEvent(rowStore._gridCacheAttached); rowStore._gridCacheAttached = false; } } }, refresh: function() { this._bindStore(); this._resetTopPositionHeight(); this._resetHeight(); this._initSmartRenderingPlaceholder(); this._calculateGridWidth(); this._renderGridHeader(); }, getViewPort: function() { var scrollLeft = this.$config.scrollLeft || 0; var scrollTop = this.$config.scrollTop || 0; var height = this.$config.height || 0; var width = this.$config.width || 0; return { y: scrollTop, y_end: scrollTop + height, x: scrollLeft, x_end: scrollLeft + width, height, width }; }, scrollTo: function(left, top) { if (!this.isVisible()) return; var scrolled = false; this.$config.scrollTop = this.$config.scrollTop || 0; this.$config.scrollLeft = this.$config.scrollLeft || 0; if (left * 1 == left) { this.$config.scrollLeft = this.$state.scrollLeft = this.$grid.scrollLeft = left; scrolled = true; } if (top * 1 == top) { this.$config.scrollTop = this.$state.scrollTop = this.$grid_data.scrollTop = top; scrolled = true; } if (scrolled) { this.callEvent("onScroll", [this.$config.scrollLeft, this.$config.scrollTop]); } }, getColumnIndex: function(name, excludeHidden) { var columns = this.$getConfig().columns; var hiddenIndexShift = 0; for (var i = 0; i < columns.length; i++) { if (excludeHidden && columns[i].hide) { hiddenIndexShift++; } if (columns[i].name == name) { return i - hiddenIndexShift; } } return null; }, getColumn: function(name) { var index = this.getColumnIndex(name); if (index === null) { return null; } return this.$getConfig().columns[index]; }, getGridColumns: function() { var config2 = this.$getConfig(); return config2.columns.slice(); }, isVisible: function() { if (this.$parent && this.$parent.$config) { return !this.$parent.$config.hidden; } else { return this.$grid.offsetWidth; } }, _createLayerConfig: function() { var gantt2 = this.$gantt; var self2 = this; var layers = [{ renderer: gantt2.$ui.layers.gridLine(), container: this.$grid_data, filter: [function() { return self2.isVisible(); }] }, { renderer: gantt2.$ui.layers.gridTaskRowResizer(), container: this.$grid_data, append: true, filter: [function() { return gantt2.config.resize_rows; }] }]; return layers; }, _addLayers: function(gantt2) { if (!this.$config.bind) return; this._taskLayers = []; var self2 = this; var layers = this.$gantt.$services.getService("layers"); var taskRenderer = layers.getDataRender(this.$config.bind); if (!taskRenderer) { taskRenderer = layers.createDataRender({ name: this.$config.bind, defaultContainer: function() { return self2.$grid_data; } }); } var taskLayers2 = this.$config.layers; for (var i = 0; taskLayers2 && i < taskLayers2.length; i++) { var layer = taskLayers2[i]; layer.view = this; var bar_layer = taskRenderer.addLayer(layer); this._taskLayers.push(bar_layer); } this._bindStore(); this._initSmartRenderingPlaceholder(); }, _refreshPlaceholderOnStoreUpdate: function(id) { var config2 = this.$getConfig(), store = this.$config.rowStore; if (!store || id !== null || !this.isVisible() || !config2.smart_rendering) { return; } var contentHeight; if (this.$config.scrollY) { var scroll = this.$gantt.$ui.getView(this.$config.scrollY); if (scroll) contentHeight = scroll.getScrollState().scrollSize; } if (!contentHeight) { contentHeight = store ? this.getTotalHeight() : 0; } if (contentHeight) { if (this.$rowsPlaceholder && this.$rowsPlaceholder.parentNode) { this.$rowsPlaceholder.parentNode.removeChild(this.$rowsPlaceholder); } var placeholder = this.$rowsPlaceholder = document.createElement("div"); placeholder.style.visibility = "hidden"; placeholder.style.height = contentHeight + "px"; placeholder.style.width = "1px"; this.$grid_data.appendChild(placeholder); } }, _initSmartRenderingPlaceholder: function() { var store = this.$config.rowStore; if (!store) { return; } else { this._initSmartRenderingPlaceholder = function() { }; } this._staticBgHandler = store.attachEvent("onStoreUpdated", bind(this._refreshPlaceholderOnStoreUpdate, this)); }, _initEvents: function() { var gantt2 = this.$gantt; this._mouseDelegates.delegate("click", "gantt_close", gantt2.bind(function(e, id, trg) { var store = this.$config.rowStore; if (!store) return true; var target = locateAttribute(e, this.$config.item_attribute); if (target) { store.close(target.getAttribute(this.$config.item_attribute)); } return false; }, this), this.$grid); this._mouseDelegates.delegate("click", "gantt_open", gantt2.bind(function(e, id, trg) { var store = this.$config.rowStore; if (!store) return true; var target = locateAttribute(e, this.$config.item_attribute); if (target) { store.open(target.getAttribute(this.$config.item_attribute)); } return false; }, this), this.$grid); }, _clearLayers: function(gantt2) { var layers = this.$gantt.$services.getService("layers"); var taskRenderer = layers.getDataRender(this.$config.bind); if (this._taskLayers) { for (var i = 0; i < this._taskLayers.length; i++) { taskRenderer.removeLayer(this._taskLayers[i]); } } this._taskLayers = []; }, _getColumnWidth: function(column, config2, width) { var min_width = column.min_width || config2.min_grid_column_width; var new_width = Math.max(width, min_width || 10); if (column.max_width) new_width = Math.min(new_width, column.max_width); return new_width; }, _checkGridColumnMinWidthLimits: function(columns, config2) { for (var i = 0, l = columns.length; i < l; i++) { var width = columns[i].width * 1; if (!columns[i].min_width && width < config2.min_grid_column_width) { columns[i].min_width = width; } } }, _getGridWidthLimits: function() { var config2 = this.$getConfig(), columns = this.getGridColumns(), min_limit = 0, max_limit = 0; for (var i = 0; i < columns.length; i++) { min_limit += columns[i].min_width ? columns[i].min_width : config2.min_grid_column_width; if (max_limit !== void 0) { max_limit = columns[i].max_width ? max_limit + columns[i].max_width : void 0; } } this._checkGridColumnMinWidthLimits(columns, config2); return [min_limit, max_limit]; }, _setColumnsWidth: function(newWidth, start_index) { var config2 = this.$getConfig(); var columns = this.getGridColumns(), columns_width = 0, final_width = newWidth; start_index = !window.isNaN(start_index) ? start_index : -1; for (var i = 0, l = columns.length; i < l; i++) { columns_width += columns[i].width * 1; } if (window.isNaN(columns_width)) { this._calculateGridWidth(); columns_width = 0; for (var i = 0, l = columns.length; i < l; i++) { columns_width += columns[i].width * 1; } } var extra_width = final_width - columns_width; var start_width = 0; for (var i = 0; i < start_index + 1; i++) { start_width += columns[i].width; } columns_width -= start_width; for (var i = start_index + 1; i < columns.length; i++) { var col = columns[i]; var share = Math.round(extra_width * (col.width / columns_width)); if (extra_width < 0) { if (col.min_width && col.width + share < col.min_width) share = col.min_width - col.width; else if (!col.min_width && config2.min_grid_column_width && col.width + share < config2.min_grid_column_width) share = config2.min_grid_column_width - col.width; } else if (col.max_width && col.width + share > col.max_width) share = col.max_width - col.width; columns_width -= col.width; col.width += share; extra_width -= share; } var iterator = extra_width > 0 ? 1 : -1; while (extra_width > 0 && iterator === 1 || extra_width < 0 && iterator === -1) { var curExtra = extra_width; for (i = start_index + 1; i < columns.length; i++) { var new_width = columns[i].width + iterator; if (new_width == this._getColumnWidth(columns[i], config2, new_width)) { extra_width -= iterator; columns[i].width = new_width; } if (!extra_width) break; } if (curExtra == extra_width) break; } if (extra_width && start_index > -1) { var new_width = columns[start_index].width + extra_width; if (new_width == this._getColumnWidth(columns[start_index], config2, new_width)) columns[start_index].width = new_width; } return this._getColsTotalWidth(); }, _getColsTotalWidth: function() { var columns = this.getGridColumns(); var cols_width = 0; for (var i = 0; i < columns.length; i++) { var v = parseFloat(columns[i].width); if (window.isNaN(v)) { return false; } cols_width += v; } return cols_width; }, _calculateGridWidth: function() { var config2 = this.$getConfig(); var columns = this.getGridColumns(); var cols_width = 0; var unknown = []; var width = []; for (var i = 0; i < columns.length; i++) { var v = parseFloat(columns[i].width); if (window.isNaN(v)) { v = config2.min_grid_column_width || 10; unknown.push(i); } width[i] = v; cols_width += v; } var gridWidth = this._getGridWidth() + 1; if (config2.autofit || unknown.length) { var diff = gridWidth - cols_width; if (config2.autofit && !config2.grid_elastic_columns) { for (var i = 0; i < width.length; i++) { var delta = Math.round(diff / (width.length - i)); width[i] += delta; var new_width = this._getColumnWidth(columns[i], config2, width[i]); if (new_width != width[i]) { delta = new_width - width[i]; width[i] = new_width; } diff -= delta; } } else if (unknown.length) { for (var i = 0; i < unknown.length; i++) { var delta = Math.round(diff / (unknown.length - i)); var index = unknown[i]; width[index] += delta; var new_width = this._getColumnWidth(columns[index], config2, width[index]); if (new_width != width[index]) { delta = new_width - width[index]; width[index] = new_width; } diff -= delta; } } for (var i = 0; i < width.length; i++) { columns[i].width = width[i]; } } else { var changed = gridWidth != cols_width; this.$config.width = cols_width - 1; config2.grid_width = cols_width; if (changed) { this.$parent._setContentSize(this.$config.width, null); } } }, _renderGridHeader: function() { var gantt2 = this.$gantt; var config2 = this.$getConfig(); var locale2 = this.$gantt.locale; var templates2 = this.$gantt.templates; var columns = this.getGridColumns(); if (config2.rtl) { columns = columns.reverse(); } var cells = []; var width = 0, labels = locale2.labels; var lineHeigth = config2.scale_height - 1; const renderableComponents = {}; for (var i = 0; i < columns.length; i++) { var last = i == columns.length - 1; var col = columns[i]; if (!col.name) { col.name = gantt2.uid() + ""; } var colWidth = col.width * 1; var gridWidth = this._getGridWidth(); if (last && gridWidth > width + colWidth) col.width = colWidth = gridWidth - width; width += colWidth; var sort = gantt2._sort && col.name == gantt2._sort.name ? `
` : ""; var cssClass = ["gantt_grid_head_cell", "gantt_grid_head_" + col.name, last ? "gantt_last_cell" : "", templates2.grid_header_class(col.name, col)].join(" "); var style = "width:" + (colWidth - (last ? 1 : 0)) + "px;"; var label = col.label || labels["column_" + col.name] || labels[col.name]; if (typeof label === "function") { label = label.call(gantt2, col.name, col); } label = label || ""; let componentLabel = false; if (gantt2.config.external_render && gantt2.config.external_render.isElement(label)) { componentLabel = true; renderableComponents[col.name] = label; } var ariaAttrs = gantt2._waiAria.gridScaleCellAttrString(col, label); var cell = "
" + (!componentLabel ? label : "
") + sort + "
"; cells.push(cell); } this.$grid_scale.style.height = config2.scale_height + "px"; this.$grid_scale.style.lineHeight = lineHeigth + "px"; this.$grid_scale.innerHTML = cells.join(""); for (let i2 in renderableComponents) { gantt2.config.external_render.renderElement(renderableComponents[i2], this.$grid_scale.querySelector("[data-column-id='" + i2 + "'] [data-component-container]")); } if (this._renderHeaderResizers) { this._renderHeaderResizers(); } }, _getGridWidth: function() { return this.$config.width; }, destructor: function() { this._clearLayers(this.$gantt); if (this._mouseDelegates) { this._mouseDelegates.destructor(); this._mouseDelegates = null; } this._unbindStore(); this.$grid = null; this.$grid_scale = null; this.$grid_data = null; this.$gantt = null; if (this.$config.rowStore) { this.$config.rowStore.detachEvent(this._staticBgHandler); this.$config.rowStore = null; } this.callEvent("onDestroy", []); this.detachAllEvents(); } }; function clearTaskStoreHandler(self2) { if (self2._delayRender) { self2._delayRender.$cancelTimeout(); } if (!self2.$gantt) { return; } var tasks2 = self2.$gantt.$data.tasksStore; var ownStore = self2.$config.rowStore; var handlerIdProperty = "_attached_" + ownStore.$config.name; if (self2[handlerIdProperty]) { tasks2.detachEvent(self2[handlerIdProperty]); self2[handlerIdProperty] = null; } if (ownStore.$attachedResourceViewHandler) { ownStore.detachEvent(ownStore.$attachedResourceViewHandler); ownStore.$attachedResourceViewHandler = null; tasks2.detachEvent(ownStore.$attachedTaskStoreHandler); ownStore.$attachedTaskStoreHandler = null; } } function createMixin(_super) { var initGrid = _super.prototype.init, destroyGrid = _super.prototype.destructor; return { init: function() { initGrid.apply(this, arguments); this._linkToTaskStore(); }, destructor: function() { clearTaskStoreHandler(this); destroyGrid.apply(this, arguments); }, previousDragId: null, relevantResources: null, _linkToTaskStore: function() { if (this.$config.rowStore && this.$gantt.$data.tasksStore) { var tasks2 = this.$gantt.$data.tasksStore; var ownStore = this.$config.rowStore; clearTaskStoreHandler(this); var self2 = this; var delayRender = delay(function() { if (self2.$gantt.getState().lightbox) { delayRender(); } else { const linkedStore = self2.$config.rowStore; const repaintStack = self2._getRelevantResources(); if (repaintStack && linkedStore.$config.name === self2.$gantt.config.resource_store) { if (repaintStack == "nothing_to_repaint") { return; } linkedStore._quick_refresh = true; self2.relevantResources.forEach(function(id) { linkedStore.refresh(id); }); linkedStore._quick_refresh = false; } else { linkedStore.refresh(); } } }, 300); this._delayRender = delayRender; var handlerIdProperty = "_attached_" + ownStore.$config.name; if (!self2[handlerIdProperty]) { self2[handlerIdProperty] = tasks2.attachEvent("onStoreUpdated", function() { if (!delayRender.$pending && !this._skipResourceRepaint) { const state = self2.$gantt.getState(); if (state.drag_mode == "progress") { return true; } else if (state.drag_mode && state.drag_id) { self2.previousDragId = state.drag_id; } delayRender(); } return true; }); } this.$gantt.attachEvent("onDestroy", function() { clearTaskStoreHandler(self2); return true; }); if (!ownStore.$attachedResourceViewHandler) { ownStore.$attachedResourceViewHandler = ownStore.attachEvent("onBeforeFilter", function() { if (self2.$gantt.getState().lightbox) { return false; } if (delayRender.$pending) { delayRender.$cancelTimeout(); } self2._updateNestedTasks(); return true; }); ownStore.$attachedTaskStoreHandler = tasks2.attachEvent("onAfterDelete", function() { ownStore._mark_recompute = true; }); } } }, _getRelevantResources: function() { if (!this.$gantt.getTaskAssignments) { return null; } const state = this.$gantt.getState(); const linkedStore = this.$config.rowStore; let resourceIds = []; if (state.drag_mode && state.drag_id && linkedStore.$config.name === this.$gantt.config.resource_store) { if (this.previousDragId == state.drag_id) { if (this.relevantResources) { return this.relevantResources; } else { resourceIds = this._getIdsFromAssignments(this.previousDragId); } } else { this.previousDragId = state.drag_id; resourceIds = this._getIdsFromAssignments(this.previousDragId); } } else if (this.previousDragId) { resourceIds = this._getIdsFromAssignments(this.previousDragId); this.previousDragId = null; } else { return null; } if (!resourceIds.length) { return this.relevantResources = "nothing_to_repaint"; } resourceIds.forEach(function(resourceId) { if (linkedStore.eachParent) { linkedStore.eachParent(function(parent) { resourceIds.push(parent.id); }, resourceId); } }); return this.relevantResources = [...new Set(resourceIds)]; }, _getIdsFromAssignments: function(id) { const gantt2 = this.$gantt; const resourceIds = []; const task = gantt2.getTask(id); let assignments = gantt2.getTaskAssignments(id); assignments.forEach(function(assignment) { resourceIds.push(assignment.resource_id); }); if (gantt2.isSummaryTask(task) && gantt2.config.drag_project) { gantt2.eachTask(function(child) { const childAssignments = gantt2.getTaskAssignments(child.id); childAssignments.forEach(function(assignment) { resourceIds.push(assignment.resource_id); }); }, id); } if (gantt2.config.drag_multiple && gantt2.getSelectedTasks) { const selectedIds = gantt2.getSelectedTasks(); selectedIds.forEach(function(selectedId) { const selectedAssignments = gantt2.getTaskAssignments(selectedId); selectedAssignments.forEach(function(assignment) { resourceIds.push(assignment.resource_id); }); }); } return resourceIds; }, _updateNestedTasks: function() { var gantt2 = this.$gantt; var resourceStore = gantt2.getDatastore(gantt2.config.resource_store); if (!resourceStore.$config.fetchTasks) { return; } resourceStore.silent(function() { var toAddArray = []; var toAdd = {}; var toDelete = {}; resourceStore.eachItem(function(resource) { if (resource.$role == "task") { toDelete[resource.id] = true; return; } var assignments = gantt2.getResourceAssignments(resource.id); var addedTasks = {}; assignments.sort(function(a, b) { const resourceData = resourceStore.pull; const resource1 = resourceData[`${a.task_id}_${a.resource_id}`]; const resource2 = resourceData[`${b.task_id}_${b.resource_id}`]; if (resource1 && resource2) { return resource1.$local_index - resource2.$local_index; } else { return 0; } }); assignments.forEach(function(a) { if (addedTasks[a.task_id] || !gantt2.isTaskExists(a.task_id)) { return; } addedTasks[a.task_id] = true; var task = gantt2.getTask(a.task_id); var copy2; if (resourceStore.$config.copyOnParse) { copy2 = gantt2.copy(task); } else { copy2 = Object.create(task); } copy2.id = task.id + "_" + resource.id; copy2.$task_id = task.id; copy2.$resource_id = resource.id; copy2[resourceStore.$parentProperty] = resource.id; copy2.$role = "task"; toAddArray.push(copy2); toAdd[copy2.id] = true; }); }); for (var id in toDelete) { if (!toAdd[id]) { resourceStore.removeItem(id); } } if (toAddArray.length) { resourceStore.parse(toAddArray); } }); } }; } const GridRL = function(_super) { function GridRL2(parent, config2, factory2, gantt2) { return _super.apply(this, arguments) || this; } __extends(GridRL2, _super); mixin(GridRL2.prototype, { init: function(container) { const gantt2 = this.$gantt; const gridAriaAttr = gantt2._waiAria.gridAttrString(); const gridDataAriaAttr = gantt2._waiAria.gridDataAttrString(); const _ganttConfig = this.$getConfig(); _ganttConfig.row_height = this._getResourceConfig().row_height ? this._getResourceConfig().row_height : gantt2.resource_table.row_height; _ganttConfig.reorder_grid_columns || false; if (this.$config.reorder_grid_columns !== void 0) { this.$config.reorder_grid_columns; } if (this.$config.bind === void 0) { this.$config.bind = "temp_resource_assignment_store"; this.$config.name = "resource_grid_lightbox"; this.$config.$id = "GridRL"; } container.innerHTML = "
"; this.$grid = container.childNodes[0]; this.$grid.innerHTML = "
"; this.$grid_scale = this.$grid.childNodes[0]; this.$grid_data = this.$grid.childNodes[1]; let attr = _ganttConfig[this.$config.bind + "_attribute"]; if (!attr && this.$config.bind) { attr = "data-" + this.$config.bind + "-id"; } this.$config.item_attribute = attr || null; if (!this.$config.layers) { const layers = this._createLayerConfig(); this.$config.layers = layers; } const domEvents = createScope(); this.event = domEvents.attach; this.eventRemove = domEvents.detach; this._eventRemoveAll = domEvents.detachAll; this._createDomEventScope = domEvents.extend; this._addLayers(this.$gantt); this._initEvents(); this.callEvent("onReady", []); }, getColumn: function(name) { const index = this.getColumnIndex(name); if (index === null) { return null; } const columns = this._getResourceColumns(); return columns[index] || null; }, getColumnIndex: function(name, excludeHidden) { const columns = this._getResourceColumns(); let hiddenIndexShift = 0; for (let i = 0; i < columns.length; i++) { if (excludeHidden && columns[i].hide) { hiddenIndexShift++; } if (columns[i].name == name) { return i - hiddenIndexShift; } } return null; }, getGridColumns: function() { const columns = this._getResourceColumns(); const visibleColumns = []; for (let i = 0; i < columns.length; i++) { if (!columns[i].hide) visibleColumns.push(columns[i]); } return visibleColumns; }, _createLayerConfig: function() { const gantt2 = this.$gantt; const self2 = this; const layers = [{ renderer: gantt2.$ui.layers.gridLine(), container: this.$grid_data, filter: [function() { return self2.isVisible(); }] }, { renderer: gantt2.$ui.layers.gridTaskRowResizer(), container: this.$grid_data, append: true, filter: [function() { return gantt2.config.resize_rows; }] }]; return layers; }, _renderGridHeader: function() { const gantt2 = this.$gantt; const config2 = this._getResourceConfig(); const locale2 = this.$gantt.locale; const templates2 = this.$getTemplates(); let columns = this._getResourceColumns(); if (config2.rtl) { columns = columns.reverse(); } if (!config2.scale_height) { config2.scale_height = gantt2.resource_table.scale_height; } let cells = []; let width = 0, labels = locale2.labels; let lineHeigth = config2.scale_height - 1; for (let i = 0; i < columns.length; i++) { let last = i == columns.length - 1; let col = columns[i]; if (!col.name) { col.name = gantt2.uid() + ""; } let colWidth = col.width * 1; let gridWidth = this._getGridWidth(); if (last && gridWidth > width + colWidth) col.width = colWidth = gridWidth - width; width += colWidth; let sort = gantt2._sort && col.name == gantt2._sort.name ? `
` : ""; let cssClass = ["gantt_grid_head_cell", "gantt_grid_head_" + col.name, last ? "gantt_last_cell" : "", templates2.grid_header_class ? templates2.grid_header_class(col.name, col) : ""].join(" "); let style = "width:" + (colWidth - (last ? 1 : 0)) + "px;"; let label = col.label || labels["column_" + col.name] || labels[col.name]; label = label || ""; const ariaAttrs = gantt2._waiAria.gridScaleCellAttrString(col, label); const cell = "
" + label + sort + "
"; cells.push(cell); } this.$grid_scale.style.height = config2.scale_height + "px"; this.$grid_scale.style.lineHeight = lineHeigth + "px"; this.$grid_scale.style.width = "inherit"; this.$grid_scale.innerHTML = cells.join(""); }, isVisible: function() { if (this.$parent) { return !this.$parent.hidden; } else { return this.$grid.offsetWidth; } }, _initEvents: function() { }, _getResourceSection: function() { return gantt.getLightboxSection(this.$config.sectionName).section; }, $getTemplates: function() { return this._getResourceSection().templates || {}; }, _getResourceConfig: function() { return this._getResourceSection().config || gantt.resource_table; }, _getResourceColumns: function() { var _a; return ((_a = this._getResourceSection().config) == null ? void 0 : _a.columns) || gantt.resource_table.columns; }, destructor: function() { if (this._mouseDelegates) { this._mouseDelegates.destructor(); this._mouseDelegates = null; } this._unbindStore(); this.$grid = null; this.$grid_scale = null; this.$grid_data = null; this._eventRemoveAll(); gantt.ext.inlineEditorsLightbox.destructor(); this.callEvent("onDestroy", []); this.detachAllEvents(); } }, true); mixin(GridRL2.prototype, createMixin(GridRL2), true); return GridRL2; }(Grid); const defaultMapping = { init: function(controller, grid) { var gantt2 = grid.$gantt; gantt2.attachEvent("onTaskClick", function(id, e) { if (gantt2._is_icon_open_click(e)) return true; var state = controller.getState(); var cell = controller.locateCell(e.target); if (cell && controller.getEditorConfig(cell.columnName)) { if (controller.isVisible() && state.id == cell.id && state.columnName == cell.columnName) ; else { controller.startEdit(cell.id, cell.columnName); } return false; } return true; }); if (grid.$config.id === "GridRL") { gantt2.event(gantt2.getLightbox(), "click", function(e) { const domHelpers2 = gantt2.utils.dom; const state = controller.getState(); const cell = controller.locateCell(e.target); if (cell && controller.getEditorConfig(cell.columnName)) { if (cell.columnName == "duration" || cell.columnName == "end") { const tempAssignmentStore = gantt2.getDatastore("temp_resource_assignment_store"); const assignment = tempAssignmentStore.getItem(cell.id); if (assignment) { if (!assignment.start_date) { gantt2.message({ type: "warning", text: "Specify assignment start date" }); controller.hide(); return false; } } } if (controller.isVisible() && state.id == cell.id && state.columnName == cell.columnName) ; else { controller.startEdit(cell.id, cell.columnName); } if (controller.isChanged()) { controller.save(); } return false; } if (domHelpers2.closest(e.target, `.gantt_custom_button.gantt_add_resources`)) { return; } if (domHelpers2.closest(e.target, `[data-assignment-delete]`)) { const assignmentId = e.target.getAttribute("data-assignment-delete"); gantt2.confirm({ text: "Resource assignment will be deleted permanently, are you sure?", cancel: "No", ok: "Delete", callback: function(result) { if (result) { const tempAssignmentStore = gantt2.getDatastore("temp_resource_assignment_store"); tempAssignmentStore.removeItem(assignmentId); if (tempAssignmentStore.getItems().length == 0) { const resourceSection = gantt2.getLightboxSection(grid.$config.sectionName); const block = gantt2.form_blocks["resource_selector"]; const node = gantt2._lightbox_root.querySelector("#" + resourceSection.section.id).nextSibling; block.set_value.call(gantt2, node, [], {}, resourceSection.section, true); } gantt2.refreshData(); } else { return; } } }); } if (controller.isVisible()) { controller.save(); controller.hide(); } else { controller.hide(); } }); gantt2.lightbox_events.gantt_save_btn = function() { controller.save(); gantt2._save_lightbox(); }; } gantt2.attachEvent("onEmptyClick", function() { if (controller.isVisible() && controller.isChanged()) { controller.save(); } else { controller.hide(); } return true; }); gantt2.attachEvent("onTaskDblClick", function(id, e) { var state = controller.getState(); var cell = controller.locateCell(e.target); if (cell && controller.isVisible() && cell.columnName == state.columnName) { return false; } return true; }); }, onShow: function(controller, placeholder, grid) { var gantt2 = grid.$gantt; if (gantt2.ext && gantt2.ext.keyboardNavigation) { var keyNav = gantt2.ext.keyboardNavigation; keyNav.attachEvent("onKeyDown", function(command, e) { var keyboard = gantt2.constants.KEY_CODES; var keyCode = e.keyCode; var preventKeyNav = false; switch (keyCode) { case keyboard.SPACE: if (controller.isVisible()) { preventKeyNav = true; } break; } if (preventKeyNav) { return false; } else { return true; } }); } placeholder.onkeydown = function(e) { e = e || window.event; var keyboard = gantt2.constants.KEY_CODES; if (e.defaultPrevented || e.shiftKey && e.keyCode != keyboard.TAB) { return; } var shouldPrevent = true; switch (e.keyCode) { case gantt2.keys.edit_save: controller.save(); break; case gantt2.keys.edit_cancel: controller.hide(); break; case keyboard.UP: case keyboard.DOWN: if (controller.isVisible()) { controller.hide(); shouldPrevent = false; } break; case keyboard.TAB: if (e.shiftKey) { controller.editPrevCell(true); } else { controller.editNextCell(true); } break; default: shouldPrevent = false; break; } if (shouldPrevent) { e.preventDefault(); } }; if (grid.$config.id === "GridRL") { placeholder.onkeyup = function(e) { e = e || window.event; var keyboard = gantt2.constants.KEY_CODES; if (e.defaultPrevented || e.shiftKey && e.keyCode != keyboard.TAB) { return; } if (gantt2._lightbox_id && controller.isChanged()) { controller.save(); } }; let timeout; placeholder.onwheel = function(e) { if (gantt2._lightbox_id && controller.isChanged()) { clearTimeout(timeout); timeout = setTimeout(function() { controller.save(); }, 100); } }; } }, onHide: function() { }, destroy: function() { } }; const keyNavMappings = { init: function(controller, grid) { var self2 = controller; var gantt2 = grid.$gantt; var onBlurDelay = null; var keyNav = gantt2.ext.keyboardNavigation; keyNav.attachEvent("onBeforeFocus", function(node) { var activeCell = controller.locateCell(node); clearTimeout(onBlurDelay); if (activeCell) { var columnName = activeCell.columnName; var id = activeCell.id; var editorState = self2.getState(); if (self2.isVisible()) { if (editorState.id == id && editorState.columnName === columnName) { return false; } } } return true; }); keyNav.attachEvent("onFocus", function(node) { var activeCell = controller.locateCell(node); var state = controller.getState(); clearTimeout(onBlurDelay); if (activeCell && !(activeCell.id == state.id && activeCell.columnName == state.columnName)) { if (self2.isVisible()) { self2.save(); } } return true; }); controller.attachEvent("onHide", function() { clearTimeout(onBlurDelay); }); keyNav.attachEvent("onBlur", function() { onBlurDelay = setTimeout(function() { self2.save(); }); return true; }); gantt2.attachEvent("onTaskDblClick", function(id, e) { var state = controller.getState(); var cell = controller.locateCell(e.target); if (cell && controller.isVisible() && cell.columnName == state.columnName) { return false; } return true; }); gantt2.attachEvent("onTaskClick", function(id, e) { if (gantt2._is_icon_open_click(e)) return true; var state = controller.getState(); var cell = controller.locateCell(e.target); if (cell && controller.getEditorConfig(cell.columnName)) { if (controller.isVisible() && state.id == cell.id && state.columnName == cell.columnName) ; else { controller.startEdit(cell.id, cell.columnName); } return false; } return true; }); gantt2.attachEvent("onEmptyClick", function() { self2.save(); return true; }); keyNav.attachEvent("onKeyDown", function(command, e) { var activeCell = controller.locateCell(e.target); var hasEditor = activeCell ? controller.getEditorConfig(activeCell.columnName) : false; var state = controller.getState(); var keyboard = gantt2.constants.KEY_CODES; var keyCode = e.keyCode; var preventKeyNav = false; switch (keyCode) { case keyboard.ENTER: if (controller.isVisible()) { controller.save(); e.preventDefault(); preventKeyNav = true; } else if (hasEditor && !(e.ctrlKey || e.metaKey || e.shiftKey)) { self2.startEdit(activeCell.id, activeCell.columnName); e.preventDefault(); preventKeyNav = true; } break; case keyboard.ESC: if (controller.isVisible()) { controller.hide(); e.preventDefault(); preventKeyNav = true; } break; case keyboard.UP: case keyboard.DOWN: break; case keyboard.LEFT: case keyboard.RIGHT: if (hasEditor && controller.isVisible() || state.editorType === "date") { preventKeyNav = true; } break; case keyboard.SPACE: if (controller.isVisible()) { preventKeyNav = true; } if (hasEditor && !controller.isVisible()) { self2.startEdit(activeCell.id, activeCell.columnName); e.preventDefault(); preventKeyNav = true; } break; case keyboard.DELETE: if (hasEditor && !controller.isVisible()) { self2.startEdit(activeCell.id, activeCell.columnName); preventKeyNav = true; } else if (hasEditor && controller.isVisible()) { preventKeyNav = true; } break; case keyboard.TAB: if (controller.isVisible()) { if (e.shiftKey) { controller.editPrevCell(true); } else { controller.editNextCell(true); } var newState = controller.getState(); if (newState.id) { keyNav.focus({ type: "taskCell", id: newState.id, column: newState.columnName }); } e.preventDefault(); preventKeyNav = true; } break; default: if (controller.isVisible()) preventKeyNav = true; else { if (keyCode >= 48 && keyCode <= 57 || keyCode > 95 && keyCode < 112 || keyCode >= 64 && keyCode <= 91 || keyCode > 185 && keyCode < 193 || keyCode > 218 && keyCode < 223) { var modifiers = command.modifiers; var anyModifier = modifiers.alt || modifiers.ctrl || modifiers.meta || modifiers.shift; if (modifiers.alt || e.key === "Meta") ; else if (anyModifier && keyNav.getCommandHandler(command, "taskCell")) ; else if (hasEditor && !controller.isVisible()) { self2.startEdit(activeCell.id, activeCell.columnName); preventKeyNav = true; } } } break; } if (preventKeyNav) { return false; } else { return true; } }); }, onShow: function(controller, placeholder, grid) { }, onHide: function(controller, placeholder, grid) { const gantt2 = grid.$gantt; if (gantt2) { gantt2.focus(); } }, destroy: function() { } }; function getKeyboardMapping(gantt2) { var mapping = null; return { setMapping: function(map) { mapping = map; }, getMapping: function() { if (mapping) { return mapping; } else if (gantt2.config.keyboard_navigation_cells && gantt2.ext.keyboardNavigation) { return keyNavMappings; } else { return defaultMapping; } } }; } function BaseFactory(gantt2) { var BaseEditor = function() { }; BaseEditor.prototype = { show: function(id, column, config2, placeholder) { }, hide: function() { }, set_value: function(value, id, column, node) { this.get_input(node).value = value; }, get_value: function(id, column, node) { return this.get_input(node).value || ""; }, is_changed: function(value, id, column, node) { var currentValue = this.get_value(id, column, node); if (currentValue && value && currentValue.valueOf && value.valueOf) { return currentValue.valueOf() != value.valueOf(); } else { return currentValue != value; } }, is_valid: function(value, id, column, node) { return true; }, save: function(id, column, node) { }, get_input: function(node) { return node.querySelector("input"); }, focus: function(node) { var input = this.get_input(node); if (!input) { return; } if (input.focus) { input.focus(); } if (input.select) { input.select(); } } }; return BaseEditor; } function textEditorFactory(gantt2) { var BaseEditor = BaseFactory(); function TextEditor() { var self2 = BaseEditor.apply(this, arguments) || this; return self2; } __extends(TextEditor, BaseEditor); mixin(TextEditor.prototype, { show: function(id, column, config2, placeholder) { var html = `
`; placeholder.innerHTML = html; } }, true); return TextEditor; } function numberEditorFactory(gantt2) { var BaseEditor = BaseFactory(); function NumberEditor() { var self2 = BaseEditor.apply(this, arguments) || this; return self2; } __extends(NumberEditor, BaseEditor); mixin(NumberEditor.prototype, { show: function(id, column, config2, placeholder) { var min = config2.min || 0, max = config2.max || 100; var html = `
`; placeholder.innerHTML = html; placeholder.oninput = function(e) { if (+e.target.value < min) { e.target.value = min; } if (+e.target.value > max) { e.target.value = max; } }; }, get_value: function(id, column, node) { return this.get_input(node).value || ""; }, is_valid: function(value, id, column, node) { return !isNaN(parseInt(value, 10)); } }, true); return NumberEditor; } function selectEditorFactory(gantt2) { var BaseEditor = BaseFactory(); function SelectEditor() { var self2 = BaseEditor.apply(this, arguments) || this; return self2; } __extends(SelectEditor, BaseEditor); mixin(SelectEditor.prototype, { show: function(id, column, config2, placeholder) { var html = `
"; placeholder.innerHTML = html; }, get_input: function(node) { return node.querySelector("select"); } }, true); return SelectEditor; } function dateEditorFactory(gantt2) { var BaseEditor = BaseFactory(); var html5DateFormat = "%Y-%m-%d"; var dateToStr2 = null; var strToDate2 = null; function init() { if (!dateToStr2) { dateToStr2 = gantt2.date.date_to_str(html5DateFormat); } if (!strToDate2) { strToDate2 = gantt2.date.str_to_date(html5DateFormat); } } function DateEditor() { var self2 = BaseEditor.apply(this, arguments) || this; return self2; } __extends(DateEditor, BaseEditor); mixin(DateEditor.prototype, { show: function(id, column, config2, placeholder) { init(); var minValue = null; var maxValue = null; if (typeof config2.min === "function") { minValue = config2.min(id, column); } else { minValue = config2.min; } if (typeof config2.max === "function") { maxValue = config2.max(id, column); } else { maxValue = config2.max; } var minAttr = minValue ? " min='" + dateToStr2(minValue) + "' " : ""; var maxAttr = maxValue ? " max='" + dateToStr2(maxValue) + "' " : ""; var html = `
`; placeholder.innerHTML = html; placeholder.oninput = function(e) { if (e.target.value && (minValue || maxValue)) { if (+gantt2.date.str_to_date("%Y-%m-%d")(e.target.value) < +minValue) { e.target.value = gantt2.date.date_to_str("%Y-%m-%d")(minValue); } if (+gantt2.date.str_to_date("%Y-%m-%d")(e.target.value) > +maxValue) { e.target.value = gantt2.date.date_to_str("%Y-%m-%d")(maxValue); } } }; }, set_value: function(value, id, column, node) { if (value && value.getFullYear) { this.get_input(node).value = dateToStr2(value); } else { this.get_input(node).value = value; } }, is_valid: function(value, id, column, node) { if (!value || isNaN(value.getTime())) return false; return true; }, get_value: function(id, column, node) { var parsed; try { parsed = strToDate2(this.get_input(node).value || ""); } catch (e) { parsed = null; } return parsed; } }, true); return DateEditor; } function predecessorEditorFactory(gantt2) { var BaseEditor = BaseFactory(); function PredecessorEditor() { var self2 = BaseEditor.apply(this, arguments) || this; return self2; } __extends(PredecessorEditor, BaseEditor); function getFormatter(config2) { return config2.formatter || gantt2.ext.formatters.linkFormatter(); } function parseInputString(value, config2) { var predecessors = (value || "").split(config2.delimiter || ","); for (var i = 0; i < predecessors.length; i++) { var val = predecessors[i].trim(); if (val) { predecessors[i] = val; } else { predecessors.splice(i, 1); i--; } } predecessors.sort(); return predecessors; } function formatPredecessors(task, config2, gantt3) { var links = task.$target; var labels = []; for (var i = 0; i < links.length; i++) { var link = gantt3.getLink(links[i]); labels.push(getFormatter(config2).format(link)); } return labels.join((config2.delimiter || ",") + " "); } function getSelectedLinks(taskId, predecessorCodes, config2) { var links = []; [...new Set(predecessorCodes)].forEach(function(code) { var link = getFormatter(config2).parse(code); if (link) { link.target = taskId; link.id = "predecessor_generated"; if (gantt2.isLinkAllowed(link)) { link.id = void 0; links.push(link); } } }); return links; } function formatLinkKey(link) { return link.source + "_" + link.target + "_" + link.type + "_" + (link.lag || 0); } function getLinksDiff(task, predecessorCodes, config2) { var selectedLinks = getSelectedLinks(task.id, predecessorCodes, config2); var existingLinksSearch = {}; task.$target.forEach(function(linkId) { var link = gantt2.getLink(linkId); existingLinksSearch[formatLinkKey(link)] = link.id; }); var linksToAdd = []; selectedLinks.forEach(function(link) { var linkKey = formatLinkKey(link); if (!existingLinksSearch[linkKey]) { linksToAdd.push(link); } else { delete existingLinksSearch[linkKey]; } }); var linksToDelete = []; for (var i in existingLinksSearch) { linksToDelete.push(existingLinksSearch[i]); } return { add: linksToAdd, remove: linksToDelete }; } mixin(PredecessorEditor.prototype, { show: function(id, column, config2, placeholder) { var html = `
`; placeholder.innerHTML = html; }, hide: function() { }, set_value: function(value, id, column, node) { this.get_input(node).value = formatPredecessors(value, column.editor, gantt2); }, get_value: function(id, column, node) { return parseInputString(this.get_input(node).value || "", column.editor); }, save: function(id, column, node) { var task = gantt2.getTask(id); var linksDiff = getLinksDiff(task, this.get_value(id, column, node), column.editor); if (linksDiff.add.length || linksDiff.remove.length) { gantt2.batchUpdate(function() { linksDiff.add.forEach(function(link) { gantt2.addLink(link); }); linksDiff.remove.forEach(function(linkId) { gantt2.deleteLink(linkId); }); if (gantt2.autoSchedule) gantt2.autoSchedule(); }); } }, is_changed: function(value, id, column, node) { var inputPredecessors = this.get_value(id, column, node); var taskPredecessors = parseInputString(formatPredecessors(value, column.editor, gantt2), column.editor); return inputPredecessors.join() !== taskPredecessors.join(); } }, true); return PredecessorEditor; } function durationEditorFactory(gantt2) { var BaseEditor = BaseFactory(); function TextEditor() { var self2 = BaseEditor.apply(this, arguments) || this; return self2; } __extends(TextEditor, BaseEditor); function getFormatter(config2) { return config2.formatter || gantt2.ext.formatters.durationFormatter(); } mixin(TextEditor.prototype, { show: function(id, column, config2, placeholder) { var html = `
`; placeholder.innerHTML = html; }, set_value: function(value, id, column, node) { this.get_input(node).value = getFormatter(column.editor).format(value); }, get_value: function(id, column, node) { return getFormatter(column.editor).parse(this.get_input(node).value || ""); } }, true); return TextEditor; } function linkedPropertiesProcessor(gantt2) { return function processTaskDateProperties(item, mapTo, mode) { if (mode == "keepDates") { keepDatesOnEdit(item, mapTo); } else if (mode == "keepDuration") { keepDurationOnEdit(item, mapTo); } else { defaultActionOnEdit(item, mapTo); } }; function keepDatesOnEdit(item, mapTo) { if (mapTo == "duration") { item.end_date = gantt2.calculateEndDate(item); } else if (mapTo == "end_date" || mapTo == "start_date") { item.duration = gantt2.calculateDuration(item); } } function keepDurationOnEdit(item, mapTo) { if (mapTo == "end_date") { item.start_date = decreaseStartDate(item); } else if (mapTo == "start_date" || mapTo == "duration") { item.end_date = gantt2.calculateEndDate(item); } } function defaultActionOnEdit(item, mapTo) { if (gantt2._getAutoSchedulingConfig().schedule_from_end) { if (mapTo == "end_date" || mapTo == "duration") { item.start_date = decreaseStartDate(item); } else if (mapTo == "start_date") { item.duration = gantt2.calculateDuration(item); } } else { if (mapTo == "start_date" || mapTo == "duration") { item.end_date = gantt2.calculateEndDate(item); } else if (mapTo == "end_date") { item.duration = gantt2.calculateDuration(item); } } } function decreaseStartDate(item) { return gantt2.calculateEndDate({ start_date: item.end_date, duration: -item.duration, task: item }); } } function initConfigs(gantt2) { gantt2.config.editor_types = { text: new (textEditorFactory())(), number: new (numberEditorFactory())(), select: new (selectEditorFactory())(), date: new (dateEditorFactory(gantt2))(), predecessor: new (predecessorEditorFactory(gantt2))(), duration: new (durationEditorFactory(gantt2))() }; } function create(gantt2) { var keyboardMapping = getKeyboardMapping(gantt2); var eventBus = {}; makeEventable(eventBus); function createGridEditors(grid) { function _getGridCellFromNode(node) { if (!isChildOf(node, grid.$grid)) { return null; } var row = locateAttribute(node, grid.$config.item_attribute); var cell = locateAttribute(node, "data-column-name"); if (row && cell) { var columnName = cell.getAttribute("data-column-name"); var id = row.getAttribute(grid.$config.item_attribute); return { id, columnName }; } return null; } function _getEditorPosition(itemId, columnName) { var config2 = grid.$getConfig(); var top = grid.getItemTop(itemId); var height = grid.getItemHeight(itemId); var cols = grid.getGridColumns(); var left = 0, right = 0, width = 0; for (var i = 0; i < cols.length; i++) { if (cols[i].name == columnName) { width = cols[i].width; break; } if (config2.rtl) { right += cols[i].width; } else { left += cols[i].width; } } if (config2.rtl) { return { top, right, height, width }; } else { return { top, left, height, width }; } } function findVisibleIndex(grid2, columnName) { var columns = grid2.getGridColumns(); for (var i = 0; i < columns.length; i++) { if (columns[i].name == columnName) { return i; } } return 0; } function _createPlaceholder(itemId, columnName) { var config2 = grid.$getConfig(); var pos = _getEditorPosition(itemId, columnName); var el = document.createElement("div"); el.className = "gantt_grid_editor_placeholder"; el.setAttribute(grid.$config.item_attribute, itemId); el.setAttribute(grid.$config.bind + "_id", itemId); el.setAttribute("data-column-name", columnName); var visibleIndex = findVisibleIndex(grid, columnName); el.setAttribute("data-column-index", visibleIndex); gantt2._waiAria.inlineEditorAttr(el); if (config2.rtl) { el.style.cssText = ["top:" + pos.top + "px", "right:" + pos.right + "px", "width:" + pos.width + "px", "height:" + pos.height + "px"].join(";"); } else { el.style.cssText = ["top:" + pos.top + "px", "left:" + pos.left + "px", "width:" + pos.width + "px", "height:" + pos.height + "px"].join(";"); } return el; } var updateTaskDateProperties = linkedPropertiesProcessor(gantt2); var handlers = []; var ganttHandlers = []; var store = null; var controller = { _itemId: null, _columnName: null, _editor: null, _editorType: null, _placeholder: null, locateCell: _getGridCellFromNode, getEditorConfig: function(columnName) { var column = grid.getColumn(columnName); if (column) { return column.editor; } }, init: function() { var mapping = keyboardMapping.getMapping(); if (mapping.init) { mapping.init(this, grid); } store = grid.$gantt.getDatastore(grid.$config.bind); if (!store && gantt2.$data.tempAssignmentsStore) { store = gantt2.$data.tempAssignmentsStore; } var self2 = this; handlers.push(store.attachEvent("onIdChange", function(oldId, newId) { if (self2._itemId == oldId) { self2._itemId = newId; } })); handlers.push(store.attachEvent("onStoreUpdated", function() { if (grid.$gantt.getState("batchUpdate").batch_update) { return; } if (self2.isVisible() && !store.isVisible(self2._itemId)) { self2.hide(); } })); ganttHandlers.push(gantt2.attachEvent("onDataRender", function() { if (self2._editor && self2._placeholder && !isChildOf(self2._placeholder, gantt2.$root)) { grid.$grid_data.appendChild(self2._placeholder); } })); this.init = function() { }; }, getState: function() { return { editor: this._editor, editorType: this._editorType, placeholder: this._placeholder, id: this._itemId, columnName: this._columnName }; }, startEdit: function(itemId, columnName) { if (this.isVisible()) { this.save(); } if (!store.exists(itemId)) { return; } var editorState = { id: itemId, columnName }; if (gantt2.isReadonly(store.getItem(itemId))) { this.callEvent("onEditPrevent", [editorState]); return; } if (this.callEvent("onBeforeEditStart", [editorState]) === false) { this.callEvent("onEditPrevent", [editorState]); return; } const asyncShow = this.show(editorState.id, editorState.columnName); if (asyncShow && asyncShow.then) { asyncShow.then((function() { this.setValue(); this.callEvent("onEditStart", [editorState]); }).bind(this)); } else { this.setValue(); this.callEvent("onEditStart", [editorState]); } }, isVisible: function() { if (gantt2._lightbox_id) { return !!(this._editor && isChildOf(this._placeholder, gantt2._lightbox)); } return !!(this._editor && isChildOf(this._placeholder, gantt2.$root)); }, show: function(itemId, columnName) { if (this.isVisible()) { this.save(); } var editorState = { id: itemId, columnName }; var column = grid.getColumn(editorState.columnName); var editorConfig = this.getEditorConfig(column.name); if (!editorConfig) return; var editor = grid.$getConfig().editor_types[editorConfig.type]; var placeholder = _createPlaceholder(editorState.id, editorState.columnName); grid.$grid_data.appendChild(placeholder); const onAfterShow = (function() { this._editor = editor; this._placeholder = placeholder; this._itemId = editorState.id; this._columnName = editorState.columnName; this._editorType = editorConfig.type; var mapping = keyboardMapping.getMapping(); if (mapping.onShow) { mapping.onShow(this, placeholder, grid); } placeholder._onReMount = (function() { this.setValue(); }).bind(this); }).bind(this); const editorResult = editor.show(editorState.id, column, editorConfig, placeholder); if (editorResult && editorResult.then) { return editorResult.then(() => { onAfterShow(); }); } else { onAfterShow(); } }, setValue: function() { var state = this.getState(); var itemId = state.id, columnName = state.columnName; var column = grid.getColumn(columnName); var item = store.getItem(itemId); var editorConfig = this.getEditorConfig(columnName); var value; if (!editorConfig) return; if (gantt2._lightbox_id) { let assignment = store.getItem(this._itemId); if (editorConfig.map_to === "text") { let resource = gantt2.getDatastore(gantt2.config.resource_store).getItem(assignment.resource_id); value = resource.text; } else if (editorConfig.map_to === "start_date") { value = item.start_date === "" || item.start_date === null ? gantt2.getTask(gantt2._lightbox_id).start_date : item.start_date; } else { value = item[editorConfig.map_to]; } } else { value = item[editorConfig.map_to]; } if (editorConfig.map_to === "auto") { value = store.getItem(itemId); } this._editor.set_value(value, itemId, column, this._placeholder); this.focus(); }, focus: function() { this._editor.focus(this._placeholder); }, getValue: function() { var column = grid.getColumn(this._columnName); return this._editor.get_value(this._itemId, column, this._placeholder); }, _getItemValue: function() { var editorConfig = this.getEditorConfig(this._columnName); if (!editorConfig) return; var value; if (gantt2._lightbox_id) { let assignment = store.getItem(this._itemId); if (editorConfig.type === "select" && editorConfig.map_to !== "mode") { let resource = gantt2.getDatastore(gantt2.config.resource_store).getItem(assignment.resource_id); value = resource.id; } else { value = assignment[editorConfig.map_to]; } } else { var item = gantt2.getTask(this._itemId); value = item[editorConfig.map_to]; } if (editorConfig.map_to == "auto") { value = store.getItem(this._itemId); } return value; }, isChanged: function() { var column = grid.getColumn(this._columnName); var value = this._getItemValue(); return this._editor.is_changed(value, this._itemId, column, this._placeholder); }, hide: function() { if (!this._itemId) return; var itemId = this._itemId, columnName = this._columnName; var mapping = keyboardMapping.getMapping(); if (mapping.onHide) { mapping.onHide(this, this._placeholder, grid); } this._itemId = null; this._columnName = null; this._editorType = null; if (!this._placeholder) return; if (this._editor && this._editor.hide) { this._editor.hide(this._placeholder); } this._editor = null; if (this._placeholder.parentNode) { this._placeholder.parentNode.removeChild(this._placeholder); } this._placeholder = null; this.callEvent("onEditEnd", [{ id: itemId, columnName }]); }, save: function() { if (!(this.isVisible() && store.exists(this._itemId) && this.isChanged())) { this.hide(); return; } var itemId = this._itemId, columnName = this._columnName; if (!store.exists(itemId)) { return; } var item = store.getItem(itemId); var editorConfig = this.getEditorConfig(columnName); var editorState = { id: itemId, columnName, newValue: this.getValue(), oldValue: this._getItemValue() }; if (this.callEvent("onBeforeSave", [editorState]) !== false) { if (!this._editor.is_valid || this._editor.is_valid(editorState.newValue, editorState.id, grid.getColumn(columnName), this._placeholder)) { if (gantt2._lightbox_id) { if (editorState.newValue == "") { editorState.newValue = editorState.oldValue; } } var mapTo = editorConfig.map_to; var value = editorState.newValue; if (mapTo != "auto") { item[mapTo] = value; updateTaskDateProperties(item, mapTo, gantt2.config.inline_editors_date_processing); store.updateItem(itemId); } else { this._editor.save(itemId, grid.getColumn(columnName), this._placeholder); } this.callEvent("onSave", [editorState]); } } if (!gantt2._lightbox_id) { this.hide(); } }, _findEditableCell: function findEditableCell(start, direction) { var nextIndex = start; var columns = grid.getGridColumns(); var nextColumn = columns[nextIndex]; var columnName = nextColumn ? nextColumn.name : null; if (columnName) { while (columnName && !this.getEditorConfig(columnName)) { columnName = this._findEditableCell(start + direction, direction); } return columnName; } return null; }, getNextCell: function moveCell(dir) { return this._findEditableCell(grid.getColumnIndex(this._columnName, true) + dir, dir); }, getFirstCell: function getFirstCell() { return this._findEditableCell(0, 1); }, getLastCell: function getLastCell() { return this._findEditableCell(grid.getGridColumns().length - 1, -1); }, editNextCell: function nextCell(canChangeRow) { var cell = this.getNextCell(1); if (cell) { var nextColumn = this.getNextCell(1); if (nextColumn && this.getEditorConfig(nextColumn)) { this.startEdit(this._itemId, nextColumn); } } else if (canChangeRow && this.moveRow(1)) { var task = this.moveRow(1); cell = this.getFirstCell(); if (cell && this.getEditorConfig(cell)) { this.startEdit(task, cell); } } }, editPrevCell: function prevCell(canChangeRow) { var cell = this.getNextCell(-1); if (cell) { var nextColumn = this.getNextCell(-1); if (nextColumn && this.getEditorConfig(nextColumn)) { this.startEdit(this._itemId, nextColumn); } } else if (canChangeRow && this.moveRow(-1)) { var task = this.moveRow(-1); cell = this.getLastCell(); if (cell && this.getEditorConfig(cell)) { this.startEdit(task, cell); } } }, moveRow: function moveRow(dir) { var moveTask = dir > 0 ? gantt2.getNext : gantt2.getPrev; moveTask = gantt2.bind(moveTask, gantt2); var nextItem = moveTask(this._itemId); while (gantt2.isTaskExists(nextItem) && gantt2.isReadonly(gantt2.getTask(nextItem))) { nextItem = moveTask(nextItem); } return nextItem; }, editNextRow: function nextRow(skipReadonly) { var id = this.getState().id; if (!gantt2.isTaskExists(id)) return; var next = null; if (skipReadonly) { next = this.moveRow(1); } else { next = gantt2.getNext(id); } if (gantt2.isTaskExists(next)) { this.startEdit(next, this._columnName); } }, editPrevRow: function prevRow(skipReadonly) { var id = this.getState().id; if (!gantt2.isTaskExists(id)) return; var prev = null; if (skipReadonly) { prev = this.moveRow(-1); } else { prev = gantt2.getPrev(id); } if (gantt2.isTaskExists(prev)) { this.startEdit(prev, this._columnName); } }, detachStore: function() { handlers.forEach(function(handlerId) { store.detachEvent(handlerId); }); ganttHandlers.forEach(function(handlerId) { gantt2.detachEvent(handlerId); }); handlers = []; ganttHandlers = []; store = null; this.hide(); }, destructor: function() { this.detachStore(); this.detachAllEvents(); } }; mixin(controller, keyboardMapping); mixin(controller, eventBus); return controller; } var inlineEditController = { init: initConfigs, createEditors: createGridEditors }; mixin(inlineEditController, keyboardMapping); mixin(inlineEditController, eventBus); return inlineEditController; } function isBarInViewport(item, viewport, view, config2, gantt2) { if (!item.start_date || !item.end_date) { return null; } var top = view.getItemTop(item.id); var height = view.getItemHeight(item.id); if (top > viewport.y_end || top + height < viewport.y) { return false; } var padding = 200; var startCoord = view.posFromDate(item.start_date, view._getPositioningContext ? view._getPositioningContext(item) : null); var endCoord = view.posFromDate(item.end_date, view._getPositioningContext ? view._getPositioningContext(item) : null); var left = Math.min(startCoord, endCoord) - padding; var right = Math.max(startCoord, endCoord) + padding; if (left > viewport.x_end || right < viewport.x) { return false; } return true; } function createTaskRenderer$2(gantt2) { function _render_task_element(task, view, config2) { var config2 = view.$getConfig(); var painters = config2.type_renderers; var renderer = painters[gantt2.getTaskType(task.type)], defaultRenderer = _task_default_render; if (!renderer) { return defaultRenderer.call(gantt2, task, view, config2); } else { return renderer.call(gantt2, task, function(task2) { return defaultRenderer.call(gantt2, task2, view, config2); }, view); } } function _task_default_render(task, view, config2) { if (gantt2._isAllowedUnscheduledTask(task)) return; if (!gantt2._isTaskInTimelineLimits(task)) { return; } var pos = view.getItemPosition(task); var cfg = config2, templates2 = view.$getTemplates(); var taskType = gantt2.getTaskType(task.type); var height = view.getBarHeight(task.id, taskType == cfg.types.milestone); var controlsMargin = 0; if (taskType == cfg.types.milestone) { controlsMargin = (height - pos.height) / 2; } var padd = Math.floor((view.getItemHeight(task.id) - height) / 2); const hasBaselines = gantt2.config.baselines && task.baselines && task.baselines.length; const baselinesOnDifferentRow = gantt2.config.baselines && (gantt2.config.baselines.render_mode == "separateRow" || gantt2.config.baselines.render_mode == "individualRow"); if (hasBaselines && baselinesOnDifferentRow) { if (task.bar_height !== "full" && task.bar_height < task.row_height) { if (taskType === cfg.types.milestone) { let milestoneHeight = view.getBarHeight(task.id, true); let milestoneWidth = Math.sqrt(2 * milestoneHeight * milestoneHeight); padd = Math.floor((milestoneWidth - height) / 2) + 2; } else { padd = 2; } } } if (taskType == cfg.types.milestone) { pos.left -= Math.round(height / 2); pos.width = height; } var div = document.createElement("div"); var width = Math.round(pos.width); if (view.$config.item_attribute) { div.setAttribute(view.$config.item_attribute, task.id); div.setAttribute(view.$config.bind + "_id", task.id); } if (cfg.show_progress && taskType != cfg.types.milestone) { _render_task_progress(task, div, width, cfg, templates2); } var content = _render_task_content(task, width, templates2); div.appendChild(content); var css = _combine_item_class("gantt_task_line", templates2.task_class(task.start_date, task.end_date, task), task.id, view); if (task.color || task.progressColor || task.textColor) { css += " gantt_task_inline_color"; } if (pos.width < 20) { css += " gantt_thin_task"; } div.className = css; var styles = ["left:" + pos.left + "px", "top:" + (padd + pos.top) + "px", "height:" + height + "px", "line-height:" + Math.max(height < 30 ? height - 2 : height, 0) + "px", "width:" + width + "px"]; div.style.cssText = styles.join(";"); if (task.color) { div.style.setProperty("--dhx-gantt-task-background", task.color); } if (task.textColor) { div.style.setProperty("--dhx-gantt-task-color", task.textColor); } if (task.progressColor) { div.style.setProperty("--dhx-gantt-task-progress-color", task.progressColor); } var side = _render_leftside_content(task, cfg, templates2, controlsMargin); if (side) div.appendChild(side); side = _render_rightside_content(task, cfg, templates2, controlsMargin); if (side) div.appendChild(side); gantt2._waiAria.setTaskBarAttr(task, div); var state = gantt2.getState(); const taskEditable = !gantt2.isReadonly(task); const timelineDrag = gantt2.ext.dragTimeline && gantt2.ext.dragTimeline._isDragInProgress(); if (taskEditable || timelineDrag) { if (cfg.drag_resize && !gantt2.isSummaryTask(task) && taskType != cfg.types.milestone) { _render_pair(div, "gantt_task_drag", task, function(css2) { var el = document.createElement("div"); el.className = css2; return el; }, cfg); } if (cfg.drag_links && cfg.show_links) { _render_pair(div, "gantt_link_control", task, function(css2) { var outer = document.createElement("div"); outer.className = css2; outer.style.cssText = ["height:" + height + "px", "line-height:" + height + "px"].join(";"); var inner = document.createElement("div"); inner.className = "gantt_link_point"; var showLinkPoints = false; if (state.link_source_id && cfg.touch) { showLinkPoints = true; } inner.style.display = showLinkPoints ? "block" : ""; outer.appendChild(inner); return outer; }, cfg, controlsMargin); } } return div; } function _render_side_content(task, template, cssClass, marginStyle) { if (!template) return null; var text = template(task.start_date, task.end_date, task); if (!text) return null; var content = document.createElement("div"); content.className = "gantt_side_content " + cssClass; content.innerHTML = text; if (marginStyle) { content.style[marginStyle.type] = Math.abs(marginStyle.value) + "px"; } return content; } function _render_leftside_content(task, cfg, templates2, margin) { var css = "gantt_left " + _get_link_crossing_css(!cfg.rtl ? true : false, task); var marginStyle = null; if (margin) { marginStyle = { type: "marginRight", value: margin }; } return _render_side_content(task, templates2.leftside_text, css, marginStyle); } function _render_rightside_content(task, cfg, templates2, margin) { var css = "gantt_right " + _get_link_crossing_css(!cfg.rtl ? false : true, task); var marginStyle = null; if (margin) { marginStyle = { type: "marginLeft", value: margin }; } return _render_side_content(task, templates2.rightside_text, css, marginStyle); } function _get_link_crossing_css(left, task) { var cond = _get_conditions(left); for (var i in cond) { var links = task[i]; for (var ln = 0; ln < links.length; ln++) { var link = gantt2.getLink(links[ln]); for (var tp = 0; tp < cond[i].length; tp++) { if (link.type == cond[i][tp]) { return "gantt_link_crossing"; } } } } return ""; } function _render_task_content(task, width, templates2) { var content = document.createElement("div"); if (gantt2.getTaskType(task.type) != gantt2.config.types.milestone) { content.innerHTML = templates2.task_text(task.start_date, task.end_date, task); } else if (gantt2.getTaskType(task.type) == gantt2.config.types.milestone && width) { content.style.height = content.style.width = width + "px"; } content.className = "gantt_task_content"; return content; } function _render_task_progress(task, element, maxWidth, cfg, templates2) { var done = task.progress * 1 || 0; maxWidth = Math.max(maxWidth, 0); var pr = document.createElement("div"); var width = Math.round(maxWidth * done); width = Math.min(maxWidth, width); pr.style.width = width + "px"; pr.className = "gantt_task_progress"; pr.innerHTML = templates2.progress_text(task.start_date, task.end_date, task); if (cfg.rtl) { pr.style.position = "absolute"; pr.style.right = "0px"; } var wrapper = document.createElement("div"); wrapper.className = "gantt_task_progress_wrapper"; wrapper.appendChild(pr); element.appendChild(wrapper); const taskEditable = !gantt2.isReadonly(task); const timelineDrag = gantt2.ext.dragTimeline && gantt2.ext.dragTimeline._isDragInProgress(); if (gantt2.config.drag_progress && (taskEditable || timelineDrag)) { var drag = document.createElement("div"); var markerPos = width; if (cfg.rtl) { markerPos = maxWidth - width; } drag.style.left = markerPos + "px"; drag.className = "gantt_task_progress_drag"; drag.innerHTML = ` `; pr.appendChild(drag); element.appendChild(drag); } } function _get_conditions(leftside) { if (leftside) { return { $source: [gantt2.config.links.start_to_start], $target: [gantt2.config.links.start_to_start, gantt2.config.links.finish_to_start] }; } else { return { $source: [gantt2.config.links.finish_to_start, gantt2.config.links.finish_to_finish], $target: [gantt2.config.links.finish_to_finish] }; } } function _combine_item_class(basic, template, itemId, view) { var cfg = view.$getConfig(); var css = [basic]; if (template) css.push(template); var state = gantt2.getState(); var task = gantt2.getTask(itemId); if (gantt2.getTaskType(task.type) == cfg.types.milestone) { css.push("gantt_milestone"); } else if (gantt2.getTaskType(task.type) == cfg.types.project) { css.push("gantt_project"); } css.push("gantt_bar_" + gantt2.getTaskType(task.type)); if (gantt2.isSummaryTask(task)) css.push("gantt_dependent_task"); if (gantt2.isSplitTask(task) && (task.$inlineSplit && task.$inlineSplit.length || (cfg.open_split_tasks && !task.$open && (task.$inlineSplit && task.$inlineSplit.length) || !cfg.open_split_tasks))) { css.push("gantt_split_parent"); } if (cfg.select_task && gantt2.isSelectedTask(itemId)) { css.push("gantt_selected"); } if (itemId == state.drag_id) { css.push("gantt_drag_" + state.drag_mode); if (state.touch_drag) { css.push("gantt_touch_" + state.drag_mode); } } if (state.link_source_id == itemId) { css.push("gantt_link_source"); if (state.link_from_start) { css.push("gantt_link_from_start"); } else { css.push("gantt_link_from_end"); } } if (state.link_target_id == itemId) css.push("gantt_link_target"); if (cfg.highlight_critical_path && gantt2.isCriticalTask) { if (gantt2.isCriticalTask(task)) css.push("gantt_critical_task"); } if (state.link_landing_area && (state.link_target_id && state.link_source_id) && state.link_target_id != state.link_source_id && (state.link_target_id == itemId || state.link_source_id == itemId)) { var from_id = state.link_source_id; var from_start = state.link_from_start; var to_start = state.link_to_start; var allowDrag = gantt2.isLinkAllowed(from_id, itemId, from_start, to_start); var dragClass = ""; if (allowDrag) { if (to_start) dragClass = "link_start_allow"; else dragClass = "link_finish_allow"; } else { if (to_start) dragClass = "link_start_deny"; else dragClass = "link_finish_deny"; } css.push(dragClass); } return css.join(" "); } function _render_pair(parent, css, task, content, config2, margin) { var state = gantt2.getState(); var className, element; if (+task.start_date >= +state.min_date) { className = [css, config2.rtl ? "task_right" : "task_left", "task_start_date"]; element = content(className.join(" ")); element.setAttribute("data-bind-property", "start_date"); if (margin) { element.style.marginLeft = margin + "px"; } parent.appendChild(element); } if (+task.end_date <= +state.max_date) { className = [css, config2.rtl ? "task_left" : "task_right", "task_end_date"]; element = content(className.join(" ")); element.setAttribute("data-bind-property", "end_date"); if (margin) { element.style.marginRight = margin + "px"; } parent.appendChild(element); } } return _render_task_element; } function createTaskRenderer$1(gantt2) { var defaultRender = createTaskRenderer$2(gantt2); return { render: defaultRender, update: null, isInViewPort: isBarInViewport, getVisibleRange: getVisibleTasksRange }; } function resourceHistogramRenderer() { console.error("You are trying to use a Pro feature that is not available in the GPL version."); return { render: function() { }, isInViewPort: function() { }, getVisibleRange: function() { } }; } function createTaskRenderer(gantt2) { const defaultRender = createTaskRenderer$2(gantt2); const renderedNodes = {}; function checkVisibility(child, viewPort, timeline, config2, gantt3) { let isVisible2 = true; if (config2.smart_rendering) { isVisible2 = isBarInViewport(child, viewPort, timeline); } return isVisible2; } function generateChildElement(task, child, timeline, sizes) { const childCopy = gantt2.copy(gantt2.getTask(child.id)); childCopy.$rendered_at = task.id; const displayRollup = gantt2.callEvent("onBeforeRollupTaskDisplay", [childCopy.id, childCopy, task.id]); if (displayRollup === false) { return; } const element = defaultRender(childCopy, timeline); if (!element) { return; } const height = timeline.getBarHeight(task.id, child.type == gantt2.config.types.milestone); const padding = Math.floor((timeline.getItemHeight(task.id) - height) / 2); element.style.top = sizes.top + padding + "px"; element.classList.add("gantt_rollup_child"); element.setAttribute("data-rollup-parent-id", task.id); return element; } function getKey(childId, renderParentId) { return childId + "_" + renderParentId; } function renderRollupTask(task, timeline, config2, viewPort) { if (task.rollup !== false && task.$rollup && task.$rollup.length) { const el = document.createElement("div"), sizes = gantt2.getTaskPosition(task); if (viewPort) { viewPort.y = 0; viewPort.y_end = gantt2.$task_bg.scrollHeight; } task.$rollup.forEach(function(itemId) { if (!gantt2.isTaskExists(itemId)) { return; } const child = gantt2.getTask(itemId); let isVisible2 = checkVisibility(child, viewPort, timeline, config2); if (!isVisible2) { return; } const element = generateChildElement(task, child, timeline, sizes); if (element) { renderedNodes[getKey(child.id, task.id)] = element; el.appendChild(element); } else { renderedNodes[getKey(child.id, task.id)] = false; } }); return el; } return false; } function repaintRollupTask(task, itemNode, timeline, config2, viewPort) { const el = document.createElement("div"), sizes = gantt2.getTaskPosition(task); viewPort.y = 0; viewPort.y_end = gantt2.$task_bg.scrollHeight; task.$rollup.forEach(function(itemId) { const child = gantt2.getTask(itemId); const rollupKey = getKey(child.id, task.id); let isVisible2 = checkVisibility(child, viewPort, timeline, config2); if (isVisible2 !== !!renderedNodes[rollupKey]) { if (isVisible2) { const element = generateChildElement(task, child, timeline, sizes); renderedNodes[rollupKey] = element || false; } else { renderedNodes[rollupKey] = false; } } if (!!renderedNodes[rollupKey]) { el.appendChild(renderedNodes[rollupKey]); } itemNode.innerHTML = ""; itemNode.appendChild(el); }); } return { render: renderRollupTask, update: repaintRollupTask, isInViewPort: isBarInViewport, getVisibleRange: getVisibleTasksRange }; } function getRectangle(item, view, config2) { return { top: view.getItemTop(item.id), height: view.getItemHeight(item.id), left: 0, right: Infinity }; } function getVisibleCellsRange(scale, viewport) { var firstCellIndex = 0; var lastCellIndex = scale.left.length - 1; if (viewport) { for (var i = 0; i < scale.left.length; i++) { var left = scale.left[i]; if (left < viewport.x) { firstCellIndex = i; } if (left > viewport.x_end) { lastCellIndex = i; break; } } } return { start: firstCellIndex, end: lastCellIndex }; } function isColumnVisible(columnIndex, scale, viewPort, gantt2) { var width = scale.width[columnIndex]; if (width <= 0) { return false; } if (!gantt2.config.smart_rendering || isLegacyRender(gantt2)) { return true; } var cellLeftCoord = scale.left[columnIndex] - width; var cellRightCoord = scale.left[columnIndex] + width; return cellLeftCoord <= viewPort.x_end && cellRightCoord >= viewPort.x; } function bgPlaceholder(items, gantt2) { var placeholderConfig = gantt2.config.timeline_placeholder; items = items || []; if (placeholderConfig && items.filter((e) => e.id === "timeline_placeholder_task").length === 0) { var state = gantt2.getState(); var lastTaskId = null; var start_date = state.min_date; var end_date = state.max_date; if (items.length) { lastTaskId = items[items.length - 1].id; } var placeholderTask = { start_date, end_date, row_height: placeholderConfig.height || 0, id: "timeline_placeholder_task", unscheduled: true, lastTaskId, calendar_id: placeholderConfig.calendar || "global", $source: [], $target: [] }; items.push(placeholderTask); } } function createTaskBgRender(gantt2) { var renderedCells = {}; var visibleCells = {}; function isRendered(item, columnIndex) { if (renderedCells[item.id][columnIndex] && renderedCells[item.id][columnIndex].parentNode) { return true; } else { return false; } } function detachRenderedCell(itemId, columnIndex) { if (renderedCells[itemId] && renderedCells[itemId][columnIndex] && renderedCells[itemId][columnIndex].parentNode) { renderedCells[itemId][columnIndex].parentNode.removeChild(renderedCells[itemId][columnIndex]); } } function getCellClassTemplate(view) { var templates2 = view.$getTemplates(); var cssTemplate; if (typeof templates2.task_cell_class !== "undefined") { cssTemplate = templates2.task_cell_class; var log = console.warn || console.log; log("gantt.templates.task_cell_class template is deprecated and will be removed soon. Please use gantt.templates.timeline_cell_class instead."); } else { cssTemplate = templates2.timeline_cell_class; } return cssTemplate; } function getCellContentTemplate(view) { var templates2 = view.$getTemplates(); var contentTemplate = templates2.timeline_cell_content; return contentTemplate; } function renderCells(item, node, view, config2, viewPort) { var cfg = view.getScale(); var count = cfg.count; var cssTemplate = getCellClassTemplate(view); var contentTemplate = getCellContentTemplate(view); if (config2.show_task_cells) { if (!renderedCells[item.id]) { renderedCells[item.id] = {}; } if (!visibleCells[item.id]) { visibleCells[item.id] = {}; } var range = getVisibleCellsRange(cfg, viewPort); for (var i in visibleCells[item.id]) { var index = visibleCells[item.id][i]; if (Number(index) < range.start || Number(index) > range.end) { detachRenderedCell(item.id, index); } } visibleCells[item.id] = {}; for (var columnIndex = range.start; columnIndex <= range.end; columnIndex++) { var cell = renderOneCell(cfg, columnIndex, item, viewPort, count, cssTemplate, contentTemplate, config2); if (!cell && isRendered(item, columnIndex)) { detachRenderedCell(item.id, columnIndex); } else if (cell && !cell.parentNode) { node.appendChild(cell); } } } } function renderOneCell(scale, columnIndex, item, viewPort, count, cssTemplate, contentTemplate, config2) { var width = scale.width[columnIndex], cssclass = ""; if (isColumnVisible(columnIndex, scale, viewPort, gantt2)) { var cssTemplateContent = cssTemplate(item, scale.trace_x[columnIndex]); var htmlTemplateContent = ""; if (contentTemplate) { htmlTemplateContent = contentTemplate(item, scale.trace_x[columnIndex]); } if (config2.static_background) { var customCell = !!(cssTemplateContent || htmlTemplateContent); if (!(config2.static_background_cells && customCell)) { return null; } } if (renderedCells[item.id][columnIndex]) { visibleCells[item.id][columnIndex] = columnIndex; return renderedCells[item.id][columnIndex]; } var cell = document.createElement("div"); cell.style.width = width + "px"; cssclass = "gantt_task_cell" + (columnIndex == count - 1 ? " gantt_last_cell" : ""); if (cssTemplateContent) { cssclass += " " + cssTemplateContent; } cell.className = cssclass; if (htmlTemplateContent) { cell.innerHTML = htmlTemplateContent; } cell.style.position = "absolute"; cell.style.left = scale.left[columnIndex] + "px"; renderedCells[item.id][columnIndex] = cell; visibleCells[item.id][columnIndex] = columnIndex; return cell; } return null; } function _render_bg_line(item, view, config2, viewPort) { var templates2 = view.$getTemplates(); var cfg = view.getScale(); var count = cfg.count; if (config2.static_background && !config2.static_background_cells) { return null; } var row = document.createElement("div"); var cellCssTemplate = getCellClassTemplate(view); var cellHtmlTemplate = getCellContentTemplate(view); var range; if (!viewPort || !config2.smart_rendering || isLegacyRender(gantt2)) { range = { start: 0, end: count - 1 }; } else { range = getVisibleCellsRange(cfg, viewPort.x); } if (config2.show_task_cells) { renderedCells[item.id] = {}; visibleCells[item.id] = {}; for (var columnIndex = range.start; columnIndex <= range.end; columnIndex++) { var cell = renderOneCell(cfg, columnIndex, item, viewPort, count, cellCssTemplate, cellHtmlTemplate, config2); if (cell) { row.appendChild(cell); } } } const store = view.$config.rowStore; const odd = store.getIndexById(item.id) % 2 !== 0; var cssTemplate = templates2.task_row_class(item.start_date, item.end_date, item); var css = "gantt_task_row" + (odd ? " odd" : "") + (cssTemplate ? " " + cssTemplate : ""); if (store.isSelected(item.id)) { css += " gantt_selected"; } row.className = css; if (config2.smart_rendering) { row.style.position = "absolute"; row.style.top = view.getItemTop(item.id) + "px"; row.style.width = "100%"; } else { row.style.position = "relative"; } row.style.height = view.getItemHeight(item.id) + "px"; if (item.id == "timeline_placeholder_task") { var placeholderTop = 0; if (item.lastTaskId) { var lastTaskTop = view.getItemTop(item.lastTaskId); var lastTaskHeight = view.getItemHeight(item.lastTaskId); placeholderTop = lastTaskTop + lastTaskHeight; } var maxHeight = item.row_height || view.$task_data.offsetHeight; var placeholderHeight = maxHeight - placeholderTop; if (placeholderHeight < 0) { placeholderHeight = 0; } if (config2.smart_rendering) { row.style.top = placeholderTop + "px"; } row.style.height = placeholderHeight + "px"; } if (view.$config.item_attribute) { row.setAttribute(view.$config.item_attribute, item.id); row.setAttribute(view.$config.bind + "_id", item.id); } return row; } return { render: _render_bg_line, update: renderCells, getRectangle, getVisibleRange: getVisibleTasksRange, prepareData: bgPlaceholder }; } function createLinkRender(gantt2) { function _render_link_element(link, view, config2) { var source = gantt2.getTask(link.source); if (source.hide_bar) { return; } var target = gantt2.getTask(link.target); if (target.hide_bar) { return; } var pt = path_builder.get_endpoint(link, view, source, target); var dy = pt.e_y - pt.y; var dx = pt.e_x - pt.x; if (!dx && !dy) { return null; } var dots = path_builder.get_points(link, view, source, target); const lines = drawer.get_lines(dots, view); const shapes = transform_lines_to_shapes(lines.filter((l) => l.size > 0), config2); const div = render_shapes(shapes, view, link, config2); var css = "gantt_task_link"; if (link.color) { css += " gantt_link_inline_color"; } var cssTemplate = gantt2.templates.link_class ? gantt2.templates.link_class(link) : ""; if (cssTemplate) { css += " " + cssTemplate; } if (config2.highlight_critical_path && gantt2.isCriticalLink) { if (gantt2.isCriticalLink(link)) css += " gantt_critical_link"; } div.className = css; if (view.$config.link_attribute) { div.setAttribute(view.$config.link_attribute, link.id); div.setAttribute("link_id", link.id); } if (link.color) { div.style.setProperty("--dhx-gantt-link-background", link.color); } gantt2._waiAria.linkAttr(link, div); return div; } function render_shapes(shapes, view, link, config2) { const container = document.createElement("div"); shapes.forEach((shape) => { let element; if (shape.type === "line") { element = drawer.render_line(shape.data, null, view, link.source); } else if (shape.type === "corner") { element = drawer.render_corner(shape.data, view); } else if (shape.type === "arrow") { element = drawer.render_arrow(shape.data, config2); } container.appendChild(element); }); return container; } function transform_lines_to_shapes(lines, config2) { const radius = config2.link_radius || 4; const arrowSize = config2.link_arrow_size || 6; const shapes = []; for (let i = 0; i < lines.length; i++) { const line = lines[i]; const nextLine = lines[i + 1]; if (!nextLine || config2.link_radius <= 1) { shapes.push({ type: "line", data: line }); continue; } if (line.direction !== nextLine.direction) { if (line.size < radius || nextLine.size < radius) { shapes.push({ type: "line", data: line }); continue; } line.size -= radius; shapes.push({ type: "line", data: line }); let cornerX = line.x; let cornerY = line.y - config2.link_line_width / 2; switch (line.direction) { case "right": cornerX += line.size; break; case "left": cornerX -= line.size; break; case "down": cornerY += line.size; break; case "up": cornerY -= line.size; break; } const corner = { x: cornerX, y: cornerY, direction: { from: line.direction, to: nextLine.direction }, radius }; shapes.push({ type: "corner", data: corner }); switch (nextLine.direction) { case "right": nextLine.x += radius; nextLine.size -= radius; break; case "left": nextLine.x -= radius; nextLine.size -= radius; break; case "down": nextLine.y += radius; nextLine.size -= radius; break; case "up": nextLine.y -= radius; nextLine.size -= radius; break; } } else { shapes.push({ type: "line", data: line }); } } const lastLine = lines[lines.length - 1]; if (lastLine.direction === "right" || lastLine.direction === "left") { lastLine.size -= arrowSize * 3 / 4; let arrowX = lastLine.direction === "right" ? lastLine.x + lastLine.size : lastLine.x - lastLine.size - arrowSize / 2; let arrowY = lastLine.y - config2.link_line_width / 2 - arrowSize / 2 + 1; if (lastLine.direction === "left") { arrowY -= 1; arrowX -= 2; } else { arrowX -= 1; } const arrow = { x: arrowX, y: arrowY, size: arrowSize, direction: lastLine.direction }; shapes.push({ type: "line", data: lastLine }); shapes.push({ type: "arrow", data: arrow }); } else { shapes.push({ type: "line", data: lastLine }); } return shapes; } var drawer = { current_pos: null, dirs: { left: "left", right: "right", up: "up", down: "down" }, path: [], clear: function() { this.current_pos = null; this.path = []; }, point: function(pos) { this.current_pos = gantt2.copy(pos); }, get_lines: function(dots) { this.clear(); this.point(dots[0]); for (var i = 1; i < dots.length; i++) { this.line_to(dots[i]); } return this.get_path(); }, line_to: function(pos) { var next = gantt2.copy(pos); var prev = this.current_pos; var line = this._get_line(prev, next); this.path.push(line); this.current_pos = next; }, get_path: function() { return this.path; }, get_wrapper_sizes: function(v, view, itemId) { var config2 = view.$getConfig(); var res, wrapper_size = config2.link_wrapper_width, y = v.y - wrapper_size / 2; switch (v.direction) { case this.dirs.left: res = { top: y, height: wrapper_size, lineHeight: wrapper_size, left: v.x - v.size - wrapper_size / 2, width: v.size + wrapper_size }; break; case this.dirs.right: res = { top: y, lineHeight: wrapper_size, height: wrapper_size, left: v.x - wrapper_size / 2, width: v.size + wrapper_size }; break; case this.dirs.up: res = { top: y - v.size, lineHeight: v.size + wrapper_size, height: v.size + wrapper_size, left: v.x - wrapper_size / 2, width: wrapper_size }; break; case this.dirs.down: res = { top: y, lineHeight: v.size + wrapper_size, height: v.size + wrapper_size, left: v.x - wrapper_size / 2, width: wrapper_size }; break; } return res; }, get_line_sizes: function(v, view) { var config2 = view.$getConfig(); var res, line_size = config2.link_line_width, wrapper_size = config2.link_wrapper_width, size = v.size + line_size; switch (v.direction) { case this.dirs.left: case this.dirs.right: res = { height: line_size, width: size, marginTop: (wrapper_size - line_size) / 2, marginLeft: (wrapper_size - line_size) / 2 }; break; case this.dirs.up: case this.dirs.down: res = { height: size, width: line_size, marginTop: (wrapper_size - line_size) / 2, marginLeft: (wrapper_size - line_size) / 2 }; break; } return res; }, render_line: function(v, end, view, itemId) { var pos = this.get_wrapper_sizes(v, view, itemId); var wrapper = document.createElement("div"); wrapper.style.cssText = ["top:" + pos.top + "px", "left:" + pos.left + "px", "height:" + pos.height + "px", "width:" + pos.width + "px"].join(";"); wrapper.className = "gantt_line_wrapper"; var innerPos = this.get_line_sizes(v, view); var inner = document.createElement("div"); inner.style.cssText = ["height:" + innerPos.height + "px", "width:" + innerPos.width + "px", "margin-top:" + innerPos.marginTop + "px", "margin-left:" + innerPos.marginLeft + "px"].join(";"); inner.className = "gantt_link_line_" + v.direction; wrapper.appendChild(inner); return wrapper; }, render_corner: function(corner, view) { const radius = corner.radius; const config2 = view.$getConfig(); const lineWidth = config2.link_line_width || 2; const cornerDiv = document.createElement("div"); cornerDiv.classList.add("gantt_link_corner"); cornerDiv.classList.add(`gantt_link_corner_${corner.direction.from}_${corner.direction.to}`); cornerDiv.style.width = `${radius}px`; cornerDiv.style.height = `${radius}px`; let borderVertical; let borderHorizontal; if (corner.direction.from === "right" && corner.direction.to === "down") { borderVertical = "Right"; borderHorizontal = "Top"; cornerDiv.style.left = `${corner.x - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y}px`; } else if (corner.direction.from === "down" && corner.direction.to === "right") { borderVertical = "Left"; borderHorizontal = "Bottom"; cornerDiv.style.left = `${corner.x - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y}px`; } else if (corner.direction.from === "right" && corner.direction.to === "up") { borderVertical = "Right"; borderHorizontal = "Bottom"; cornerDiv.style.left = `${corner.x - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y - radius}px`; } else if (corner.direction.from === "up" && corner.direction.to === "right") { borderVertical = "Left"; borderHorizontal = "Top"; cornerDiv.style.left = `${corner.x - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y - radius}px`; } else if (corner.direction.from === "left" && corner.direction.to === "down") { borderVertical = "Left"; borderHorizontal = "Top"; cornerDiv.style.left = `${corner.x - radius - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y}px`; } else if (corner.direction.from === "down" && corner.direction.to === "left") { borderVertical = "Right"; borderHorizontal = "Bottom"; cornerDiv.style.left = `${corner.x - radius - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y}px`; } else if (corner.direction.from === "left" && corner.direction.to === "up") { borderVertical = "Left"; borderHorizontal = "Bottom"; cornerDiv.style.left = `${corner.x - radius - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y - radius}px`; } else if (corner.direction.from === "up" && corner.direction.to === "left") { borderVertical = "Right"; borderHorizontal = "Top"; cornerDiv.style.left = `${corner.x - radius - config2.link_line_width / 2}px`; cornerDiv.style.top = `${corner.y - radius}px`; } cornerDiv.style[`border${borderHorizontal}Width`] = `${lineWidth}px`; cornerDiv.style[`border${borderVertical}Width`] = `${lineWidth}px`; cornerDiv.style[`border${borderVertical}Style`] = `solid`; cornerDiv.style[`border${borderHorizontal}Style`] = `solid`; cornerDiv.style[`border${borderHorizontal}${borderVertical}Radius`] = `${radius}px`; return cornerDiv; }, render_arrow(arrow, config2) { var div = document.createElement("div"); var top = arrow.y; var left = arrow.x; var size = config2.link_arrow_size; div.style.setProperty("--dhx-gantt-icon-size", `${size}px`); var className = "gantt_link_arrow gantt_link_arrow_" + arrow.direction; div.style.top = top + "px"; div.style.left = left + "px"; div.className = className; return div; }, _get_line: function(from, to) { var direction = this.get_direction(from, to); var vect = { x: from.x, y: from.y, direction: this.get_direction(from, to) }; if (direction == this.dirs.left || direction == this.dirs.right) { vect.size = Math.abs(from.x - to.x); } else { vect.size = Math.abs(from.y - to.y); } return vect; }, get_direction: function(from, to) { var direction = 0; if (to.x < from.x) { direction = this.dirs.left; } else if (to.x > from.x) { direction = this.dirs.right; } else if (to.y > from.y) { direction = this.dirs.down; } else { direction = this.dirs.up; } return direction; } }; var path_builder = { path: [], clear: function() { this.path = []; }, current: function() { return this.path[this.path.length - 1]; }, point: function(next) { if (!next) return this.current(); this.path.push(gantt2.copy(next)); return next; }, point_to: function(direction, diff, point) { if (!point) point = gantt2.copy(this.point()); else point = { x: point.x, y: point.y }; var dir = drawer.dirs; switch (direction) { case dir.left: point.x -= diff; break; case dir.right: point.x += diff; break; case dir.up: point.y -= diff; break; case dir.down: point.y += diff; break; } return this.point(point); }, get_points: function(link, view, source, target) { var pt = this.get_endpoint(link, view, source, target); var xy = gantt2.config; var dy = pt.e_y - pt.y; var dx = pt.e_x - pt.x; var dir = drawer.dirs; var rowHeight = view.getItemHeight(link.source); this.clear(); this.point({ x: pt.x, y: pt.y }); var shiftX = 2 * xy.link_arrow_size; var lineType = this.get_line_type(link, view.$getConfig()); var forward = pt.e_x > pt.x; if (lineType.from_start && lineType.to_start) { this.point_to(dir.left, shiftX); if (forward) { this.point_to(dir.down, dy); this.point_to(dir.right, dx); } else { this.point_to(dir.right, dx); this.point_to(dir.down, dy); } this.point_to(dir.right, shiftX); } else if (!lineType.from_start && lineType.to_start) { if (dy !== 0) { forward = pt.e_x > pt.x + 2 * shiftX; } this.point_to(dir.right, shiftX); if (forward) { dx -= shiftX; this.point_to(dir.down, dy); this.point_to(dir.right, dx); } else { dx -= 2 * shiftX; var sign = dy > 0 ? 1 : -1; this.point_to(dir.down, sign * (rowHeight / 2)); this.point_to(dir.right, dx); this.point_to(dir.down, sign * (Math.abs(dy) - rowHeight / 2)); this.point_to(dir.right, shiftX); } } else if (!lineType.from_start && !lineType.to_start) { this.point_to(dir.right, shiftX); if (forward) { this.point_to(dir.right, dx); this.point_to(dir.down, dy); } else { this.point_to(dir.down, dy); this.point_to(dir.right, dx); } this.point_to(dir.left, shiftX); } else if (lineType.from_start && !lineType.to_start) { if (dy !== 0) { forward = pt.e_x > pt.x - 2 * shiftX; } this.point_to(dir.left, shiftX); if (!forward) { dx += shiftX; this.point_to(dir.down, dy); this.point_to(dir.right, dx); } else { dx += 2 * shiftX; var sign = dy > 0 ? 1 : -1; this.point_to(dir.down, sign * (rowHeight / 2)); this.point_to(dir.right, dx); this.point_to(dir.down, sign * (Math.abs(dy) - rowHeight / 2)); this.point_to(dir.left, shiftX); } } return this.path; }, get_line_type: function(link, config2) { var types = config2.links; var from_start = false, to_start = false; if (link.type == types.start_to_start) { from_start = to_start = true; } else if (link.type == types.finish_to_finish) { from_start = to_start = false; } else if (link.type == types.finish_to_start) { from_start = false; to_start = true; } else if (link.type == types.start_to_finish) { from_start = true; to_start = false; } else { gantt2.assert(false, "Invalid link type"); } if (config2.rtl) { from_start = !from_start; to_start = !to_start; } return { from_start, to_start }; }, get_endpoint: function(link, view, source, target) { var config2 = view.$getConfig(); var lineType = this.get_line_type(link, config2); var from_start = lineType.from_start, to_start = lineType.to_start; var from = getMilestonePosition(source, view, config2), to = getMilestonePosition(target, view, config2); return { x: from_start ? from.left : from.left + from.width, e_x: to_start ? to.left : to.left + to.width, y: from.top + from.rowHeight / 2 - 1, e_y: to.top + to.rowHeight / 2 - 1 }; } }; function getMilestonePosition(task, view, config2) { var pos = view.getItemPosition(task); let splitParams = getMaxParentHeight(gantt2, view, task); let maxHeight = splitParams.maxHeight; let splitChild = splitParams.splitChild; const baselinesOnDifferentRow = gantt2.config.baselines && (gantt2.config.baselines.render_mode == "separateRow" || gantt2.config.baselines.render_mode == "individualRow"); const baselines2 = baselinesOnDifferentRow && task.baselines && task.baselines.length; if (splitParams.shrinkHeight) { pos.rowHeight = maxHeight; } let milestoneWidth; let milestoneTask = gantt2.getTaskType(task.type) == config2.types.milestone; if (milestoneTask) { let milestoneHeight = view.getBarHeight(task.id, true); milestoneWidth = Math.sqrt(2 * milestoneHeight * milestoneHeight); if (splitParams.shrinkHeight && maxHeight < milestoneHeight) { milestoneHeight = maxHeight; milestoneWidth = maxHeight; } pos.left -= milestoneWidth / 2; pos.width = milestoneWidth; } if (splitChild) { if (maxHeight >= pos.height) { const siblingBaselines = childrenHaveBaselines(gantt2, task.parent); if (baselines2 || siblingBaselines) { if (milestoneTask) { pos.rowHeight = pos.height + 4; pos.left += (pos.width - pos.rowHeight + 4) / 2; pos.width = pos.rowHeight - 3; } else { pos.rowHeight = pos.height + 6; } } else if (milestoneTask) { pos.left += (milestoneWidth - pos.height) / 2; } } else { pos.rowHeight = maxHeight + 2; if (milestoneTask) { pos.left += (pos.width - pos.rowHeight + 4) / 2; pos.width = pos.rowHeight - 3; } } } else if (baselines2) { pos.rowHeight = pos.height + 4; } return pos; } return { render: _render_link_element, update: null, isInViewPort: isLinkInViewPort, getVisibleRange: getVisibleRange() }; } function isInViewPort(item, viewport, view, config2, gantt2) { if (gantt2.$ui.getView("grid") && (gantt2.config.keyboard_navigation && gantt2.getSelectedId() || gantt2.ext.inlineEditors && gantt2.ext.inlineEditors.getState().id)) { if (!item.$expanded_branch) return false; return true; } var top = view.getItemTop(item.id); var height = view.getItemHeight(item.id); if (top > viewport.y_end || top + height < viewport.y) { return false; } return true; } function createGridLineRender(gantt2) { function _render_grid_item(item, view, config2, viewport) { var columns = view.getGridColumns(); var templates2 = view.$getTemplates(); var store = view.$config.rowStore; var cells = []; var has_child; for (var i = 0; i < columns.length; i++) { var last = i == columns.length - 1; var col = columns[i]; var cell; var value; var textValue; if (col.name == "add") { var aria = gantt2._waiAria.gridAddButtonAttrString(col); value = "
"; textValue = ""; } else { if (col.template) value = col.template(item); else value = item[col.name]; if (isDate(value)) { value = templates2.date_grid(value, item, col.name); } if (value === null || value === void 0) { value = ""; } textValue = value; value = "
" + value + "
"; } var css = "gantt_cell" + (last ? " gantt_last_cell" : ""); var tree = []; if (col.tree) { css += " gantt_cell_tree"; for (var j = 0; j < item.$level; j++) tree.push(templates2.grid_indent(item)); has_child = store.hasChild(item.id) && !(gantt2.isSplitTask(item) && !gantt2.config.open_split_tasks); if (has_child) { tree.push(templates2.grid_open(item)); tree.push(templates2.grid_folder(item)); } else { tree.push(templates2.grid_blank(item)); tree.push(templates2.grid_file(item)); } } var style = "width:" + (col.width - (last ? 1 : 0)) + "px;"; if (this.defined(col.align)) { var flexAlign = { right: "flex-end", left: "flex-start", center: "center" }; var justifyContent = flexAlign[col.align]; style += "text-align:" + col.align + ";justify-content:" + justifyContent + ";"; } var aria = gantt2._waiAria.gridCellAttrString(col, textValue, item); tree.push(value); cell = "
" + tree.join("") + "
"; cells.push(cell); } css = ""; const storeName = store.$config.name; switch (storeName) { case "task": css = gantt2.getGlobalTaskIndex(item.id) % 2 === 0 ? "" : " odd"; break; case "resource": css = store.visibleOrder.indexOf(item.id) % 2 === 0 ? "" : " odd"; break; } css += item.$transparent ? " gantt_transparent" : ""; css += item.$dataprocessor_class ? " " + item.$dataprocessor_class : ""; if (templates2.grid_row_class) { var css_template = templates2.grid_row_class.call(gantt2, item.start_date, item.end_date, item); if (css_template) css += " " + css_template; } if (store.isSelected(item.id)) { css += " gantt_selected"; } var el = document.createElement("div"); el.className = "gantt_row" + css + " gantt_row_" + gantt2.getTaskType(item.type); var height = view.getItemHeight(item.id); el.style.height = height + "px"; el.style.lineHeight = height + "px"; if (config2.smart_rendering) { el.style.position = "absolute"; el.style.left = "0px"; el.style.top = view.getItemTop(item.id) + "px"; } if (view.$config.item_attribute) { el.setAttribute(view.$config.item_attribute, item.id); el.setAttribute(view.$config.bind + "_id", item.id); } gantt2._waiAria.taskRowAttr(item, el); el.innerHTML = cells.join(""); return el; } function onrender(item, rowNode, view) { var columns = view.getGridColumns(); for (var i = 0; i < columns.length; i++) { var column = columns[i]; if (column.onrender) { var cellNode = rowNode.querySelector(`[data-column-name="${column.name}"]`); if (cellNode) { var content = column.onrender(item, cellNode); if (content && typeof content === "string") { cellNode.innerHTML = content; } else if (content && typeof content === "object") { if (gantt2.config.external_render) { var adapter = gantt2.config.external_render; if (adapter.isElement(content)) { adapter.renderElement(content, cellNode); } } } } } } } return { render: _render_grid_item, update: null, getRectangle: getRowRectangle, isInViewPort, getVisibleRange: getVisibleTasksRange, onrender }; } function createResourceTimelineBuilder(gantt2) { let resourceTaskCache = {}; gantt2.$data.tasksStore.attachEvent("onStoreUpdated", function() { resourceTaskCache = {}; }); function getResourceLoad(resource, resourceProperty, scale, timeline) { const cacheKey = resource.id + "_" + resourceProperty + "_" + scale.unit + "_" + scale.step; let res; if (!resourceTaskCache[cacheKey]) { res = resourceTaskCache[cacheKey] = calculateResourceLoad(resource, resourceProperty, scale, timeline); } else { res = resourceTaskCache[cacheKey]; } return res; } function calculateResourceLoadFromAssignments(items, scale, assignmentsPassed) { const scaleUnit = scale.unit; const scaleStep = scale.step; const timegrid = {}; const precalculatedTimes = {}; for (let i = 0; i < items.length; i++) { const item = items[i]; let task = item; if (assignmentsPassed) { task = gantt2.getTask(item.task_id); } if (task.unscheduled) { continue; } let minDate = item.start_date || task.start_date; let maxDate = item.end_date || task.end_date; if (assignmentsPassed) { if (item.start_date) { minDate = new Date(Math.max(item.start_date.valueOf(), task.start_date.valueOf())); } if (item.end_date) { maxDate = new Date(Math.min(item.end_date.valueOf(), task.end_date.valueOf())); } if (item.mode && item.mode == "fixedDates") { minDate = item.start_date; maxDate = item.end_date; } } let firstColumn = findBinary(scale.trace_x, minDate.valueOf()); let minScaleDate = new Date(scale.trace_x[firstColumn] || gantt2.date[scaleUnit + "_start"](new Date(minDate))); let currDate = new Date(Math.min(minDate.valueOf(), minScaleDate.valueOf())); let calendar = gantt2.config.work_time ? gantt2.getTaskCalendar(task) : gantt2; precalculatedTimes[calendar.id] = {}; while (currDate < maxDate) { const cachedTimes = precalculatedTimes[calendar.id]; let date2 = currDate; const timestamp = date2.valueOf(); currDate = gantt2.date.add(currDate, scaleStep, scaleUnit); if (cachedTimes[timestamp] === false) { continue; } if (!timegrid[timestamp]) { timegrid[timestamp] = { tasks: [], assignments: [] }; } timegrid[timestamp].tasks.push(task); if (assignmentsPassed) { timegrid[timestamp].assignments.push(item); } } } return timegrid; } function calculateResourceLoad(resource, resourceProperty, scale, timeline) { let items; let assignmentsPassed = false; let timegrid = {}; if (gantt2.config.process_resource_assignments && resourceProperty === gantt2.config.resource_property) { if (resource.$role == "task") { items = gantt2.getResourceAssignments(resource.$resource_id, resource.$task_id); } else { items = gantt2.getResourceAssignments(resource.id); } assignmentsPassed = true; } else if (resource.$role == "task") { items = []; } else { items = gantt2.getTaskBy(resourceProperty, resource.id); } timegrid = calculateResourceLoadFromAssignments(items, scale, assignmentsPassed); const scaleUnit = scale.unit; const scaleStep = scale.step; const timetable = []; let start, end, tasks2, assignments, cell; const config2 = timeline.$getConfig(); for (let i = 0; i < scale.trace_x.length; i++) { start = new Date(scale.trace_x[i]); end = gantt2.date.add(start, scaleStep, scaleUnit); cell = timegrid[start.valueOf()] || {}; tasks2 = cell.tasks || []; assignments = cell.assignments || []; if (tasks2.length || config2.resource_render_empty_cells) { timetable.push({ start_date: start, end_date: end, tasks: tasks2, assignments }); } else { timetable.push(null); } } return timetable; } return getResourceLoad; } function generateRenderResourceLine(gantt2) { var getResourceLoad = createResourceTimelineBuilder(gantt2); var renderedResourceLines = {}; function renderResourceLineCell(resource, day, templates2, config2, timeline) { var css = templates2.resource_cell_class(day.start_date, day.end_date, resource, day.tasks, day.assignments); var content = templates2.resource_cell_value(day.start_date, day.end_date, resource, day.tasks, day.assignments); var height = timeline.getItemHeight(resource.id) - 1; if (css || content) { var sizes = timeline.getItemPosition(resource, day.start_date, day.end_date); var el = document.createElement("div"); el.setAttribute(timeline.$config.item_attribute, resource.id); el.className = ["gantt_resource_marker", css].join(" "); el.style.cssText = ["left:" + sizes.left + "px", "width:" + sizes.width + "px", "height:" + height + "px", "line-height:" + height + "px", "top:" + sizes.top + "px"].join(";"); if (content) el.innerHTML = content; return el; } return null; } function detachRenderedResourceLine(id, index) { if (renderedResourceLines[id] && renderedResourceLines[id][index] && renderedResourceLines[id][index].parentNode) { renderedResourceLines[id][index].parentNode.removeChild(renderedResourceLines[id][index]); } } function renderResourceLine(resource, timeline, config2, viewport) { var templates2 = timeline.$getTemplates(); var scale = timeline.getScale(); var timetable = getResourceLoad(resource, config2.resource_property, timeline.getScale(), timeline); var smartRendering = !!viewport; var cells = []; renderedResourceLines[resource.id] = {}; var range = getVisibleCellsRange(scale, viewport); for (var columnIndex = range.start; columnIndex <= range.end; columnIndex++) { var day = timetable[columnIndex]; if (!day) { continue; } if (smartRendering && !isColumnVisible(columnIndex, scale, viewport, gantt2)) { continue; } var cell = renderResourceLineCell(resource, day, templates2, config2, timeline); if (cell) { cells.push(cell); renderedResourceLines[resource.id][columnIndex] = cell; } } var row = null; if (cells.length) { row = document.createElement("div"); for (var i = 0; i < cells.length; i++) { row.appendChild(cells[i]); } } return row; } function updateResourceLine(resource, node, timeline, config2, viewport) { var templates2 = timeline.$getTemplates(); var scale = timeline.getScale(); var timetable = getResourceLoad(resource, config2.resource_property, timeline.getScale(), timeline); var range = getVisibleCellsRange(scale, viewport); var checkedColumns = {}; if (renderedResourceLines && renderedResourceLines[resource.id]) { for (var i in renderedResourceLines[resource.id]) { checkedColumns[i] = i; } } for (var columnIndex = range.start; columnIndex <= range.end; columnIndex++) { var day = timetable[columnIndex]; checkedColumns[columnIndex] = false; if (!day) { continue; } if (!isColumnVisible(columnIndex, scale, viewport, gantt2)) { detachRenderedResourceLine(resource.id, columnIndex); continue; } if (!renderedResourceLines[resource.id] || !renderedResourceLines[resource.id][columnIndex]) { var cell = renderResourceLineCell(resource, day, templates2, config2, timeline); if (cell) { node.appendChild(cell); renderedResourceLines[resource.id][columnIndex] = cell; } } else if (renderedResourceLines[resource.id] && renderedResourceLines[resource.id][columnIndex] && !renderedResourceLines[resource.id][columnIndex].parentNode) { node.appendChild(renderedResourceLines[resource.id][columnIndex]); } } for (var i in checkedColumns) { if (checkedColumns[i] !== false) { detachRenderedResourceLine(resource.id, i); } } } return { render: renderResourceLine, update: updateResourceLine, getRectangle, getVisibleRange: getVisibleTasksRange }; } function createGridTaskRowResizerRender(gantt2) { function _render_grid_item(item, view, viewport) { var config2 = view.$getConfig(); var resize_el = document.createElement("div"); resize_el.className = "gantt_task_grid_row_resize_wrap"; resize_el.style.top = view.getItemTop(item.id) + view.getItemHeight(item.id) + "px"; resize_el.innerHTML = "
"; resize_el.setAttribute(config2.task_grid_row_resizer_attribute, item.id); gantt2._waiAria.rowResizerAttr(resize_el); return resize_el; } return { render: _render_grid_item, update: null, getRectangle: getRowRectangle, getVisibleRange: getVisibleTasksRange }; } function _init_dnd$1(gantt2, grid) { var DnD2 = gantt2.$services.getService("dnd"); if (!grid.$config.bind || !gantt2.getDatastore(grid.$config.bind)) { return; } function locate(e) { return locateAttribute(e, grid.$config.item_attribute); } function getStore() { return gantt2.getDatastore(grid.$config.bind); } function checkPlaceholderTask(id) { return isPlaceholderTask(id, gantt2, getStore()); } var dnd = new DnD2(grid.$grid_data, { updates_per_second: 60 }); if (gantt2.defined(grid.$getConfig().dnd_sensitivity)) dnd.config.sensitivity = grid.$getConfig().dnd_sensitivity; dnd.attachEvent("onBeforeDragStart", gantt2.bind(function(obj, e) { var el = locate(e); if (!el) return false; if (gantt2.hideQuickInfo) gantt2.hideQuickInfo(); if (closest(e.target, ".gantt_grid_editor_placeholder")) { return false; } var id = el.getAttribute(grid.$config.item_attribute); if (checkPlaceholderTask(id)) return false; var datastore = getStore(); var task = datastore.getItem(id); if (gantt2.isReadonly(task)) return false; dnd.config.initial_open_state = task.$open; if (!gantt2.callEvent("onRowDragStart", [id, e.target || e.srcElement, e])) { return false; } }, gantt2)); dnd.attachEvent("onAfterDragStart", gantt2.bind(function(obj, e) { var el = locate(e); dnd.config.marker.innerHTML = el.outerHTML; var element = dnd.config.marker.firstChild; if (element) { element.style.position = "static"; } dnd.config.id = el.getAttribute(grid.$config.item_attribute); var store = getStore(); var task = store.getItem(dnd.config.id); dnd.config.index = store.getBranchIndex(dnd.config.id); dnd.config.parent = task.parent; task.$open = false; task.$transparent = true; this.refreshData(); }, gantt2)); dnd.lastTaskOfLevel = function(level) { var last_item = null; var store = getStore(); var tasks2 = store.getItems(); for (var i = 0, len = tasks2.length; i < len; i++) { if (tasks2[i].$level == level) { last_item = tasks2[i]; } } return last_item ? last_item.id : null; }; dnd._getGridPos = gantt2.bind(function(e) { var pos = getNodePosition(grid.$grid_data); var x = pos.x + grid.$grid.scrollLeft; var y = e.pos.y - 10; var rowHeight = grid.getItemHeight(dnd.config.id); if (y < pos.y) y = pos.y; var gridHeight = grid.getTotalHeight(); if (y > pos.y + gridHeight - rowHeight) y = pos.y + gridHeight - rowHeight; const maxBottom = pos.y + pos.height; if (y > maxBottom - rowHeight) { y = maxBottom - rowHeight; } pos.x = x; pos.y = y; return pos; }, gantt2); dnd._getTargetY = gantt2.bind(function(e) { var pos = getNodePosition(grid.$grid_data); var scrollPos = grid.$state.scrollTop || 0; var maxBottom = gantt2.$grid_data.getBoundingClientRect().height + scrollPos; var y = e.pageY - pos.y + scrollPos; if (y > maxBottom) { y = maxBottom; } else if (y < scrollPos) { y = scrollPos; } return y; }, gantt2); dnd._getTaskByY = gantt2.bind(function(y, dropIndex) { var store = getStore(); y = y || 0; var index = grid.getItemIndexByTopPosition(y); index = dropIndex < index ? index - 1 : index; if (index > store.countVisible() - 1) return null; return store.getIdByIndex(index); }, gantt2); dnd.attachEvent("onDragMove", gantt2.bind(function(obj, e) { var gridDataSizes = gantt2.$grid_data.getBoundingClientRect(); var maxBottom = gridDataSizes.height + gridDataSizes.y + (grid.$state.scrollTop || 0) + window.scrollY; var dd = dnd.config; var pos = dnd._getGridPos(e); gantt2._waiAria.reorderMarkerAttr(dd.marker); var config2 = grid.$getConfig(), store = getStore(); if (pos.y < maxBottom) { dd.marker.style.top = pos.y + "px"; } else { dd.marker.style.top = maxBottom + "px"; } dd.marker.style.left = pos.x + 10 + "px"; const containerSize = getNodePosition(gantt2.$root); if (pos.width > containerSize.width) { dd.marker.style.width = containerSize.width - 10 - 2 + "px"; dd.marker.style.overflow = "hidden"; } var item = store.getItem(dnd.config.id); var targetY = dnd._getTargetY(e); var el = dnd._getTaskByY(targetY, store.getIndexById(item.id)); if (!store.exists(el)) { el = dnd.lastTaskOfLevel(config2.order_branch_free ? item.$level : 0); if (el == dnd.config.id) { el = null; } } function allowedLevel(next2, item2) { return !store.isChildOf(over.id, item2.id) && (next2.$level == item2.$level || config2.order_branch_free); } if (store.exists(el)) { var over = store.getItem(el); var itemTop = grid.getItemTop(over.id); var itemHeight = grid.getItemHeight(over.id); if (itemTop + itemHeight / 2 < targetY) { var index = store.getIndexById(over.id); var nextId = store.getNext(over.id); var next = store.getItem(nextId); if (checkPlaceholderTask(nextId)) { var prevId = store.getPrev(next.id); next = store.getItem(prevId); } if (next) { if (next.id != item.id) { over = next; } else { if (config2.order_branch_free) { if (!(store.isChildOf(item.id, over.id) && store.getChildren(over.id).length == 1)) return; else { store.move(item.id, store.getBranchIndex(over.id) + 1, store.getParent(over.id)); return; } } else { return; } } } else { nextId = store.getIdByIndex(index); next = store.getItem(nextId); if (checkPlaceholderTask(nextId)) { var prevId = store.getPrev(next.id); next = store.getItem(prevId); } if (allowedLevel(next, item) && next.id != item.id) { store.move(item.id, -1, store.getParent(next.id)); return; } } } else if (config2.order_branch_free) { if (over.id != item.id && allowedLevel(over, item) && !checkPlaceholderTask(over.id)) { if (!store.hasChild(over.id)) { over.$open = true; store.move(item.id, -1, over.id); return; } if (store.getIndexById(over.id) || itemHeight / 3 < targetY) return; } } var index = store.getIndexById(over.id), prevId = store.getIdByIndex(index - 1); var prev = store.getItem(prevId); var shift = 1; while ((!prev || prev.id == over.id) && index - shift >= 0) { prevId = store.getIdByIndex(index - shift); prev = store.getItem(prevId); shift++; } if (item.id == over.id || checkPlaceholderTask(over.id)) return; if (allowedLevel(over, item) && item.id != over.id) { store.move(item.id, 0, 0, over.id); } else if (over.$level == item.$level - 1 && !store.getChildren(over.id).length) { store.move(item.id, 0, over.id); } else if (prev && allowedLevel(prev, item) && item.id != prev.id) { store.move(item.id, -1, store.getParent(prev.id)); } } return true; }, gantt2)); dnd.attachEvent("onDragEnd", gantt2.bind(function() { var store = getStore(); var task = store.getItem(dnd.config.id); task.$transparent = false; task.$open = dnd.config.initial_open_state; if (this.callEvent("onBeforeRowDragEnd", [dnd.config.id, dnd.config.parent, dnd.config.index]) === false) { store.move(dnd.config.id, dnd.config.index, dnd.config.parent); task.$drop_target = null; } else { this.callEvent("onRowDragEnd", [dnd.config.id, task.$drop_target]); } gantt2.render(); this.refreshData(); }, gantt2)); } const rowDnd = { init: _init_dnd$1 }; const dropTarget = { createDropTargetObject: function createDropTargetObject(parent) { var res = { targetParent: null, targetIndex: 0, targetId: null, child: false, nextSibling: false, prevSibling: false }; if (parent) { mixin(res, parent, true); } return res; }, nextSiblingTarget: function nextSiblingTarget(dndTaskId, targetTaskId, store) { var result = this.createDropTargetObject(); result.targetId = targetTaskId; result.nextSibling = true; result.targetParent = store.getParent(result.targetId); result.targetIndex = store.getBranchIndex(result.targetId); if (store.getParent(dndTaskId) != result.targetParent || result.targetIndex < store.getBranchIndex(dndTaskId)) { result.targetIndex += 1; } return result; }, prevSiblingTarget: function prevSiblingTarget(dndTaskId, targetTaskId, store) { var result = this.createDropTargetObject(); result.targetId = targetTaskId; result.prevSibling = true; result.targetParent = store.getParent(result.targetId); result.targetIndex = store.getBranchIndex(result.targetId); if (store.getParent(dndTaskId) == result.targetParent && result.targetIndex > store.getBranchIndex(dndTaskId)) { result.targetIndex -= 1; } return result; }, firstChildTarget: function firstChildTarget(dndTaskId, targetTaskId, store) { var result = this.createDropTargetObject(); result.targetId = targetTaskId; result.targetParent = result.targetId; result.targetIndex = 0; result.child = true; return result; }, lastChildTarget: function lastChildTarget(dndTaskId, targetTaskId, store) { var children = store.getChildren(targetTaskId); var result = this.createDropTargetObject(); result.targetId = children[children.length - 1]; result.targetParent = targetTaskId; result.targetIndex = children.length; result.nextSibling = true; return result; } }; function getLast(store) { var current = store.getNext(); while (store.exists(current)) { var next = store.getNext(current); if (!store.exists(next)) { return current; } else { current = next; } } return null; } function findClosesTarget(dndTaskId, taskId, allowedLevel, store, up) { var prev = taskId; while (store.exists(prev)) { var targetLevel = store.calculateItemLevel(store.getItem(prev)); if ((targetLevel === allowedLevel || targetLevel === allowedLevel - 1) && store.getBranchIndex(prev) > -1) { break; } else { prev = up ? store.getPrev(prev) : store.getNext(prev); } } if (store.exists(prev)) { if (store.calculateItemLevel(store.getItem(prev)) === allowedLevel) { return up ? dropTarget.nextSiblingTarget(dndTaskId, prev, store) : dropTarget.prevSiblingTarget(dndTaskId, prev, store); } else { return dropTarget.firstChildTarget(dndTaskId, prev, store); } } return null; } function findTargetAbove(dndTaskId, taskId, allowedLevel, store) { return findClosesTarget(dndTaskId, taskId, allowedLevel, store, true); } function findTargetBelow(dndTaskId, taskId, allowedLevel, store) { return findClosesTarget(dndTaskId, taskId, allowedLevel, store, false); } function getSameLevelDropPosition(dndTaskId, targetTaskId, relTargetPos, eventTop, store, level) { var result; if (targetTaskId !== store.$getRootId()) { var targetTask = store.getItem(targetTaskId); var targetLevel = store.calculateItemLevel(targetTask); if (targetLevel === level) { var prevSibling = store.getPrevSibling(targetTaskId); if (relTargetPos < 0.5 && !prevSibling) { result = dropTarget.prevSiblingTarget(dndTaskId, targetTaskId, store); } else { if (relTargetPos < 0.5) { targetTaskId = prevSibling; } result = dropTarget.nextSiblingTarget(dndTaskId, targetTaskId, store); } } else if (targetLevel > level) { store.eachParent(function(parent) { if (store.calculateItemLevel(parent) === level) { targetTaskId = parent.id; } }, targetTask); result = findTargetAbove(dndTaskId, targetTaskId, level, store); } else { var targetAbove = findTargetAbove(dndTaskId, targetTaskId, level, store); var targetBelow = findTargetBelow(dndTaskId, targetTaskId, level, store); result = relTargetPos < 0.5 ? targetAbove : targetBelow; } } else { var rootId = store.$getRootId(); var rootLevel = store.getChildren(rootId); result = dropTarget.createDropTargetObject(); if (rootLevel.length && eventTop >= 0) { result = findTargetAbove(dndTaskId, getLast(store), level, store); } else { result = findTargetBelow(dndTaskId, rootId, level, store); } } return result; } function getMultiLevelDropPosition(dndTaskId, targetTaskId, relTargetPos, eventTop, store) { var result; if (targetTaskId !== store.$getRootId()) { if (relTargetPos < 0.25) { result = dropTarget.prevSiblingTarget(dndTaskId, targetTaskId, store); } else if (relTargetPos > 0.6 && !(store.hasChild(targetTaskId) && store.getItem(targetTaskId).$open)) { result = dropTarget.nextSiblingTarget(dndTaskId, targetTaskId, store); } else { result = dropTarget.firstChildTarget(dndTaskId, targetTaskId, store); } } else { var rootId = store.$getRootId(); if (store.hasChild(rootId) && eventTop >= 0) { result = dropTarget.lastChildTarget(dndTaskId, rootId, store); } else { result = dropTarget.firstChildTarget(dndTaskId, rootId, store); } } return result; } function highlightPosition(target, root, grid) { var markerPos = getTaskMarkerPosition(target, grid); root.marker.style.left = markerPos.x + 9 + "px"; root.marker.style.width = markerPos.width + "px"; root.marker.style.overflow = "hidden"; var markerLine = root.markerLine; if (!markerLine) { markerLine = document.createElement("div"); markerLine.className = "gantt_drag_marker gantt_grid_dnd_marker"; markerLine.innerHTML = "
"; markerLine.style.pointerEvents = "none"; } if (target.child) { highlightFolder(target, markerLine, grid); } else { highlightRow(target, markerLine, grid); } if (!root.markerLine) { document.body.appendChild(markerLine); root.markerLine = markerLine; } } function removeLineHighlight(root) { if (root.markerLine && root.markerLine.parentNode) { root.markerLine.parentNode.removeChild(root.markerLine); } root.markerLine = null; } function highlightRow(target, markerLine, grid) { var linePos = getLineMarkerPosition(target, grid); var maxBottom = grid.$grid_data.getBoundingClientRect().bottom + window.scrollY; markerLine.innerHTML = "
"; markerLine.style.left = linePos.x + "px"; markerLine.style.height = "4px"; var markerLineTop = linePos.y - 2; markerLine.style.top = markerLineTop + "px"; markerLine.style.width = linePos.width + "px"; if (markerLineTop > maxBottom) { markerLine.style.top = maxBottom + "px"; } return markerLine; } function highlightFolder(target, markerFolder, grid) { var id = target.targetParent; var pos = gridToPageCoordinates({ x: 0, y: grid.getItemTop(id) }, grid); var maxBottom = grid.$grid_data.getBoundingClientRect().bottom + window.scrollY; let folderHighlightWidth = setWidthWithinContainer(grid.$gantt, grid.$grid_data.offsetWidth); markerFolder.innerHTML = "
"; markerFolder.style.width = folderHighlightWidth + "px"; markerFolder.style.top = pos.y + "px"; markerFolder.style.left = pos.x + "px"; markerFolder.style.height = grid.getItemHeight(id) + "px"; if (pos.y > maxBottom) { markerFolder.style.top = maxBottom + "px"; } return markerFolder; } function getLineMarkerPosition(target, grid) { var store = grid.$config.rowStore; var pos = { x: 0, y: 0 }; var indentNode = grid.$grid_data.querySelector(".gantt_tree_indent"); var indent = 15; var level = 0; if (indentNode) { indent = indentNode.offsetWidth; } var iconWidth = 40; if (target.targetId !== store.$getRootId()) { var itemTop = grid.getItemTop(target.targetId); var itemHeight = grid.getItemHeight(target.targetId); level = store.exists(target.targetId) ? store.calculateItemLevel(store.getItem(target.targetId)) : 0; if (target.prevSibling) { pos.y = itemTop; } else if (target.nextSibling) { var childCount = 0; store.eachItem(function(child) { if (store.getIndexById(child.id) !== -1) childCount++; }, target.targetId); pos.y = itemTop + itemHeight + childCount * itemHeight; } else { pos.y = itemTop + itemHeight; level += 1; } } pos.x = iconWidth + level * indent; pos.width = setWidthWithinContainer(grid.$gantt, Math.max(grid.$grid_data.offsetWidth - pos.x, 0), pos.x); return gridToPageCoordinates(pos, grid); } function gridToPageCoordinates(pos, grid) { var gridPos = getNodePosition(grid.$grid_data); pos.x += gridPos.x + grid.$grid.scrollLeft; pos.y += gridPos.y - grid.$grid_data.scrollTop; return pos; } function getTaskMarkerPosition(e, grid) { var pos = getNodePosition(grid.$grid_data); var ePos = getRelativeEventPosition(e, grid.$grid_data); var x = pos.x + grid.$grid.scrollLeft; var y = ePos.y - 10; var rowHeight = grid.getItemHeight(e.targetId); if (y < pos.y) y = pos.y; var gridHeight = grid.getTotalHeight(); if (y > pos.y + gridHeight - rowHeight) y = pos.y + gridHeight - rowHeight; pos.x = x; pos.y = y; pos.width = setWidthWithinContainer(grid.$gantt, pos.width, 9); return pos; } function setWidthWithinContainer(gantt2, width, offset = 0) { const containerSize = getNodePosition(gantt2.$root); if (width > containerSize.width) { width = containerSize.width - offset - 2; } return width; } const higlighter = { removeLineHighlight, highlightPosition }; function _init_dnd(gantt2, grid) { var DnD2 = gantt2.$services.getService("dnd"); if (!grid.$config.bind || !gantt2.getDatastore(grid.$config.bind)) { return; } function locate(e) { return locateAttribute(e, grid.$config.item_attribute); } function getStore() { return gantt2.getDatastore(grid.$config.bind); } function checkPlaceholderTask(id) { return isPlaceholderTask(id, gantt2, getStore()); } var dnd = new DnD2(grid.$grid_data, { updates_per_second: 60 }); if (gantt2.defined(grid.$getConfig().dnd_sensitivity)) dnd.config.sensitivity = grid.$getConfig().dnd_sensitivity; dnd.attachEvent("onBeforeDragStart", gantt2.bind(function(obj, e) { var el = locate(e); if (!el) return false; if (gantt2.hideQuickInfo) gantt2.hideQuickInfo(); if (closest(e.target, ".gantt_grid_editor_placeholder")) { return false; } var id = el.getAttribute(grid.$config.item_attribute); var datastore = grid.$config.rowStore; var task = datastore.getItem(id); if (gantt2.isReadonly(task) || checkPlaceholderTask(id)) return false; dnd.config.initial_open_state = task.$open; if (!gantt2.callEvent("onRowDragStart", [id, e.target || e.srcElement, e])) { return false; } }, gantt2)); dnd.attachEvent("onAfterDragStart", gantt2.bind(function(obj, e) { var el = locate(e); dnd.config.marker.innerHTML = el.outerHTML; var element = dnd.config.marker.firstChild; if (element) { dnd.config.marker.style.opacity = 0.4; element.style.position = "static"; element.style.pointerEvents = "none"; } dnd.config.id = el.getAttribute(grid.$config.item_attribute); var store = grid.$config.rowStore; var task = store.getItem(dnd.config.id); dnd.config.level = store.calculateItemLevel(task); dnd.config.drop_target = dropTarget.createDropTargetObject({ targetParent: store.getParent(task.id), targetIndex: store.getBranchIndex(task.id), targetId: task.id, nextSibling: true }); task.$open = false; task.$transparent = true; this.refreshData(); }, gantt2)); function getTargetTaskId(e) { var y = getRelativeEventPosition(e, grid.$grid_data).y; var store = grid.$config.rowStore; if (!document.doctype) { y += window.scrollY; } y = y || 0; var scrollPos = grid.$state.scrollTop || 0; var maxBottom = gantt2.$grid_data.getBoundingClientRect().height + scrollPos + window.scrollY; var minTop = scrollPos; var firstVisibleTaskIndex = grid.getItemIndexByTopPosition(grid.$state.scrollTop); if (!store.exists(firstVisibleTaskIndex)) { firstVisibleTaskIndex = store.countVisible() - 1; } if (firstVisibleTaskIndex < 0) { return store.$getRootId(); } var firstVisibleTaskId = store.getIdByIndex(firstVisibleTaskIndex); var firstVisibleTaskPos = grid.$state.scrollTop / grid.getItemHeight(firstVisibleTaskId); var hiddenTaskPart = firstVisibleTaskPos - Math.floor(firstVisibleTaskPos); if (hiddenTaskPart > 0.1 && hiddenTaskPart < 0.9) { maxBottom = maxBottom - grid.getItemHeight(firstVisibleTaskId) * hiddenTaskPart; minTop = minTop + grid.getItemHeight(firstVisibleTaskId) * (1 - hiddenTaskPart); } const gridPosition = getNodePosition(grid.$grid_data); const gridBottom = gridPosition.y + gridPosition.height; const placeholderRowHeight = dnd.config.marker.offsetHeight; if (y + placeholderRowHeight + window.scrollY >= maxBottom) { dnd.config.marker.style.top = gridBottom - placeholderRowHeight + "px"; } if (y >= maxBottom) { y = maxBottom; } else if (y <= minTop) { y = minTop; dnd.config.marker.style.top = gridPosition.y + "px"; } var index = grid.getItemIndexByTopPosition(y); if (index > store.countVisible() - 1 || index < 0) { return store.$getRootId(); } var targetId = store.getIdByIndex(index); if (checkPlaceholderTask(targetId)) { return store.getPrevSibling(targetId); } return store.getIdByIndex(index); } function getDropPosition(e) { var targetTaskId = getTargetTaskId(e); var relTargetPos = null; var store = grid.$config.rowStore; var config2 = grid.$getConfig(); var lockLevel = !config2.order_branch_free; var eventTop = getRelativeEventPosition(e, grid.$grid_data).y; if (!document.doctype) { eventTop += window.scrollY; } if (targetTaskId !== store.$getRootId()) { var rowTop = grid.getItemTop(targetTaskId); var rowHeight = grid.getItemHeight(targetTaskId); relTargetPos = (eventTop - rowTop) / rowHeight; } var result; if (!lockLevel) { result = getMultiLevelDropPosition(dnd.config.id, targetTaskId, relTargetPos, eventTop, store); } else { result = getSameLevelDropPosition(dnd.config.id, targetTaskId, relTargetPos, eventTop, store, dnd.config.level); if (result && result.targetParent && checkPlaceholderTask(result.targetParent)) { targetTaskId = store.getPrevSibling(result.targetParent); result = getSameLevelDropPosition(dnd.config.id, targetTaskId, relTargetPos, eventTop, store, dnd.config.level); } } return result; } dnd.attachEvent("onDragMove", gantt2.bind(function(obj, e) { var target = getDropPosition(e); if (!target || gantt2.callEvent("onBeforeRowDragMove", [dnd.config.id, target.targetParent, target.targetIndex]) === false) { target = dropTarget.createDropTargetObject(dnd.config.drop_target); } higlighter.highlightPosition(target, dnd.config, grid); dnd.config.drop_target = target; gantt2._waiAria.reorderMarkerAttr(dnd.config.marker); this.callEvent("onRowDragMove", [dnd.config.id, target.targetParent, target.targetIndex]); return true; }, gantt2)); dnd.attachEvent("onDragEnd", gantt2.bind(function() { var store = grid.$config.rowStore; var task = store.getItem(dnd.config.id); higlighter.removeLineHighlight(dnd.config); task.$transparent = false; task.$open = dnd.config.initial_open_state; var target = dnd.config.drop_target; if (this.callEvent("onBeforeRowDragEnd", [dnd.config.id, target.targetParent, target.targetIndex]) === false) { task.$drop_target = null; } else { store.move(dnd.config.id, target.targetIndex, target.targetParent); gantt2.render(); this.callEvent("onRowDragEnd", [dnd.config.id, target.targetParent, target.targetIndex]); } store.refresh(task.id); }, gantt2)); } const rowDndMarker = { init: _init_dnd }; var initializer$2 = /* @__PURE__ */ function() { return function(gantt2) { return { onCreated: function(grid) { grid.$config = mixin(grid.$config, { bind: "task" }); if (grid.$config.id == "grid") { this.extendGantt(grid); gantt2.ext.inlineEditors = gantt2.ext._inlineEditors.createEditors(grid); gantt2.ext.inlineEditors.init(); } this._mouseDelegates = create$1(gantt2); }, onInitialized: function(grid) { var config2 = grid.$getConfig(); if (config2.order_branch) { if (config2.order_branch == "marker") { rowDndMarker.init(grid.$gantt, grid); } else { rowDnd.init(grid.$gantt, grid); } } this.initEvents(grid, gantt2); if (grid.$config.id == "grid") { this.extendDom(grid); } }, onDestroyed: function(grid) { if (grid.$config.id == "grid") { gantt2.ext.inlineEditors.detachStore(); } this.clearEvents(grid, gantt2); }, initEvents: function(grid, gantt3) { this._mouseDelegates.delegate("click", "gantt_row", gantt3.bind(function(e, id, trg) { const config2 = grid.$getConfig(); if (id !== null) { const task = this.getTask(id); if (config2.scroll_on_click) { const notOpenIcon = !gantt3._is_icon_open_click(e); const visibleTimeline = gantt3.$ui.getView("timeline"); if (notOpenIcon && visibleTimeline) { this.showDate(task.start_date); } } gantt3.callEvent("onTaskRowClick", [id, trg]); } }, gantt3), grid.$grid); this._mouseDelegates.delegate("click", "gantt_grid_head_cell", gantt3.bind(function(e, id, trg) { var column = trg.getAttribute("data-column-id"); if (!gantt3.callEvent("onGridHeaderClick", [column, e])) return; var config2 = grid.$getConfig(); if (column == "add") { var mouseEvents2 = gantt3.$services.getService("mouseEvents"); mouseEvents2.callHandler("click", "gantt_add", grid.$grid, [e, config2.root_id]); return; } if (config2.sort && column) { var sorting_method = column, conf; for (var i = 0; i < config2.columns.length; i++) { if (config2.columns[i].name == column) { conf = config2.columns[i]; break; } } if (conf && conf.sort !== void 0 && conf.sort !== true) { sorting_method = conf.sort; if (!sorting_method) { return; } } var sort = this._sort && this._sort.direction && this._sort.name == column ? this._sort.direction : "desc"; sort = sort == "desc" ? "asc" : "desc"; this._sort = { name: column, direction: sort }; this.sort(sorting_method, sort == "desc"); } }, gantt3), grid.$grid); this._mouseDelegates.delegate("click", "gantt_add", gantt3.bind(function(e, id, trg) { var config2 = grid.$getConfig(); if (config2.readonly) return; var item = {}; this.createTask(item, id ? id : gantt3.config.root_id); return false; }, gantt3), grid.$grid); }, clearEvents: function(grid, gantt3) { this._mouseDelegates.destructor(); this._mouseDelegates = null; }, extendDom: function(grid) { gantt2.$grid = grid.$grid; gantt2.$grid_scale = grid.$grid_scale; gantt2.$grid_data = grid.$grid_data; }, extendGantt: function(grid) { gantt2.getGridColumns = gantt2.bind(grid.getGridColumns, grid); grid.attachEvent("onColumnResizeStart", function() { return gantt2.callEvent("onColumnResizeStart", arguments); }); grid.attachEvent("onColumnResize", function() { return gantt2.callEvent("onColumnResize", arguments); }); grid.attachEvent("onColumnResizeEnd", function() { return gantt2.callEvent("onColumnResizeEnd", arguments); }); grid.attachEvent("onColumnResizeComplete", function(columns, totalWidth) { gantt2.config.grid_width = totalWidth; }); grid.attachEvent("onBeforeRowResize", function() { return gantt2.callEvent("onBeforeRowResize", arguments); }); grid.attachEvent("onRowResize", function() { return gantt2.callEvent("onRowResize", arguments); }); grid.attachEvent("onBeforeRowResizeEnd", function() { return gantt2.callEvent("onBeforeRowResizeEnd", arguments); }); grid.attachEvent("onAfterRowResize", function() { return gantt2.callEvent("onAfterRowResize", arguments); }); } }; }; }(); function createTaskDND(timeline, gantt2) { var services2 = gantt2.$services; return { drag: null, dragMultiple: {}, _events: { before_start: {}, before_finish: {}, after_finish: {} }, _handlers: {}, init: function() { this._domEvents = gantt2._createDomEventScope(); this.clear_drag_state(); var drag = gantt2.config.drag_mode; this.set_actions(); var stateService = services2.getService("state"); stateService.registerProvider("tasksDnd", bind(function() { return { drag_id: this.drag ? this.drag.id : void 0, drag_mode: this.drag ? this.drag.mode : void 0, drag_from_start: this.drag ? this.drag.left : void 0 }; }, this)); var evs = { before_start: "onBeforeTaskDrag", before_finish: "onBeforeTaskChanged", after_finish: "onAfterTaskDrag" }; for (var stage in this._events) { for (var mode in drag) { this._events[stage][mode] = evs[stage]; } } this._handlers[drag.move] = this._move; this._handlers[drag.resize] = this._resize; this._handlers[drag.progress] = this._resize_progress; }, set_actions: function() { var data2 = timeline.$task_data; this._domEvents.attach(data2, "mousemove", gantt2.bind(function(e) { this.on_mouse_move(e); }, this)); this._domEvents.attach(data2, "mousedown", gantt2.bind(function(e) { this.on_mouse_down(e); }, this)); this._domEvents.attach(document.body, "mouseup", gantt2.bind(function(e) { this.on_mouse_up(e); }, this)); }, _getPositioningContext: function(task) { if (timeline._getPositioningContext) { return timeline._getPositioningContext(task); } return null; }, clear_drag_state: function() { this.drag = { id: null, mode: null, pos: null, start_x: null, start_y: null, obj: null, left: null }; this.dragMultiple = {}; }, _resize: function(task, shift, drag) { var cfg = timeline.$getConfig(); var coords_x = this._drag_task_coords(task, drag); if (drag.left) { task.start_date = gantt2.dateFromPos(coords_x.start + shift, this._getPositioningContext(task)); if (!task.start_date) { task.start_date = new Date(gantt2.getState().min_date); } } else { task.end_date = gantt2.dateFromPos(coords_x.end + shift, this._getPositioningContext(task)); if (!task.end_date) { task.end_date = new Date(gantt2.getState().max_date); } } var minDurationInUnits = this._calculateMinDuration(cfg.min_duration, cfg.duration_unit); if (task.end_date - task.start_date < cfg.min_duration) { if (drag.left) task.start_date = gantt2.calculateEndDate(task.end_date, -minDurationInUnits, cfg.duration_unit, task); else task.end_date = gantt2.calculateEndDate(task.start_date, minDurationInUnits, cfg.duration_unit, task); } gantt2._init_task_timing(task); }, _calculateMinDuration: function(duration, unit) { var inMs = { minute: 6e4, hour: 36e5, day: 864e5, week: 6048e5, month: 24192e5, year: 31356e6 }; return Math.ceil(duration / inMs[unit]); }, _resize_progress: function(task, shift, drag) { var coords_x = this._drag_task_coords(task, drag); var config2 = timeline.$getConfig(); var diffValue = !config2.rtl ? drag.pos.x - coords_x.start : coords_x.start - drag.pos.x; var diff = Math.max(0, diffValue); task.progress = Math.min(1, diff / Math.abs(coords_x.end - coords_x.start)); }, _find_max_shift: function(dragItems, shift) { var correctShift; for (var i in dragItems) { var drag = dragItems[i]; var task = gantt2.getTask(drag.id); if (task.unscheduled) { continue; } var coords_x = this._drag_task_coords(task, drag); var minX = gantt2.posFromDate(new Date(gantt2.getState().min_date), this._getPositioningContext(task)); var maxX = gantt2.posFromDate(new Date(gantt2.getState().max_date), this._getPositioningContext(task)); if (coords_x.end + shift > maxX) { var maxShift = maxX - coords_x.end; if (maxShift < correctShift || correctShift === void 0) { correctShift = maxShift; } } else if (coords_x.start + shift < minX) { var minShift = minX - coords_x.start; if (minShift > correctShift || correctShift === void 0) { correctShift = minShift; } } } return correctShift; }, _move: function(task, shift, drag, multipleDragShift) { var coords_x = this._drag_task_coords(task, drag); var new_start = null, new_end = null; if (multipleDragShift) { new_start = new Date(+drag.obj.start_date + multipleDragShift), new_end = new Date(+drag.obj.end_date + multipleDragShift); } else { new_start = gantt2.dateFromPos(coords_x.start + shift, this._getPositioningContext(task)), new_end = gantt2.dateFromPos(coords_x.end + shift, this._getPositioningContext(task)); } if (!new_start) { task.start_date = new Date(gantt2.getState().min_date); task.end_date = gantt2.dateFromPos(gantt2.posFromDate(task.start_date) + (coords_x.end - coords_x.start), this._getPositioningContext(task)); } else if (!new_end) { task.end_date = new Date(gantt2.getState().max_date); task.start_date = gantt2.dateFromPos(gantt2.posFromDate(task.end_date) - (coords_x.end - coords_x.start), this._getPositioningContext(task)); } else { task.start_date = new_start; task.end_date = new_end; } }, _drag_task_coords: function(t2, drag) { var start = drag.obj_s_x = drag.obj_s_x || gantt2.posFromDate(t2.start_date, this._getPositioningContext(t2)); var end = drag.obj_e_x = drag.obj_e_x || gantt2.posFromDate(t2.end_date, this._getPositioningContext(t2)); return { start, end }; }, _mouse_position_change: function(oldPos, newPos) { var dx = oldPos.x - newPos.x, dy = oldPos.y - newPos.y; return Math.sqrt(dx * dx + dy * dy); }, _is_number: function(n) { return !isNaN(parseFloat(n)) && isFinite(n); }, on_mouse_move: function(e) { if (this.drag.start_drag) { var pos = getRelativeEventPosition(e, gantt2.$task_data); var sX = this.drag.start_drag.start_x, sY = this.drag.start_drag.start_y; if (Date.now() - this.drag.timestamp > 50 || this._is_number(sX) && this._is_number(sY) && this._mouse_position_change({ x: sX, y: sY }, pos) > 20) { this._start_dnd(e); } } var drag = this.drag; if (drag.mode) { if (!checkTimeout(this, 40)) return; this._update_on_move(e); } }, _update_item_on_move: function(shift, id, mode, drag, e, multipleDragShift) { var task = gantt2.getTask(id); var original = gantt2.mixin({}, task); var copy2 = gantt2.mixin({}, task); this._handlers[mode].apply(this, [copy2, shift, drag, multipleDragShift]); gantt2.mixin(task, copy2, true); gantt2.callEvent("onTaskDrag", [task.id, mode, copy2, original, e]); gantt2.mixin(task, copy2, true); gantt2.refreshTask(id); }, _update_on_move: function(e) { var drag = this.drag; var config2 = timeline.$getConfig(); if (drag.mode) { var pos = getRelativeEventPosition(e, timeline.$task_data); if (drag.pos && drag.pos.x == pos.x) return; drag.pos = pos; const task = gantt2.getTask(drag.id); var curr_date = gantt2.dateFromPos(pos.x, this._getPositioningContext(task)); if (!curr_date || isNaN(curr_date.getTime())) return; var shift = pos.x - drag.start_x; if (this._handlers[drag.mode]) { if (drag.mode === config2.drag_mode.move) { var dragHash = {}; if (this._isMultiselect()) { var selectedTasksIds = gantt2.getSelectedTasks(); if (selectedTasksIds.indexOf(drag.id) >= 0) { dragHash = this.dragMultiple; } } var dragProject = false; if (gantt2.isSummaryTask(task) && gantt2.config.drag_project) { var initialDrag = {}; initialDrag[drag.id] = copy(drag); dragProject = true; dragHash = mixin(initialDrag, this.dragMultiple); } var maxShift = this._find_max_shift(dragHash, shift); if (maxShift !== void 0) { shift = maxShift; } this._update_item_on_move(shift, drag.id, drag.mode, drag, e); let multipleDragShift; if (maxShift === void 0) { const newStartPos = gantt2.posFromDate(drag.obj.start_date, this._getPositioningContext(drag.obj)); const newEndPos = gantt2.posFromDate(drag.obj.end_date, this._getPositioningContext(drag.obj)); if (drag.handle_offset === void 0) { const width = newEndPos - newStartPos; const dragPos = drag.start_x - newStartPos; drag.handle_offset = dragPos / width; } const newWidth = Math.abs(newEndPos - newStartPos); let dragX = newStartPos + newWidth * drag.handle_offset; const shiftDate = gantt2.dateFromPos(dragX, this._getPositioningContext(drag.obj)); multipleDragShift = curr_date - shiftDate; } for (var i in dragHash) { var childDrag = dragHash[i]; if (dragProject && childDrag.id != drag.id) { gantt2._bulk_dnd = true; } this._update_item_on_move(shift, childDrag.id, childDrag.mode, childDrag, e, multipleDragShift); } gantt2._bulk_dnd = false; } else { this._update_item_on_move(shift, drag.id, drag.mode, drag, e); } gantt2._update_parents(drag.id); } } }, on_mouse_down: function(e, src) { if (e.button == 2 && e.button !== void 0) return; var config2 = timeline.$getConfig(); var id = gantt2.locate(e); var task = null; if (gantt2.isTaskExists(id)) { task = gantt2.getTask(id); } if (gantt2.isReadonly(task) || this.drag.mode) return; this.clear_drag_state(); src = src || (e.target || e.srcElement); var className = getClassName(src); var drag = this._get_drag_mode(className, src); if (!className || !drag) { if (src.parentNode) return this.on_mouse_down(e, src.parentNode); else return; } if (!drag) { if (gantt2.checkEvent("onMouseDown") && gantt2.callEvent("onMouseDown", [className.split(" ")[0]])) { if (src.parentNode) return this.on_mouse_down(e, src.parentNode); } } else { if (drag.mode && drag.mode != config2.drag_mode.ignore && config2["drag_" + drag.mode]) { id = gantt2.locate(src); task = gantt2.copy(gantt2.getTask(id) || {}); if (gantt2.isReadonly(task)) { this.clear_drag_state(); return false; } if (gantt2.isSummaryTask(task) && !(task.auto_scheduling === false) && !config2.drag_project && drag.mode != config2.drag_mode.progress) { this.clear_drag_state(); return; } drag.id = id; var pos = getRelativeEventPosition(e, gantt2.$task_data); drag.start_x = pos.x; drag.start_y = pos.y; drag.obj = task; this.drag.start_drag = drag; this.drag.timestamp = Date.now(); } else this.clear_drag_state(); } }, _fix_dnd_scale_time: function(task, drag) { var config2 = timeline.$getConfig(); var unit = gantt2.getScale().unit, step = gantt2.getScale().step; if (!config2.round_dnd_dates) { unit = "minute"; step = config2.time_step; } function fixStart(task2) { if (!gantt2.config.correct_work_time) return; var config3 = timeline.$getConfig(); if (!gantt2.isWorkTime(task2.start_date, void 0, task2)) task2.start_date = gantt2.calculateEndDate({ start_date: task2.start_date, duration: -1, unit: config3.duration_unit, task: task2 }); } function fixEnd(task2) { if (!gantt2.config.correct_work_time) return; var config3 = timeline.$getConfig(); if (!gantt2.isWorkTime(new Date(task2.end_date - 1), void 0, task2)) task2.end_date = gantt2.calculateEndDate({ start_date: task2.end_date, duration: 1, unit: config3.duration_unit, task: task2 }); } const dndContext = timeline._getPositioningContext(task); if (drag.mode == config2.drag_mode.resize) { if (drag.left) { task.start_date = gantt2.roundDate({ date: task.start_date, unit, step }); if (dndContext && dndContext.calendar) { task.start_date = dndContext.calendar.getClosestWorkTime({ date: task.start_date, dir: "future" }); } fixStart(task); } else { task.end_date = gantt2.roundDate({ date: task.end_date, unit, step }); if (dndContext && dndContext.calendar) { task.end_date = dndContext.calendar.getClosestWorkTime({ date: task.end_date }); } fixEnd(task); } } else if (drag.mode == config2.drag_mode.move) { task.start_date = gantt2.roundDate({ date: task.start_date, unit, step }); if (dndContext && dndContext.calendar) { task.start_date = dndContext.calendar.getClosestWorkTime({ date: task.start_date, dir: "future" }); } fixStart(task); task.end_date = gantt2.calculateEndDate(task); } }, _fix_working_times: function(task, drag) { var config2 = timeline.$getConfig(); var drag = drag || { mode: config2.drag_mode.move }; if (drag.mode == config2.drag_mode.resize) { if (drag.left) { task.start_date = gantt2.getClosestWorkTime({ date: task.start_date, dir: "future", task }); } else { task.end_date = gantt2.getClosestWorkTime({ date: task.end_date, dir: "past", task }); } } else if (drag.mode == config2.drag_mode.move) { gantt2.correctTaskWorkTime(task); } }, _finalize_mouse_up: function(taskId, config2, drag, e) { var task = gantt2.getTask(taskId); if (config2.work_time && config2.correct_work_time) { this._fix_working_times(task, drag); } this._fix_dnd_scale_time(task, drag); if (!this._fireEvent("before_finish", drag.mode, [taskId, drag.mode, gantt2.copy(drag.obj), e])) { this.clear_drag_state(); if (taskId == drag.id) { drag.obj._dhx_changed = false; gantt2.mixin(task, drag.obj, true); } gantt2.refreshTask(task.id); if (task.$level > 100) { let shouldRepaint = false; gantt2.eachParent(function(parent) { if (!shouldRepaint && parent.type === gantt2.config.types.project) { const initialDates = { start_date: parent.start_date, end_date: parent.end_date }; gantt2.resetProjectDates(parent); if (+initialDates.start_date !== +parent.start_date || +initialDates.end_date !== +parent.end_date) { shouldRepaint = true; } } }, task.id); if (shouldRepaint) { gantt2.refreshData(); } } else { gantt2.eachParent(function(parent) { if (parent.type === gantt2.config.types.project) { const initialDates = { start_date: parent.start_date, end_date: parent.end_date }; gantt2.resetProjectDates(parent); if (+initialDates.start_date !== +parent.start_date || +initialDates.end_date !== +parent.end_date) { gantt2.refreshTask(parent.id); } } }, task.id); } } else { var drag_id = taskId; gantt2._init_task_timing(task); this.clear_drag_state(); gantt2.updateTask(task.id); this._fireEvent("after_finish", drag.mode, [drag_id, drag.mode, e]); } }, on_mouse_up: function(e) { var drag = this.drag; if (drag.mode && drag.id) { var config2 = timeline.$getConfig(); var task = gantt2.getTask(drag.id); var dragMultiple = this.dragMultiple; var finalizingBulkMove = false; var moveCount = 0; if (drag.mode === config2.drag_mode.move) { if (gantt2.isSummaryTask(task) && config2.drag_project || this._isMultiselect()) { finalizingBulkMove = true; moveCount = Object.keys(dragMultiple).length; } } var doFinalize = function doFinalize2() { if (finalizingBulkMove) { for (var i in dragMultiple) { if (dragMultiple[i].id != drag.id) { this._finalize_mouse_up(dragMultiple[i].id, config2, dragMultiple[i], e); } } } this._finalize_mouse_up(drag.id, config2, drag, e); }; if (finalizingBulkMove && moveCount > 10) { gantt2.batchUpdate((function() { doFinalize.call(this); }).bind(this)); } else { doFinalize.call(this); } } this.clear_drag_state(); }, _get_drag_mode: function(className, el) { var config2 = timeline.$getConfig(); var modes = config2.drag_mode; var classes = (className || "").split(" "); var classname = classes[0]; var drag = { mode: null, left: null }; switch (classname) { case "gantt_task_line": case "gantt_task_content": drag.mode = modes.move; break; case "gantt_task_drag": drag.mode = modes.resize; var dragProperty = el.getAttribute("data-bind-property"); if (dragProperty == "start_date") { drag.left = true; } else { drag.left = false; } break; case "gantt_task_progress_drag": drag.mode = modes.progress; break; case "gantt_link_control": case "gantt_link_point": drag.mode = modes.ignore; break; default: drag = null; break; } return drag; }, _start_dnd: function(e) { var drag = this.drag = this.drag.start_drag; delete drag.start_drag; var cfg = timeline.$getConfig(); var id = drag.id; if (!cfg["drag_" + drag.mode] || !gantt2.callEvent("onBeforeDrag", [id, drag.mode, e]) || !this._fireEvent("before_start", drag.mode, [id, drag.mode, e])) { this.clear_drag_state(); } else { delete drag.start_drag; var task = gantt2.getTask(id); if (gantt2.isReadonly(task)) { this.clear_drag_state(); return; } if (this._isMultiselect()) { var selectedTasksIds = gantt2.getSelectedTasks(); if (selectedTasksIds.indexOf(drag.id) >= 0) { forEach(selectedTasksIds, gantt2.bind(function(taskId) { var selectedTask = gantt2.getTask(taskId); if (gantt2.isSummaryTask(selectedTask) && gantt2.config.drag_project && drag.mode == cfg.drag_mode.move) { this._addSubtasksToDragMultiple(selectedTask.id); } this.dragMultiple[taskId] = gantt2.mixin({ id: selectedTask.id, obj: gantt2.copy(selectedTask) }, this.drag); }, this)); } } if (gantt2.isSummaryTask(task) && gantt2.config.drag_project && drag.mode == cfg.drag_mode.move) { this._addSubtasksToDragMultiple(task.id); } gantt2.callEvent("onTaskDragStart", []); } }, _fireEvent: function(stage, mode, params) { gantt2.assert(this._events[stage], "Invalid stage:{" + stage + "}"); var trigger = this._events[stage][mode]; gantt2.assert(trigger, "Unknown after drop mode:{" + mode + "}"); gantt2.assert(params, "Invalid event arguments"); if (!gantt2.checkEvent(trigger)) return true; return gantt2.callEvent(trigger, params); }, round_task_dates: function(task) { var drag_state = this.drag; var config2 = timeline.$getConfig(); if (!drag_state) { drag_state = { mode: config2.drag_mode.move }; } this._fix_dnd_scale_time(task, drag_state); }, destructor: function() { this._domEvents.detachAll(); }, _isMultiselect: function() { return gantt2.config.drag_multiple && !!(gantt2.getSelectedTasks && gantt2.getSelectedTasks().length > 0); }, _addSubtasksToDragMultiple: function(summaryId) { gantt2.eachTask(function(child) { this.dragMultiple[child.id] = gantt2.mixin({ id: child.id, obj: gantt2.copy(child) }, this.drag); }, summaryId, this); } }; } function initTaskDND() { var _tasks_dnd; return { extend: function(timeline) { timeline.roundTaskDates = function(task) { _tasks_dnd.round_task_dates(task); }; }, init: function(timeline, gantt2) { _tasks_dnd = createTaskDND(timeline, gantt2); timeline._tasks_dnd = _tasks_dnd; return _tasks_dnd.init(gantt2); }, destructor: function() { if (_tasks_dnd) { _tasks_dnd.destructor(); _tasks_dnd = null; } } }; } const taskDnD = { createTaskDND: initTaskDND }; var initLinksDND = function(timeline, gantt2) { var _link_landing, _link_target_task, _link_target_task_start, _link_source_task, _link_source_task_start, markerDefaultOffset = 10, scrollDefaultSize = 18; function getDndState() { return { link_source_id: _link_source_task, link_target_id: _link_target_task, link_from_start: _link_source_task_start, link_to_start: _link_target_task_start, link_landing_area: _link_landing }; } var services2 = gantt2.$services; var state = services2.getService("state"); var DnD2 = services2.getService("dnd"); state.registerProvider("linksDnD", getDndState); var start_marker = "task_start_date", end_marker = "task_end_date", link_edge_marker = "gantt_link_point", link_landing_hover_area = "gantt_link_control"; var dnd = new DnD2(timeline.$task_bars, { sensitivity: 0, updates_per_second: 60, mousemoveContainer: gantt2.$root, selector: "." + link_edge_marker, preventDefault: true }); dnd.attachEvent("onBeforeDragStart", gantt2.bind(function(obj, e) { var target = e.target || e.srcElement; resetDndState(); if (gantt2.getState("tasksDnd").drag_id) return false; if (locateClassName(target, link_edge_marker)) { if (locateClassName(target, start_marker)) _link_source_task_start = true; var sid = gantt2.locate(e); _link_source_task = sid; var t2 = gantt2.getTask(sid); if (gantt2.isReadonly(t2)) { resetDndState(); return false; } this._dir_start = { x: dnd.config.original_element_sizes.x + dnd.config.original_element_sizes.width / 2, y: dnd.config.original_element_sizes.y + dnd.config.original_element_sizes.height / 2 }; return true; } else { return false; } }, this)); dnd.attachEvent("onAfterDragStart", gantt2.bind(function(obj, e) { if (gantt2.config.touch) { gantt2.refreshData(); } updateMarkedHtml(dnd.config.marker); }, this)); function getVieportSize() { var root = gantt2.$root; return { right: root.offsetWidth, bottom: root.offsetHeight }; } function getMarkerSize(marker2) { var width = 0, height = 0; if (marker2) { width = marker2.offsetWidth || 0; height = marker2.offsetHeight || 0; } return { width, height }; } function getPosition(e, marker2) { var oldPos = dnd.getPosition(e); var markerSize = getMarkerSize(marker2); var viewportSize = getVieportSize(); var offsetX = gantt2.config.tooltip_offset_x || markerDefaultOffset; var offsetY = gantt2.config.tooltip_offset_y || markerDefaultOffset; var scrollSize = gantt2.config.scroll_size || scrollDefaultSize; var ganttOffsetY = gantt2.$container.getBoundingClientRect().y + window.scrollY; var position = { y: oldPos.y + offsetY, x: oldPos.x + offsetX, bottom: oldPos.y + markerSize.height + offsetY + scrollSize, right: oldPos.x + markerSize.width + offsetX + scrollSize }; if (position.bottom > viewportSize.bottom + ganttOffsetY) { position.y = viewportSize.bottom + ganttOffsetY - markerSize.height - offsetY; } if (position.right > viewportSize.right) { position.x = viewportSize.right - markerSize.width - offsetX; } return position; } dnd.attachEvent("onDragMove", gantt2.bind(function(obj, e) { var dd = dnd.config; var pos = getPosition(e, dd.marker); advanceMarker(dd.marker, pos); var landing = !!locateClassName(e, link_landing_hover_area); var prevTarget = _link_target_task; var prevLanding = _link_landing; var prevToStart = _link_target_task_start; var targ = gantt2.locate(e), to_start = true; var eventTarget = getTargetNode(e); var sameGantt = isChildOf(eventTarget, gantt2.$root); if (!sameGantt) { landing = false; targ = null; } if (landing) { to_start = !locateClassName(e, end_marker); landing = !!targ; } _link_target_task = targ; _link_landing = landing; _link_target_task_start = to_start; if (landing) { var node = locateClassName(e, link_landing_hover_area); const point = node.querySelector(`.${link_edge_marker}`); if (point) { const absCoords = getRelativeNodePosition(point, timeline.$task_bg); this._dir_end = { x: absCoords.x + point.offsetWidth / 2, y: absCoords.y + point.offsetHeight / 2 }; } } else { this._dir_end = getRelativeEventPosition(e, timeline.$task_data); if (gantt2.env.isEdge) { this._dir_end.y += window.scrollY; } } var targetChanged = !(prevLanding == landing && prevTarget == targ && prevToStart == to_start); if (targetChanged) { if (prevTarget) gantt2.refreshTask(prevTarget, false); if (targ) gantt2.refreshTask(targ, false); } if (targetChanged) { updateMarkedHtml(dd.marker); } showDirectingLine(this._dir_start.x, this._dir_start.y, this._dir_end.x, this._dir_end.y); return true; }, this)); dnd.attachEvent("onDragEnd", gantt2.bind(function() { var drag = getDndState(); if (drag.link_source_id && drag.link_target_id && drag.link_source_id != drag.link_target_id) { var type = gantt2._get_link_type(drag.link_from_start, drag.link_to_start); var link = { source: drag.link_source_id, target: drag.link_target_id, type }; if (link.type && gantt2.isLinkAllowed(link)) { if (gantt2.callEvent("onLinkCreated", [link])) { gantt2.addLink(link); } } } resetDndState(); if (gantt2.config.touch) { gantt2.refreshData(); } else { if (drag.link_source_id) gantt2.refreshTask(drag.link_source_id, false); if (drag.link_target_id) gantt2.refreshTask(drag.link_target_id, false); } removeDirectionLine(); }, this)); function updateMarkedHtml(marker2) { var link = getDndState(); if (link.link_source_id && link.link_target_id) { if (gantt2.isLinkAllowed(link.link_source_id, link.link_target_id, link.link_from_start, link.link_to_start)) ; } var className = gantt2.templates.drag_link_class(link.link_source_id, link.link_from_start, link.link_target_id, link.link_to_start); var html = "
" + gantt2.templates.drag_link(link.link_source_id, link.link_from_start, link.link_target_id, link.link_to_start) + "
"; marker2.innerHTML = html; } function advanceMarker(marker2, pos) { marker2.style.left = pos.x + "px"; marker2.style.top = pos.y + "px"; } function resetDndState() { _link_source_task = _link_source_task_start = _link_target_task = null; _link_target_task_start = true; } function showDirectingLine(s_x, s_y, e_x, e_y) { var div = getDirectionLine(); var link = getDndState(); var css = ["gantt_link_direction"]; if (gantt2.templates.link_direction_class) { css.push(gantt2.templates.link_direction_class(link.link_source_id, link.link_from_start, link.link_target_id, link.link_to_start)); } var dist = Math.sqrt(Math.pow(e_x - s_x, 2) + Math.pow(e_y - s_y, 2)); dist = Math.max(0, dist - 3); if (!dist) return; div.className = css.join(" "); var tan = (e_y - s_y) / (e_x - s_x), angle = Math.atan(tan); if (coordinateCircleQuarter(s_x, e_x, s_y, e_y) == 2) { angle += Math.PI; } else if (coordinateCircleQuarter(s_x, e_x, s_y, e_y) == 3) { angle -= Math.PI; } var sin = Math.sin(angle), cos = Math.cos(angle), top = Math.round(s_y), left = Math.round(s_x); var style = ["-webkit-transform: rotate(" + angle + "rad)", "-moz-transform: rotate(" + angle + "rad)", "-ms-transform: rotate(" + angle + "rad)", "-o-transform: rotate(" + angle + "rad)", "transform: rotate(" + angle + "rad)", "width:" + Math.round(dist) + "px"]; if (window.navigator.userAgent.indexOf("MSIE 8.0") != -1) { style.push('-ms-filter: "' + ieTransform(sin, cos) + '"'); var shiftLeft = Math.abs(Math.round(s_x - e_x)), shiftTop = Math.abs(Math.round(e_y - s_y)); switch (coordinateCircleQuarter(s_x, e_x, s_y, e_y)) { case 1: top -= shiftTop; break; case 2: left -= shiftLeft; top -= shiftTop; break; case 3: left -= shiftLeft; break; } } style.push("top:" + top + "px"); style.push("left:" + left + "px"); div.style.cssText = style.join(";"); } function ieTransform(sin, cos) { return "progid:DXImageTransform.Microsoft.Matrix(M11 = " + cos + ",M12 = -" + sin + ",M21 = " + sin + ",M22 = " + cos + ",SizingMethod = 'auto expand')"; } function coordinateCircleQuarter(sX, eX, sY, eY) { if (eX >= sX) { if (eY <= sY) { return 1; } else { return 4; } } else { if (eY <= sY) { return 2; } else { return 3; } } } function getDirectionLine() { if (!dnd._direction || !dnd._direction.parentNode) { dnd._direction = document.createElement("div"); timeline.$task_links.appendChild(dnd._direction); } return dnd._direction; } function removeDirectionLine() { if (dnd._direction) { if (dnd._direction.parentNode) dnd._direction.parentNode.removeChild(dnd._direction); dnd._direction = null; } } gantt2.attachEvent("onGanttRender", gantt2.bind(function() { if (dnd._direction) { showDirectingLine(this._dir_start.x, this._dir_start.y, this._dir_end.x, this._dir_end.y); } }, this)); }; const linkDnD = { createLinkDND: function() { return { init: initLinksDND }; } }; var initializer$1 = /* @__PURE__ */ function() { return function(gantt2) { var services2 = gantt2.$services; return { onCreated: function(timeline) { var config2 = timeline.$config; config2.bind = defined(config2.bind) ? config2.bind : "task"; config2.bindLinks = defined(config2.bindLinks) ? config2.bindLinks : "link"; timeline._linksDnD = linkDnD.createLinkDND(); timeline._tasksDnD = taskDnD.createTaskDND(); timeline._tasksDnD.extend(timeline); this._mouseDelegates = create$1(gantt2); }, onInitialized: function(timeline) { this._attachDomEvents(gantt2); this._attachStateProvider(gantt2, timeline); timeline._tasksDnD.init(timeline, gantt2); timeline._linksDnD.init(timeline, gantt2); if (timeline.$config.id == "timeline") { this.extendDom(timeline); } }, onDestroyed: function(timeline) { this._clearDomEvents(gantt2); this._clearStateProvider(gantt2); if (timeline._tasksDnD) { timeline._tasksDnD.destructor(); } }, extendDom: function(timeline) { gantt2.$task = timeline.$task; gantt2.$task_scale = timeline.$task_scale; gantt2.$task_data = timeline.$task_data; gantt2.$task_bg = timeline.$task_bg; gantt2.$task_links = timeline.$task_links; gantt2.$task_bars = timeline.$task_bars; }, _clearDomEvents: function() { this._mouseDelegates.destructor(); this._mouseDelegates = null; }, _attachDomEvents: function(gantt3) { function _delete_link_handler(id, e) { if (id && this.callEvent("onLinkDblClick", [id, e])) { var link = this.getLink(id); if (this.isReadonly(link)) return; var title = ""; var question = this.locale.labels.link + " " + this.templates.link_description(this.getLink(id)) + " " + this.locale.labels.confirm_link_deleting; window.setTimeout(function() { gantt3._delete_link_confirm({ link, message: question, title, callback: function() { gantt3.deleteLink(id); } }); }, this.config.touch ? 300 : 1); } } this._mouseDelegates.delegate("click", "gantt_task_link", gantt3.bind(function(e, trg) { var id = this.locate(e, this.config.link_attribute); if (id) { this.callEvent("onLinkClick", [id, e]); } }, gantt3), this.$task); this._mouseDelegates.delegate("click", "gantt_scale_cell", gantt3.bind(function(e, trg) { var pos = getRelativeEventPosition(e, gantt3.$task_data); var date2 = gantt3.dateFromPos(pos.x); var coll = Math.floor(gantt3.columnIndexByDate(date2)); var coll_date = gantt3.getScale().trace_x[coll]; gantt3.callEvent("onScaleClick", [e, coll_date]); }, gantt3), this.$task); this._mouseDelegates.delegate("doubleclick", "gantt_task_link", gantt3.bind(function(e, id, trg) { var id = this.locate(e, gantt3.config.link_attribute); _delete_link_handler.call(this, id, e); }, gantt3), this.$task); this._mouseDelegates.delegate("doubleclick", "gantt_link_point", gantt3.bind(function(e, id, trg) { var id = this.locate(e), task = this.getTask(id); var link = null; if (trg.parentNode && getClassName(trg.parentNode)) { if (getClassName(trg.parentNode).indexOf("_left") > -1) { link = task.$target[0]; } else { link = task.$source[0]; } } if (link) _delete_link_handler.call(this, link, e); return false; }, gantt3), this.$task); }, _attachStateProvider: function(gantt3, timeline) { var self2 = timeline; var state = services2.getService("state"); state.registerProvider("tasksTimeline", function() { return { scale_unit: self2._tasks ? self2._tasks.unit : void 0, scale_step: self2._tasks ? self2._tasks.step : void 0 }; }); }, _clearStateProvider: function() { var state = services2.getService("state"); state.unregisterProvider("tasksTimeline"); } }; }; }(); var initializer = /* @__PURE__ */ function() { return function(gantt2) { return { getVerticalScrollbar: function() { return gantt2.$ui.getView("scrollVer"); }, getHorizontalScrollbar: function() { return gantt2.$ui.getView("scrollHor"); }, _legacyGridResizerClass: function(layout) { var resizers = layout.getCellsByType("resizer"); for (var i = 0; i < resizers.length; i++) { var r = resizers[i]; var gridResizer = false; var prev = r.$parent.getPrevSibling(r.$id); if (prev && prev.$config && prev.$config.id === "grid") { gridResizer = true; } else { var next = r.$parent.getNextSibling(r.$id); if (next && next.$config && next.$config.id === "grid") { gridResizer = true; } } if (gridResizer) { r.$config.css = (r.$config.css ? r.$config.css + " " : "") + "gantt_grid_resize_wrap"; } } }, onCreated: function(layout) { var first = true; this._legacyGridResizerClass(layout); layout.attachEvent("onBeforeResize", function() { var mainTimeline = gantt2.$ui.getView("timeline"); if (mainTimeline) mainTimeline.$config.hidden = mainTimeline.$parent.$config.hidden = !gantt2.config.show_chart; var mainGrid = gantt2.$ui.getView("grid"); if (!mainGrid) return; var colsWidth = mainGrid._getColsTotalWidth(); var hideGrid = !gantt2.config.show_grid || !gantt2.config.grid_width || colsWidth === 0; if (first && !hideGrid && colsWidth !== false) { gantt2.config.grid_width = colsWidth; } mainGrid.$config.hidden = mainGrid.$parent.$config.hidden = hideGrid; if (!mainGrid.$config.hidden) { var grid_limits = mainGrid._getGridWidthLimits(); if (grid_limits[0] && gantt2.config.grid_width < grid_limits[0]) gantt2.config.grid_width = grid_limits[0]; if (grid_limits[1] && gantt2.config.grid_width > grid_limits[1]) gantt2.config.grid_width = grid_limits[1]; if (mainTimeline && gantt2.config.show_chart) { mainGrid.$config.width = gantt2.config.grid_width - 1; if (!mainGrid.$config.scrollable && mainGrid.$config.scrollY && gantt2.$root.offsetWidth) { var ganttContainerWidth = mainGrid.$gantt.$layout.$container.offsetWidth; var verticalScrollbar = gantt2.$ui.getView(mainGrid.$config.scrollY); var verticalScrollbarWidth = verticalScrollbar.$config.width; var gridOverflow = ganttContainerWidth - (mainGrid.$config.width + verticalScrollbarWidth) - 4; if (gridOverflow < 0) { mainGrid.$config.width += gridOverflow; gantt2.config.grid_width += gridOverflow; } } if (!first) { if (mainTimeline && !isChildOf(mainTimeline.$task, layout.$view)) { if (!mainGrid.$config.original_grid_width) { var skinSettings = gantt2.skins[gantt2.skin]; if (skinSettings && skinSettings.config && skinSettings.config.grid_width) { mainGrid.$config.original_grid_width = skinSettings.config.grid_width; } else { mainGrid.$config.original_grid_width = 0; } } gantt2.config.grid_width = mainGrid.$config.original_grid_width; mainGrid.$parent.$config.width = gantt2.config.grid_width; } else { mainGrid.$parent._setContentSize(mainGrid.$config.width, null); gantt2.$layout._syncCellSizes(mainGrid.$parent.$config.group, { value: gantt2.config.grid_width, isGravity: false }); } } else { mainGrid.$parent.$config.width = gantt2.config.grid_width; if (mainGrid.$parent.$config.group) { gantt2.$layout._syncCellSizes(mainGrid.$parent.$config.group, { value: mainGrid.$parent.$config.width, isGravity: false }); } } } else { if (mainTimeline && isChildOf(mainTimeline.$task, layout.$view)) { mainGrid.$config.original_grid_width = gantt2.config.grid_width; } if (!first) { mainGrid.$parent.$config.width = 0; } } } first = false; }); this._initScrollStateEvents(layout); }, _initScrollStateEvents: function(layout) { gantt2._getVerticalScrollbar = this.getVerticalScrollbar; gantt2._getHorizontalScrollbar = this.getHorizontalScrollbar; var vertical = this.getVerticalScrollbar(); var horizontal = this.getHorizontalScrollbar(); if (vertical) { vertical.attachEvent("onScroll", function(oldPos, newPos, dir) { var scrollState = gantt2.getScrollState(); gantt2.callEvent("onGanttScroll", [scrollState.x, oldPos, scrollState.x, newPos]); }); } if (horizontal) { horizontal.attachEvent("onScroll", function(oldPos, newPos, dir) { var scrollState = gantt2.getScrollState(); gantt2.callEvent("onGanttScroll", [oldPos, scrollState.y, newPos, scrollState.y]); var grid = gantt2.$ui.getView("grid"); if (grid && grid.$grid_data && !grid.$config.scrollable) { grid.$grid_data.style.left = grid.$grid.scrollLeft + "px"; grid.$grid_data.scrollLeft = grid.$grid.scrollLeft; } }); } layout.attachEvent("onResize", function() { if (vertical && !gantt2.$scroll_ver) { gantt2.$scroll_ver = vertical.$scroll_ver; } if (horizontal && !gantt2.$scroll_hor) { gantt2.$scroll_hor = horizontal.$scroll_hor; } }); }, _findGridResizer: function(layout, grid) { var resizers = layout.getCellsByType("resizer"); var gridFirst = true; var gridResizer; for (var i = 0; i < resizers.length; i++) { var res = resizers[i]; res._getSiblings(); var prev = res._behind; var next = res._front; if (prev && prev.$content === grid || prev.isChild && prev.isChild(grid)) { gridResizer = res; gridFirst = true; break; } else if (next && next.$content === grid || next.isChild && next.isChild(grid)) { gridResizer = res; gridFirst = false; break; } } return { resizer: gridResizer, gridFirst }; }, onInitialized: function(layout) { var grid = gantt2.$ui.getView("grid"); var resizeInfo = this._findGridResizer(layout, grid); if (resizeInfo.resizer) { var gridFirst = resizeInfo.gridFirst, next = resizeInfo.resizer; if (next.$config.mode !== "x") { return; } var initialWidth; next.attachEvent("onResizeStart", function(prevCellWidth, nextCellWidth) { var grid2 = gantt2.$ui.getView("grid"); var viewCell = grid2 ? grid2.$parent : null; if (viewCell) { var limits = grid2._getGridWidthLimits(); if (!grid2.$config.scrollable) viewCell.$config.minWidth = limits[0]; viewCell.$config.maxWidth = limits[1]; } initialWidth = gridFirst ? prevCellWidth : nextCellWidth; return gantt2.callEvent("onGridResizeStart", [initialWidth]); }); next.attachEvent("onResize", function(newBehindSize, newFrontSize) { var newSize = gridFirst ? newBehindSize : newFrontSize; return gantt2.callEvent("onGridResize", [initialWidth, newSize]); }); next.attachEvent("onResizeEnd", function(oldBackSize, oldFrontSize, newBackSize, newFrontSize) { var oldSize = gridFirst ? oldBackSize : oldFrontSize; var newSize = gridFirst ? newBackSize : newFrontSize; var grid2 = gantt2.$ui.getView("grid"); var viewCell = grid2 ? grid2.$parent : null; if (viewCell) { viewCell.$config.minWidth = void 0; } var res = gantt2.callEvent("onGridResizeEnd", [oldSize, newSize]); if (res && newSize !== 0) { gantt2.config.grid_width = newSize; } return res; }); } }, onDestroyed: function(timeline) { } }; }; }(); function initUI(gantt2) { function attachInitializer(view, initializer2) { var ext = initializer2(gantt2); if (ext.onCreated) ext.onCreated(view); view.attachEvent("onReady", function() { if (ext.onInitialized) ext.onInitialized(view); }); view.attachEvent("onDestroy", function() { if (ext.onDestroyed) ext.onDestroyed(view); }); } var factory2 = uiFactory$1.createFactory(gantt2); factory2.registerView("cell", Cell); factory2.registerView("resizer", Resizer); factory2.registerView("scrollbar", ScrollbarCell); factory2.registerView("layout", Layout, function(view) { var id = view.$config ? view.$config.id : null; if (id === "main") { attachInitializer(view, initializer); } }); factory2.registerView("viewcell", ViewCell); factory2.registerView("multiview", ViewLayout); factory2.registerView("timeline", Timeline, function(view) { var id = view.$config ? view.$config.id : null; if (id === "timeline" || view.$config.bind == "task") { attachInitializer(view, initializer$1); } }); factory2.registerView("grid", Grid, function(view) { var id = view.$config ? view.$config.id : null; if (id === "grid" || view.$config.bind == "task") { attachInitializer(view, initializer$2); } }); factory2.registerView("resourceGrid", Grid); factory2.registerView("GridRL", GridRL); factory2.registerView("resourceTimeline", Timeline); factory2.registerView("resourceHistogram", Timeline); var layersEngine = createLayerEngine(gantt2); var inlineEditors = create(gantt2); gantt2.ext.inlineEditors = inlineEditors; gantt2.ext._inlineEditors = inlineEditors; inlineEditors.init(gantt2); return { factory: factory2, mouseEvents: mouseEvents.init(gantt2), layersApi: layersEngine.init(), render: { gridLine: function() { return createGridLineRender(gantt2); }, taskBg: function() { return createTaskBgRender(gantt2); }, taskBar: function() { return createTaskRenderer$1(gantt2); }, timedProjectBar: function() { return createTaskRenderer$1(gantt2); }, taskRollupBar: function() { return createTaskRenderer(gantt2); }, taskSplitBar: function() { return resourceHistogramRenderer(); }, taskConstraints: function() { return resourceHistogramRenderer(); }, taskDeadline: function() { return resourceHistogramRenderer(); }, taskBaselines: function() { return resourceHistogramRenderer(); }, link: function() { return createLinkRender(gantt2); }, resourceRow: function() { return generateRenderResourceLine(gantt2); }, resourceHistogram: function() { return resourceHistogramRenderer(); }, gridTaskRowResizer: function() { return createGridTaskRowResizerRender(gantt2); } }, layersService: { getDataRender: function(name) { return layersEngine.getDataRender(name, gantt2); }, createDataRender: function(config2) { return layersEngine.createDataRender(config2, gantt2); } } }; } const ui$1 = { init: initUI }; function createLayoutFacade() { function getTimeline(gantt2) { return gantt2.$ui.getView("timeline"); } function getGrid(gantt2) { return gantt2.$ui.getView("grid"); } function getBaseCell(gantt2) { var timeline = getTimeline(gantt2); if (timeline && !timeline.$config.hidden) { return timeline; } else { var grid = getGrid(gantt2); if (grid && !grid.$config.hidden) { return grid; } else { return null; } } } function getVerticalScrollbar(gantt2) { var baseCell = null; var gridDrag = false; var gridMarkers = [".gantt_drag_marker.gantt_grid_resize_area", ".gantt_drag_marker .gantt_row.gantt_row_task", ".gantt_drag_marker.gantt_grid_dnd_marker"]; gridMarkers.forEach(function(selector) { gridDrag = gridDrag || !!document.querySelector(selector); }); if (gridDrag) { baseCell = getGrid(gantt2); } else { baseCell = getBaseCell(gantt2); } if (!baseCell) { return null; } var verticalScrollbar = getAttachedScrollbar(gantt2, baseCell, "scrollY"); return verticalScrollbar; } function getHorizontalScrollbar(gantt2) { var baseCell = getBaseCell(gantt2); if (!baseCell || baseCell.id == "grid") { return null; } var horizontalScrollbar = getAttachedScrollbar(gantt2, baseCell, "scrollX"); return horizontalScrollbar; } function getAttachedScrollbar(gantt2, cell, type) { var attachedScrollbar = cell.$config[type]; var scrollbarView = gantt2.$ui.getView(attachedScrollbar); return scrollbarView; } var DEFAULT_VALUE = "DEFAULT_VALUE"; function tryCall(getView, method, args, fallback) { var view = getView(this); if (!(view && view.isVisible())) { if (fallback) { return fallback(); } else { return DEFAULT_VALUE; } } else { return view[method].apply(view, args); } } return { getColumnIndex: function(name) { var res = tryCall.call(this, getGrid, "getColumnIndex", [name]); if (res === DEFAULT_VALUE) { return 0; } else { return res; } }, dateFromPos: function(x) { var res = tryCall.call(this, getTimeline, "dateFromPos", Array.prototype.slice.call(arguments)); if (res === DEFAULT_VALUE) { return this.getState().min_date; } else { return res; } }, posFromDate: function(date2) { var res = tryCall.call(this, getTimeline, "posFromDate", Array.prototype.slice.call(arguments)); if (res === DEFAULT_VALUE) { return 0; } else { return res; } }, getRowTop: function(index) { var self2 = this; var res = tryCall.call(self2, getTimeline, "getRowTop", [index], function() { return tryCall.call(self2, getGrid, "getRowTop", [index]); }); if (res === DEFAULT_VALUE) { return 0; } else { return res; } }, getTaskTop: function(id) { var self2 = this; var res = tryCall.call(self2, getTimeline, "getItemTop", [id], function() { return tryCall.call(self2, getGrid, "getItemTop", [id]); }); if (res === DEFAULT_VALUE) { return 0; } else { return res; } }, getTaskPosition: function(task, start_date, end_date) { var res = tryCall.call(this, getTimeline, "getItemPosition", [task, start_date, end_date]); if (res === DEFAULT_VALUE) { var top = this.getTaskTop(task.id); var height = this.getTaskBarHeight(task.id); return { left: 0, top, height, width: 0 }; } else { return res; } }, getTaskBarHeight: function(taskId, isMilestoneRender) { var self2 = this; var res = tryCall.call(self2, getTimeline, "getBarHeight", [taskId, isMilestoneRender], function() { return tryCall.call(self2, getGrid, "getItemHeight", [taskId]); }); if (res === DEFAULT_VALUE) { return 0; } else { return res; } }, getTaskHeight: function(taskId) { var self2 = this; var res = tryCall.call(self2, getTimeline, "getItemHeight", [taskId], function() { return tryCall.call(self2, getGrid, "getItemHeight", [taskId]); }); if (res === DEFAULT_VALUE) { return 0; } else { return res; } }, columnIndexByDate: function(date2) { var res = tryCall.call(this, getTimeline, "columnIndexByDate", [date2]); if (res === DEFAULT_VALUE) { return 0; } else { return res; } }, roundTaskDates: function() { tryCall.call(this, getTimeline, "roundTaskDates", []); }, getScale: function() { var res = tryCall.call(this, getTimeline, "getScale", []); if (res === DEFAULT_VALUE) { return null; } else { return res; } }, getTaskNode: function(id) { var timeline = getTimeline(this); if (!timeline || !timeline.isVisible()) { return null; } else { var node = timeline._taskRenderer.rendered[id]; if (!node) { var domAttr = timeline.$config.item_attribute; node = timeline.$task_bars.querySelector("[" + domAttr + "='" + id + "']"); } return node || null; } }, getLinkNode: function(id) { var timeline = getTimeline(this); if (!timeline.isVisible()) { return null; } else { return timeline._linkRenderer.rendered[id]; } }, scrollTo: function(left, top) { var vertical = getVerticalScrollbar(this); var horizontal = getHorizontalScrollbar(this); var oldH = { position: 0 }, oldV = { position: 0 }; if (vertical) { oldV = vertical.getScrollState(); } if (horizontal) { oldH = horizontal.getScrollState(); } var scrollHorizontal = horizontal && left * 1 == left; var scrollVertical = vertical && top * 1 == top; var scrollBoth = scrollHorizontal && scrollVertical; if (scrollBoth) { var verticalViews = vertical._getLinkedViews(); var horizontalViews = horizontal._getLinkedViews(); var commonViews = []; for (var i = 0; i < verticalViews.length; i++) { for (var j = 0; j < horizontalViews.length; j++) { if (verticalViews[i].$config.id && horizontalViews[j].$config.id && verticalViews[i].$config.id === horizontalViews[j].$config.id) { commonViews.push(verticalViews[i].$config.id); } } } } if (scrollHorizontal) { if (commonViews) { commonViews.forEach((function(viewId) { this.$ui.getView(viewId).$config.$skipSmartRenderOnScroll = true; }).bind(this)); } horizontal.scroll(left); if (commonViews) { commonViews.forEach((function(viewId) { this.$ui.getView(viewId).$config.$skipSmartRenderOnScroll = false; }).bind(this)); } } if (scrollVertical) { vertical.scroll(top); } var newV = { position: 0 }, newH = { position: 0 }; if (vertical) { newV = vertical.getScrollState(); } if (horizontal) { newH = horizontal.getScrollState(); } this.callEvent("onGanttScroll", [oldH.position, oldV.position, newH.position, newV.position]); }, showDate: function(date2) { var date_x = this.posFromDate(date2); var scroll_to = Math.max(date_x - this.config.task_scroll_offset, 0); this.scrollTo(scroll_to); }, showTask: function(id) { var pos = this.getTaskPosition(this.getTask(id)); var leftPos = pos.left; if (this.config.rtl) leftPos = pos.left + pos.width; var left = Math.max(leftPos - this.config.task_scroll_offset, 0); var dataHeight = this._scroll_state().y; var top; if (!dataHeight) { top = pos.top; } else { top = pos.top - (dataHeight - this.getTaskBarHeight(id)) / 2; } this.scrollTo(left, top); var gridCell = getGrid(this); var timelineCell = getTimeline(this); if (gridCell && timelineCell && gridCell.$config.scrollY != timelineCell.$config.scrollY) { var gridScrollbar = getAttachedScrollbar(this, gridCell, "scrollY"); gridScrollbar.scrollTo(null, top); } }, _scroll_state: function() { var result = { x: false, y: false, x_pos: 0, y_pos: 0, scroll_size: this.config.scroll_size + 1, x_inner: 0, y_inner: 0 }; var scrollVer = getVerticalScrollbar(this), scrollHor = getHorizontalScrollbar(this); if (scrollHor) { var horState = scrollHor.getScrollState(); if (horState.visible) { result.x = horState.size; result.x_inner = horState.scrollSize; } result.x_pos = horState.position || 0; } if (scrollVer) { var verState = scrollVer.getScrollState(); if (verState.visible) { result.y = verState.size; result.y_inner = verState.scrollSize; } result.y_pos = verState.position || 0; } return result; }, getScrollState: function() { var state = this._scroll_state(); return { x: state.x_pos, y: state.y_pos, inner_width: state.x, inner_height: state.y, width: state.x_inner, height: state.y_inner }; }, getLayoutView: function(cellName) { return this.$ui.getView(cellName); }, scrollLayoutCell: function(cellName, left, top) { const cell = this.$ui.getView(cellName); if (!cell) { return false; } if (left !== null) { const horizontalScroll = this.$ui.getView(cell.$config.scrollX); if (horizontalScroll) { horizontalScroll.scrollTo(left, null); } } if (top !== null) { const verticalScroll = this.$ui.getView(cell.$config.scrollY); if (verticalScroll) { verticalScroll.scrollTo(null, top); } } } }; } function taskLayers(gantt2) { delete gantt2.addTaskLayer; delete gantt2.addLinkLayer; } function _configure(col, data2, force) { for (var key in data2) if (typeof col[key] == "undefined" || force) col[key] = data2[key]; } function _get_skin(force, gantt2) { const styles = getComputedStyle(gantt2.$root); const themeVar = styles.getPropertyValue("--dhx-gantt-theme"); let isCssVarTheme = !!themeVar; let themeName; if (isCssVarTheme) { themeName = themeVar; } else { var skin2 = gantt2.skin; themeName = skin2; if (!skin2 || force) { var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length; i++) { var res = links[i].href.match("dhtmlxgantt_([a-z_]+).css"); if (res) { if (gantt2.skins[res[1]] || !skin2) { themeName = res[1]; break; } } } } } gantt2._theme_info = { theme: themeName, cssVarTheme: isCssVarTheme }; gantt2.skin = themeName || "terrace"; var skinset = gantt2.skins[gantt2.skin] || gantt2.skins["terrace"]; _configure(gantt2.config, skinset.config, force); if (!isCssVarTheme) { gantt2.config.link_radius = 1; } var config2 = gantt2.getGridColumns(); if (config2[1] && !gantt2.defined(config2[1].width)) config2[1].width = skinset._second_column_width; if (config2[2] && !gantt2.defined(config2[2].width)) config2[2].width = skinset._third_column_width; for (var i = 0; i < config2.length; i++) { var column = config2[i]; if (column.name == "add") { if (!column.width) { column.width = 44; } if (!(gantt2.defined(column.min_width) && gantt2.defined(column.max_width))) { column.min_width = column.min_width || column.width; column.max_width = column.max_width || column.width; } if (column.min_width) column.min_width = +column.min_width; if (column.max_width) column.max_width = +column.max_width; if (column.width) { column.width = +column.width; column.width = column.min_width && column.min_width > column.width ? column.min_width : column.width; column.width = column.max_width && column.max_width < column.width ? column.max_width : column.width; } } } if (skinset.config.task_height) { gantt2.config.task_height = skinset.config.task_height || "full"; } if (skinset.config.bar_height) { gantt2.config.bar_height = skinset.config.bar_height || "full"; } if (skinset._lightbox_template) gantt2._lightbox_template = skinset._lightbox_template; if (skinset._redefine_lightbox_buttons) { gantt2.config.buttons_right = skinset._redefine_lightbox_buttons["buttons_right"]; gantt2.config.buttons_left = skinset._redefine_lightbox_buttons["buttons_left"]; } gantt2.resetLightbox(); } function skin(gantt2) { if (!gantt2.resetSkin) { gantt2.resetSkin = function() { this.skin = ""; _get_skin(true, this); }; gantt2.skins = {}; gantt2.attachEvent("onGanttLayoutReady", function() { _get_skin(false, this); monitorThemeChange(); }); } gantt2._addThemeClass = function() { document.documentElement.setAttribute("data-gantt-theme", gantt2.skin); }; gantt2.setSkin = function(value) { const skinChanged = this.skin !== value; this.skin = value; gantt2._addThemeClass(); monitorThemeChange(); if (gantt2.$root) { _get_skin(skinChanged ? false : true, gantt2); this.render(); } }; let monitorIntervalId = null; function monitorThemeChange() { const container = gantt2.$root; if (monitorIntervalId) { clearInterval(monitorIntervalId); } if (container) { monitorIntervalId = setInterval(() => { const csstheme = getComputedStyle(container).getPropertyValue("--dhx-gantt-theme"); if (csstheme && csstheme !== gantt2.skin) { gantt2.setSkin(csstheme); } }, 100); } } gantt2.attachEvent("onDestroy", function() { clearInterval(monitorIntervalId); }); } function skyblue(gantt2) { gantt2.skins.skyblue = { config: { grid_width: 370, row_height: 27, bar_height_padding: 4, scale_height: 27, link_line_width: 1, link_arrow_size: 8, link_radius: 2, lightbox_additional_height: 75 }, _second_column_width: 95, _third_column_width: 80 }; } function meadow(gantt2) { gantt2.skins.meadow = { config: { grid_width: 380, row_height: 27, scale_height: 30, link_line_width: 2, link_arrow_size: 10, bar_height_padding: 4, lightbox_additional_height: 72 }, _second_column_width: 95, _third_column_width: 80 }; } function terrace(gantt2) { gantt2.skins.terrace = { config: { grid_width: 390, row_height: 36, scale_height: 36, link_line_width: 2, link_arrow_size: 12, bar_height_padding: 9, lightbox_additional_height: 75 }, _second_column_width: 100, _third_column_width: 70 }; } function broadway(gantt2) { gantt2.skins.broadway = { config: { grid_width: 390, row_height: 35, scale_height: 35, link_line_width: 1, link_arrow_size: 9, bar_height_padding: 4, lightbox_additional_height: 86 }, _second_column_width: 100, _third_column_width: 80, _lightbox_template: "
 
", _config_buttons_left: {}, _config_buttons_right: { gantt_delete_btn: "icon_delete", gantt_save_btn: "icon_save" } }; } function material(gantt2) { gantt2.skins.material = { config: { grid_width: 411, row_height: 34, scale_height: 36, link_line_width: 2, link_arrow_size: 12, bar_height_padding: 9, lightbox_additional_height: 80 }, _second_column_width: 110, _third_column_width: 75, _redefine_lightbox_buttons: { buttons_left: ["dhx_delete_btn"], buttons_right: ["dhx_cancel_btn", "dhx_save_btn"] } }; gantt2.attachEvent("onAfterTaskDrag", function(id) { var t2 = gantt2.getTaskNode(id); if (t2) { t2.className += " gantt_drag_animation"; setTimeout(function() { var indx = t2.className.indexOf(" gantt_drag_animation"); if (indx > -1) { t2.className = t2.className.slice(0, indx); } }, 200); } }); } function dark(gantt2) { gantt2.skins.dark = { config: { grid_width: 390, row_height: 36, scale_height: 36, link_line_width: 2, link_arrow_size: 12, bar_height_padding: 9, lightbox_additional_height: 75 }, _second_column_width: 100, _third_column_width: 70 }; } function contrast_black(gantt2) { gantt2.skins["contrast_black"] = { config: { grid_width: 390, row_height: 35, scale_height: 35, link_line_width: 2, link_arrow_size: 12, lightbox_additional_height: 75 }, _second_column_width: 100, _third_column_width: 80 }; } function contrast_white(gantt2) { gantt2.skins["contrast_white"] = { config: { grid_width: 390, row_height: 35, scale_height: 35, link_line_width: 2, link_arrow_size: 12, lightbox_additional_height: 75 }, _second_column_width: 100, _third_column_width: 80 }; } function autoscroll(gantt2) { var scrollRange = 50, scrollStep = 30, scrollDelay = 10, scrollSpeed = 50; var interval = null, isMove = false, delayTimeout = null, startPos = { started: false }, eventPos = {}; function isDisplayed(element) { return element && isChildOf(element, gantt2.$root) && element.offsetHeight; } function getAutoscrollContainer() { var element; if (isDisplayed(gantt2.$task)) { element = gantt2.$task; } else if (isDisplayed(gantt2.$grid)) { element = gantt2.$grid; } else { element = gantt2.$root; } return element; } function isScrollState() { var dragMarker = !!document.querySelector(".gantt_drag_marker"); var isResize = !!document.querySelector(".gantt_drag_marker.gantt_grid_resize_area") || !!document.querySelector(".gantt_drag_marker.gantt_row_grid_resize_area"); var isLink = !!document.querySelector(".gantt_link_direction"); var state = gantt2.getState(); var isClickDrag = state.autoscroll; isMove = dragMarker && !isResize && !isLink; return !(!state.drag_mode && !dragMarker || isResize) || isClickDrag; } function defineDelayTimeout(state) { if (delayTimeout) { clearTimeout(delayTimeout); delayTimeout = null; } if (state) { var speed = gantt2.config.autoscroll_speed; if (speed && speed < 10) speed = 10; delayTimeout = setTimeout(function() { interval = setInterval(tick, speed || scrollSpeed); }, gantt2.config.autoscroll_delay || scrollDelay); } } function defineScrollInterval(state) { if (state) { defineDelayTimeout(true); if (!startPos.started) { startPos.x = eventPos.x; startPos.y = eventPos.y; startPos.started = true; } } else { if (interval) { clearInterval(interval); interval = null; } defineDelayTimeout(false); startPos.started = false; } } function autoscrollInterval(event2) { var isScroll = isScrollState(); if ((interval || delayTimeout) && !isScroll) { defineScrollInterval(false); } if (!gantt2.config.autoscroll || !isScroll) { return false; } eventPos = { x: event2.clientX, y: event2.clientY }; if (event2.type == "touchmove") { eventPos.x = event2.targetTouches[0].clientX; eventPos.y = event2.targetTouches[0].clientY; } if (!interval && isScroll) { defineScrollInterval(true); } } function tick() { if (!isScrollState()) { defineScrollInterval(false); return false; } var container = getAutoscrollContainer(); if (!container) { return; } var gridDrag = false; var gridMarkers = [".gantt_drag_marker.gantt_grid_resize_area", ".gantt_drag_marker .gantt_row.gantt_row_task", ".gantt_drag_marker.gantt_grid_dnd_marker"]; gridMarkers.forEach(function(selector) { gridDrag = gridDrag || !!document.querySelector(selector); }); if (gridDrag) { container = gantt2.$grid; } var box = getNodePosition(container); var posX = eventPos.x - box.x; var posY = eventPos.y - box.y + window.scrollY; var scrollLeft = isMove ? 0 : need_scroll(posX, box.width, startPos.x - box.x); var scrollTop = need_scroll(posY, box.height, startPos.y - box.y + window.scrollY); var scrollState = gantt2.getScrollState(); var currentScrollTop = scrollState.y, scrollOuterHeight = scrollState.inner_height, scrollInnerHeight = scrollState.height, currentScrollLeft = scrollState.x, scrollOuterWidth = scrollState.inner_width, scrollInnerWidth = scrollState.width; if (scrollTop && !scrollOuterHeight) { scrollTop = 0; } else if (scrollTop < 0 && !currentScrollTop) { scrollTop = 0; } else if (scrollTop > 0 && currentScrollTop + scrollOuterHeight >= scrollInnerHeight + 2) { scrollTop = 0; } if (scrollLeft && !scrollOuterWidth) { scrollLeft = 0; } else if (scrollLeft < 0 && !currentScrollLeft) { scrollLeft = 0; } else if (scrollLeft > 0 && currentScrollLeft + scrollOuterWidth >= scrollInnerWidth) { scrollLeft = 0; } var step = gantt2.config.autoscroll_step; if (step && step < 2) step = 2; scrollLeft = scrollLeft * (step || scrollStep); scrollTop = scrollTop * (step || scrollStep); if (scrollLeft || scrollTop) { scroll(scrollLeft, scrollTop); } } function need_scroll(pos, boxSize, startCoord) { if (pos - scrollRange < 0 && pos < startCoord) return -1; else if (pos > boxSize - scrollRange && pos > startCoord) return 1; return 0; } function scroll(left, top) { var scrollState = gantt2.getScrollState(); var scrollLeft = null, scrollTop = null; if (left) { scrollLeft = scrollState.x + left; scrollLeft = Math.min(scrollState.width, scrollLeft); scrollLeft = Math.max(0, scrollLeft); } if (top) { scrollTop = scrollState.y + top; scrollTop = Math.min(scrollState.height, scrollTop); scrollTop = Math.max(0, scrollTop); } gantt2.scrollTo(scrollLeft, scrollTop); } gantt2.attachEvent("onGanttReady", function() { if (!isHeadless(gantt2)) { var eventElement = getRootNode(gantt2.$root) || document.body; gantt2.eventRemove(eventElement, "mousemove", autoscrollInterval); gantt2.event(eventElement, "mousemove", autoscrollInterval); gantt2.eventRemove(eventElement, "touchmove", autoscrollInterval); gantt2.event(eventElement, "touchmove", autoscrollInterval); gantt2.eventRemove(eventElement, "pointermove", autoscrollInterval); gantt2.event(eventElement, "pointermove", autoscrollInterval); } }); gantt2.attachEvent("onDestroy", function() { defineScrollInterval(false); }); } if (typeof window !== "undefined" && window.jQuery) { (function($) { var methods = []; $.fn.dhx_gantt = function(config2) { config2 = config2 || {}; if (typeof config2 === "string") { if (methods[config2]) { return methods[config2].apply(this, []); } else { $.error("Method " + config2 + " does not exist on jQuery.dhx_gantt"); } } else { var views = []; this.each(function() { if (this && this.getAttribute) { if (!this.gantt && !(window.gantt.$root == this)) { var newgantt = window.gantt.$container && window.Gantt ? window.Gantt.getGanttInstance() : window.gantt; for (var key in config2) if (key != "data") newgantt.config[key] = config2[key]; newgantt.init(this); if (config2.data) newgantt.parse(config2.data); views.push(newgantt); } else views.push(typeof this.gantt == "object" ? this.gantt : window.gantt); } }); if (views.length === 1) return views[0]; return views; } }; })(window.jQuery); } const jquery_hooks = null; if (typeof window !== "undefined" && window.dhtmlx) { if (!window.dhtmlx.attaches) window.dhtmlx.attaches = {}; window.dhtmlx.attaches.attachGantt = function(start, end, gantt2) { var obj = document.createElement("DIV"); gantt2 = gantt2 || window.gantt; obj.id = "gantt_" + gantt2.uid(); obj.style.width = "100%"; obj.style.height = "100%"; obj.cmp = "grid"; document.body.appendChild(obj); this.attachObject(obj.id); this.dataType = "gantt"; this.dataObj = gantt2; var that = this.vs[this.av]; that.grid = gantt2; gantt2.init(obj.id, start, end); obj.firstChild.style.border = "none"; that.gridId = obj.id; that.gridObj = obj; var method_name = "_viewRestore"; return this.vs[this[method_name]()].grid; }; } if (typeof window !== "undefined" && typeof window.dhtmlXCellObject != "undefined") { window.dhtmlXCellObject.prototype.attachGantt = function(start, end, gantt2) { gantt2 = gantt2 || window.gantt; var obj = document.createElement("DIV"); obj.id = "gantt_" + gantt2.uid(); obj.style.width = "100%"; obj.style.height = "100%"; obj.cmp = "grid"; document.body.appendChild(obj); this.attachObject(obj.id); this.dataType = "gantt"; this.dataObj = gantt2; gantt2.init(obj.id, start, end); obj.firstChild.style.border = "none"; obj = null; this.callEvent("_onContentAttach", []); return this.dataObj; }; } const dhtmlx_hooks = null; const USE_KEY = ["ctrlKey", "altKey", "shiftKey", "metaKey"]; const _defaultScales = [[{ unit: "month", date: "%M", step: 1 }, { unit: "day", date: "%d", step: 1 }], [{ unit: "day", date: "%d %M", step: 1 }], [{ unit: "day", date: "%d %M", step: 1 }, { unit: "hour", date: "%H:00", step: 8 }], [{ unit: "day", date: "%d %M", step: 1 }, { unit: "hour", date: "%H:00", step: 1 }]]; class TimelineZoom { constructor(gantt2) { this.zoomIn = () => { const index = this.getCurrentLevel() - 1; if (index < 0) { return; } this.setLevel(index); }; this.zoomOut = () => { const index = this.getCurrentLevel() + 1; if (index > this._levels.length - 1) { return; } this.setLevel(index); }; this.getCurrentLevel = () => this._activeLevelIndex; this.getLevels = () => this._levels; this.setLevel = (level) => { const zoomLevel = this._getZoomIndexByName(level); if (zoomLevel === -1) { this.$gantt.assert(zoomLevel !== -1, "Invalid zoom level for gantt.ext.zoom.setLevel. " + level + " is not an expected value."); } this._setLevel(zoomLevel, 0); }; this._getZoomIndexByName = (levelName) => { let zoomLevel = -1; if (typeof levelName === "string") { if (!isNaN(Number(levelName)) && this._levels[Number(levelName)]) { zoomLevel = Number(levelName); } else { for (let i = 0; i < this._levels.length; i++) { if (this._levels[i].name === levelName) { zoomLevel = i; break; } } } } else { zoomLevel = levelName; } return zoomLevel; }; this._getVisibleDate = () => { if (!this.$gantt.$task) { return null; } const scrollPos = this.$gantt.getScrollState().x; const viewPort = this.$gantt.$task.offsetWidth; this._visibleDate = this.$gantt.dateFromPos(scrollPos + viewPort / 2); }; this._setLevel = (level, cursorOffset) => { this._activeLevelIndex = level; const gantt3 = this.$gantt; const nextConfig = gantt3.copy(this._levels[this._activeLevelIndex]); const chartConfig = gantt3.copy(nextConfig); delete chartConfig.name; gantt3.mixin(gantt3.config, chartConfig, true); const resourceViews = ["resourceTimeline", "resourceHistogram"]; resourceViews.forEach(function(name) { const resourceView = gantt3.$ui.getView(name); if (resourceView) { const resourceConfig = resourceView.$getConfig(); if (!resourceConfig.fixed_scales) { gantt3.mixin(resourceConfig, chartConfig, true); } } }); const isRendered = !!gantt3.$root && !!gantt3.$task; if (isRendered) { if (cursorOffset) { const cursorDate = this.$gantt.dateFromPos(cursorOffset + this.$gantt.getScrollState().x); this.$gantt.render(); const newPosition = this.$gantt.posFromDate(cursorDate); this.$gantt.scrollTo(newPosition - cursorOffset); } else { const viewPort = this.$gantt.$task.offsetWidth; if (!this._visibleDate) { this._getVisibleDate(); } const middleDate = this._visibleDate; this.$gantt.render(); const newPosition = this.$gantt.posFromDate(middleDate); this.$gantt.scrollTo(newPosition - viewPort / 2); } this.callEvent("onAfterZoom", [this._activeLevelIndex, nextConfig]); } }; this._attachWheelEvent = (config2) => { const event2 = env.isFF ? "wheel" : "mousewheel"; let el; if (typeof config2.element === "function") { el = config2.element(); } else { el = config2.element; } if (!el) { return; } this._domEvents.attach(el, event2, this.$gantt.bind(function(e) { if (this._useKey) { if (USE_KEY.indexOf(this._useKey) < 0) { return false; } if (!e[this._useKey]) { return false; } } if (typeof this._handler === "function") { this._handler.apply(this, [e]); return true; } }, this), { passive: false }); }; this._defaultHandler = (e) => { const timelineOffset = this.$gantt.$task.getBoundingClientRect().x; const cursorOffset = e.clientX - timelineOffset; const wheelY = this.$gantt.env.isFF ? e.deltaY * -40 : e.wheelDelta; let wheelUp = false; if (wheelY > 0) { wheelUp = true; } e.preventDefault(); e.stopPropagation(); this._setScaleSettings(wheelUp, cursorOffset); }; this._setScaleDates = () => { if (this._initialStartDate && this._initialEndDate) { this.$gantt.config.start_date = this._initialStartDate; this.$gantt.config.end_date = this._initialEndDate; } }; this.$gantt = gantt2; this._domEvents = this.$gantt._createDomEventScope(); } init(config2) { if (this.$gantt.env.isNode) { return; } this._initialStartDate = config2.startDate; this._initialEndDate = config2.endDate; this._activeLevelIndex = config2.activeLevelIndex ? config2.activeLevelIndex : 0; this._levels = this._mapScales(config2.levels || _defaultScales); this._handler = config2.handler || this._defaultHandler; this._minColumnWidth = config2.minColumnWidth || 60; this._maxColumnWidth = config2.maxColumnWidth || 240; this._widthStep = config2.widthStep || 3 / 8 * config2.minColumnWidth; this._useKey = config2.useKey; if (!this._initialized) { makeEventable(this); this.$gantt.attachEvent("onGanttScroll", () => { this._getVisibleDate(); }); } this._domEvents.detachAll(); if (config2.trigger === "wheel") { if (this.$gantt.$root) { this._attachWheelEvent(config2); } else { this.$gantt.attachEvent("onGanttLayoutReady", () => { this.$gantt.attachEvent("onGanttRender", () => { this._attachWheelEvent(config2); }, { once: true }); }); } } this._initialized = true; this.setLevel(this._activeLevelIndex); } _mapScales(levels) { return levels.map((l) => { if (Array.isArray(l)) { return { scales: l }; } else { return l; } }); } _setScaleSettings(wheelUp, cursorOffset) { if (wheelUp) { this._stepUp(cursorOffset); } else { this._stepDown(cursorOffset); } } _stepUp(cursorOffset) { if (this._activeLevelIndex >= this._levels.length - 1) { return; } let nextLevel = this._activeLevelIndex; this._setScaleDates(); if (this._widthStep) { let newColumnWidth = this.$gantt.config.min_column_width + this._widthStep; if (newColumnWidth > this._maxColumnWidth) { newColumnWidth = this._minColumnWidth; nextLevel++; } this.$gantt.config.min_column_width = newColumnWidth; } else { nextLevel++; } this._setLevel(nextLevel, cursorOffset); } _stepDown(cursorOffset) { if (this._activeLevelIndex < 1) { return; } let nextLevel = this._activeLevelIndex; this._setScaleDates(); if (this._widthStep) { let newColumnWidth = this.$gantt.config.min_column_width - this._widthStep; if (newColumnWidth < this._minColumnWidth) { newColumnWidth = this._maxColumnWidth; nextLevel--; } this.$gantt.config.min_column_width = newColumnWidth; } else { nextLevel--; } this._setLevel(nextLevel, cursorOffset); } } function plugins(gantt2) { if (!gantt2.ext) { gantt2.ext = {}; } var modules = [autoscroll, jquery_hooks, dhtmlx_hooks]; for (var i = 0; i < modules.length; i++) { if (modules[i]) modules[i](gantt2); } gantt2.ext.zoom = new TimelineZoom(gantt2); } function touch(gantt2) { gantt2.config.touch_drag = 75; gantt2.config.touch = true; gantt2.config.touch_feedback = true; gantt2.config.touch_feedback_duration = 1; gantt2._prevent_touch_scroll = false; gantt2._touch_feedback = function() { if (gantt2.config.touch_feedback) { if (navigator.vibrate) navigator.vibrate(gantt2.config.touch_feedback_duration); } }; gantt2.attachEvent("onGanttReady", function() { if (gantt2.$container) { addTouchEvents(); } }); gantt2.attachEvent("onGanttLayoutReady", function() { if (gantt2.$container) { gantt2.attachEvent("onGanttRender", addTouchEvents, { once: true }); } }); function addTouchEvents() { if (gantt2.config.touch != "force") gantt2.config.touch = gantt2.config.touch && (navigator.userAgent.indexOf("Mobile") != -1 || navigator.userAgent.indexOf("iPad") != -1 || navigator.userAgent.indexOf("Android") != -1 || navigator.userAgent.indexOf("Touch") != -1) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1; if (gantt2.config.touch) { const touchEventsSupported = !gantt2.env.isIE || !!window.navigator.maxTouchPoints; if (touchEventsSupported) { gantt2._touch_events(["touchmove", "touchstart", "touchend"], function(ev) { if (ev.touches && ev.touches.length > 1) return null; if (ev.touches[0]) return { target: ev.target, pageX: ev.touches[0].pageX, pageY: ev.touches[0].pageY, clientX: ev.touches[0].clientX, clientY: ev.touches[0].clientY }; else return ev; }, function(ev) { return ev.defaultPrevented; }); } else if (window.PointerEvent) { gantt2._touch_events(["pointermove", "pointerdown", "pointerup"], function(ev) { if (ev.pointerType == "mouse") return null; return ev; }, function(ev) { return !ev || ev.pointerType == "mouse"; }); } } } function findTargetView(event2) { var allViews = gantt2.$layout.getCellsByType("viewCell"); for (var i = 0; i < allViews.length; i++) { var box = allViews[i].$view.getBoundingClientRect(); if (event2.clientX >= box.left && event2.clientX <= box.right && event2.clientY <= box.bottom && event2.clientY >= box.top) { return allViews[i]; } } } function getScrollState(view) { var scrollX = view.$config.scrollX ? gantt2.$ui.getView(view.$config.scrollX) : null; var scrollY = view.$config.scrollY ? gantt2.$ui.getView(view.$config.scrollY) : null; var scrollState = { x: null, y: null }; if (scrollX) { var state = scrollX.getScrollState(); if (state.visible) { scrollState.x = scrollX.$view.scrollLeft; } } if (scrollY) { var state = scrollY.getScrollState(); if (state.visible) { scrollState.y = scrollY.$view.scrollTop; } } return scrollState; } function scrollView(view, left, top) { var scrollX = view.$config.scrollX ? gantt2.$ui.getView(view.$config.scrollX) : null; var scrollY = view.$config.scrollY ? gantt2.$ui.getView(view.$config.scrollY) : null; if (scrollX) { scrollX.scrollTo(left, null); } if (scrollY) { scrollY.scrollTo(null, top); } } function getTaskDND() { var tasksDnD; if (gantt2.$ui.getView("timeline")) { tasksDnD = gantt2.$ui.getView("timeline")._tasks_dnd; } return tasksDnD; } var touchHandlers = []; gantt2._touch_events = function(names, accessor, ignore) { var dblclicktime = 0; var actionMode = false; var scrollMode = false; var actionStart = null; var previousActionStart = null; var scrollState; var longTapTimer = null; var currentDndId = null; var dndNodes = []; var targetView = null; let multiTouchEvents = {}; for (var i = 0; i < touchHandlers.length; i++) { gantt2.eventRemove(touchHandlers[i][0], touchHandlers[i][1], touchHandlers[i][2]); } touchHandlers = []; touchHandlers.push([gantt2.$container, names[0], function(e) { var tasksDnD = getTaskDND(); if (ignore(e)) return; if (!actionMode) return; if (longTapTimer) clearTimeout(longTapTimer); var source = accessor(e); if (tasksDnD && (tasksDnD.drag.id || tasksDnD.drag.start_drag)) { tasksDnD.on_mouse_move(source); if (e.preventDefault) e.preventDefault(); e.cancelBubble = true; return false; } if (!gantt2._prevent_touch_scroll) { if (source && actionStart) { var dx = actionStart.pageX - source.pageX; var dy = actionStart.pageY - source.pageY; if (!scrollMode && (Math.abs(dx) > 5 || Math.abs(dy) > 5)) { scrollMode = true; dblclicktime = 0; if (targetView) { scrollState = getScrollState(targetView); } else { scrollState = gantt2.getScrollState(); } } if (scrollMode) { var newScrollState; var scrollX = scrollState.x + dx; var scrollY = scrollState.y + dy; if (targetView) { scrollView(targetView, scrollX, scrollY); newScrollState = getScrollState(targetView); } else { gantt2.scrollTo(scrollX, scrollY); newScrollState = gantt2.getScrollState(); } if (scrollState.x != newScrollState.x && dy > 2 * dx || scrollState.y != newScrollState.y && dx > 2 * dy) { return block_action(e); } } } return block_action(e); } return true; }]); try { document.addEventListener("touchmove", function(e) { if (gantt2._touch_drag) { block_action(e); } }, { passive: false }); } catch (e) { console.warn("Cannot prevent touch event for the page drag"); } touchHandlers.push([this.$container, "contextmenu", function(e) { if (actionMode) return block_action(e); }]); touchHandlers.push([this.$container, names[1], function(e) { multiTouchEvents = e.touches.length; if (document && document.body) { document.body.classList.add("gantt_touch_active"); } if (ignore(e)) return; if (e.touches && e.touches.length > 1) { actionMode = false; return; } actionStart = accessor(e); targetView = findTargetView(actionStart); if (!gantt2._locate_css(actionStart, "gantt_hor_scroll") && !gantt2._locate_css(actionStart, "gantt_ver_scroll")) { actionMode = true; } var tasksDnD = getTaskDND(); longTapTimer = setTimeout(function() { var taskId = gantt2.locate(actionStart); if (tasksDnD && (taskId && !gantt2._locate_css(actionStart, "gantt_link_control") && !gantt2._locate_css(actionStart, "gantt_grid_data"))) { tasksDnD.on_mouse_down(actionStart); if (tasksDnD.drag && tasksDnD.drag.start_drag) { cloneTaskRendered(taskId); tasksDnD._start_dnd(actionStart); gantt2._touch_drag = true; gantt2.refreshTask(taskId); gantt2._touch_feedback(); } } longTapTimer = null; }, gantt2.config.touch_drag); }]); touchHandlers.push([this.$container, names[2], function(e) { if (document && document.body) { document.body.classList.remove("gantt_touch_active"); } if (ignore(e)) return; if (longTapTimer) clearTimeout(longTapTimer); gantt2._touch_drag = false; actionMode = false; var source = accessor(e); var tasksDnD = getTaskDND(); if (tasksDnD) tasksDnD.on_mouse_up(source); if (currentDndId && gantt2.isTaskExists(currentDndId)) { gantt2.refreshTask(currentDndId); if (dndNodes.length) { dndNodes.forEach(function(node) { if (node.parentNode) { node.parentNode.removeChild(node); } }); gantt2._touch_feedback(); } } actionMode = scrollMode = false; dndNodes = []; currentDndId = null; if (actionStart && dblclicktime) { var now = /* @__PURE__ */ new Date(); const noMultitouch = multiTouchEvents <= 1; const sameTarget = previousActionStart && previousActionStart.target.innerHTML == actionStart.target.innerHTML; if (now - dblclicktime < 500 && noMultitouch && sameTarget) { var mouseEvents2 = gantt2.$services.getService("mouseEvents"); mouseEvents2.onDoubleClick(actionStart); block_action(e); } else { dblclicktime = now; previousActionStart = actionStart; } } else { dblclicktime = /* @__PURE__ */ new Date(); } }]); for (var i = 0; i < touchHandlers.length; i++) { gantt2.event(touchHandlers[i][0], touchHandlers[i][1], touchHandlers[i][2]); } function block_action(e) { if (e && e.preventDefault && e.cancelable) { e.preventDefault(); } e.cancelBubble = true; return false; } function cloneTaskRendered(taskId) { const renders = gantt2._getTaskLayers(); let task = gantt2.getTask(taskId); if (task) { let visible = gantt2.isTaskVisible(taskId); if (visible) { currentDndId = taskId; for (let i2 = 0; i2 < renders.length; i2++) { task = renders[i2].rendered[taskId]; if (task && task.getAttribute(gantt2.config.task_attribute) && task.getAttribute(gantt2.config.task_attribute) == taskId) { const copy2 = task.cloneNode(true); dndNodes.push(task); renders[i2].rendered[taskId] = copy2; task.style.display = "none"; copy2.className += " gantt_drag_move "; task.parentNode.appendChild(copy2); } } } else if (task.$split_subtask) { let renderedParent = task.$rendered_parent; visible = gantt2.isTaskVisible(renderedParent); if (!visible) { return; } currentDndId = taskId; for (let i2 = 0; i2 < renders.length; i2++) { const parent = renders[i2].rendered[renderedParent]; let taskNode; if (parent && parent.childNodes) { taskNode = parent.querySelector(`[${gantt2.config.task_attribute}="${task.id}"]`); } if (taskNode) { const copy2 = taskNode.cloneNode(true); taskNode.parentNode.appendChild(copy2); gantt2.$task_bars.appendChild(taskNode); taskNode.style.display = "none"; dndNodes.push(taskNode); taskNode = null; } } } } } }; } function dummy() { console.log("Method is not implemented."); } function BaseControl() { } BaseControl.prototype.render = dummy; BaseControl.prototype.set_value = dummy; BaseControl.prototype.get_value = dummy; BaseControl.prototype.focus = dummy; function Super(gantt2) { return BaseControl; } function TemplateControlConstructor(gantt2) { const _super = Super(); function TemplateControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(TemplateControl, _super); TemplateControl.prototype.render = function(sns) { let height = sns.height ? `${sns.height}px` : ""; return `
`; }; TemplateControl.prototype.set_value = function(node, value) { node.innerHTML = value || ""; }; TemplateControl.prototype.get_value = function(node) { return node.innerHTML || ""; }; TemplateControl.prototype.focus = function() { }; return TemplateControl; } function TextareaControlConstructor(gantt2) { const _super = Super(); function TextareaControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(TextareaControl, _super); TextareaControl.prototype.render = function(sns) { const height = (sns.height || "130") + "px"; const placeholder = sns.placeholder ? `placeholder='${sns.placeholder}'` : ""; return `
`; }; TextareaControl.prototype.set_value = function(node, value) { gantt2.form_blocks.textarea._get_input(node).value = value || ""; }; TextareaControl.prototype.get_value = function(node) { return gantt2.form_blocks.textarea._get_input(node).value; }; TextareaControl.prototype.focus = function(node) { var a = gantt2.form_blocks.textarea._get_input(node); gantt2._focus(a, true); }; TextareaControl.prototype._get_input = function(node) { return node.querySelector("textarea"); }; return TextareaControl; } function TimeControlConstructor(gantt2) { const _super = Super(); function TimeControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(TimeControl, _super); TimeControl.prototype.render = function(sns) { var time = gantt2.form_blocks.getTimePicker.call(this, sns); let sectionClassName = "gantt_section_time"; if (sns.name !== "time") { sectionClassName += " gantt_section_" + sns.name; } var html = "
"; html += time; if (sns.single_date) { time = gantt2.form_blocks.getTimePicker.call(this, sns, true); html += ""; } else { html += "  –  "; } html += time; html += "
"; return html; }; TimeControl.prototype.set_value = function(node, value, ev, config2) { var cfg = config2; var s = node.getElementsByTagName("select"); var map = config2._time_format_order; if (cfg.auto_end_date) { var _update_lightbox_select = function() { start_date = new Date(s[map[2]].value, s[map[1]].value, s[map[0]].value, 0, 0); end_date = gantt2.calculateEndDate({ start_date, duration: 1, task: ev }); gantt2.form_blocks._fill_lightbox_select(s, map.size, end_date, map, cfg); }; for (var i = 0; i < 4; i++) { s[i].onchange = _update_lightbox_select; } } var mapping = gantt2._resolve_default_mapping(config2); if (typeof mapping === "string") mapping = { start_date: mapping }; var start_date = ev[mapping.start_date] || /* @__PURE__ */ new Date(); var end_date = ev[mapping.end_date] || gantt2.calculateEndDate({ start_date, duration: 1, task: ev }); gantt2.form_blocks._fill_lightbox_select(s, 0, start_date, map, cfg); gantt2.form_blocks._fill_lightbox_select(s, map.size, end_date, map, cfg); }; TimeControl.prototype.get_value = function(node, ev, config2) { var selects = node.getElementsByTagName("select"); var startDate; var map = config2._time_format_order; function _getEndDate(selects2, map2, startDate2) { var endDate = gantt2.form_blocks.getTimePickerValue(selects2, config2, map2.size); if (endDate <= startDate2) { if (config2.autofix_end !== false || config2.single_date) { return gantt2.date.add(startDate2, gantt2._get_timepicker_step(), "minute"); } } return endDate; } startDate = gantt2.form_blocks.getTimePickerValue(selects, config2); if (typeof gantt2._resolve_default_mapping(config2) === "string") { return startDate; } return { start_date: startDate, end_date: _getEndDate(selects, map, startDate) }; }; TimeControl.prototype.focus = function(node) { gantt2._focus(node.getElementsByTagName("select")[0]); }; return TimeControl; } var htmlHelpers = { getHtmlSelect: function(options, attributes, value) { var innerHTML = ""; var _this = this; options = options || []; forEach(options, function(entry) { var _attributes = [{ key: "value", value: entry.key }]; if (value == entry.key) { _attributes[_attributes.length] = { key: "selected", value: "selected" }; } if (entry.attributes) { _attributes = _attributes.concat(entry.attributes); } innerHTML += _this.getHtmlOption({ innerHTML: entry.label }, _attributes); }); return _getHtmlContainer("select", { innerHTML }, attributes); }, getHtmlOption: function(options, attributes) { return _getHtmlContainer("option", options, attributes); }, getHtmlButton: function(options, attributes) { return _getHtmlContainer("button", options, attributes); }, getHtmlDiv: function(options, attributes) { return _getHtmlContainer("div", options, attributes); }, getHtmlLabel: function(options, attributes) { return _getHtmlContainer("label", options, attributes); }, getHtmlInput: function(attributes) { return ""; } }; function _getHtmlContainer(tag, options, attributes) { var html; options = options || []; html = "<" + tag + _getHtmlAttributes(attributes || []) + ">" + (options.innerHTML || "") + ""; return html; } function _getHtmlAttributes(attributes) { var html = ""; forEach(attributes, function(entry) { html += " " + entry.key + "='" + entry.value + "'"; }); return html; } function ResourcesControlConstructor(gantt2) { const _super = Super(); function SelectControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(SelectControl, _super); SelectControl.prototype.render = function(sns) { const height = sns.height ? `height:${sns.height}px;` : ""; let html = `
`; html += htmlHelpers.getHtmlSelect(sns.options, [{ key: "style", value: "width:100%;" }, { key: "title", value: sns.name }]); html += "
"; return html; }; SelectControl.prototype.set_value = function(node, value, ev, sns) { var select = node.firstChild; if (!select._dhx_onchange && sns.onchange) { select.onchange = sns.onchange; select._dhx_onchange = true; } if (typeof value === "undefined") value = (select.options[0] || {}).value; select.value = value || ""; }; SelectControl.prototype.get_value = function(node) { return node.firstChild.value; }; SelectControl.prototype.focus = function(node) { var a = node.firstChild; gantt2._focus(a, true); }; return SelectControl; } function CheckboxControlConstructor(gantt2) { var _super = Super(); function CheckboxControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(CheckboxControl, _super); CheckboxControl.prototype.render = function(sns) { const height = sns.height ? `height:${sns.height}px;` : ""; let html = `
`; if (sns.options && sns.options.length) { for (var i = 0; i < sns.options.length; i++) { html += ""; } } else { sns.single_value = true; html += ""; } html += "
"; return html; }; CheckboxControl.prototype.set_value = function(node, value, ev, sns) { var checkboxes = Array.prototype.slice.call(node.querySelectorAll("input[type=checkbox]")); if (!node._dhx_onchange && sns.onchange) { node.onchange = sns.onchange; node._dhx_onchange = true; } if (sns.single_value) { var box = checkboxes[0]; box.checked = !!value; } else { forEach(checkboxes, function(entry) { entry.checked = value ? value.indexOf(entry.value) >= 0 : false; }); } }; CheckboxControl.prototype.get_value = function(node, task, sns) { if (sns.single_value) { var box = node.querySelector("input[type=checkbox]"); return box.checked; } else { return arrayMap(Array.prototype.slice.call(node.querySelectorAll("input[type=checkbox]:checked")), function(entry) { return entry.value; }); } }; CheckboxControl.prototype.focus = function(node) { gantt2._focus(node.querySelector("input[type=checkbox]")); }; return CheckboxControl; } function RadioControlConstructor(gantt2) { const _super = Super(); function RadioControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(RadioControl, _super); RadioControl.prototype.render = function(sns) { const height = sns.height ? `${sns.height}px` : ""; let html = `
`; if (sns.options && sns.options.length) { for (var i = 0; i < sns.options.length; i++) { html += ""; } } html += "
"; return html; }; RadioControl.prototype.set_value = function(node, value, ev, sns) { var radio; if (!sns.options || !sns.options.length) return; radio = node.querySelector("input[type=radio][value='" + value + "']") || node.querySelector("input[type=radio][value='" + sns.default_value + "']"); if (!radio) return; if (!node._dhx_onchange && sns.onchange) { node.onchange = sns.onchange; node._dhx_onchange = true; } radio.checked = true; }; RadioControl.prototype.get_value = function(node, ev) { var result = node.querySelector("input[type=radio]:checked"); return result ? result.value : ""; }; RadioControl.prototype.focus = function(node) { gantt2._focus(node.querySelector("input[type=radio]")); }; return RadioControl; } function DurationControlConstructor(gantt2) { var _super = Super(); function DurationControl() { var self2 = _super.apply(this, arguments) || this; return self2; } function getFormatter(config2) { return config2.formatter || new DurationFormatterNumeric(); } __extends(DurationControl, _super); DurationControl.prototype.render = function(sns) { var time = "
" + gantt2.form_blocks.getTimePicker.call(this, sns) + "
"; var label = " " + gantt2.locale.labels[gantt2.config.duration_unit + "s"] + " "; var singleDate = sns.single_date ? " style='display:none'" : ""; var readonly = sns.readonly ? " disabled='disabled'" : ""; var ariaAttr = gantt2._waiAria.lightboxDurationInputAttrString(sns); var durationInputClass = "gantt_duration_value"; if (sns.formatter) { label = ""; durationInputClass += " gantt_duration_value_formatted"; } var duration = "
" + label + "
"; let sectionClassName = "gantt_section_time gantt_section_duration"; if (sns.name !== "time") { sectionClassName += " gantt_section_" + sns.name; } var html = "
" + time + " " + duration + "
"; return html; }; DurationControl.prototype.set_value = function(node, value, ev, config2) { var s = node.getElementsByTagName("select"); var inps = node.getElementsByTagName("input"); var duration = inps[1]; var btns = [inps[0], inps[2]]; var endspan = node.getElementsByTagName("span")[0]; var map = config2._time_format_order; var mapping; var start_date; var end_date; var duration_val; function _calc_date() { var start_date2 = _getStartDate.call(gantt2, node, config2); var duration2 = _getDuration.call(gantt2, node, config2); var end_date2 = gantt2.calculateEndDate({ start_date: start_date2, duration: duration2, task: ev }); var template = gantt2.templates.task_end_date || gantt2.templates.task_date; endspan.innerHTML = template(end_date2); } function _change_duration(step) { var value2 = duration.value; value2 = getFormatter(config2).parse(value2); if (window.isNaN(value2)) value2 = 0; value2 += step; if (value2 < 1) value2 = 1; duration.value = getFormatter(config2).format(value2); _calc_date(); } btns[0].onclick = gantt2.bind(function() { _change_duration(-1 * gantt2.config.duration_step); }, this); btns[1].onclick = gantt2.bind(function() { _change_duration(1 * gantt2.config.duration_step); }, this); s[0].onchange = _calc_date; s[1].onchange = _calc_date; s[2].onchange = _calc_date; if (s[3]) s[3].onchange = _calc_date; duration.onkeydown = gantt2.bind(function(e) { var code; e = e || window.event; code = e.charCode || e.keyCode || e.which; if (code == gantt2.constants.KEY_CODES.DOWN) { _change_duration(-1 * gantt2.config.duration_step); return false; } if (code == gantt2.constants.KEY_CODES.UP) { _change_duration(1 * gantt2.config.duration_step); return false; } window.setTimeout(_calc_date, 1); }, this); duration.onchange = gantt2.bind(_calc_date, this); mapping = gantt2._resolve_default_mapping(config2); if (typeof mapping === "string") mapping = { start_date: mapping }; start_date = ev[mapping.start_date] || /* @__PURE__ */ new Date(); end_date = ev[mapping.end_date] || gantt2.calculateEndDate({ start_date, duration: 1, task: ev }); duration_val = Math.round(ev[mapping.duration]) || gantt2.calculateDuration({ start_date, end_date, task: ev }); duration_val = getFormatter(config2).format(duration_val); gantt2.form_blocks._fill_lightbox_select(s, 0, start_date, map, config2); duration.value = duration_val; _calc_date(); }; DurationControl.prototype.get_value = function(node, ev, config2) { var startDate = _getStartDate(node, config2); var duration = _getDuration(node, config2); var endDate = gantt2.calculateEndDate({ start_date: startDate, duration, task: ev }); if (typeof gantt2._resolve_default_mapping(config2) == "string") { return startDate; } return { start_date: startDate, end_date: endDate, duration }; }; DurationControl.prototype.focus = function(node) { gantt2._focus(node.getElementsByTagName("select")[0]); }; function _getStartDate(node, config2) { var s = node.getElementsByTagName("select"); var map = config2._time_format_order; var hours = 0; var minutes = 0; if (gantt2.defined(map[3])) { var input = s[map[3]]; var time = parseInt(input.value, 10); if (isNaN(time) && input.hasAttribute("data-value")) { time = parseInt(input.getAttribute("data-value"), 10); } hours = Math.floor(time / 60); minutes = time % 60; } return new Date(s[map[2]].value, s[map[1]].value, s[map[0]].value, hours, minutes); } function _getDuration(node, config2) { var duration = node.getElementsByTagName("input")[1]; duration = getFormatter(config2).parse(duration.value); if (!duration || window.isNaN(duration)) duration = 1; if (duration < 0) duration *= -1; return duration; } return DurationControl; } function ParentControlConstructor(gantt2) { var _super = ResourcesControlConstructor(gantt2); function ParentControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(ParentControl, _super); ParentControl.prototype.render = function(sns) { return _display(sns, false); }; ParentControl.prototype.set_value = function(node, value, ev, config2) { if (value === 0) value = "0"; if (!ev.id && gantt2.getState().lightbox) { ev.id = gantt2.getLightboxValues().id; } var tmpDom = document.createElement("div"); tmpDom.innerHTML = _display(config2, ev.id); var newOptions = tmpDom.removeChild(tmpDom.firstChild); node.onselect = null; node.parentNode.replaceChild(newOptions, node); return gantt2.form_blocks.select.set_value.apply(gantt2, [newOptions, value, ev, config2]); }; function _display(config2, item_id) { var tasks2 = [], options = []; if (item_id) { tasks2 = gantt2.getTaskByTime(); if (config2.allow_root) { tasks2.unshift({ id: gantt2.config.root_id, text: config2.root_label || "" }); } tasks2 = _filter(tasks2, config2, item_id); if (config2.sort) { tasks2.sort(config2.sort); } } var text = config2.template || gantt2.templates.task_text; for (var i = 0; i < tasks2.length; i++) { var label = text.apply(gantt2, [tasks2[i].start_date, tasks2[i].end_date, tasks2[i]]); if (label === void 0) { label = ""; } options.push({ key: tasks2[i].id, label }); } config2.options = options; config2.map_to = config2.map_to || "parent"; return gantt2.form_blocks.select.render.apply(this, arguments); } function _filter(options, config2, item_id) { var filter = config2.filter || function() { return true; }; options = options.slice(0); for (var i = 0; i < options.length; i++) { var task = options[i]; if (task.id == item_id || gantt2.isChildOf(task.id, item_id) || filter(task.id, task) === false) { options.splice(i, 1); i--; } } return options; } return ParentControl; } function ConstraintControlConstructor(gantt2) { var _super = Super(); function ConstraintControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(ConstraintControl, _super); function isNonTimedConstraint(value) { if (!value || value === gantt2.config.constraint_types.ASAP || value === gantt2.config.constraint_types.ALAP) { return true; } else { return false; } } function toggleTimeSelect(timeSelects, typeValue) { var isNonTimed = isNonTimedConstraint(typeValue); for (var i = 0; i < timeSelects.length; i++) { timeSelects[i].disabled = isNonTimed; } } ConstraintControl.prototype.render = function(sns) { const height = sns.height ? `height:${sns.height}px;` : ""; let html = `
`; var options = []; for (var i in gantt2.config.constraint_types) { options.push({ key: gantt2.config.constraint_types[i], label: gantt2.locale.labels[gantt2.config.constraint_types[i]] }); } sns.options = sns.options || options; html += "" + htmlHelpers.getHtmlSelect(sns.options, [{ key: "data-type", value: "constraint-type" }]) + ""; var timeLabel = gantt2.locale.labels["constraint_date"] || "Constraint date"; html += ""; html += "
"; return html; }; ConstraintControl.prototype.set_value = function(node, value, task, config2) { var typeSelect = node.querySelector("[data-constraint-type-select] select"); var timeSelects = node.querySelectorAll("[data-constraint-time-select] select"); var map = config2._time_format_order; var mapping = gantt2._resolve_default_mapping(config2); if (!typeSelect._eventsInitialized) { typeSelect.addEventListener("change", function(e) { toggleTimeSelect(timeSelects, e.target.value); }); typeSelect._eventsInitialized = true; } var constraintDate = task[mapping.constraint_date] || /* @__PURE__ */ new Date(); gantt2.form_blocks._fill_lightbox_select(timeSelects, 0, constraintDate, map, config2); var constraintType = task[mapping.constraint_type] || gantt2.getConstraintType(task); typeSelect.value = constraintType; toggleTimeSelect(timeSelects, constraintType); }; ConstraintControl.prototype.get_value = function(node, task, config2) { var typeSelect = node.querySelector("[data-constraint-type-select] select"); var timeSelects = node.querySelectorAll("[data-constraint-time-select] select"); var constraintType = typeSelect.value; var constraintDate = null; if (!isNonTimedConstraint(constraintType)) { constraintDate = gantt2.form_blocks.getTimePickerValue(timeSelects, config2); } return { constraint_type: constraintType, constraint_date: constraintDate }; }; ConstraintControl.prototype.focus = function(node) { gantt2._focus(node.querySelector("select")); }; return ConstraintControl; } function TypeselectControlConstructor(gantt2) { const _super = ResourcesControlConstructor(gantt2); function TypeselectControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(TypeselectControl, _super); TypeselectControl.prototype.render = function(sns) { var types = gantt2.config.types, locale2 = gantt2.locale.labels, options = []; var filter = sns.filter || function(typeKey, typeValue) { if (!types.placeholder || typeValue !== types.placeholder) { return true; } return false; }; for (var i in types) { if (!filter(i, types[i]) === false) { options.push({ key: types[i], label: locale2["type_" + i] }); } } sns.options = options; var oldOnChange = sns.onchange; sns.onchange = function() { gantt2._lightbox_current_type = this.value; gantt2.changeLightboxType(this.value); if (typeof oldOnChange == "function") { oldOnChange.apply(this, arguments); } }; return _super.prototype.render.apply(this, arguments); }; return TypeselectControl; } function BaselineControlConstructor(gantt2) { var _super = Super(); function DurationControl() { var self2 = _super.apply(this, arguments) || this; return self2; } function getFormatter(config2) { return config2.formatter || new DurationFormatterNumeric(); } function _generateBaselineRow(node, baseline, task, config2) { const time = "
" + gantt2.form_blocks.getTimePicker.call(gantt2, config2) + "
"; let durationLabel = " " + gantt2.locale.labels[gantt2.config.duration_unit + "s"] + " "; const singleDate = config2.single_date ? " style='display:none'" : ""; const readonly = config2.readonly ? " disabled='disabled'" : ""; const ariaAttr = gantt2._waiAria.lightboxDurationInputAttrString(config2); const deleteLabel = gantt2.locale.labels.baselines_remove_button; let durationInputClass = "gantt_duration_value"; if (config2.formatter) { durationLabel = ""; durationInputClass += " gantt_duration_value_formatted"; } const durationEl = "
" + durationLabel + "
"; const deleteButton = `
`; const baselineRow = document.createElement("div"); baselineRow.className = "gantt_section_time gantt_section_duration"; baselineRow.setAttribute("data-baseline-id", baseline.id); baselineRow.innerHTML = time + durationEl + deleteButton + "
"; node.appendChild(baselineRow); var s = baselineRow.getElementsByTagName("select"); var inps = baselineRow.getElementsByTagName("input"); var duration = inps[1]; var btns = [inps[0], inps[2]]; var endspan = baselineRow.getElementsByTagName("span")[0]; var map = config2._time_format_order; var start_date; var end_date; var duration_val; const deleteEl = baselineRow.querySelector(".baseline_delete_button"); deleteEl.onclick = function(e) { const section = baselineRow.parentNode; baselineRow.innerHTML = ""; baselineRow.remove(); if (section.innerHTML === "") { section.innerHTML = gantt2.locale.labels.baselines_section_placeholder; } }; function _calc_date() { var start_date2 = _getStartDate.call(gantt2, baselineRow, config2); var duration2 = _getDuration.call(gantt2, baselineRow, config2); var end_date2 = gantt2.calculateEndDate({ start_date: start_date2, duration: duration2, task }); var template = gantt2.templates.task_end_date || gantt2.templates.task_date; endspan.innerHTML = template(end_date2); } function _change_duration(step) { var value = duration.value; value = getFormatter(config2).parse(value); if (window.isNaN(value)) value = 0; value += step; if (value < 1) value = 1; duration.value = getFormatter(config2).format(value); _calc_date(); } btns[0].onclick = gantt2.bind(function() { _change_duration(-1 * gantt2.config.duration_step); }, gantt2); btns[1].onclick = gantt2.bind(function() { _change_duration(1 * gantt2.config.duration_step); }, gantt2); s[0].onchange = _calc_date; s[1].onchange = _calc_date; s[2].onchange = _calc_date; if (s[3]) s[3].onchange = _calc_date; duration.onkeydown = gantt2.bind(function(e) { var code; e = e || window.event; code = e.charCode || e.keyCode || e.which; if (code == gantt2.constants.KEY_CODES.DOWN) { _change_duration(-1 * gantt2.config.duration_step); return false; } if (code == gantt2.constants.KEY_CODES.UP) { _change_duration(1 * gantt2.config.duration_step); return false; } window.setTimeout(_calc_date, 1); }, gantt2); duration.onchange = gantt2.bind(_calc_date, gantt2); gantt2._resolve_default_mapping(config2); start_date = baseline.start_date || /* @__PURE__ */ new Date(); end_date = baseline.end_date || gantt2.calculateEndDate({ start_date, duration: 1, task }); duration_val = gantt2.calculateDuration({ start_date, end_date, task }); duration_val = getFormatter(config2).format(duration_val); gantt2.form_blocks._fill_lightbox_select(s, 0, start_date, map, config2); duration.value = duration_val; _calc_date(); } __extends(DurationControl, _super); DurationControl.prototype.render = function(sns) { const baselineSection = `
`; return baselineSection; }; DurationControl.prototype.set_value = function(node, value, task, config2) { if (task.baselines) { node.innerHTML = ""; task.baselines.forEach((baseline) => { _generateBaselineRow(node, baseline, task, config2); }); } else { node.innerHTML = gantt2.locale.labels.baselines_section_placeholder; } }; DurationControl.prototype.get_value = function(node, task, config2) { const baselines2 = []; const baselineRows = node.querySelectorAll(`[data-baseline-id]`); baselineRows.forEach((baselineNode) => { const baselineId = baselineNode.dataset.baselineId; const baselineStore = gantt2.getDatastore("baselines"); let baseline = baselineStore.getItem(baselineId); let updatedBaseline; if (baseline) { updatedBaseline = gantt2.copy(baseline); } else { updatedBaseline = { id: gantt2.uid(), task_id: task.id, text: "Baseline 1" }; } updatedBaseline.start_date = _getStartDate(baselineNode, config2); updatedBaseline.duration = _getDuration(baselineNode, config2); updatedBaseline.end_date = gantt2.calculateEndDate({ start_date: updatedBaseline.start_date, duration: updatedBaseline.duration, task }); baselines2.push(updatedBaseline); }); return baselines2; }; DurationControl.prototype.button_click = function(index, el, section, container) { if (gantt2.callEvent("onSectionButton", [gantt2._lightbox_id, section]) === false) { return; } if (el.closest(".gantt_custom_button.gantt_remove_baselines")) { container.innerHTML = gantt2.locale.labels.baselines_section_placeholder; } if (el.closest(".gantt_custom_button.gantt_add_baselines")) { if (container.innerHTML == gantt2.locale.labels.baselines_section_placeholder) { container.innerHTML = ""; } const task = gantt2.getTask(gantt2._lightbox_id); const baseline = { id: gantt2.uid(), task_id: task.id, start_date: task.start_date, end_date: task.end_date }; const config2 = gantt2._get_typed_lightbox_config()[index]; _generateBaselineRow(container, baseline, task, config2); } }; DurationControl.prototype.focus = function(node) { gantt2._focus(node.getElementsByTagName("select")[0]); }; function _getStartDate(node, config2) { var s = node.getElementsByTagName("select"); var map = config2._time_format_order; var hours = 0; var minutes = 0; if (gantt2.defined(map[3])) { var input = s[map[3]]; var time = parseInt(input.value, 10); if (isNaN(time) && input.hasAttribute("data-value")) { time = parseInt(input.getAttribute("data-value"), 10); } hours = Math.floor(time / 60); minutes = time % 60; } return new Date(s[map[2]].value, s[map[1]].value, s[map[0]].value, hours, minutes); } function _getDuration(node, config2) { var duration = node.getElementsByTagName("input")[1]; duration = getFormatter(config2).parse(duration.value); if (!duration || window.isNaN(duration)) duration = 1; if (duration < 0) duration *= -1; return duration; } return DurationControl; } function NewResourcesControlConstructor(gantt2) { const _super = Super(); const localCache = { resourcesValues: {}, filter: {}, eventsInitialized: {}, gridID: null, resource_filter_value: null, initialValues: [], newValues: [] }; const selectResEditor = { type: "select", map_to: "resource_id", options: gantt2.serverList("resourceOptions") }; const numberEditor = { type: "number", map_to: "value", min: 0, max: 100 }; const dateToStr2 = gantt2.date.date_to_str("%d-%m-%Y"); gantt2.resource_table = { scale_height: 35, row_height: 35, columns: [{ name: "resource", label: "Resource", align: "center", width: 80, editor: selectResEditor, template: function(assignment) { let defaultValue = "Unassigned"; const resource = gantt2.getDatastore(gantt2.config.resource_store).getItem(assignment.resource_id); return resource ? resource.text : defaultValue; } }, { name: "hours/Day", label: "Hours/Day", align: "center", width: 70, editor: numberEditor, template: function(assignment) { return assignment.value ? +assignment.value : ``; } }, { name: "start", label: "Start", align: "center", width: 100, template: function(assignment) { return assignment.start_date ? dateToStr2(assignment.start_date) : ``; } }, { name: "end", label: "End", align: "center", width: 100, template: function(assignment) { return assignment.end_date ? dateToStr2(assignment.end_date) : ``; } }, { name: "duration", label: "Duration", align: "center", width: 80, template: function(assignment) { if (assignment.duration) { return `${assignment.duration} day${assignment.duration == 1 ? "" : "s"}`; } else { return ``; } } }, { name: "delete", label: "Delete", align: "center", width: 80, template: function(assignment) { return `
`; } }], resource_default_assignment: { duration: null, value: 8, start_date: null, end_date: null, mode: "default" } }; gantt2.attachEvent("onAfterLightbox", _clearCached); function newResourcesControl() { var self2 = _super.apply(this, arguments) || this; return self2; } __extends(newResourcesControl, _super); function _generateResourceInputSection(index, name) { const resourceFilterPlaceholder = gantt2.locale.labels.resources_filter_placeholder || "Search..."; const html = `
${gantt2.locale.labels.resources_add_button}
`; return html; } function _generateResourceTable(node, assignments, task, sns) { if (gantt2.$ui.getView("GridRL") && !localCache.gridID) { gantt2.$ui.getView("GridRL").destructor(); } if (!localCache.gridID) { const resourceTable = document.createElement("div"); resourceTable.classList.add("gantt_resource_selector_grid"); const tempAssignmentStore = gantt2.createDatastore({ name: "temp_resource_assignment_store", initItem: function(item) { if (!item.id) { item.id = gantt2.uid(); } return item; } }); gantt2.$data.tempAssignmentsStore = tempAssignmentStore; const gridConfig = { ...gantt2.config.layout, id: "GridRL", sectionName: sns.name }; const grid = gantt2.$ui.createView("GridRL", gantt2.$root, gridConfig); grid.init(resourceTable); const width = gantt2._lightbox.offsetWidth - (gantt2.config.wide_form ? 150 : 0); grid.setSize(width, "auto"); gantt2.ext.inlineEditorsLightbox = gantt2.ext._inlineEditors.createEditors(grid); gantt2.ext.inlineEditorsLightbox.init(); localCache.gridID = grid.$id; node.appendChild(resourceTable); const resourceAssignmentsStore = gantt2.getDatastore(gantt2.config.resource_assignment_store); const searchItems = []; resourceAssignmentsStore.eachItem(function(item) { if (item.task_id && item.task_id == task.id) { searchItems.push(item); } }); const clonedAssignments = structuredClone(searchItems); tempAssignmentStore.parse(clonedAssignments); } gantt2.$data.tempAssignmentsStore.attachEvent("onFilterItem", function(id, assignment) { if (assignment.task_id == task.id) { if (!localCache.resource_filter_value) { return true; } else { let resource = gantt2.getDatastore(gantt2.config.resource_store).getItem(assignment.resource_id); if (resource.text.toLowerCase().indexOf(localCache.resource_filter_value) > -1) return true; } } return false; }); gantt2.refreshData(); } function _generateAssignmentDefaultRow(sectionName) { let resource_id; const task = gantt2.getTask(gantt2._lightbox_id); const assignments = gantt2.getTaskAssignments(task.id); if (assignments.length) { resource_id = assignments[0].resource_id; } else { const resources2 = gantt2.serverList("resourceOptions"); if (resources2.length) { resource_id = resources2[0].id; } else { throw new Error(`There is no any resources in resource store, please check your data: https://docs.dhtmlx.com/gantt/desktop__resource_management.html#assigningresources`); } } const tempAssignmentStore = gantt2.getDatastore("temp_resource_assignment_store"); const lightboxSection = gantt2.getLightboxSection(sectionName).section; const resourceConfig = lightboxSection.config ?? gantt2.resource_table; const config2 = resourceConfig.resource_default_assignment ?? gantt2.resource_table.resource_default_assignment; tempAssignmentStore.addItem({ resource_id, task_id: task.id, duration: config2.duration ?? gantt2.calculateDuration(task), value: config2.value, start_date: config2.start_date ?? task.start_date, end_date: config2.end_date ?? task.end_date, mode: config2.mode }); gantt2.refreshData(); } function _setFocus(container) { const resourceRows = container.querySelectorAll(".gantt_row.gantt_row_task"); if (resourceRows) { const lastRow = resourceRows[resourceRows.length - 1]; const resourceCell = lastRow.querySelector(".gantt_cell"); if (resourceCell) { const { id, columnName } = gantt2.ext.inlineEditorsLightbox.locateCell(resourceCell); if (id && columnName) { gantt2.ext.inlineEditorsLightbox.startEdit(id, columnName); } } } } newResourcesControl.prototype.render = function(sns) { if (!sns.options) { sns.options = gantt2.serverList("resourceOptions"); } if (!sns.map_to || sns.map_to == "resource_selector" || sns.map_to == "auto") { sns.map_to = gantt2.config.resource_property; } let html; html = ``; html += _generateResourceInputSection(sns.index, sns.name); html += ``; html += ``; return html; }; newResourcesControl.prototype.button_click = function(index, el, section, container) { const sectionName = section.getAttribute("data-section-name") || container.getAttribute("data-section-name"); const firstAddBtn = document.querySelector("[data-resource-selector-section]"); const placeholder = document.querySelector(".resources_section_placeholder"); const resourceSection = document.querySelector(`.gantt_section_${sectionName} .gantt_resource_selector_filter_wrapper`); const resourceGrid = document.querySelector(`.gantt_section_${sectionName} .gantt_grid`); firstAddBtn.style.display = "none"; if (gantt2.callEvent("onSectionButton", [gantt2._lightbox_id, section]) === false) { return; } if (el.closest(".gantt_custom_button.gantt_add_resources")) { placeholder.style.display = "none"; const tempAssignmentStore = gantt2.getDatastore("temp_resource_assignment_store"); if (tempAssignmentStore && tempAssignmentStore.getItems().length == 0) { resourceSection.style.display = "flex"; resourceGrid.style.display = "block"; } _generateAssignmentDefaultRow(sectionName); _setFocus(container); } }; function setInitialValues(task) { localCache.initialValues = []; localCache.newValues = []; const assignmentStore = gantt2.$data.assignmentsStore; const storeAssignments = assignmentStore.find(function(a) { return a.task_id == task.id; }); for (let i = 0; i < storeAssignments.length; i++) { localCache.initialValues[i] = { resource_id: storeAssignments[i].resource_id, value: storeAssignments[i].value, id: storeAssignments[i].id }; } } newResourcesControl.prototype.set_value = function(node, assignments, task, sns, initialized) { let firstAddBtn = document.querySelector("[data-resource-selector-section]"); let placeholder = document.querySelector(".resources_section_placeholder"); setInitialValues(task); if (!initialized) { _generateResourceTable(node, assignments, task, sns); _setFilterCache(node, sns); _initEvents(node, assignments, sns, this); firstAddBtn.style.display = "none"; let resourceGrid = document.querySelector(`.gantt_section_${sns.name} .gantt_grid`); let resourceSection = document.querySelector(`.gantt_section_${sns.name} .gantt_resource_selector_filter_wrapper`); resourceGrid.style.display = "none"; resourceSection.style.display = "none"; } const tempAssignmentStore = gantt2.getDatastore("temp_resource_assignment_store"); if (tempAssignmentStore) { let resourceSection = document.querySelector(`.gantt_section_${sns.name} .gantt_resource_selector_filter_wrapper`); let resourceGrid = document.querySelector(`.gantt_section_${sns.name} .gantt_grid`); if (tempAssignmentStore.getItems().length == 0) { if (firstAddBtn.style.display == "none") { firstAddBtn.style.display = "flex"; } resourceSection.style.display = "none"; resourceGrid.style.display = "none"; placeholder.style.display = "block"; } else { resourceSection.style.display = "flex"; resourceGrid.style.display = "block"; placeholder.style.display = "none"; } } gantt2._center_lightbox(gantt2.getLightbox()); }; newResourcesControl.prototype.get_value = function(node, task, sns, type) { const tempAssignmentStore = gantt2.getDatastore("temp_resource_assignment_store"); const storeAssignments = tempAssignmentStore.find(function(a) { return a.task_id == task.id; }); for (let i = 0; i < storeAssignments.length; i++) { localCache.newValues[i] = { resource_id: storeAssignments[i].resource_id.toString(), value: storeAssignments[i].value, id: storeAssignments[i].id, start_date: storeAssignments[i].start_date, end_date: storeAssignments[i].end_date, duration: storeAssignments[i].duration, mode: storeAssignments[i].mode, delay: storeAssignments[i].delay }; } if (type == "save") { return localCache.newValues; } else { return localCache.initialValues; } }; function getVisibleResources(task, options) { let visibleResources = []; const tempAssignmentStore = gantt2.getDatastore("temp_resource_assignment_store"); const currentAssignments = tempAssignmentStore.find(function(a) { return a.task_id == task.id; }); for (let i = 0; i < currentAssignments.length; i++) { let resource = gantt2.getDatastore(gantt2.config.resource_store).getItem(currentAssignments[i].resource_id); if (resource) { visibleResources.push(resource); } } return visibleResources; } function _getValue(el) { return el.value.trim(); } function _initEvents(node, ev, sns, context) { if (localCache.eventsInitialized[sns.id]) return; var _applyFilter = function(e) { _saveValues(sns, node); var resultSns; var query; var input; var filterCache = _getFilterCache(sns); input = filterCache.input; query = _getValue(input); localCache.resource_filter_value = query.toLowerCase(); filterCache.filterApplied = !!query; if (gantt2.getState().lightbox) { ev = gantt2.getLightboxValues(); } resultSns = _getSnsToHideUnsetted(sns, ev, query); var value = ev[sns.map_to]; context.form_blocks.resource_selector.set_value(node, value, ev, resultSns); }; function _saveValues(sns2, domElement) { var selector = _getInputElementSelector(); var inputs = domElement.querySelectorAll(selector); localCache.resourcesValues[sns2.id] = localCache.resourcesValues[sns2.id] || {}; for (var i = 0; i < inputs.length; i++) { var key = inputs[i].getAttribute("data-item-id"); var originalAssignmentId = inputs[i].getAttribute("data-assignment-id"); if (!inputs[i].disabled) { localCache.resourcesValues[sns2.id][key] = { value: inputs[i].value, id: originalAssignmentId }; } else { delete localCache.resourcesValues[sns2.id][key]; } } } _applyFilter = throttle(_applyFilter, 100); _getFilterCache(sns).container.addEventListener("keyup", _applyFilter); _getFilterCache(sns).container.addEventListener("input", _applyFilter, true); _getFilterCache(sns).container.addEventListener("change", _applyFilter, true); localCache.eventsInitialized[sns.id] = true; } function _getSnsToHideUnsetted(controlConfig, task, query, hideUnsetted) { var comparison; var resultConfig = gantt2.copy(controlConfig); if (query === "") { resultConfig.resources = []; let resourceIds = localCache.newValues.map((obj) => obj.resource_id); if (resourceIds && resourceIds.length > 0) { for (let i = 0; i < resourceIds.length; i++) { let resource = gantt2.getDatastore(gantt2.config.resource_store).getItem(resourceIds[i]); if (resource) { resultConfig.resources.push(resource); } } } return resultConfig; } comparison = function(entry) { if (entry.text.toLowerCase().indexOf(query.toLowerCase()) >= 0) { return entry; } }; resultConfig.resources = getVisibleResources(task, controlConfig.options); resultConfig.resources = arrayFilter(resultConfig.resources, comparison); return resultConfig; } function _getInputElementSelector(isChecked) { { return ".gantt_resource_amount_input"; } } function _setFilterCache(node, sns) { if (!localCache.filter[sns.id]) { var container = node.querySelector(".gantt_resources_filter"); var input = container.querySelector(".gantt_resources_filter_input"); localCache.filter[sns.id] = { container, input, filterApplied: false }; } return localCache.filter[sns.id]; } function _getFilterCache(sns) { return localCache.filter[sns.id]; } function _clearCached() { for (var key in localCache.filter) { localCache.filter[key].input.value = ""; localCache.filter[key].filterApplied = false; } localCache.resourcesValues = {}; localCache.eventsInitialized = {}; localCache.resource_filter_value = null; localCache.gridID = null; localCache.initialValues = []; localCache.newValues = []; } return newResourcesControl; } function lightbox(gantt2) { var TemplateControl = TemplateControlConstructor(); var TextareaControl = TextareaControlConstructor(gantt2); var TimeControl = TimeControlConstructor(gantt2); var SelectControl = ResourcesControlConstructor(gantt2); var CheckboxControl = CheckboxControlConstructor(gantt2); var RadioControl = RadioControlConstructor(gantt2); var DurationControl = DurationControlConstructor(gantt2); var ParentControl = ParentControlConstructor(gantt2); var ResourcesControl = ResourcesControlConstructor(gantt2); var ConstraintControl = ConstraintControlConstructor(gantt2); var TypeselectControl = TypeselectControlConstructor(gantt2); var BaselineControl = BaselineControlConstructor(gantt2); var NewResourcesControl = NewResourcesControlConstructor(gantt2); gantt2._lightbox_methods = {}; gantt2._lightbox_template = "
 
"; gantt2._lightbox_template = `
 
`; gantt2._lightbox_root = gantt2.$root; function setParentNode() { const cspEnvironment = gantt2.config.csp === true; if (cspEnvironment || gantt2.env.isSalesforce) { gantt2._lightbox_root = gantt2.$root; } else { gantt2._lightbox_root = document.body; } } var state = gantt2.$services.getService("state"); state.registerProvider("lightbox", function() { return { lightbox: gantt2._lightbox_id }; }); gantt2.showLightbox = function(id) { var task = this.getTask(id); if (!this.callEvent("onBeforeLightbox", [id])) { if (gantt2.isTaskExists(id) && gantt2.getTask(id).$new) { this.$data.tasksStore._updateOrder(); } return; } var box = this.getLightbox(this.getTaskType(task.type)); this.showCover(box); this._fill_lightbox(id, box); this._setLbPosition(box); this._waiAria.lightboxVisibleAttr(box); this.callEvent("onLightbox", [id]); }; function _is_chart_visible(gantt3) { var timeline = gantt3.$ui.getView("timeline"); if (timeline && timeline.isVisible()) { return true; } else { return false; } } gantt2._get_timepicker_step = function() { if (this.config.round_dnd_dates) { var step; if (_is_chart_visible(this)) { var scale = gantt2.getScale(); step = getSecondsInUnit(scale.unit) * scale.step / 60; } if (!step || step >= 60 * 24) { step = this.config.time_step; } return step; } return this.config.time_step; }; gantt2.getLabel = function(property, key) { var sections = this._get_typed_lightbox_config(); for (var i = 0; i < sections.length; i++) { if (sections[i].map_to == property) { var options = sections[i].options; for (var j = 0; j < options.length; j++) { if (options[j].key == key) { return options[j].label; } } } } return ""; }; gantt2.updateCollection = function(list_name, collection) { collection = collection.slice(0); var list = gantt2.serverList(list_name); if (!list) return false; list.splice(0, list.length); list.push.apply(list, collection || []); gantt2.resetLightbox(); }; gantt2.getLightboxType = function() { return this.getTaskType(this._lightbox_type); }; gantt2.getLightbox = function(type) { var lightboxDiv; var fullWidth; var html; var sns; var ds; var classNames = ""; setParentNode(); if (type === void 0) type = this.getLightboxType(); if (!this._lightbox || this.getLightboxType() != this.getTaskType(type)) { this._lightbox_type = this.getTaskType(type); lightboxDiv = document.createElement("div"); classNames = "gantt_cal_light"; fullWidth = this._is_lightbox_timepicker(); if (gantt2.config.wide_form) classNames += " gantt_cal_light_wide"; if (fullWidth) { classNames += " gantt_cal_light_full"; } lightboxDiv.className = classNames; lightboxDiv.style.visibility = "hidden"; html = this._lightbox_template; html += "
"; html += getHtmlButtons(this.config.buttons_left); html += "
"; html += getHtmlButtons(this.config.buttons_right); html += "
"; lightboxDiv.innerHTML = html; gantt2._waiAria.lightboxAttr(lightboxDiv); if (gantt2.config.drag_lightbox) { lightboxDiv.firstChild.onmousedown = gantt2._ready_to_dnd; lightboxDiv.firstChild.addEventListener("touchstart", function(e) { gantt2._ready_to_dnd(e.touches[0]); }); lightboxDiv.firstChild.onselectstart = function() { return false; }; lightboxDiv.firstChild.style.cursor = "pointer"; gantt2._init_dnd_events(); } if (this._lightbox) { this.resetLightbox(); } show_cover(); this._cover.insertBefore(lightboxDiv, this._cover.firstChild); this._lightbox = lightboxDiv; sns = this._get_typed_lightbox_config(type); html = this._render_sections(sns); ds = lightboxDiv.querySelector("div.gantt_cal_larea"); var backup_overflow = ds.style.overflow; ds.style.overflow = "hidden"; ds.innerHTML = html; bindLabelsToInputs(sns); ds.style.overflow = backup_overflow; this._init_lightbox_events(this); lightboxDiv.style.display = "none"; lightboxDiv.style.visibility = "visible"; } return this._lightbox; }; gantt2._render_sections = function(sns) { var html = ""; for (var i = 0; i < sns.length; i++) { var block = this.form_blocks[sns[i].type]; if (!block) continue; sns[i].id = "area_" + this.uid(); var display = sns[i].hidden ? " style='display:none'" : ""; var button = ""; if (sns[i].button) { button = "
" + this.locale.labels["button_" + sns[i].button] + "
"; } if (sns[i].type == "baselines") { button = "
" + this.locale.labels.baselines_remove_all_button + "
" + this.locale.labels.baselines_add_button + "
"; } if (sns[i].type == "resource_selector") { sns[i].index = i; button = `
${this.locale.labels.resources_add_button}
`; } if (this.config.wide_form) { html += "
"; } html += "
" + block.render.call(this, sns[i]); html += "
"; } return html; }; gantt2._center_lightbox = function(box) { gantt2._setLbPosition(box); }; gantt2._setLbPosition = function(box) { if (!box) { return; } const rootElement = gantt2._lightbox_root || gantt2.$root; box.style.top = Math.max(rootElement.offsetHeight / 2 - box.offsetHeight / 2, 0) + "px"; box.style.left = Math.max(rootElement.offsetWidth / 2 - box.offsetWidth / 2, 0) + "px"; }; gantt2.showCover = function(box) { if (box) { box.style.display = "block"; this._setLbPosition(box); } show_cover(); this._cover.style.display = ""; }; const show_cover = function() { if (gantt2._cover) { return; } gantt2._cover = document.createElement("div"); gantt2._cover.className = "gantt_cal_cover"; gantt2._cover.style.display = "none"; gantt2.event(gantt2._cover, "mousemove", gantt2._move_while_dnd); gantt2.event(gantt2._cover, "mouseup", gantt2._finish_dnd); const rootElement = gantt2._lightbox_root || gantt2.$root; rootElement.appendChild(gantt2._cover); }; gantt2._init_lightbox_events = function() { gantt2.lightbox_events = {}; gantt2.lightbox_events.gantt_save_btn = function() { gantt2._save_lightbox(); }; gantt2.lightbox_events.gantt_delete_btn = function() { gantt2._lightbox_current_type = null; if (!gantt2.callEvent("onLightboxDelete", [gantt2._lightbox_id])) return; if (gantt2.isTaskExists(gantt2._lightbox_id)) { gantt2.$click.buttons["delete"](gantt2._lightbox_id); } else { gantt2.hideLightbox(); } }; gantt2.lightbox_events.gantt_cancel_btn = function() { gantt2._cancel_lightbox(); }; gantt2.lightbox_events["default"] = function(e, src) { if (src.getAttribute("data-dhx-button")) { gantt2.callEvent("onLightboxButton", [src.className, src, e]); } else { var index, block, sec; var className = getClassName(src); if (className.indexOf("gantt_custom_button") != -1) { if (className.indexOf("gantt_custom_button_") != -1) { index = src.parentNode.getAttribute("data-index"); sec = src; while (sec && getClassName(sec).indexOf("gantt_cal_lsection") == -1) { sec = sec.parentNode; } } else { index = src.getAttribute("data-index"); sec = src.closest(".gantt_cal_lsection"); src = src.firstChild; } } var sections = gantt2._get_typed_lightbox_config(); if (index) { index = index * 1; block = gantt2.form_blocks[sections[index * 1].type]; block.button_click(index, src, sec, sec.nextSibling); } } }; this.event(gantt2.getLightbox(), "click", function(e) { if (e.target.closest(".gantt_cal_ltitle_close_btn")) { gantt2._cancel_lightbox(); } var src = getTargetNode(e); var className = getClassName(src); if (!className) { src = src.previousSibling; className = getClassName(src); } if (src && className && className.indexOf("gantt_btn_set") === 0) { src = src.firstChild; className = getClassName(src); } if (src && className) { var func = gantt2.defined(gantt2.lightbox_events[src.className]) ? gantt2.lightbox_events[src.className] : gantt2.lightbox_events["default"]; return func(e, src); } return false; }); gantt2.getLightbox().onkeydown = function(e) { var event2 = e || window.event; var target = e.target || e.srcElement; var buttonTarget = getClassName(target).indexOf("gantt_btn_set") > -1; switch ((e || event2).keyCode) { case gantt2.constants.KEY_CODES.SPACE: { if ((e || event2).shiftKey) return; if (buttonTarget && target.click) { target.click(); } break; } case gantt2.keys.edit_save: if ((e || event2).shiftKey) return; if (buttonTarget && target.click) { target.click(); } else { gantt2._save_lightbox(); } break; case gantt2.keys.edit_cancel: gantt2._cancel_lightbox(); break; } }; }; gantt2._cancel_lightbox = function() { var task = this.getLightboxValues("cancel"); gantt2._lightbox_current_type = null; this.callEvent("onLightboxCancel", [this._lightbox_id, task.$new]); if (gantt2.isTaskExists(task.id) && task.$new) { this.silent(function() { gantt2.$data.tasksStore.removeItem(task.id); gantt2._update_flags(task.id, null); }); this.refreshData(); } this.hideLightbox(); }; gantt2._save_lightbox = function() { var task = this.getLightboxValues("save"); gantt2._lightbox_current_type = null; if (!this.callEvent("onLightboxSave", [this._lightbox_id, task, !!task.$new])) return; gantt2.$data.tasksStore._skipTaskRecalculation = "lightbox"; if (task.$new) { delete task.$new; this.addTask(task, task.parent, this.getTaskIndex(task.id)); } else if (this.isTaskExists(task.id)) { this.mixin(this.getTask(task.id), task, true); this.refreshTask(task.id); this.updateTask(task.id); } gantt2.$data.tasksStore._skipTaskRecalculation = false; this.refreshData(); this.hideLightbox(); }; gantt2._resolve_default_mapping = function(section) { var mapping = section.map_to; var time_controls = { time: true, time_optional: true, duration: true, duration_optional: true }; if (time_controls[section.type]) { if (section.map_to == "auto") { mapping = { start_date: "start_date", end_date: "end_date", duration: "duration" }; } else if (typeof section.map_to === "string") { mapping = { start_date: section.map_to }; } } else if (section.type === "constraint") { if (!section.map_to || typeof section.map_to === "string") { mapping = { constraint_type: "constraint_type", constraint_date: "constraint_date" }; } } return mapping; }; gantt2.getLightboxValues = function(type) { let task = {}; if (gantt2.isTaskExists(this._lightbox_id)) { task = this.mixin({}, this.getTask(this._lightbox_id)); } const sns = this._get_typed_lightbox_config(); const sortedSns = [...sns].sort((a, b) => { if (a.name === "time") return 1; if (b.name === "time") return -1; return 0; }); for (let i = 0; i < sortedSns.length; i++) { let node = gantt2._lightbox_root.querySelector("#" + sortedSns[i].id); node = node ? node.nextSibling : node; let block = this.form_blocks[sortedSns[i].type]; if (!block) continue; let res = block.get_value.call(this, node, task, sortedSns[i], type); let map_to = gantt2._resolve_default_mapping(sortedSns[i]); if (typeof map_to == "string" && map_to != "auto") { task[map_to] = res; } else if (typeof map_to == "object") { for (let property in map_to) { if (map_to[property]) task[map_to[property]] = res[property]; } } } if (gantt2._lightbox_current_type) { task.type = gantt2._lightbox_current_type; } return task; }; gantt2.hideLightbox = function() { var box = this.getLightbox(); if (box) box.style.display = "none"; this._waiAria.lightboxHiddenAttr(box); this._lightbox_id = null; this.hideCover(box); this.resetLightbox(); this.callEvent("onAfterLightbox", []); }; gantt2.hideCover = function(box) { if (box) { box.style.display = "none"; } if (this._cover) this._cover.parentNode.removeChild(this._cover); this._cover = null; }; gantt2.resetLightbox = function() { if (gantt2._lightbox && !gantt2._custom_lightbox) gantt2._lightbox.remove(); gantt2._lightbox = null; }; gantt2._set_lightbox_values = function(data2, box) { var task = data2; var s = box.getElementsByTagName("span"); var lightboxHeader = []; if (gantt2.templates.lightbox_header) { lightboxHeader.push(""); lightboxHeader.push(gantt2.templates.lightbox_header(task.start_date, task.end_date, task)); s[1].innerHTML = ""; s[2].innerHTML = gantt2.templates.lightbox_header(task.start_date, task.end_date, task); } else { lightboxHeader.push(this.templates.task_time(task.start_date, task.end_date, task)); lightboxHeader.push(String(this.templates.task_text(task.start_date, task.end_date, task) || "").substr(0, 70)); s[1].innerHTML = this.templates.task_time(task.start_date, task.end_date, task); s[2].innerHTML = String(this.templates.task_text(task.start_date, task.end_date, task) || "").substr(0, 70); } s[1].innerHTML = lightboxHeader[0]; s[2].innerHTML = lightboxHeader[1]; gantt2._waiAria.lightboxHeader(box, lightboxHeader.join(" ")); var sns = this._get_typed_lightbox_config(this.getLightboxType()); for (var i = 0; i < sns.length; i++) { var section = sns[i]; if (!this.form_blocks[section.type]) { continue; } var node = gantt2._lightbox_root.querySelector("#" + section.id).nextSibling; var block = this.form_blocks[section.type]; var map_to = gantt2._resolve_default_mapping(sns[i]); var value = this.defined(task[map_to]) ? task[map_to] : section.default_value; block.set_value.call(gantt2, node, value, task, section); if (section.focus) block.focus.call(gantt2, node); } if (gantt2.isTaskExists(data2.id)) { gantt2._lightbox_id = data2.id; } }; gantt2._fill_lightbox = function(id, box) { var task = this.getTask(id); this._set_lightbox_values(task, box); }; gantt2.getLightboxSection = function(name) { var config2 = this._get_typed_lightbox_config(); var i = 0; for (i; i < config2.length; i++) if (config2[i].name == name) break; var section = config2[i]; if (!section) return null; if (!this._lightbox) this.getLightbox(); var header = gantt2._lightbox_root.querySelector("#" + section.id); var node = header.nextSibling; var result = { section, header, node, getValue: function(ev) { return gantt2.form_blocks[section.type].get_value.call(gantt2, node, ev || {}, section); }, setValue: function(value, ev) { return gantt2.form_blocks[section.type].set_value.call(gantt2, node, value, ev || {}, section); } }; var handler = this._lightbox_methods["get_" + section.type + "_control"]; return handler ? handler(result) : result; }; gantt2._lightbox_methods.get_template_control = function(result) { result.control = result.node; return result; }; gantt2._lightbox_methods.get_select_control = function(result) { result.control = result.node.getElementsByTagName("select")[0]; return result; }; gantt2._lightbox_methods.get_textarea_control = function(result) { result.control = result.node.getElementsByTagName("textarea")[0]; return result; }; gantt2._lightbox_methods.get_time_control = function(result) { result.control = result.node.getElementsByTagName("select"); return result; }; gantt2._init_dnd_events = function() { var eventElement = gantt2._lightbox_root; this.event(eventElement, "mousemove", gantt2._move_while_dnd); this.event(eventElement, "mouseup", gantt2._finish_dnd); this.event(eventElement, "touchmove", function(e) { gantt2._move_while_dnd(e.touches[0]); }); this.event(eventElement, "touchend", function(e) { gantt2._finish_dnd(e.touches[0]); }); }; gantt2._move_while_dnd = function(event2) { if (gantt2._dnd_start_lb) { if (!document.gantt_unselectable) { gantt2._lightbox_root.className += " gantt_unselectable"; document.gantt_unselectable = true; } var lb = gantt2.getLightbox(); var now = [event2.pageX, event2.pageY]; lb.style.top = gantt2._lb_start[1] + now[1] - gantt2._dnd_start_lb[1] + "px"; lb.style.left = gantt2._lb_start[0] + now[0] - gantt2._dnd_start_lb[0] + "px"; } }; gantt2._ready_to_dnd = function(event2) { var lb = gantt2.getLightbox(); gantt2._lb_start = [lb.offsetLeft, lb.offsetTop]; gantt2._dnd_start_lb = [event2.pageX, event2.pageY]; }; gantt2._finish_dnd = function() { if (gantt2._lb_start) { gantt2._lb_start = gantt2._dnd_start_lb = false; gantt2._lightbox_root.className = gantt2._lightbox_root.className.replace(" gantt_unselectable", ""); document.gantt_unselectable = false; } }; gantt2._focus = function(node, select) { if (node && node.focus) { if (gantt2.config.touch) ; else { try { if (select && node.select) node.select(); node.focus(); } catch (e) { } } } }; gantt2.form_blocks = { getTimePicker: function(sns, hidden) { var html = ""; var cfg = this.config; var i; var options; var ariaAttrs; var readonly; var display; var settings = { first: 0, last: 24 * 60, date: this.date.date_part(new Date(gantt2._min_date.valueOf())), timeFormat: getTimeFormat(sns) }; sns._time_format_order = { size: 0 }; if (gantt2.config.limit_time_select) { settings.first = 60 * cfg.first_hour; settings.last = 60 * cfg.last_hour + 1; settings.date.setHours(cfg.first_hour); } for (i = 0; i < settings.timeFormat.length; i++) { if (i > 0) { html += " "; } options = getHtmlTimePickerOptions(sns, i, settings); if (options) { ariaAttrs = gantt2._waiAria.lightboxSelectAttrString(settings.timeFormat[i]); readonly = sns.readonly ? "disabled='disabled'" : ""; display = hidden ? " style='display:none' " : ""; html += ""; } } return html; }, getTimePickerValue: function(selects, config2, offset) { var map = config2._time_format_order; var needSetTime = gantt2.defined(map[3]); var time; var hours = 0; var minutes = 0; var mapOffset = offset || 0; if (needSetTime) { time = parseInt(selects[map[3] + mapOffset].value, 10); hours = Math.floor(time / 60); minutes = time % 60; } return new Date(selects[map[2] + mapOffset].value, selects[map[1] + mapOffset].value, selects[map[0] + mapOffset].value, hours, minutes); }, _fill_lightbox_select: function(s, i, d, map) { s[i + map[0]].value = d.getDate(); s[i + map[1]].value = d.getMonth(); s[i + map[2]].value = d.getFullYear(); if (gantt2.defined(map[3])) { var v = d.getHours() * 60 + d.getMinutes(); v = Math.round(v / gantt2._get_timepicker_step()) * gantt2._get_timepicker_step(); var input = s[i + map[3]]; input.value = v; input.setAttribute("data-value", v); } }, template: new TemplateControl(), textarea: new TextareaControl(), select: new SelectControl(), time: new TimeControl(), duration: new DurationControl(), parent: new ParentControl(), radio: new RadioControl(), checkbox: new CheckboxControl(), resources: new ResourcesControl(), constraint: new ConstraintControl(), baselines: new BaselineControl(), typeselect: new TypeselectControl(), resource_selector: new NewResourcesControl() }; gantt2._is_lightbox_timepicker = function() { var s = this._get_typed_lightbox_config(); for (var i = 0; i < s.length; i++) if (s[i].name == "time" && s[i].type == "time") return true; return false; }; gantt2._delete_task_confirm = function({ task, message, title, callback, ok }) { gantt2._simple_confirm(message, title, callback, ok); }; gantt2._delete_link_confirm = function({ link, message, title, callback, ok }) { gantt2._simple_confirm(message, title, callback, ok); }; gantt2._simple_confirm = function(message, title, callback, ok) { if (!message) return callback(); var opts = { text: message }; if (title) opts.title = title; if (ok) { opts.ok = ok; } if (callback) { opts.callback = function(result) { if (result) callback(); }; } gantt2.confirm(opts); }; function _get_type_name(type_value) { for (var i in this.config.types) { if (this.config.types[i] == type_value) { return i; } } return "task"; } gantt2._get_typed_lightbox_config = function(type) { if (type === void 0) { type = this.getLightboxType(); } var field = _get_type_name.call(this, type); if (gantt2.config.lightbox[field + "_sections"]) { return gantt2.config.lightbox[field + "_sections"]; } else { return gantt2.config.lightbox.sections; } }; gantt2._silent_redraw_lightbox = function(type) { var oldType = this.getLightboxType(); if (this.getState().lightbox) { var taskId = this.getState().lightbox; var formData = this.getLightboxValues(), task = this.copy(this.getTask(taskId)); this.resetLightbox(); var updTask = this.mixin(task, formData, true); var box = this.getLightbox(type ? type : void 0); this._set_lightbox_values(updTask, box); this.showCover(box); } else { this.resetLightbox(); this.getLightbox(type ? type : void 0); } this.callEvent("onLightboxChange", [oldType, this.getLightboxType()]); }; function bindLabelsToInputs(sns) { var section; var label; var labelBlock; var inputBlock; var input; var i; for (i = 0; i < sns.length; i++) { section = sns[i]; labelBlock = gantt2._lightbox_root.querySelector("#" + section.id); if (!section.id || !labelBlock) continue; label = labelBlock.querySelector("label"); inputBlock = labelBlock.nextSibling; if (!inputBlock) continue; input = inputBlock.querySelector("input, select, textarea"); if (input) { input.id = input.id || "input_" + gantt2.uid(); section.inputId = input.id; label.setAttribute("for", section.inputId); } } } function getHtmlButtons(buttons, floatRight) { var button; var ariaAttr; var html = ""; var i; for (i = 0; i < buttons.length; i++) { button = gantt2.config._migrate_buttons[buttons[i]] ? gantt2.config._migrate_buttons[buttons[i]] : buttons[i]; ariaAttr = gantt2._waiAria.lightboxButtonAttrString(button); html += "
" + gantt2.locale.labels[button] + "
"; } return html; } function getTimeFormat(sns) { var scale; var unit; var result; if (sns.time_format) return sns.time_format; result = ["%d", "%m", "%Y"]; scale = gantt2.getScale(); unit = scale ? scale.unit : gantt2.config.duration_unit; if (getSecondsInUnit(unit) < getSecondsInUnit("day")) { result.push("%H:%i"); } return result; } function getHtmlTimePickerOptions(sns, index, settings) { var range; var offset; var start_year; var end_year; var i; var time; var diff; var tdate; var html = ""; switch (settings.timeFormat[index]) { case "%Y": sns._time_format_order[2] = index; sns._time_format_order.size++; if (sns.year_range) { if (!isNaN(sns.year_range)) { range = sns.year_range; } else if (sns.year_range.push) { start_year = sns.year_range[0]; end_year = sns.year_range[1]; } } range = range || 10; offset = offset || Math.floor(range / 2); start_year = start_year || settings.date.getFullYear() - offset; end_year = end_year || gantt2.getState().max_date.getFullYear() + offset; for (i = start_year; i <= end_year; i++) html += ""; break; case "%m": sns._time_format_order[1] = index; sns._time_format_order.size++; for (i = 0; i < 12; i++) html += ""; break; case "%d": sns._time_format_order[0] = index; sns._time_format_order.size++; for (i = 1; i < 32; i++) html += ""; break; case "%H:%i": sns._time_format_order[3] = index; sns._time_format_order.size++; i = settings.first; tdate = settings.date.getDate(); sns._time_values = []; while (i < settings.last) { time = gantt2.templates.time_picker(settings.date); html += ""; sns._time_values.push(i); settings.date.setTime(settings.date.valueOf() + gantt2._get_timepicker_step() * 60 * 1e3); diff = settings.date.getDate() != tdate ? 1 : 0; i = diff * 24 * 60 + settings.date.getHours() * 60 + settings.date.getMinutes(); } break; } return html; } } function lightbox_optional_time(gantt2) { gantt2._extend_to_optional = function(lightbox_block) { var duration = lightbox_block; var optional_time = { render: duration.render, focus: duration.focus, set_value: function(node, value, task, section) { var mapping = gantt2._resolve_default_mapping(section); if (!task[mapping.start_date] || mapping.start_date == "start_date" && this._isAllowedUnscheduledTask(task)) { optional_time.disable(node, section); var val = {}; for (var i in mapping) { val[mapping[i]] = task[i]; } return duration.set_value.call(gantt2, node, value, val, section); } else { optional_time.enable(node, section); return duration.set_value.call(gantt2, node, value, task, section); } }, get_value: function(node, task, section) { if (section.disabled) { return { start_date: null }; } else { return duration.get_value.call(gantt2, node, task, section); } }, update_block: function(node, section) { gantt2.callEvent("onSectionToggle", [gantt2._lightbox_id, section]); node.style.display = section.disabled ? "none" : ""; if (section.button) { var button = node.previousSibling.querySelector(".gantt_custom_button_label"), labels = gantt2.locale.labels; var button_text = section.disabled ? labels[section.name + "_enable_button"] : labels[section.name + "_disable_button"]; button.innerHTML = button_text; } }, disable: function(node, section) { section.disabled = true; optional_time.update_block(node, section); }, enable: function(node, section) { section.disabled = false; optional_time.update_block(node, section); }, button_click: function(index, el, section, container) { if (gantt2.callEvent("onSectionButton", [gantt2._lightbox_id, section]) === false) { return; } var config2 = gantt2._get_typed_lightbox_config()[index]; if (config2.disabled) { optional_time.enable(container, config2); } else { optional_time.disable(container, config2); } } }; return optional_time; }; gantt2.form_blocks.duration_optional = gantt2._extend_to_optional(gantt2.form_blocks.duration); gantt2.form_blocks.time_optional = gantt2._extend_to_optional(gantt2.form_blocks.time); } function wai_aria(gantt2) { var htmlTags = new RegExp("<(?:.|\n)*?>", "gm"); var extraSpaces = new RegExp(" +", "gm"); function stripHTMLLite(htmlText) { return (htmlText + "").replace(htmlTags, " ").replace(extraSpaces, " "); } var singleQuotes = new RegExp("'", "gm"); function escapeQuotes(text) { return (text + "").replace(singleQuotes, "'"); } gantt2._waiAria = { getAttributeString: function(attr) { var attributes = [" "]; for (var i2 in attr) { var text = escapeQuotes(stripHTMLLite(attr[i2])); attributes.push(i2 + "='" + text + "'"); } attributes.push(" "); return attributes.join(" "); }, getTimelineCellAttr: function(dateString) { return gantt2._waiAria.getAttributeString({ "aria-label": dateString }); }, _taskCommonAttr: function(task, div) { if (!(task.start_date && task.end_date)) return; div.setAttribute("aria-label", stripHTMLLite(gantt2.templates.tooltip_text(task.start_date, task.end_date, task))); if (task.$dataprocessor_class) { div.setAttribute("aria-busy", true); } }, setTaskBarAttr: function(task, div) { this._taskCommonAttr(task, div); div.setAttribute("role", "img"); if (!gantt2.isReadonly(task) && gantt2.config.drag_move) { if (task.id != gantt2.getState("tasksDnd").drag_id) { div.setAttribute("aria-grabbed", false); } else { div.setAttribute("aria-grabbed", true); } } }, taskRowAttr: function(task, div) { this._taskCommonAttr(task, div); if (!gantt2.isReadonly(task) && gantt2.config.order_branch) { div.setAttribute("aria-grabbed", false); } div.setAttribute("role", "row"); div.setAttribute("aria-selected", gantt2.isSelectedTask(task.id) ? "true" : "false"); div.setAttribute("aria-level", task.$level + 1 || 1); if (gantt2.hasChild(task.id)) { div.setAttribute("aria-expanded", task.$open ? "true" : "false"); } }, linkAttr: function(link, div) { var linkTypes = gantt2.config.links; var toStart = link.type == linkTypes.finish_to_start || link.type == linkTypes.start_to_start; var fromStart = link.type == linkTypes.start_to_start || link.type == linkTypes.start_to_finish; var content = gantt2.locale.labels.link + " " + gantt2.templates.drag_link(link.source, fromStart, link.target, toStart); div.setAttribute("role", "img"); div.setAttribute("aria-label", stripHTMLLite(content)); }, gridSeparatorAttr: function(div) { div.setAttribute("role", "columnheader"); }, rowResizerAttr: function(div) { div.setAttribute("role", "row"); }, lightboxHiddenAttr: function(div) { div.setAttribute("aria-hidden", "true"); }, lightboxVisibleAttr: function(div) { div.setAttribute("aria-hidden", "false"); }, lightboxAttr: function(div) { div.setAttribute("role", "dialog"); div.setAttribute("aria-hidden", "true"); div.firstChild.setAttribute("role", "heading"); div.firstChild.setAttribute("aria-level", "1"); }, lightboxButtonAttrString: function(buttonName) { return this.getAttributeString({ role: "button", "aria-label": gantt2.locale.labels[buttonName], tabindex: "0" }); }, lightboxHeader: function(div, headerText) { div.setAttribute("aria-label", headerText); }, lightboxSelectAttrString: function(time_option) { var label = ""; switch (time_option) { case "%Y": label = gantt2.locale.labels.years; break; case "%m": label = gantt2.locale.labels.months; break; case "%d": label = gantt2.locale.labels.days; break; case "%H:%i": label = gantt2.locale.labels.hours + gantt2.locale.labels.minutes; break; } return gantt2._waiAria.getAttributeString({ "aria-label": label }); }, lightboxDurationInputAttrString: function(section) { return this.getAttributeString({ "aria-label": gantt2.locale.labels.column_duration, "aria-valuemin": "0", role: "spinbutton" }); }, inlineEditorAttr: function(div) { div.setAttribute("role", "row"); }, gridAttrString: function() { return [" role='treegrid'", gantt2.config.multiselect ? "aria-multiselectable='true'" : "aria-multiselectable='false'", " "].join(" "); }, gridScaleRowAttrString: function() { return "role='row'"; }, gridScaleCellAttrString: function(column, label) { var attrs = ""; if (column.name == "add") { attrs = this.getAttributeString({ role: "columnheader", "aria-label": gantt2.locale.labels.new_task }); } else { var attributes = { role: "columnheader", "aria-label": gantt2.config.external_render && gantt2.config.external_render.isElement(label) ? "" : label }; if (gantt2._sort && gantt2._sort.name == column.name) { if (gantt2._sort.direction == "asc") { attributes["aria-sort"] = "ascending"; } else { attributes["aria-sort"] = "descending"; } } attrs = this.getAttributeString(attributes); } return attrs; }, gridDataAttrString: function() { return "role='rowgroup'"; }, reorderMarkerAttr: function(div) { div.setAttribute("role", "grid"); div.firstChild.removeAttribute("aria-level"); div.firstChild.setAttribute("aria-grabbed", "true"); }, gridCellAttrString: function(column, textValue, task) { var attributes = { role: "gridcell", "aria-label": textValue }; if (!column.editor || gantt2.isReadonly(task)) { attributes["aria-readonly"] = true; } return this.getAttributeString(attributes); }, gridAddButtonAttrString: function(column) { return this.getAttributeString({ role: "button", "aria-label": gantt2.locale.labels.new_task }); }, messageButtonAttrString: function(buttonLabel) { return "tabindex='0' role='button' aria-label='" + buttonLabel + "'"; }, messageInfoAttr: function(div) { div.setAttribute("role", "alert"); }, messageModalAttr: function(div, uid2) { div.setAttribute("role", "dialog"); if (uid2) { div.setAttribute("aria-labelledby", uid2); } }, quickInfoAttr: function(div) { div.setAttribute("role", "dialog"); }, quickInfoHeaderAttrString: function() { return " role='heading' aria-level='1' "; }, quickInfoHeader: function(div, header) { div.setAttribute("aria-label", header); }, quickInfoButtonAttrString: function(label) { return gantt2._waiAria.getAttributeString({ role: "button", "aria-label": label, tabindex: "0" }); }, tooltipAttr: function(div) { div.setAttribute("role", "tooltip"); }, tooltipVisibleAttr: function(div) { div.setAttribute("aria-hidden", "false"); }, tooltipHiddenAttr: function(div) { div.setAttribute("aria-hidden", "true"); } }; function isDisabled() { return !gantt2.config.wai_aria_attributes; } for (var i in gantt2._waiAria) { gantt2._waiAria[i] = /* @__PURE__ */ function(payload) { return function() { if (isDisabled()) { return ""; } return payload.apply(this, arguments); }; }(gantt2._waiAria[i]); } } function ui(gantt2) { if (!env.isNode) { gantt2.utils = { arrayFind, dom: domHelpers }; var domEvents = createScope(); gantt2.event = domEvents.attach; gantt2.eventRemove = domEvents.detach; gantt2._eventRemoveAll = domEvents.detachAll; gantt2._createDomEventScope = domEvents.extend; mixin(gantt2, messages(gantt2)); var uiApi = ui$1.init(gantt2); gantt2.$ui = uiApi.factory; gantt2.$ui.layers = uiApi.render; gantt2.$mouseEvents = uiApi.mouseEvents; gantt2.$services.setService("mouseEvents", function() { return gantt2.$mouseEvents; }); gantt2.mixin(gantt2, uiApi.layersApi); taskLayers(gantt2); gantt2.$services.setService("layers", function() { return uiApi.layersService; }); gantt2.mixin(gantt2, createLayoutFacade()); skin(gantt2); skyblue(gantt2); dark(gantt2); meadow(gantt2); terrace(gantt2); broadway(gantt2); material(gantt2); contrast_black(gantt2); contrast_white(gantt2); plugins(gantt2); touch(gantt2); lightbox(gantt2); lightbox_optional_time(gantt2); wai_aria(gantt2); gantt2.locate = function(e) { var trg = getTargetNode(e); if (closest(trg, ".gantt_task_row")) { return null; } var targetAttribute = arguments[1] || this.config.task_attribute; var node = locateAttribute(trg, targetAttribute); if (node) { return node.getAttribute(targetAttribute); } else { return null; } }; gantt2._locate_css = function(e, classname, strict) { return locateClassName(e, classname, strict); }; gantt2._locateHTML = function(e, attribute) { return locateAttribute(e, attribute || this.config.task_attribute); }; } gantt2.attachEvent("onParse", function() { if (!isHeadless(gantt2)) { gantt2.attachEvent("onGanttRender", function() { if (gantt2.config.initial_scroll) { var firstTask = gantt2.getTaskByIndex(0); var id = firstTask ? firstTask.id : gantt2.config.root_id; if (gantt2.isTaskExists(id) && gantt2.$task && gantt2.utils.dom.isChildOf(gantt2.$task, gantt2.$container)) { gantt2.showTask(id); } } }, { once: true }); } }); gantt2.attachEvent("onBeforeGanttReady", function() { if (!this.config.scroll_size) this.config.scroll_size = getScrollSize() || 15; if (!isHeadless(gantt2)) { this._eventRemoveAll(); this.$mouseEvents.reset(); this.resetLightbox(); } }); gantt2.attachEvent("onGanttReady", function() { if (!isHeadless(gantt2) && gantt2.config.rtl) { gantt2.$layout.getCellsByType("viewCell").forEach(function(cell) { var attachedScrollbar = cell.$config.scrollX; if (!attachedScrollbar) return; var scrollbar = gantt2.$ui.getView(attachedScrollbar); if (scrollbar) scrollbar.scrollTo(scrollbar.$config.scrollSize, 0); }); } }); gantt2.attachEvent("onGanttReady", function() { if (!isHeadless(gantt2)) { var activePlugins = gantt2.plugins(); var availablePlugins = { auto_scheduling: gantt2.autoSchedule, click_drag: gantt2.ext.clickDrag, critical_path: gantt2.isCriticalTask, drag_timeline: gantt2.ext.dragTimeline, export_api: gantt2.exportToPDF, fullscreen: gantt2.ext.fullscreen, grouping: gantt2.groupBy, keyboard_navigation: gantt2.ext.keyboardNavigation, marker: gantt2.addMarker, multiselect: gantt2.eachSelectedTask, overlay: gantt2.ext.overlay, quick_info: gantt2.templates.quick_info_content, tooltip: gantt2.ext.tooltips, undo: gantt2.undo }; for (let plugin in availablePlugins) { if (availablePlugins[plugin] && !activePlugins[plugin]) { console.warn(`You connected the '${plugin}' extension via an obsolete file. To fix it, you need to remove the obsolete file and connect the extension via the plugins method: https://docs.dhtmlx.com/gantt/api__gantt_plugins.html`); } } } }); } function ajaxLoading(gantt2) { gantt2.load = function(url, type, callback) { this._load_url = url; this.assert(arguments.length, "Invalid load arguments"); var tp = "json", cl = null; if (arguments.length >= 3) { tp = type; cl = callback; } else { if (typeof arguments[1] == "string") tp = arguments[1]; else if (typeof arguments[1] == "function") cl = arguments[1]; } this._load_type = tp; this.callEvent("onLoadStart", [url, tp]); return this.ajax.get(url, gantt2.bind(function(l) { this.on_load(l, tp); this.callEvent("onLoadEnd", [url, tp]); if (typeof cl == "function") cl.call(this); }, this)); }; } function base(supportedExtensions) { var gantt2 = factory(supportedExtensions); if (!gantt2.env.isNode) { ui(gantt2); ajaxLoading(gantt2); } return gantt2; } const gantt$1 = scope.gantt = base(extensions); exports2.default = gantt$1; exports2.gantt = gantt$1; Object.defineProperties(exports2, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); }); //# sourceMappingURL=dhtmlxgantt.js.map