api.js 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. (function(){
  2. var apiUrl = "https://export.dhtmlx.com/gantt";
  3. var templates = [
  4. "leftside_text",
  5. "rightside_text",
  6. "task_text",
  7. "progress_text",
  8. "task_class"
  9. ];
  10. function xdr(url, pack, cb){
  11. if (gantt.env.isIE){
  12. gantt.env.isIE = false;
  13. gantt.ajax.post(url, pack, cb);
  14. gantt.env.isIE = true;
  15. } else {
  16. gantt.ajax.post(url, pack, cb);
  17. }
  18. }
  19. function defaults(obj, std){
  20. for (var key in std)
  21. if (!obj[key])
  22. obj[key] = std[key];
  23. return obj;
  24. }
  25. //compatibility for new versions of gantt
  26. if(!gantt.ajax){
  27. if(window.dhtmlxAjax){
  28. gantt.ajax = window.dhtmlxAjax;
  29. }else if(window.dhx4){
  30. gantt.ajax = window.dhx4.ajax;
  31. }
  32. }
  33. function mark_columns(base){
  34. var columns = base.config.columns;
  35. if (columns)
  36. for (var i = 0; i < columns.length; i++) {
  37. if (columns[i].template)
  38. columns[i].$template = true;
  39. }
  40. }
  41. function add_export_methods(gantt){
  42. var color_box = null;
  43. var color_hash = {};
  44. function get_styles(css){
  45. if (!color_box){
  46. var color_box = document.createElement("DIV");
  47. color_box.style.cssText = "position:absolute; display:none;";
  48. document.body.appendChild(color_box);
  49. }
  50. if (color_hash[css])
  51. return color_hash[css];
  52. color_box.className = css;
  53. return (color_hash[css] = get_color(color_box, "color")+";"+get_color(color_box, "backgroundColor"));
  54. }
  55. gantt._getWorktimeSettings = function() {
  56. var defaultWorkTimes = {
  57. hours : [0, 24],
  58. dates : {0:true, 1:true, 2:true, 3:true, 4:true, 5:true, 6:true}
  59. };
  60. var time;
  61. if(!gantt.config.work_time){
  62. time = defaultWorkTimes;
  63. }else{
  64. var wTime = gantt._working_time_helper;
  65. if (wTime && wTime.get_calendar) {
  66. time = wTime.get_calendar();
  67. } else if (wTime) {
  68. time = {
  69. hours : wTime.hours,
  70. dates : wTime.dates
  71. };
  72. } else if (gantt.config.worktimes && gantt.config.worktimes.global) {
  73. time = {
  74. hours : gantt.config.worktimes.global.hours,
  75. dates : gantt.config.worktimes.global.dates
  76. };
  77. } else {
  78. time = defaultWorkTimes;
  79. };
  80. }
  81. return time;
  82. };
  83. gantt.exportToPDF = function(config){
  84. if (config && config.raw){
  85. config = defaults(config, {
  86. name:"gantt.pdf", data:this._serialize_html()
  87. });
  88. } else {
  89. config = defaults((config || {}), {
  90. name:"gantt.pdf",
  91. data:this._serialize_all(),
  92. config:this.config
  93. });
  94. fix_columns(gantt, config.config.columns);
  95. }
  96. config.version = this.version;
  97. this._send_to_export(config, "pdf");
  98. };
  99. gantt.exportToPNG = function(config){
  100. if (config && config.raw){
  101. config = defaults(config, {
  102. name:"gantt.png", data:this._serialize_html()
  103. });
  104. } else {
  105. config = defaults((config || {}), {
  106. name:"gantt.png",
  107. data:this._serialize_all(),
  108. config:this.config
  109. });
  110. fix_columns(gantt, config.config.columns);
  111. }
  112. config.version = this.version;
  113. this._send_to_export(config, "png");
  114. };
  115. gantt.exportToICal = function(config){
  116. config = defaults((config || {}), {
  117. name:"gantt.ical",
  118. data:this._serialize_plain().data,
  119. version:this.version
  120. });
  121. this._send_to_export(config, "ical");
  122. };
  123. function eachTaskTimed(start, end){
  124. return function(code, parent, master){
  125. parent = parent || this.config.root_id;
  126. master = master || this;
  127. var branch = this.getChildren(parent);
  128. if (branch)
  129. for (var i=0; i<branch.length; i++){
  130. var item = this._pull[branch[i]];
  131. if ((!start || item.end_date > start) && (!end || item.start_date < end))
  132. code.call(master, item);
  133. if (this.hasChild(item.id))
  134. this.eachTask(code, item.id, master);
  135. }
  136. };
  137. }
  138. gantt.exportToExcel = function(config){
  139. config = config || {};
  140. var tasks, dates;
  141. var state, scroll;
  142. if (config.start || config.end){
  143. state = this.getState();
  144. dates = [ this.config.start_date, this.config.end_date ];
  145. scroll = this.getScrollState();
  146. var convert = this.date.str_to_date(this.config.date_format);
  147. tasks = this.eachTask;
  148. if (config.start)
  149. this.config.start_date = convert(config.start);
  150. if (config.end)
  151. this.config.end_date = convert(config.end);
  152. this.render();
  153. this.eachTask = eachTaskTimed(this.config.start_date, this.config.end_date);
  154. }
  155. this._no_progress_colors =config.visual === "base-colors";
  156. config = defaults(config, {
  157. name:"gantt.xlsx",
  158. title:"Tasks",
  159. data:this._serialize_table(config).data,
  160. columns:this._serialize_columns({ rawDates: true }),
  161. version:this.version
  162. });
  163. if (config.visual)
  164. config.scales = this._serialize_scales(config);
  165. this._send_to_export(config, "excel");
  166. if (config.start || config.end){
  167. this.config.start_date = state.min_date;
  168. this.config.end_date = state.max_date;
  169. this.eachTask = tasks;
  170. this.render();
  171. this.scrollTo(scroll.x, scroll.y);
  172. this.config.start_date = dates[0];
  173. this.config.end_date = dates[1];
  174. }
  175. };
  176. gantt.exportToJSON = function(config){
  177. config = defaults((config || {}), {
  178. name:"gantt.json",
  179. data:this._serialize_all(),
  180. config: this.config,
  181. columns:this._serialize_columns(),
  182. worktime : gantt._getWorktimeSettings(),
  183. version:this.version
  184. });
  185. this._send_to_export(config, "json");
  186. };
  187. function sendImportAjax(config){
  188. var url = config.server || apiUrl;
  189. var store = config.store || 0;
  190. var formData = config.data;
  191. var callback = config.callback;
  192. formData.append("type", "excel-parse");
  193. formData.append("data", JSON.stringify({
  194. sheet: config.sheet || 0
  195. }));
  196. if(store)
  197. formData.append("store", store);
  198. var xhr = new XMLHttpRequest();
  199. xhr.onreadystatechange = function (e) {
  200. if(xhr.readyState == 4 && xhr.status == 0){// network error
  201. if(callback){
  202. callback(null);
  203. }
  204. }
  205. };
  206. xhr.onload = function() {
  207. var fail = xhr.status > 400;
  208. var info = null;
  209. if (!fail){
  210. try{
  211. info = JSON.parse(xhr.responseText);
  212. }catch(e){}
  213. }
  214. if(callback){
  215. callback(info);
  216. }
  217. };
  218. xhr.open('POST', url, true);
  219. xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  220. xhr.send(formData);
  221. }
  222. gantt.importFromExcel = function(config){
  223. var formData = config.data;
  224. if(formData instanceof FormData){
  225. }else if(formData instanceof File){
  226. var data = new FormData();
  227. data.append("file", formData);
  228. config.data = data;
  229. }
  230. sendImportAjax(config);
  231. };
  232. gantt._msp_config = function(config){
  233. if (config.project)
  234. for (var i in config.project){
  235. if (!config._custom_data)
  236. config._custom_data = {};
  237. config._custom_data[i] = config.project[i](this.config);
  238. }
  239. if (config.tasks)
  240. for (var j = 0; j < config.data.length; j++){
  241. var el = this.getTask(config.data[j].id);
  242. if (!el._custom_data)
  243. el._custom_data = {};
  244. for (var i in config.tasks)
  245. el._custom_data[i] = config.tasks[i](el, this.config);
  246. }
  247. delete config.project;
  248. delete config.tasks;
  249. config.time = gantt._getWorktimeSettings();
  250. var p_dates = this.getSubtaskDates();
  251. var format = this.date.date_to_str("%d-%m-%Y %H:%i:%s");
  252. config.start_end = {
  253. start_date: format(p_dates.start_date),
  254. end_date: format(p_dates.end_date)
  255. };
  256. };
  257. gantt._msp_data = function(){
  258. var old_xml_format = this.templates.xml_format;
  259. var old_format_date = this.templates.format_date;
  260. this.templates.xml_format = this.date.date_to_str("%d-%m-%Y %H:%i:%s");
  261. this.templates.format_date = this.date.date_to_str("%d-%m-%Y %H:%i:%s");
  262. var data = this._serialize_all();
  263. this.templates.xml_format = old_xml_format;
  264. this.templates.format_date = old_format_date;
  265. return data;
  266. };
  267. gantt._ajax_to_export = function(data, type, callback){
  268. delete data.callback;
  269. var url = data.server || apiUrl;
  270. var pack = "type="+type+"&store=1&data="+encodeURIComponent(JSON.stringify(data));
  271. var cb = function(loader){
  272. var xdoc = loader.xmlDoc || loader;
  273. var fail = xdoc.status > 400;
  274. var info = null;
  275. if (!fail){
  276. try{
  277. info = JSON.parse(xdoc.responseText);
  278. }catch(e){}
  279. }
  280. callback(info);
  281. };
  282. xdr(url, pack, cb);
  283. };
  284. gantt._send_to_export = function(data, type){
  285. var convert = this.date.date_to_str(this.config.date_format || this.config.xml_date);
  286. if (data.config){
  287. data.config = this.copy(data.config);
  288. mark_columns(data, type);
  289. if(data.config.start_date && data.config.end_date){
  290. if(data.config.start_date instanceof Date){
  291. data.config.start_date = convert(data.config.start_date)
  292. }
  293. if(data.config.end_date instanceof Date){
  294. data.config.end_date = convert(data.config.end_date)
  295. }
  296. }
  297. }
  298. if (data.callback)
  299. return gantt._ajax_to_export(data, type, data.callback);
  300. var form = this._create_hidden_form();
  301. form.firstChild.action = data.server || apiUrl;
  302. form.firstChild.childNodes[0].value = JSON.stringify(data);
  303. form.firstChild.childNodes[1].value = type;
  304. form.firstChild.submit();
  305. };
  306. gantt._create_hidden_form = function(){
  307. if (!this._hidden_export_form){
  308. var t = this._hidden_export_form = document.createElement("div");
  309. t.style.display = "none";
  310. t.innerHTML = "<form method='POST' target='_blank'><textarea name='data' style='width:0px; height:0px;' readonly='true'></textarea><input type='hidden' name='type' value=''></form>";
  311. document.body.appendChild(t);
  312. }
  313. return this._hidden_export_form;
  314. };
  315. //patch broken json serialization in gantt 2.1
  316. var original = gantt.json._copyObject;
  317. function copy_object_base(obj){
  318. var copy = {};
  319. for (var key in obj){
  320. if (key.charAt(0) == "$")
  321. continue;
  322. copy[key] = obj[key];
  323. }
  324. var formatDate = gantt.templates.xml_format || gantt.templates.format_date;
  325. copy.start_date = formatDate(copy.start_date);
  326. if (copy.end_date)
  327. copy.end_date = formatDate(copy.end_date);
  328. return copy;
  329. }
  330. function copy_object_plain(obj){
  331. var text = gantt.templates.task_text(obj.start_date, obj.end_date, obj);
  332. var copy = copy_object_base(obj);
  333. copy.text = text || copy.text;
  334. return copy;
  335. }
  336. function get_color(node, style){
  337. var value = node.currentStyle ? node.currentStyle[style] : getComputedStyle(node, null)[style];
  338. var rgb = value.replace(/\s/g,'').match(/^rgba?\((\d+),(\d+),(\d+)/i);
  339. return ((rgb && rgb.length === 4) ?
  340. ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
  341. ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
  342. ("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : value).replace("#","");
  343. }
  344. // Excel interprets UTC time as local time in every timezone, send local time instead of actual UTC time.
  345. // https://github.com/SheetJS/js-xlsx/issues/126#issuecomment-60531614
  346. var toISOstring = gantt.date.date_to_str("%Y-%m-%dT%H:%i:%s.000Z");
  347. // excel serialization
  348. function copy_object_table(obj){
  349. var copy = copy_object_columns(obj, copy_object_plain(obj));
  350. if (copy.start_date)
  351. copy.start_date = toISOstring(obj.start_date);
  352. if (copy.end_date)
  353. copy.end_date = toISOstring(obj.end_date);
  354. // private gantt._day_index_by_date was replaced by public gantt.columnIndexByDate in gantt 5.0
  355. var getDayIndex = gantt._day_index_by_date ? gantt._day_index_by_date : gantt.columnIndexByDate;
  356. copy.$start = getDayIndex.call(gantt, obj.start_date);
  357. copy.$end = getDayIndex.call(gantt, obj.end_date);
  358. copy.$level = obj.$level;
  359. copy.$type = obj.$rendered_type;
  360. var tmps = gantt.templates;
  361. copy.$text = tmps.task_text(obj.start, obj.end_date, obj);
  362. copy.$left = tmps.leftside_text ? tmps.leftside_text(obj.start, obj.end_date, obj) : "";
  363. copy.$right = tmps.rightside_text ? tmps.rightside_text(obj.start, obj.end_date, obj) : "";
  364. return copy;
  365. }
  366. function copy_object_colors(obj){
  367. var copy = copy_object_table(obj);
  368. var node = gantt.getTaskNode(obj.id);
  369. if (node && node.firstChild){
  370. var color = get_color((gantt._no_progress_colors ? node : node.firstChild), "backgroundColor");
  371. if (color == "363636")
  372. color = get_color(node, "backgroundColor");
  373. copy.$color = color;
  374. } else if (obj.color)
  375. copy.$color = obj.color;
  376. return copy;
  377. }
  378. function copy_object_columns(obj, copy){
  379. for(var i=0; i<gantt.config.columns.length; i++){
  380. var ct = gantt.config.columns[i].template;
  381. if (ct) {
  382. var val = ct(obj);
  383. if (val instanceof Date)
  384. val = gantt.templates.date_grid(val, obj);
  385. copy["_"+i] = val;
  386. }
  387. }
  388. return copy;
  389. }
  390. function copy_object_all(obj){
  391. var copy = copy_object_base(obj);
  392. //serialize all text templates
  393. for (var i = 0; i < templates.length; i++){
  394. var template = gantt.templates[templates[i]];
  395. if (template)
  396. copy["$"+i] = template(obj.start_date, obj.end_date, obj);
  397. }
  398. copy_object_columns(obj, copy);
  399. copy.open = obj.$open;
  400. return copy;
  401. }
  402. function fix_columns(gantt, columns){
  403. for (var i = 0; i < columns.length; i++) {
  404. columns[i].label = columns[i].label || gantt.locale.labels["column_"+columns[i].name];
  405. if (typeof columns[i].width == "string") columns[i].width = columns[i].width*1;
  406. }
  407. }
  408. gantt._serialize_html = function(){
  409. var smartScales = gantt.config.smart_scales;
  410. var smartRendering = gantt.config.smart_rendering;
  411. if(smartScales || smartRendering){
  412. gantt.config.smart_rendering = false;
  413. gantt.config.smart_scales = false;
  414. gantt.render();
  415. }
  416. var html = this.$container.parentNode.innerHTML;
  417. if(smartScales || smartRendering){
  418. gantt.config.smart_scales = smartScales;
  419. gantt.config.smart_rendering = smartRendering;
  420. gantt.render();
  421. }
  422. return html;
  423. };
  424. gantt._serialize_all = function(){
  425. gantt.json._copyObject = copy_object_all;
  426. var data = export_serialize();
  427. gantt.json._copyObject = original;
  428. return data;
  429. };
  430. gantt._serialize_plain = function(){
  431. var oldXmlFormat = gantt.templates.xml_format;
  432. var oldFormatDate = gantt.templates.format_date;
  433. gantt.templates.xml_format = gantt.date.date_to_str("%Y%m%dT%H%i%s", true);
  434. gantt.templates.format_date = gantt.date.date_to_str("%Y%m%dT%H%i%s", true);
  435. gantt.json._copyObject = copy_object_plain;
  436. var data = export_serialize();
  437. gantt.templates.xml_format = oldXmlFormat;
  438. gantt.templates.format_date = oldFormatDate;
  439. gantt.json._copyObject = original;
  440. delete data.links;
  441. return data;
  442. };
  443. function get_raw() {
  444. // support Gantt < 5.0
  445. if (gantt._scale_helpers) {
  446. var scales = gantt._get_scales(),
  447. min_width = gantt.config.min_column_width,
  448. autosize_min_width = gantt._get_resize_options().x ? Math.max(gantt.config.autosize_min_width, 0) : config.$task.offsetWidth,
  449. height = config.config.scale_height - 1;
  450. return gantt._scale_helpers.prepareConfigs(scales, min_width, autosize_min_width, height);
  451. } else { // Gantt >= 5.0
  452. var timeline = gantt.$ui.getView("timeline");
  453. if (timeline) {
  454. var availWidth = timeline.$config.width;
  455. if (gantt.config.autosize == "x" || gantt.config.autosize == "xy") {
  456. availWidth = Math.max(gantt.config.autosize_min_width, 0);
  457. }
  458. var state = gantt.getState(),
  459. scales = timeline._getScales(),
  460. min_width = gantt.config.min_column_width,
  461. height = gantt.config.scale_height-1,
  462. rtl = gantt.config.rtl;
  463. return timeline.$scaleHelper.prepareConfigs(scales, min_width, availWidth, height, state.min_date, state.max_date, rtl);
  464. }
  465. }
  466. }
  467. gantt._serialize_table = function(config){
  468. gantt.json._copyObject = config.visual ? copy_object_colors : copy_object_table;
  469. var data = export_serialize();
  470. gantt.json._copyObject = original;
  471. delete data.links;
  472. if (config.cellColors){
  473. var css = this.templates.timeline_cell_class || this.templates.task_cell_class;
  474. if (css){
  475. var raw = get_raw();
  476. var steps = raw[0].trace_x;
  477. for (var i=1; i<raw.length; i++)
  478. if (raw[i].trace_x.length > steps.length)
  479. steps = raw[i].trace_x;
  480. for (var i=0; i<data.data.length; i++){
  481. data.data[i].styles = [];
  482. var task = this.getTask(data.data[i].id);
  483. for (var j = 0; j < steps.length; j++) {
  484. var date = steps[j];
  485. var cell_css = css(task, date);
  486. if (cell_css)
  487. data.data[i].styles.push({ index: j, styles: get_styles(cell_css) });
  488. }
  489. }
  490. }
  491. }
  492. return data;
  493. };
  494. gantt._serialize_scales = function(config){
  495. var scales = [];
  496. var raw = get_raw();
  497. var min = Infinity;
  498. var max = 0;
  499. for (var i=0; i<raw.length; i++) min = Math.min(min, raw[i].col_width);
  500. for (var i=0; i<raw.length; i++){
  501. var start = 0;
  502. var end = 0;
  503. var row = [];
  504. scales.push(row);
  505. var step = raw[i];
  506. max = Math.max(max, step.trace_x.length);
  507. var template = step.format || step.template || (step.date ? gantt.date.date_to_str(step.date) : gantt.config.date_scale);
  508. for (var j = 0; j < step.trace_x.length; j++) {
  509. var date = step.trace_x[j];
  510. end = start + Math.round(step.width[j]/min);
  511. var scale_cell = { text: template(date), start: start, end: end };
  512. if (config.cellColors){
  513. var css = step.css || this.templates.scale_cell_class;
  514. if (css){
  515. var scale_css = css(date);
  516. if (scale_css)
  517. scale_cell.styles=get_styles(scale_css);
  518. }
  519. }
  520. row.push(scale_cell);
  521. start = end;
  522. }
  523. }
  524. return { width:max, height:scales.length, data:scales };
  525. };
  526. gantt._serialize_columns = function(config){
  527. gantt.exportMode = true;
  528. var columns = [];
  529. var cols = gantt.config.columns;
  530. var ccount = 0;
  531. for (var i = 0; i < cols.length; i++){
  532. if (cols[i].name == "add" || cols[i].name == "buttons") continue;
  533. columns[ccount] = {
  534. id: ((cols[i].template) ? ("_"+i) : cols[i].name),
  535. header: cols[i].label || gantt.locale.labels["column_"+cols[i].name],
  536. width: (cols[i].width ? Math.floor(cols[i].width/4) : "")
  537. };
  538. if (cols[i].name == "duration")
  539. columns[ccount].type = "number";
  540. if (cols[i].name == "start_date" || cols[i].name == "end_date"){
  541. columns[ccount].type = "date";
  542. if (config && config.rawDates)
  543. columns[ccount].id = cols[i].name;
  544. }
  545. ccount++;
  546. }
  547. gantt.exportMode = false;
  548. return columns;
  549. };
  550. function export_serialize(){
  551. gantt.exportMode = true;
  552. var data = gantt.serialize();
  553. gantt.exportMode = false;
  554. return data;
  555. }
  556. }
  557. add_export_methods(gantt);
  558. if (window.Gantt && Gantt.plugin)
  559. Gantt.plugin(add_export_methods);
  560. })();
  561. (function () {
  562. var apiUrl = "https://export.dhtmlx.com/gantt";
  563. function set_level(data) {
  564. for (var i = 0; i < data.length; i++) {
  565. if (data[i].parent == 0) {
  566. data[i]._lvl = 1;
  567. }
  568. for (var j = i + 1; j < data.length; j++) {
  569. if (data[i].id == data[j].parent) {
  570. data[j]._lvl = data[i]._lvl + 1;
  571. }
  572. }
  573. }
  574. }
  575. function clear_level(data) {
  576. for (var i = 0; i < data.length; i++) {
  577. delete data[i]._lvl
  578. }
  579. }
  580. function clear_rec_links(data) {
  581. set_level(data.data);
  582. var tasks = {};
  583. for (var i = 0; i < data.data.length; i++) {
  584. tasks[data.data[i].id] = data.data[i];
  585. }
  586. var links = {};
  587. for (i = 0; i < data.links.length; i++) {
  588. var link = data.links[i];
  589. if(gantt.isTaskExists(link.source) && gantt.isTaskExists(link.target)){
  590. links[link.id] = link;
  591. }
  592. }
  593. for (i in links) {
  594. make_links_same_level(links[i], tasks);
  595. }
  596. var skippedLinks = {};
  597. for (i in tasks) {
  598. clear_circ_dependencies(tasks[i], links, tasks, {}, skippedLinks, null);
  599. }
  600. for (i in links) {
  601. clear_links_same_level(links, tasks);
  602. }
  603. for (i = 0; i < data.links.length; i++) {
  604. if (!links[data.links[i].id]) {
  605. data.links.splice(i, 1);
  606. i--;
  607. }
  608. }
  609. clear_level(data.data);
  610. }
  611. function clear_circ_dependencies(task, links, tasks, usedTasks, skippedLinks, prevLink) {
  612. var sources = task.$_source;
  613. if (!sources) return;
  614. if (usedTasks[task.id]) {
  615. on_circ_dependency_find(prevLink, links, usedTasks, skippedLinks);
  616. }
  617. usedTasks[task.id] = true;
  618. var targets = {};
  619. for (var i = 0; i < sources.length; i++) {
  620. if (skippedLinks[sources[i]]) continue;
  621. var curLink = links[sources[i]];
  622. var targetTask = tasks[curLink._target];
  623. if (targets[targetTask.id]) { // two link from one task to another
  624. on_circ_dependency_find(curLink, links, usedTasks, skippedLinks);
  625. }
  626. targets[targetTask.id] = true;
  627. clear_circ_dependencies(targetTask, links, tasks, usedTasks, skippedLinks, curLink);
  628. }
  629. usedTasks[task.id] = false;
  630. }
  631. function on_circ_dependency_find(link, links, usedTasks, skippedLinks) {
  632. if (link) {
  633. if (gantt.callEvent("onExportCircularDependency", [link.id, link])) {
  634. delete links[link.id];
  635. }
  636. delete usedTasks[link._source];
  637. delete usedTasks[link._target];
  638. skippedLinks[link.id] = true;
  639. }
  640. }
  641. function make_links_same_level(link, tasks) {
  642. var task,
  643. targetLvl,
  644. linkT = {
  645. target: tasks[link.target],
  646. source: tasks[link.source]
  647. };
  648. if (linkT.target._lvl != linkT.source._lvl) {
  649. if (linkT.target._lvl < linkT.source._lvl) {
  650. task = "source";
  651. targetLvl = linkT.target._lvl
  652. }
  653. else {
  654. task = "target";
  655. targetLvl = linkT.source._lvl;
  656. }
  657. do {
  658. var parent = tasks[linkT[task].parent];
  659. if (!parent) break;
  660. linkT[task] = parent;
  661. } while (linkT[task]._lvl < targetLvl);
  662. var sourceParent = tasks[linkT.source.parent],
  663. targetParent = tasks[linkT.target.parent];
  664. while (sourceParent && targetParent && sourceParent.id != targetParent.id) {
  665. linkT.source = sourceParent;
  666. linkT.target = targetParent;
  667. sourceParent = tasks[linkT.source.parent];
  668. targetParent = tasks[linkT.target.parent];
  669. }
  670. }
  671. link._target = linkT.target.id;
  672. link._source = linkT.source.id;
  673. if (!linkT.target.$_target)
  674. linkT.target.$_target = [];
  675. linkT.target.$_target.push(link.id);
  676. if (!linkT.source.$_source)
  677. linkT.source.$_source = [];
  678. linkT.source.$_source.push(link.id);
  679. }
  680. function clear_links_same_level(links, tasks) {
  681. for (var link in links) {
  682. delete links[link]._target;
  683. delete links[link]._source;
  684. }
  685. for (var task in tasks) {
  686. delete tasks[task].$_source;
  687. delete tasks[task].$_target;
  688. }
  689. }
  690. function customProjectProperties(data, config){
  691. if (config && config.project) {
  692. for (var i in config.project) {
  693. if (!gantt.config.$custom_data)
  694. gantt.config.$custom_data = {};
  695. gantt.config.$custom_data[i] = typeof config.project[i] == "function" ? config.project[i](gantt.config) : config.project[i];
  696. }
  697. delete config.project;
  698. }
  699. }
  700. function customTaskProperties(data, config){
  701. if (config && config.tasks) {
  702. data.data.forEach(function (el) {
  703. for (var i in config.tasks) {
  704. if (!el.$custom_data)
  705. el.$custom_data = {};
  706. el.$custom_data[i] = typeof config.tasks[i] == "function" ? config.tasks[i](el, gantt.config) : config.tasks[i];
  707. }
  708. });
  709. delete config.tasks;
  710. }
  711. }
  712. function exportConfig(data, config){
  713. var p_name = config.name || 'gantt.xml';
  714. delete config.name;
  715. gantt.config.custom = config;
  716. var time = gantt._getWorktimeSettings();
  717. var p_dates = gantt.getSubtaskDates();
  718. if (p_dates.start_date && p_dates.end_date) {
  719. var formatDate = gantt.templates.xml_format || gantt.templates.format_date;
  720. gantt.config.start_end = {
  721. start_date: formatDate(p_dates.start_date),
  722. end_date: formatDate(p_dates.end_date)
  723. };
  724. }
  725. var manual = config.auto_scheduling === undefined ? false : !!config.auto_scheduling;
  726. var res = {
  727. callback: config.callback || null,
  728. config: gantt.config,
  729. data: data,
  730. manual: manual,
  731. name: p_name,
  732. worktime: time
  733. };
  734. for(var i in config) res[i] = config[i];
  735. return res;
  736. }
  737. function add_export_methods(gantt) {
  738. gantt._ms_export = {};
  739. gantt.exportToMSProject = function (config) {
  740. config = config || {};
  741. config.skip_circular_links = config.skip_circular_links === undefined ? true : !!config.skip_circular_links;
  742. var old_xml_format = this.templates.xml_format;
  743. var old_format_date = this.templates.format_date;
  744. this.templates.xml_format = this.date.date_to_str("%d-%m-%Y %H:%i:%s");
  745. this.templates.format_date = this.date.date_to_str("%d-%m-%Y %H:%i:%s");
  746. var data = this._serialize_all();
  747. customProjectProperties(data, config);
  748. customTaskProperties(data, config);
  749. if (config.skip_circular_links) {
  750. clear_rec_links(data);
  751. }
  752. config = exportConfig(data, config);
  753. this._send_to_export(config, config.type || "msproject");
  754. this.templates.xml_format = old_xml_format;
  755. this.templates.format_date = old_format_date;
  756. this.config.$custom_data = null;
  757. this.config.custom = null;
  758. };
  759. gantt.exportToPrimaveraP6 = function(config){
  760. config.type = "primaveraP6";
  761. return gantt.exportToMSProject(config);
  762. };
  763. function sendImportAjax(config){
  764. var url = config.server || apiUrl;
  765. var store = config.store || 0;
  766. var formData = config.data;
  767. var callback = config.callback;
  768. var settings = {};
  769. if(config.durationUnit) settings.durationUnit = config.durationUnit
  770. if(config.projectProperties) settings.projectProperties = config.projectProperties;
  771. if(config.taskProperties) settings.taskProperties = config.taskProperties;
  772. formData.append("type", config.type || "msproject-parse");
  773. formData.append("data", JSON.stringify(settings));
  774. if(store)
  775. formData.append("store", store);
  776. var xhr = new XMLHttpRequest();
  777. xhr.onreadystatechange = function (e) {
  778. if(xhr.readyState == 4 && xhr.status == 0){// network error
  779. if(callback){
  780. callback(null);
  781. }
  782. }
  783. };
  784. xhr.onload = function() {
  785. var fail = xhr.status > 400;
  786. var info = null;
  787. if (!fail){
  788. try{
  789. info = JSON.parse(xhr.responseText);
  790. }catch(e){}
  791. }
  792. if(callback){
  793. callback(info);
  794. }
  795. };
  796. xhr.open('POST', url, true);
  797. xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  798. xhr.send(formData);
  799. }
  800. gantt.importFromMSProject = function(config){
  801. var formData = config.data;
  802. if(formData instanceof FormData){
  803. }else if(formData instanceof File){
  804. var data = new FormData();
  805. data.append("file", formData);
  806. config.data = data;
  807. }
  808. sendImportAjax(config);
  809. };
  810. gantt.importFromPrimaveraP6 = function(config){
  811. config.type = "primaveraP6-parse";
  812. return gantt.importFromMSProject(config);
  813. };
  814. }
  815. add_export_methods(gantt);
  816. if (window.Gantt && Gantt.plugin)
  817. Gantt.plugin(add_export_methods);
  818. })();