@workiom/frappe-gantt 1.0.13 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- :root{--g-arrow-color: #1f2937;--g-arrow-critical-color: #ff7676;--g-bar-color: #fff;--g-bar-border: #fff;--g-tick-color-thick: #ededed;--g-tick-color: #f3f3f3;--g-actions-background: #f3f3f3;--g-border-color: #ebeff2;--g-text-muted: #7c7c7c;--g-text-light: #fff;--g-text-dark: #171717;--g-progress-color: #dbdbdb;--g-handle-color: #37352f;--g-weekend-label-color: #dcdce4;--g-expected-progress: #c4c4e9;--g-header-background: #fff;--g-row-color: #fdfdfd;--g-row-border-color: #c7c7c7;--g-today-highlight: #37352f;--g-popup-actions: #ebeff2;--g-weekend-highlight-color: #f7f7f7}.gantt-container{line-height:14.5px;position:relative;overflow:auto;font-size:12px;height:var(--gv-grid-height);width:100%;border-radius:8px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:#fff;box-shadow:0 10px 24px -3px #0003;padding:10px;border-radius:5px;width:max-content;z-index:1000}.gantt-container .popup-wrapper .title{margin-bottom:2px;color:var(--g-text-dark);font-size:.85rem;font-weight:650;line-height:15px}.gantt-container .popup-wrapper .subtitle{color:var(--g-text-dark);font-size:.8rem;margin-bottom:5px}.gantt-container .popup-wrapper .details{color:var(--g-text-muted);font-size:.7rem}.gantt-container .popup-wrapper .actions{margin-top:10px;margin-left:3px}.gantt-container .popup-wrapper .action-btn{border:none;padding:5px 8px;background-color:var(--g-popup-actions);border-right:1px solid var(--g-text-light)}.gantt-container .popup-wrapper .action-btn:hover{background-color:brightness(97%)}.gantt-container .popup-wrapper .action-btn:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px}.gantt-container .popup-wrapper .action-btn:last-child{border-right:none;border-top-right-radius:4px;border-bottom-right-radius:4px}.gantt-container .grid-header{height:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);background-color:var(--g-header-background);position:sticky;top:0;left:0;border-bottom:1px solid var(--g-row-border-color);z-index:1000}.gantt-container .lower-text,.gantt-container .upper-text{text-anchor:middle}.gantt-container .upper-header{height:var(--gv-upper-header-height)}.gantt-container .lower-header{height:var(--gv-lower-header-height)}.gantt-container .lower-text{font-size:12px;position:absolute;width:calc(var(--gv-column-width) * .8);height:calc(var(--gv-lower-header-height) * .8);margin:0 calc(var(--gv-column-width) * .1);align-content:center;text-align:center;color:var(--g-text-muted)}.gantt-container .upper-text{position:absolute;width:fit-content;font-weight:500;font-size:14px;color:var(--g-text-dark);height:calc(var(--gv-lower-header-height) * .66)}.gantt-container .current-upper{position:sticky;left:0!important;padding-left:17px;background:#fff}.gantt-container .side-header{position:sticky;top:0;right:0;float:right;z-index:1000;line-height:20px;font-weight:400;width:max-content;margin-left:auto;padding-right:10px;padding-top:10px;background:var(--g-header-background);display:flex}.gantt-container .side-header *{transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:var(--g-actions-background);border-radius:.5rem;border:none;padding:5px 8px;color:var(--g-text-dark);font-size:14px;letter-spacing:.02em;font-weight:420;box-sizing:content-box;margin-right:5px}.gantt-container .side-header *:last-child{margin-right:0}.gantt-container .side-header *:hover{filter:brightness(97.5%)}.gantt-container .side-header select{width:60px;padding-top:2px;padding-bottom:2px}.gantt-container .side-header select:focus{outline:none}.gantt-container .date-range-highlight{background-color:var(--g-progress-color);border-radius:12px;height:calc(var(--gv-lower-header-height) - 6px);top:calc(var(--gv-upper-header-height) + 5px);position:absolute}.gantt-container .current-highlight{position:absolute;background:var(--g-today-highlight);width:1px;z-index:999}.gantt-container .current-ball-highlight{position:absolute;background:var(--g-today-highlight);z-index:1001;border-radius:50%}.gantt-container .current-date-highlight{background:var(--g-today-highlight);color:var(--g-text-light);border-radius:5px}.gantt-container .holiday-label{position:absolute;top:0;left:0;opacity:0;z-index:1000;background:--g-weekend-label-color;border-radius:5px;padding:2px 5px}.gantt-container .holiday-label.show{opacity:100}.gantt-container .extras{position:sticky;left:0}.gantt-container .extras .adjust{position:absolute;left:8px;top:calc(var(--gv-grid-height) - 60px);background-color:#000000b3;color:#fff;border:none;padding:8px;border-radius:3px}.gantt-container .hide{display:none}.gantt{user-select:none;-webkit-user-select:none;position:absolute;left:0}.gantt .grid-background{fill:none}.gantt .grid-row{fill:var(--g-row-color)}.gantt .row-line{stroke:var(--g-border-color)}.gantt .tick{stroke:var(--g-tick-color);stroke-width:.4}.gantt .tick.thick{stroke:var(--g-tick-color-thick);stroke-width:.7}.gantt .arrow{fill:none;stroke:var(--g-arrow-color);stroke-width:1.5}.gantt .arrow-critical{stroke:var(--g-arrow-critical-color)}.gantt .bar-wrapper .bar{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:0;transition:stroke-width .3s ease}.gantt .bar-progress{fill:var(--g-progress-color);border-radius:4px}.gantt .bar-expected-progress{fill:var(--g-expected-progress)}.gantt .bar-invalid{fill:transparent;stroke:var(--g-bar-border);stroke-width:1;stroke-dasharray:5}:is(.gantt .bar-invalid)~.bar-label{fill:var(--g-text-light)}.gantt .bar-label{fill:var(--g-text-dark);dominant-baseline:central;font-family:Helvetica;font-size:13px;font-weight:400}.gantt .bar-label.big{fill:var(--g-text-dark);text-anchor:start}.gantt .handle{fill:var(--g-handle-color);opacity:0;transition:opacity .3s ease}.gantt .handle.active,.gantt .handle.visible{cursor:ew-resize;opacity:1}.gantt .handle.progress{fill:var(--g-text-muted)}.gantt .bar-wrapper{cursor:pointer}.gantt .bar-wrapper .bar{outline:1px solid var(--g-row-border-color);border-radius:3px}.gantt .bar-wrapper:hover .bar{transition:transform .3s ease}.gantt .bar-wrapper:hover .date-range-highlight{display:block}.gantt .add-task-icon{cursor:pointer;transition:opacity .2s ease}.gantt .add-task-icon .add-task-icon-bg{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:1;transition:all .2s ease}.gantt .add-task-icon .add-task-icon-plus{stroke:var(--g-text-dark);stroke-width:2;stroke-linecap:round;transition:stroke .2s ease}.gantt .add-task-icon.active .add-task-icon-bg,.gantt .add-task-icon:hover .add-task-icon-bg{fill:var(--g-progress-color);stroke:var(--g-progress-color)}.gantt .add-task-icon.active .add-task-icon-plus,.gantt .add-task-icon:hover .add-task-icon-plus{stroke:var(--g-text-light)}
1
+ :root{--g-arrow-color: #1f2937;--g-arrow-critical-color: #f5c044;--g-arrow-invalid-color: #ff7676;--g-bar-color: #fff;--g-bar-border: #fff;--g-tick-color-thick: #ededed;--g-tick-color: #f3f3f3;--g-actions-background: #f3f3f3;--g-border-color: #ebeff2;--g-text-muted: #7c7c7c;--g-text-light: #fff;--g-text-dark: #171717;--g-progress-color: #dbdbdb;--g-handle-color: transparent;--g-weekend-label-color: #dcdce4;--g-expected-progress: #c4c4e9;--g-header-background: #fff;--g-row-color: #fdfdfd;--g-row-border-color: #c7c7c7;--g-today-highlight: #37352f;--g-popup-actions: #ebeff2;--g-weekend-highlight-color: #f7f7f7}.gantt-container{line-height:14.5px;position:relative;overflow:auto;font-size:12px;height:var(--gv-grid-height);width:100%;border-radius:8px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:#fff;box-shadow:0 10px 24px -3px #0003;padding:10px;border-radius:5px;width:max-content;z-index:1000}.gantt-container .popup-wrapper .title{margin-bottom:2px;color:var(--g-text-dark);font-size:.85rem;font-weight:650;line-height:15px}.gantt-container .popup-wrapper .subtitle{color:var(--g-text-dark);font-size:.8rem;margin-bottom:5px}.gantt-container .popup-wrapper .details{color:var(--g-text-muted);font-size:.7rem}.gantt-container .popup-wrapper .actions{margin-top:10px;margin-left:3px}.gantt-container .popup-wrapper .action-btn{border:none;padding:5px 8px;background-color:var(--g-popup-actions);border-right:1px solid var(--g-text-light)}.gantt-container .popup-wrapper .action-btn:hover{background-color:brightness(97%)}.gantt-container .popup-wrapper .action-btn:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px}.gantt-container .popup-wrapper .action-btn:last-child{border-right:none;border-top-right-radius:4px;border-bottom-right-radius:4px}.gantt-container .grid-header{height:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);background-color:var(--g-header-background);position:sticky;top:0;left:0;border-bottom:1px solid var(--g-row-border-color);z-index:1000}.gantt-container .lower-text,.gantt-container .upper-text{text-anchor:middle}.gantt-container .upper-header{height:var(--gv-upper-header-height)}.gantt-container .lower-header{height:var(--gv-lower-header-height)}.gantt-container .lower-text{font-size:12px;position:absolute;width:calc(var(--gv-column-width) * .8);height:calc(var(--gv-lower-header-height) * .8);margin:0 calc(var(--gv-column-width) * .1);align-content:center;text-align:center;color:var(--g-text-muted)}.gantt-container .upper-text{position:absolute;width:fit-content;font-weight:500;font-size:14px;color:var(--g-text-dark);height:calc(var(--gv-lower-header-height) * .66)}.gantt-container .current-upper{position:sticky;left:0!important;padding-left:17px;background:#fff}.gantt-container .side-header{position:sticky;top:0;right:0;float:right;z-index:1000;line-height:20px;font-weight:400;width:max-content;margin-left:auto;padding-right:10px;padding-top:10px;background:var(--g-header-background);display:flex}.gantt-container .side-header *{transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:var(--g-actions-background);border-radius:.5rem;border:none;padding:5px 8px;color:var(--g-text-dark);font-size:14px;letter-spacing:.02em;font-weight:420;box-sizing:content-box;margin-right:5px}.gantt-container .side-header *:last-child{margin-right:0}.gantt-container .side-header *:hover{filter:brightness(97.5%)}.gantt-container .side-header select{width:60px;padding-top:2px;padding-bottom:2px}.gantt-container .side-header select:focus{outline:none}.gantt-container .date-range-highlight{background-color:var(--g-progress-color);border-radius:12px;height:calc(var(--gv-lower-header-height) - 6px);top:calc(var(--gv-upper-header-height) + 5px);position:absolute}.gantt-container .current-highlight{position:absolute;background:var(--g-today-highlight);width:1px;z-index:999}.gantt-container .current-ball-highlight{position:absolute;background:var(--g-today-highlight);z-index:1001;border-radius:50%}.gantt-container .current-date-highlight{background:var(--g-today-highlight);color:var(--g-text-light);border-radius:5px}.gantt-container .holiday-label{position:absolute;top:0;left:0;opacity:0;z-index:1000;background:--g-weekend-label-color;border-radius:5px;padding:2px 5px}.gantt-container .holiday-label.show{opacity:100}.gantt-container .extras{position:sticky;left:0}.gantt-container .extras .adjust{position:absolute;left:8px;top:calc(var(--gv-grid-height) - 60px);background-color:#000000b3;color:#fff;border:none;padding:8px;border-radius:3px}.gantt-container .hide{display:none}.gantt{user-select:none;-webkit-user-select:none;position:absolute;left:0}.gantt .grid-background{fill:none}.gantt .grid-row{fill:var(--g-row-color)}.gantt .row-line{stroke:var(--g-border-color)}.gantt .tick{stroke:var(--g-tick-color);stroke-width:.4}.gantt .tick.thick{stroke:var(--g-tick-color-thick);stroke-width:.7}.gantt .arrow{fill:none;stroke:var(--g-arrow-color);stroke-width:1.5}.gantt .arrow-critical{stroke:var(--g-arrow-critical-color)}.gantt .arrow-invalid{stroke:var(--g-arrow-invalid-color)}.gantt .bar-wrapper .bar{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:0;transition:stroke-width .3s ease}.gantt .bar-progress{fill:var(--g-progress-color);border-radius:4px}.gantt .bar-expected-progress{fill:var(--g-expected-progress)}.gantt .bar-invalid{fill:transparent;stroke:var(--g-bar-border);stroke-width:1;stroke-dasharray:5}:is(.gantt .bar-invalid)~.bar-label{fill:var(--g-text-light)}.gantt .bar-label{fill:var(--g-text-dark);dominant-baseline:central;font-family:Helvetica;font-size:13px;font-weight:400}.gantt .bar-label.big{fill:var(--g-text-dark);text-anchor:start}.gantt .handle{fill:var(--g-handle-color);opacity:0;transition:opacity .3s ease}.gantt .handle.active,.gantt .handle.visible{cursor:ew-resize;opacity:1}.gantt .handle.progress{fill:var(--g-text-muted)}.gantt .bar-wrapper{cursor:pointer}.gantt .bar-wrapper .bar{outline:1px solid var(--g-row-border-color);border-radius:3px}.gantt .bar-wrapper:hover .bar{transition:transform .3s ease}.gantt .bar-wrapper:hover .date-range-highlight{display:block}.gantt .add-task-icon{cursor:pointer;transition:opacity .2s ease}.gantt .add-task-icon .add-task-icon-bg{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:1;transition:all .2s ease}.gantt .add-task-icon .add-task-icon-plus{stroke:var(--g-text-dark);stroke-width:2;stroke-linecap:round;transition:stroke .2s ease}.gantt .add-task-icon.active .add-task-icon-bg,.gantt .add-task-icon:hover .add-task-icon-bg{fill:var(--g-progress-color);stroke:var(--g-progress-color)}.gantt .add-task-icon.active .add-task-icon-plus,.gantt .add-task-icon:hover .add-task-icon-plus{stroke:var(--g-text-light)}
@@ -32,7 +32,7 @@ const M = "year", D = "month", L = "day", T = "hour", Y = "minute", A = "second"
32
32
  to_string(r, t = !1) {
33
33
  if (!(r instanceof Date))
34
34
  throw new TypeError("Invalid argument type");
35
- const e = this.get_date_values(r).map((s, o) => (o === 1 && (s = s + 1), o === 6 ? v(s + "", 3, "0") : v(s + "", 2, "0"))), i = `${e[0]}-${e[1]}-${e[2]}`, n = `${e[3]}:${e[4]}:${e[5]}.${e[6]}`;
35
+ const e = this.get_date_values(r).map((s, o) => (o === 1 && (s = s + 1), o === 6 ? x(s + "", 3, "0") : x(s + "", 2, "0"))), i = `${e[0]}-${e[1]}-${e[2]}`, n = `${e[3]}:${e[4]}:${e[5]}.${e[6]}`;
36
36
  return i + (t ? " " + n : "");
37
37
  },
38
38
  format(r, t = "YYYY-MM-DD HH:mm:ss.SSS", e = "en") {
@@ -40,9 +40,9 @@ const M = "year", D = "month", L = "day", T = "hour", Y = "minute", A = "second"
40
40
  month: "long"
41
41
  }), n = new Intl.DateTimeFormat(e, {
42
42
  month: "short"
43
- }), s = i.format(r), o = s.charAt(0).toUpperCase() + s.slice(1), a = this.get_date_values(r).map((c) => v(c, 2, 0)), h = {
43
+ }), s = i.format(r), o = s.charAt(0).toUpperCase() + s.slice(1), a = this.get_date_values(r).map((c) => x(c, 2, 0)), h = {
44
44
  YYYY: a[0],
45
- MM: v(+a[1] + 1, 2, 0),
45
+ MM: x(+a[1] + 1, 2, 0),
46
46
  DD: a[2],
47
47
  HH: a[3],
48
48
  mm: a[4],
@@ -158,7 +158,7 @@ const M = "year", D = "month", L = "day", T = "hour", Y = "minute", A = "second"
158
158
  return r.getFullYear() % 4 ? 365 : 366;
159
159
  }
160
160
  };
161
- function v(r, t, e) {
161
+ function x(r, t, e) {
162
162
  return r = r + "", t = t >> 0, e = String(typeof e < "u" ? e : " "), r.length > t ? String(r) : (t = t - r.length, t > e.length && (e += e.repeat(t / e.length)), e.slice(0, t) + String(r));
163
163
  }
164
164
  function u(r, t) {
@@ -240,11 +240,28 @@ u.attr = (r, t, e) => {
240
240
  };
241
241
  class C {
242
242
  constructor(t, e, i) {
243
- this.gantt = t, this.from_task = e, this.to_task = i, this.is_critical = this.check_critical_path(), this.calculate_path(), this.draw();
243
+ this.gantt = t, this.from_task = e, this.to_task = i, this.is_critical = this.check_critical_path(), this.is_invalid = this.check_invalid_dependency(), this.calculate_path(), this.draw();
244
244
  }
245
245
  check_critical_path() {
246
246
  return this.gantt.options.critical_path ? this.from_task.task._is_critical === !0 && this.to_task.task._is_critical === !0 : !1;
247
247
  }
248
+ check_invalid_dependency() {
249
+ const t = this.to_task.task.dependencies_type || this.gantt.options.dependencies_type;
250
+ if (t === "fixed")
251
+ return this.to_task.$bar.getX() < this.from_task.$bar.getX();
252
+ const e = this.from_task.task, i = this.to_task.task;
253
+ switch (t) {
254
+ case "finish-to-start":
255
+ return i._start < e._end;
256
+ case "start-to-start":
257
+ return i._start < e._start;
258
+ case "finish-to-finish":
259
+ return i._end < e._end;
260
+ case "start-to-finish":
261
+ return i._end < e._start;
262
+ }
263
+ return !1;
264
+ }
248
265
  calculate_path() {
249
266
  let t = this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;
250
267
  const e = () => this.to_task.$bar.getX() < t + this.gantt.options.padding && t > this.from_task.$bar.getX() + this.gantt.options.padding;
@@ -286,15 +303,18 @@ class C {
286
303
  }
287
304
  }
288
305
  draw() {
289
- this.element = f("path", {
306
+ let t = "";
307
+ this.is_invalid ? t = "arrow-invalid" : this.is_critical && (t = "arrow-critical"), this.element = f("path", {
290
308
  d: this.path,
291
309
  "data-from": this.from_task.task.id,
292
310
  "data-to": this.to_task.task.id,
293
- class: this.is_critical ? "arrow-critical" : ""
311
+ class: t
294
312
  });
295
313
  }
296
314
  update() {
297
- this.calculate_path(), this.element.setAttribute("d", this.path);
315
+ this.calculate_path(), this.element.setAttribute("d", this.path), this.is_invalid = this.check_invalid_dependency();
316
+ let t = "";
317
+ this.is_invalid ? t = "arrow-invalid" : this.is_critical && (t = "arrow-critical"), this.element.setAttribute("class", t);
298
318
  }
299
319
  }
300
320
  class q {
@@ -389,6 +409,7 @@ class q {
389
409
  this.gantt.gantt_start,
390
410
  this.gantt.config.unit
391
411
  ) / this.gantt.config.step * this.gantt.config.column_width;
412
+ this.$date_highlight && this.$date_highlight.parentNode && this.$date_highlight.parentNode.removeChild(this.$date_highlight);
392
413
  let i = this.gantt.create_el({
393
414
  classes: `date-range-highlight hide highlight-${this.task.id}`,
394
415
  width: this.width,
@@ -497,13 +518,13 @@ class q {
497
518
  }
498
519
  draw_resize_handles() {
499
520
  if (this.invalid || this.gantt.options.readonly) return;
500
- const t = this.$bar, e = 3;
521
+ const t = this.$bar, e = 8;
501
522
  if (this.handles = [], this.gantt.options.readonly_dates || (this.handles.push(
502
523
  f("rect", {
503
- x: t.getEndX() - e / 2,
504
- y: t.getY() + this.height / 4,
524
+ x: t.getEndX() - e,
525
+ y: t.getY() + (this.height - this.height * 0.8) / 2,
505
526
  width: e,
506
- height: this.height / 2,
527
+ height: this.height * 0.8,
507
528
  rx: 2,
508
529
  ry: 2,
509
530
  class: "handle right",
@@ -511,10 +532,10 @@ class q {
511
532
  })
512
533
  ), this.handles.push(
513
534
  f("rect", {
514
- x: t.getX() - e / 2,
515
- y: t.getY() + this.height / 4,
535
+ x: t.getX() - e,
536
+ y: t.getY() + (this.height - this.height * 0.8) / 2,
516
537
  width: e,
517
- height: this.height / 2,
538
+ height: this.height * 0.8,
518
539
  rx: 2,
519
540
  ry: 2,
520
541
  class: "handle left",
@@ -617,12 +638,7 @@ class q {
617
638
  }
618
639
  update_bar_position({ x: t = null, width: e = null }) {
619
640
  const i = this.$bar;
620
- if (t) {
621
- if (!this.validate_dependency_constraints(t, e))
622
- return;
623
- this.update_attr(i, "x", t), this.x = t, this.$date_highlight.style.left = t + "px";
624
- }
625
- e > 0 && (this.update_attr(i, "width", e), this.$date_highlight.style.width = e + "px"), this.update_label_position(), this.update_handle_position(), this.update_add_icon_position(), this.date_changed(), this.compute_duration(), this.gantt.options.show_expected_progress && this.update_expected_progressbar_position(), this.update_progressbar_position(), this.update_arrow_position();
641
+ t && (this.update_attr(i, "x", t), this.x = t, this.$date_highlight.style.left = t + "px"), e > 0 && (this.update_attr(i, "width", e), this.$date_highlight.style.width = e + "px"), this.update_label_position(), this.update_handle_position(), this.update_add_icon_position(), this.date_changed(), this.compute_duration(), this.gantt.options.show_expected_progress && this.update_expected_progressbar_position(), this.update_progressbar_position(), this.update_arrow_position();
626
642
  }
627
643
  validate_dependency_constraints(t, e = null) {
628
644
  const i = this.task.dependencies_type || this.gantt.options.dependencies_type;
@@ -1054,7 +1070,7 @@ class j {
1054
1070
  let o = [];
1055
1071
  e.dependencies && (o = e.dependencies.split(",").map((a) => a.trim().replaceAll(" ", "_")).filter((a) => a)), e.dependencies = o;
1056
1072
  }
1057
- return e.id ? typeof e.id == "string" ? e.id = e.id.replaceAll(" ", "_") : e.id = `${e.id}` : e.id = B(e), e;
1073
+ return e.id ? typeof e.id == "string" ? e.id = e.id.replaceAll(" ", "_") : e.id = `${e.id}` : e.id = N(e), e;
1058
1074
  }).filter((e) => e), this.setup_dependencies();
1059
1075
  }
1060
1076
  setup_dependencies() {
@@ -1642,8 +1658,8 @@ class j {
1642
1658
  this.options.move_dependencies && w === "fixed" ? m = [
1643
1659
  o,
1644
1660
  ...this.get_all_dependent_tasks(o)
1645
- ] : m = [o], a = m.map((x) => this.get_bar(x)), this.bar_being_dragged = !1, d = e, a.forEach((x) => {
1646
- const b = x.$bar;
1661
+ ] : m = [o], a = m.map((v) => this.get_bar(v)), this.bar_being_dragged = !1, d = e, a.forEach((v) => {
1662
+ const b = v.$bar;
1647
1663
  b.ox = b.getX(), b.oy = b.getY(), b.owidth = b.getWidth(), b.finaldx = 0;
1648
1664
  });
1649
1665
  }), this.options.infinite_padding) {
@@ -1697,15 +1713,15 @@ class j {
1697
1713
  ), m = this.upperTexts.find(
1698
1714
  (y) => y.textContent === w
1699
1715
  ), m !== this.$current && (this.$current && this.$current.classList.remove("current-upper"), m.classList.add("current-upper"), this.$current = m), i = _.currentTarget.scrollLeft;
1700
- let [x, b, X] = this.get_start_end_positions();
1716
+ let [v, b, X] = this.get_start_end_positions();
1701
1717
  i > X + 100 ? (this.$adjust.innerHTML = "&larr;", this.$adjust.classList.remove("hide"), this.$adjust.onclick = () => {
1702
1718
  this.$container.scrollTo({
1703
1719
  left: b,
1704
1720
  behavior: "smooth"
1705
1721
  });
1706
- }) : i + _.currentTarget.offsetWidth < x - 100 ? (this.$adjust.innerHTML = "&rarr;", this.$adjust.classList.remove("hide"), this.$adjust.onclick = () => {
1722
+ }) : i + _.currentTarget.offsetWidth < v - 100 ? (this.$adjust.innerHTML = "&rarr;", this.$adjust.classList.remove("hide"), this.$adjust.onclick = () => {
1707
1723
  this.$container.scrollTo({
1708
- left: x,
1724
+ left: v,
1709
1725
  behavior: "smooth"
1710
1726
  });
1711
1727
  }) : this.$adjust.classList.add("hide"), p && (c = g.map((y) => this.get_bar(y)), this.options.auto_move_label && c.forEach((y) => {
@@ -1732,21 +1748,20 @@ class j {
1732
1748
  var _, c, g;
1733
1749
  t = !1, n = !1, s = !1, (g = (c = (_ = this.$container.querySelector(".visible")) == null ? void 0 : _.classList) == null ? void 0 : c.remove) == null || g.call(c, "visible");
1734
1750
  }), u.on(this.$svg, "mouseup", (_) => {
1751
+ const c = this.bar_being_dragged === !0;
1735
1752
  this.bar_being_dragged = null;
1736
- const c = [];
1753
+ const g = [];
1737
1754
  a.forEach((p) => {
1738
- p.$bar.finaldx && (p.date_changed(), p.compute_progress(), p.set_action_completed(), c.push({
1755
+ if (!p.$bar.finaldx) {
1756
+ c && p.set_action_completed();
1757
+ return;
1758
+ }
1759
+ p.date_changed(), p.compute_progress(), p.set_action_completed(), g.push({
1739
1760
  task: p.task,
1740
1761
  start: p.task._start,
1741
1762
  end: l.add(p.task._end, -1, "second")
1742
- }));
1743
- });
1744
- const g = this.get_bar(o);
1745
- if (g && g.$bar.finaldx) {
1746
- const p = this.update_dependent_tasks_by_type(g);
1747
- c.push(...p);
1748
- }
1749
- this.options.critical_path && a.some((p) => p.$bar.finaldx) && (this.calculate_critical_path(), this.update_arrow_critical_path()), c.length > 0 && c.forEach(({ task: p, start: w, end: m }) => {
1763
+ });
1764
+ }), this.options.critical_path && a.some((p) => p.$bar.finaldx) && (this.calculate_critical_path(), this.update_arrow_critical_path()), g.length > 0 && g.forEach(({ task: p, start: w, end: m }) => {
1750
1765
  this.trigger_event("after_date_change", [p, w, m]);
1751
1766
  });
1752
1767
  }), this.bind_bar_progress();
@@ -1913,7 +1928,7 @@ j.VIEW_MODE = {
1913
1928
  MONTH: $[5],
1914
1929
  YEAR: $[6]
1915
1930
  };
1916
- function B(r) {
1931
+ function N(r) {
1917
1932
  return r.name + "_" + Math.random().toString(36).slice(2, 12);
1918
1933
  }
1919
1934
  function k(r) {
@@ -1,4 +1,4 @@
1
- (function(x,v){typeof exports=="object"&&typeof module<"u"?module.exports=v():typeof define=="function"&&define.amd?define(v):(x=typeof globalThis<"u"?globalThis:x||self,x.Gantt=v())})(this,function(){"use strict";const x="year",v="month",L="day",T="hour",Y="minute",A="second",S="millisecond",l={parse_duration(r){const e=/([0-9]+)(y|m|d|h|min|s|ms)/gm.exec(r);if(e!==null){if(e[2]==="y")return{duration:parseInt(e[1]),scale:"year"};if(e[2]==="m")return{duration:parseInt(e[1]),scale:"month"};if(e[2]==="d")return{duration:parseInt(e[1]),scale:"day"};if(e[2]==="h")return{duration:parseInt(e[1]),scale:"hour"};if(e[2]==="min")return{duration:parseInt(e[1]),scale:"minute"};if(e[2]==="s")return{duration:parseInt(e[1]),scale:"second"};if(e[2]==="ms")return{duration:parseInt(e[1]),scale:"millisecond"}}},parse(r,t="-",e=/[.:]/){if(r instanceof Date)return r;if(typeof r=="string"){let i,n;const s=r.split(" ");i=s[0].split(t).map(a=>parseInt(a,10)),n=s[1]&&s[1].split(e),i[1]=i[1]?i[1]-1:0;let o=i;return n&&n.length&&(n.length===4&&(n[3]="0."+n[3],n[3]=parseFloat(n[3])*1e3),o=o.concat(n)),new Date(...o)}},to_string(r,t=!1){if(!(r instanceof Date))throw new TypeError("Invalid argument type");const e=this.get_date_values(r).map((s,o)=>(o===1&&(s=s+1),o===6?M(s+"",3,"0"):M(s+"",2,"0"))),i=`${e[0]}-${e[1]}-${e[2]}`,n=`${e[3]}:${e[4]}:${e[5]}.${e[6]}`;return i+(t?" "+n:"")},format(r,t="YYYY-MM-DD HH:mm:ss.SSS",e="en"){const i=new Intl.DateTimeFormat(e,{month:"long"}),n=new Intl.DateTimeFormat(e,{month:"short"}),s=i.format(r),o=s.charAt(0).toUpperCase()+s.slice(1),a=this.get_date_values(r).map(c=>M(c,2,0)),h={YYYY:a[0],MM:M(+a[1]+1,2,0),DD:a[2],HH:a[3],mm:a[4],ss:a[5],SSS:a[6],D:a[2],MMMM:o,MMM:n.format(r)};let d=t;const _=[];return Object.keys(h).sort((c,g)=>g.length-c.length).forEach(c=>{d.includes(c)&&(d=d.replaceAll(c,`$${_.length}`),_.push(h[c]))}),_.forEach((c,g)=>{d=d.replaceAll(`$${g}`,c)}),d},diff(r,t,e="day"){let i,n,s,o,a,h,d;i=r-t+(t.getTimezoneOffset()-r.getTimezoneOffset())*6e4,n=i/1e3,o=n/60,s=o/60,a=s/24;let _=r.getFullYear()-t.getFullYear(),c=r.getMonth()-t.getMonth();return c+=a%30/30,h=_*12+c,r.getDate()<t.getDate()&&h--,d=h/12,e.endsWith("s")||(e+="s"),Math.round({milliseconds:i,seconds:n,minutes:o,hours:s,days:a,months:h,years:d}[e]*100)/100},today(){const r=this.get_date_values(new Date).slice(0,3);return new Date(...r)},now(){return new Date},add(r,t,e){t=parseInt(t,10);const i=[r.getFullYear()+(e===x?t:0),r.getMonth()+(e===v?t:0),r.getDate()+(e===L?t:0),r.getHours()+(e===T?t:0),r.getMinutes()+(e===Y?t:0),r.getSeconds()+(e===A?t:0),r.getMilliseconds()+(e===S?t:0)];return new Date(...i)},start_of(r,t){const e={[x]:6,[v]:5,[L]:4,[T]:3,[Y]:2,[A]:1,[S]:0};function i(s){const o=e[t];return e[s]<=o}const n=[r.getFullYear(),i(x)?0:r.getMonth(),i(v)?1:r.getDate(),i(L)?0:r.getHours(),i(T)?0:r.getMinutes(),i(Y)?0:r.getSeconds(),i(A)?0:r.getMilliseconds()];return new Date(...n)},clone(r){return new Date(...this.get_date_values(r))},get_date_values(r){return[r.getFullYear(),r.getMonth(),r.getDate(),r.getHours(),r.getMinutes(),r.getSeconds(),r.getMilliseconds()]},convert_scales(r,t){const e={millisecond:11574074074074074e-24,second:11574074074074073e-21,minute:.0006944444444444445,hour:.041666666666666664,day:1,month:30,year:365},{duration:i,scale:n}=this.parse_duration(r);return i*e[n]/e[t]},get_days_in_month(r){const t=[31,28,31,30,31,30,31,31,30,31,30,31],e=r.getMonth();if(e!==1)return t[e];const i=r.getFullYear();return i%4===0&&i%100!=0||i%400===0?29:28},get_days_in_year(r){return r.getFullYear()%4?365:366}};function M(r,t,e){return r=r+"",t=t>>0,e=String(typeof e<"u"?e:" "),r.length>t?String(r):(t=t-r.length,t>e.length&&(e+=e.repeat(t/e.length)),e.slice(0,t)+String(r))}function u(r,t){return typeof r=="string"?(t||document).querySelector(r):r||null}function f(r,t){const e=document.createElementNS("http://www.w3.org/2000/svg",r);for(let i in t)i==="append_to"?t.append_to.appendChild(e):i==="innerHTML"?e.innerHTML=t.innerHTML:i==="clipPath"?e.setAttribute("clip-path","url(#"+t[i]+")"):e.setAttribute(i,t[i]);return e}function E(r,t,e,i){const n=z(r,t,e,i);if(n===r){const s=document.createEvent("HTMLEvents");s.initEvent("click",!0,!0),s.eventName="click",n.dispatchEvent(s)}}function z(r,t,e,i,n="0.4s",s="0.1s"){const o=r.querySelector("animate");if(o)return u.attr(o,{attributeName:t,from:e,to:i,dur:n,begin:"click + "+s}),r;const a=f("animate",{attributeName:t,from:e,to:i,dur:n,begin:s,calcMode:"spline",values:e+";"+i,keyTimes:"0; 1",keySplines:W("ease-out")});return r.appendChild(a),r}function W(r){return{ease:".25 .1 .25 1",linear:"0 0 1 1","ease-in":".42 0 1 1","ease-out":"0 0 .58 1","ease-in-out":".42 0 .58 1"}[r]}u.on=(r,t,e,i)=>{i?u.delegate(r,t,e,i):(i=e,u.bind(r,t,i))},u.off=(r,t,e)=>{r.removeEventListener(t,e)},u.bind=(r,t,e)=>{t.split(/\s+/).forEach(function(i){r.addEventListener(i,e)})},u.delegate=(r,t,e,i)=>{r.addEventListener(t,function(n){const s=n.target.closest(e);s&&(n.delegatedTarget=s,i.call(this,n,s))})},u.closest=(r,t)=>t?t.matches(r)?t:u.closest(r,t.parentNode):null,u.attr=(r,t,e)=>{if(!e&&typeof t=="string")return r.getAttribute(t);if(typeof t=="object"){for(let i in t)u.attr(r,i,t[i]);return}r.setAttribute(t,e)};class C{constructor(t,e,i){this.gantt=t,this.from_task=e,this.to_task=i,this.is_critical=this.check_critical_path(),this.calculate_path(),this.draw()}check_critical_path(){return this.gantt.options.critical_path?this.from_task.task._is_critical===!0&&this.to_task.task._is_critical===!0:!1}calculate_path(){let t=this.from_task.$bar.getX()+this.from_task.$bar.getWidth()/2;const e=()=>this.to_task.$bar.getX()<t+this.gantt.options.padding&&t>this.from_task.$bar.getX()+this.gantt.options.padding;for(;e();)t-=10;t-=10;let i=this.gantt.config.header_height+this.gantt.options.bar_height+(this.gantt.options.padding+this.gantt.options.bar_height)*this.from_task.task._index+this.gantt.options.padding/2,n=this.to_task.$bar.getX()-13,s=this.gantt.config.header_height+this.gantt.options.bar_height/2+(this.gantt.options.padding+this.gantt.options.bar_height)*this.to_task.task._index+this.gantt.options.padding/2;const o=this.from_task.task._index>this.to_task.task._index;let a=this.gantt.options.arrow_curve;const h=o?1:0;let d=o?-a:a;if(this.to_task.$bar.getX()<=this.from_task.$bar.getX()+this.gantt.options.padding){let _=this.gantt.options.padding/2-a;_<0&&(_=0,a=this.gantt.options.padding/2,d=o?-a:a);const c=this.to_task.$bar.getY()+this.to_task.$bar.getHeight()/2-d,g=this.to_task.$bar.getX()-this.gantt.options.padding;this.path=`
1
+ (function(v,x){typeof exports=="object"&&typeof module<"u"?module.exports=x():typeof define=="function"&&define.amd?define(x):(v=typeof globalThis<"u"?globalThis:v||self,v.Gantt=x())})(this,function(){"use strict";const v="year",x="month",L="day",T="hour",Y="minute",A="second",S="millisecond",l={parse_duration(r){const e=/([0-9]+)(y|m|d|h|min|s|ms)/gm.exec(r);if(e!==null){if(e[2]==="y")return{duration:parseInt(e[1]),scale:"year"};if(e[2]==="m")return{duration:parseInt(e[1]),scale:"month"};if(e[2]==="d")return{duration:parseInt(e[1]),scale:"day"};if(e[2]==="h")return{duration:parseInt(e[1]),scale:"hour"};if(e[2]==="min")return{duration:parseInt(e[1]),scale:"minute"};if(e[2]==="s")return{duration:parseInt(e[1]),scale:"second"};if(e[2]==="ms")return{duration:parseInt(e[1]),scale:"millisecond"}}},parse(r,t="-",e=/[.:]/){if(r instanceof Date)return r;if(typeof r=="string"){let i,n;const s=r.split(" ");i=s[0].split(t).map(a=>parseInt(a,10)),n=s[1]&&s[1].split(e),i[1]=i[1]?i[1]-1:0;let o=i;return n&&n.length&&(n.length===4&&(n[3]="0."+n[3],n[3]=parseFloat(n[3])*1e3),o=o.concat(n)),new Date(...o)}},to_string(r,t=!1){if(!(r instanceof Date))throw new TypeError("Invalid argument type");const e=this.get_date_values(r).map((s,o)=>(o===1&&(s=s+1),o===6?M(s+"",3,"0"):M(s+"",2,"0"))),i=`${e[0]}-${e[1]}-${e[2]}`,n=`${e[3]}:${e[4]}:${e[5]}.${e[6]}`;return i+(t?" "+n:"")},format(r,t="YYYY-MM-DD HH:mm:ss.SSS",e="en"){const i=new Intl.DateTimeFormat(e,{month:"long"}),n=new Intl.DateTimeFormat(e,{month:"short"}),s=i.format(r),o=s.charAt(0).toUpperCase()+s.slice(1),a=this.get_date_values(r).map(c=>M(c,2,0)),h={YYYY:a[0],MM:M(+a[1]+1,2,0),DD:a[2],HH:a[3],mm:a[4],ss:a[5],SSS:a[6],D:a[2],MMMM:o,MMM:n.format(r)};let d=t;const _=[];return Object.keys(h).sort((c,g)=>g.length-c.length).forEach(c=>{d.includes(c)&&(d=d.replaceAll(c,`$${_.length}`),_.push(h[c]))}),_.forEach((c,g)=>{d=d.replaceAll(`$${g}`,c)}),d},diff(r,t,e="day"){let i,n,s,o,a,h,d;i=r-t+(t.getTimezoneOffset()-r.getTimezoneOffset())*6e4,n=i/1e3,o=n/60,s=o/60,a=s/24;let _=r.getFullYear()-t.getFullYear(),c=r.getMonth()-t.getMonth();return c+=a%30/30,h=_*12+c,r.getDate()<t.getDate()&&h--,d=h/12,e.endsWith("s")||(e+="s"),Math.round({milliseconds:i,seconds:n,minutes:o,hours:s,days:a,months:h,years:d}[e]*100)/100},today(){const r=this.get_date_values(new Date).slice(0,3);return new Date(...r)},now(){return new Date},add(r,t,e){t=parseInt(t,10);const i=[r.getFullYear()+(e===v?t:0),r.getMonth()+(e===x?t:0),r.getDate()+(e===L?t:0),r.getHours()+(e===T?t:0),r.getMinutes()+(e===Y?t:0),r.getSeconds()+(e===A?t:0),r.getMilliseconds()+(e===S?t:0)];return new Date(...i)},start_of(r,t){const e={[v]:6,[x]:5,[L]:4,[T]:3,[Y]:2,[A]:1,[S]:0};function i(s){const o=e[t];return e[s]<=o}const n=[r.getFullYear(),i(v)?0:r.getMonth(),i(x)?1:r.getDate(),i(L)?0:r.getHours(),i(T)?0:r.getMinutes(),i(Y)?0:r.getSeconds(),i(A)?0:r.getMilliseconds()];return new Date(...n)},clone(r){return new Date(...this.get_date_values(r))},get_date_values(r){return[r.getFullYear(),r.getMonth(),r.getDate(),r.getHours(),r.getMinutes(),r.getSeconds(),r.getMilliseconds()]},convert_scales(r,t){const e={millisecond:11574074074074074e-24,second:11574074074074073e-21,minute:.0006944444444444445,hour:.041666666666666664,day:1,month:30,year:365},{duration:i,scale:n}=this.parse_duration(r);return i*e[n]/e[t]},get_days_in_month(r){const t=[31,28,31,30,31,30,31,31,30,31,30,31],e=r.getMonth();if(e!==1)return t[e];const i=r.getFullYear();return i%4===0&&i%100!=0||i%400===0?29:28},get_days_in_year(r){return r.getFullYear()%4?365:366}};function M(r,t,e){return r=r+"",t=t>>0,e=String(typeof e<"u"?e:" "),r.length>t?String(r):(t=t-r.length,t>e.length&&(e+=e.repeat(t/e.length)),e.slice(0,t)+String(r))}function u(r,t){return typeof r=="string"?(t||document).querySelector(r):r||null}function f(r,t){const e=document.createElementNS("http://www.w3.org/2000/svg",r);for(let i in t)i==="append_to"?t.append_to.appendChild(e):i==="innerHTML"?e.innerHTML=t.innerHTML:i==="clipPath"?e.setAttribute("clip-path","url(#"+t[i]+")"):e.setAttribute(i,t[i]);return e}function E(r,t,e,i){const n=z(r,t,e,i);if(n===r){const s=document.createEvent("HTMLEvents");s.initEvent("click",!0,!0),s.eventName="click",n.dispatchEvent(s)}}function z(r,t,e,i,n="0.4s",s="0.1s"){const o=r.querySelector("animate");if(o)return u.attr(o,{attributeName:t,from:e,to:i,dur:n,begin:"click + "+s}),r;const a=f("animate",{attributeName:t,from:e,to:i,dur:n,begin:s,calcMode:"spline",values:e+";"+i,keyTimes:"0; 1",keySplines:W("ease-out")});return r.appendChild(a),r}function W(r){return{ease:".25 .1 .25 1",linear:"0 0 1 1","ease-in":".42 0 1 1","ease-out":"0 0 .58 1","ease-in-out":".42 0 .58 1"}[r]}u.on=(r,t,e,i)=>{i?u.delegate(r,t,e,i):(i=e,u.bind(r,t,i))},u.off=(r,t,e)=>{r.removeEventListener(t,e)},u.bind=(r,t,e)=>{t.split(/\s+/).forEach(function(i){r.addEventListener(i,e)})},u.delegate=(r,t,e,i)=>{r.addEventListener(t,function(n){const s=n.target.closest(e);s&&(n.delegatedTarget=s,i.call(this,n,s))})},u.closest=(r,t)=>t?t.matches(r)?t:u.closest(r,t.parentNode):null,u.attr=(r,t,e)=>{if(!e&&typeof t=="string")return r.getAttribute(t);if(typeof t=="object"){for(let i in t)u.attr(r,i,t[i]);return}r.setAttribute(t,e)};class C{constructor(t,e,i){this.gantt=t,this.from_task=e,this.to_task=i,this.is_critical=this.check_critical_path(),this.is_invalid=this.check_invalid_dependency(),this.calculate_path(),this.draw()}check_critical_path(){return this.gantt.options.critical_path?this.from_task.task._is_critical===!0&&this.to_task.task._is_critical===!0:!1}check_invalid_dependency(){const t=this.to_task.task.dependencies_type||this.gantt.options.dependencies_type;if(t==="fixed")return this.to_task.$bar.getX()<this.from_task.$bar.getX();const e=this.from_task.task,i=this.to_task.task;switch(t){case"finish-to-start":return i._start<e._end;case"start-to-start":return i._start<e._start;case"finish-to-finish":return i._end<e._end;case"start-to-finish":return i._end<e._start}return!1}calculate_path(){let t=this.from_task.$bar.getX()+this.from_task.$bar.getWidth()/2;const e=()=>this.to_task.$bar.getX()<t+this.gantt.options.padding&&t>this.from_task.$bar.getX()+this.gantt.options.padding;for(;e();)t-=10;t-=10;let i=this.gantt.config.header_height+this.gantt.options.bar_height+(this.gantt.options.padding+this.gantt.options.bar_height)*this.from_task.task._index+this.gantt.options.padding/2,n=this.to_task.$bar.getX()-13,s=this.gantt.config.header_height+this.gantt.options.bar_height/2+(this.gantt.options.padding+this.gantt.options.bar_height)*this.to_task.task._index+this.gantt.options.padding/2;const o=this.from_task.task._index>this.to_task.task._index;let a=this.gantt.options.arrow_curve;const h=o?1:0;let d=o?-a:a;if(this.to_task.$bar.getX()<=this.from_task.$bar.getX()+this.gantt.options.padding){let _=this.gantt.options.padding/2-a;_<0&&(_=0,a=this.gantt.options.padding/2,d=o?-a:a);const c=this.to_task.$bar.getY()+this.to_task.$bar.getHeight()/2-d,g=this.to_task.$bar.getX()-this.gantt.options.padding;this.path=`
2
2
  M ${t} ${i}
3
3
  v ${_}
4
4
  a ${a} ${a} 0 0 1 ${-a} ${a}
@@ -16,7 +16,7 @@
16
16
  L ${n} ${s}
17
17
  m -5 -5
18
18
  l 5 5
19
- l -5 5`}}draw(){this.element=f("path",{d:this.path,"data-from":this.from_task.task.id,"data-to":this.to_task.task.id,class:this.is_critical?"arrow-critical":""})}update(){this.calculate_path(),this.element.setAttribute("d",this.path)}}class q{constructor(t,e){this.set_defaults(t,e),this.prepare_wrappers(),this.prepare_helpers(),this.refresh()}refresh(){this.bar_group.innerHTML="",this.handle_group.innerHTML="",this.task.custom_class?this.group.classList.add(this.task.custom_class):this.group.classList=["bar-wrapper"],this.unbind(),this.prepare_values(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e,this.name=this.name||"",this.is_dragging=!1,this.is_hovering_bar=!1,this.is_hovering_icon=!1,this.add_icon_hide_timeout=null}prepare_wrappers(){this.group=f("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:""),"data-id":this.task.id}),this.bar_group=f("g",{class:"bar-group",append_to:this.group}),this.handle_group=f("g",{class:"handle-group",append_to:this.group})}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,(!this.task._start||!(this.task._start instanceof Date))&&(this.task._start=new Date(this.task.start)),(!this.task._end||!(this.task._end instanceof Date))&&(this.task._end=new Date(this.task.end)),this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.config.column_width*this.duration,(!this.task.progress||this.task.progress<0)&&(this.task.progress=0),this.task.progress>100&&(this.task.progress=100)}prepare_helpers(){SVGElement.prototype.getX=function(){return+this.getAttribute("x")},SVGElement.prototype.getY=function(){return+this.getAttribute("y")},SVGElement.prototype.getWidth=function(){return+this.getAttribute("width")},SVGElement.prototype.getHeight=function(){return+this.getAttribute("height")},SVGElement.prototype.getEndX=function(){return this.getX()+this.getWidth()}}prepare_expected_progress_values(){this.compute_expected_progress(),this.expected_progress_width=this.gantt.options.column_width*this.duration*(this.expected_progress/100)||0}draw(){this.draw_bar(),this.draw_progress_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_label(),this.draw_resize_handles(),this.task.thumbnail&&this.draw_thumbnail(),this.gantt.options.task_add_icon_position&&this.draw_add_task_icon()}draw_bar(){this.$bar=f("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar",append_to:this.bar_group}),this.task.color&&(this.$bar.style.fill=this.task.color),E(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=f("rect",{x:this.x,y:this.y,width:this.expected_progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-expected-progress",append_to:this.bar_group}),E(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.progress_width=this.calculate_progress_width();let t=this.corner_radius;/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(t=this.corner_radius+2),this.$bar_progress=f("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:t,ry:t,class:"bar-progress",append_to:this.bar_group}),this.task.color_progress&&(this.$bar_progress.style.fill=this.task.color_progress);const e=l.diff(this.task._start,this.gantt.gantt_start,this.gantt.config.unit)/this.gantt.config.step*this.gantt.config.column_width;let i=this.gantt.create_el({classes:`date-range-highlight hide highlight-${this.task.id}`,width:this.width,left:e});this.$date_highlight=i,this.gantt.$lower_header.prepend(this.$date_highlight),E(this.$bar_progress,"width",0,this.progress_width)}calculate_progress_width(){const t=this.$bar.getWidth(),e=this.x+t,i=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<e),0)*this.gantt.config.column_width;let n=(t-i)*this.task.progress/100;const s=this.x+n,o=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<s),0)*this.gantt.config.column_width;n+=o;let a=this.gantt.get_ignored_region(this.x+n);for(;a.length;)n+=this.gantt.config.column_width,a=this.gantt.get_ignored_region(this.x+n);return this.progress_width=n,n}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),this.$bar_label=f("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),this.task.color_text&&(this.$bar_label.style.fill=this.task.color_text),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,i,n;i=f("defs",{append_to:this.bar_group}),f("rect",{id:"rect_"+this.task.id,x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:i}),n=f("clipPath",{id:"clip_"+this.task.id,append_to:i}),f("use",{href:"#rect_"+this.task.id,append_to:n}),f("image",{x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,class:"bar-img",href:this.task.thumbnail,clipPath:"clip_"+this.task.id,append_to:this.bar_group})}draw_add_task_icon(){this.icon_size=20,this.icon_padding=5;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-20-5;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+5;else return;const n=this.y+(this.height-20)/2;this.$add_icon_group=f("g",{class:"add-task-icon hide",append_to:this.handle_group}),this.$add_icon_circle=f("circle",{cx:i+20/2,cy:n+20/2,r:20/2,class:"add-task-icon-bg",append_to:this.$add_icon_group}),this.$add_icon_vertical=f("line",{x1:i+20/2,y1:n+5,x2:i+20/2,y2:n+20-5,class:"add-task-icon-plus",append_to:this.$add_icon_group}),this.$add_icon_horizontal=f("line",{x1:i+5,y1:n+20/2,x2:i+20-5,y2:n+20/2,class:"add-task-icon-plus",append_to:this.$add_icon_group}),u.on(this.$add_icon_group,"mousedown",s=>{s.stopPropagation()}),u.on(this.$add_icon_group,"mouseup",s=>{s.stopPropagation()}),u.on(this.$add_icon_group,"click",s=>{s.stopPropagation(),this.gantt.trigger_event("task_add",[this.task])}),u.on(this.$add_icon_group,"mouseenter",s=>{this.is_hovering_icon=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.$add_icon_group.classList.add("active"),this.$add_icon_group.classList.remove("hide"),s.stopPropagation()}),u.on(this.$add_icon_group,"mouseleave",()=>{this.is_hovering_icon=!1,this.$add_icon_group.classList.remove("active"),this.is_hovering_bar||this.$add_icon_group.classList.add("hide")})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=3;if(this.handles=[],this.gantt.options.readonly_dates||(this.handles.push(f("rect",{x:t.getEndX()-e/2,y:t.getY()+this.height/4,width:e,height:this.height/2,rx:2,ry:2,class:"handle right",append_to:this.handle_group})),this.handles.push(f("rect",{x:t.getX()-e/2,y:t.getY()+this.height/4,width:e,height:this.height/2,rx:2,ry:2,class:"handle left",append_to:this.handle_group}))),!this.gantt.options.readonly_progress){const i=this.$bar_progress;this.$handle_progress=f("circle",{cx:i.getEndX(),cy:i.getY()+i.getHeight()/2,r:4.5,class:"handle progress",append_to:this.handle_group}),this.handles.push(this.$handle_progress)}for(let i of this.handles)u.on(i,"mouseenter",()=>i.classList.add("active")),u.on(i,"mouseleave",()=>i.classList.remove("active"))}bind(){this.invalid||this.setup_click_event()}unbind(){this.invalid||this.group&&this.event_listeners&&(this.event_listeners.forEach(({event:t,handler:e})=>{u.off(this.group,t,e)}),this.event_listeners=[])}setup_click_event(){this.event_listeners=[];let t=this.task.id;const e=g=>{this.gantt.trigger_event("hover",[this.task,g.screenX,g.screenY,g])};if(u.on(this.group,"mouseover",e),this.event_listeners.push({event:"mouseover",handler:e}),this.gantt.options.popup_on==="click"){const g=p=>{const w=p.offsetX||p.layerX;if(this.$handle_progress){const m=+this.$handle_progress.getAttribute("cx");if(m>w-1&&m<w+1||this.gantt.bar_being_dragged)return}this.gantt.show_popup({x:p.offsetX||p.layerX,y:p.offsetY||p.layerY,task:this.task,target:this.$bar})};u.on(this.group,"click",g),this.event_listeners.push({event:"click",handler:g})}let i;const n=g=>{i=setTimeout(()=>{this.gantt.options.popup_on==="hover"&&this.gantt.show_popup({x:g.offsetX||g.layerX,y:g.offsetY||g.layerY,task:this.task,target:this.$bar}),this.gantt.$container.querySelector(`.highlight-${t}`).classList.remove("hide")},200),this.$add_icon_group&&(this.is_hovering_bar=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.is_dragging||this.$add_icon_group.classList.remove("hide"))};u.on(this.group,"mouseenter",n),this.event_listeners.push({event:"mouseenter",handler:n});const s=()=>{var g,p;clearTimeout(i),this.gantt.options.popup_on==="hover"&&((p=(g=this.gantt.popup)==null?void 0:g.hide)==null||p.call(g)),this.gantt.$container.querySelector(`.highlight-${t}`).classList.add("hide"),this.$add_icon_group&&(this.is_hovering_bar=!1,this.add_icon_hide_timeout&&clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=setTimeout(()=>{this.is_hovering_icon||this.$add_icon_group.classList.add("hide")},200))};u.on(this.group,"mouseleave",s),this.event_listeners.push({event:"mouseleave",handler:s});const o=()=>{this.is_dragging=!0,this.hide_add_icon()};u.on(this.group,"mousedown",o),this.event_listeners.push({event:"mousedown",handler:o});const a=()=>{setTimeout(()=>{this.gantt.bar_being_dragged!==!0&&(this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide"))},0)};u.on(this.group,"mouseup",a),this.event_listeners.push({event:"mouseup",handler:a});const h=()=>{this.action_completed||this.gantt.bar_being_dragged||this.gantt.trigger_event("click",[this.task])};u.on(this.group,"click",h),this.event_listeners.push({event:"click",handler:h});const d=()=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"dblclick",d),this.event_listeners.push({event:"dblclick",handler:d});let _=!1;const c=g=>{if(!_)return _=!0,setTimeout(function(){_=!1},300),!1;g.preventDefault(),!this.action_completed&&(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"touchstart",c),this.event_listeners.push({event:"touchstart",handler:c})}update_bar_position({x:t=null,width:e=null}){const i=this.$bar;if(t){if(!this.validate_dependency_constraints(t,e))return;this.update_attr(i,"x",t),this.x=t,this.$date_highlight.style.left=t+"px"}e>0&&(this.update_attr(i,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.update_add_icon_position(),this.date_changed(),this.compute_duration(),this.gantt.options.show_expected_progress&&this.update_expected_progressbar_position(),this.update_progressbar_position(),this.update_arrow_position()}validate_dependency_constraints(t,e=null){const i=this.task.dependencies_type||this.gantt.options.dependencies_type;if(i==="fixed")return this.task.dependencies.map(_=>this.gantt.get_bar(_).$bar.getX()).reduce((_,c)=>_&&t>=c,!0);const n=t/this.gantt.config.column_width,s=l.add(this.gantt.gantt_start,n*this.gantt.config.step,this.gantt.config.unit),a=(e||this.$bar.getWidth())/this.gantt.config.column_width,h=l.add(s,a*this.gantt.config.step,this.gantt.config.unit);for(const d of this.task.dependencies){const _=this.gantt.get_bar(d);if(!_)continue;const c=_.task;switch(i){case"finish-to-start":if(s<c._end)return!1;break;case"start-to-start":if(s<c._start)return!1;break;case"finish-to-finish":if(h<c._end)return!1;break;case"start-to-finish":if(h<c._start)return!1;break}}return!0}update_label_position_on_horizontal_scroll({x:t,sx:e}){const i=this.gantt.$container,n=this.group.querySelector(".bar-label"),s=this.group.querySelector(".bar-img")||"",o=this.bar_group.querySelector(".img_mask")||"";let a=this.$bar.getX()+this.$bar.getWidth(),h=n.getX()+t,d=s&&s.getX()+t||0,_=s&&s.getBBox().width+7||7,c=h+n.getBBox().width+7,g=e+i.clientWidth/2;n.classList.contains("big")||(c<a&&t>0&&c<g||h-_>this.$bar.getX()&&t<0&&c>g)&&(n.setAttribute("x",h),s&&(s.setAttribute("x",d),o.setAttribute("x",d)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:i}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(i)&&(t=!0,this.task._end=i),t&&this.gantt.trigger_event("date_change",[this.task,e,l.add(i,-1,"second")])}progress_changed(){this.task.progress=this.compute_progress(),this.gantt.trigger_event("progress_change",[this.task,this.task.progress])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,10),this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide")}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.config.column_width;let i=l.add(this.gantt.gantt_start,e*this.gantt.config.step,this.gantt.config.unit);const n=t.getWidth()/this.gantt.config.column_width,s=l.add(i,n*this.gantt.config.step,this.gantt.config.unit);return{new_start_date:i,new_end_date:s}}compute_progress(){this.progress_width=this.$bar_progress.getWidth(),this.x=this.$bar_progress.getBBox().x;const t=this.x+this.progress_width,e=this.progress_width-this.gantt.config.ignored_positions.reduce((n,s)=>n+(s>=this.x&&s<=t),0)*this.gantt.config.column_width;if(e<0)return 0;const i=this.$bar.getWidth()-this.ignored_duration_raw*this.gantt.config.column_width;return parseInt(e/i*100,10)}compute_expected_progress(){this.expected_progress=l.diff(l.today(),this.task._start,"hour")/this.gantt.config.step,this.expected_progress=(this.expected_progress<this.duration?this.expected_progress:this.duration)*100/this.duration}compute_x(){const{column_width:t}=this.gantt.config,e=this.task._start,i=this.gantt.gantt_start;let s=l.diff(e,i,this.gantt.config.unit)/this.gantt.config.step*t;this.x=s}compute_y(){this.y=this.gantt.config.header_height+this.gantt.options.padding/2+this.task._index*(this.height+this.gantt.options.padding)}compute_duration(){let t=0,e=0;for(let i=new Date(this.task._start);i<this.task._end;i.setDate(i.getDate()+1))e++,!this.gantt.config.ignored_dates.find(n=>n.getTime()===i.getTime())&&(!this.gantt.config.ignored_function||!this.gantt.config.ignored_function(i))&&t++;this.task.actual_duration=t,this.task.ignored_duration=e-t,this.duration=l.convert_scales(e+"d",this.gantt.config.unit)/this.gantt.config.step,this.actual_duration_raw=l.convert_scales(t+"d",this.gantt.config.unit)/this.gantt.config.step,this.ignored_duration_raw=this.duration-this.actual_duration_raw}update_attr(t,e,i){return i=+i,isNaN(i)||t.setAttribute(e,i),t}update_expected_progressbar_position(){this.invalid||(this.$expected_bar_progress.setAttribute("x",this.$bar.getX()),this.compute_expected_progress(),this.$expected_bar_progress.setAttribute("width",this.gantt.config.column_width*this.actual_duration_raw*(this.expected_progress/100)||0))}update_progressbar_position(){this.invalid||this.gantt.options.readonly||(this.$bar_progress.setAttribute("x",this.$bar.getX()),this.$bar_progress.setAttribute("width",this.calculate_progress_width()))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,i=this.group.querySelector(".bar-label"),n=this.group.querySelector(".bar-img");let s=5,o=this.image_size+10;const a=i.getBBox().width,h=e.getWidth();a>h?(i.classList.add("big"),n?(n.setAttribute("x",e.getEndX()+s),t.setAttribute("x",e.getEndX()+s),i.setAttribute("x",e.getEndX()+o)):i.setAttribute("x",e.getEndX()+s)):(i.classList.remove("big"),n?(n.setAttribute("x",e.getX()+s),t.setAttribute("x",e.getX()+s),i.setAttribute("x",e.getX()+h/2+o)):i.setAttribute("x",e.getX()+h/2-a/2))}update_handle_position(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX());const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_add_icon_position(){if(!this.$add_icon_group)return;const t=this.icon_size,e=this.icon_padding;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-t-e;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+e;else return;const n=this.y+(this.height-t)/2;this.$add_icon_circle.setAttribute("cx",i+t/2),this.$add_icon_circle.setAttribute("cy",n+t/2),this.$add_icon_vertical.setAttribute("x1",i+t/2),this.$add_icon_vertical.setAttribute("y1",n+5),this.$add_icon_vertical.setAttribute("x2",i+t/2),this.$add_icon_vertical.setAttribute("y2",n+t-5),this.$add_icon_horizontal.setAttribute("x1",i+5),this.$add_icon_horizontal.setAttribute("y1",n+t/2),this.$add_icon_horizontal.setAttribute("x2",i+t-5),this.$add_icon_horizontal.setAttribute("y2",n+t/2)}hide_add_icon(){this.$add_icon_group&&this.$add_icon_group.classList.add("hide")}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class F{constructor(t,e,i){this.parent=t,this.popup_func=e,this.gantt=i,this.make()}make(){this.parent.innerHTML=`
19
+ l -5 5`}}draw(){let t="";this.is_invalid?t="arrow-invalid":this.is_critical&&(t="arrow-critical"),this.element=f("path",{d:this.path,"data-from":this.from_task.task.id,"data-to":this.to_task.task.id,class:t})}update(){this.calculate_path(),this.element.setAttribute("d",this.path),this.is_invalid=this.check_invalid_dependency();let t="";this.is_invalid?t="arrow-invalid":this.is_critical&&(t="arrow-critical"),this.element.setAttribute("class",t)}}class q{constructor(t,e){this.set_defaults(t,e),this.prepare_wrappers(),this.prepare_helpers(),this.refresh()}refresh(){this.bar_group.innerHTML="",this.handle_group.innerHTML="",this.task.custom_class?this.group.classList.add(this.task.custom_class):this.group.classList=["bar-wrapper"],this.unbind(),this.prepare_values(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e,this.name=this.name||"",this.is_dragging=!1,this.is_hovering_bar=!1,this.is_hovering_icon=!1,this.add_icon_hide_timeout=null}prepare_wrappers(){this.group=f("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:""),"data-id":this.task.id}),this.bar_group=f("g",{class:"bar-group",append_to:this.group}),this.handle_group=f("g",{class:"handle-group",append_to:this.group})}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,(!this.task._start||!(this.task._start instanceof Date))&&(this.task._start=new Date(this.task.start)),(!this.task._end||!(this.task._end instanceof Date))&&(this.task._end=new Date(this.task.end)),this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.config.column_width*this.duration,(!this.task.progress||this.task.progress<0)&&(this.task.progress=0),this.task.progress>100&&(this.task.progress=100)}prepare_helpers(){SVGElement.prototype.getX=function(){return+this.getAttribute("x")},SVGElement.prototype.getY=function(){return+this.getAttribute("y")},SVGElement.prototype.getWidth=function(){return+this.getAttribute("width")},SVGElement.prototype.getHeight=function(){return+this.getAttribute("height")},SVGElement.prototype.getEndX=function(){return this.getX()+this.getWidth()}}prepare_expected_progress_values(){this.compute_expected_progress(),this.expected_progress_width=this.gantt.options.column_width*this.duration*(this.expected_progress/100)||0}draw(){this.draw_bar(),this.draw_progress_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_label(),this.draw_resize_handles(),this.task.thumbnail&&this.draw_thumbnail(),this.gantt.options.task_add_icon_position&&this.draw_add_task_icon()}draw_bar(){this.$bar=f("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar",append_to:this.bar_group}),this.task.color&&(this.$bar.style.fill=this.task.color),E(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=f("rect",{x:this.x,y:this.y,width:this.expected_progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-expected-progress",append_to:this.bar_group}),E(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.progress_width=this.calculate_progress_width();let t=this.corner_radius;/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(t=this.corner_radius+2),this.$bar_progress=f("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:t,ry:t,class:"bar-progress",append_to:this.bar_group}),this.task.color_progress&&(this.$bar_progress.style.fill=this.task.color_progress);const e=l.diff(this.task._start,this.gantt.gantt_start,this.gantt.config.unit)/this.gantt.config.step*this.gantt.config.column_width;this.$date_highlight&&this.$date_highlight.parentNode&&this.$date_highlight.parentNode.removeChild(this.$date_highlight);let i=this.gantt.create_el({classes:`date-range-highlight hide highlight-${this.task.id}`,width:this.width,left:e});this.$date_highlight=i,this.gantt.$lower_header.prepend(this.$date_highlight),E(this.$bar_progress,"width",0,this.progress_width)}calculate_progress_width(){const t=this.$bar.getWidth(),e=this.x+t,i=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<e),0)*this.gantt.config.column_width;let n=(t-i)*this.task.progress/100;const s=this.x+n,o=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<s),0)*this.gantt.config.column_width;n+=o;let a=this.gantt.get_ignored_region(this.x+n);for(;a.length;)n+=this.gantt.config.column_width,a=this.gantt.get_ignored_region(this.x+n);return this.progress_width=n,n}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),this.$bar_label=f("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),this.task.color_text&&(this.$bar_label.style.fill=this.task.color_text),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,i,n;i=f("defs",{append_to:this.bar_group}),f("rect",{id:"rect_"+this.task.id,x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:i}),n=f("clipPath",{id:"clip_"+this.task.id,append_to:i}),f("use",{href:"#rect_"+this.task.id,append_to:n}),f("image",{x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,class:"bar-img",href:this.task.thumbnail,clipPath:"clip_"+this.task.id,append_to:this.bar_group})}draw_add_task_icon(){this.icon_size=20,this.icon_padding=5;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-20-5;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+5;else return;const n=this.y+(this.height-20)/2;this.$add_icon_group=f("g",{class:"add-task-icon hide",append_to:this.handle_group}),this.$add_icon_circle=f("circle",{cx:i+20/2,cy:n+20/2,r:20/2,class:"add-task-icon-bg",append_to:this.$add_icon_group}),this.$add_icon_vertical=f("line",{x1:i+20/2,y1:n+5,x2:i+20/2,y2:n+20-5,class:"add-task-icon-plus",append_to:this.$add_icon_group}),this.$add_icon_horizontal=f("line",{x1:i+5,y1:n+20/2,x2:i+20-5,y2:n+20/2,class:"add-task-icon-plus",append_to:this.$add_icon_group}),u.on(this.$add_icon_group,"mousedown",s=>{s.stopPropagation()}),u.on(this.$add_icon_group,"mouseup",s=>{s.stopPropagation()}),u.on(this.$add_icon_group,"click",s=>{s.stopPropagation(),this.gantt.trigger_event("task_add",[this.task])}),u.on(this.$add_icon_group,"mouseenter",s=>{this.is_hovering_icon=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.$add_icon_group.classList.add("active"),this.$add_icon_group.classList.remove("hide"),s.stopPropagation()}),u.on(this.$add_icon_group,"mouseleave",()=>{this.is_hovering_icon=!1,this.$add_icon_group.classList.remove("active"),this.is_hovering_bar||this.$add_icon_group.classList.add("hide")})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=8;if(this.handles=[],this.gantt.options.readonly_dates||(this.handles.push(f("rect",{x:t.getEndX()-e,y:t.getY()+(this.height-this.height*.8)/2,width:e,height:this.height*.8,rx:2,ry:2,class:"handle right",append_to:this.handle_group})),this.handles.push(f("rect",{x:t.getX()-e,y:t.getY()+(this.height-this.height*.8)/2,width:e,height:this.height*.8,rx:2,ry:2,class:"handle left",append_to:this.handle_group}))),!this.gantt.options.readonly_progress){const i=this.$bar_progress;this.$handle_progress=f("circle",{cx:i.getEndX(),cy:i.getY()+i.getHeight()/2,r:4.5,class:"handle progress",append_to:this.handle_group}),this.handles.push(this.$handle_progress)}for(let i of this.handles)u.on(i,"mouseenter",()=>i.classList.add("active")),u.on(i,"mouseleave",()=>i.classList.remove("active"))}bind(){this.invalid||this.setup_click_event()}unbind(){this.invalid||this.group&&this.event_listeners&&(this.event_listeners.forEach(({event:t,handler:e})=>{u.off(this.group,t,e)}),this.event_listeners=[])}setup_click_event(){this.event_listeners=[];let t=this.task.id;const e=g=>{this.gantt.trigger_event("hover",[this.task,g.screenX,g.screenY,g])};if(u.on(this.group,"mouseover",e),this.event_listeners.push({event:"mouseover",handler:e}),this.gantt.options.popup_on==="click"){const g=p=>{const w=p.offsetX||p.layerX;if(this.$handle_progress){const m=+this.$handle_progress.getAttribute("cx");if(m>w-1&&m<w+1||this.gantt.bar_being_dragged)return}this.gantt.show_popup({x:p.offsetX||p.layerX,y:p.offsetY||p.layerY,task:this.task,target:this.$bar})};u.on(this.group,"click",g),this.event_listeners.push({event:"click",handler:g})}let i;const n=g=>{i=setTimeout(()=>{this.gantt.options.popup_on==="hover"&&this.gantt.show_popup({x:g.offsetX||g.layerX,y:g.offsetY||g.layerY,task:this.task,target:this.$bar}),this.gantt.$container.querySelector(`.highlight-${t}`).classList.remove("hide")},200),this.$add_icon_group&&(this.is_hovering_bar=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.is_dragging||this.$add_icon_group.classList.remove("hide"))};u.on(this.group,"mouseenter",n),this.event_listeners.push({event:"mouseenter",handler:n});const s=()=>{var g,p;clearTimeout(i),this.gantt.options.popup_on==="hover"&&((p=(g=this.gantt.popup)==null?void 0:g.hide)==null||p.call(g)),this.gantt.$container.querySelector(`.highlight-${t}`).classList.add("hide"),this.$add_icon_group&&(this.is_hovering_bar=!1,this.add_icon_hide_timeout&&clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=setTimeout(()=>{this.is_hovering_icon||this.$add_icon_group.classList.add("hide")},200))};u.on(this.group,"mouseleave",s),this.event_listeners.push({event:"mouseleave",handler:s});const o=()=>{this.is_dragging=!0,this.hide_add_icon()};u.on(this.group,"mousedown",o),this.event_listeners.push({event:"mousedown",handler:o});const a=()=>{setTimeout(()=>{this.gantt.bar_being_dragged!==!0&&(this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide"))},0)};u.on(this.group,"mouseup",a),this.event_listeners.push({event:"mouseup",handler:a});const h=()=>{this.action_completed||this.gantt.bar_being_dragged||this.gantt.trigger_event("click",[this.task])};u.on(this.group,"click",h),this.event_listeners.push({event:"click",handler:h});const d=()=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"dblclick",d),this.event_listeners.push({event:"dblclick",handler:d});let _=!1;const c=g=>{if(!_)return _=!0,setTimeout(function(){_=!1},300),!1;g.preventDefault(),!this.action_completed&&(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))};u.on(this.group,"touchstart",c),this.event_listeners.push({event:"touchstart",handler:c})}update_bar_position({x:t=null,width:e=null}){const i=this.$bar;t&&(this.update_attr(i,"x",t),this.x=t,this.$date_highlight.style.left=t+"px"),e>0&&(this.update_attr(i,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.update_add_icon_position(),this.date_changed(),this.compute_duration(),this.gantt.options.show_expected_progress&&this.update_expected_progressbar_position(),this.update_progressbar_position(),this.update_arrow_position()}validate_dependency_constraints(t,e=null){const i=this.task.dependencies_type||this.gantt.options.dependencies_type;if(i==="fixed")return this.task.dependencies.map(_=>this.gantt.get_bar(_).$bar.getX()).reduce((_,c)=>_&&t>=c,!0);const n=t/this.gantt.config.column_width,s=l.add(this.gantt.gantt_start,n*this.gantt.config.step,this.gantt.config.unit),a=(e||this.$bar.getWidth())/this.gantt.config.column_width,h=l.add(s,a*this.gantt.config.step,this.gantt.config.unit);for(const d of this.task.dependencies){const _=this.gantt.get_bar(d);if(!_)continue;const c=_.task;switch(i){case"finish-to-start":if(s<c._end)return!1;break;case"start-to-start":if(s<c._start)return!1;break;case"finish-to-finish":if(h<c._end)return!1;break;case"start-to-finish":if(h<c._start)return!1;break}}return!0}update_label_position_on_horizontal_scroll({x:t,sx:e}){const i=this.gantt.$container,n=this.group.querySelector(".bar-label"),s=this.group.querySelector(".bar-img")||"",o=this.bar_group.querySelector(".img_mask")||"";let a=this.$bar.getX()+this.$bar.getWidth(),h=n.getX()+t,d=s&&s.getX()+t||0,_=s&&s.getBBox().width+7||7,c=h+n.getBBox().width+7,g=e+i.clientWidth/2;n.classList.contains("big")||(c<a&&t>0&&c<g||h-_>this.$bar.getX()&&t<0&&c>g)&&(n.setAttribute("x",h),s&&(s.setAttribute("x",d),o.setAttribute("x",d)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:i}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(i)&&(t=!0,this.task._end=i),t&&this.gantt.trigger_event("date_change",[this.task,e,l.add(i,-1,"second")])}progress_changed(){this.task.progress=this.compute_progress(),this.gantt.trigger_event("progress_change",[this.task,this.task.progress])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,10),this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide")}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.config.column_width;let i=l.add(this.gantt.gantt_start,e*this.gantt.config.step,this.gantt.config.unit);const n=t.getWidth()/this.gantt.config.column_width,s=l.add(i,n*this.gantt.config.step,this.gantt.config.unit);return{new_start_date:i,new_end_date:s}}compute_progress(){this.progress_width=this.$bar_progress.getWidth(),this.x=this.$bar_progress.getBBox().x;const t=this.x+this.progress_width,e=this.progress_width-this.gantt.config.ignored_positions.reduce((n,s)=>n+(s>=this.x&&s<=t),0)*this.gantt.config.column_width;if(e<0)return 0;const i=this.$bar.getWidth()-this.ignored_duration_raw*this.gantt.config.column_width;return parseInt(e/i*100,10)}compute_expected_progress(){this.expected_progress=l.diff(l.today(),this.task._start,"hour")/this.gantt.config.step,this.expected_progress=(this.expected_progress<this.duration?this.expected_progress:this.duration)*100/this.duration}compute_x(){const{column_width:t}=this.gantt.config,e=this.task._start,i=this.gantt.gantt_start;let s=l.diff(e,i,this.gantt.config.unit)/this.gantt.config.step*t;this.x=s}compute_y(){this.y=this.gantt.config.header_height+this.gantt.options.padding/2+this.task._index*(this.height+this.gantt.options.padding)}compute_duration(){let t=0,e=0;for(let i=new Date(this.task._start);i<this.task._end;i.setDate(i.getDate()+1))e++,!this.gantt.config.ignored_dates.find(n=>n.getTime()===i.getTime())&&(!this.gantt.config.ignored_function||!this.gantt.config.ignored_function(i))&&t++;this.task.actual_duration=t,this.task.ignored_duration=e-t,this.duration=l.convert_scales(e+"d",this.gantt.config.unit)/this.gantt.config.step,this.actual_duration_raw=l.convert_scales(t+"d",this.gantt.config.unit)/this.gantt.config.step,this.ignored_duration_raw=this.duration-this.actual_duration_raw}update_attr(t,e,i){return i=+i,isNaN(i)||t.setAttribute(e,i),t}update_expected_progressbar_position(){this.invalid||(this.$expected_bar_progress.setAttribute("x",this.$bar.getX()),this.compute_expected_progress(),this.$expected_bar_progress.setAttribute("width",this.gantt.config.column_width*this.actual_duration_raw*(this.expected_progress/100)||0))}update_progressbar_position(){this.invalid||this.gantt.options.readonly||(this.$bar_progress.setAttribute("x",this.$bar.getX()),this.$bar_progress.setAttribute("width",this.calculate_progress_width()))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,i=this.group.querySelector(".bar-label"),n=this.group.querySelector(".bar-img");let s=5,o=this.image_size+10;const a=i.getBBox().width,h=e.getWidth();a>h?(i.classList.add("big"),n?(n.setAttribute("x",e.getEndX()+s),t.setAttribute("x",e.getEndX()+s),i.setAttribute("x",e.getEndX()+o)):i.setAttribute("x",e.getEndX()+s)):(i.classList.remove("big"),n?(n.setAttribute("x",e.getX()+s),t.setAttribute("x",e.getX()+s),i.setAttribute("x",e.getX()+h/2+o)):i.setAttribute("x",e.getX()+h/2-a/2))}update_handle_position(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX());const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_add_icon_position(){if(!this.$add_icon_group)return;const t=this.icon_size,e=this.icon_padding;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-t-e;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+e;else return;const n=this.y+(this.height-t)/2;this.$add_icon_circle.setAttribute("cx",i+t/2),this.$add_icon_circle.setAttribute("cy",n+t/2),this.$add_icon_vertical.setAttribute("x1",i+t/2),this.$add_icon_vertical.setAttribute("y1",n+5),this.$add_icon_vertical.setAttribute("x2",i+t/2),this.$add_icon_vertical.setAttribute("y2",n+t-5),this.$add_icon_horizontal.setAttribute("x1",i+5),this.$add_icon_horizontal.setAttribute("y1",n+t/2),this.$add_icon_horizontal.setAttribute("x2",i+t-5),this.$add_icon_horizontal.setAttribute("y2",n+t/2)}hide_add_icon(){this.$add_icon_group&&this.$add_icon_group.classList.add("hide")}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class F{constructor(t,e,i){this.parent=t,this.popup_func=e,this.gantt=i,this.make()}make(){this.parent.innerHTML=`
20
20
  <div class="title"></div>
21
21
  <div class="subtitle"></div>
22
22
  <div class="details"></div>
@@ -26,4 +26,4 @@
26
26
  M0,4 l4,-4
27
27
  M3,5 l2,-2"
28
28
  style="stroke:grey; stroke-width:0.3" />
29
- </pattern>`;for(let i=new Date(this.gantt_start);i<=this.gantt_end;i.setDate(i.getDate()+1)){if(!this.config.ignored_dates.find(s=>s.getTime()==i.getTime())&&(!this.config.ignored_function||!this.config.ignored_function(i)))continue;let n=l.convert_scales(l.diff(i,this.gantt_start)+"d",this.config.unit)/this.config.step;this.config.ignored_positions.push(n*this.config.column_width),f("rect",{x:n*this.config.column_width,y:this.config.header_height,width:this.config.column_width,height:t,class:"ignored-bar",style:"fill: url(#diagonalHatch);",append_to:this.$svg})}this.highlight_current(this.config.view_mode)}create_el({left:t,top:e,width:i,height:n,id:s,classes:o,append_to:a,type:h}){let d=document.createElement(h||"div");for(let _ of o.split(" "))d.classList.add(_);return d.style.top=e+"px",d.style.left=t+"px",s&&(d.id=s),i&&(d.style.width=i+"px"),n&&(d.style.height=n+"px"),a&&a.appendChild(d),d}make_dates(){this.get_dates_to_draw().forEach((t,e)=>{if(t.lower_text){let i=this.create_el({left:t.x,top:t.lower_y,classes:"lower-text date_"+D(t.formatted_date),append_to:this.$lower_header});i.innerText=t.lower_text}if(t.upper_text){let i=this.create_el({left:t.x,top:t.upper_y,classes:"upper-text",append_to:this.$upper_header});i.innerText=t.upper_text}}),this.upperTexts=Array.from(this.$container.querySelectorAll(".upper-text"))}get_dates_to_draw(){let t=null;return this.dates.map((i,n)=>{const s=this.get_date_info(i,t,n);return t=s,s})}get_date_info(t,e){let i=e?e.date:null;this.config.column_width;const n=e?e.x+e.column_width:0;let s=this.config.view_mode.upper_text,o=this.config.view_mode.lower_text;return s?typeof s=="string"&&(this.config.view_mode.upper_text=a=>l.format(a,s,this.options.language)):this.config.view_mode.upper_text=()=>"",o?typeof o=="string"&&(this.config.view_mode.lower_text=a=>l.format(a,o,this.options.language)):this.config.view_mode.lower_text=()=>"",{date:t,formatted_date:D(l.format(t,this.config.date_format,this.options.language)),column_width:this.config.column_width,x:n,upper_text:this.config.view_mode.upper_text(t,i,this.options.language),lower_text:this.config.view_mode.lower_text(t,i,this.options.language),upper_y:17,lower_y:this.options.upper_header_height+5}}make_bars(){this.bars=this.tasks.map(t=>{const e=new q(this,t);return this.layers.bar.appendChild(e.group),e})}make_arrows(){this.arrows=[],this.options.critical_path&&this.calculate_critical_path();for(let t of this.tasks){let e=[];e=t.dependencies.map(i=>{const n=this.get_task(i);if(!n)return;const s=new C(this,this.bars[n._index],this.bars[t._index]);return this.layers.arrow.appendChild(s.element),s}).filter(Boolean),this.arrows=this.arrows.concat(e)}}calculate_critical_path(){this.tasks.forEach(s=>s._is_critical=!1);const t={};this.tasks.forEach(s=>{t[s.id]={es:0,ef:0,ls:0,lf:0}});const e=s=>{if(t[s.id].ef>0)return t[s.id];let o=0;s.dependencies&&s.dependencies.length>0&&s.dependencies.forEach(h=>{const d=this.get_task(h);if(d){const _=e(d);o=Math.max(o,_.ef)}}),t[s.id].es=o;const a=l.diff(s._end,s._start,"hour")/24;return t[s.id].ef=o+a,t[s.id]};this.tasks.forEach(s=>e(s));const i=Math.max(...Object.values(t).map(s=>s.ef)),n=s=>{if(t[s.id].ls>0||t[s.id].lf>0)return t[s.id];const o=this.tasks.filter(d=>d.dependencies&&d.dependencies.includes(s.id));let a=i;o.length>0&&o.forEach(d=>{const _=n(d);a=Math.min(a,_.ls)});const h=l.diff(s._end,s._start,"hour")/24;return t[s.id].lf=a,t[s.id].ls=a-h,t[s.id]};this.tasks.forEach(s=>n(s)),this.tasks.forEach(s=>{const o=t[s.id],a=o.ls-o.es;s._is_critical=Math.abs(a)<.01})}update_arrow_critical_path(){this.arrows.forEach(t=>{t.from_task.task._is_critical===!0&&t.to_task.task._is_critical===!0?t.element.classList.add("arrow-critical"):t.element.classList.remove("arrow-critical")})}map_arrows_on_bars(){for(let t of this.bars)t.arrows=this.arrows.filter(e=>e.from_task.task.id===t.task.id||e.to_task.task.id===t.task.id)}set_dimensions(){const{width:t}=this.$svg.getBoundingClientRect(),e=this.$svg.querySelector(".grid .grid-row")?this.$svg.querySelector(".grid .grid-row").getAttribute("width"):0;t<e&&this.$svg.setAttribute("width",e)}set_scroll_position(t){if(this.options.infinite_padding&&(!t||t==="start")){let[o,...a]=this.get_start_end_positions();this.$container.scrollLeft=o;return}if(!t||t==="start")t=this.gantt_start;else if(t==="end")t=this.gantt_end;else{if(t==="today")return this.scroll_current();typeof t=="string"&&(t=l.parse(t))}const i=l.diff(t,this.gantt_start,this.config.unit)/this.config.step*this.config.column_width;this.$container.scrollTo({left:i-this.config.column_width/6,behavior:"smooth"}),this.$current&&this.$current.classList.remove("current-upper"),this.current_date=l.add(this.gantt_start,this.$container.scrollLeft/this.config.column_width,this.config.unit);let n=this.config.view_mode.upper_text(this.current_date,null,this.options.language),s=this.upperTexts.find(o=>o.textContent===n);this.current_date=l.add(this.gantt_start,(this.$container.scrollLeft+s.clientWidth)/this.config.column_width,this.config.unit),n=this.config.view_mode.upper_text(this.current_date,null,this.options.language),s=this.upperTexts.find(o=>o.textContent===n),s.classList.add("current-upper"),this.$current=s}scroll_current(){let t=this.get_closest_date();t&&this.set_scroll_position(t[0])}get_closest_date(){let t=new Date;if(t<this.gantt_start||t>this.gantt_end)return null;let e=new Date,i=this.$container.querySelector(".date_"+D(l.format(e,this.config.date_format,this.options.language))),n=0;for(;!i&&n<this.config.step;)e=l.add(e,-1,this.config.unit),i=this.$container.querySelector(".date_"+D(l.format(e,this.config.date_format,this.options.language))),n++;return[new Date(l.format(e,this.config.date_format,this.options.language)+" "),i]}bind_grid_click(){u.on(this.$container,"click",".grid-row, .grid-header, .ignored-bar, .holiday-highlight",()=>{this.unselect_all(),this.hide_popup()})}bind_holiday_labels(){const t=this.$container.querySelectorAll(".holiday-highlight");for(let e of t){const i=this.$container.querySelector(".label_"+e.classList[1]);if(!i)continue;let n;e.onmouseenter=s=>{n=setTimeout(()=>{i.classList.add("show"),i.style.left=(s.offsetX||s.layerX)+"px",i.style.top=(s.offsetY||s.layerY)+"px"},300)},e.onmouseleave=s=>{clearTimeout(n),i.classList.remove("show")}}}get_start_end_positions(){if(!this.bars.length)return[0,0,0];let{x:t,width:e}=this.bars[0].group.getBBox(),i=t,n=t,s=t+e;return Array.prototype.forEach.call(this.bars,function({group:o},a){let{x:h,width:d}=o.getBBox();h<i&&(i=h),h>n&&(n=h),h+d>s&&(s=h+d)}),[i,n,s]}bind_bar_events(){let t=!1,e=0,i=0,n=!1,s=!1,o=null,a=[];this.bar_being_dragged=null;const h=()=>t||n||s;this.$svg.onclick=_=>{_.target.classList.contains("grid-row")&&this.unselect_all()};let d=0;if(u.on(this.$svg,"mousemove",".bar-wrapper, .handle",_=>{this.bar_being_dragged===!1&&Math.abs((_.offsetX||_.layerX)-d)>10&&(this.bar_being_dragged=!0)}),u.on(this.$svg,"mousedown",".bar-wrapper, .handle",(_,c)=>{const g=u.closest(".bar-wrapper",c);c.classList.contains("left")?(n=!0,c.classList.add("visible")):c.classList.contains("right")?(s=!0,c.classList.add("visible")):c.classList.contains("bar-wrapper")&&(t=!0),this.popup&&this.popup.hide(),e=_.offsetX||_.layerX,o=g.getAttribute("data-id");const w=this.get_bar(o).task.dependencies_type||this.options.dependencies_type;let m;this.options.move_dependencies&&w==="fixed"?m=[o,...this.get_all_dependent_tasks(o)]:m=[o],a=m.map(k=>this.get_bar(k)),this.bar_being_dragged=!1,d=e,a.forEach(k=>{const y=k.$bar;y.ox=y.getX(),y.oy=y.getY(),y.owidth=y.getWidth(),y.finaldx=0})}),this.options.infinite_padding){let _=!1;u.on(this.$container,"mousewheel",c=>{let g=this.$container.scrollWidth/2;if(!_&&c.currentTarget.scrollLeft<=g){let p=c.currentTarget.scrollLeft;_=!0,this.gantt_start=l.add(this.gantt_start,-this.config.extend_by_units,this.config.unit),this.setup_date_values(),this.render(),c.currentTarget.scrollLeft=p+this.config.column_width*this.config.extend_by_units,setTimeout(()=>_=!1,300)}if(!_&&c.currentTarget.scrollWidth-(c.currentTarget.scrollLeft+c.currentTarget.clientWidth)<=g){let p=c.currentTarget.scrollLeft;_=!0,this.gantt_end=l.add(this.gantt_end,this.config.extend_by_units,this.config.unit),this.setup_date_values(),this.render(),c.currentTarget.scrollLeft=p,setTimeout(()=>_=!1,300)}})}u.on(this.$container,"scroll",_=>{let c=[];const g=this.bars.map(({group:$})=>$.getAttribute("data-id"));let p;i&&(p=_.currentTarget.scrollLeft-i),this.current_date=l.add(this.gantt_start,_.currentTarget.scrollLeft/this.config.column_width*this.config.step,this.config.unit);let w=this.config.view_mode.upper_text(this.current_date,null,this.options.language),m=this.upperTexts.find($=>$.textContent===w);this.current_date=l.add(this.gantt_start,(_.currentTarget.scrollLeft+m.clientWidth)/this.config.column_width*this.config.step,this.config.unit),w=this.config.view_mode.upper_text(this.current_date,null,this.options.language),m=this.upperTexts.find($=>$.textContent===w),m!==this.$current&&(this.$current&&this.$current.classList.remove("current-upper"),m.classList.add("current-upper"),this.$current=m),i=_.currentTarget.scrollLeft;let[k,y,B]=this.get_start_end_positions();i>B+100?(this.$adjust.innerHTML="&larr;",this.$adjust.classList.remove("hide"),this.$adjust.onclick=()=>{this.$container.scrollTo({left:y,behavior:"smooth"})}):i+_.currentTarget.offsetWidth<k-100?(this.$adjust.innerHTML="&rarr;",this.$adjust.classList.remove("hide"),this.$adjust.onclick=()=>{this.$container.scrollTo({left:k,behavior:"smooth"})}):this.$adjust.classList.add("hide"),p&&(c=g.map($=>this.get_bar($)),this.options.auto_move_label&&c.forEach($=>{$.update_label_position_on_horizontal_scroll({x:p,sx:_.currentTarget.scrollLeft})}))}),u.on(this.$svg,"mousemove",_=>{if(!h())return;const c=(_.offsetX||_.layerX)-e;a.forEach(g=>{const p=g.$bar;p.finaldx=this.get_snap_position(c,p.ox),this.hide_popup(),n?o===g.task.id?g.update_bar_position({x:p.ox+p.finaldx,width:p.owidth-p.finaldx}):g.update_bar_position({x:p.ox+p.finaldx}):s?o===g.task.id&&g.update_bar_position({width:p.owidth+p.finaldx}):t&&!this.options.readonly&&!this.options.readonly_dates&&g.update_bar_position({x:p.ox+p.finaldx})})}),document.addEventListener("mouseup",()=>{var _,c,g;t=!1,n=!1,s=!1,(g=(c=(_=this.$container.querySelector(".visible"))==null?void 0:_.classList)==null?void 0:c.remove)==null||g.call(c,"visible")}),u.on(this.$svg,"mouseup",_=>{this.bar_being_dragged=null;const c=[];a.forEach(p=>{p.$bar.finaldx&&(p.date_changed(),p.compute_progress(),p.set_action_completed(),c.push({task:p.task,start:p.task._start,end:l.add(p.task._end,-1,"second")}))});const g=this.get_bar(o);if(g&&g.$bar.finaldx){const p=this.update_dependent_tasks_by_type(g);c.push(...p)}this.options.critical_path&&a.some(p=>p.$bar.finaldx)&&(this.calculate_critical_path(),this.update_arrow_critical_path()),c.length>0&&c.forEach(({task:p,start:w,end:m})=>{this.trigger_event("after_date_change",[p,w,m])})}),this.bind_bar_progress()}bind_bar_progress(){let t=0,e=null,i=null,n=null,s=null;u.on(this.$svg,"mousedown",".handle.progress",(a,h)=>{e=!0,t=a.offsetX||a.layerX;const _=u.closest(".bar-wrapper",h).getAttribute("data-id");i=this.get_bar(_),n=i.$bar_progress,s=i.$bar,n.finaldx=0,n.owidth=n.getWidth(),n.min_dx=-n.owidth,n.max_dx=s.getWidth()-n.getWidth()});const o=this.config.ignored_positions.map(a=>[a,a+this.config.column_width]);u.on(this.$svg,"mousemove",a=>{if(!e)return;let h=a.offsetX||a.layerX;if(h>t){let c=o.find(([g,p])=>h>=g&&h<p);for(;c;)h=c[1],c=o.find(([g,p])=>h>=g&&h<p)}else{let c=o.find(([g,p])=>h>g&&h<=p);for(;c;)h=c[0],c=o.find(([g,p])=>h>g&&h<=p)}let _=h-t;console.log(n),_>n.max_dx&&(_=n.max_dx),_<n.min_dx&&(_=n.min_dx),n.setAttribute("width",n.owidth+_),u.attr(i.$handle_progress,"cx",n.getEndX()),n.finaldx=_}),u.on(this.$svg,"mouseup",()=>{e=!1,n&&n.finaldx&&(n.finaldx=0,i.progress_changed(),i.set_action_completed(),i=null,n=null,s=null)})}get_all_dependent_tasks(t){let e=[],i=[t];for(;i.length;){const n=i.reduce((s,o)=>(s=s.concat(this.dependency_map[o]),s),[]);e=e.concat(n),i=n.filter(s=>!i.includes(s))}return e.filter(Boolean)}update_dependent_tasks_by_type(t){const e=t.task.dependencies_type||this.options.dependencies_type,i=[];return e==="fixed"||(this.dependency_map[t.task.id]||[]).forEach(s=>{const o=this.get_bar(s);if(!o)return;const a=o.task,h=a.dependencies_type||this.options.dependencies_type;let d,_;const c=l.diff(a._end,a._start,"hour");let g=!1;switch(h){case"finish-to-start":t.task._end>a._start&&(d=new Date(t.task._end),_=l.add(d,c,"hour"),g=!0);break;case"start-to-start":t.task._start>a._start&&(d=new Date(t.task._start),_=l.add(d,c,"hour"),g=!0);break;case"finish-to-finish":t.task._end>a._end&&(_=new Date(t.task._end),d=l.add(_,-c,"hour"),g=!0);break;case"start-to-finish":t.task._start>a._end&&(_=new Date(t.task._start),d=l.add(_,-c,"hour"),g=!0);break;default:return}if(!g)return;a._start=d,a._end=_,o.compute_x(),o.compute_duration(),o.update_bar_position({x:o.x,width:o.width}),this.trigger_event("date_change",[a,d,l.add(_,-1,"second")]),i.push({task:a,start:d,end:l.add(_,-1,"second")});const p=this.update_dependent_tasks_by_type(o);i.push(...p)}),i}get_snap_position(t,e){let i=1;const n=this.options.snap_at||this.config.view_mode.snap_at||"1d";if(n!=="unit"){const{duration:_,scale:c}=l.parse_duration(n);i=l.convert_scales(this.config.view_mode.step,c)/_}const s=t%(this.config.column_width/i);let o=t-s+(s<this.config.column_width/i*2?0:this.config.column_width/i),a=e+o;const h=o>0?1:-1;let d=this.get_ignored_region(a,h);for(;d.length;)a+=this.config.column_width*h,d=this.get_ignored_region(a,h),d.length||(a-=this.config.column_width*h);return a-e}get_ignored_region(t,e=1){return e===1?this.config.ignored_positions.filter(i=>t>i&&t<=i+this.config.column_width):this.config.ignored_positions.filter(i=>t>=i&&t<i+this.config.column_width)}unselect_all(){this.popup&&this.popup.parent.classList.add("hide"),this.$container.querySelectorAll(".date-range-highlight").forEach(t=>t.classList.add("hide"))}view_is(t){return typeof t=="string"?this.config.view_mode.name===t:Array.isArray(t)?t.some(view_is):this.config.view_mode.name===t.name}get_task(t){return this.tasks.find(e=>e.id===t)}get_bar(t){return this.bars.find(e=>e.task.id===t)}show_popup(t){this.options.popup!==!1&&(this.popup||(this.popup=new F(this.$popup_wrapper,this.options.popup,this)),this.popup.show(t))}hide_popup(){this.popup&&this.popup.hide()}trigger_event(t,e){this.options["on_"+t]&&this.options["on_"+t].apply(this,e)}get_oldest_starting_date(){return this.tasks.length?this.tasks.map(t=>t._start).reduce((t,e)=>e<=t?e:t):new Date}clear(){var t,e,i,n,s,o,a,h,d,_;this.$svg.innerHTML="",(e=(t=this.$header)==null?void 0:t.remove)==null||e.call(t),(n=(i=this.$side_header)==null?void 0:i.remove)==null||n.call(i),(o=(s=this.$current_highlight)==null?void 0:s.remove)==null||o.call(s),(h=(a=this.$extras)==null?void 0:a.remove)==null||h.call(a),(_=(d=this.popup)==null?void 0:d.hide)==null||_.call(d)}}X.VIEW_MODE={HOUR:b[0],QUARTER_DAY:b[1],HALF_DAY:b[2],DAY:b[3],WEEK:b[4],MONTH:b[5],YEAR:b[6]};function j(r){return r.name+"_"+Math.random().toString(36).slice(2,12)}function D(r){return r.replaceAll(" ","_").replaceAll(":","_").replaceAll(".","_")}return X});
29
+ </pattern>`;for(let i=new Date(this.gantt_start);i<=this.gantt_end;i.setDate(i.getDate()+1)){if(!this.config.ignored_dates.find(s=>s.getTime()==i.getTime())&&(!this.config.ignored_function||!this.config.ignored_function(i)))continue;let n=l.convert_scales(l.diff(i,this.gantt_start)+"d",this.config.unit)/this.config.step;this.config.ignored_positions.push(n*this.config.column_width),f("rect",{x:n*this.config.column_width,y:this.config.header_height,width:this.config.column_width,height:t,class:"ignored-bar",style:"fill: url(#diagonalHatch);",append_to:this.$svg})}this.highlight_current(this.config.view_mode)}create_el({left:t,top:e,width:i,height:n,id:s,classes:o,append_to:a,type:h}){let d=document.createElement(h||"div");for(let _ of o.split(" "))d.classList.add(_);return d.style.top=e+"px",d.style.left=t+"px",s&&(d.id=s),i&&(d.style.width=i+"px"),n&&(d.style.height=n+"px"),a&&a.appendChild(d),d}make_dates(){this.get_dates_to_draw().forEach((t,e)=>{if(t.lower_text){let i=this.create_el({left:t.x,top:t.lower_y,classes:"lower-text date_"+D(t.formatted_date),append_to:this.$lower_header});i.innerText=t.lower_text}if(t.upper_text){let i=this.create_el({left:t.x,top:t.upper_y,classes:"upper-text",append_to:this.$upper_header});i.innerText=t.upper_text}}),this.upperTexts=Array.from(this.$container.querySelectorAll(".upper-text"))}get_dates_to_draw(){let t=null;return this.dates.map((i,n)=>{const s=this.get_date_info(i,t,n);return t=s,s})}get_date_info(t,e){let i=e?e.date:null;this.config.column_width;const n=e?e.x+e.column_width:0;let s=this.config.view_mode.upper_text,o=this.config.view_mode.lower_text;return s?typeof s=="string"&&(this.config.view_mode.upper_text=a=>l.format(a,s,this.options.language)):this.config.view_mode.upper_text=()=>"",o?typeof o=="string"&&(this.config.view_mode.lower_text=a=>l.format(a,o,this.options.language)):this.config.view_mode.lower_text=()=>"",{date:t,formatted_date:D(l.format(t,this.config.date_format,this.options.language)),column_width:this.config.column_width,x:n,upper_text:this.config.view_mode.upper_text(t,i,this.options.language),lower_text:this.config.view_mode.lower_text(t,i,this.options.language),upper_y:17,lower_y:this.options.upper_header_height+5}}make_bars(){this.bars=this.tasks.map(t=>{const e=new q(this,t);return this.layers.bar.appendChild(e.group),e})}make_arrows(){this.arrows=[],this.options.critical_path&&this.calculate_critical_path();for(let t of this.tasks){let e=[];e=t.dependencies.map(i=>{const n=this.get_task(i);if(!n)return;const s=new C(this,this.bars[n._index],this.bars[t._index]);return this.layers.arrow.appendChild(s.element),s}).filter(Boolean),this.arrows=this.arrows.concat(e)}}calculate_critical_path(){this.tasks.forEach(s=>s._is_critical=!1);const t={};this.tasks.forEach(s=>{t[s.id]={es:0,ef:0,ls:0,lf:0}});const e=s=>{if(t[s.id].ef>0)return t[s.id];let o=0;s.dependencies&&s.dependencies.length>0&&s.dependencies.forEach(h=>{const d=this.get_task(h);if(d){const _=e(d);o=Math.max(o,_.ef)}}),t[s.id].es=o;const a=l.diff(s._end,s._start,"hour")/24;return t[s.id].ef=o+a,t[s.id]};this.tasks.forEach(s=>e(s));const i=Math.max(...Object.values(t).map(s=>s.ef)),n=s=>{if(t[s.id].ls>0||t[s.id].lf>0)return t[s.id];const o=this.tasks.filter(d=>d.dependencies&&d.dependencies.includes(s.id));let a=i;o.length>0&&o.forEach(d=>{const _=n(d);a=Math.min(a,_.ls)});const h=l.diff(s._end,s._start,"hour")/24;return t[s.id].lf=a,t[s.id].ls=a-h,t[s.id]};this.tasks.forEach(s=>n(s)),this.tasks.forEach(s=>{const o=t[s.id],a=o.ls-o.es;s._is_critical=Math.abs(a)<.01})}update_arrow_critical_path(){this.arrows.forEach(t=>{t.from_task.task._is_critical===!0&&t.to_task.task._is_critical===!0?t.element.classList.add("arrow-critical"):t.element.classList.remove("arrow-critical")})}map_arrows_on_bars(){for(let t of this.bars)t.arrows=this.arrows.filter(e=>e.from_task.task.id===t.task.id||e.to_task.task.id===t.task.id)}set_dimensions(){const{width:t}=this.$svg.getBoundingClientRect(),e=this.$svg.querySelector(".grid .grid-row")?this.$svg.querySelector(".grid .grid-row").getAttribute("width"):0;t<e&&this.$svg.setAttribute("width",e)}set_scroll_position(t){if(this.options.infinite_padding&&(!t||t==="start")){let[o,...a]=this.get_start_end_positions();this.$container.scrollLeft=o;return}if(!t||t==="start")t=this.gantt_start;else if(t==="end")t=this.gantt_end;else{if(t==="today")return this.scroll_current();typeof t=="string"&&(t=l.parse(t))}const i=l.diff(t,this.gantt_start,this.config.unit)/this.config.step*this.config.column_width;this.$container.scrollTo({left:i-this.config.column_width/6,behavior:"smooth"}),this.$current&&this.$current.classList.remove("current-upper"),this.current_date=l.add(this.gantt_start,this.$container.scrollLeft/this.config.column_width,this.config.unit);let n=this.config.view_mode.upper_text(this.current_date,null,this.options.language),s=this.upperTexts.find(o=>o.textContent===n);this.current_date=l.add(this.gantt_start,(this.$container.scrollLeft+s.clientWidth)/this.config.column_width,this.config.unit),n=this.config.view_mode.upper_text(this.current_date,null,this.options.language),s=this.upperTexts.find(o=>o.textContent===n),s.classList.add("current-upper"),this.$current=s}scroll_current(){let t=this.get_closest_date();t&&this.set_scroll_position(t[0])}get_closest_date(){let t=new Date;if(t<this.gantt_start||t>this.gantt_end)return null;let e=new Date,i=this.$container.querySelector(".date_"+D(l.format(e,this.config.date_format,this.options.language))),n=0;for(;!i&&n<this.config.step;)e=l.add(e,-1,this.config.unit),i=this.$container.querySelector(".date_"+D(l.format(e,this.config.date_format,this.options.language))),n++;return[new Date(l.format(e,this.config.date_format,this.options.language)+" "),i]}bind_grid_click(){u.on(this.$container,"click",".grid-row, .grid-header, .ignored-bar, .holiday-highlight",()=>{this.unselect_all(),this.hide_popup()})}bind_holiday_labels(){const t=this.$container.querySelectorAll(".holiday-highlight");for(let e of t){const i=this.$container.querySelector(".label_"+e.classList[1]);if(!i)continue;let n;e.onmouseenter=s=>{n=setTimeout(()=>{i.classList.add("show"),i.style.left=(s.offsetX||s.layerX)+"px",i.style.top=(s.offsetY||s.layerY)+"px"},300)},e.onmouseleave=s=>{clearTimeout(n),i.classList.remove("show")}}}get_start_end_positions(){if(!this.bars.length)return[0,0,0];let{x:t,width:e}=this.bars[0].group.getBBox(),i=t,n=t,s=t+e;return Array.prototype.forEach.call(this.bars,function({group:o},a){let{x:h,width:d}=o.getBBox();h<i&&(i=h),h>n&&(n=h),h+d>s&&(s=h+d)}),[i,n,s]}bind_bar_events(){let t=!1,e=0,i=0,n=!1,s=!1,o=null,a=[];this.bar_being_dragged=null;const h=()=>t||n||s;this.$svg.onclick=_=>{_.target.classList.contains("grid-row")&&this.unselect_all()};let d=0;if(u.on(this.$svg,"mousemove",".bar-wrapper, .handle",_=>{this.bar_being_dragged===!1&&Math.abs((_.offsetX||_.layerX)-d)>10&&(this.bar_being_dragged=!0)}),u.on(this.$svg,"mousedown",".bar-wrapper, .handle",(_,c)=>{const g=u.closest(".bar-wrapper",c);c.classList.contains("left")?(n=!0,c.classList.add("visible")):c.classList.contains("right")?(s=!0,c.classList.add("visible")):c.classList.contains("bar-wrapper")&&(t=!0),this.popup&&this.popup.hide(),e=_.offsetX||_.layerX,o=g.getAttribute("data-id");const w=this.get_bar(o).task.dependencies_type||this.options.dependencies_type;let m;this.options.move_dependencies&&w==="fixed"?m=[o,...this.get_all_dependent_tasks(o)]:m=[o],a=m.map(k=>this.get_bar(k)),this.bar_being_dragged=!1,d=e,a.forEach(k=>{const y=k.$bar;y.ox=y.getX(),y.oy=y.getY(),y.owidth=y.getWidth(),y.finaldx=0})}),this.options.infinite_padding){let _=!1;u.on(this.$container,"mousewheel",c=>{let g=this.$container.scrollWidth/2;if(!_&&c.currentTarget.scrollLeft<=g){let p=c.currentTarget.scrollLeft;_=!0,this.gantt_start=l.add(this.gantt_start,-this.config.extend_by_units,this.config.unit),this.setup_date_values(),this.render(),c.currentTarget.scrollLeft=p+this.config.column_width*this.config.extend_by_units,setTimeout(()=>_=!1,300)}if(!_&&c.currentTarget.scrollWidth-(c.currentTarget.scrollLeft+c.currentTarget.clientWidth)<=g){let p=c.currentTarget.scrollLeft;_=!0,this.gantt_end=l.add(this.gantt_end,this.config.extend_by_units,this.config.unit),this.setup_date_values(),this.render(),c.currentTarget.scrollLeft=p,setTimeout(()=>_=!1,300)}})}u.on(this.$container,"scroll",_=>{let c=[];const g=this.bars.map(({group:$})=>$.getAttribute("data-id"));let p;i&&(p=_.currentTarget.scrollLeft-i),this.current_date=l.add(this.gantt_start,_.currentTarget.scrollLeft/this.config.column_width*this.config.step,this.config.unit);let w=this.config.view_mode.upper_text(this.current_date,null,this.options.language),m=this.upperTexts.find($=>$.textContent===w);this.current_date=l.add(this.gantt_start,(_.currentTarget.scrollLeft+m.clientWidth)/this.config.column_width*this.config.step,this.config.unit),w=this.config.view_mode.upper_text(this.current_date,null,this.options.language),m=this.upperTexts.find($=>$.textContent===w),m!==this.$current&&(this.$current&&this.$current.classList.remove("current-upper"),m.classList.add("current-upper"),this.$current=m),i=_.currentTarget.scrollLeft;let[k,y,N]=this.get_start_end_positions();i>N+100?(this.$adjust.innerHTML="&larr;",this.$adjust.classList.remove("hide"),this.$adjust.onclick=()=>{this.$container.scrollTo({left:y,behavior:"smooth"})}):i+_.currentTarget.offsetWidth<k-100?(this.$adjust.innerHTML="&rarr;",this.$adjust.classList.remove("hide"),this.$adjust.onclick=()=>{this.$container.scrollTo({left:k,behavior:"smooth"})}):this.$adjust.classList.add("hide"),p&&(c=g.map($=>this.get_bar($)),this.options.auto_move_label&&c.forEach($=>{$.update_label_position_on_horizontal_scroll({x:p,sx:_.currentTarget.scrollLeft})}))}),u.on(this.$svg,"mousemove",_=>{if(!h())return;const c=(_.offsetX||_.layerX)-e;a.forEach(g=>{const p=g.$bar;p.finaldx=this.get_snap_position(c,p.ox),this.hide_popup(),n?o===g.task.id?g.update_bar_position({x:p.ox+p.finaldx,width:p.owidth-p.finaldx}):g.update_bar_position({x:p.ox+p.finaldx}):s?o===g.task.id&&g.update_bar_position({width:p.owidth+p.finaldx}):t&&!this.options.readonly&&!this.options.readonly_dates&&g.update_bar_position({x:p.ox+p.finaldx})})}),document.addEventListener("mouseup",()=>{var _,c,g;t=!1,n=!1,s=!1,(g=(c=(_=this.$container.querySelector(".visible"))==null?void 0:_.classList)==null?void 0:c.remove)==null||g.call(c,"visible")}),u.on(this.$svg,"mouseup",_=>{const c=this.bar_being_dragged===!0;this.bar_being_dragged=null;const g=[];a.forEach(p=>{if(!p.$bar.finaldx){c&&p.set_action_completed();return}p.date_changed(),p.compute_progress(),p.set_action_completed(),g.push({task:p.task,start:p.task._start,end:l.add(p.task._end,-1,"second")})}),this.options.critical_path&&a.some(p=>p.$bar.finaldx)&&(this.calculate_critical_path(),this.update_arrow_critical_path()),g.length>0&&g.forEach(({task:p,start:w,end:m})=>{this.trigger_event("after_date_change",[p,w,m])})}),this.bind_bar_progress()}bind_bar_progress(){let t=0,e=null,i=null,n=null,s=null;u.on(this.$svg,"mousedown",".handle.progress",(a,h)=>{e=!0,t=a.offsetX||a.layerX;const _=u.closest(".bar-wrapper",h).getAttribute("data-id");i=this.get_bar(_),n=i.$bar_progress,s=i.$bar,n.finaldx=0,n.owidth=n.getWidth(),n.min_dx=-n.owidth,n.max_dx=s.getWidth()-n.getWidth()});const o=this.config.ignored_positions.map(a=>[a,a+this.config.column_width]);u.on(this.$svg,"mousemove",a=>{if(!e)return;let h=a.offsetX||a.layerX;if(h>t){let c=o.find(([g,p])=>h>=g&&h<p);for(;c;)h=c[1],c=o.find(([g,p])=>h>=g&&h<p)}else{let c=o.find(([g,p])=>h>g&&h<=p);for(;c;)h=c[0],c=o.find(([g,p])=>h>g&&h<=p)}let _=h-t;console.log(n),_>n.max_dx&&(_=n.max_dx),_<n.min_dx&&(_=n.min_dx),n.setAttribute("width",n.owidth+_),u.attr(i.$handle_progress,"cx",n.getEndX()),n.finaldx=_}),u.on(this.$svg,"mouseup",()=>{e=!1,n&&n.finaldx&&(n.finaldx=0,i.progress_changed(),i.set_action_completed(),i=null,n=null,s=null)})}get_all_dependent_tasks(t){let e=[],i=[t];for(;i.length;){const n=i.reduce((s,o)=>(s=s.concat(this.dependency_map[o]),s),[]);e=e.concat(n),i=n.filter(s=>!i.includes(s))}return e.filter(Boolean)}update_dependent_tasks_by_type(t){const e=t.task.dependencies_type||this.options.dependencies_type,i=[];return e==="fixed"||(this.dependency_map[t.task.id]||[]).forEach(s=>{const o=this.get_bar(s);if(!o)return;const a=o.task,h=a.dependencies_type||this.options.dependencies_type;let d,_;const c=l.diff(a._end,a._start,"hour");let g=!1;switch(h){case"finish-to-start":t.task._end>a._start&&(d=new Date(t.task._end),_=l.add(d,c,"hour"),g=!0);break;case"start-to-start":t.task._start>a._start&&(d=new Date(t.task._start),_=l.add(d,c,"hour"),g=!0);break;case"finish-to-finish":t.task._end>a._end&&(_=new Date(t.task._end),d=l.add(_,-c,"hour"),g=!0);break;case"start-to-finish":t.task._start>a._end&&(_=new Date(t.task._start),d=l.add(_,-c,"hour"),g=!0);break;default:return}if(!g)return;a._start=d,a._end=_,o.compute_x(),o.compute_duration(),o.update_bar_position({x:o.x,width:o.width}),this.trigger_event("date_change",[a,d,l.add(_,-1,"second")]),i.push({task:a,start:d,end:l.add(_,-1,"second")});const p=this.update_dependent_tasks_by_type(o);i.push(...p)}),i}get_snap_position(t,e){let i=1;const n=this.options.snap_at||this.config.view_mode.snap_at||"1d";if(n!=="unit"){const{duration:_,scale:c}=l.parse_duration(n);i=l.convert_scales(this.config.view_mode.step,c)/_}const s=t%(this.config.column_width/i);let o=t-s+(s<this.config.column_width/i*2?0:this.config.column_width/i),a=e+o;const h=o>0?1:-1;let d=this.get_ignored_region(a,h);for(;d.length;)a+=this.config.column_width*h,d=this.get_ignored_region(a,h),d.length||(a-=this.config.column_width*h);return a-e}get_ignored_region(t,e=1){return e===1?this.config.ignored_positions.filter(i=>t>i&&t<=i+this.config.column_width):this.config.ignored_positions.filter(i=>t>=i&&t<i+this.config.column_width)}unselect_all(){this.popup&&this.popup.parent.classList.add("hide"),this.$container.querySelectorAll(".date-range-highlight").forEach(t=>t.classList.add("hide"))}view_is(t){return typeof t=="string"?this.config.view_mode.name===t:Array.isArray(t)?t.some(view_is):this.config.view_mode.name===t.name}get_task(t){return this.tasks.find(e=>e.id===t)}get_bar(t){return this.bars.find(e=>e.task.id===t)}show_popup(t){this.options.popup!==!1&&(this.popup||(this.popup=new F(this.$popup_wrapper,this.options.popup,this)),this.popup.show(t))}hide_popup(){this.popup&&this.popup.hide()}trigger_event(t,e){this.options["on_"+t]&&this.options["on_"+t].apply(this,e)}get_oldest_starting_date(){return this.tasks.length?this.tasks.map(t=>t._start).reduce((t,e)=>e<=t?e:t):new Date}clear(){var t,e,i,n,s,o,a,h,d,_;this.$svg.innerHTML="",(e=(t=this.$header)==null?void 0:t.remove)==null||e.call(t),(n=(i=this.$side_header)==null?void 0:i.remove)==null||n.call(i),(o=(s=this.$current_highlight)==null?void 0:s.remove)==null||o.call(s),(h=(a=this.$extras)==null?void 0:a.remove)==null||h.call(a),(_=(d=this.popup)==null?void 0:d.hide)==null||_.call(d)}}X.VIEW_MODE={HOUR:b[0],QUARTER_DAY:b[1],HALF_DAY:b[2],DAY:b[3],WEEK:b[4],MONTH:b[5],YEAR:b[6]};function j(r){return r.name+"_"+Math.random().toString(36).slice(2,12)}function D(r){return r.replaceAll(" ","_").replaceAll(":","_").replaceAll(".","_")}return X});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workiom/frappe-gantt",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "A simple, modern, interactive gantt library for the web",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/arrow.js CHANGED
@@ -6,6 +6,7 @@ export default class Arrow {
6
6
  this.from_task = from_task;
7
7
  this.to_task = to_task;
8
8
  this.is_critical = this.check_critical_path();
9
+ this.is_invalid = this.check_invalid_dependency();
9
10
 
10
11
  this.calculate_path();
11
12
  this.draw();
@@ -19,6 +20,39 @@ export default class Arrow {
19
20
  this.to_task.task._is_critical === true;
20
21
  }
21
22
 
23
+ check_invalid_dependency() {
24
+ const dependencies_type = this.to_task.task.dependencies_type ||
25
+ this.gantt.options.dependencies_type;
26
+
27
+ // Fixed dependencies use old logic
28
+ if (dependencies_type === 'fixed') {
29
+ return this.to_task.$bar.getX() < this.from_task.$bar.getX();
30
+ }
31
+
32
+ const parent_task = this.from_task.task;
33
+ const child_task = this.to_task.task;
34
+
35
+ switch(dependencies_type) {
36
+ case 'finish-to-start':
37
+ // Child task cannot start before parent finishes
38
+ return child_task._start < parent_task._end;
39
+
40
+ case 'start-to-start':
41
+ // Child task cannot start before parent starts
42
+ return child_task._start < parent_task._start;
43
+
44
+ case 'finish-to-finish':
45
+ // Child task cannot finish before parent finishes
46
+ return child_task._end < parent_task._end;
47
+
48
+ case 'start-to-finish':
49
+ // Child task cannot finish before parent starts
50
+ return child_task._end < parent_task._start;
51
+ }
52
+
53
+ return false;
54
+ }
55
+
22
56
  calculate_path() {
23
57
  let start_x =
24
58
  this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;
@@ -98,16 +132,35 @@ export default class Arrow {
98
132
  }
99
133
 
100
134
  draw() {
135
+ let arrowClass = '';
136
+ if (this.is_invalid) {
137
+ arrowClass = 'arrow-invalid';
138
+ } else if (this.is_critical) {
139
+ arrowClass = 'arrow-critical';
140
+ }
141
+
101
142
  this.element = createSVG('path', {
102
143
  d: this.path,
103
144
  'data-from': this.from_task.task.id,
104
145
  'data-to': this.to_task.task.id,
105
- class: this.is_critical ? 'arrow-critical' : '',
146
+ class: arrowClass,
106
147
  });
107
148
  }
108
149
 
109
150
  update() {
110
151
  this.calculate_path();
111
152
  this.element.setAttribute('d', this.path);
153
+
154
+ // Update invalid state
155
+ this.is_invalid = this.check_invalid_dependency();
156
+
157
+ // Update class
158
+ let arrowClass = '';
159
+ if (this.is_invalid) {
160
+ arrowClass = 'arrow-invalid';
161
+ } else if (this.is_critical) {
162
+ arrowClass = 'arrow-critical';
163
+ }
164
+ this.element.setAttribute('class', arrowClass);
112
165
  }
113
166
  }
package/src/bar.js CHANGED
@@ -184,6 +184,11 @@ export default class Bar {
184
184
  this.gantt.config.step) *
185
185
  this.gantt.config.column_width;
186
186
 
187
+ // Remove existing date highlight element if it exists to avoid duplicates
188
+ if (this.$date_highlight && this.$date_highlight.parentNode) {
189
+ this.$date_highlight.parentNode.removeChild(this.$date_highlight);
190
+ }
191
+
187
192
  let $date_highlight = this.gantt.create_el({
188
193
  classes: `date-range-highlight hide highlight-${this.task.id}`,
189
194
  width: this.width,
@@ -384,15 +389,15 @@ export default class Bar {
384
389
  if (this.invalid || this.gantt.options.readonly) return;
385
390
 
386
391
  const bar = this.$bar;
387
- const handle_width = 3;
392
+ const handle_width = 8;
388
393
  this.handles = [];
389
394
  if (!this.gantt.options.readonly_dates) {
390
395
  this.handles.push(
391
396
  createSVG('rect', {
392
- x: bar.getEndX() - handle_width / 2,
393
- y: bar.getY() + this.height / 4,
397
+ x: bar.getEndX() - handle_width,
398
+ y: bar.getY() + (this.height - this.height * 0.8) / 2,
394
399
  width: handle_width,
395
- height: this.height / 2,
400
+ height: this.height * 0.8,
396
401
  rx: 2,
397
402
  ry: 2,
398
403
  class: 'handle right',
@@ -402,10 +407,10 @@ export default class Bar {
402
407
 
403
408
  this.handles.push(
404
409
  createSVG('rect', {
405
- x: bar.getX() - handle_width / 2,
406
- y: bar.getY() + this.height / 4,
410
+ x: bar.getX() - handle_width,
411
+ y: bar.getY() + (this.height - this.height * 0.8) / 2,
407
412
  width: handle_width,
408
- height: this.height / 2,
413
+ height: this.height * 0.8,
409
414
  rx: 2,
410
415
  ry: 2,
411
416
  class: 'handle left',
@@ -619,10 +624,7 @@ export default class Bar {
619
624
  const bar = this.$bar;
620
625
 
621
626
  if (x) {
622
- // Validate against dependency constraints
623
- if (!this.validate_dependency_constraints(x, width)) {
624
- return;
625
- }
627
+ // Allow invalid positions, but track the state
626
628
  this.update_attr(bar, 'x', x);
627
629
  this.x = x;
628
630
  this.$date_highlight.style.left = x + 'px';
package/src/index.js CHANGED
@@ -1443,12 +1443,20 @@ export default class Gantt {
1443
1443
  });
1444
1444
 
1445
1445
  $.on(this.$svg, 'mouseup', (e) => {
1446
+ const was_dragging = this.bar_being_dragged === true;
1446
1447
  this.bar_being_dragged = null;
1447
1448
  const tasks_changed = [];
1448
1449
 
1449
1450
  bars.forEach((bar) => {
1450
1451
  const $bar = bar.$bar;
1451
- if (!$bar.finaldx) return;
1452
+ if (!$bar.finaldx) {
1453
+ // No net movement, but if user was dragging, mark as completed
1454
+ // This prevents click events from firing after drag gestures
1455
+ if (was_dragging) {
1456
+ bar.set_action_completed();
1457
+ }
1458
+ return;
1459
+ }
1452
1460
  bar.date_changed();
1453
1461
  bar.compute_progress();
1454
1462
  bar.set_action_completed();
@@ -1462,12 +1470,13 @@ export default class Gantt {
1462
1470
 
1463
1471
  // Update dependent tasks based on dependencies_type
1464
1472
  // Only update for the parent bar that was actually moved
1465
- const parent_bar = this.get_bar(parent_bar_id);
1466
- if (parent_bar && parent_bar.$bar.finaldx) {
1467
- const dependent_changes = this.update_dependent_tasks_by_type(parent_bar);
1468
- // Add dependent task changes to the list
1469
- tasks_changed.push(...dependent_changes);
1470
- }
1473
+ // DISABLED: Allow invalid dependencies instead of auto-updating
1474
+ // const parent_bar = this.get_bar(parent_bar_id);
1475
+ // if (parent_bar && parent_bar.$bar.finaldx) {
1476
+ // const dependent_changes = this.update_dependent_tasks_by_type(parent_bar);
1477
+ // // Add dependent task changes to the list
1478
+ // tasks_changed.push(...dependent_changes);
1479
+ // }
1471
1480
 
1472
1481
  // Recalculate critical path if enabled and any bar was moved
1473
1482
  if (this.options.critical_path && bars.some(bar => bar.$bar.finaldx)) {
@@ -8,7 +8,8 @@
8
8
  --g-text-light-dark: #ececec;
9
9
  --g-text-color-dark: #f7f7f7;
10
10
  --g-progress-color: #8a8aff;
11
- --g-arrow-critical-color-dark: #ff9999;
11
+ --g-arrow-critical-color-dark: #f5c044;
12
+ --g-arrow-invalid-color-dark: #ff7676;
12
13
  }
13
14
 
14
15
  .dark > .gantt-container .gantt {
@@ -32,6 +33,10 @@
32
33
  stroke: var(--g-arrow-critical-color-dark);
33
34
  }
34
35
 
36
+ & .arrow-invalid {
37
+ stroke: var(--g-arrow-invalid-color-dark);
38
+ }
39
+
35
40
  & .bar {
36
41
  fill: var(--g-bar-color-dark);
37
42
  stroke: none;
@@ -272,6 +272,10 @@
272
272
  stroke: var(--g-arrow-critical-color);
273
273
  }
274
274
 
275
+ & .arrow-invalid {
276
+ stroke: var(--g-arrow-invalid-color);
277
+ }
278
+
275
279
  & .bar-wrapper .bar {
276
280
  fill: var(--g-bar-color);
277
281
  stroke: var(--g-bar-border);
@@ -1,6 +1,7 @@
1
1
  :root {
2
2
  --g-arrow-color: #1f2937;
3
- --g-arrow-critical-color: #ff7676;
3
+ --g-arrow-critical-color: #f5c044;
4
+ --g-arrow-invalid-color: #ff7676;
4
5
  --g-bar-color: #fff;
5
6
  --g-bar-border: #fff;
6
7
  --g-tick-color-thick: #ededed;
@@ -11,7 +12,7 @@
11
12
  --g-text-light: #fff;
12
13
  --g-text-dark: #171717;
13
14
  --g-progress-color: #dbdbdb;
14
- --g-handle-color: #37352f;
15
+ --g-handle-color: transparent;
15
16
  --g-weekend-label-color: #dcdce4;
16
17
  --g-expected-progress: #c4c4e9;
17
18
  --g-header-background: #fff;