/*
|
@license
|
|
dhtmlxGantt v.6.2.6 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 Commercial/Enterprise or Ultimate license on our site https://dhtmlx.com/docs/products/dhtmlxGantt/#licensing or contact us at sales@dhtmlx.com
|
|
(c) XB Software Ltd.
|
|
*/
|
(function webpackUniversalModuleDefinition(root, factory) {
|
if(typeof exports === 'object' && typeof module === 'object')
|
module.exports = factory();
|
else if(typeof define === 'function' && define.amd)
|
define([], factory);
|
else {
|
var a = factory();
|
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
}
|
})(window, function() {
|
return /******/ (function(modules) { // webpackBootstrap
|
/******/ // The module cache
|
/******/ var installedModules = {};
|
/******/
|
/******/ // The require function
|
/******/ function __webpack_require__(moduleId) {
|
/******/
|
/******/ // Check if module is in cache
|
/******/ if(installedModules[moduleId]) {
|
/******/ return installedModules[moduleId].exports;
|
/******/ }
|
/******/ // Create a new module (and put it into the cache)
|
/******/ var module = installedModules[moduleId] = {
|
/******/ i: moduleId,
|
/******/ l: false,
|
/******/ exports: {}
|
/******/ };
|
/******/
|
/******/ // Execute the module function
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
/******/
|
/******/ // Flag the module as loaded
|
/******/ module.l = true;
|
/******/
|
/******/ // Return the exports of the module
|
/******/ return module.exports;
|
/******/ }
|
/******/
|
/******/
|
/******/ // expose the modules object (__webpack_modules__)
|
/******/ __webpack_require__.m = modules;
|
/******/
|
/******/ // expose the module cache
|
/******/ __webpack_require__.c = installedModules;
|
/******/
|
/******/ // define getter function for harmony exports
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
/******/ }
|
/******/ };
|
/******/
|
/******/ // define __esModule on exports
|
/******/ __webpack_require__.r = function(exports) {
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
/******/ }
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
/******/ };
|
/******/
|
/******/ // create a fake namespace object
|
/******/ // mode & 1: value is a module id, require it
|
/******/ // mode & 2: merge all properties of value into the ns
|
/******/ // mode & 4: return value when already ns object
|
/******/ // mode & 8|1: behave like require
|
/******/ __webpack_require__.t = function(value, mode) {
|
/******/ if(mode & 1) value = __webpack_require__(value);
|
/******/ if(mode & 8) return value;
|
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
/******/ var ns = Object.create(null);
|
/******/ __webpack_require__.r(ns);
|
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
/******/ return ns;
|
/******/ };
|
/******/
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
/******/ __webpack_require__.n = function(module) {
|
/******/ var getter = module && module.__esModule ?
|
/******/ function getDefault() { return module['default']; } :
|
/******/ function getModuleExports() { return module; };
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
/******/ return getter;
|
/******/ };
|
/******/
|
/******/ // Object.prototype.hasOwnProperty.call
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
/******/
|
/******/ // __webpack_public_path__
|
/******/ __webpack_require__.p = "/codebase/sources/";
|
/******/
|
/******/
|
/******/ // Load entry module and return exports
|
/******/ return __webpack_require__(__webpack_require__.s = "./sources/ext/undo.js");
|
/******/ })
|
/************************************************************************/
|
/******/ ({
|
|
/***/ "./sources/ext/undo.js":
|
/*!*****************************!*\
|
!*** ./sources/ext/undo.js ***!
|
\*****************************/
|
/*! no static exports found */
|
/***/ (function(module, exports) {
|
|
gantt.config.undo_steps = 10;
|
gantt.config.undo = true;
|
gantt.config.redo = true;
|
|
gantt.undo = function(){
|
this._undo.undo();
|
};
|
|
gantt.getUndoStack = function(){
|
return this._undo._undoStack;
|
};
|
|
gantt.getRedoStack = function(){
|
return this._undo._redoStack;
|
};
|
|
gantt.clearUndoStack = function(){
|
this._undo._undoStack = [];
|
};
|
|
gantt.clearRedoStack = function(){
|
this._undo._redoStack = [];
|
};
|
|
gantt.redo = function(){
|
this._undo.redo();
|
};
|
|
/**
|
* entities that require different processing for undoing-redoing changes
|
* @type {{link: string, task: string}}
|
*/
|
gantt.config.undo_types = {
|
link: "link",
|
task: "task"
|
};
|
|
/**
|
* types of traced actions
|
* @type {{update: string, remove: string, add: string}}
|
*/
|
gantt.config.undo_actions = {
|
update: "update",
|
remove: "remove", // remove item from datastore
|
add: "add",
|
move: "move" // move task in grid
|
};
|
|
gantt._undo = {
|
_undoStack:[],
|
_redoStack:[],
|
maxSteps:10,
|
undo_enabled: true,
|
redo_enabled: true,
|
_push: function(stack, action){
|
if(!action.commands.length)
|
return;
|
|
var event = stack === this._undoStack ? "onBeforeUndoStack" : "onBeforeRedoStack";
|
if(gantt.callEvent(event, [action]) === false){
|
return;
|
}
|
// commands can be removed from event handler
|
if(!action.commands.length)
|
return;
|
|
stack.push(action);
|
while(stack.length > this.maxSteps){
|
stack.shift();
|
}
|
return action;
|
},
|
_pop:function(stack){
|
return stack.pop();
|
},
|
|
_reorderCommands: function(action){
|
// firstly process tasks and only then links
|
// in order to ensure links are added not earlier than their tasks
|
// firstly to 'move' actions and only then updates
|
var weights = {any: 0, link:1, task:2};
|
var 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.$index - b.$index;
|
}else{
|
return 0;
|
}
|
|
}else{
|
var weightA = weights[a.entity] || weights.any;
|
var weightB = weights[b.entity] || weights.any;
|
return weightB - weightA;
|
}
|
|
});
|
},
|
undo:function(){
|
this.updateConfigs();
|
if(!this.undo_enabled)
|
return;
|
|
var action = this._pop(this._undoStack);
|
if(action)
|
this._reorderCommands(action);
|
if(gantt.callEvent("onBeforeUndo", [action]) !== false){
|
if(action){
|
|
this._applyAction(this.action.invert(action));
|
this._push(this._redoStack, gantt.copy(action));
|
gantt.callEvent("onAfterUndo", [action]);
|
return;
|
}
|
}
|
gantt.callEvent("onAfterUndo", [null]);
|
},
|
|
redo:function(){
|
this.updateConfigs();
|
if(!this.redo_enabled)
|
return;
|
|
var action = this._pop(this._redoStack);
|
if(action)
|
this._reorderCommands(action);
|
|
if(gantt.callEvent("onBeforeRedo", [action]) !== false){
|
if(action){
|
this._applyAction(action);
|
this._push(this._undoStack, gantt.copy(action));
|
gantt.callEvent("onAfterRedo", [action]);
|
return;
|
}
|
}
|
gantt.callEvent("onAfterRedo", [null]);
|
},
|
|
_applyAction:function(action){
|
var command = null,
|
entities = this.command.entity,
|
actions = this.command.type;
|
|
var methods = {};
|
methods[entities.task] = {
|
add: "addTask",
|
update: "updateTask",
|
remove: "deleteTask",
|
move: "moveTask",
|
isExists: "isTaskExists"
|
};
|
methods[entities.link] = {
|
add: "addLink",
|
update: "updateLink",
|
remove: "deleteLink",
|
isExists: "isLinkExists"
|
};
|
|
gantt.batchUpdate(function() {
|
for (var i = 0; i < action.commands.length; i++) {
|
command = action.commands[i];
|
var method = methods[command.entity][command.type],
|
check = methods[command.entity]["isExists"];
|
|
if (command.type == actions.add) {
|
gantt[method](command.oldValue, command.oldValue.parent, command.oldValue.$index);
|
} else if (command.type == actions.remove) {
|
if (gantt[check](command.value.id))
|
gantt[method](command.value.id);
|
} else if (command.type == actions.update) {
|
gantt[method](command.value.id, command.value);
|
} else if (command.type == actions.move) {
|
gantt[method](command.value.id, command.value.$index, command.value.parent);
|
}
|
}
|
});
|
},
|
|
//storeUndo:
|
logAction: function(action){
|
this._push(this._undoStack, action);
|
this._redoStack = [];
|
},
|
|
action: {
|
create: function(commands){
|
return {commands: commands ? commands.slice() : []};
|
},
|
invert: function(action){
|
var revert = gantt.copy(action);
|
var commands = gantt._undo.command;
|
|
for(var i = 0; i < action.commands.length; i++){
|
var command = revert.commands[i] = commands.invert(revert.commands[i]);
|
if(command.type == commands.type.update || command.type == commands.type.move){
|
var value = command.value;
|
command.value = command.oldValue;
|
command.oldValue = value;
|
}
|
}
|
return revert;
|
}
|
},
|
|
command:{
|
create: function(value, oldValue, type, entity){
|
return {
|
entity:entity,
|
type:type,
|
value:gantt.copy(value),
|
oldValue:gantt.copy(oldValue || value)
|
};
|
},
|
invert: function(command){
|
var revert = gantt.copy(command);
|
revert.type = this.inverseCommands(command.type);
|
return revert;
|
},
|
// entities that require different processing for undoing-redoing changes
|
entity:null,
|
|
//types of traced actions
|
type:null,
|
inverseCommands:function(command){
|
switch (command){
|
case this.type.update:
|
return this.type.update;
|
case this.type.remove:
|
return this.type.add;
|
case this.type.add:
|
return this.type.remove;
|
case this.type.load:
|
return this.type.clear;
|
case this.type.clear:
|
return this.type.load;
|
case this.type.move:
|
return this.type.move;
|
default:
|
gantt.assert(false, "Invalid command "+ command);
|
return null;
|
}
|
}
|
},
|
|
monitor: {
|
_batchAction: null,
|
_batchMode: false,
|
_ignore: false,
|
_ignoreMoveEvents: false,
|
isMoveEventsIgnored: function() {
|
return this._ignoreMoveEvents;
|
},
|
toggleIgnoreMoveEvents: function(newValue) {
|
this._ignoreMoveEvents = newValue || false;
|
},
|
startIgnore: function(){
|
this._ignore = true;
|
},
|
stopIgnore: function(){
|
this._ignore = false;
|
},
|
startBatchAction : function(){
|
// try catching updates made from event handlers using timeout
|
if(this.timeout){
|
clearTimeout(this.timeout);
|
}
|
this.timeout = setTimeout(function(){
|
gantt._undo.monitor.stopBatchAction();
|
}, 10);
|
|
|
if(this._ignore || this._batchMode)
|
return;
|
|
this._batchMode = true;
|
this._batchAction = gantt._undo.action.create();
|
},
|
stopBatchAction: function(){
|
if(this._ignore)
|
return;
|
var undo = gantt._undo;
|
if(this._batchAction){
|
undo.logAction(this._batchAction);
|
}
|
this._batchMode = false;
|
this._batchAction = null;
|
},
|
|
_storeCommand: function(command){
|
var undo = gantt._undo;
|
undo.updateConfigs();
|
|
if(!undo.undo_enabled)
|
return;
|
|
if(this._batchMode){
|
this._batchAction.commands.push(command);
|
}else{
|
var action = undo.action.create([command]);
|
undo.logAction(action);
|
}
|
},
|
_storeEntityCommand: function(obj, old, actionType, entityType){
|
var undo = gantt._undo;
|
var command = undo.command.create(obj, old, actionType, entityType);
|
this._storeCommand(command);
|
},
|
_storeTaskCommand: function(obj, type){
|
this._storeEntityCommand(obj, this.getInitialTask(obj.id), type, gantt._undo.command.entity.task);
|
},
|
_storeLinkCommand: function(obj, type){
|
this._storeEntityCommand(obj, this.getInitialLink(obj.id), type, gantt._undo.command.entity.link);
|
},
|
onTaskAdded:function(task){
|
if(!this._ignore)
|
this._storeTaskCommand(task, gantt._undo.command.type.add);
|
},
|
onTaskUpdated:function(task){
|
if(!this._ignore)
|
this._storeTaskCommand(task, gantt._undo.command.type.update);
|
},
|
onTaskMoved: function(task){
|
if (!this._ignore) {
|
this._storeEntityCommand(
|
task,
|
this.getInitialTask(task.id),
|
gantt._undo.command.type.move,
|
gantt._undo.command.entity.task
|
);
|
}
|
},
|
onTaskDeleted: function(task){
|
if(!this._ignore){
|
this._storeTaskCommand(task, gantt._undo.command.type.remove);
|
if(this._nestedTasks[task.id]){
|
var children = this._nestedTasks[task.id];
|
for(var i = 0; i < children.length; i++){
|
this._storeTaskCommand(children[i], gantt._undo.command.type.remove);
|
}
|
}
|
if(this._nestedLinks[task.id]){
|
var childrenLinks = this._nestedLinks[task.id];
|
for(var i = 0; i < childrenLinks.length; i++){
|
this._storeLinkCommand(childrenLinks[i], gantt._undo.command.type.remove);
|
}
|
}
|
}
|
},
|
|
onLinkAdded: function(link){
|
if(!this._ignore)
|
this._storeLinkCommand(link, gantt._undo.command.type.add);
|
},
|
onLinkUpdated: function(link){
|
if(!this._ignore)
|
this._storeLinkCommand(link, gantt._undo.command.type.update);
|
},
|
onLinkDeleted: function(link){
|
if(!this._ignore)
|
this._storeLinkCommand(link, gantt._undo.command.type.remove);
|
},
|
_initialTasks:{},
|
_nestedTasks:{},
|
_nestedLinks:{},
|
_getLinks: function(task){
|
return task.$source.concat(task.$target);
|
},
|
setNestedTasks: function(id, taskIds){
|
var task = null,
|
tasks = [],
|
linkIds = this._getLinks(gantt.getTask(id));
|
|
for(var i = 0; i < taskIds.length; i++){
|
task = this.setInitialTask(taskIds[i]);
|
|
linkIds = linkIds.concat(this._getLinks(task));
|
|
|
tasks.push(task);
|
}
|
|
var uniqueLinks = {};
|
for(var i = 0; i < linkIds.length; i++){
|
uniqueLinks[linkIds[i]] = true;
|
}
|
var links = [];
|
for(var i in uniqueLinks){
|
links.push(this.setInitialLink(i));
|
}
|
this._nestedTasks[id] = tasks;
|
this._nestedLinks[id] = links;
|
},
|
setInitialTask: function(id, overwrite){
|
if (overwrite || (!this._initialTasks[id] || !this._batchMode)) {
|
var task = gantt.copy(gantt.getTask(id));
|
task.$index = gantt.getTaskIndex(id);
|
this.setInitialTaskObject(id, task);
|
}
|
return this._initialTasks[id];
|
},
|
getInitialTask: function(id){
|
return this._initialTasks[id];
|
},
|
clearInitialTasks: function(){
|
this._initialTasks = {};
|
},
|
setInitialTaskObject: function(id, object) {
|
this._initialTasks[id] = object;
|
},
|
|
_initialLinks:{},
|
setInitialLink: function(id){
|
if(!this._initialLinks[id] || !this._batchMode)
|
this._initialLinks[id] = gantt.copy(gantt.getLink(id));
|
|
return this._initialLinks[id];
|
},
|
getInitialLink: function(id){
|
return this._initialLinks[id];
|
}
|
}
|
|
|
};
|
gantt._undo.updateConfigs = function(){
|
gantt._undo.maxSteps = gantt.config.undo_steps;
|
gantt._undo.command.entity = gantt.config.undo_types;
|
gantt._undo.command.type = gantt.config.undo_actions;
|
gantt._undo.undo_enabled = !!gantt.config.undo;
|
gantt._undo.redo_enabled = (!!gantt.config.undo) && (!!gantt.config.redo);
|
};
|
|
|
(function(){
|
|
var monitor = gantt._undo.monitor;
|
|
var noTrack = {
|
"onBeforeUndo":"onAfterUndo",
|
"onBeforeRedo": "onAfterRedo"
|
};
|
for(var i in noTrack){
|
gantt.attachEvent(i, function(){
|
monitor.startIgnore();
|
return true;
|
});
|
gantt.attachEvent(noTrack[i], function(){
|
monitor.stopIgnore();
|
return true;
|
});
|
}
|
|
var batchActions = [
|
"onTaskDragStart",
|
"onAfterTaskUpdate",
|
"onAfterTaskDelete",
|
"onBeforeBatchUpdate"
|
];
|
|
for(var i = 0; i < batchActions.length; i++){
|
gantt.attachEvent(batchActions[i], function(){
|
monitor.startBatchAction();
|
return true;
|
});
|
}
|
function store(id){
|
monitor.setInitialTask(id);
|
gantt.eachTask(function(child){
|
monitor.setInitialTask(child.id);
|
}, id);
|
return true;
|
}
|
|
gantt.attachEvent("onBeforeTaskDrag", store);
|
gantt.attachEvent("onLightbox", store);
|
gantt.attachEvent("onBeforeTaskAutoSchedule", function(task){ store(task.id); return true;});
|
|
var deleteCacheCooldown = null;
|
|
function saveInitialAll(){
|
if(!deleteCacheCooldown){
|
deleteCacheCooldown = setTimeout(function(){
|
deleteCacheCooldown = null;
|
});
|
|
monitor.clearInitialTasks();
|
gantt.eachTask(function(task){
|
monitor.setInitialTask(task.id);
|
});
|
}
|
}
|
|
gantt.attachEvent("onBeforeTaskDelete", function(id){
|
store(id);
|
var nested = [];
|
|
// remember task indexes in case their being deleted in a loop, so they could be restored in the correct order
|
saveInitialAll();
|
|
gantt.eachTask(function(task){
|
nested.push(task.id);
|
}, id);
|
monitor.setNestedTasks(id, nested);
|
return true;
|
});
|
if(gantt.ext.inlineEditors){
|
gantt.ext.inlineEditors.attachEvent("onEditStart", function(state){
|
store(state.id);
|
});
|
}
|
|
gantt.attachEvent("onAfterTaskAdd", function (id, task) {
|
monitor.setInitialTask(id, true);
|
monitor.onTaskAdded(task);
|
});
|
gantt.attachEvent("onAfterTaskUpdate", function(id, task){
|
monitor.onTaskUpdated(task);
|
});
|
gantt.attachEvent("onAfterTaskDelete", function(id, task){
|
monitor.onTaskDeleted(task);
|
});
|
|
gantt.attachEvent("onAfterLinkAdd", function(id, task){
|
monitor.onLinkAdded(task);
|
});
|
gantt.attachEvent("onAfterLinkUpdate", function(id, task){
|
monitor.onLinkUpdated(task);
|
});
|
gantt.attachEvent("onAfterLinkDelete", function(id, task){
|
monitor.onLinkDeleted(task);
|
});
|
|
var datastore = gantt.getDatastore("task");
|
|
datastore.attachEvent("onBeforeItemMove", function(id, parent, tindex){
|
if (!monitor.isMoveEventsIgnored()) {
|
|
saveInitialAll();
|
}
|
return true;
|
});
|
|
|
datastore.attachEvent("onAfterItemMove", function(id, parent, tindex){
|
if (!monitor.isMoveEventsIgnored()) {
|
monitor.onTaskMoved(getMoveObjectByTaskId(id));
|
}
|
return true;
|
});
|
|
gantt.attachEvent("onRowDragStart", function(id, target, e) {
|
monitor.toggleIgnoreMoveEvents(true);
|
saveInitialAll();
|
return true;
|
});
|
|
gantt.attachEvent("onRowDragEnd", function(id, target) {
|
monitor.onTaskMoved(getMoveObjectByTaskId(id));
|
monitor.toggleIgnoreMoveEvents();
|
return true;
|
});
|
|
function getMoveObjectByTaskId(id) {
|
return gantt.copy(gantt.getTask(id));
|
}
|
|
function updTask(task, oldId, newId){
|
if(!task) return;
|
|
if(task.id == oldId){
|
task.id = newId;
|
}
|
|
if(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(link.source == oldTaskId){
|
link.source = newTaskId;
|
}
|
if(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) {
|
var undo = gantt._undo;
|
|
for (var i = 0; i < log.length; i++) {
|
var entry = log[i];
|
for (var j = 0; j < entry.commands.length; j++) {
|
if (entry.commands[j].entity == undo.command.entity.task) {
|
changeTaskCommandId(entry.commands[j], oldId, newId);
|
} else if (entry.commands[j].entity == undo.command.entity.link) {
|
changeLinkCommandId(entry.commands[j], oldId, newId);
|
}
|
}
|
}
|
}
|
|
function updateLinksIds(log, oldId, newId){
|
var undo = gantt._undo;
|
|
for (var i = 0; i < log.length; i++) {
|
var entry = log[i];
|
for (var j = 0; j < entry.commands.length; j++) {
|
var command = entry.commands[j];
|
if (command.entity == undo.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;
|
}
|
}
|
}
|
}
|
}
|
|
gantt.attachEvent("onTaskIdChange", function(oldId, newId){
|
var undo = gantt._undo;
|
updateTasksIds(undo._undoStack,oldId, newId);
|
updateTasksIds(undo._redoStack,oldId, newId);
|
});
|
gantt.attachEvent("onLinkIdChange", function(oldId, newId){
|
var undo = gantt._undo;
|
updateLinksIds(undo._undoStack,oldId, newId);
|
updateLinksIds(undo._redoStack,oldId, newId);
|
});
|
gantt.attachEvent("onGanttReady", function(){
|
gantt._undo.updateConfigs();
|
});
|
})();
|
|
|
/***/ })
|
|
/******/ });
|
});
|