diff --git a/dist/frappe-gantt.es.js b/dist/frappe-gantt.es.js
index 755b6af3..5dc8c3be 100644
--- a/dist/frappe-gantt.es.js
+++ b/dist/frappe-gantt.es.js
@@ -36,54 +36,54 @@ const k = "year", D = "month", $ = "day", E = "hour", Y = "minute", A = "second"
return n;
if (typeof n == "string") {
let s, i;
- const r = n.split(" ");
- s = r[0].split(t).map((a) => parseInt(a, 10)), i = r[1] && r[1].split(e), s[1] = s[1] ? s[1] - 1 : 0;
- let o = s;
- return i && i.length && (i.length === 4 && (i[3] = "0." + i[3], i[3] = parseFloat(i[3]) * 1e3), o = o.concat(i)), new Date(...o);
+ const o = n.split(" ");
+ s = o[0].split(t).map((a) => parseInt(a, 10)), i = o[1] && o[1].split(e), s[1] = s[1] ? s[1] - 1 : 0;
+ let r = s;
+ return i && i.length && (i.length === 4 && (i[3] = "0." + i[3], i[3] = parseFloat(i[3]) * 1e3), r = r.concat(i)), new Date(...r);
}
},
to_string(n, t = !1) {
if (!(n instanceof Date))
throw new TypeError("Invalid argument type");
- const e = this.get_date_values(n).map((r, o) => (o === 1 && (r = r + 1), o === 6 ? v(r + "", 3, "0") : v(r + "", 2, "0"))), s = `${e[0]}-${e[1]}-${e[2]}`, i = `${e[3]}:${e[4]}:${e[5]}.${e[6]}`;
+ const e = this.get_date_values(n).map((o, r) => (r === 1 && (o = o + 1), r === 6 ? v(o + "", 3, "0") : v(o + "", 2, "0"))), s = `${e[0]}-${e[1]}-${e[2]}`, i = `${e[3]}:${e[4]}:${e[5]}.${e[6]}`;
return s + (t ? " " + i : "");
},
format(n, t = "YYYY-MM-DD HH:mm:ss.SSS", e = "en") {
const i = new Intl.DateTimeFormat(e, {
month: "long"
- }).format(n), r = i.charAt(0).toUpperCase() + i.slice(1), o = this.get_date_values(n).map((g) => v(g, 2, 0)), a = {
- YYYY: o[0],
- MM: v(+o[1] + 1, 2, 0),
- DD: o[2],
- HH: o[3],
- mm: o[4],
- ss: o[5],
- SSS: o[6],
- D: o[2],
- MMMM: r,
- MMM: S[r]
+ }).format(n), o = i.charAt(0).toUpperCase() + i.slice(1), r = this.get_date_values(n).map((g) => v(g, 2, 0)), a = {
+ YYYY: r[0],
+ MM: v(+r[1] + 1, 2, 0),
+ DD: r[2],
+ HH: r[3],
+ mm: r[4],
+ ss: r[5],
+ SSS: r[6],
+ D: r[2],
+ MMMM: o,
+ MMM: S[o]
};
- let d = t;
- const p = [];
+ let p = t;
+ const d = [];
return Object.keys(a).sort((g, c) => c.length - g.length).forEach((g) => {
- d.includes(g) && (d = d.replaceAll(g, `$${p.length}`), p.push(a[g]));
- }), p.forEach((g, c) => {
- d = d.replaceAll(`$${c}`, g);
- }), d;
+ p.includes(g) && (p = p.replaceAll(g, `$${d.length}`), d.push(a[g]));
+ }), d.forEach((g, c) => {
+ p = p.replaceAll(`$${c}`, g);
+ }), p;
},
diff(n, t, e = $) {
- let s, i, r, o, a, d, p;
- s = n - t, i = s / 1e3, o = i / 60, r = o / 60, a = r / 24;
+ let s, i, o, r, a, p, d;
+ s = n - t, i = s / 1e3, r = i / 60, o = r / 60, a = o / 24;
const g = n.getFullYear() - t.getFullYear(), c = n.getMonth() - t.getMonth();
- return d = g * 12 + c, n.getDate() < t.getDate() && d--, p = d / 12, e.endsWith("s") || (e += "s"), Math.floor(
+ return p = g * 12 + c, n.getDate() < t.getDate() && p--, d = p / 12, e.endsWith("s") || (e += "s"), Math.floor(
{
milliseconds: s,
seconds: i,
- minutes: o,
- hours: r,
+ minutes: r,
+ hours: o,
days: a,
- months: d,
- years: p
+ months: p,
+ years: d
}[e]
);
},
@@ -117,9 +117,9 @@ const k = "year", D = "month", $ = "day", E = "hour", Y = "minute", A = "second"
[A]: 1,
[L]: 0
};
- function s(r) {
- const o = e[t];
- return e[r] <= o;
+ function s(o) {
+ const r = e[t];
+ return e[o] <= r;
}
const i = [
n.getFullYear(),
@@ -169,19 +169,19 @@ function u(n, t) {
function H(n, t, e, s) {
const i = W(n, t, e, s);
if (i === n) {
- const r = document.createEvent("HTMLEvents");
- r.initEvent("click", !0, !0), r.eventName = "click", i.dispatchEvent(r);
+ const o = document.createEvent("HTMLEvents");
+ o.initEvent("click", !0, !0), o.eventName = "click", i.dispatchEvent(o);
}
}
-function W(n, t, e, s, i = "0.4s", r = "0.1s") {
- const o = n.querySelector("animate");
- if (o)
- return _.attr(o, {
+function W(n, t, e, s, i = "0.4s", o = "0.1s") {
+ const r = n.querySelector("animate");
+ if (r)
+ return _.attr(r, {
attributeName: t,
from: e,
to: s,
dur: i,
- begin: "click + " + r
+ begin: "click + " + o
// artificial click
}), n;
const a = u("animate", {
@@ -189,7 +189,7 @@ function W(n, t, e, s, i = "0.4s", r = "0.1s") {
from: e,
to: s,
dur: i,
- begin: r,
+ begin: o,
calcMode: "spline",
values: e + ";" + s,
keyTimes: "0; 1",
@@ -219,8 +219,8 @@ _.bind = (n, t, e) => {
};
_.delegate = (n, t, e, s) => {
n.addEventListener(t, function(i) {
- const r = i.target.closest(e);
- r && (i.delegatedTarget = r, s.call(this, i, r));
+ const o = i.target.closest(e);
+ o && (i.delegatedTarget = o, s.call(this, i, o));
});
};
_.closest = (n, t) => t ? t.matches(n) ? t : _.closest(n, t.parentNode) : null;
@@ -399,29 +399,38 @@ class O {
}
setup_click_event() {
let t = this.task.id;
- _.on(this.group, "mouseover", (s) => {
+ if (_.on(this.group, "mouseover", (e) => {
this.gantt.trigger_event("hover", [
this.task,
- s.screenX,
- s.screenY,
- s
+ e.screenX,
+ e.screenY,
+ e
]);
- });
- let e;
- _.on(
- this.group,
- "mouseenter",
- (s) => e = setTimeout(() => {
- this.show_popup(s.offsetX || s.layerX), document.getElementById(
+ }), this.gantt.options.popup_on === "click") {
+ let e = !1;
+ _.on(this.group, "click", (s) => {
+ console.log(e), e ? this.gantt.hide_popup() : (this.show_popup(s.offsetX || s.layerX), document.getElementById(
`${t}-highlight`
- ).style.display = "block";
- }, 200)
- ), _.on(this.group, "mouseleave", () => {
- var s, i;
- clearTimeout(e), (i = (s = this.gantt.popup) == null ? void 0 : s.hide) == null || i.call(s), document.getElementById(`${t}-highlight`).style.display = "none";
- }), _.on(this.group, "click", () => {
+ ).style.display = "block"), e = !e;
+ });
+ } else {
+ let e;
+ _.on(
+ this.group,
+ "mouseenter",
+ (s) => e = setTimeout(() => {
+ this.show_popup(s.offsetX || s.layerX), document.getElementById(
+ `${t}-highlight`
+ ).style.display = "block";
+ }, 200)
+ ), _.on(this.group, "mouseleave", () => {
+ var s, i;
+ clearTimeout(e), (i = (s = this.gantt.popup) == null ? void 0 : s.hide) == null || i.call(s), document.getElementById(`${t}-highlight`).style.display = "none";
+ });
+ }
+ _.on(this.group, "click", () => {
this.gantt.trigger_event("click", [this.task]);
- }), _.on(this.group, "dblclick", (s) => {
+ }), _.on(this.group, "dblclick", (e) => {
this.action_completed || (this.group.classList.remove("active"), this.gantt.popup && this.gantt.popup.parent.classList.remove("hidden"), this.gantt.trigger_event("double_click", [this.task]));
});
}
@@ -448,7 +457,7 @@ class O {
update_bar_position({ x: t = null, width: e = null }) {
const s = this.$bar;
if (t) {
- if (!this.task.dependencies.map((o) => this.gantt.get_bar(o).$bar.getX()).reduce((o, a) => t >= a, t)) {
+ if (!this.task.dependencies.map((r) => this.gantt.get_bar(r).$bar.getX()).reduce((r, a) => t >= a, t)) {
e = null;
return;
}
@@ -457,9 +466,9 @@ class O {
e && (this.update_attr(s, "width", e), this.$date_highlight.style.width = e + "px"), this.update_label_position(), this.update_handle_position(), this.gantt.options.show_expected_progress && (this.date_changed(), this.compute_duration(), this.update_expected_progressbar_position()), this.update_progressbar_position(), this.update_arrow_position();
}
update_label_position_on_horizontal_scroll({ x: t, sx: e }) {
- const s = document.querySelector(".gantt-container"), i = this.group.querySelector(".bar-label"), r = this.group.querySelector(".bar-img") || "", o = this.bar_group.querySelector(".img_mask") || "";
- let a = this.$bar.getX() + this.$bar.getWidth(), d = i.getX() + t, p = r && r.getX() + t || 0, g = r && r.getBBox().width + 7 || 7, c = d + i.getBBox().width + 7, f = e + s.clientWidth / 2;
- i.classList.contains("big") || (c < a && t > 0 && c < f || d - g > this.$bar.getX() && t < 0 && c > f) && (i.setAttribute("x", d), r && (r.setAttribute("x", p), o.setAttribute("x", p)));
+ const s = document.querySelector(".gantt-container"), i = this.group.querySelector(".bar-label"), o = this.group.querySelector(".bar-img") || "", r = this.bar_group.querySelector(".img_mask") || "";
+ let a = this.$bar.getX() + this.$bar.getWidth(), p = i.getX() + t, d = o && o.getX() + t || 0, g = o && o.getBBox().width + 7 || 7, c = p + i.getBBox().width + 7, f = e + s.clientWidth / 2;
+ i.classList.contains("big") || (c < a && t > 0 && c < f || p - g > this.$bar.getX() && t < 0 && c > f) && (i.setAttribute("x", p), o && (o.setAttribute("x", d), r.setAttribute("x", d)));
}
date_changed() {
let t = !1;
@@ -490,12 +499,12 @@ class O {
i,
"minute"
));
- const r = t.getWidth() / this.gantt.options.column_width, o = h.add(
+ const o = t.getWidth() / this.gantt.options.column_width, r = h.add(
s,
- r * this.gantt.options.step,
+ o * this.gantt.options.step,
"hour"
);
- return { new_start_date: s, new_end_date: o };
+ return { new_start_date: s, new_end_date: r };
}
compute_progress() {
const t = this.$bar_progress.getWidth() / this.$bar.getWidth() * 100;
@@ -506,15 +515,15 @@ class O {
}
compute_x() {
const { step: t, column_width: e } = this.gantt.options, s = this.task._start, i = this.gantt.gantt_start;
- let o = h.diff(s, i, "hour") / t * e;
+ let r = h.diff(s, i, "hour") / t * e;
if (this.gantt.view_is("Month")) {
- const a = h.diff(s, i, "month") * 30, d = Math.min(
+ const a = h.diff(s, i, "month") * 30, p = Math.min(
29,
h.format(s, "DD")
);
- o = (a + d) * e / 30;
+ r = (a + p) * e / 30;
}
- this.x = o;
+ this.x = r;
}
compute_y() {
this.y = this.gantt.options.header_height + this.gantt.options.padding + this.task._index * (this.height + this.gantt.options.padding);
@@ -543,20 +552,20 @@ class O {
}
update_label_position() {
const t = this.bar_group.querySelector(".img_mask") || "", e = this.$bar, s = this.group.querySelector(".bar-label"), i = this.group.querySelector(".bar-img");
- let r = 5, o = this.image_size + 10;
- const a = s.getBBox().width, d = e.getWidth();
- a > d ? (s.classList.add("big"), i ? (i.setAttribute("x", e.getX() + e.getWidth() + r), t.setAttribute(
+ let o = 5, r = this.image_size + 10;
+ const a = s.getBBox().width, p = e.getWidth();
+ a > p ? (s.classList.add("big"), i ? (i.setAttribute("x", e.getX() + e.getWidth() + o), t.setAttribute(
"x",
- e.getX() + e.getWidth() + r
+ e.getX() + e.getWidth() + o
), s.setAttribute(
"x",
- e.getX() + e.getWidth() + o
- )) : s.setAttribute("x", e.getX() + e.getWidth() + r)) : (s.classList.remove("big"), i ? (i.setAttribute("x", e.getX() + r), t.setAttribute("x", e.getX() + r), s.setAttribute(
+ e.getX() + e.getWidth() + r
+ )) : s.setAttribute("x", e.getX() + e.getWidth() + o)) : (s.classList.remove("big"), i ? (i.setAttribute("x", e.getX() + o), t.setAttribute("x", e.getX() + o), s.setAttribute(
"x",
- e.getX() + d / 2 + o
+ e.getX() + p / 2 + r
)) : s.setAttribute(
"x",
- e.getX() + d / 2 - a / 2
+ e.getX() + p / 2 - a / 2
));
}
update_handle_position() {
@@ -582,25 +591,25 @@ class C {
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;
- const s = this.gantt.options.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, i = this.to_task.$bar.getX() - this.gantt.options.padding / 2 - 7, r = this.gantt.options.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, o = this.from_task.task._index > this.to_task.task._index, a = this.gantt.options.arrow_curve, d = o ? 1 : 0, p = o ? -a : a, g = o ? r + this.gantt.options.arrow_curve : r - this.gantt.options.arrow_curve;
+ const s = this.gantt.options.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, i = this.to_task.$bar.getX() - this.gantt.options.padding / 2 - 7, o = this.gantt.options.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, r = this.from_task.task._index > this.to_task.task._index, a = this.gantt.options.arrow_curve, p = r ? 1 : 0, d = r ? -a : a, g = r ? o + this.gantt.options.arrow_curve : o - this.gantt.options.arrow_curve;
if (this.path = `
M ${t} ${s}
V ${g}
- a ${a} ${a} 0 0 ${d} ${a} ${p}
- L ${i} ${r}
+ a ${a} ${a} 0 0 ${p} ${a} ${d}
+ L ${i} ${o}
m -5 -5
l 5 5
l -5 5`, this.to_task.$bar.getX() < this.from_task.$bar.getX() + this.gantt.options.padding) {
- const c = this.gantt.options.padding / 2 - a, f = this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - p, w = this.to_task.$bar.getX() - this.gantt.options.padding;
+ const c = this.gantt.options.padding / 2 - a, f = this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - d, w = this.to_task.$bar.getX() - this.gantt.options.padding;
this.path = `
M ${t} ${s}
v ${c}
a ${a} ${a} 0 0 1 -${a} ${a}
H ${w}
- a ${a} ${a} 0 0 ${d} -${a} ${p}
+ a ${a} ${a} 0 0 ${p} -${a} ${d}
V ${f}
- a ${a} ${a} 0 0 ${d} ${a} ${p}
- L ${i} ${r}
+ a ${a} ${a} 0 0 ${p} ${a} ${d}
+ L ${i} ${o}
m -5 -5
l 5 5
l -5 5`;
@@ -637,8 +646,9 @@ class N {
i += '
', this.parent.innerHTML = i, this.pointer = this.parent.querySelector(".pointer");
} else
this.title.innerHTML = t.title, this.subtitle.innerHTML = t.subtitle;
+ console.log("hey in");
let s;
- e instanceof HTMLElement ? s = e.getBoundingClientRect() : e instanceof SVGElement && (s = t.target_element.getBBox()), this.parent.style.left = t.x - this.parent.clientWidth / 2 + "px", this.parent.style.top = s.y + s.height + 10 + "px", this.pointer.style.left = this.parent.clientWidth / 2 + "px", this.pointer.style.top = "-15px", this.parent.style.opacity = 1;
+ e instanceof HTMLElement ? s = e.getBoundingClientRect() : e instanceof SVGElement && (s = t.target_element.getBBox()), this.parent.style.left = t.x - this.parent.clientWidth / 2 + "px", this.parent.style.top = s.y + s.height + 10 + "px", this.parent.classList.remove("hidden"), this.pointer.style.left = this.parent.clientWidth / 2 + "px", this.pointer.style.top = "-15px", this.parent.style.opacity = 1;
}
hide() {
this.parent.style.opacity = 0, this.parent.style.left = 0;
@@ -672,6 +682,7 @@ const l = {
date_format: "YYYY-MM-DD",
show_expected_progress: !1,
popup: null,
+ popup_on: "hover",
language: "en",
readonly: !1,
progress_readonly: !1,
@@ -714,19 +725,19 @@ class B {
setup_tasks(t) {
this.tasks = t.map((e, s) => {
if (e._start = h.parse(e.start), e.end === void 0 && e.duration !== void 0 && (e.end = e._start, e.duration.split(" ").forEach((a) => {
- let { duration: d, scale: p } = h.parse_duration(a);
- e.end = h.add(e.end, d, p);
+ let { duration: p, scale: d } = h.parse_duration(a);
+ e.end = h.add(e.end, p, d);
})), e._end = h.parse(e.end), h.diff(e._end, e._start, "year") < 0)
throw Error(
"start of task can't be after end of task: in task #, " + (s + 1)
);
if (h.diff(e._end, e._start, "year") > 10 && (e.end = null), e._index = s, !e.start && !e.end) {
- const o = h.today();
- e._start = o, e._end = h.add(o, 2, "day");
+ const r = h.today();
+ e._start = r, e._end = h.add(r, 2, "day");
}
- if (!e.start && e.end && (e._start = h.add(e._end, -2, "day")), e.start && !e.end && (e._end = h.add(e._start, 2, "day")), h.get_date_values(e._end).slice(3).every((o) => o === 0) && (e._end = h.add(e._end, 24, "hour")), (!e.start || !e.end) && (e.invalid = !0), typeof e.dependencies == "string" || !e.dependencies) {
- let o = [];
- e.dependencies && (o = e.dependencies.split(",").map((a) => a.trim().replaceAll(" ", "_")).filter((a) => a)), e.dependencies = o;
+ if (!e.start && e.end && (e._start = h.add(e._end, -2, "day")), e.start && !e.end && (e._end = h.add(e._start, 2, "day")), h.get_date_values(e._end).slice(3).every((r) => r === 0) && (e._end = h.add(e._end, 24, "hour")), (!e.start || !e.end) && (e.invalid = !0), typeof e.dependencies == "string" || !e.dependencies) {
+ let r = [];
+ e.dependencies && (r = e.dependencies.split(",").map((a) => a.trim().replaceAll(" ", "_")).filter((a) => a)), e.dependencies = r;
}
return e.id ? typeof e.id == "string" ? e.id = e.id.replaceAll(" ", "_") : e.id = `${e.id}` : e.id = F(e), e;
}), this.setup_dependencies();
@@ -756,21 +767,21 @@ class B {
let t, e;
this.gantt_start ? t = h.start_of(this.gantt_start, "day") : t = /* @__PURE__ */ new Date(), this.gantt_end ? e = h.start_of(this.gantt_end, "day") : e = /* @__PURE__ */ new Date();
let s;
- for (let [a, d] of Object.entries(l))
- d === this.options.view_mode && (s = a);
- const [i, r] = this.options.view_mode_padding[s].map(h.parse_duration);
+ for (let [a, p] of Object.entries(l))
+ p === this.options.view_mode && (s = a);
+ const [i, o] = this.options.view_mode_padding[s].map(h.parse_duration);
t = h.add(
t,
-i.duration,
i.scale
);
- let o;
- this.view_is(l.YEAR) ? o = "YYYY" : this.view_is(l.MONTH) ? o = "YYYY-MM" : this.view_is(l.DAY) ? o = "YYYY-MM-DD" : o = "YYYY-MM-DD HH", this.gantt_start = h.parse(
- h.format(t, o)
+ let r;
+ this.view_is(l.YEAR) ? r = "YYYY" : this.view_is(l.MONTH) ? r = "YYYY-MM" : this.view_is(l.DAY) ? r = "YYYY-MM-DD" : r = "YYYY-MM-DD HH", this.gantt_start = h.parse(
+ h.format(t, r)
), this.gantt_start.setHours(0, 0, 0, 0), this.gantt_end = h.add(
e,
- r.duration,
- r.scale
+ o.duration,
+ o.scale
);
}
setup_date_values() {
@@ -821,7 +832,7 @@ class B {
make_grid_rows() {
const t = u("g", { append_to: this.layers.grid }), e = this.dates.length * this.options.column_width, s = this.options.bar_height + this.options.padding;
let i = this.options.header_height + this.options.padding / 2;
- for (let r of this.tasks)
+ for (let o of this.tasks)
u("rect", {
x: 0,
y: i,
@@ -847,8 +858,8 @@ class B {
const s = document.createElement("option");
s.selected = !0, s.disabled = !0, s.textContent = "Mode", e.appendChild(s);
for (const i in l) {
- const r = document.createElement("option");
- r.value = l[i], r.textContent = l[i], e.appendChild(r);
+ const o = document.createElement("option");
+ o.value = l[i], o.textContent = l[i], e.appendChild(o);
}
e.addEventListener(
"change",
@@ -872,11 +883,11 @@ class B {
update_button_position() {
const t = this.$container.getBoundingClientRect(), e = this.$side_header.getBoundingClientRect(), { left: s, y: i } = this.$header.getBoundingClientRect();
e.top < t.top || e.bottom > t.bottom ? (this.$side_header.style.position = "absolute", this.$side_header.style.top = `${t.scrollTop + e.top}px`) : (this.$side_header.style.position = "fixed", this.$side_header.style.top = i + 10 + "px");
- const r = Math.min(
+ const o = Math.min(
this.$header.clientWidth,
this.$container.clientWidth
);
- this.$side_header.style.left = s + this.$container.scrollLeft + r - this.$side_header.clientWidth + "px", this.$today_button && (this.$today_button.style.left = `${t.left + 20}px`);
+ this.$side_header.style.left = s + this.$container.scrollLeft + o - this.$side_header.clientWidth + "px", this.$today_button && (this.$today_button.style.left = `${t.left + 20}px`);
}
make_grid_ticks() {
if (!["both", "vertical", "horizontal"].includes(this.options.lines))
@@ -884,26 +895,26 @@ class B {
let t = 0, e = this.options.header_height + this.options.padding / 2, s = (this.options.bar_height + this.options.padding) * this.tasks.length, i = u("g", {
class: "lines_layer",
append_to: this.layers.grid
- }), r = this.options.header_height + this.options.padding / 2;
- const o = this.dates.length * this.options.column_width, a = this.options.bar_height + this.options.padding;
+ }), o = this.options.header_height + this.options.padding / 2;
+ const r = this.dates.length * this.options.column_width, a = this.options.bar_height + this.options.padding;
if (this.options.lines !== "vertical")
- for (let d of this.tasks)
+ for (let p of this.tasks)
u("line", {
x1: 0,
- y1: r + a,
- x2: o,
- y2: r + a,
+ y1: o + a,
+ x2: r,
+ y2: o + a,
class: "row-line",
append_to: i
- }), r += a;
+ }), o += a;
if (this.options.lines !== "horizontal")
- for (let d of this.dates) {
- let p = "tick";
- this.view_is(l.DAY) && d.getDate() === 1 && (p += " thick"), this.view_is(l.WEEK) && d.getDate() >= 1 && d.getDate() < 8 && (p += " thick"), this.view_is(l.MONTH) && d.getMonth() % 3 === 0 && (p += " thick"), u("path", {
+ for (let p of this.dates) {
+ let d = "tick";
+ this.view_is(l.DAY) && p.getDate() === 1 && (d += " thick"), this.view_is(l.WEEK) && p.getDate() >= 1 && p.getDate() < 8 && (d += " thick"), this.view_is(l.MONTH) && p.getMonth() % 3 === 0 && (d += " thick"), u("path", {
d: `M ${t} ${e} v ${s}`,
- class: p,
+ class: d,
append_to: this.layers.grid
- }), this.view_is(l.MONTH) ? t += h.get_days_in_month(d) * this.options.column_width / 30 : t += this.options.column_width;
+ }), this.view_is(l.MONTH) ? t += h.get_days_in_month(p) * this.options.column_width / 30 : t += this.options.column_width;
}
}
highlightWeekends() {
@@ -933,20 +944,20 @@ class B {
};
}
for (let s of this.dates) {
- const i = /* @__PURE__ */ new Date(), r = new Date(s), o = new Date(s);
+ const i = /* @__PURE__ */ new Date(), o = new Date(s), r = new Date(s);
switch (t) {
case l.WEEK:
- o.setDate(s.getDate() + 7);
+ r.setDate(s.getDate() + 7);
break;
case l.MONTH:
- o.setMonth(s.getMonth() + 1);
+ r.setMonth(s.getMonth() + 1);
break;
case l.YEAR:
- o.setFullYear(s.getFullYear() + 1);
+ r.setFullYear(s.getFullYear() + 1);
break;
}
- if (i >= r && i <= o)
- return { x: e, date: r };
+ if (i >= o && i <= r)
+ return { x: e, date: o };
e += this.options.column_width;
}
return { x: e };
@@ -956,7 +967,7 @@ class B {
const { x: t, date: e } = this.computeGridHighlightDimensions(
this.options.view_mode
);
- if (!e || !this.dates.find((o) => o.getTime() == e.getTime()))
+ if (!e || !this.dates.find((r) => r.getTime() == e.getTime()))
return;
const s = this.options.header_height + this.options.padding / 2, i = (this.options.bar_height + this.options.padding) * this.tasks.length;
this.$current_highlight = this.create_el({
@@ -966,15 +977,15 @@ class B {
classes: "current-highlight",
append_to: this.$container
});
- let r = document.getElementById(
+ let o = document.getElementById(
h.format(e).replaceAll(" ", "_")
);
- r && (r.classList.add("current-date-highlight"), r.style.top = +r.style.top.slice(0, -2) - 4 + "px", r.style.left = +r.style.left.slice(0, -2) - 8 + "px");
+ o && (o.classList.add("current-date-highlight"), o.style.top = +o.style.top.slice(0, -2) - 4 + "px", o.style.left = +o.style.left.slice(0, -2) - 8 + "px");
}
}
- create_el({ left: t, top: e, width: s, height: i, id: r, classes: o, append_to: a }) {
- let d = document.createElement("div");
- return d.classList.add(o), d.style.top = e + "px", d.style.left = t + "px", r && (d.id = r), s && (d.style.width = i + "px"), i && (d.style.height = i + "px"), a.appendChild(d), d;
+ create_el({ left: t, top: e, width: s, height: i, id: o, classes: r, append_to: a }) {
+ let p = document.createElement("div");
+ return p.classList.add(r), p.style.top = e + "px", p.style.left = t + "px", o && (p.id = o), s && (p.style.width = i + "px"), i && (p.style.height = i + "px"), a.appendChild(p), p;
}
make_dates() {
this.upper_texts_x = {}, this.get_dates_to_draw().forEach((t, e) => {
@@ -995,8 +1006,8 @@ class B {
get_dates_to_draw() {
let t = null;
return this.dates.map((s, i) => {
- const r = this.get_date_info(s, t, i);
- return t = r, r;
+ const o = this.get_date_info(s, t, i);
+ return t = o, o;
});
}
get_date_info(t, e) {
@@ -1029,32 +1040,32 @@ class B {
Month_upper: t.getFullYear() !== s.getFullYear() ? h.format(t, "YYYY", this.options.language) : "",
Year_upper: t.getFullYear() !== s.getFullYear() ? h.format(t, "YYYY", this.options.language) : ""
};
- let r = this.view_is(l.MONTH) ? h.get_days_in_month(t) * this.options.column_width / 30 : this.options.column_width;
- const o = {
+ let o = this.view_is(l.MONTH) ? h.get_days_in_month(t) * this.options.column_width / 30 : this.options.column_width;
+ const r = {
x: e ? e.base_pos_x + e.column_width : 0,
lower_y: this.options.header_height - 20,
upper_y: this.options.header_height - 50
}, a = {
- Hour_lower: r / 2,
- Hour_upper: r * 12,
- "Quarter Day_lower": r / 2,
- "Quarter Day_upper": r * 2,
- "Half Day_lower": r / 2,
- "Half Day_upper": r,
- Day_lower: r / 2,
- Day_upper: r / 2,
- Week_lower: r / 2,
- Week_upper: r * 4 / 2,
- Month_lower: r / 2,
- Month_upper: r / 2,
- Year_lower: r / 2,
- Year_upper: r * 30 / 2
+ Hour_lower: o / 2,
+ Hour_upper: o * 12,
+ "Quarter Day_lower": o / 2,
+ "Quarter Day_upper": o * 2,
+ "Half Day_lower": o / 2,
+ "Half Day_upper": o,
+ Day_lower: o / 2,
+ Day_upper: o / 2,
+ Week_lower: o / 2,
+ Week_upper: o * 4 / 2,
+ Month_lower: o / 2,
+ Month_upper: o / 2,
+ Year_lower: o / 2,
+ Year_upper: o * 30 / 2
};
return {
date: t,
formatted_date: h.format(t).replaceAll(" ", "_"),
- column_width: r,
- base_pos_x: o.x,
+ column_width: o,
+ base_pos_x: r.x,
upper_text: this.options.lower_text ? this.options.upper_text(
t,
this.options.view_mode,
@@ -1065,10 +1076,10 @@ class B {
this.options.view_mode,
i[`${this.options.view_mode}_lower`]
) : i[`${this.options.view_mode}_lower`],
- upper_x: o.x + a[`${this.options.view_mode}_upper`],
- upper_y: o.upper_y,
- lower_x: o.x + a[`${this.options.view_mode}_lower`],
- lower_y: o.lower_y
+ upper_x: r.x + a[`${this.options.view_mode}_upper`],
+ upper_y: r.upper_y,
+ lower_x: r.x + a[`${this.options.view_mode}_lower`],
+ lower_y: r.lower_y
};
}
make_bars() {
@@ -1085,14 +1096,14 @@ class B {
const i = this.get_task(s);
if (!i)
return;
- const r = new C(
+ const o = new C(
this,
this.bars[i._index],
// from_task
this.bars[t._index]
// to_task
);
- return this.layers.arrow.appendChild(r.element), r;
+ return this.layers.arrow.appendChild(o.element), o;
}).filter(Boolean), this.arrows = this.arrows.concat(e);
}
}
@@ -1127,28 +1138,28 @@ class B {
});
}
bind_bar_events() {
- let t = !1, e = 0, s = 0, i = !1, r = !1, o = null, a = [];
+ let t = !1, e = 0, s = 0, i = !1, o = !1, r = null, a = [];
this.bar_being_dragged = null;
- function d() {
- return t || i || r;
+ function p() {
+ return t || i || o;
}
- this.$svg.onclick = (p) => {
- p.target.classList.contains("grid-row") && this.unselect_all();
- }, _.on(this.$svg, "mousedown", ".bar-wrapper, .handle", (p, g) => {
+ this.$svg.onclick = (d) => {
+ d.target.classList.contains("grid-row") && this.unselect_all();
+ }, _.on(this.$svg, "mousedown", ".bar-wrapper, .handle", (d, g) => {
const c = _.closest(".bar-wrapper", g);
- a.forEach((w) => w.group.classList.remove("active")), g.classList.contains("left") ? i = !0 : g.classList.contains("right") ? r = !0 : g.classList.contains("bar-wrapper") && (t = !0), c.classList.add("active"), this.popup && this.popup.parent.classList.add("hidden"), this.popup && this.popup.parent.classList.add("hidden"), e = p.offsetX || p.layerX, p.offsetY || p.layerY, o = c.getAttribute("data-id"), a = [
- o,
- ...this.get_all_dependent_tasks(o)
- ].map((w) => this.get_bar(w)), this.bar_being_dragged = o, a.forEach((w) => {
+ a.forEach((w) => w.group.classList.remove("active")), g.classList.contains("left") ? i = !0 : g.classList.contains("right") ? o = !0 : g.classList.contains("bar-wrapper") && (t = !0), c.classList.add("active"), this.popup && this.popup.parent.classList.add("hidden"), this.popup && this.popup.parent.classList.add("hidden"), e = d.offsetX || d.layerX, d.offsetY || d.layerY, r = c.getAttribute("data-id"), a = [
+ r,
+ ...this.get_all_dependent_tasks(r)
+ ].map((w) => this.get_bar(w)), this.bar_being_dragged = r, a.forEach((w) => {
const b = w.$bar;
b.ox = b.getX(), b.oy = b.getY(), b.owidth = b.getWidth(), b.finaldx = 0;
});
- }), _.on(this.$container, "scroll", (p) => {
+ }), _.on(this.$container, "scroll", (d) => {
let g = document.querySelectorAll(".bar-wrapper"), c = [];
const f = [];
let w;
- s && (w = p.currentTarget.scrollLeft - s);
- const b = p.currentTarget.scrollLeft / this.options.column_width * this.options.step / 24;
+ s && (w = d.currentTarget.scrollLeft - s);
+ const b = d.currentTarget.scrollLeft / this.options.column_width * this.options.step / 24;
let y = "D MMM";
["Year", "Month"].includes(this.options.view_mode) ? y = "YYYY" : ["Day", "Week"].includes(this.options.view_mode) ? y = "MMMM" : this.view_is("Half Day") ? y = "D" : this.view_is("Hour") && (y = "D MMMM");
let T = h.format(
@@ -1171,54 +1182,54 @@ class B {
}), w && (c = f.map((m) => this.get_bar(m)), this.options.auto_move_label && c.forEach((m) => {
m.update_label_position_on_horizontal_scroll({
x: w,
- sx: p.currentTarget.scrollLeft
+ sx: d.currentTarget.scrollLeft
});
- })), s = p.currentTarget.scrollLeft;
- }), _.on(this.$svg, "mousemove", (p) => {
- if (!d())
+ })), s = d.currentTarget.scrollLeft;
+ }), _.on(this.$svg, "mousemove", (d) => {
+ if (!p())
return;
- const g = (p.offsetX || p.layerX) - e;
+ const g = (d.offsetX || d.layerX) - e;
a.forEach((c) => {
const f = c.$bar;
- f.finaldx = this.get_snap_position(g), this.hide_popup(), i ? o === c.task.id ? c.update_bar_position({
+ f.finaldx = this.get_snap_position(g), this.hide_popup(), i ? r === c.task.id ? c.update_bar_position({
x: f.ox + f.finaldx,
width: f.owidth - f.finaldx
}) : c.update_bar_position({
x: f.ox + f.finaldx
- }) : r ? o === c.task.id && c.update_bar_position({
+ }) : o ? r === c.task.id && c.update_bar_position({
width: f.owidth + f.finaldx
}) : t && !this.options.readonly && !this.options.dates_readonly && c.update_bar_position({ x: f.ox + f.finaldx });
});
- }), document.addEventListener("mouseup", (p) => {
- t = !1, i = !1, r = !1;
- }), _.on(this.$svg, "mouseup", (p) => {
+ }), document.addEventListener("mouseup", (d) => {
+ t = !1, i = !1, o = !1;
+ }), _.on(this.$svg, "mouseup", (d) => {
this.bar_being_dragged = null, a.forEach((g) => {
g.$bar.finaldx && (g.date_changed(), g.set_action_completed());
});
}), this.bind_bar_progress();
}
bind_bar_progress() {
- let t = 0, e = null, s = null, i = null, r = null;
- _.on(this.$svg, "mousedown", ".handle.progress", (o, a) => {
- e = !0, t = o.offsetX || o.layerX, o.offsetY || o.layerY;
- const p = _.closest(".bar-wrapper", a).getAttribute("data-id");
- s = this.get_bar(p), i = s.$bar_progress, r = s.$bar, i.finaldx = 0, i.owidth = i.getWidth(), i.min_dx = -i.getWidth(), i.max_dx = r.getWidth() - i.getWidth();
- }), _.on(this.$svg, "mousemove", (o) => {
+ let t = 0, e = null, s = null, i = null, o = null;
+ _.on(this.$svg, "mousedown", ".handle.progress", (r, a) => {
+ e = !0, t = r.offsetX || r.layerX, r.offsetY || r.layerY;
+ const d = _.closest(".bar-wrapper", a).getAttribute("data-id");
+ s = this.get_bar(d), i = s.$bar_progress, o = s.$bar, i.finaldx = 0, i.owidth = i.getWidth(), i.min_dx = -i.getWidth(), i.max_dx = o.getWidth() - i.getWidth();
+ }), _.on(this.$svg, "mousemove", (r) => {
if (!e)
return;
- let a = (o.offsetX || o.layerX) - t;
+ let a = (r.offsetX || r.layerX) - t;
a > i.max_dx && (a = i.max_dx), a < i.min_dx && (a = i.min_dx);
- const d = s.$handle_progress;
- _.attr(i, "width", i.owidth + a), _.attr(d, "cx", i.getEndX()), i.finaldx = a;
+ const p = s.$handle_progress;
+ _.attr(i, "width", i.owidth + a), _.attr(p, "cx", i.getEndX()), i.finaldx = a;
}), _.on(this.$svg, "mouseup", () => {
- e = !1, i && i.finaldx && (i.finaldx = 0, s.progress_changed(), s.set_action_completed(), s = null, i = null, r = null);
+ e = !1, i && i.finaldx && (i.finaldx = 0, s.progress_changed(), s.set_action_completed(), s = null, i = null, o = null);
});
}
get_all_dependent_tasks(t) {
let e = [], s = [t];
for (; s.length; ) {
- const i = s.reduce((r, o) => (r = r.concat(this.dependency_map[o]), r), []);
- e = e.concat(i), s = i.filter((r) => !s.includes(r));
+ const i = s.reduce((o, r) => (o = o.concat(this.dependency_map[r]), o), []);
+ e = e.concat(i), s = i.filter((o) => !s.includes(o));
}
return e.filter(Boolean);
}
@@ -1266,8 +1277,8 @@ class B {
* @memberof Gantt
*/
clear() {
- var t, e, s, i, r, o;
- this.$svg.innerHTML = "", (e = (t = this.$header) == null ? void 0 : t.remove) == null || e.call(t), (i = (s = this.$current_highlight) == null ? void 0 : s.remove) == null || i.call(s), (o = (r = this.popup) == null ? void 0 : r.hide) == null || o.call(r);
+ var t, e, s, i, o, r;
+ this.$svg.innerHTML = "", (e = (t = this.$header) == null ? void 0 : t.remove) == null || e.call(t), (i = (s = this.$current_highlight) == null ? void 0 : s.remove) == null || i.call(s), (r = (o = this.popup) == null ? void 0 : o.hide) == null || r.call(o);
}
}
B.VIEW_MODE = l;
diff --git a/dist/frappe-gantt.umd.js b/dist/frappe-gantt.umd.js
index ff3fcb18..e792746e 100644
--- a/dist/frappe-gantt.umd.js
+++ b/dist/frappe-gantt.umd.js
@@ -1,8 +1,8 @@
-(function(y,x){typeof exports=="object"&&typeof module<"u"?module.exports=x():typeof define=="function"&&define.amd?define(x):(y=typeof globalThis<"u"?globalThis:y||self,y.Gantt=x())})(this,function(){"use strict";const y="year",x="month",M="day",D="hour",E="minute",Y="second",L="millisecond",S={January:"Jan",February:"Feb",March:"Mar",April:"Apr",May:"May",June:"Jun",July:"Jul",August:"Aug",September:"Sep",October:"Oct",November:"Nov",December:"Dec"},h={parse_duration(o){const e=/([0-9]+)(y|m|d|h|min|s|ms)/gm.exec(o);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(o,t="-",e=/[.:]/){if(o instanceof Date)return o;if(typeof o=="string"){let s,i;const n=o.split(" ");s=n[0].split(t).map(a=>parseInt(a,10)),i=n[1]&&n[1].split(e),s[1]=s[1]?s[1]-1:0;let r=s;return i&&i.length&&(i.length===4&&(i[3]="0."+i[3],i[3]=parseFloat(i[3])*1e3),r=r.concat(i)),new Date(...r)}},to_string(o,t=!1){if(!(o instanceof Date))throw new TypeError("Invalid argument type");const e=this.get_date_values(o).map((n,r)=>(r===1&&(n=n+1),r===6?k(n+"",3,"0"):k(n+"",2,"0"))),s=`${e[0]}-${e[1]}-${e[2]}`,i=`${e[3]}:${e[4]}:${e[5]}.${e[6]}`;return s+(t?" "+i:"")},format(o,t="YYYY-MM-DD HH:mm:ss.SSS",e="en"){const i=new Intl.DateTimeFormat(e,{month:"long"}).format(o),n=i.charAt(0).toUpperCase()+i.slice(1),r=this.get_date_values(o).map(g=>k(g,2,0)),a={YYYY:r[0],MM:k(+r[1]+1,2,0),DD:r[2],HH:r[3],mm:r[4],ss:r[5],SSS:r[6],D:r[2],MMMM:n,MMM:S[n]};let d=t;const p=[];return Object.keys(a).sort((g,c)=>c.length-g.length).forEach(g=>{d.includes(g)&&(d=d.replaceAll(g,`$${p.length}`),p.push(a[g]))}),p.forEach((g,c)=>{d=d.replaceAll(`$${c}`,g)}),d},diff(o,t,e=M){let s,i,n,r,a,d,p;s=o-t,i=s/1e3,r=i/60,n=r/60,a=n/24;const g=o.getFullYear()-t.getFullYear(),c=o.getMonth()-t.getMonth();return d=g*12+c,o.getDate()>0,e=String(typeof e<"u"?e:" "),o.length>t?String(o):(t=t-o.length,t>e.length&&(e+=e.repeat(t/e.length)),e.slice(0,t)+String(o))}function _(o,t){return typeof o=="string"?(t||document).querySelector(o):o||null}function u(o,t){const e=document.createElementNS("http://www.w3.org/2000/svg",o);for(let s in t)s==="append_to"?t.append_to.appendChild(e):s==="innerHTML"?e.innerHTML=t.innerHTML:s==="clipPath"?e.setAttribute("clip-path","url(#"+t[s]+")"):e.setAttribute(s,t[s]);return e}function A(o,t,e,s){const i=W(o,t,e,s);if(i===o){const n=document.createEvent("HTMLEvents");n.initEvent("click",!0,!0),n.eventName="click",i.dispatchEvent(n)}}function W(o,t,e,s,i="0.4s",n="0.1s"){const r=o.querySelector("animate");if(r)return _.attr(r,{attributeName:t,from:e,to:s,dur:i,begin:"click + "+n}),o;const a=u("animate",{attributeName:t,from:e,to:s,dur:i,begin:n,calcMode:"spline",values:e+";"+s,keyTimes:"0; 1",keySplines:X("ease-out")});return o.appendChild(a),o}function X(o){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"}[o]}_.on=(o,t,e,s)=>{s?_.delegate(o,t,e,s):(s=e,_.bind(o,t,s))},_.off=(o,t,e)=>{o.removeEventListener(t,e)},_.bind=(o,t,e)=>{t.split(/\s+/).forEach(function(s){o.addEventListener(s,e)})},_.delegate=(o,t,e,s)=>{o.addEventListener(t,function(i){const n=i.target.closest(e);n&&(i.delegatedTarget=n,s.call(this,i,n))})},_.closest=(o,t)=>t?t.matches(o)?t:_.closest(o,t.parentNode):null,_.attr=(o,t,e)=>{if(!e&&typeof t=="string")return o.getAttribute(t);if(typeof t=="object"){for(let s in t)_.attr(o,s,t[s]);return}o.setAttribute(t,e)};class O{constructor(t,e){this.set_defaults(t,e),this.prepare(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e}prepare(){this.prepare_values(),this.prepare_helpers()}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.options.column_width*this.duration,this.progress_width=this.gantt.options.column_width*this.duration*(this.task.progress/100)||0,this.group=u("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:"")+(this.task.important?" important":""),"data-id":this.task.id}),this.bar_group=u("g",{class:"bar-group",append_to:this.group}),this.handle_group=u("g",{class:"handle-group",append_to:this.group})}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()}draw_bar(){this.$bar=u("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar"+(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&!this.task.important?" safari":""),append_to:this.bar_group}),A(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=u("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}),A(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.$bar_progress=u("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-progress",append_to:this.bar_group});const t=h.diff(this.task._start,this.gantt.gantt_start,"hour")/this.gantt.options.step*this.gantt.options.column_width;let e=document.createElement("div");e.id=`${this.task.id}-highlight`,e.classList.add("date-highlight"),e.style.height=this.height*.8+"px",e.style.width=this.width+"px",e.style.top=this.gantt.options.header_height-25+"px",e.style.left=t+"px",this.$date_highlight=e,this.gantt.$lower_header.prepend(e),A(this.$bar_progress,"width",0,this.progress_width)}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),u("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,s,i;s=u("defs",{append_to:this.bar_group}),u("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:s}),i=u("clipPath",{id:"clip_"+this.task.id,append_to:s}),u("use",{href:"#rect_"+this.task.id,append_to:i}),u("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_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=8;if(this.gantt.options.dates_readonly||(u("rect",{x:t.getX()+t.getWidth()+e-4,y:t.getY()+1,width:e,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle right",append_to:this.handle_group}),u("rect",{x:t.getX()-e-4,y:t.getY()+1,width:e,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle left",append_to:this.handle_group})),!this.gantt.options.progress_readonly){const s=this.$bar_progress;this.$handle_progress=u("circle",{cx:s.getEndX(),cy:s.getY()+s.getHeight()/2,r:5,class:"handle progress",append_to:this.handle_group})}}bind(){this.invalid||this.setup_click_event()}setup_click_event(){let t=this.task.id;_.on(this.group,"mouseover",s=>{this.gantt.trigger_event("hover",[this.task,s.screenX,s.screenY,s])});let e;_.on(this.group,"mouseenter",s=>e=setTimeout(()=>{this.show_popup(s.offsetX||s.layerX),document.getElementById(`${t}-highlight`).style.display="block"},200)),_.on(this.group,"mouseleave",()=>{var s,i;clearTimeout(e),(i=(s=this.gantt.popup)==null?void 0:s.hide)==null||i.call(s),document.getElementById(`${t}-highlight`).style.display="none"}),_.on(this.group,"click",()=>{this.gantt.trigger_event("click",[this.task])}),_.on(this.group,"dblclick",s=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hidden"),this.gantt.trigger_event("double_click",[this.task]))})}show_popup(t){if(this.gantt.bar_being_dragged)return;const e=h.format(this.task._start,"MMM D",this.gantt.options.language),s=h.format(h.add(this.task._end,-1,"second"),"MMM D",this.gantt.options.language),i=`${e} - ${s}
Progress: ${this.task.progress}`;this.gantt.show_popup({x:t,target_element:this.$bar,title:this.task.name,subtitle:i,task:this.task})}update_bar_position({x:t=null,width:e=null}){const s=this.$bar;if(t){if(!this.task.dependencies.map(r=>this.gantt.get_bar(r).$bar.getX()).reduce((r,a)=>t>=a,t)){e=null;return}this.update_attr(s,"x",t),this.$date_highlight.style.left=t+"px"}e&&(this.update_attr(s,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.gantt.options.show_expected_progress&&(this.date_changed(),this.compute_duration(),this.update_expected_progressbar_position()),this.update_progressbar_position(),this.update_arrow_position()}update_label_position_on_horizontal_scroll({x:t,sx:e}){const s=document.querySelector(".gantt-container"),i=this.group.querySelector(".bar-label"),n=this.group.querySelector(".bar-img")||"",r=this.bar_group.querySelector(".img_mask")||"";let a=this.$bar.getX()+this.$bar.getWidth(),d=i.getX()+t,p=n&&n.getX()+t||0,g=n&&n.getBBox().width+7||7,c=d+i.getBBox().width+7,f=e+s.clientWidth/2;i.classList.contains("big")||(c0&&cthis.$bar.getX()&&t<0&&c>f)&&(i.setAttribute("x",d),n&&(n.setAttribute("x",p),r.setAttribute("x",p)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:s}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(s)&&(t=!0,this.task._end=s),t&&this.gantt.trigger_event("date_change",[this.task,e,h.add(s,-1,"second")])}progress_changed(){const t=this.compute_progress();this.task.progress=t,this.gantt.trigger_event("progress_change",[this.task,t])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,1e3)}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.options.column_width;let s=h.add(this.gantt.gantt_start,e*this.gantt.options.step,"hour");const i=this.gantt.gantt_start.getTimezoneOffset()-s.getTimezoneOffset();i&&(s=h.add(s,i,"minute"));const n=t.getWidth()/this.gantt.options.column_width,r=h.add(s,n*this.gantt.options.step,"hour");return{new_start_date:s,new_end_date:r}}compute_progress(){const t=this.$bar_progress.getWidth()/this.$bar.getWidth()*100;return parseInt(t,10)}compute_expected_progress(){this.expected_progress=h.diff(h.today(),this.task._start,"hour")/this.gantt.options.step,this.expected_progress=(this.expected_progressd?(s.classList.add("big"),i?(i.setAttribute("x",e.getX()+e.getWidth()+n),t.setAttribute("x",e.getX()+e.getWidth()+n),s.setAttribute("x",e.getX()+e.getWidth()+r)):s.setAttribute("x",e.getX()+e.getWidth()+n)):(s.classList.remove("big"),i?(i.setAttribute("x",e.getX()+n),t.setAttribute("x",e.getX()+n),s.setAttribute("x",e.getX()+d/2+r)):s.setAttribute("x",e.getX()+d/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()-12),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX()+4);const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class C{constructor(t,e,s){this.gantt=t,this.from_task=e,this.to_task=s,this.calculate_path(),this.draw()}calculate_path(){let t=this.from_task.$bar.getX()+this.from_task.$bar.getWidth()/2;const e=()=>this.to_task.$bar.getX()this.from_task.$bar.getX()+this.gantt.options.padding;for(;e();)t-=10;const s=this.gantt.options.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,i=this.to_task.$bar.getX()-this.gantt.options.padding/2-7,n=this.gantt.options.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,r=this.from_task.task._index>this.to_task.task._index,a=this.gantt.options.arrow_curve,d=r?1:0,p=r?-a:a,g=r?n+this.gantt.options.arrow_curve:n-this.gantt.options.arrow_curve;if(this.path=`
+(function(y,x){typeof exports=="object"&&typeof module<"u"?module.exports=x():typeof define=="function"&&define.amd?define(x):(y=typeof globalThis<"u"?globalThis:y||self,y.Gantt=x())})(this,function(){"use strict";const y="year",x="month",M="day",D="hour",E="minute",Y="second",L="millisecond",S={January:"Jan",February:"Feb",March:"Mar",April:"Apr",May:"May",June:"Jun",July:"Jul",August:"Aug",September:"Sep",October:"Oct",November:"Nov",December:"Dec"},h={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 s,i;const o=r.split(" ");s=o[0].split(t).map(a=>parseInt(a,10)),i=o[1]&&o[1].split(e),s[1]=s[1]?s[1]-1:0;let n=s;return i&&i.length&&(i.length===4&&(i[3]="0."+i[3],i[3]=parseFloat(i[3])*1e3),n=n.concat(i)),new Date(...n)}},to_string(r,t=!1){if(!(r instanceof Date))throw new TypeError("Invalid argument type");const e=this.get_date_values(r).map((o,n)=>(n===1&&(o=o+1),n===6?k(o+"",3,"0"):k(o+"",2,"0"))),s=`${e[0]}-${e[1]}-${e[2]}`,i=`${e[3]}:${e[4]}:${e[5]}.${e[6]}`;return s+(t?" "+i:"")},format(r,t="YYYY-MM-DD HH:mm:ss.SSS",e="en"){const i=new Intl.DateTimeFormat(e,{month:"long"}).format(r),o=i.charAt(0).toUpperCase()+i.slice(1),n=this.get_date_values(r).map(g=>k(g,2,0)),a={YYYY:n[0],MM:k(+n[1]+1,2,0),DD:n[2],HH:n[3],mm:n[4],ss:n[5],SSS:n[6],D:n[2],MMMM:o,MMM:S[o]};let d=t;const p=[];return Object.keys(a).sort((g,c)=>c.length-g.length).forEach(g=>{d.includes(g)&&(d=d.replaceAll(g,`$${p.length}`),p.push(a[g]))}),p.forEach((g,c)=>{d=d.replaceAll(`$${c}`,g)}),d},diff(r,t,e=M){let s,i,o,n,a,d,p;s=r-t,i=s/1e3,n=i/60,o=n/60,a=o/24;const g=r.getFullYear()-t.getFullYear(),c=r.getMonth()-t.getMonth();return d=g*12+c,r.getDate()>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 _(r,t){return typeof r=="string"?(t||document).querySelector(r):r||null}function u(r,t){const e=document.createElementNS("http://www.w3.org/2000/svg",r);for(let s in t)s==="append_to"?t.append_to.appendChild(e):s==="innerHTML"?e.innerHTML=t.innerHTML:s==="clipPath"?e.setAttribute("clip-path","url(#"+t[s]+")"):e.setAttribute(s,t[s]);return e}function A(r,t,e,s){const i=W(r,t,e,s);if(i===r){const o=document.createEvent("HTMLEvents");o.initEvent("click",!0,!0),o.eventName="click",i.dispatchEvent(o)}}function W(r,t,e,s,i="0.4s",o="0.1s"){const n=r.querySelector("animate");if(n)return _.attr(n,{attributeName:t,from:e,to:s,dur:i,begin:"click + "+o}),r;const a=u("animate",{attributeName:t,from:e,to:s,dur:i,begin:o,calcMode:"spline",values:e+";"+s,keyTimes:"0; 1",keySplines:X("ease-out")});return r.appendChild(a),r}function X(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]}_.on=(r,t,e,s)=>{s?_.delegate(r,t,e,s):(s=e,_.bind(r,t,s))},_.off=(r,t,e)=>{r.removeEventListener(t,e)},_.bind=(r,t,e)=>{t.split(/\s+/).forEach(function(s){r.addEventListener(s,e)})},_.delegate=(r,t,e,s)=>{r.addEventListener(t,function(i){const o=i.target.closest(e);o&&(i.delegatedTarget=o,s.call(this,i,o))})},_.closest=(r,t)=>t?t.matches(r)?t:_.closest(r,t.parentNode):null,_.attr=(r,t,e)=>{if(!e&&typeof t=="string")return r.getAttribute(t);if(typeof t=="object"){for(let s in t)_.attr(r,s,t[s]);return}r.setAttribute(t,e)};class O{constructor(t,e){this.set_defaults(t,e),this.prepare(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e}prepare(){this.prepare_values(),this.prepare_helpers()}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.options.column_width*this.duration,this.progress_width=this.gantt.options.column_width*this.duration*(this.task.progress/100)||0,this.group=u("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:"")+(this.task.important?" important":""),"data-id":this.task.id}),this.bar_group=u("g",{class:"bar-group",append_to:this.group}),this.handle_group=u("g",{class:"handle-group",append_to:this.group})}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()}draw_bar(){this.$bar=u("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar"+(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&!this.task.important?" safari":""),append_to:this.bar_group}),A(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=u("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}),A(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.$bar_progress=u("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-progress",append_to:this.bar_group});const t=h.diff(this.task._start,this.gantt.gantt_start,"hour")/this.gantt.options.step*this.gantt.options.column_width;let e=document.createElement("div");e.id=`${this.task.id}-highlight`,e.classList.add("date-highlight"),e.style.height=this.height*.8+"px",e.style.width=this.width+"px",e.style.top=this.gantt.options.header_height-25+"px",e.style.left=t+"px",this.$date_highlight=e,this.gantt.$lower_header.prepend(e),A(this.$bar_progress,"width",0,this.progress_width)}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),u("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,s,i;s=u("defs",{append_to:this.bar_group}),u("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:s}),i=u("clipPath",{id:"clip_"+this.task.id,append_to:s}),u("use",{href:"#rect_"+this.task.id,append_to:i}),u("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_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=8;if(this.gantt.options.dates_readonly||(u("rect",{x:t.getX()+t.getWidth()+e-4,y:t.getY()+1,width:e,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle right",append_to:this.handle_group}),u("rect",{x:t.getX()-e-4,y:t.getY()+1,width:e,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle left",append_to:this.handle_group})),!this.gantt.options.progress_readonly){const s=this.$bar_progress;this.$handle_progress=u("circle",{cx:s.getEndX(),cy:s.getY()+s.getHeight()/2,r:5,class:"handle progress",append_to:this.handle_group})}}bind(){this.invalid||this.setup_click_event()}setup_click_event(){let t=this.task.id;if(_.on(this.group,"mouseover",e=>{this.gantt.trigger_event("hover",[this.task,e.screenX,e.screenY,e])}),this.gantt.options.popup_on==="click"){let e=!1;_.on(this.group,"click",s=>{console.log(e),e?this.gantt.hide_popup():(this.show_popup(s.offsetX||s.layerX),document.getElementById(`${t}-highlight`).style.display="block"),e=!e})}else{let e;_.on(this.group,"mouseenter",s=>e=setTimeout(()=>{this.show_popup(s.offsetX||s.layerX),document.getElementById(`${t}-highlight`).style.display="block"},200)),_.on(this.group,"mouseleave",()=>{var s,i;clearTimeout(e),(i=(s=this.gantt.popup)==null?void 0:s.hide)==null||i.call(s),document.getElementById(`${t}-highlight`).style.display="none"})}_.on(this.group,"click",()=>{this.gantt.trigger_event("click",[this.task])}),_.on(this.group,"dblclick",e=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hidden"),this.gantt.trigger_event("double_click",[this.task]))})}show_popup(t){if(this.gantt.bar_being_dragged)return;const e=h.format(this.task._start,"MMM D",this.gantt.options.language),s=h.format(h.add(this.task._end,-1,"second"),"MMM D",this.gantt.options.language),i=`${e} - ${s}
Progress: ${this.task.progress}`;this.gantt.show_popup({x:t,target_element:this.$bar,title:this.task.name,subtitle:i,task:this.task})}update_bar_position({x:t=null,width:e=null}){const s=this.$bar;if(t){if(!this.task.dependencies.map(n=>this.gantt.get_bar(n).$bar.getX()).reduce((n,a)=>t>=a,t)){e=null;return}this.update_attr(s,"x",t),this.$date_highlight.style.left=t+"px"}e&&(this.update_attr(s,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.gantt.options.show_expected_progress&&(this.date_changed(),this.compute_duration(),this.update_expected_progressbar_position()),this.update_progressbar_position(),this.update_arrow_position()}update_label_position_on_horizontal_scroll({x:t,sx:e}){const s=document.querySelector(".gantt-container"),i=this.group.querySelector(".bar-label"),o=this.group.querySelector(".bar-img")||"",n=this.bar_group.querySelector(".img_mask")||"";let a=this.$bar.getX()+this.$bar.getWidth(),d=i.getX()+t,p=o&&o.getX()+t||0,g=o&&o.getBBox().width+7||7,c=d+i.getBBox().width+7,f=e+s.clientWidth/2;i.classList.contains("big")||(c0&&cthis.$bar.getX()&&t<0&&c>f)&&(i.setAttribute("x",d),o&&(o.setAttribute("x",p),n.setAttribute("x",p)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:s}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(s)&&(t=!0,this.task._end=s),t&&this.gantt.trigger_event("date_change",[this.task,e,h.add(s,-1,"second")])}progress_changed(){const t=this.compute_progress();this.task.progress=t,this.gantt.trigger_event("progress_change",[this.task,t])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,1e3)}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.options.column_width;let s=h.add(this.gantt.gantt_start,e*this.gantt.options.step,"hour");const i=this.gantt.gantt_start.getTimezoneOffset()-s.getTimezoneOffset();i&&(s=h.add(s,i,"minute"));const o=t.getWidth()/this.gantt.options.column_width,n=h.add(s,o*this.gantt.options.step,"hour");return{new_start_date:s,new_end_date:n}}compute_progress(){const t=this.$bar_progress.getWidth()/this.$bar.getWidth()*100;return parseInt(t,10)}compute_expected_progress(){this.expected_progress=h.diff(h.today(),this.task._start,"hour")/this.gantt.options.step,this.expected_progress=(this.expected_progressd?(s.classList.add("big"),i?(i.setAttribute("x",e.getX()+e.getWidth()+o),t.setAttribute("x",e.getX()+e.getWidth()+o),s.setAttribute("x",e.getX()+e.getWidth()+n)):s.setAttribute("x",e.getX()+e.getWidth()+o)):(s.classList.remove("big"),i?(i.setAttribute("x",e.getX()+o),t.setAttribute("x",e.getX()+o),s.setAttribute("x",e.getX()+d/2+n)):s.setAttribute("x",e.getX()+d/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()-12),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX()+4);const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class C{constructor(t,e,s){this.gantt=t,this.from_task=e,this.to_task=s,this.calculate_path(),this.draw()}calculate_path(){let t=this.from_task.$bar.getX()+this.from_task.$bar.getWidth()/2;const e=()=>this.to_task.$bar.getX()this.from_task.$bar.getX()+this.gantt.options.padding;for(;e();)t-=10;const s=this.gantt.options.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,i=this.to_task.$bar.getX()-this.gantt.options.padding/2-7,o=this.gantt.options.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,n=this.from_task.task._index>this.to_task.task._index,a=this.gantt.options.arrow_curve,d=n?1:0,p=n?-a:a,g=n?o+this.gantt.options.arrow_curve:o-this.gantt.options.arrow_curve;if(this.path=`
M ${t} ${s}
V ${g}
a ${a} ${a} 0 0 ${d} ${a} ${p}
- L ${i} ${n}
+ L ${i} ${o}
m -5 -5
l 5 5
l -5 5`,this.to_task.$bar.getX()
- `,this.hide(),this.title=this.parent.querySelector(".title"),this.subtitle=this.parent.querySelector(".subtitle"),this.pointer=this.parent.querySelector(".pointer")}show(t){if(!t.target_element)throw new Error("target_element is required to show popup");const e=t.target_element;if(this.custom_html){let i=this.custom_html(t.task);i+='',this.parent.innerHTML=i,this.pointer=this.parent.querySelector(".pointer")}else this.title.innerHTML=t.title,this.subtitle.innerHTML=t.subtitle;let s;e instanceof HTMLElement?s=e.getBoundingClientRect():e instanceof SVGElement&&(s=t.target_element.getBBox()),this.parent.style.left=t.x-this.parent.clientWidth/2+"px",this.parent.style.top=s.y+s.height+10+"px",this.pointer.style.left=this.parent.clientWidth/2+"px",this.pointer.style.top="-15px",this.parent.style.opacity=1}hide(){this.parent.style.opacity=0,this.parent.style.left=0}}const l={HOUR:"Hour",QUARTER_DAY:"Quarter Day",HALF_DAY:"Half Day",DAY:"Day",WEEK:"Week",MONTH:"Month",YEAR:"Year"},R={HOUR:["7d","7d"],QUARTER_DAY:["7d","7d"],HALF_DAY:["7d","7d"],DAY:["1m","1m"],WEEK:["1m","1m"],MONTH:["1m","1m"],YEAR:["2y","2y"]},I={header_height:65,column_width:30,view_modes:[...Object.values(l)],bar_height:30,bar_corner_radius:3,arrow_curve:5,padding:18,view_mode:"Day",date_format:"YYYY-MM-DD",show_expected_progress:!1,popup:null,language:"en",readonly:!1,progress_readonly:!1,dates_readonly:!1,highlight_weekend:!0,scroll_to:"start",lines:"both",auto_move_label:!0,today_button:!0,view_mode_select:!1};class T{constructor(t,e,s){this.setup_wrapper(t),this.setup_options(s),this.setup_tasks(e),this.change_view_mode(),this.bind_events()}setup_wrapper(t){let e,s;if(typeof t=="string"&&(t=document.querySelector(t)),t instanceof HTMLElement)s=t,e=t.querySelector("svg");else if(t instanceof SVGElement)e=t;else throw new TypeError("Frappe Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter");e?(this.$svg=e,this.$svg.classList.add("gantt")):this.$svg=u("svg",{append_to:s,class:"gantt"}),this.$container=document.createElement("div"),this.$container.classList.add("gantt-container"),this.$svg.parentElement.appendChild(this.$container),this.$container.appendChild(this.$svg),this.$popup_wrapper=document.createElement("div"),this.$popup_wrapper.classList.add("popup-wrapper"),this.$container.appendChild(this.$popup_wrapper)}setup_options(t){this.options={...I,...t},t.view_mode_padding||(t.view_mode_padding={});for(let[e,s]of Object.entries(t.view_mode_padding))typeof s=="string"&&(t.view_mode_padding[e]=[s,s]);this.options.view_mode_padding={...R,...t.view_mode_padding}}setup_tasks(t){this.tasks=t.map((e,s)=>{if(e._start=h.parse(e.start),e.end===void 0&&e.duration!==void 0&&(e.end=e._start,e.duration.split(" ").forEach(a=>{let{duration:d,scale:p}=h.parse_duration(a);e.end=h.add(e.end,d,p)})),e._end=h.parse(e.end),h.diff(e._end,e._start,"year")<0)throw Error("start of task can't be after end of task: in task #, "+(s+1));if(h.diff(e._end,e._start,"year")>10&&(e.end=null),e._index=s,!e.start&&!e.end){const r=h.today();e._start=r,e._end=h.add(r,2,"day")}if(!e.start&&e.end&&(e._start=h.add(e._end,-2,"day")),e.start&&!e.end&&(e._end=h.add(e._start,2,"day")),h.get_date_values(e._end).slice(3).every(r=>r===0)&&(e._end=h.add(e._end,24,"hour")),(!e.start||!e.end)&&(e.invalid=!0),typeof e.dependencies=="string"||!e.dependencies){let r=[];e.dependencies&&(r=e.dependencies.split(",").map(a=>a.trim().replaceAll(" ","_")).filter(a=>a)),e.dependencies=r}return e.id?typeof e.id=="string"?e.id=e.id.replaceAll(" ","_"):e.id=`${e.id}`:e.id=B(e),e}),this.setup_dependencies()}setup_dependencies(){this.dependency_map={};for(let t of this.tasks)for(let e of t.dependencies)this.dependency_map[e]=this.dependency_map[e]||[],this.dependency_map[e].push(t.id)}refresh(t){this.setup_tasks(t),this.change_view_mode()}change_view_mode(t=this.options.view_mode){this.update_view_scale(t),this.setup_dates(),this.render(),this.trigger_event("view_change",[t])}update_view_scale(t){this.options.view_mode=t,t===l.HOUR?(this.options.step=24/24,this.options.column_width=38):t===l.DAY?(this.options.step=24,this.options.column_width=38):t===l.HALF_DAY?(this.options.step=24/2,this.options.column_width=38):t===l.QUARTER_DAY?(this.options.step=24/4,this.options.column_width=38):t===l.WEEK?(this.options.step=24*7,this.options.column_width=140):t===l.MONTH?(this.options.step=24*30,this.options.column_width=120):t===l.YEAR&&(this.options.step=24*365,this.options.column_width=120)}setup_dates(){this.setup_gantt_dates(),this.setup_date_values()}setup_gantt_dates(){this.gantt_start=this.gantt_end=null;for(let a of this.tasks)(!this.gantt_start||a._startthis.gantt_end)&&(this.gantt_end=a._end);let t,e;this.gantt_start?t=h.start_of(this.gantt_start,"day"):t=new Date,this.gantt_end?e=h.start_of(this.gantt_end,"day"):e=new Date;let s;for(let[a,d]of Object.entries(l))d===this.options.view_mode&&(s=a);const[i,n]=this.options.view_mode_padding[s].map(h.parse_duration);t=h.add(t,-i.duration,i.scale);let r;this.view_is(l.YEAR)?r="YYYY":this.view_is(l.MONTH)?r="YYYY-MM":this.view_is(l.DAY)?r="YYYY-MM-DD":r="YYYY-MM-DD HH",this.gantt_start=h.parse(h.format(t,r)),this.gantt_start.setHours(0,0,0,0),this.gantt_end=h.add(e,n.duration,n.scale)}setup_date_values(){this.dates=[];let t=null;for(;t===null||tt.bottom?(this.$side_header.style.position="absolute",this.$side_header.style.top=`${t.scrollTop+e.top}px`):(this.$side_header.style.position="fixed",this.$side_header.style.top=i+10+"px");const n=Math.min(this.$header.clientWidth,this.$container.clientWidth);this.$side_header.style.left=s+this.$container.scrollLeft+n-this.$side_header.clientWidth+"px",this.$today_button&&(this.$today_button.style.left=`${t.left+20}px`)}make_grid_ticks(){if(!["both","vertical","horizontal"].includes(this.options.lines))return;let t=0,e=this.options.header_height+this.options.padding/2,s=(this.options.bar_height+this.options.padding)*this.tasks.length,i=u("g",{class:"lines_layer",append_to:this.layers.grid}),n=this.options.header_height+this.options.padding/2;const r=this.dates.length*this.options.column_width,a=this.options.bar_height+this.options.padding;if(this.options.lines!=="vertical")for(let d of this.tasks)u("line",{x1:0,y1:n+a,x2:r,y2:n+a,class:"row-line",append_to:i}),n+=a;if(this.options.lines!=="horizontal")for(let d of this.dates){let p="tick";this.view_is(l.DAY)&&d.getDate()===1&&(p+=" thick"),this.view_is(l.WEEK)&&d.getDate()>=1&&d.getDate()<8&&(p+=" thick"),this.view_is(l.MONTH)&&d.getMonth()%3===0&&(p+=" thick"),u("path",{d:`M ${t} ${e} v ${s}`,class:p,append_to:this.layers.grid}),this.view_is(l.MONTH)?t+=h.get_days_in_month(d)*this.options.column_width/30:t+=this.options.column_width}}highlightWeekends(){if(!(!this.view_is("Day")&&!this.view_is("Half Day"))){for(let t=new Date(this.gantt_start);t<=this.gantt_end;t.setDate(t.getDate()+1))if(t.getDay()===0||t.getDay()===6){const e=h.diff(t,this.gantt_start,"hour")/this.options.step*this.options.column_width,s=(this.options.bar_height+this.options.padding)*this.tasks.length;u("rect",{x:e,y:this.options.header_height+this.options.padding/2,width:(this.view_is("Day")?1:2)*this.options.column_width,height:s,class:"holiday-highlight",append_to:this.layers.grid})}}}computeGridHighlightDimensions(t){let e=this.options.column_width/2;if(this.view_is(l.DAY)){let s=h.today();return{x:e+h.diff(s,this.gantt_start,"hour")/this.options.step*this.options.column_width,date:s}}for(let s of this.dates){const i=new Date,n=new Date(s),r=new Date(s);switch(t){case l.WEEK:r.setDate(s.getDate()+7);break;case l.MONTH:r.setMonth(s.getMonth()+1);break;case l.YEAR:r.setFullYear(s.getFullYear()+1);break}if(i>=n&&i<=r)return{x:e,date:n};e+=this.options.column_width}return{x:e}}make_grid_highlights(){if(this.options.highlight_weekend&&this.highlightWeekends(),this.view_is(l.DAY)||this.view_is(l.WEEK)||this.view_is(l.MONTH)||this.view_is(l.YEAR)){const{x:t,date:e}=this.computeGridHighlightDimensions(this.options.view_mode);if(!e||!this.dates.find(r=>r.getTime()==e.getTime()))return;const s=this.options.header_height+this.options.padding/2,i=(this.options.bar_height+this.options.padding)*this.tasks.length;this.$current_highlight=this.create_el({top:s,left:t,height:i,classes:"current-highlight",append_to:this.$container});let n=document.getElementById(h.format(e).replaceAll(" ","_"));n&&(n.classList.add("current-date-highlight"),n.style.top=+n.style.top.slice(0,-2)-4+"px",n.style.left=+n.style.left.slice(0,-2)-8+"px")}}create_el({left:t,top:e,width:s,height:i,id:n,classes:r,append_to:a}){let d=document.createElement("div");return d.classList.add(r),d.style.top=e+"px",d.style.left=t+"px",n&&(d.id=n),s&&(d.style.width=i+"px"),i&&(d.style.height=i+"px"),a.appendChild(d),d}make_dates(){this.upper_texts_x={},this.get_dates_to_draw().forEach((t,e)=>{let s=this.create_el({left:t.lower_x,top:t.lower_y,id:t.formatted_date,classes:"lower-text",append_to:this.$lower_header});if(s.innerText=t.lower_text,s.style.left=+s.style.left.slice(0,-2)+"px",t.upper_text){this.upper_texts_x[t.upper_text]=t.upper_x;let i=document.createElement("div");i.classList.add("upper-text"),i.style.left=t.upper_x+"px",i.style.top=t.upper_y+"px",i.innerText=t.upper_text,this.$upper_header.appendChild(i),t.upper_x>this.layers.grid.getBBox().width&&i.remove()}})}get_dates_to_draw(){let t=null;return this.dates.map((s,i)=>{const n=this.get_date_info(s,t,i);return t=n,n})}get_date_info(t,e){let s=e?e.date:h.add(t,1,"day");const i={Hour_lower:h.format(t,"HH",this.options.language),"Quarter Day_lower":h.format(t,"HH",this.options.language),"Half Day_lower":h.format(t,"HH",this.options.language),Day_lower:t.getDate()!==s.getDate()?h.format(t,"D",this.options.language):"",Week_lower:t.getMonth()!==s.getMonth()?h.format(t,"D MMM",this.options.language):h.format(t,"D",this.options.language),Month_lower:h.format(t,"MMMM",this.options.language),Year_lower:h.format(t,"YYYY",this.options.language),Hour_upper:t.getDate()!==s.getDate()?h.format(t,"D MMMM",this.options.language):"","Quarter Day_upper":t.getDate()!==s.getDate()?h.format(t,"D MMM",this.options.language):"","Half Day_upper":t.getDate()!==s.getDate()?t.getMonth()!==s.getMonth()?h.format(t,"D MMM",this.options.language):h.format(t,"D",this.options.language):"",Day_upper:t.getMonth()!==s.getMonth()||!e?h.format(t,"MMMM",this.options.language):"",Week_upper:t.getMonth()!==s.getMonth()?h.format(t,"MMMM",this.options.language):"",Month_upper:t.getFullYear()!==s.getFullYear()?h.format(t,"YYYY",this.options.language):"",Year_upper:t.getFullYear()!==s.getFullYear()?h.format(t,"YYYY",this.options.language):""};let n=this.view_is(l.MONTH)?h.get_days_in_month(t)*this.options.column_width/30:this.options.column_width;const r={x:e?e.base_pos_x+e.column_width:0,lower_y:this.options.header_height-20,upper_y:this.options.header_height-50},a={Hour_lower:n/2,Hour_upper:n*12,"Quarter Day_lower":n/2,"Quarter Day_upper":n*2,"Half Day_lower":n/2,"Half Day_upper":n,Day_lower:n/2,Day_upper:n/2,Week_lower:n/2,Week_upper:n*4/2,Month_lower:n/2,Month_upper:n/2,Year_lower:n/2,Year_upper:n*30/2};return{date:t,formatted_date:h.format(t).replaceAll(" ","_"),column_width:n,base_pos_x:r.x,upper_text:this.options.lower_text?this.options.upper_text(t,this.options.view_mode,i[`${this.options.view_mode}_upper`]):i[`${this.options.view_mode}_upper`],lower_text:this.options.lower_text?this.options.lower_text(t,this.options.view_mode,i[`${this.options.view_mode}_lower`]):i[`${this.options.view_mode}_lower`],upper_x:r.x+a[`${this.options.view_mode}_upper`],upper_y:r.upper_y,lower_x:r.x+a[`${this.options.view_mode}_lower`],lower_y:r.lower_y}}make_bars(){this.bars=this.tasks.map(t=>{const e=new O(this,t);return this.layers.bar.appendChild(e.group),e})}make_arrows(){this.arrows=[];for(let t of this.tasks){let e=[];e=t.dependencies.map(s=>{const i=this.get_task(s);if(!i)return;const n=new C(this,this.bars[i._index],this.bars[t._index]);return this.layers.arrow.appendChild(n.element),n}).filter(Boolean),this.arrows=this.arrows.concat(e)}}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_width(){const t=this.$svg.getBoundingClientRect().width,e=this.$svg.querySelector(".grid .grid-row")?this.$svg.querySelector(".grid .grid-row").getAttribute("width"):0;t{this.unselect_all(),this.hide_popup()})}bind_bar_events(){let t=!1,e=0,s=0,i=!1,n=!1,r=null,a=[];this.bar_being_dragged=null;function d(){return t||i||n}this.$svg.onclick=p=>{p.target.classList.contains("grid-row")&&this.unselect_all()},_.on(this.$svg,"mousedown",".bar-wrapper, .handle",(p,g)=>{const c=_.closest(".bar-wrapper",g);a.forEach(w=>w.group.classList.remove("active")),g.classList.contains("left")?i=!0:g.classList.contains("right")?n=!0:g.classList.contains("bar-wrapper")&&(t=!0),c.classList.add("active"),this.popup&&this.popup.parent.classList.add("hidden"),this.popup&&this.popup.parent.classList.add("hidden"),e=p.offsetX||p.layerX,p.offsetY||p.layerY,r=c.getAttribute("data-id"),a=[r,...this.get_all_dependent_tasks(r)].map(w=>this.get_bar(w)),this.bar_being_dragged=r,a.forEach(w=>{const b=w.$bar;b.ox=b.getX(),b.oy=b.getY(),b.owidth=b.getWidth(),b.finaldx=0})}),_.on(this.$container,"scroll",p=>{let g=document.querySelectorAll(".bar-wrapper"),c=[];const f=[];let w;s&&(w=p.currentTarget.scrollLeft-s);const b=p.currentTarget.scrollLeft/this.options.column_width*this.options.step/24;let $="D MMM";["Year","Month"].includes(this.options.view_mode)?$="YYYY":["Day","Week"].includes(this.options.view_mode)?$="MMMM":this.view_is("Half Day")?$="D":this.view_is("Hour")&&($="D MMMM");let F=h.format(h.add(this.gantt_start,b,"day"),$);const v=Array.from(document.querySelectorAll(".upper-text")).find(m=>m.textContent===F);if(v&&!v.classList.contains("current-upper")){const m=document.querySelector(".current-upper");m&&(m.classList.remove("current-upper"),m.style.left=this.upper_texts_x[m.textContent]+"px",m.style.top=this.options.header_height-50+"px"),v.classList.add("current-upper");let H=this.$svg.getBoundingClientRect();v.style.left=H.x+this.$container.scrollLeft+10+"px",v.style.top=H.y+this.options.header_height-50+"px"}Array.prototype.forEach.call(g,function(m,H){f.push(m.getAttribute("data-id"))}),w&&(c=f.map(m=>this.get_bar(m)),this.options.auto_move_label&&c.forEach(m=>{m.update_label_position_on_horizontal_scroll({x:w,sx:p.currentTarget.scrollLeft})})),s=p.currentTarget.scrollLeft}),_.on(this.$svg,"mousemove",p=>{if(!d())return;const g=(p.offsetX||p.layerX)-e;a.forEach(c=>{const f=c.$bar;f.finaldx=this.get_snap_position(g),this.hide_popup(),i?r===c.task.id?c.update_bar_position({x:f.ox+f.finaldx,width:f.owidth-f.finaldx}):c.update_bar_position({x:f.ox+f.finaldx}):n?r===c.task.id&&c.update_bar_position({width:f.owidth+f.finaldx}):t&&!this.options.readonly&&!this.options.dates_readonly&&c.update_bar_position({x:f.ox+f.finaldx})})}),document.addEventListener("mouseup",p=>{t=!1,i=!1,n=!1}),_.on(this.$svg,"mouseup",p=>{this.bar_being_dragged=null,a.forEach(g=>{g.$bar.finaldx&&(g.date_changed(),g.set_action_completed())})}),this.bind_bar_progress()}bind_bar_progress(){let t=0,e=null,s=null,i=null,n=null;_.on(this.$svg,"mousedown",".handle.progress",(r,a)=>{e=!0,t=r.offsetX||r.layerX,r.offsetY||r.layerY;const p=_.closest(".bar-wrapper",a).getAttribute("data-id");s=this.get_bar(p),i=s.$bar_progress,n=s.$bar,i.finaldx=0,i.owidth=i.getWidth(),i.min_dx=-i.getWidth(),i.max_dx=n.getWidth()-i.getWidth()}),_.on(this.$svg,"mousemove",r=>{if(!e)return;let a=(r.offsetX||r.layerX)-t;a>i.max_dx&&(a=i.max_dx),a{e=!1,i&&i.finaldx&&(i.finaldx=0,s.progress_changed(),s.set_action_completed(),s=null,i=null,n=null)})}get_all_dependent_tasks(t){let e=[],s=[t];for(;s.length;){const i=s.reduce((n,r)=>(n=n.concat(this.dependency_map[r]),n),[]);e=e.concat(i),s=i.filter(n=>!s.includes(n))}return e.filter(Boolean)}get_snap_position(t){let e=t,s,i;return this.view_is(l.WEEK)?(s=t%(this.options.column_width/7),i=e-s+(s{t.classList.remove("active")}),this.popup&&this.popup.parent.classList.remove("hidden")}view_is(t){return typeof t=="string"?this.options.view_mode===t:Array.isArray(t)?t.some(e=>this.options.view_mode===e):!1}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 N(this.$popup_wrapper,this.options.popup)),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,s,i,n,r;this.$svg.innerHTML="",(e=(t=this.$header)==null?void 0:t.remove)==null||e.call(t),(i=(s=this.$current_highlight)==null?void 0:s.remove)==null||i.call(s),(r=(n=this.popup)==null?void 0:n.hide)==null||r.call(n)}}T.VIEW_MODE=l;function B(o){return o.name+"_"+Math.random().toString(36).slice(2,12)}return T});
+ `,this.hide(),this.title=this.parent.querySelector(".title"),this.subtitle=this.parent.querySelector(".subtitle"),this.pointer=this.parent.querySelector(".pointer")}show(t){if(!t.target_element)throw new Error("target_element is required to show popup");const e=t.target_element;if(this.custom_html){let i=this.custom_html(t.task);i+='',this.parent.innerHTML=i,this.pointer=this.parent.querySelector(".pointer")}else this.title.innerHTML=t.title,this.subtitle.innerHTML=t.subtitle;console.log("hey in");let s;e instanceof HTMLElement?s=e.getBoundingClientRect():e instanceof SVGElement&&(s=t.target_element.getBBox()),this.parent.style.left=t.x-this.parent.clientWidth/2+"px",this.parent.style.top=s.y+s.height+10+"px",this.parent.classList.remove("hidden"),this.pointer.style.left=this.parent.clientWidth/2+"px",this.pointer.style.top="-15px",this.parent.style.opacity=1}hide(){this.parent.style.opacity=0,this.parent.style.left=0}}const l={HOUR:"Hour",QUARTER_DAY:"Quarter Day",HALF_DAY:"Half Day",DAY:"Day",WEEK:"Week",MONTH:"Month",YEAR:"Year"},R={HOUR:["7d","7d"],QUARTER_DAY:["7d","7d"],HALF_DAY:["7d","7d"],DAY:["1m","1m"],WEEK:["1m","1m"],MONTH:["1m","1m"],YEAR:["2y","2y"]},I={header_height:65,column_width:30,view_modes:[...Object.values(l)],bar_height:30,bar_corner_radius:3,arrow_curve:5,padding:18,view_mode:"Day",date_format:"YYYY-MM-DD",show_expected_progress:!1,popup:null,popup_on:"hover",language:"en",readonly:!1,progress_readonly:!1,dates_readonly:!1,highlight_weekend:!0,scroll_to:"start",lines:"both",auto_move_label:!0,today_button:!0,view_mode_select:!1};class T{constructor(t,e,s){this.setup_wrapper(t),this.setup_options(s),this.setup_tasks(e),this.change_view_mode(),this.bind_events()}setup_wrapper(t){let e,s;if(typeof t=="string"&&(t=document.querySelector(t)),t instanceof HTMLElement)s=t,e=t.querySelector("svg");else if(t instanceof SVGElement)e=t;else throw new TypeError("Frappe Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter");e?(this.$svg=e,this.$svg.classList.add("gantt")):this.$svg=u("svg",{append_to:s,class:"gantt"}),this.$container=document.createElement("div"),this.$container.classList.add("gantt-container"),this.$svg.parentElement.appendChild(this.$container),this.$container.appendChild(this.$svg),this.$popup_wrapper=document.createElement("div"),this.$popup_wrapper.classList.add("popup-wrapper"),this.$container.appendChild(this.$popup_wrapper)}setup_options(t){this.options={...I,...t},t.view_mode_padding||(t.view_mode_padding={});for(let[e,s]of Object.entries(t.view_mode_padding))typeof s=="string"&&(t.view_mode_padding[e]=[s,s]);this.options.view_mode_padding={...R,...t.view_mode_padding}}setup_tasks(t){this.tasks=t.map((e,s)=>{if(e._start=h.parse(e.start),e.end===void 0&&e.duration!==void 0&&(e.end=e._start,e.duration.split(" ").forEach(a=>{let{duration:d,scale:p}=h.parse_duration(a);e.end=h.add(e.end,d,p)})),e._end=h.parse(e.end),h.diff(e._end,e._start,"year")<0)throw Error("start of task can't be after end of task: in task #, "+(s+1));if(h.diff(e._end,e._start,"year")>10&&(e.end=null),e._index=s,!e.start&&!e.end){const n=h.today();e._start=n,e._end=h.add(n,2,"day")}if(!e.start&&e.end&&(e._start=h.add(e._end,-2,"day")),e.start&&!e.end&&(e._end=h.add(e._start,2,"day")),h.get_date_values(e._end).slice(3).every(n=>n===0)&&(e._end=h.add(e._end,24,"hour")),(!e.start||!e.end)&&(e.invalid=!0),typeof e.dependencies=="string"||!e.dependencies){let n=[];e.dependencies&&(n=e.dependencies.split(",").map(a=>a.trim().replaceAll(" ","_")).filter(a=>a)),e.dependencies=n}return e.id?typeof e.id=="string"?e.id=e.id.replaceAll(" ","_"):e.id=`${e.id}`:e.id=B(e),e}),this.setup_dependencies()}setup_dependencies(){this.dependency_map={};for(let t of this.tasks)for(let e of t.dependencies)this.dependency_map[e]=this.dependency_map[e]||[],this.dependency_map[e].push(t.id)}refresh(t){this.setup_tasks(t),this.change_view_mode()}change_view_mode(t=this.options.view_mode){this.update_view_scale(t),this.setup_dates(),this.render(),this.trigger_event("view_change",[t])}update_view_scale(t){this.options.view_mode=t,t===l.HOUR?(this.options.step=24/24,this.options.column_width=38):t===l.DAY?(this.options.step=24,this.options.column_width=38):t===l.HALF_DAY?(this.options.step=24/2,this.options.column_width=38):t===l.QUARTER_DAY?(this.options.step=24/4,this.options.column_width=38):t===l.WEEK?(this.options.step=24*7,this.options.column_width=140):t===l.MONTH?(this.options.step=24*30,this.options.column_width=120):t===l.YEAR&&(this.options.step=24*365,this.options.column_width=120)}setup_dates(){this.setup_gantt_dates(),this.setup_date_values()}setup_gantt_dates(){this.gantt_start=this.gantt_end=null;for(let a of this.tasks)(!this.gantt_start||a._startthis.gantt_end)&&(this.gantt_end=a._end);let t,e;this.gantt_start?t=h.start_of(this.gantt_start,"day"):t=new Date,this.gantt_end?e=h.start_of(this.gantt_end,"day"):e=new Date;let s;for(let[a,d]of Object.entries(l))d===this.options.view_mode&&(s=a);const[i,o]=this.options.view_mode_padding[s].map(h.parse_duration);t=h.add(t,-i.duration,i.scale);let n;this.view_is(l.YEAR)?n="YYYY":this.view_is(l.MONTH)?n="YYYY-MM":this.view_is(l.DAY)?n="YYYY-MM-DD":n="YYYY-MM-DD HH",this.gantt_start=h.parse(h.format(t,n)),this.gantt_start.setHours(0,0,0,0),this.gantt_end=h.add(e,o.duration,o.scale)}setup_date_values(){this.dates=[];let t=null;for(;t===null||tt.bottom?(this.$side_header.style.position="absolute",this.$side_header.style.top=`${t.scrollTop+e.top}px`):(this.$side_header.style.position="fixed",this.$side_header.style.top=i+10+"px");const o=Math.min(this.$header.clientWidth,this.$container.clientWidth);this.$side_header.style.left=s+this.$container.scrollLeft+o-this.$side_header.clientWidth+"px",this.$today_button&&(this.$today_button.style.left=`${t.left+20}px`)}make_grid_ticks(){if(!["both","vertical","horizontal"].includes(this.options.lines))return;let t=0,e=this.options.header_height+this.options.padding/2,s=(this.options.bar_height+this.options.padding)*this.tasks.length,i=u("g",{class:"lines_layer",append_to:this.layers.grid}),o=this.options.header_height+this.options.padding/2;const n=this.dates.length*this.options.column_width,a=this.options.bar_height+this.options.padding;if(this.options.lines!=="vertical")for(let d of this.tasks)u("line",{x1:0,y1:o+a,x2:n,y2:o+a,class:"row-line",append_to:i}),o+=a;if(this.options.lines!=="horizontal")for(let d of this.dates){let p="tick";this.view_is(l.DAY)&&d.getDate()===1&&(p+=" thick"),this.view_is(l.WEEK)&&d.getDate()>=1&&d.getDate()<8&&(p+=" thick"),this.view_is(l.MONTH)&&d.getMonth()%3===0&&(p+=" thick"),u("path",{d:`M ${t} ${e} v ${s}`,class:p,append_to:this.layers.grid}),this.view_is(l.MONTH)?t+=h.get_days_in_month(d)*this.options.column_width/30:t+=this.options.column_width}}highlightWeekends(){if(!(!this.view_is("Day")&&!this.view_is("Half Day"))){for(let t=new Date(this.gantt_start);t<=this.gantt_end;t.setDate(t.getDate()+1))if(t.getDay()===0||t.getDay()===6){const e=h.diff(t,this.gantt_start,"hour")/this.options.step*this.options.column_width,s=(this.options.bar_height+this.options.padding)*this.tasks.length;u("rect",{x:e,y:this.options.header_height+this.options.padding/2,width:(this.view_is("Day")?1:2)*this.options.column_width,height:s,class:"holiday-highlight",append_to:this.layers.grid})}}}computeGridHighlightDimensions(t){let e=this.options.column_width/2;if(this.view_is(l.DAY)){let s=h.today();return{x:e+h.diff(s,this.gantt_start,"hour")/this.options.step*this.options.column_width,date:s}}for(let s of this.dates){const i=new Date,o=new Date(s),n=new Date(s);switch(t){case l.WEEK:n.setDate(s.getDate()+7);break;case l.MONTH:n.setMonth(s.getMonth()+1);break;case l.YEAR:n.setFullYear(s.getFullYear()+1);break}if(i>=o&&i<=n)return{x:e,date:o};e+=this.options.column_width}return{x:e}}make_grid_highlights(){if(this.options.highlight_weekend&&this.highlightWeekends(),this.view_is(l.DAY)||this.view_is(l.WEEK)||this.view_is(l.MONTH)||this.view_is(l.YEAR)){const{x:t,date:e}=this.computeGridHighlightDimensions(this.options.view_mode);if(!e||!this.dates.find(n=>n.getTime()==e.getTime()))return;const s=this.options.header_height+this.options.padding/2,i=(this.options.bar_height+this.options.padding)*this.tasks.length;this.$current_highlight=this.create_el({top:s,left:t,height:i,classes:"current-highlight",append_to:this.$container});let o=document.getElementById(h.format(e).replaceAll(" ","_"));o&&(o.classList.add("current-date-highlight"),o.style.top=+o.style.top.slice(0,-2)-4+"px",o.style.left=+o.style.left.slice(0,-2)-8+"px")}}create_el({left:t,top:e,width:s,height:i,id:o,classes:n,append_to:a}){let d=document.createElement("div");return d.classList.add(n),d.style.top=e+"px",d.style.left=t+"px",o&&(d.id=o),s&&(d.style.width=i+"px"),i&&(d.style.height=i+"px"),a.appendChild(d),d}make_dates(){this.upper_texts_x={},this.get_dates_to_draw().forEach((t,e)=>{let s=this.create_el({left:t.lower_x,top:t.lower_y,id:t.formatted_date,classes:"lower-text",append_to:this.$lower_header});if(s.innerText=t.lower_text,s.style.left=+s.style.left.slice(0,-2)+"px",t.upper_text){this.upper_texts_x[t.upper_text]=t.upper_x;let i=document.createElement("div");i.classList.add("upper-text"),i.style.left=t.upper_x+"px",i.style.top=t.upper_y+"px",i.innerText=t.upper_text,this.$upper_header.appendChild(i),t.upper_x>this.layers.grid.getBBox().width&&i.remove()}})}get_dates_to_draw(){let t=null;return this.dates.map((s,i)=>{const o=this.get_date_info(s,t,i);return t=o,o})}get_date_info(t,e){let s=e?e.date:h.add(t,1,"day");const i={Hour_lower:h.format(t,"HH",this.options.language),"Quarter Day_lower":h.format(t,"HH",this.options.language),"Half Day_lower":h.format(t,"HH",this.options.language),Day_lower:t.getDate()!==s.getDate()?h.format(t,"D",this.options.language):"",Week_lower:t.getMonth()!==s.getMonth()?h.format(t,"D MMM",this.options.language):h.format(t,"D",this.options.language),Month_lower:h.format(t,"MMMM",this.options.language),Year_lower:h.format(t,"YYYY",this.options.language),Hour_upper:t.getDate()!==s.getDate()?h.format(t,"D MMMM",this.options.language):"","Quarter Day_upper":t.getDate()!==s.getDate()?h.format(t,"D MMM",this.options.language):"","Half Day_upper":t.getDate()!==s.getDate()?t.getMonth()!==s.getMonth()?h.format(t,"D MMM",this.options.language):h.format(t,"D",this.options.language):"",Day_upper:t.getMonth()!==s.getMonth()||!e?h.format(t,"MMMM",this.options.language):"",Week_upper:t.getMonth()!==s.getMonth()?h.format(t,"MMMM",this.options.language):"",Month_upper:t.getFullYear()!==s.getFullYear()?h.format(t,"YYYY",this.options.language):"",Year_upper:t.getFullYear()!==s.getFullYear()?h.format(t,"YYYY",this.options.language):""};let o=this.view_is(l.MONTH)?h.get_days_in_month(t)*this.options.column_width/30:this.options.column_width;const n={x:e?e.base_pos_x+e.column_width:0,lower_y:this.options.header_height-20,upper_y:this.options.header_height-50},a={Hour_lower:o/2,Hour_upper:o*12,"Quarter Day_lower":o/2,"Quarter Day_upper":o*2,"Half Day_lower":o/2,"Half Day_upper":o,Day_lower:o/2,Day_upper:o/2,Week_lower:o/2,Week_upper:o*4/2,Month_lower:o/2,Month_upper:o/2,Year_lower:o/2,Year_upper:o*30/2};return{date:t,formatted_date:h.format(t).replaceAll(" ","_"),column_width:o,base_pos_x:n.x,upper_text:this.options.lower_text?this.options.upper_text(t,this.options.view_mode,i[`${this.options.view_mode}_upper`]):i[`${this.options.view_mode}_upper`],lower_text:this.options.lower_text?this.options.lower_text(t,this.options.view_mode,i[`${this.options.view_mode}_lower`]):i[`${this.options.view_mode}_lower`],upper_x:n.x+a[`${this.options.view_mode}_upper`],upper_y:n.upper_y,lower_x:n.x+a[`${this.options.view_mode}_lower`],lower_y:n.lower_y}}make_bars(){this.bars=this.tasks.map(t=>{const e=new O(this,t);return this.layers.bar.appendChild(e.group),e})}make_arrows(){this.arrows=[];for(let t of this.tasks){let e=[];e=t.dependencies.map(s=>{const i=this.get_task(s);if(!i)return;const o=new C(this,this.bars[i._index],this.bars[t._index]);return this.layers.arrow.appendChild(o.element),o}).filter(Boolean),this.arrows=this.arrows.concat(e)}}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_width(){const t=this.$svg.getBoundingClientRect().width,e=this.$svg.querySelector(".grid .grid-row")?this.$svg.querySelector(".grid .grid-row").getAttribute("width"):0;t{this.unselect_all(),this.hide_popup()})}bind_bar_events(){let t=!1,e=0,s=0,i=!1,o=!1,n=null,a=[];this.bar_being_dragged=null;function d(){return t||i||o}this.$svg.onclick=p=>{p.target.classList.contains("grid-row")&&this.unselect_all()},_.on(this.$svg,"mousedown",".bar-wrapper, .handle",(p,g)=>{const c=_.closest(".bar-wrapper",g);a.forEach(w=>w.group.classList.remove("active")),g.classList.contains("left")?i=!0:g.classList.contains("right")?o=!0:g.classList.contains("bar-wrapper")&&(t=!0),c.classList.add("active"),this.popup&&this.popup.parent.classList.add("hidden"),this.popup&&this.popup.parent.classList.add("hidden"),e=p.offsetX||p.layerX,p.offsetY||p.layerY,n=c.getAttribute("data-id"),a=[n,...this.get_all_dependent_tasks(n)].map(w=>this.get_bar(w)),this.bar_being_dragged=n,a.forEach(w=>{const b=w.$bar;b.ox=b.getX(),b.oy=b.getY(),b.owidth=b.getWidth(),b.finaldx=0})}),_.on(this.$container,"scroll",p=>{let g=document.querySelectorAll(".bar-wrapper"),c=[];const f=[];let w;s&&(w=p.currentTarget.scrollLeft-s);const b=p.currentTarget.scrollLeft/this.options.column_width*this.options.step/24;let $="D MMM";["Year","Month"].includes(this.options.view_mode)?$="YYYY":["Day","Week"].includes(this.options.view_mode)?$="MMMM":this.view_is("Half Day")?$="D":this.view_is("Hour")&&($="D MMMM");let F=h.format(h.add(this.gantt_start,b,"day"),$);const v=Array.from(document.querySelectorAll(".upper-text")).find(m=>m.textContent===F);if(v&&!v.classList.contains("current-upper")){const m=document.querySelector(".current-upper");m&&(m.classList.remove("current-upper"),m.style.left=this.upper_texts_x[m.textContent]+"px",m.style.top=this.options.header_height-50+"px"),v.classList.add("current-upper");let H=this.$svg.getBoundingClientRect();v.style.left=H.x+this.$container.scrollLeft+10+"px",v.style.top=H.y+this.options.header_height-50+"px"}Array.prototype.forEach.call(g,function(m,H){f.push(m.getAttribute("data-id"))}),w&&(c=f.map(m=>this.get_bar(m)),this.options.auto_move_label&&c.forEach(m=>{m.update_label_position_on_horizontal_scroll({x:w,sx:p.currentTarget.scrollLeft})})),s=p.currentTarget.scrollLeft}),_.on(this.$svg,"mousemove",p=>{if(!d())return;const g=(p.offsetX||p.layerX)-e;a.forEach(c=>{const f=c.$bar;f.finaldx=this.get_snap_position(g),this.hide_popup(),i?n===c.task.id?c.update_bar_position({x:f.ox+f.finaldx,width:f.owidth-f.finaldx}):c.update_bar_position({x:f.ox+f.finaldx}):o?n===c.task.id&&c.update_bar_position({width:f.owidth+f.finaldx}):t&&!this.options.readonly&&!this.options.dates_readonly&&c.update_bar_position({x:f.ox+f.finaldx})})}),document.addEventListener("mouseup",p=>{t=!1,i=!1,o=!1}),_.on(this.$svg,"mouseup",p=>{this.bar_being_dragged=null,a.forEach(g=>{g.$bar.finaldx&&(g.date_changed(),g.set_action_completed())})}),this.bind_bar_progress()}bind_bar_progress(){let t=0,e=null,s=null,i=null,o=null;_.on(this.$svg,"mousedown",".handle.progress",(n,a)=>{e=!0,t=n.offsetX||n.layerX,n.offsetY||n.layerY;const p=_.closest(".bar-wrapper",a).getAttribute("data-id");s=this.get_bar(p),i=s.$bar_progress,o=s.$bar,i.finaldx=0,i.owidth=i.getWidth(),i.min_dx=-i.getWidth(),i.max_dx=o.getWidth()-i.getWidth()}),_.on(this.$svg,"mousemove",n=>{if(!e)return;let a=(n.offsetX||n.layerX)-t;a>i.max_dx&&(a=i.max_dx),a{e=!1,i&&i.finaldx&&(i.finaldx=0,s.progress_changed(),s.set_action_completed(),s=null,i=null,o=null)})}get_all_dependent_tasks(t){let e=[],s=[t];for(;s.length;){const i=s.reduce((o,n)=>(o=o.concat(this.dependency_map[n]),o),[]);e=e.concat(i),s=i.filter(o=>!s.includes(o))}return e.filter(Boolean)}get_snap_position(t){let e=t,s,i;return this.view_is(l.WEEK)?(s=t%(this.options.column_width/7),i=e-s+(s{t.classList.remove("active")}),this.popup&&this.popup.parent.classList.remove("hidden")}view_is(t){return typeof t=="string"?this.options.view_mode===t:Array.isArray(t)?t.some(e=>this.options.view_mode===e):!1}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 N(this.$popup_wrapper,this.options.popup)),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,s,i,o,n;this.$svg.innerHTML="",(e=(t=this.$header)==null?void 0:t.remove)==null||e.call(t),(i=(s=this.$current_highlight)==null?void 0:s.remove)==null||i.call(s),(n=(o=this.popup)==null?void 0:o.hide)==null||n.call(o)}}T.VIEW_MODE=l;function B(r){return r.name+"_"+Math.random().toString(36).slice(2,12)}return T});
diff --git a/index.html b/index.html
index be958b27..48461353 100644
--- a/index.html
+++ b/index.html
@@ -94,16 +94,16 @@
];
// Uncomment to test fixed header
- // tasks = [
- // ...tasks,
- // ...Array.from({ length: tasks.length * 3 }, (_, i) => ({
- // ...tasks[i % 3],
- // id: i,
- // })),
- // ];
+ tasks = [
+ ...tasks,
+ ...Array.from({ length: tasks.length * 3 }, (_, i) => ({
+ ...tasks[i % 3],
+ id: i,
+ })),
+ ];
let gantt_chart = new Gantt('.gantt-target', tasks, {
- on_click (task) {
+ on_click(task) {
console.log('Click', task);
},
// on_hover (task, x, y) {
@@ -111,7 +111,7 @@
// },
view_mode: 'Day',
view_mode_padding: { DAY: '3d' },
- // popup: false,
+ // popup_on: 'click',
// scroll_to: 'today',
// view_mode_select: true,
// dates_readonly: true,
diff --git a/src/bar.js b/src/bar.js
index 0761f5ac..257a9862 100644
--- a/src/bar.js
+++ b/src/bar.js
@@ -282,25 +282,41 @@ export default class Bar {
]);
});
- let timeout;
- $.on(
- this.group,
- 'mouseenter',
- (e) =>
- (timeout = setTimeout(() => {
+ if (this.gantt.options.popup_on === 'click') {
+ let opened = false;
+ $.on(this.group, 'click', (e) => {
+ console.log(opened);
+ if (!opened) {
this.show_popup(e.offsetX || e.layerX);
document.getElementById(
`${task_id}-highlight`,
).style.display = 'block';
- }, 200)),
- );
+ } else {
+ this.gantt.hide_popup();
+ }
+ opened = !opened;
+ });
+ } else {
+ let timeout;
+ $.on(
+ this.group,
+ 'mouseenter',
+ (e) =>
+ (timeout = setTimeout(() => {
+ this.show_popup(e.offsetX || e.layerX);
+ document.getElementById(
+ `${task_id}-highlight`,
+ ).style.display = 'block';
+ }, 200)),
+ );
- $.on(this.group, 'mouseleave', () => {
- clearTimeout(timeout);
- this.gantt.popup?.hide?.();
- document.getElementById(`${task_id}-highlight`).style.display =
- 'none';
- });
+ $.on(this.group, 'mouseleave', () => {
+ clearTimeout(timeout);
+ this.gantt.popup?.hide?.();
+ document.getElementById(`${task_id}-highlight`).style.display =
+ 'none';
+ });
+ }
$.on(this.group, 'click', () => {
this.gantt.trigger_event('click', [this.task]);
@@ -333,7 +349,6 @@ export default class Bar {
this.gantt.options.language,
);
const subtitle = `${start_date} - ${end_date}
Progress: ${this.task.progress}`;
-
this.gantt.show_popup({
x,
target_element: this.$bar,
diff --git a/src/index.js b/src/index.js
index c38cd936..b5f8053a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -38,6 +38,7 @@ const DEFAULT_OPTIONS = {
date_format: 'YYYY-MM-DD',
show_expected_progress: false,
popup: null,
+ popup_on: 'hover',
language: 'en',
readonly: false,
progress_readonly: false,
diff --git a/src/popup.js b/src/popup.js
index d2b9c764..40e4b753 100644
--- a/src/popup.js
+++ b/src/popup.js
@@ -35,7 +35,7 @@ export default class Popup {
this.title.innerHTML = options.title;
this.subtitle.innerHTML = options.subtitle;
}
-
+ console.log('hey in');
// set position
let position_meta;
if (target_element instanceof HTMLElement) {
@@ -48,6 +48,7 @@ export default class Popup {
this.parent.style.top =
position_meta.y + position_meta.height + 10 + 'px';
+ this.parent.classList.remove('hidden');
this.pointer.style.left = this.parent.clientWidth / 2 + 'px';
this.pointer.style.top = '-15px';