diff --git a/README.md b/README.md index 7dc4d85..2f2c36e 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,12 @@ var gantt = new Gantt("#gantt", tasks, { }); ``` +You can add `dark` class to the container element to apply dark theme. + +```html +
+``` + ### Contributing If you want to contribute enhancements or fixes: diff --git a/dist/frappe-gantt.css b/dist/frappe-gantt.css index ba26cab..ed1dfe2 100644 --- a/dist/frappe-gantt.css +++ b/dist/frappe-gantt.css @@ -1,3 +1,71 @@ +.dark > .gantt-container .gantt .grid-header { + fill: #252525; + stroke: #616161; +} +.dark > .gantt-container .gantt .grid-row { + fill: #252525; +} +.dark > .gantt-container .gantt .grid-row:nth-child(even) { + fill: #3e3e3e; +} +.dark > .gantt-container .gantt .row-line { + stroke: #3e3e3e; +} +.dark > .gantt-container .gantt .tick { + stroke: #616161; +} +.dark > .gantt-container .gantt .today-highlight { + opacity: 0.2; +} +.dark > .gantt-container .gantt .arrow { + stroke: #eee; +} +.dark > .gantt-container .gantt .bar { + fill: #616161; + stroke: none; +} +.dark > .gantt-container .gantt .bar-progress { + fill: #8a8aff; +} +.dark > .gantt-container .gantt .bar-invalid { + fill: transparent; + stroke: #c6ccd2; +} +.dark > .gantt-container .gantt .bar-invalid ~ .bar-label { + fill: #ececec; +} +.dark > .gantt-container .gantt .bar-label.big { + fill: #ececec; +} +.dark > .gantt-container .gantt .bar-wrapper:hover .bar { + fill: #6e6e6e; +} +.dark > .gantt-container .gantt .bar-wrapper:hover .bar-progress { + fill: #a4a4ff; +} +.dark > .gantt-container .gantt .bar-wrapper.active .bar { + fill: #6e6e6e; +} +.dark > .gantt-container .gantt .bar-wrapper.active .bar-progress { + fill: #a4a4ff; +} +.dark > .gantt-container .gantt .upper-text { + fill: #a2a2a2; +} +.dark > .gantt-container .gantt .lower-text { + fill: #f7f7f7; +} + +.dark > .gantt-container .popup-wrapper { + background-color: #333; +} +.dark > .gantt-container .popup-wrapper .title { + border-color: #a4a4ff; +} +.dark > .gantt-container .popup-wrapper .pointer { + border-top-color: #333; +} + .gantt .grid-background { fill: none; } diff --git a/dist/frappe-gantt.min.css b/dist/frappe-gantt.min.css index 3d9eb3a..9ae6319 100644 --- a/dist/frappe-gantt.min.css +++ b/dist/frappe-gantt.min.css @@ -1 +1 @@ -.gantt .grid-background{fill:none}.gantt .grid-header{fill:#fff;stroke:#e0e0e0;stroke-width:1.4}.gantt .grid-row{fill:#fff}.gantt .grid-row:nth-child(even){fill:#f5f5f5}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.2}.gantt .tick.thick{stroke-width:.4}.gantt .today-highlight{fill:#fcf8e3;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar{fill:#b8c2cc;stroke:#8d99a6;stroke-width:0;transition:stroke-width .3s ease;user-select:none}.gantt .bar-progress{fill:#acacfa}.gantt .bar-expected-progress{fill:#c4c4e9}.gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#8d99a6;stroke-width:1;stroke-dasharray:5}.gantt .bar-invalid~.bar-label{fill:#555}.gantt .bar-label{fill:#fff;dominant-baseline:central;text-anchor:middle;font-size:12px;font-weight:lighter}.gantt .bar-label.big{fill:#555;text-anchor:start}.gantt .handle{fill:#ddd;cursor:ew-resize;opacity:0;visibility:hidden;transition:opacity .3s ease}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper:hover .bar{fill:#a9b5c1}.gantt .bar-wrapper:hover .bar-progress{fill:#9494f9}.gantt .bar-wrapper:hover .handle{visibility:visible;opacity:1}.gantt .bar-wrapper.active .bar{fill:#a9b5c1}.gantt .bar-wrapper.active .bar-progress{fill:#9494f9}.gantt .lower-text,.gantt .upper-text{font-size:12px;text-anchor:middle}.gantt .upper-text{fill:#555}.gantt .lower-text{fill:#333}.gantt .hide{display:none}.gantt-container{position:relative;overflow:auto;font-size:12px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:rgba(0,0,0,.8);padding:0;color:#959da5;border-radius:3px}.gantt-container .popup-wrapper .title{border-bottom:3px solid #acacfa;padding:10px}.gantt-container .popup-wrapper .subtitle{padding:10px;color:#dfe2e5}.gantt-container .popup-wrapper .pointer{position:absolute;height:5px;margin:0 0 0 -5px;border:5px solid rgba(0,0,0,0);border-top-color:rgba(0,0,0,.8)} \ No newline at end of file +.dark>.gantt-container .gantt .grid-header{fill:#252525;stroke:#616161}.dark>.gantt-container .gantt .grid-row{fill:#252525}.dark>.gantt-container .gantt .grid-row:nth-child(even){fill:#3e3e3e}.dark>.gantt-container .gantt .row-line{stroke:#3e3e3e}.dark>.gantt-container .gantt .tick{stroke:#616161}.dark>.gantt-container .gantt .today-highlight{opacity:.2}.dark>.gantt-container .gantt .arrow{stroke:#eee}.dark>.gantt-container .gantt .bar{fill:#616161;stroke:none}.dark>.gantt-container .gantt .bar-progress{fill:#8a8aff}.dark>.gantt-container .gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#c6ccd2}.dark>.gantt-container .gantt .bar-invalid~.bar-label{fill:#ececec}.dark>.gantt-container .gantt .bar-label.big{fill:#ececec}.dark>.gantt-container .gantt .bar-wrapper:hover .bar{fill:#6e6e6e}.dark>.gantt-container .gantt .bar-wrapper:hover .bar-progress{fill:#a4a4ff}.dark>.gantt-container .gantt .bar-wrapper.active .bar{fill:#6e6e6e}.dark>.gantt-container .gantt .bar-wrapper.active .bar-progress{fill:#a4a4ff}.dark>.gantt-container .gantt .upper-text{fill:#a2a2a2}.dark>.gantt-container .gantt .lower-text{fill:#f7f7f7}.dark>.gantt-container .popup-wrapper{background-color:#333}.dark>.gantt-container .popup-wrapper .title{border-color:#a4a4ff}.dark>.gantt-container .popup-wrapper .pointer{border-top-color:#333}.gantt .grid-background{fill:none}.gantt .grid-header{fill:#fff;stroke:#e0e0e0;stroke-width:1.4}.gantt .grid-row{fill:#fff}.gantt .grid-row:nth-child(even){fill:#f5f5f5}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.2}.gantt .tick.thick{stroke-width:.4}.gantt .today-highlight{fill:#fcf8e3;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar{fill:#b8c2cc;stroke:#8d99a6;stroke-width:0;transition:stroke-width .3s ease;user-select:none}.gantt .bar-progress{fill:#a3a3ff}.gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#8d99a6;stroke-width:1;stroke-dasharray:5}.gantt .bar-invalid~.bar-label{fill:#555}.gantt .bar-label{fill:#fff;dominant-baseline:central;text-anchor:middle;font-size:12px;font-weight:lighter}.gantt .bar-label.big{fill:#555;text-anchor:start}.gantt .handle{fill:#ddd;cursor:ew-resize;opacity:0;visibility:hidden;transition:opacity .3s ease}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper:hover .bar{fill:#a9b5c1}.gantt .bar-wrapper:hover .bar-progress{fill:#8a8aff}.gantt .bar-wrapper:hover .handle{visibility:visible;opacity:1}.gantt .bar-wrapper.active .bar{fill:#a9b5c1}.gantt .bar-wrapper.active .bar-progress{fill:#8a8aff}.gantt .lower-text,.gantt .upper-text{font-size:12px;text-anchor:middle}.gantt .upper-text{fill:#555}.gantt .lower-text{fill:#333}.gantt .hide{display:none}.gantt-container{position:relative;overflow:auto;font-size:12px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:rgba(0,0,0,.8);padding:0;color:#959da5;border-radius:3px}.gantt-container .popup-wrapper .title{border-bottom:3px solid #a3a3ff;padding:10px}.gantt-container .popup-wrapper .subtitle{padding:10px;color:#dfe2e5}.gantt-container .popup-wrapper .pointer{position:absolute;height:5px;margin:0 0 0 -5px;border:5px solid rgba(0,0,0,0);border-top-color:rgba(0,0,0,.8)} \ No newline at end of file diff --git a/dist/frappe-gantt.min.js.map b/dist/frappe-gantt.min.js.map index fb2ee67..a3cd5d6 100644 --- a/dist/frappe-gantt.min.js.map +++ b/dist/frappe-gantt.min.js.map @@ -1 +1 @@ -{"version":3,"file":"frappe-gantt.min.js","sources":["../src/date_utils.js","../src/svg_utils.js","../src/bar.js","../src/arrow.js","../src/popup.js","../src/index.js"],"sourcesContent":["const YEAR = 'year';\nconst MONTH = 'month';\nconst DAY = 'day';\nconst HOUR = 'hour';\nconst MINUTE = 'minute';\nconst SECOND = 'second';\nconst MILLISECOND = 'millisecond';\n\nexport default {\n parse(date, date_separator = '-', time_separator = /[.:]/) {\n if (date instanceof Date) {\n return date;\n }\n if (typeof date === 'string') {\n let date_parts, time_parts;\n const parts = date.split(' ');\n\n date_parts = parts[0]\n .split(date_separator)\n .map((val) => parseInt(val, 10));\n time_parts = parts[1] && parts[1].split(time_separator);\n\n // month is 0 indexed\n date_parts[1] = date_parts[1] - 1;\n\n let vals = date_parts;\n\n if (time_parts && time_parts.length) {\n if (time_parts.length == 4) {\n time_parts[3] = '0.' + time_parts[3];\n time_parts[3] = parseFloat(time_parts[3]) * 1000;\n }\n vals = vals.concat(time_parts);\n }\n\n return new Date(...vals);\n }\n },\n\n to_string(date, with_time = false) {\n if (!(date instanceof Date)) {\n throw new TypeError('Invalid argument type');\n }\n const vals = this.get_date_values(date).map((val, i) => {\n if (i === 1) {\n // add 1 for month\n val = val + 1;\n }\n\n if (i === 6) {\n return padStart(val + '', 3, '0');\n }\n\n return padStart(val + '', 2, '0');\n });\n const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`;\n const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`;\n\n return date_string + (with_time ? ' ' + time_string : '');\n },\n\n format(date, format_string = 'YYYY-MM-DD HH:mm:ss.SSS', lang = 'en') {\n const dateTimeFormat = new Intl.DateTimeFormat(lang, {\n month: 'long'\n });\n const month_name = dateTimeFormat.format(date);\n const month_name_capitalized =\n month_name.charAt(0).toUpperCase() + month_name.slice(1);\n\n const values = this.get_date_values(date).map(d => padStart(d, 2, 0));\n const format_map = {\n YYYY: values[0],\n MM: padStart(+values[1] + 1, 2, 0),\n DD: values[2],\n HH: values[3],\n mm: values[4],\n ss: values[5],\n SSS: values[6],\n D: values[2],\n MMMM: month_name_capitalized,\n MMM: month_name_capitalized,\n };\n\n let str = format_string;\n const formatted_values = [];\n\n Object.keys(format_map)\n .sort((a, b) => b.length - a.length) // big string first\n .forEach((key) => {\n if (str.includes(key)) {\n str = str.replace(key, `$${formatted_values.length}`);\n formatted_values.push(format_map[key]);\n }\n });\n\n formatted_values.forEach((value, i) => {\n str = str.replace(`$${i}`, value);\n });\n\n return str;\n },\n\n diff(date_a, date_b, scale = DAY) {\n let milliseconds, seconds, hours, minutes, days, months, years;\n\n milliseconds = date_a - date_b;\n seconds = milliseconds / 1000;\n minutes = seconds / 60;\n hours = minutes / 60;\n days = hours / 24;\n months = days / 30;\n years = months / 12;\n\n if (!scale.endsWith('s')) {\n scale += 's';\n }\n\n return Math.floor(\n {\n milliseconds,\n seconds,\n minutes,\n hours,\n days,\n months,\n years,\n }[scale]\n );\n },\n\n today() {\n const vals = this.get_date_values(new Date()).slice(0, 3);\n return new Date(...vals);\n },\n\n now() {\n return new Date();\n },\n\n add(date, qty, scale) {\n qty = parseInt(qty, 10);\n const vals = [\n date.getFullYear() + (scale === YEAR ? qty : 0),\n date.getMonth() + (scale === MONTH ? qty : 0),\n date.getDate() + (scale === DAY ? qty : 0),\n date.getHours() + (scale === HOUR ? qty : 0),\n date.getMinutes() + (scale === MINUTE ? qty : 0),\n date.getSeconds() + (scale === SECOND ? qty : 0),\n date.getMilliseconds() + (scale === MILLISECOND ? qty : 0),\n ];\n return new Date(...vals);\n },\n\n start_of(date, scale) {\n const scores = {\n [YEAR]: 6,\n [MONTH]: 5,\n [DAY]: 4,\n [HOUR]: 3,\n [MINUTE]: 2,\n [SECOND]: 1,\n [MILLISECOND]: 0,\n };\n\n function should_reset(_scale) {\n const max_score = scores[scale];\n return scores[_scale] <= max_score;\n }\n\n const vals = [\n date.getFullYear(),\n should_reset(YEAR) ? 0 : date.getMonth(),\n should_reset(MONTH) ? 1 : date.getDate(),\n should_reset(DAY) ? 0 : date.getHours(),\n should_reset(HOUR) ? 0 : date.getMinutes(),\n should_reset(MINUTE) ? 0 : date.getSeconds(),\n should_reset(SECOND) ? 0 : date.getMilliseconds(),\n ];\n\n return new Date(...vals);\n },\n\n clone(date) {\n return new Date(...this.get_date_values(date));\n },\n\n get_date_values(date) {\n return [\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n ];\n },\n\n get_days_in_month(date) {\n const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\n const month = date.getMonth();\n\n if (month !== 1) {\n return no_of_days[month];\n }\n\n // Feb\n const year = date.getFullYear();\n if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {\n return 29;\n }\n return 28;\n },\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart\nfunction padStart(str, targetLength, padString) {\n str = str + '';\n targetLength = targetLength >> 0;\n padString = String(typeof padString !== 'undefined' ? padString : ' ');\n if (str.length > targetLength) {\n return String(str);\n } else {\n targetLength = targetLength - str.length;\n if (targetLength > padString.length) {\n padString += padString.repeat(targetLength / padString.length);\n }\n return padString.slice(0, targetLength) + String(str);\n }\n}\n","export function $(expr, con) {\n return typeof expr === 'string'\n ? (con || document).querySelector(expr)\n : expr || null;\n}\n\nexport function createSVG(tag, attrs) {\n const elem = document.createElementNS('http://www.w3.org/2000/svg', tag);\n for (let attr in attrs) {\n if (attr === 'append_to') {\n const parent = attrs.append_to;\n parent.appendChild(elem);\n } else if (attr === 'innerHTML') {\n elem.innerHTML = attrs.innerHTML;\n } else {\n elem.setAttribute(attr, attrs[attr]);\n }\n }\n return elem;\n}\n\nexport function animateSVG(svgElement, attr, from, to) {\n const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);\n\n if (animatedSvgElement === svgElement) {\n // triggered 2nd time programmatically\n // trigger artificial click event\n const event = document.createEvent('HTMLEvents');\n event.initEvent('click', true, true);\n event.eventName = 'click';\n animatedSvgElement.dispatchEvent(event);\n }\n}\n\nfunction getAnimationElement(\n svgElement,\n attr,\n from,\n to,\n dur = '0.4s',\n begin = '0.1s'\n) {\n const animEl = svgElement.querySelector('animate');\n if (animEl) {\n $.attr(animEl, {\n attributeName: attr,\n from,\n to,\n dur,\n begin: 'click + ' + begin, // artificial click\n });\n return svgElement;\n }\n\n const animateElement = createSVG('animate', {\n attributeName: attr,\n from,\n to,\n dur,\n begin,\n calcMode: 'spline',\n values: from + ';' + to,\n keyTimes: '0; 1',\n keySplines: cubic_bezier('ease-out'),\n });\n svgElement.appendChild(animateElement);\n\n return svgElement;\n}\n\nfunction cubic_bezier(name) {\n return {\n ease: '.25 .1 .25 1',\n linear: '0 0 1 1',\n 'ease-in': '.42 0 1 1',\n 'ease-out': '0 0 .58 1',\n 'ease-in-out': '.42 0 .58 1',\n }[name];\n}\n\n$.on = (element, event, selector, callback) => {\n if (!callback) {\n callback = selector;\n $.bind(element, event, callback);\n } else {\n $.delegate(element, event, selector, callback);\n }\n};\n\n$.off = (element, event, handler) => {\n element.removeEventListener(event, handler);\n};\n\n$.bind = (element, event, callback) => {\n event.split(/\\s+/).forEach(function (event) {\n element.addEventListener(event, callback);\n });\n};\n\n$.delegate = (element, event, selector, callback) => {\n element.addEventListener(event, function (e) {\n const delegatedTarget = e.target.closest(selector);\n if (delegatedTarget) {\n e.delegatedTarget = delegatedTarget;\n callback.call(this, e, delegatedTarget);\n }\n });\n};\n\n$.closest = (selector, element) => {\n if (!element) return null;\n\n if (element.matches(selector)) {\n return element;\n }\n\n return $.closest(selector, element.parentNode);\n};\n\n$.attr = (element, attr, value) => {\n if (!value && typeof attr === 'string') {\n return element.getAttribute(attr);\n }\n\n if (typeof attr === 'object') {\n for (let key in attr) {\n $.attr(element, key, attr[key]);\n }\n return;\n }\n\n element.setAttribute(attr, value);\n};\n","import date_utils from './date_utils';\nimport { $, createSVG, animateSVG } from './svg_utils';\n\nexport default class Bar {\n constructor(gantt, task) {\n this.set_defaults(gantt, task);\n this.prepare();\n this.draw();\n this.bind();\n }\n\n set_defaults(gantt, task) {\n this.action_completed = false;\n this.gantt = gantt;\n this.task = task;\n }\n\n prepare() {\n this.prepare_values();\n this.prepare_helpers();\n }\n\n prepare_values() {\n this.invalid = this.task.invalid;\n this.height = this.gantt.options.bar_height;\n this.compute_x();\n this.compute_y();\n this.compute_duration();\n this.corner_radius = this.gantt.options.bar_corner_radius;\n this.width = this.gantt.options.column_width * this.duration;\n this.progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.task.progress / 100) || 0;\n this.group = createSVG('g', {\n class: 'bar-wrapper ' + (this.task.custom_class || ''),\n 'data-id': this.task.id,\n });\n this.bar_group = createSVG('g', {\n class: 'bar-group',\n append_to: this.group,\n });\n this.handle_group = createSVG('g', {\n class: 'handle-group',\n append_to: this.group,\n });\n }\n\n prepare_helpers() {\n SVGElement.prototype.getX = function () {\n return +this.getAttribute('x');\n };\n SVGElement.prototype.getY = function () {\n return +this.getAttribute('y');\n };\n SVGElement.prototype.getWidth = function () {\n return +this.getAttribute('width');\n };\n SVGElement.prototype.getHeight = function () {\n return +this.getAttribute('height');\n };\n SVGElement.prototype.getEndX = function () {\n return this.getX() + this.getWidth();\n };\n }\n\n prepare_expected_progress_values() {\n this.compute_expected_progress();\n this.expected_progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.expected_progress / 100) || 0;\n }\n\n draw() {\n this.draw_bar();\n if (this.gantt.options.show_expected_progress) {\n this.prepare_expected_progress_values();\n this.draw_expected_progress_bar();\n }\n this.draw_progress_bar();\n this.draw_label();\n this.draw_resize_handles();\n }\n\n draw_bar() {\n this.$bar = createSVG('rect', {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'bar',\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar, 'width', 0, this.width);\n\n if (this.invalid) {\n this.$bar.classList.add('bar-invalid');\n }\n }\n\n draw_expected_progress_bar() {\n if (this.invalid) return;\n this.$expected_bar_progress = createSVG('rect', {\n x: this.x,\n y: this.y,\n width: this.expected_progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'bar-expected-progress',\n append_to: this.bar_group,\n });\n\n animateSVG(this.$expected_bar_progress, 'width', 0, this.expected_progress_width);\n }\n\n draw_progress_bar() {\n if (this.invalid) return;\n this.$bar_progress = createSVG('rect', {\n x: this.x,\n y: this.y,\n width: this.progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'bar-progress',\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar_progress, 'width', 0, this.progress_width);\n }\n\n draw_label() {\n createSVG('text', {\n x: this.x + this.width / 2,\n y: this.y + this.height / 2,\n innerHTML: this.task.name,\n class: 'bar-label',\n append_to: this.bar_group,\n });\n // labels get BBox in the next tick\n requestAnimationFrame(() => this.update_label_position());\n }\n\n draw_resize_handles() {\n if (this.invalid) return;\n\n const bar = this.$bar;\n const handle_width = 8;\n\n createSVG('rect', {\n x: bar.getX() + bar.getWidth() - 9,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'handle right',\n append_to: this.handle_group,\n });\n\n createSVG('rect', {\n x: bar.getX() + 1,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'handle left',\n append_to: this.handle_group,\n });\n\n if (this.task.progress && this.task.progress < 100) {\n this.$handle_progress = createSVG('polygon', {\n points: this.get_progress_polygon_points().join(','),\n class: 'handle progress',\n append_to: this.handle_group,\n });\n }\n }\n\n get_progress_polygon_points() {\n const bar_progress = this.$bar_progress;\n return [\n bar_progress.getEndX() - 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX() + 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX(),\n bar_progress.getY() + bar_progress.getHeight() - 8.66,\n ];\n }\n\n bind() {\n if (this.invalid) return;\n this.setup_click_event();\n }\n\n setup_click_event() {\n $.on(this.group, 'focus ' + this.gantt.options.popup_trigger, (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.show_popup();\n this.gantt.unselect_all();\n this.group.classList.add('active');\n });\n\n $.on(this.group, 'dblclick', (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.gantt.trigger_event('click', [this.task]);\n });\n }\n\n show_popup() {\n if (this.gantt.bar_being_dragged) return;\n\n const start_date = date_utils.format(\n this.task._start,\n 'MMM D',\n this.gantt.options.language\n );\n const end_date = date_utils.format(\n date_utils.add(this.task._end, -1, 'second'),\n 'MMM D',\n this.gantt.options.language\n );\n const subtitle = start_date + ' - ' + end_date;\n\n this.gantt.show_popup({\n target_element: this.$bar,\n title: this.task.name,\n subtitle: subtitle,\n task: this.task,\n });\n }\n\n update_bar_position({ x = null, width = null }) {\n const bar = this.$bar;\n if (x) {\n // get all x values of parent task\n const xs = this.task.dependencies.map((dep) => {\n return this.gantt.get_bar(dep).$bar.getX();\n });\n // child task must not go before parent\n const valid_x = xs.reduce((prev, curr) => {\n return x >= curr;\n }, x);\n if (!valid_x) {\n width = null;\n return;\n }\n this.update_attr(bar, 'x', x);\n }\n if (width && width >= this.gantt.options.column_width) {\n this.update_attr(bar, 'width', width);\n }\n this.update_label_position();\n this.update_handle_position();\n if (this.gantt.options.show_expected_progress){\n this.date_changed();\n this.compute_duration();\n this.update_expected_progressbar_position();\n }\n this.update_progressbar_position();\n this.update_arrow_position();\n }\n\n date_changed() {\n let changed = false;\n const { new_start_date, new_end_date } = this.compute_start_end_date();\n\n if (Number(this.task._start) !== Number(new_start_date)) {\n changed = true;\n this.task._start = new_start_date;\n }\n\n if (Number(this.task._end) !== Number(new_end_date)) {\n changed = true;\n this.task._end = new_end_date;\n }\n\n if (!changed) return;\n\n this.gantt.trigger_event('date_change', [\n this.task,\n new_start_date,\n date_utils.add(new_end_date, -1, 'second'),\n ]);\n }\n\n progress_changed() {\n const new_progress = this.compute_progress();\n this.task.progress = new_progress;\n this.gantt.trigger_event('progress_change', [this.task, new_progress]);\n }\n\n set_action_completed() {\n this.action_completed = true;\n setTimeout(() => (this.action_completed = false), 1000);\n }\n\n compute_start_end_date() {\n const bar = this.$bar;\n const x_in_units = bar.getX() / this.gantt.options.column_width;\n const new_start_date = date_utils.add(\n this.gantt.gantt_start,\n x_in_units * this.gantt.options.step,\n 'hour'\n );\n const width_in_units = bar.getWidth() / this.gantt.options.column_width;\n const new_end_date = date_utils.add(\n new_start_date,\n width_in_units * this.gantt.options.step,\n 'hour'\n );\n\n return { new_start_date, new_end_date };\n }\n\n compute_progress() {\n const progress =\n (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100;\n return parseInt(progress, 10);\n }\n\n compute_expected_progress() {\n this.expected_progress = date_utils.diff(date_utils.today(), this.task._start, 'hour') / this.gantt.options.step;\n this.expected_progress = ((this.expected_progress < this.duration) ? this.expected_progress : this.duration) * 100 / this.duration;\n }\n\n compute_x() {\n const { step, column_width } = this.gantt.options;\n const task_start = this.task._start;\n const gantt_start = this.gantt.gantt_start;\n\n const diff = date_utils.diff(task_start, gantt_start, 'hour');\n let x = (diff / step) * column_width;\n\n if (this.gantt.view_is('Month')) {\n const diff = date_utils.diff(task_start, gantt_start, 'day');\n x = (diff * column_width) / 30;\n }\n this.x = x;\n }\n\n compute_y() {\n this.y = (\n this.gantt.options.header_height +\n this.gantt.options.padding +\n this.task._index * (this.height + this.gantt.options.padding)\n );\n }\n\n compute_duration() {\n this.duration = date_utils.diff(this.task._end, this.task._start, 'hour') /\n this.gantt.options.step;\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.gantt.view_is('Week')) {\n rem = dx % (this.gantt.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 14\n ? 0\n : this.gantt.options.column_width / 7);\n } else if (this.gantt.view_is('Month')) {\n rem = dx % (this.gantt.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 60\n ? 0\n : this.gantt.options.column_width / 30);\n } else {\n rem = dx % this.gantt.options.column_width;\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 2\n ? 0\n : this.gantt.options.column_width);\n }\n return position;\n }\n\n update_attr(element, attr, value) {\n value = +value;\n if (!isNaN(value)) {\n element.setAttribute(attr, value);\n }\n return element;\n }\n\n update_expected_progressbar_position() {\n if (this.invalid) return;\n this.$expected_bar_progress.setAttribute('x', this.$bar.getX());\n this.compute_expected_progress();\n this.$expected_bar_progress.setAttribute(\n 'width',\n this.gantt.options.column_width * this.duration * (this.expected_progress / 100) || 0\n );\n }\n\n update_progressbar_position() {\n if (this.invalid) return;\n this.$bar_progress.setAttribute('x', this.$bar.getX());\n this.$bar_progress.setAttribute(\n 'width',\n this.$bar.getWidth() * (this.task.progress / 100)\n );\n }\n\n update_label_position() {\n const bar = this.$bar,\n label = this.group.querySelector('.bar-label');\n\n if (label.getBBox().width > bar.getWidth()) {\n label.classList.add('big');\n label.setAttribute('x', bar.getX() + bar.getWidth() + 5);\n } else {\n label.classList.remove('big');\n label.setAttribute('x', bar.getX() + bar.getWidth() / 2);\n }\n }\n\n update_handle_position() {\n if (this.invalid) return;\n const bar = this.$bar;\n this.handle_group\n .querySelector('.handle.left')\n .setAttribute('x', bar.getX() + 1);\n this.handle_group\n .querySelector('.handle.right')\n .setAttribute('x', bar.getEndX() - 9);\n const handle = this.group.querySelector('.handle.progress');\n handle &&\n handle.setAttribute('points', this.get_progress_polygon_points());\n }\n\n update_arrow_position() {\n this.arrows = this.arrows || [];\n for (let arrow of this.arrows) {\n arrow.update();\n }\n }\n}\n\nfunction isFunction(functionToCheck) {\n var getType = {};\n return (\n functionToCheck &&\n getType.toString.call(functionToCheck) === '[object Function]'\n );\n}\n","import { createSVG } from './svg_utils';\n\nexport default class Arrow {\n constructor(gantt, from_task, to_task) {\n this.gantt = gantt;\n this.from_task = from_task;\n this.to_task = to_task;\n\n this.calculate_path();\n this.draw();\n }\n\n calculate_path() {\n let start_x =\n this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;\n\n const condition = () =>\n this.to_task.$bar.getX() < start_x + this.gantt.options.padding &&\n start_x > this.from_task.$bar.getX() + this.gantt.options.padding;\n\n while (condition()) {\n start_x -= 10;\n }\n\n const start_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.from_task.task._index +\n this.gantt.options.padding;\n\n const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2;\n const end_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height / 2 +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.to_task.task._index +\n this.gantt.options.padding;\n\n const from_is_below_to =\n this.from_task.task._index > this.to_task.task._index;\n const curve = this.gantt.options.arrow_curve;\n const clockwise = from_is_below_to ? 1 : 0;\n const curve_y = from_is_below_to ? -curve : curve;\n const offset = from_is_below_to\n ? end_y + this.gantt.options.arrow_curve\n : end_y - this.gantt.options.arrow_curve;\n\n this.path = `\n M ${start_x} ${start_y}\n V ${offset}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n\n if (\n this.to_task.$bar.getX() <\n this.from_task.$bar.getX() + this.gantt.options.padding\n ) {\n const down_1 = this.gantt.options.padding / 2 - curve;\n const down_2 =\n this.to_task.$bar.getY() +\n this.to_task.$bar.getHeight() / 2 -\n curve_y;\n const left = this.to_task.$bar.getX() - this.gantt.options.padding;\n\n this.path = `\n M ${start_x} ${start_y}\n v ${down_1}\n a ${curve} ${curve} 0 0 1 -${curve} ${curve}\n H ${left}\n a ${curve} ${curve} 0 0 ${clockwise} -${curve} ${curve_y}\n V ${down_2}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n }\n }\n\n draw() {\n this.element = createSVG('path', {\n d: this.path,\n 'data-from': this.from_task.task.id,\n 'data-to': this.to_task.task.id,\n });\n }\n\n update() {\n this.calculate_path();\n this.element.setAttribute('d', this.path);\n }\n}\n","export default class Popup {\n constructor(parent, custom_html) {\n this.parent = parent;\n this.custom_html = custom_html;\n this.make();\n }\n\n make() {\n this.parent.innerHTML = `\n
\n
\n
\n `;\n\n this.hide();\n\n this.title = this.parent.querySelector('.title');\n this.subtitle = this.parent.querySelector('.subtitle');\n this.pointer = this.parent.querySelector('.pointer');\n }\n\n show(options) {\n if (!options.target_element) {\n throw new Error('target_element is required to show popup');\n }\n if (!options.position) {\n options.position = 'left';\n }\n const target_element = options.target_element;\n\n if (this.custom_html) {\n let html = this.custom_html(options.task);\n html += '
';\n this.parent.innerHTML = html;\n this.pointer = this.parent.querySelector('.pointer');\n } else {\n // set data\n this.title.innerHTML = options.title;\n this.subtitle.innerHTML = options.subtitle;\n this.parent.style.width = this.parent.clientWidth + 'px';\n }\n\n // set position\n let position_meta;\n if (target_element instanceof HTMLElement) {\n position_meta = target_element.getBoundingClientRect();\n } else if (target_element instanceof SVGElement) {\n position_meta = options.target_element.getBBox();\n }\n\n if (options.position === 'left') {\n this.parent.style.left =\n position_meta.x + (position_meta.width + 10) + 'px';\n this.parent.style.top = position_meta.y + 'px';\n\n this.pointer.style.transform = 'rotateZ(90deg)';\n this.pointer.style.left = '-7px';\n this.pointer.style.top = '2px';\n }\n\n // show\n this.parent.style.opacity = 1;\n }\n\n hide() {\n this.parent.style.opacity = 0;\n this.parent.style.left = 0;\n }\n}\n","import date_utils from './date_utils';\nimport { $, createSVG } from './svg_utils';\nimport Bar from './bar';\nimport Arrow from './arrow';\nimport Popup from './popup';\n\nimport './gantt.scss';\n\nconst VIEW_MODE = {\n QUARTER_DAY: 'Quarter Day',\n HALF_DAY: 'Half Day',\n DAY: 'Day',\n WEEK: 'Week',\n MONTH: 'Month',\n YEAR: 'Year',\n};\n\nexport default class Gantt {\n constructor(wrapper, tasks, options) {\n this.setup_wrapper(wrapper);\n this.setup_options(options);\n this.setup_tasks(tasks);\n // initialize with default view mode\n this.change_view_mode();\n this.bind_events();\n }\n\n setup_wrapper(element) {\n let svg_element, wrapper_element;\n\n // CSS Selector is passed\n if (typeof element === 'string') {\n element = document.querySelector(element);\n }\n\n // get the SVGElement\n if (element instanceof HTMLElement) {\n wrapper_element = element;\n svg_element = element.querySelector('svg');\n } else if (element instanceof SVGElement) {\n svg_element = element;\n } else {\n throw new TypeError(\n 'Frappé Gantt only supports usage of a string CSS selector,' +\n \" HTML DOM element or SVG DOM element for the 'element' parameter\"\n );\n }\n\n // svg element\n if (!svg_element) {\n // create it\n this.$svg = createSVG('svg', {\n append_to: wrapper_element,\n class: 'gantt',\n });\n } else {\n this.$svg = svg_element;\n this.$svg.classList.add('gantt');\n }\n\n // wrapper element\n this.$container = document.createElement('div');\n this.$container.classList.add('gantt-container');\n\n const parent_element = this.$svg.parentElement;\n parent_element.appendChild(this.$container);\n this.$container.appendChild(this.$svg);\n\n // popup wrapper\n this.popup_wrapper = document.createElement('div');\n this.popup_wrapper.classList.add('popup-wrapper');\n this.$container.appendChild(this.popup_wrapper);\n }\n\n setup_options(options) {\n const default_options = {\n header_height: 50,\n column_width: 30,\n step: 24,\n view_modes: [...Object.values(VIEW_MODE)],\n bar_height: 20,\n bar_corner_radius: 3,\n arrow_curve: 5,\n padding: 18,\n view_mode: 'Day',\n date_format: 'YYYY-MM-DD',\n popup_trigger: 'click',\n custom_popup_html: null,\n language: 'en',\n };\n this.options = Object.assign({}, default_options, options);\n }\n\n setup_tasks(tasks) {\n // prepare tasks\n this.tasks = tasks.map((task, i) => {\n // convert to Date objects\n task._start = date_utils.parse(task.start);\n task._end = date_utils.parse(task.end);\n\n // make task invalid if duration too large\n if (date_utils.diff(task._end, task._start, 'year') > 10) {\n task.end = null;\n }\n\n // cache index\n task._index = i;\n\n // invalid dates\n if (!task.start && !task.end) {\n const today = date_utils.today();\n task._start = today;\n task._end = date_utils.add(today, 2, 'day');\n }\n\n if (!task.start && task.end) {\n task._start = date_utils.add(task._end, -2, 'day');\n }\n\n if (task.start && !task.end) {\n task._end = date_utils.add(task._start, 2, 'day');\n }\n\n // if hours is not set, assume the last day is full day\n // e.g: 2018-09-09 becomes 2018-09-09 23:59:59\n const task_end_values = date_utils.get_date_values(task._end);\n if (task_end_values.slice(3).every((d) => d === 0)) {\n task._end = date_utils.add(task._end, 24, 'hour');\n }\n\n // invalid flag\n if (!task.start || !task.end) {\n task.invalid = true;\n }\n\n // dependencies\n if (typeof task.dependencies === 'string' || !task.dependencies) {\n let deps = [];\n if (task.dependencies) {\n deps = task.dependencies\n .split(',')\n .map((d) => d.trim())\n .filter((d) => d);\n }\n task.dependencies = deps;\n }\n\n // uids\n if (!task.id) {\n task.id = generate_id(task);\n }\n\n return task;\n });\n\n this.setup_dependencies();\n }\n\n setup_dependencies() {\n this.dependency_map = {};\n for (let t of this.tasks) {\n for (let d of t.dependencies) {\n this.dependency_map[d] = this.dependency_map[d] || [];\n this.dependency_map[d].push(t.id);\n }\n }\n }\n\n refresh(tasks) {\n this.setup_tasks(tasks);\n this.change_view_mode();\n }\n\n change_view_mode(mode = this.options.view_mode) {\n this.update_view_scale(mode);\n this.setup_dates();\n this.render();\n // fire viewmode_change event\n this.trigger_event('view_change', [mode]);\n }\n\n update_view_scale(view_mode) {\n this.options.view_mode = view_mode;\n\n if (view_mode === VIEW_MODE.DAY) {\n this.options.step = 24;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.HALF_DAY) {\n this.options.step = 24 / 2;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.QUARTER_DAY) {\n this.options.step = 24 / 4;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.WEEK) {\n this.options.step = 24 * 7;\n this.options.column_width = 140;\n } else if (view_mode === VIEW_MODE.MONTH) {\n this.options.step = 24 * 30;\n this.options.column_width = 120;\n } else if (view_mode === VIEW_MODE.YEAR) {\n this.options.step = 24 * 365;\n this.options.column_width = 120;\n }\n }\n\n setup_dates() {\n this.setup_gantt_dates();\n this.setup_date_values();\n }\n\n setup_gantt_dates() {\n this.gantt_start = this.gantt_end = null;\n\n for (let task of this.tasks) {\n // set global start and end date\n if (!this.gantt_start || task._start < this.gantt_start) {\n this.gantt_start = task._start;\n }\n if (!this.gantt_end || task._end > this.gantt_end) {\n this.gantt_end = task._end;\n }\n }\n\n this.gantt_start = date_utils.start_of(this.gantt_start, 'day');\n this.gantt_end = date_utils.start_of(this.gantt_end, 'day');\n\n // add date padding on both sides\n if (this.view_is([VIEW_MODE.QUARTER_DAY, VIEW_MODE.HALF_DAY])) {\n this.gantt_start = date_utils.add(this.gantt_start, -7, 'day');\n this.gantt_end = date_utils.add(this.gantt_end, 7, 'day');\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n this.gantt_start = date_utils.start_of(this.gantt_start, 'year');\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'year');\n } else if (this.view_is(VIEW_MODE.YEAR)) {\n this.gantt_start = date_utils.add(this.gantt_start, -2, 'year');\n this.gantt_end = date_utils.add(this.gantt_end, 2, 'year');\n } else {\n this.gantt_start = date_utils.add(this.gantt_start, -1, 'month');\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'month');\n }\n }\n\n setup_date_values() {\n this.dates = [];\n let cur_date = null;\n\n while (cur_date === null || cur_date < this.gantt_end) {\n if (!cur_date) {\n cur_date = date_utils.clone(this.gantt_start);\n } else {\n if (this.view_is(VIEW_MODE.YEAR)) {\n cur_date = date_utils.add(cur_date, 1, 'year');\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n cur_date = date_utils.add(cur_date, 1, 'month');\n } else {\n cur_date = date_utils.add(\n cur_date,\n this.options.step,\n 'hour'\n );\n }\n }\n this.dates.push(cur_date);\n }\n }\n\n bind_events() {\n this.bind_grid_click();\n this.bind_bar_events();\n }\n\n render() {\n this.clear();\n this.setup_layers();\n this.make_grid();\n this.make_dates();\n this.make_bars();\n this.make_arrows();\n this.map_arrows_on_bars();\n this.set_width();\n this.set_scroll_position();\n }\n\n setup_layers() {\n this.layers = {};\n const layers = ['grid', 'date', 'arrow', 'progress', 'bar', 'details'];\n // make group layers\n for (let layer of layers) {\n this.layers[layer] = createSVG('g', {\n class: layer,\n append_to: this.$svg,\n });\n }\n }\n\n make_grid() {\n this.make_grid_background();\n this.make_grid_rows();\n this.make_grid_header();\n this.make_grid_ticks();\n this.make_grid_highlights();\n }\n\n make_grid_background() {\n const grid_width = this.dates.length * this.options.column_width;\n const grid_height =\n this.options.header_height +\n this.options.padding +\n (this.options.bar_height + this.options.padding) *\n this.tasks.length;\n\n createSVG('rect', {\n x: 0,\n y: 0,\n width: grid_width,\n height: grid_height,\n class: 'grid-background',\n append_to: this.layers.grid,\n });\n\n $.attr(this.$svg, {\n height: grid_height + this.options.padding + 100,\n width: '100%',\n });\n }\n\n make_grid_rows() {\n const rows_layer = createSVG('g', { append_to: this.layers.grid });\n const lines_layer = createSVG('g', { append_to: this.layers.grid });\n\n const row_width = this.dates.length * this.options.column_width;\n const row_height = this.options.bar_height + this.options.padding;\n\n let row_y = this.options.header_height + this.options.padding / 2;\n\n for (let task of this.tasks) {\n createSVG('rect', {\n x: 0,\n y: row_y,\n width: row_width,\n height: row_height,\n class: 'grid-row',\n append_to: rows_layer,\n });\n\n createSVG('line', {\n x1: 0,\n y1: row_y + row_height,\n x2: row_width,\n y2: row_y + row_height,\n class: 'row-line',\n append_to: lines_layer,\n });\n\n row_y += this.options.bar_height + this.options.padding;\n }\n }\n\n make_grid_header() {\n const header_width = this.dates.length * this.options.column_width;\n const header_height = this.options.header_height + 10;\n createSVG('rect', {\n x: 0,\n y: 0,\n width: header_width,\n height: header_height,\n class: 'grid-header',\n append_to: this.layers.grid,\n });\n }\n\n make_grid_ticks() {\n let tick_x = 0;\n let tick_y = this.options.header_height + this.options.padding / 2;\n let tick_height =\n (this.options.bar_height + this.options.padding) *\n this.tasks.length;\n\n for (let date of this.dates) {\n let tick_class = 'tick';\n // thick tick for monday\n if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) {\n tick_class += ' thick';\n }\n // thick tick for first week\n if (\n this.view_is(VIEW_MODE.WEEK) &&\n date.getDate() >= 1 &&\n date.getDate() < 8\n ) {\n tick_class += ' thick';\n }\n // thick ticks for quarters\n if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) {\n tick_class += ' thick';\n }\n\n createSVG('path', {\n d: `M ${tick_x} ${tick_y} v ${tick_height}`,\n class: tick_class,\n append_to: this.layers.grid,\n });\n\n if (this.view_is(VIEW_MODE.MONTH)) {\n tick_x +=\n (date_utils.get_days_in_month(date) *\n this.options.column_width) /\n 30;\n } else {\n tick_x += this.options.column_width;\n }\n }\n }\n\n make_grid_highlights() {\n // highlight today's date\n if (this.view_is(VIEW_MODE.DAY)) {\n const x =\n (date_utils.diff(date_utils.today(), this.gantt_start, 'hour') /\n this.options.step) *\n this.options.column_width;\n const y = 0;\n\n const width = this.options.column_width;\n const height =\n (this.options.bar_height + this.options.padding) *\n this.tasks.length +\n this.options.header_height +\n this.options.padding / 2;\n\n createSVG('rect', {\n x,\n y,\n width,\n height,\n class: 'today-highlight',\n append_to: this.layers.grid,\n });\n }\n }\n\n make_dates() {\n for (let date of this.get_dates_to_draw()) {\n createSVG('text', {\n x: date.lower_x,\n y: date.lower_y,\n innerHTML: date.lower_text,\n class: 'lower-text',\n append_to: this.layers.date,\n });\n\n if (date.upper_text) {\n const $upper_text = createSVG('text', {\n x: date.upper_x,\n y: date.upper_y,\n innerHTML: date.upper_text,\n class: 'upper-text',\n append_to: this.layers.date,\n });\n\n // remove out-of-bound dates\n if (\n $upper_text.getBBox().x2 > this.layers.grid.getBBox().width\n ) {\n $upper_text.remove();\n }\n }\n }\n }\n\n get_dates_to_draw() {\n let last_date = null;\n const dates = this.dates.map((date, i) => {\n const d = this.get_date_info(date, last_date, i);\n last_date = date;\n return d;\n });\n return dates;\n }\n\n get_date_info(date, last_date, i) {\n if (!last_date) {\n last_date = date_utils.add(date, 1, 'year');\n }\n const date_text = {\n 'Quarter Day_lower': date_utils.format(\n date,\n 'HH',\n this.options.language\n ),\n 'Half Day_lower': date_utils.format(\n date,\n 'HH',\n this.options.language\n ),\n Day_lower:\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, 'D', this.options.language)\n : '',\n Week_lower:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, 'D MMM', this.options.language)\n : date_utils.format(date, 'D', this.options.language),\n Month_lower: date_utils.format(date, 'MMMM', this.options.language),\n Year_lower: date_utils.format(date, 'YYYY', this.options.language),\n 'Quarter Day_upper':\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, 'D MMM', this.options.language)\n : '',\n 'Half Day_upper':\n date.getDate() !== last_date.getDate()\n ? date.getMonth() !== last_date.getMonth()\n ? date_utils.format(\n date,\n 'D MMM',\n this.options.language\n )\n : date_utils.format(date, 'D', this.options.language)\n : '',\n Day_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, 'MMMM', this.options.language)\n : '',\n Week_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, 'MMMM', this.options.language)\n : '',\n Month_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, 'YYYY', this.options.language)\n : '',\n Year_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, 'YYYY', this.options.language)\n : '',\n };\n\n const base_pos = {\n x: i * this.options.column_width,\n lower_y: this.options.header_height,\n upper_y: this.options.header_height - 25,\n };\n\n const x_pos = {\n 'Quarter Day_lower': (this.options.column_width * 4) / 2,\n 'Quarter Day_upper': 0,\n 'Half Day_lower': (this.options.column_width * 2) / 2,\n 'Half Day_upper': 0,\n Day_lower: this.options.column_width / 2,\n Day_upper: (this.options.column_width * 30) / 2,\n Week_lower: 0,\n Week_upper: (this.options.column_width * 4) / 2,\n Month_lower: this.options.column_width / 2,\n Month_upper: (this.options.column_width * 12) / 2,\n Year_lower: this.options.column_width / 2,\n Year_upper: (this.options.column_width * 30) / 2,\n };\n\n return {\n upper_text: date_text[`${this.options.view_mode}_upper`],\n lower_text: date_text[`${this.options.view_mode}_lower`],\n upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`],\n upper_y: base_pos.upper_y,\n lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`],\n lower_y: base_pos.lower_y,\n };\n }\n\n make_bars() {\n this.bars = this.tasks.map((task) => {\n const bar = new Bar(this, task);\n this.layers.bar.appendChild(bar.group);\n return bar;\n });\n }\n\n make_arrows() {\n this.arrows = [];\n for (let task of this.tasks) {\n let arrows = [];\n arrows = task.dependencies\n .map((task_id) => {\n const dependency = this.get_task(task_id);\n if (!dependency) return;\n const arrow = new Arrow(\n this,\n this.bars[dependency._index], // from_task\n this.bars[task._index] // to_task\n );\n this.layers.arrow.appendChild(arrow.element);\n return arrow;\n })\n .filter(Boolean); // filter falsy values\n this.arrows = this.arrows.concat(arrows);\n }\n }\n\n map_arrows_on_bars() {\n for (let bar of this.bars) {\n bar.arrows = this.arrows.filter((arrow) => {\n return (\n arrow.from_task.task.id === bar.task.id ||\n arrow.to_task.task.id === bar.task.id\n );\n });\n }\n }\n\n set_width() {\n const cur_width = this.$svg.getBoundingClientRect().width;\n const actual_width = this.$svg\n .querySelector('.grid .grid-row')\n .getAttribute('width');\n if (cur_width < actual_width) {\n this.$svg.setAttribute('width', actual_width);\n }\n }\n\n set_scroll_position() {\n const parent_element = this.$svg.parentElement;\n if (!parent_element) return;\n\n const hours_before_first_task = date_utils.diff(\n this.get_oldest_starting_date(),\n this.gantt_start,\n 'hour'\n );\n\n const scroll_pos =\n (hours_before_first_task / this.options.step) *\n this.options.column_width -\n this.options.column_width;\n\n parent_element.scrollLeft = scroll_pos;\n }\n\n bind_grid_click() {\n $.on(\n this.$svg,\n this.options.popup_trigger,\n '.grid-row, .grid-header',\n () => {\n this.unselect_all();\n this.hide_popup();\n }\n );\n }\n\n bind_bar_events() {\n let is_dragging = false;\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing_left = false;\n let is_resizing_right = false;\n let parent_bar_id = null;\n let bars = []; // instanceof Bar\n this.bar_being_dragged = null;\n\n function action_in_progress() {\n return is_dragging || is_resizing_left || is_resizing_right;\n }\n\n $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => {\n const bar_wrapper = $.closest('.bar-wrapper', element);\n\n if (element.classList.contains('left')) {\n is_resizing_left = true;\n } else if (element.classList.contains('right')) {\n is_resizing_right = true;\n } else if (element.classList.contains('bar-wrapper')) {\n is_dragging = true;\n }\n\n bar_wrapper.classList.add('active');\n\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n parent_bar_id = bar_wrapper.getAttribute('data-id');\n const ids = [\n parent_bar_id,\n ...this.get_all_dependent_tasks(parent_bar_id),\n ];\n bars = ids.map((id) => this.get_bar(id));\n\n this.bar_being_dragged = parent_bar_id;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.ox = $bar.getX();\n $bar.oy = $bar.getY();\n $bar.owidth = $bar.getWidth();\n $bar.finaldx = 0;\n });\n });\n\n $.on(this.$svg, 'mousemove', (e) => {\n if (!action_in_progress()) return;\n const dx = e.offsetX - x_on_start;\n const dy = e.offsetY - y_on_start;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.finaldx = this.get_snap_position(dx);\n this.hide_popup();\n if (is_resizing_left) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n width: $bar.owidth - $bar.finaldx,\n });\n } else {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n });\n }\n } else if (is_resizing_right) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n width: $bar.owidth + $bar.finaldx,\n });\n }\n } else if (is_dragging) {\n bar.update_bar_position({ x: $bar.ox + $bar.finaldx });\n }\n });\n });\n\n document.addEventListener('mouseup', (e) => {\n if (is_dragging || is_resizing_left || is_resizing_right) {\n bars.forEach((bar) => bar.group.classList.remove('active'));\n }\n\n is_dragging = false;\n is_resizing_left = false;\n is_resizing_right = false;\n });\n\n $.on(this.$svg, 'mouseup', (e) => {\n this.bar_being_dragged = null;\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n if (!$bar.finaldx) return;\n bar.date_changed();\n bar.set_action_completed();\n });\n });\n\n this.bind_bar_progress();\n }\n\n bind_bar_progress() {\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing = null;\n let bar = null;\n let $bar_progress = null;\n let $bar = null;\n\n $.on(this.$svg, 'mousedown', '.handle.progress', (e, handle) => {\n is_resizing = true;\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n const $bar_wrapper = $.closest('.bar-wrapper', handle);\n const id = $bar_wrapper.getAttribute('data-id');\n bar = this.get_bar(id);\n\n $bar_progress = bar.$bar_progress;\n $bar = bar.$bar;\n\n $bar_progress.finaldx = 0;\n $bar_progress.owidth = $bar_progress.getWidth();\n $bar_progress.min_dx = -$bar_progress.getWidth();\n $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth();\n });\n\n $.on(this.$svg, 'mousemove', (e) => {\n if (!is_resizing) return;\n let dx = e.offsetX - x_on_start;\n let dy = e.offsetY - y_on_start;\n\n if (dx > $bar_progress.max_dx) {\n dx = $bar_progress.max_dx;\n }\n if (dx < $bar_progress.min_dx) {\n dx = $bar_progress.min_dx;\n }\n\n const $handle = bar.$handle_progress;\n $.attr($bar_progress, 'width', $bar_progress.owidth + dx);\n $.attr($handle, 'points', bar.get_progress_polygon_points());\n $bar_progress.finaldx = dx;\n });\n\n $.on(this.$svg, 'mouseup', () => {\n is_resizing = false;\n if (!($bar_progress && $bar_progress.finaldx)) return;\n bar.progress_changed();\n bar.set_action_completed();\n });\n }\n\n get_all_dependent_tasks(task_id) {\n let out = [];\n let to_process = [task_id];\n while (to_process.length) {\n const deps = to_process.reduce((acc, curr) => {\n acc = acc.concat(this.dependency_map[curr]);\n return acc;\n }, []);\n\n out = out.concat(deps);\n to_process = deps.filter((d) => !to_process.includes(d));\n }\n\n return out.filter(Boolean);\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.view_is(VIEW_MODE.WEEK)) {\n rem = dx % (this.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 14\n ? 0\n : this.options.column_width / 7);\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n rem = dx % (this.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 60\n ? 0\n : this.options.column_width / 30);\n } else {\n rem = dx % this.options.column_width;\n position =\n odx -\n rem +\n (rem < this.options.column_width / 2\n ? 0\n : this.options.column_width);\n }\n return position;\n }\n\n unselect_all() {\n [...this.$svg.querySelectorAll('.bar-wrapper')].forEach((el) => {\n el.classList.remove('active');\n });\n }\n\n view_is(modes) {\n if (typeof modes === 'string') {\n return this.options.view_mode === modes;\n }\n\n if (Array.isArray(modes)) {\n return modes.some((mode) => this.options.view_mode === mode);\n }\n\n return false;\n }\n\n get_task(id) {\n return this.tasks.find((task) => {\n return task.id === id;\n });\n }\n\n get_bar(id) {\n return this.bars.find((bar) => {\n return bar.task.id === id;\n });\n }\n\n show_popup(options) {\n if (!this.popup) {\n this.popup = new Popup(\n this.popup_wrapper,\n this.options.custom_popup_html\n );\n }\n this.popup.show(options);\n }\n\n hide_popup() {\n this.popup && this.popup.hide();\n }\n\n trigger_event(event, args) {\n if (this.options['on_' + event]) {\n this.options['on_' + event].apply(null, args);\n }\n }\n\n /**\n * Gets the oldest starting date from the list of tasks\n *\n * @returns Date\n * @memberof Gantt\n */\n get_oldest_starting_date() {\n return this.tasks\n .map((task) => task._start)\n .reduce((prev_date, cur_date) =>\n cur_date <= prev_date ? cur_date : prev_date\n );\n }\n\n /**\n * Clear all elements from the parent svg element\n *\n * @memberof Gantt\n */\n clear() {\n this.$svg.innerHTML = '';\n }\n}\n\nGantt.VIEW_MODE = VIEW_MODE;\n\nfunction generate_id(task) {\n return task.name + '_' + Math.random().toString(36).slice(2, 12);\n}\n"],"names":["YEAR","MONTH","DAY","HOUR","MINUTE","SECOND","MILLISECOND","date_utils","parse","date","date_separator","time_separator","Date","date_parts","time_parts","parts","split","map","val","parseInt","vals","length","parseFloat","concat","to_string","with_time","TypeError","this","get_date_values","i","padStart","date_string","time_string","format","format_string","lang","month_name","Intl","DateTimeFormat","month","month_name_capitalized","charAt","toUpperCase","slice","values","d","format_map","YYYY","MM","DD","HH","mm","ss","SSS","D","MMMM","MMM","str","formatted_values","Object","keys","sort","a","b","forEach","key","includes","replace","push","value","diff","date_a","date_b","scale","milliseconds","seconds","hours","minutes","days","months","years","endsWith","Math","floor","today","now","add","qty","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getMilliseconds","start_of","scores","should_reset","_scale","clone","get_days_in_month","no_of_days","year","targetLength","padString","String","repeat","$","expr","con","document","querySelector","createSVG","tag","attrs","elem","createElementNS","attr","append_to","appendChild","innerHTML","setAttribute","animateSVG","svgElement","from","to","animatedSvgElement","dur","begin","animEl","attributeName","animateElement","calcMode","keyTimes","keySplines","cubic_bezier","getAnimationElement","event","createEvent","initEvent","eventName","dispatchEvent","name","ease","linear","on","element","selector","callback","delegate","bind","off","handler","removeEventListener","addEventListener","e","delegatedTarget","target","closest","call","matches","parentNode","getAttribute","Bar","constructor","gantt","task","set_defaults","prepare","draw","action_completed","prepare_values","prepare_helpers","invalid","height","options","bar_height","compute_x","compute_y","compute_duration","corner_radius","bar_corner_radius","width","column_width","duration","progress_width","progress","group","class","custom_class","id","bar_group","handle_group","SVGElement","prototype","getX","getY","getWidth","getHeight","getEndX","prepare_expected_progress_values","compute_expected_progress","expected_progress_width","expected_progress","draw_bar","show_expected_progress","draw_expected_progress_bar","draw_progress_bar","draw_label","draw_resize_handles","$bar","x","y","rx","ry","classList","$expected_bar_progress","$bar_progress","requestAnimationFrame","update_label_position","bar","$handle_progress","points","get_progress_polygon_points","join","bar_progress","setup_click_event","popup_trigger","show_popup","unselect_all","trigger_event","bar_being_dragged","subtitle","_start","language","_end","target_element","title","update_bar_position","dependencies","dep","get_bar","reduce","prev","curr","update_attr","update_handle_position","date_changed","update_expected_progressbar_position","update_progressbar_position","update_arrow_position","changed","new_start_date","new_end_date","compute_start_end_date","Number","progress_changed","new_progress","compute_progress","set_action_completed","setTimeout","x_in_units","gantt_start","step","width_in_units","task_start","view_is","header_height","padding","_index","get_snap_position","dx","rem","position","odx","isNaN","label","getBBox","remove","handle","arrows","arrow","update","Arrow","from_task","to_task","calculate_path","start_x","condition","start_y","end_x","end_y","from_is_below_to","curve","arrow_curve","clockwise","curve_y","offset","path","down_1","down_2","left","Popup","parent","custom_html","make","hide","pointer","show","Error","html","style","clientWidth","position_meta","HTMLElement","getBoundingClientRect","top","transform","opacity","VIEW_MODE","QUARTER_DAY","HALF_DAY","WEEK","Gantt","wrapper","tasks","setup_wrapper","setup_options","setup_tasks","change_view_mode","bind_events","svg_element","wrapper_element","$svg","$container","createElement","parentElement","popup_wrapper","default_options","view_modes","view_mode","date_format","custom_popup_html","assign","start","end","every","deps","trim","filter","random","toString","generate_id","setup_dependencies","dependency_map","t","refresh","mode","update_view_scale","setup_dates","render","setup_gantt_dates","setup_date_values","gantt_end","dates","cur_date","bind_grid_click","bind_bar_events","clear","setup_layers","make_grid","make_dates","make_bars","make_arrows","map_arrows_on_bars","set_width","set_scroll_position","layers","layer","make_grid_background","make_grid_rows","make_grid_header","make_grid_ticks","make_grid_highlights","grid_width","grid_height","grid","rows_layer","lines_layer","row_width","row_height","row_y","x1","y1","x2","y2","tick_x","tick_y","tick_height","tick_class","get_dates_to_draw","lower_x","lower_y","lower_text","upper_text","$upper_text","upper_x","upper_y","last_date","get_date_info","date_text","Day_lower","Week_lower","Month_lower","Year_lower","Day_upper","Week_upper","Month_upper","Year_upper","base_pos","x_pos","bars","task_id","dependency","get_task","Boolean","cur_width","actual_width","parent_element","scroll_pos","get_oldest_starting_date","scrollLeft","hide_popup","is_dragging","x_on_start","y_on_start","is_resizing_left","is_resizing_right","parent_bar_id","bar_wrapper","contains","offsetX","offsetY","ids","get_all_dependent_tasks","ox","oy","owidth","finaldx","bind_bar_progress","is_resizing","min_dx","max_dx","$handle","out","to_process","acc","querySelectorAll","el","modes","Array","isArray","some","find","popup","args","apply","prev_date"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"frappe-gantt.min.js","sources":["../src/date_utils.js","../src/svg_utils.js","../src/bar.js","../src/arrow.js","../src/popup.js","../src/index.js"],"sourcesContent":["const YEAR = 'year';\r\nconst MONTH = 'month';\r\nconst DAY = 'day';\r\nconst HOUR = 'hour';\r\nconst MINUTE = 'minute';\r\nconst SECOND = 'second';\r\nconst MILLISECOND = 'millisecond';\r\n\r\nexport default {\r\n parse(date, date_separator = '-', time_separator = /[.:]/) {\r\n if (date instanceof Date) {\r\n return date;\r\n }\r\n if (typeof date === 'string') {\r\n let date_parts, time_parts;\r\n const parts = date.split(' ');\r\n\r\n date_parts = parts[0]\r\n .split(date_separator)\r\n .map((val) => parseInt(val, 10));\r\n time_parts = parts[1] && parts[1].split(time_separator);\r\n\r\n // month is 0 indexed\r\n date_parts[1] = date_parts[1] - 1;\r\n\r\n let vals = date_parts;\r\n\r\n if (time_parts && time_parts.length) {\r\n if (time_parts.length == 4) {\r\n time_parts[3] = '0.' + time_parts[3];\r\n time_parts[3] = parseFloat(time_parts[3]) * 1000;\r\n }\r\n vals = vals.concat(time_parts);\r\n }\r\n\r\n return new Date(...vals);\r\n }\r\n },\r\n\r\n to_string(date, with_time = false) {\r\n if (!(date instanceof Date)) {\r\n throw new TypeError('Invalid argument type');\r\n }\r\n const vals = this.get_date_values(date).map((val, i) => {\r\n if (i === 1) {\r\n // add 1 for month\r\n val = val + 1;\r\n }\r\n\r\n if (i === 6) {\r\n return padStart(val + '', 3, '0');\r\n }\r\n\r\n return padStart(val + '', 2, '0');\r\n });\r\n const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`;\r\n const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`;\r\n\r\n return date_string + (with_time ? ' ' + time_string : '');\r\n },\r\n\r\n format(date, format_string = 'YYYY-MM-DD HH:mm:ss.SSS', lang = 'en') {\r\n const dateTimeFormat = new Intl.DateTimeFormat(lang, {\r\n month: 'long'\r\n });\r\n const month_name = dateTimeFormat.format(date);\r\n const month_name_capitalized =\r\n month_name.charAt(0).toUpperCase() + month_name.slice(1);\r\n\r\n const values = this.get_date_values(date).map(d => padStart(d, 2, 0));\r\n const format_map = {\r\n YYYY: values[0],\r\n MM: padStart(+values[1] + 1, 2, 0),\r\n DD: values[2],\r\n HH: values[3],\r\n mm: values[4],\r\n ss: values[5],\r\n SSS: values[6],\r\n D: values[2],\r\n MMMM: month_name_capitalized,\r\n MMM: month_name_capitalized,\r\n };\r\n\r\n let str = format_string;\r\n const formatted_values = [];\r\n\r\n Object.keys(format_map)\r\n .sort((a, b) => b.length - a.length) // big string first\r\n .forEach((key) => {\r\n if (str.includes(key)) {\r\n str = str.replace(key, `$${formatted_values.length}`);\r\n formatted_values.push(format_map[key]);\r\n }\r\n });\r\n\r\n formatted_values.forEach((value, i) => {\r\n str = str.replace(`$${i}`, value);\r\n });\r\n\r\n return str;\r\n },\r\n\r\n diff(date_a, date_b, scale = DAY) {\r\n let milliseconds, seconds, hours, minutes, days, months, years;\r\n\r\n milliseconds = date_a - date_b;\r\n seconds = milliseconds / 1000;\r\n minutes = seconds / 60;\r\n hours = minutes / 60;\r\n days = hours / 24;\r\n months = days / 30;\r\n years = months / 12;\r\n\r\n if (!scale.endsWith('s')) {\r\n scale += 's';\r\n }\r\n\r\n return Math.floor(\r\n {\r\n milliseconds,\r\n seconds,\r\n minutes,\r\n hours,\r\n days,\r\n months,\r\n years,\r\n }[scale]\r\n );\r\n },\r\n\r\n today() {\r\n const vals = this.get_date_values(new Date()).slice(0, 3);\r\n return new Date(...vals);\r\n },\r\n\r\n now() {\r\n return new Date();\r\n },\r\n\r\n add(date, qty, scale) {\r\n qty = parseInt(qty, 10);\r\n const vals = [\r\n date.getFullYear() + (scale === YEAR ? qty : 0),\r\n date.getMonth() + (scale === MONTH ? qty : 0),\r\n date.getDate() + (scale === DAY ? qty : 0),\r\n date.getHours() + (scale === HOUR ? qty : 0),\r\n date.getMinutes() + (scale === MINUTE ? qty : 0),\r\n date.getSeconds() + (scale === SECOND ? qty : 0),\r\n date.getMilliseconds() + (scale === MILLISECOND ? qty : 0),\r\n ];\r\n return new Date(...vals);\r\n },\r\n\r\n start_of(date, scale) {\r\n const scores = {\r\n [YEAR]: 6,\r\n [MONTH]: 5,\r\n [DAY]: 4,\r\n [HOUR]: 3,\r\n [MINUTE]: 2,\r\n [SECOND]: 1,\r\n [MILLISECOND]: 0,\r\n };\r\n\r\n function should_reset(_scale) {\r\n const max_score = scores[scale];\r\n return scores[_scale] <= max_score;\r\n }\r\n\r\n const vals = [\r\n date.getFullYear(),\r\n should_reset(YEAR) ? 0 : date.getMonth(),\r\n should_reset(MONTH) ? 1 : date.getDate(),\r\n should_reset(DAY) ? 0 : date.getHours(),\r\n should_reset(HOUR) ? 0 : date.getMinutes(),\r\n should_reset(MINUTE) ? 0 : date.getSeconds(),\r\n should_reset(SECOND) ? 0 : date.getMilliseconds(),\r\n ];\r\n\r\n return new Date(...vals);\r\n },\r\n\r\n clone(date) {\r\n return new Date(...this.get_date_values(date));\r\n },\r\n\r\n get_date_values(date) {\r\n return [\r\n date.getFullYear(),\r\n date.getMonth(),\r\n date.getDate(),\r\n date.getHours(),\r\n date.getMinutes(),\r\n date.getSeconds(),\r\n date.getMilliseconds(),\r\n ];\r\n },\r\n\r\n get_days_in_month(date) {\r\n const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\r\n\r\n const month = date.getMonth();\r\n\r\n if (month !== 1) {\r\n return no_of_days[month];\r\n }\r\n\r\n // Feb\r\n const year = date.getFullYear();\r\n if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {\r\n return 29;\r\n }\r\n return 28;\r\n },\r\n};\r\n\r\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart\r\nfunction padStart(str, targetLength, padString) {\r\n str = str + '';\r\n targetLength = targetLength >> 0;\r\n padString = String(typeof padString !== 'undefined' ? padString : ' ');\r\n if (str.length > targetLength) {\r\n return String(str);\r\n } else {\r\n targetLength = targetLength - str.length;\r\n if (targetLength > padString.length) {\r\n padString += padString.repeat(targetLength / padString.length);\r\n }\r\n return padString.slice(0, targetLength) + String(str);\r\n }\r\n}\r\n","export function $(expr, con) {\r\n return typeof expr === 'string'\r\n ? (con || document).querySelector(expr)\r\n : expr || null;\r\n}\r\n\r\nexport function createSVG(tag, attrs) {\r\n const elem = document.createElementNS('http://www.w3.org/2000/svg', tag);\r\n for (let attr in attrs) {\r\n if (attr === 'append_to') {\r\n const parent = attrs.append_to;\r\n parent.appendChild(elem);\r\n } else if (attr === 'innerHTML') {\r\n elem.innerHTML = attrs.innerHTML;\r\n } else {\r\n elem.setAttribute(attr, attrs[attr]);\r\n }\r\n }\r\n return elem;\r\n}\r\n\r\nexport function animateSVG(svgElement, attr, from, to) {\r\n const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);\r\n\r\n if (animatedSvgElement === svgElement) {\r\n // triggered 2nd time programmatically\r\n // trigger artificial click event\r\n const event = document.createEvent('HTMLEvents');\r\n event.initEvent('click', true, true);\r\n event.eventName = 'click';\r\n animatedSvgElement.dispatchEvent(event);\r\n }\r\n}\r\n\r\nfunction getAnimationElement(\r\n svgElement,\r\n attr,\r\n from,\r\n to,\r\n dur = '0.4s',\r\n begin = '0.1s'\r\n) {\r\n const animEl = svgElement.querySelector('animate');\r\n if (animEl) {\r\n $.attr(animEl, {\r\n attributeName: attr,\r\n from,\r\n to,\r\n dur,\r\n begin: 'click + ' + begin, // artificial click\r\n });\r\n return svgElement;\r\n }\r\n\r\n const animateElement = createSVG('animate', {\r\n attributeName: attr,\r\n from,\r\n to,\r\n dur,\r\n begin,\r\n calcMode: 'spline',\r\n values: from + ';' + to,\r\n keyTimes: '0; 1',\r\n keySplines: cubic_bezier('ease-out'),\r\n });\r\n svgElement.appendChild(animateElement);\r\n\r\n return svgElement;\r\n}\r\n\r\nfunction cubic_bezier(name) {\r\n return {\r\n ease: '.25 .1 .25 1',\r\n linear: '0 0 1 1',\r\n 'ease-in': '.42 0 1 1',\r\n 'ease-out': '0 0 .58 1',\r\n 'ease-in-out': '.42 0 .58 1',\r\n }[name];\r\n}\r\n\r\n$.on = (element, event, selector, callback) => {\r\n if (!callback) {\r\n callback = selector;\r\n $.bind(element, event, callback);\r\n } else {\r\n $.delegate(element, event, selector, callback);\r\n }\r\n};\r\n\r\n$.off = (element, event, handler) => {\r\n element.removeEventListener(event, handler);\r\n};\r\n\r\n$.bind = (element, event, callback) => {\r\n event.split(/\\s+/).forEach(function (event) {\r\n element.addEventListener(event, callback);\r\n });\r\n};\r\n\r\n$.delegate = (element, event, selector, callback) => {\r\n element.addEventListener(event, function (e) {\r\n const delegatedTarget = e.target.closest(selector);\r\n if (delegatedTarget) {\r\n e.delegatedTarget = delegatedTarget;\r\n callback.call(this, e, delegatedTarget);\r\n }\r\n });\r\n};\r\n\r\n$.closest = (selector, element) => {\r\n if (!element) return null;\r\n\r\n if (element.matches(selector)) {\r\n return element;\r\n }\r\n\r\n return $.closest(selector, element.parentNode);\r\n};\r\n\r\n$.attr = (element, attr, value) => {\r\n if (!value && typeof attr === 'string') {\r\n return element.getAttribute(attr);\r\n }\r\n\r\n if (typeof attr === 'object') {\r\n for (let key in attr) {\r\n $.attr(element, key, attr[key]);\r\n }\r\n return;\r\n }\r\n\r\n element.setAttribute(attr, value);\r\n};\r\n","import date_utils from './date_utils';\r\nimport { $, createSVG, animateSVG } from './svg_utils';\r\n\r\nexport default class Bar {\r\n constructor(gantt, task) {\r\n this.set_defaults(gantt, task);\r\n this.prepare();\r\n this.draw();\r\n this.bind();\r\n }\r\n\r\n set_defaults(gantt, task) {\r\n this.action_completed = false;\r\n this.gantt = gantt;\r\n this.task = task;\r\n }\r\n\r\n prepare() {\r\n this.prepare_values();\r\n this.prepare_helpers();\r\n }\r\n\r\n prepare_values() {\r\n this.invalid = this.task.invalid;\r\n this.height = this.gantt.options.bar_height;\r\n this.x = this.compute_x();\r\n this.y = this.compute_y();\r\n this.corner_radius = this.gantt.options.bar_corner_radius;\r\n this.duration =\r\n date_utils.diff(this.task._end, this.task._start, 'hour') /\r\n this.gantt.options.step;\r\n this.width = this.gantt.options.column_width * this.duration;\r\n this.progress_width =\r\n this.gantt.options.column_width *\r\n this.duration *\r\n (this.task.progress / 100) || 0;\r\n this.group = createSVG('g', {\r\n class: 'bar-wrapper ' + (this.task.custom_class || ''),\r\n 'data-id': this.task.id,\r\n });\r\n this.bar_group = createSVG('g', {\r\n class: 'bar-group',\r\n append_to: this.group,\r\n });\r\n this.handle_group = createSVG('g', {\r\n class: 'handle-group',\r\n append_to: this.group,\r\n });\r\n }\r\n\r\n prepare_helpers() {\r\n SVGElement.prototype.getX = function () {\r\n return +this.getAttribute('x');\r\n };\r\n SVGElement.prototype.getY = function () {\r\n return +this.getAttribute('y');\r\n };\r\n SVGElement.prototype.getWidth = function () {\r\n return +this.getAttribute('width');\r\n };\r\n SVGElement.prototype.getHeight = function () {\r\n return +this.getAttribute('height');\r\n };\r\n SVGElement.prototype.getEndX = function () {\r\n return this.getX() + this.getWidth();\r\n };\r\n }\r\n\r\n draw() {\r\n this.draw_bar();\r\n this.draw_progress_bar();\r\n this.draw_label();\r\n this.draw_resize_handles();\r\n }\r\n\r\n draw_bar() {\r\n this.$bar = createSVG('rect', {\r\n x: this.x,\r\n y: this.y,\r\n width: this.width,\r\n height: this.height,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'bar',\r\n append_to: this.bar_group,\r\n });\r\n\r\n animateSVG(this.$bar, 'width', 0, this.width);\r\n\r\n if (this.invalid) {\r\n this.$bar.classList.add('bar-invalid');\r\n }\r\n }\r\n\r\n draw_progress_bar() {\r\n if (this.invalid) return;\r\n this.$bar_progress = createSVG('rect', {\r\n x: this.x,\r\n y: this.y,\r\n width: this.progress_width,\r\n height: this.height,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'bar-progress',\r\n append_to: this.bar_group,\r\n });\r\n\r\n animateSVG(this.$bar_progress, 'width', 0, this.progress_width);\r\n }\r\n\r\n draw_label() {\r\n createSVG('text', {\r\n x: this.x + this.width / 2,\r\n y: this.y + this.height / 2,\r\n innerHTML: this.task.name,\r\n class: 'bar-label',\r\n append_to: this.bar_group,\r\n });\r\n // labels get BBox in the next tick\r\n requestAnimationFrame(() => this.update_label_position());\r\n }\r\n\r\n draw_resize_handles() {\r\n if (this.invalid) return;\r\n\r\n const bar = this.$bar;\r\n const handle_width = 8;\r\n\r\n createSVG('rect', {\r\n x: bar.getX() + bar.getWidth() - 9,\r\n y: bar.getY() + 1,\r\n width: handle_width,\r\n height: this.height - 2,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'handle right',\r\n append_to: this.handle_group,\r\n });\r\n\r\n createSVG('rect', {\r\n x: bar.getX() + 1,\r\n y: bar.getY() + 1,\r\n width: handle_width,\r\n height: this.height - 2,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'handle left',\r\n append_to: this.handle_group,\r\n });\r\n\r\n if (this.task.progress && this.task.progress < 100) {\r\n this.$handle_progress = createSVG('polygon', {\r\n points: this.get_progress_polygon_points().join(','),\r\n class: 'handle progress',\r\n append_to: this.handle_group,\r\n });\r\n }\r\n }\r\n\r\n get_progress_polygon_points() {\r\n const bar_progress = this.$bar_progress;\r\n return [\r\n bar_progress.getEndX() - 5,\r\n bar_progress.getY() + bar_progress.getHeight(),\r\n bar_progress.getEndX() + 5,\r\n bar_progress.getY() + bar_progress.getHeight(),\r\n bar_progress.getEndX(),\r\n bar_progress.getY() + bar_progress.getHeight() - 8.66,\r\n ];\r\n }\r\n\r\n bind() {\r\n if (this.invalid) return;\r\n this.setup_click_event();\r\n }\r\n\r\n setup_click_event() {\r\n $.on(this.group, 'focus ' + this.gantt.options.popup_trigger, (e) => {\r\n if (this.action_completed) {\r\n // just finished a move action, wait for a few seconds\r\n return;\r\n }\r\n\r\n this.show_popup();\r\n this.gantt.unselect_all();\r\n this.group.classList.add('active');\r\n });\r\n\r\n $.on(this.group, 'dblclick', (e) => {\r\n if (this.action_completed) {\r\n // just finished a move action, wait for a few seconds\r\n return;\r\n }\r\n\r\n this.gantt.trigger_event('click', [this.task]);\r\n });\r\n }\r\n\r\n show_popup() {\r\n if (this.gantt.bar_being_dragged) return;\r\n\r\n const start_date = date_utils.format(\r\n this.task._start,\r\n 'MMM D',\r\n this.gantt.options.language\r\n );\r\n const end_date = date_utils.format(\r\n date_utils.add(this.task._end, -1, 'second'),\r\n 'MMM D',\r\n this.gantt.options.language\r\n );\r\n const subtitle = start_date + ' - ' + end_date;\r\n\r\n this.gantt.show_popup({\r\n target_element: this.$bar,\r\n title: this.task.name,\r\n subtitle: subtitle,\r\n task: this.task,\r\n });\r\n }\r\n\r\n update_bar_position({ x = null, width = null }) {\r\n const bar = this.$bar;\r\n if (x) {\r\n // get all x values of parent task\r\n const xs = this.task.dependencies.map((dep) => {\r\n return this.gantt.get_bar(dep).$bar.getX();\r\n });\r\n // child task must not go before parent\r\n const valid_x = xs.reduce((prev, curr) => {\r\n return x >= curr;\r\n }, x);\r\n if (!valid_x) {\r\n width = null;\r\n return;\r\n }\r\n this.update_attr(bar, 'x', x);\r\n }\r\n if (width && width >= this.gantt.options.column_width) {\r\n this.update_attr(bar, 'width', width);\r\n }\r\n this.update_label_position();\r\n this.update_handle_position();\r\n this.update_progressbar_position();\r\n this.update_arrow_position();\r\n }\r\n\r\n date_changed() {\r\n let changed = false;\r\n const { new_start_date, new_end_date } = this.compute_start_end_date();\r\n\r\n if (Number(this.task._start) !== Number(new_start_date)) {\r\n changed = true;\r\n this.task._start = new_start_date;\r\n }\r\n\r\n if (Number(this.task._end) !== Number(new_end_date)) {\r\n changed = true;\r\n this.task._end = new_end_date;\r\n }\r\n\r\n if (!changed) return;\r\n\r\n this.gantt.trigger_event('date_change', [\r\n this.task,\r\n new_start_date,\r\n date_utils.add(new_end_date, -1, 'second'),\r\n ]);\r\n }\r\n\r\n progress_changed() {\r\n const new_progress = this.compute_progress();\r\n this.task.progress = new_progress;\r\n this.gantt.trigger_event('progress_change', [this.task, new_progress]);\r\n }\r\n\r\n set_action_completed() {\r\n this.action_completed = true;\r\n setTimeout(() => (this.action_completed = false), 1000);\r\n }\r\n\r\n compute_start_end_date() {\r\n const bar = this.$bar;\r\n const x_in_units = bar.getX() / this.gantt.options.column_width;\r\n const new_start_date = date_utils.add(\r\n this.gantt.gantt_start,\r\n x_in_units * this.gantt.options.step,\r\n 'hour'\r\n );\r\n const width_in_units = bar.getWidth() / this.gantt.options.column_width;\r\n const new_end_date = date_utils.add(\r\n new_start_date,\r\n width_in_units * this.gantt.options.step,\r\n 'hour'\r\n );\r\n\r\n return { new_start_date, new_end_date };\r\n }\r\n\r\n compute_progress() {\r\n const progress =\r\n (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100;\r\n return parseInt(progress, 10);\r\n }\r\n\r\n compute_x() {\r\n const { step, column_width } = this.gantt.options;\r\n const task_start = this.task._start;\r\n const gantt_start = this.gantt.gantt_start;\r\n\r\n const diff = date_utils.diff(task_start, gantt_start, 'hour');\r\n let x = (diff / step) * column_width;\r\n\r\n if (this.gantt.view_is('Month')) {\r\n const diff = date_utils.diff(task_start, gantt_start, 'day');\r\n x = (diff * column_width) / 30;\r\n }\r\n return x;\r\n }\r\n\r\n compute_y() {\r\n return (\r\n this.gantt.options.header_height +\r\n this.gantt.options.padding +\r\n this.task._index * (this.height + this.gantt.options.padding)\r\n );\r\n }\r\n\r\n get_snap_position(dx) {\r\n let odx = dx,\r\n rem,\r\n position;\r\n\r\n if (this.gantt.view_is('Week')) {\r\n rem = dx % (this.gantt.options.column_width / 7);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.gantt.options.column_width / 14\r\n ? 0\r\n : this.gantt.options.column_width / 7);\r\n } else if (this.gantt.view_is('Month')) {\r\n rem = dx % (this.gantt.options.column_width / 30);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.gantt.options.column_width / 60\r\n ? 0\r\n : this.gantt.options.column_width / 30);\r\n } else {\r\n rem = dx % this.gantt.options.column_width;\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.gantt.options.column_width / 2\r\n ? 0\r\n : this.gantt.options.column_width);\r\n }\r\n return position;\r\n }\r\n\r\n update_attr(element, attr, value) {\r\n value = +value;\r\n if (!isNaN(value)) {\r\n element.setAttribute(attr, value);\r\n }\r\n return element;\r\n }\r\n\r\n update_progressbar_position() {\r\n if (this.invalid) return;\r\n this.$bar_progress.setAttribute('x', this.$bar.getX());\r\n this.$bar_progress.setAttribute(\r\n 'width',\r\n this.$bar.getWidth() * (this.task.progress / 100)\r\n );\r\n }\r\n\r\n update_label_position() {\r\n const bar = this.$bar,\r\n label = this.group.querySelector('.bar-label');\r\n\r\n if (label.getBBox().width > bar.getWidth()) {\r\n label.classList.add('big');\r\n label.setAttribute('x', bar.getX() + bar.getWidth() + 5);\r\n } else {\r\n label.classList.remove('big');\r\n label.setAttribute('x', bar.getX() + bar.getWidth() / 2);\r\n }\r\n }\r\n\r\n update_handle_position() {\r\n if (this.invalid) return;\r\n const bar = this.$bar;\r\n this.handle_group\r\n .querySelector('.handle.left')\r\n .setAttribute('x', bar.getX() + 1);\r\n this.handle_group\r\n .querySelector('.handle.right')\r\n .setAttribute('x', bar.getEndX() - 9);\r\n const handle = this.group.querySelector('.handle.progress');\r\n handle &&\r\n handle.setAttribute('points', this.get_progress_polygon_points());\r\n }\r\n\r\n update_arrow_position() {\r\n this.arrows = this.arrows || [];\r\n for (let arrow of this.arrows) {\r\n arrow.update();\r\n }\r\n }\r\n}\r\n\r\nfunction isFunction(functionToCheck) {\r\n var getType = {};\r\n return (\r\n functionToCheck &&\r\n getType.toString.call(functionToCheck) === '[object Function]'\r\n );\r\n}\r\n","import { createSVG } from './svg_utils';\r\n\r\nexport default class Arrow {\r\n constructor(gantt, from_task, to_task) {\r\n this.gantt = gantt;\r\n this.from_task = from_task;\r\n this.to_task = to_task;\r\n\r\n this.calculate_path();\r\n this.draw();\r\n }\r\n\r\n calculate_path() {\r\n let start_x =\r\n this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;\r\n\r\n const condition = () =>\r\n this.to_task.$bar.getX() < start_x + this.gantt.options.padding &&\r\n start_x > this.from_task.$bar.getX() + this.gantt.options.padding;\r\n\r\n while (condition()) {\r\n start_x -= 10;\r\n }\r\n\r\n const start_y =\r\n this.gantt.options.header_height +\r\n this.gantt.options.bar_height +\r\n (this.gantt.options.padding + this.gantt.options.bar_height) *\r\n this.from_task.task._index +\r\n this.gantt.options.padding;\r\n\r\n const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2;\r\n const end_y =\r\n this.gantt.options.header_height +\r\n this.gantt.options.bar_height / 2 +\r\n (this.gantt.options.padding + this.gantt.options.bar_height) *\r\n this.to_task.task._index +\r\n this.gantt.options.padding;\r\n\r\n const from_is_below_to =\r\n this.from_task.task._index > this.to_task.task._index;\r\n const curve = this.gantt.options.arrow_curve;\r\n const clockwise = from_is_below_to ? 1 : 0;\r\n const curve_y = from_is_below_to ? -curve : curve;\r\n const offset = from_is_below_to\r\n ? end_y + this.gantt.options.arrow_curve\r\n : end_y - this.gantt.options.arrow_curve;\r\n\r\n this.path = `\r\n M ${start_x} ${start_y}\r\n V ${offset}\r\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\r\n L ${end_x} ${end_y}\r\n m -5 -5\r\n l 5 5\r\n l -5 5`;\r\n\r\n if (\r\n this.to_task.$bar.getX() <\r\n this.from_task.$bar.getX() + this.gantt.options.padding\r\n ) {\r\n const down_1 = this.gantt.options.padding / 2 - curve;\r\n const down_2 =\r\n this.to_task.$bar.getY() +\r\n this.to_task.$bar.getHeight() / 2 -\r\n curve_y;\r\n const left = this.to_task.$bar.getX() - this.gantt.options.padding;\r\n\r\n this.path = `\r\n M ${start_x} ${start_y}\r\n v ${down_1}\r\n a ${curve} ${curve} 0 0 1 -${curve} ${curve}\r\n H ${left}\r\n a ${curve} ${curve} 0 0 ${clockwise} -${curve} ${curve_y}\r\n V ${down_2}\r\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\r\n L ${end_x} ${end_y}\r\n m -5 -5\r\n l 5 5\r\n l -5 5`;\r\n }\r\n }\r\n\r\n draw() {\r\n this.element = createSVG('path', {\r\n d: this.path,\r\n 'data-from': this.from_task.task.id,\r\n 'data-to': this.to_task.task.id,\r\n });\r\n }\r\n\r\n update() {\r\n this.calculate_path();\r\n this.element.setAttribute('d', this.path);\r\n }\r\n}\r\n","export default class Popup {\r\n constructor(parent, custom_html) {\r\n this.parent = parent;\r\n this.custom_html = custom_html;\r\n this.make();\r\n }\r\n\r\n make() {\r\n this.parent.innerHTML = `\r\n
\r\n
\r\n
\r\n `;\r\n\r\n this.hide();\r\n\r\n this.title = this.parent.querySelector('.title');\r\n this.subtitle = this.parent.querySelector('.subtitle');\r\n this.pointer = this.parent.querySelector('.pointer');\r\n }\r\n\r\n show(options) {\r\n if (!options.target_element) {\r\n throw new Error('target_element is required to show popup');\r\n }\r\n if (!options.position) {\r\n options.position = 'left';\r\n }\r\n const target_element = options.target_element;\r\n\r\n if (this.custom_html) {\r\n let html = this.custom_html(options.task);\r\n html += '
';\r\n this.parent.innerHTML = html;\r\n this.pointer = this.parent.querySelector('.pointer');\r\n } else {\r\n // set data\r\n this.title.innerHTML = options.title;\r\n this.subtitle.innerHTML = options.subtitle;\r\n this.parent.style.width = this.parent.clientWidth + 'px';\r\n }\r\n\r\n // set position\r\n let position_meta;\r\n if (target_element instanceof HTMLElement) {\r\n position_meta = target_element.getBoundingClientRect();\r\n } else if (target_element instanceof SVGElement) {\r\n position_meta = options.target_element.getBBox();\r\n }\r\n\r\n if (options.position === 'left') {\r\n this.parent.style.left =\r\n position_meta.x + (position_meta.width + 10) + 'px';\r\n this.parent.style.top = position_meta.y + 'px';\r\n\r\n this.pointer.style.transform = 'rotateZ(90deg)';\r\n this.pointer.style.left = '-7px';\r\n this.pointer.style.top = '2px';\r\n }\r\n\r\n // show\r\n this.parent.style.opacity = 1;\r\n }\r\n\r\n hide() {\r\n this.parent.style.opacity = 0;\r\n this.parent.style.left = 0;\r\n }\r\n}\r\n","import date_utils from './date_utils';\r\nimport { $, createSVG } from './svg_utils';\r\nimport Bar from './bar';\r\nimport Arrow from './arrow';\r\nimport Popup from './popup';\r\n\r\nimport './gantt.scss';\r\n\r\nconst VIEW_MODE = {\r\n QUARTER_DAY: 'Quarter Day',\r\n HALF_DAY: 'Half Day',\r\n DAY: 'Day',\r\n WEEK: 'Week',\r\n MONTH: 'Month',\r\n YEAR: 'Year',\r\n};\r\n\r\nexport default class Gantt {\r\n constructor(wrapper, tasks, options) {\r\n this.setup_wrapper(wrapper);\r\n this.setup_options(options);\r\n this.setup_tasks(tasks);\r\n // initialize with default view mode\r\n this.change_view_mode();\r\n this.bind_events();\r\n }\r\n\r\n setup_wrapper(element) {\r\n let svg_element, wrapper_element;\r\n\r\n // CSS Selector is passed\r\n if (typeof element === 'string') {\r\n element = document.querySelector(element);\r\n }\r\n\r\n // get the SVGElement\r\n if (element instanceof HTMLElement) {\r\n wrapper_element = element;\r\n svg_element = element.querySelector('svg');\r\n } else if (element instanceof SVGElement) {\r\n svg_element = element;\r\n } else {\r\n throw new TypeError(\r\n 'Frappé Gantt only supports usage of a string CSS selector,' +\r\n \" HTML DOM element or SVG DOM element for the 'element' parameter\"\r\n );\r\n }\r\n\r\n // svg element\r\n if (!svg_element) {\r\n // create it\r\n this.$svg = createSVG('svg', {\r\n append_to: wrapper_element,\r\n class: 'gantt',\r\n });\r\n } else {\r\n this.$svg = svg_element;\r\n this.$svg.classList.add('gantt');\r\n }\r\n\r\n // wrapper element\r\n this.$container = document.createElement('div');\r\n this.$container.classList.add('gantt-container');\r\n\r\n const parent_element = this.$svg.parentElement;\r\n parent_element.appendChild(this.$container);\r\n this.$container.appendChild(this.$svg);\r\n\r\n // popup wrapper\r\n this.popup_wrapper = document.createElement('div');\r\n this.popup_wrapper.classList.add('popup-wrapper');\r\n this.$container.appendChild(this.popup_wrapper);\r\n }\r\n\r\n setup_options(options) {\r\n const default_options = {\r\n header_height: 50,\r\n column_width: 30,\r\n step: 24,\r\n view_modes: [...Object.values(VIEW_MODE)],\r\n bar_height: 20,\r\n bar_corner_radius: 3,\r\n arrow_curve: 5,\r\n padding: 18,\r\n view_mode: 'Day',\r\n date_format: 'YYYY-MM-DD',\r\n popup_trigger: 'click',\r\n custom_popup_html: null,\r\n language: 'en',\r\n };\r\n this.options = Object.assign({}, default_options, options);\r\n }\r\n\r\n setup_tasks(tasks) {\r\n // prepare tasks\r\n this.tasks = tasks.map((task, i) => {\r\n // convert to Date objects\r\n task._start = date_utils.parse(task.start);\r\n task._end = date_utils.parse(task.end);\r\n\r\n // make task invalid if duration too large\r\n if (date_utils.diff(task._end, task._start, 'year') > 10) {\r\n task.end = null;\r\n }\r\n\r\n // cache index\r\n task._index = i;\r\n\r\n // invalid dates\r\n if (!task.start && !task.end) {\r\n const today = date_utils.today();\r\n task._start = today;\r\n task._end = date_utils.add(today, 2, 'day');\r\n }\r\n\r\n if (!task.start && task.end) {\r\n task._start = date_utils.add(task._end, -2, 'day');\r\n }\r\n\r\n if (task.start && !task.end) {\r\n task._end = date_utils.add(task._start, 2, 'day');\r\n }\r\n\r\n // if hours is not set, assume the last day is full day\r\n // e.g: 2018-09-09 becomes 2018-09-09 23:59:59\r\n const task_end_values = date_utils.get_date_values(task._end);\r\n if (task_end_values.slice(3).every((d) => d === 0)) {\r\n task._end = date_utils.add(task._end, 24, 'hour');\r\n }\r\n\r\n // invalid flag\r\n if (!task.start || !task.end) {\r\n task.invalid = true;\r\n }\r\n\r\n // dependencies\r\n if (typeof task.dependencies === 'string' || !task.dependencies) {\r\n let deps = [];\r\n if (task.dependencies) {\r\n deps = task.dependencies\r\n .split(',')\r\n .map((d) => d.trim())\r\n .filter((d) => d);\r\n }\r\n task.dependencies = deps;\r\n }\r\n\r\n // uids\r\n if (!task.id) {\r\n task.id = generate_id(task);\r\n }\r\n\r\n return task;\r\n });\r\n\r\n this.setup_dependencies();\r\n }\r\n\r\n setup_dependencies() {\r\n this.dependency_map = {};\r\n for (let t of this.tasks) {\r\n for (let d of t.dependencies) {\r\n this.dependency_map[d] = this.dependency_map[d] || [];\r\n this.dependency_map[d].push(t.id);\r\n }\r\n }\r\n }\r\n\r\n refresh(tasks) {\r\n this.setup_tasks(tasks);\r\n this.change_view_mode();\r\n }\r\n\r\n change_view_mode(mode = this.options.view_mode) {\r\n this.update_view_scale(mode);\r\n this.setup_dates();\r\n this.render();\r\n // fire viewmode_change event\r\n this.trigger_event('view_change', [mode]);\r\n }\r\n\r\n update_view_scale(view_mode) {\r\n this.options.view_mode = view_mode;\r\n\r\n if (view_mode === VIEW_MODE.DAY) {\r\n this.options.step = 24;\r\n this.options.column_width = 38;\r\n } else if (view_mode === VIEW_MODE.HALF_DAY) {\r\n this.options.step = 24 / 2;\r\n this.options.column_width = 38;\r\n } else if (view_mode === VIEW_MODE.QUARTER_DAY) {\r\n this.options.step = 24 / 4;\r\n this.options.column_width = 38;\r\n } else if (view_mode === VIEW_MODE.WEEK) {\r\n this.options.step = 24 * 7;\r\n this.options.column_width = 140;\r\n } else if (view_mode === VIEW_MODE.MONTH) {\r\n this.options.step = 24 * 30;\r\n this.options.column_width = 120;\r\n } else if (view_mode === VIEW_MODE.YEAR) {\r\n this.options.step = 24 * 365;\r\n this.options.column_width = 120;\r\n }\r\n }\r\n\r\n setup_dates() {\r\n this.setup_gantt_dates();\r\n this.setup_date_values();\r\n }\r\n\r\n setup_gantt_dates() {\r\n this.gantt_start = this.gantt_end = null;\r\n\r\n for (let task of this.tasks) {\r\n // set global start and end date\r\n if (!this.gantt_start || task._start < this.gantt_start) {\r\n this.gantt_start = task._start;\r\n }\r\n if (!this.gantt_end || task._end > this.gantt_end) {\r\n this.gantt_end = task._end;\r\n }\r\n }\r\n\r\n this.gantt_start = date_utils.start_of(this.gantt_start, 'day');\r\n this.gantt_end = date_utils.start_of(this.gantt_end, 'day');\r\n\r\n // add date padding on both sides\r\n if (this.view_is([VIEW_MODE.QUARTER_DAY, VIEW_MODE.HALF_DAY])) {\r\n this.gantt_start = date_utils.add(this.gantt_start, -7, 'day');\r\n this.gantt_end = date_utils.add(this.gantt_end, 7, 'day');\r\n } else if (this.view_is(VIEW_MODE.MONTH)) {\r\n this.gantt_start = date_utils.start_of(this.gantt_start, 'year');\r\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'year');\r\n } else if (this.view_is(VIEW_MODE.YEAR)) {\r\n this.gantt_start = date_utils.add(this.gantt_start, -2, 'year');\r\n this.gantt_end = date_utils.add(this.gantt_end, 2, 'year');\r\n } else {\r\n this.gantt_start = date_utils.add(this.gantt_start, -1, 'month');\r\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'month');\r\n }\r\n }\r\n\r\n setup_date_values() {\r\n this.dates = [];\r\n let cur_date = null;\r\n\r\n while (cur_date === null || cur_date < this.gantt_end) {\r\n if (!cur_date) {\r\n cur_date = date_utils.clone(this.gantt_start);\r\n } else {\r\n if (this.view_is(VIEW_MODE.YEAR)) {\r\n cur_date = date_utils.add(cur_date, 1, 'year');\r\n } else if (this.view_is(VIEW_MODE.MONTH)) {\r\n cur_date = date_utils.add(cur_date, 1, 'month');\r\n } else {\r\n cur_date = date_utils.add(\r\n cur_date,\r\n this.options.step,\r\n 'hour'\r\n );\r\n }\r\n }\r\n this.dates.push(cur_date);\r\n }\r\n }\r\n\r\n bind_events() {\r\n this.bind_grid_click();\r\n this.bind_bar_events();\r\n }\r\n\r\n render() {\r\n this.clear();\r\n this.setup_layers();\r\n this.make_grid();\r\n this.make_dates();\r\n this.make_bars();\r\n this.make_arrows();\r\n this.map_arrows_on_bars();\r\n this.set_width();\r\n this.set_scroll_position();\r\n }\r\n\r\n setup_layers() {\r\n this.layers = {};\r\n const layers = ['grid', 'date', 'arrow', 'progress', 'bar', 'details'];\r\n // make group layers\r\n for (let layer of layers) {\r\n this.layers[layer] = createSVG('g', {\r\n class: layer,\r\n append_to: this.$svg,\r\n });\r\n }\r\n }\r\n\r\n make_grid() {\r\n this.make_grid_background();\r\n this.make_grid_rows();\r\n this.make_grid_header();\r\n this.make_grid_ticks();\r\n this.make_grid_highlights();\r\n }\r\n\r\n make_grid_background() {\r\n const grid_width = this.dates.length * this.options.column_width;\r\n const grid_height =\r\n this.options.header_height +\r\n this.options.padding +\r\n (this.options.bar_height + this.options.padding) *\r\n this.tasks.length;\r\n\r\n createSVG('rect', {\r\n x: 0,\r\n y: 0,\r\n width: grid_width,\r\n height: grid_height,\r\n class: 'grid-background',\r\n append_to: this.layers.grid,\r\n });\r\n\r\n $.attr(this.$svg, {\r\n height: grid_height + this.options.padding + 100,\r\n width: '100%',\r\n });\r\n }\r\n\r\n make_grid_rows() {\r\n const rows_layer = createSVG('g', { append_to: this.layers.grid });\r\n const lines_layer = createSVG('g', { append_to: this.layers.grid });\r\n\r\n const row_width = this.dates.length * this.options.column_width;\r\n const row_height = this.options.bar_height + this.options.padding;\r\n\r\n let row_y = this.options.header_height + this.options.padding / 2;\r\n\r\n for (let task of this.tasks) {\r\n createSVG('rect', {\r\n x: 0,\r\n y: row_y,\r\n width: row_width,\r\n height: row_height,\r\n class: 'grid-row',\r\n append_to: rows_layer,\r\n });\r\n\r\n createSVG('line', {\r\n x1: 0,\r\n y1: row_y + row_height,\r\n x2: row_width,\r\n y2: row_y + row_height,\r\n class: 'row-line',\r\n append_to: lines_layer,\r\n });\r\n\r\n row_y += this.options.bar_height + this.options.padding;\r\n }\r\n }\r\n\r\n make_grid_header() {\r\n const header_width = this.dates.length * this.options.column_width;\r\n const header_height = this.options.header_height + 10;\r\n createSVG('rect', {\r\n x: 0,\r\n y: 0,\r\n width: header_width,\r\n height: header_height,\r\n class: 'grid-header',\r\n append_to: this.layers.grid,\r\n });\r\n }\r\n\r\n make_grid_ticks() {\r\n let tick_x = 0;\r\n let tick_y = this.options.header_height + this.options.padding / 2;\r\n let tick_height =\r\n (this.options.bar_height + this.options.padding) *\r\n this.tasks.length;\r\n\r\n for (let date of this.dates) {\r\n let tick_class = 'tick';\r\n // thick tick for monday\r\n if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) {\r\n tick_class += ' thick';\r\n }\r\n // thick tick for first week\r\n if (\r\n this.view_is(VIEW_MODE.WEEK) &&\r\n date.getDate() >= 1 &&\r\n date.getDate() < 8\r\n ) {\r\n tick_class += ' thick';\r\n }\r\n // thick ticks for quarters\r\n if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) {\r\n tick_class += ' thick';\r\n }\r\n\r\n createSVG('path', {\r\n d: `M ${tick_x} ${tick_y} v ${tick_height}`,\r\n class: tick_class,\r\n append_to: this.layers.grid,\r\n });\r\n\r\n if (this.view_is(VIEW_MODE.MONTH)) {\r\n tick_x +=\r\n (date_utils.get_days_in_month(date) *\r\n this.options.column_width) /\r\n 30;\r\n } else {\r\n tick_x += this.options.column_width;\r\n }\r\n }\r\n }\r\n\r\n make_grid_highlights() {\r\n // highlight today's date\r\n if (this.view_is(VIEW_MODE.DAY)) {\r\n const x =\r\n (date_utils.diff(date_utils.today(), this.gantt_start, 'hour') /\r\n this.options.step) *\r\n this.options.column_width;\r\n const y = 0;\r\n\r\n const width = this.options.column_width;\r\n const height =\r\n (this.options.bar_height + this.options.padding) *\r\n this.tasks.length +\r\n this.options.header_height +\r\n this.options.padding / 2;\r\n\r\n createSVG('rect', {\r\n x,\r\n y,\r\n width,\r\n height,\r\n class: 'today-highlight',\r\n append_to: this.layers.grid,\r\n });\r\n }\r\n }\r\n\r\n make_dates() {\r\n for (let date of this.get_dates_to_draw()) {\r\n createSVG('text', {\r\n x: date.lower_x,\r\n y: date.lower_y,\r\n innerHTML: date.lower_text,\r\n class: 'lower-text',\r\n append_to: this.layers.date,\r\n });\r\n\r\n if (date.upper_text) {\r\n const $upper_text = createSVG('text', {\r\n x: date.upper_x,\r\n y: date.upper_y,\r\n innerHTML: date.upper_text,\r\n class: 'upper-text',\r\n append_to: this.layers.date,\r\n });\r\n\r\n // remove out-of-bound dates\r\n if (\r\n $upper_text.getBBox().x2 > this.layers.grid.getBBox().width\r\n ) {\r\n $upper_text.remove();\r\n }\r\n }\r\n }\r\n }\r\n\r\n get_dates_to_draw() {\r\n let last_date = null;\r\n const dates = this.dates.map((date, i) => {\r\n const d = this.get_date_info(date, last_date, i);\r\n last_date = date;\r\n return d;\r\n });\r\n return dates;\r\n }\r\n\r\n get_date_info(date, last_date, i) {\r\n if (!last_date) {\r\n last_date = date_utils.add(date, 1, 'year');\r\n }\r\n const date_text = {\r\n 'Quarter Day_lower': date_utils.format(\r\n date,\r\n 'HH',\r\n this.options.language\r\n ),\r\n 'Half Day_lower': date_utils.format(\r\n date,\r\n 'HH',\r\n this.options.language\r\n ),\r\n Day_lower:\r\n date.getDate() !== last_date.getDate()\r\n ? date_utils.format(date, 'D', this.options.language)\r\n : '',\r\n Week_lower:\r\n date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(date, 'D MMM', this.options.language)\r\n : date_utils.format(date, 'D', this.options.language),\r\n Month_lower: date_utils.format(date, 'MMMM', this.options.language),\r\n Year_lower: date_utils.format(date, 'YYYY', this.options.language),\r\n 'Quarter Day_upper':\r\n date.getDate() !== last_date.getDate()\r\n ? date_utils.format(date, 'D MMM', this.options.language)\r\n : '',\r\n 'Half Day_upper':\r\n date.getDate() !== last_date.getDate()\r\n ? date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(\r\n date,\r\n 'D MMM',\r\n this.options.language\r\n )\r\n : date_utils.format(date, 'D', this.options.language)\r\n : '',\r\n Day_upper:\r\n date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(date, 'MMMM', this.options.language)\r\n : '',\r\n Week_upper:\r\n date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(date, 'MMMM', this.options.language)\r\n : '',\r\n Month_upper:\r\n date.getFullYear() !== last_date.getFullYear()\r\n ? date_utils.format(date, 'YYYY', this.options.language)\r\n : '',\r\n Year_upper:\r\n date.getFullYear() !== last_date.getFullYear()\r\n ? date_utils.format(date, 'YYYY', this.options.language)\r\n : '',\r\n };\r\n\r\n const base_pos = {\r\n x: i * this.options.column_width,\r\n lower_y: this.options.header_height,\r\n upper_y: this.options.header_height - 25,\r\n };\r\n\r\n const x_pos = {\r\n 'Quarter Day_lower': (this.options.column_width * 4) / 2,\r\n 'Quarter Day_upper': 0,\r\n 'Half Day_lower': (this.options.column_width * 2) / 2,\r\n 'Half Day_upper': 0,\r\n Day_lower: this.options.column_width / 2,\r\n Day_upper: (this.options.column_width * 30) / 2,\r\n Week_lower: 0,\r\n Week_upper: (this.options.column_width * 4) / 2,\r\n Month_lower: this.options.column_width / 2,\r\n Month_upper: (this.options.column_width * 12) / 2,\r\n Year_lower: this.options.column_width / 2,\r\n Year_upper: (this.options.column_width * 30) / 2,\r\n };\r\n\r\n return {\r\n upper_text: date_text[`${this.options.view_mode}_upper`],\r\n lower_text: date_text[`${this.options.view_mode}_lower`],\r\n upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`],\r\n upper_y: base_pos.upper_y,\r\n lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`],\r\n lower_y: base_pos.lower_y,\r\n };\r\n }\r\n\r\n make_bars() {\r\n this.bars = this.tasks.map((task) => {\r\n const bar = new Bar(this, task);\r\n this.layers.bar.appendChild(bar.group);\r\n return bar;\r\n });\r\n }\r\n\r\n make_arrows() {\r\n this.arrows = [];\r\n for (let task of this.tasks) {\r\n let arrows = [];\r\n arrows = task.dependencies\r\n .map((task_id) => {\r\n const dependency = this.get_task(task_id);\r\n if (!dependency) return;\r\n const arrow = new Arrow(\r\n this,\r\n this.bars[dependency._index], // from_task\r\n this.bars[task._index] // to_task\r\n );\r\n this.layers.arrow.appendChild(arrow.element);\r\n return arrow;\r\n })\r\n .filter(Boolean); // filter falsy values\r\n this.arrows = this.arrows.concat(arrows);\r\n }\r\n }\r\n\r\n map_arrows_on_bars() {\r\n for (let bar of this.bars) {\r\n bar.arrows = this.arrows.filter((arrow) => {\r\n return (\r\n arrow.from_task.task.id === bar.task.id ||\r\n arrow.to_task.task.id === bar.task.id\r\n );\r\n });\r\n }\r\n }\r\n\r\n set_width() {\r\n const cur_width = this.$svg.getBoundingClientRect().width;\r\n const actual_width = this.$svg\r\n .querySelector('.grid .grid-row')\r\n .getAttribute('width');\r\n if (cur_width < actual_width) {\r\n this.$svg.setAttribute('width', actual_width);\r\n }\r\n }\r\n\r\n set_scroll_position() {\r\n const parent_element = this.$svg.parentElement;\r\n if (!parent_element) return;\r\n\r\n const hours_before_first_task = date_utils.diff(\r\n this.get_oldest_starting_date(),\r\n this.gantt_start,\r\n 'hour'\r\n );\r\n\r\n const scroll_pos =\r\n (hours_before_first_task / this.options.step) *\r\n this.options.column_width -\r\n this.options.column_width;\r\n\r\n parent_element.scrollLeft = scroll_pos;\r\n }\r\n\r\n bind_grid_click() {\r\n $.on(\r\n this.$svg,\r\n this.options.popup_trigger,\r\n '.grid-row, .grid-header',\r\n () => {\r\n this.unselect_all();\r\n this.hide_popup();\r\n }\r\n );\r\n }\r\n\r\n bind_bar_events() {\r\n let is_dragging = false;\r\n let x_on_start = 0;\r\n let y_on_start = 0;\r\n let is_resizing_left = false;\r\n let is_resizing_right = false;\r\n let parent_bar_id = null;\r\n let bars = []; // instanceof Bar\r\n this.bar_being_dragged = null;\r\n\r\n function action_in_progress() {\r\n return is_dragging || is_resizing_left || is_resizing_right;\r\n }\r\n\r\n $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => {\r\n const bar_wrapper = $.closest('.bar-wrapper', element);\r\n\r\n if (element.classList.contains('left')) {\r\n is_resizing_left = true;\r\n } else if (element.classList.contains('right')) {\r\n is_resizing_right = true;\r\n } else if (element.classList.contains('bar-wrapper')) {\r\n is_dragging = true;\r\n }\r\n\r\n bar_wrapper.classList.add('active');\r\n\r\n x_on_start = e.offsetX;\r\n y_on_start = e.offsetY;\r\n\r\n parent_bar_id = bar_wrapper.getAttribute('data-id');\r\n const ids = [\r\n parent_bar_id,\r\n ...this.get_all_dependent_tasks(parent_bar_id),\r\n ];\r\n bars = ids.map((id) => this.get_bar(id));\r\n\r\n this.bar_being_dragged = parent_bar_id;\r\n\r\n bars.forEach((bar) => {\r\n const $bar = bar.$bar;\r\n $bar.ox = $bar.getX();\r\n $bar.oy = $bar.getY();\r\n $bar.owidth = $bar.getWidth();\r\n $bar.finaldx = 0;\r\n });\r\n });\r\n\r\n $.on(this.$svg, 'mousemove', (e) => {\r\n if (!action_in_progress()) return;\r\n const dx = e.offsetX - x_on_start;\r\n const dy = e.offsetY - y_on_start;\r\n\r\n bars.forEach((bar) => {\r\n const $bar = bar.$bar;\r\n $bar.finaldx = this.get_snap_position(dx);\r\n this.hide_popup();\r\n if (is_resizing_left) {\r\n if (parent_bar_id === bar.task.id) {\r\n bar.update_bar_position({\r\n x: $bar.ox + $bar.finaldx,\r\n width: $bar.owidth - $bar.finaldx,\r\n });\r\n } else {\r\n bar.update_bar_position({\r\n x: $bar.ox + $bar.finaldx,\r\n });\r\n }\r\n } else if (is_resizing_right) {\r\n if (parent_bar_id === bar.task.id) {\r\n bar.update_bar_position({\r\n width: $bar.owidth + $bar.finaldx,\r\n });\r\n }\r\n } else if (is_dragging) {\r\n bar.update_bar_position({ x: $bar.ox + $bar.finaldx });\r\n }\r\n });\r\n });\r\n\r\n document.addEventListener('mouseup', (e) => {\r\n if (is_dragging || is_resizing_left || is_resizing_right) {\r\n bars.forEach((bar) => bar.group.classList.remove('active'));\r\n }\r\n\r\n is_dragging = false;\r\n is_resizing_left = false;\r\n is_resizing_right = false;\r\n });\r\n\r\n $.on(this.$svg, 'mouseup', (e) => {\r\n this.bar_being_dragged = null;\r\n bars.forEach((bar) => {\r\n const $bar = bar.$bar;\r\n if (!$bar.finaldx) return;\r\n bar.date_changed();\r\n bar.set_action_completed();\r\n });\r\n });\r\n\r\n this.bind_bar_progress();\r\n }\r\n\r\n bind_bar_progress() {\r\n let x_on_start = 0;\r\n let y_on_start = 0;\r\n let is_resizing = null;\r\n let bar = null;\r\n let $bar_progress = null;\r\n let $bar = null;\r\n\r\n $.on(this.$svg, 'mousedown', '.handle.progress', (e, handle) => {\r\n is_resizing = true;\r\n x_on_start = e.offsetX;\r\n y_on_start = e.offsetY;\r\n\r\n const $bar_wrapper = $.closest('.bar-wrapper', handle);\r\n const id = $bar_wrapper.getAttribute('data-id');\r\n bar = this.get_bar(id);\r\n\r\n $bar_progress = bar.$bar_progress;\r\n $bar = bar.$bar;\r\n\r\n $bar_progress.finaldx = 0;\r\n $bar_progress.owidth = $bar_progress.getWidth();\r\n $bar_progress.min_dx = -$bar_progress.getWidth();\r\n $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth();\r\n });\r\n\r\n $.on(this.$svg, 'mousemove', (e) => {\r\n if (!is_resizing) return;\r\n let dx = e.offsetX - x_on_start;\r\n let dy = e.offsetY - y_on_start;\r\n\r\n if (dx > $bar_progress.max_dx) {\r\n dx = $bar_progress.max_dx;\r\n }\r\n if (dx < $bar_progress.min_dx) {\r\n dx = $bar_progress.min_dx;\r\n }\r\n\r\n const $handle = bar.$handle_progress;\r\n $.attr($bar_progress, 'width', $bar_progress.owidth + dx);\r\n $.attr($handle, 'points', bar.get_progress_polygon_points());\r\n $bar_progress.finaldx = dx;\r\n });\r\n\r\n $.on(this.$svg, 'mouseup', () => {\r\n is_resizing = false;\r\n if (!($bar_progress && $bar_progress.finaldx)) return;\r\n bar.progress_changed();\r\n bar.set_action_completed();\r\n });\r\n }\r\n\r\n get_all_dependent_tasks(task_id) {\r\n let out = [];\r\n let to_process = [task_id];\r\n while (to_process.length) {\r\n const deps = to_process.reduce((acc, curr) => {\r\n acc = acc.concat(this.dependency_map[curr]);\r\n return acc;\r\n }, []);\r\n\r\n out = out.concat(deps);\r\n to_process = deps.filter((d) => !to_process.includes(d));\r\n }\r\n\r\n return out.filter(Boolean);\r\n }\r\n\r\n get_snap_position(dx) {\r\n let odx = dx,\r\n rem,\r\n position;\r\n\r\n if (this.view_is(VIEW_MODE.WEEK)) {\r\n rem = dx % (this.options.column_width / 7);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.options.column_width / 14\r\n ? 0\r\n : this.options.column_width / 7);\r\n } else if (this.view_is(VIEW_MODE.MONTH)) {\r\n rem = dx % (this.options.column_width / 30);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.options.column_width / 60\r\n ? 0\r\n : this.options.column_width / 30);\r\n } else {\r\n rem = dx % this.options.column_width;\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.options.column_width / 2\r\n ? 0\r\n : this.options.column_width);\r\n }\r\n return position;\r\n }\r\n\r\n unselect_all() {\r\n [...this.$svg.querySelectorAll('.bar-wrapper')].forEach((el) => {\r\n el.classList.remove('active');\r\n });\r\n }\r\n\r\n view_is(modes) {\r\n if (typeof modes === 'string') {\r\n return this.options.view_mode === modes;\r\n }\r\n\r\n if (Array.isArray(modes)) {\r\n return modes.some((mode) => this.options.view_mode === mode);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n get_task(id) {\r\n return this.tasks.find((task) => {\r\n return task.id === id;\r\n });\r\n }\r\n\r\n get_bar(id) {\r\n return this.bars.find((bar) => {\r\n return bar.task.id === id;\r\n });\r\n }\r\n\r\n show_popup(options) {\r\n if (!this.popup) {\r\n this.popup = new Popup(\r\n this.popup_wrapper,\r\n this.options.custom_popup_html\r\n );\r\n }\r\n this.popup.show(options);\r\n }\r\n\r\n hide_popup() {\r\n this.popup && this.popup.hide();\r\n }\r\n\r\n trigger_event(event, args) {\r\n if (this.options['on_' + event]) {\r\n this.options['on_' + event].apply(null, args);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the oldest starting date from the list of tasks\r\n *\r\n * @returns Date\r\n * @memberof Gantt\r\n */\r\n get_oldest_starting_date() {\r\n return this.tasks\r\n .map((task) => task._start)\r\n .reduce((prev_date, cur_date) =>\r\n cur_date <= prev_date ? cur_date : prev_date\r\n );\r\n }\r\n\r\n /**\r\n * Clear all elements from the parent svg element\r\n *\r\n * @memberof Gantt\r\n */\r\n clear() {\r\n this.$svg.innerHTML = '';\r\n }\r\n}\r\n\r\nGantt.VIEW_MODE = VIEW_MODE;\r\n\r\nfunction generate_id(task) {\r\n return task.name + '_' + Math.random().toString(36).slice(2, 12);\r\n}\r\n"],"names":["YEAR","MONTH","DAY","HOUR","MINUTE","SECOND","MILLISECOND","date_utils","parse","date","date_separator","time_separator","Date","date_parts","time_parts","parts","split","map","val","parseInt","vals","length","parseFloat","concat","to_string","with_time","TypeError","this","get_date_values","i","padStart","date_string","time_string","format","format_string","lang","month_name","Intl","DateTimeFormat","month","month_name_capitalized","charAt","toUpperCase","slice","values","d","format_map","YYYY","MM","DD","HH","mm","ss","SSS","D","MMMM","MMM","str","formatted_values","Object","keys","sort","a","b","forEach","key","includes","replace","push","value","diff","date_a","date_b","scale","milliseconds","seconds","hours","minutes","days","months","years","endsWith","Math","floor","today","now","add","qty","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getMilliseconds","start_of","scores","should_reset","_scale","clone","get_days_in_month","no_of_days","year","targetLength","padString","String","repeat","$","expr","con","document","querySelector","createSVG","tag","attrs","elem","createElementNS","attr","append_to","appendChild","innerHTML","setAttribute","animateSVG","svgElement","from","to","animatedSvgElement","dur","begin","animEl","attributeName","animateElement","calcMode","keyTimes","keySplines","cubic_bezier","getAnimationElement","event","createEvent","initEvent","eventName","dispatchEvent","name","ease","linear","on","element","selector","callback","delegate","bind","off","handler","removeEventListener","addEventListener","e","delegatedTarget","target","closest","call","matches","parentNode","getAttribute","Bar","constructor","gantt","task","set_defaults","prepare","draw","action_completed","prepare_values","prepare_helpers","invalid","height","options","bar_height","x","compute_x","y","compute_y","corner_radius","bar_corner_radius","duration","_end","_start","step","width","column_width","progress_width","progress","group","class","custom_class","id","bar_group","handle_group","SVGElement","prototype","getX","getY","getWidth","getHeight","getEndX","draw_bar","draw_progress_bar","draw_label","draw_resize_handles","$bar","rx","ry","classList","$bar_progress","requestAnimationFrame","update_label_position","bar","$handle_progress","points","get_progress_polygon_points","join","bar_progress","setup_click_event","popup_trigger","show_popup","unselect_all","trigger_event","bar_being_dragged","subtitle","language","target_element","title","update_bar_position","dependencies","dep","get_bar","reduce","prev","curr","update_attr","update_handle_position","update_progressbar_position","update_arrow_position","date_changed","changed","new_start_date","new_end_date","compute_start_end_date","Number","progress_changed","new_progress","compute_progress","set_action_completed","setTimeout","x_in_units","gantt_start","width_in_units","task_start","view_is","header_height","padding","_index","get_snap_position","dx","rem","position","odx","isNaN","label","getBBox","remove","handle","arrows","arrow","update","Arrow","from_task","to_task","calculate_path","start_x","condition","start_y","end_x","end_y","from_is_below_to","curve","arrow_curve","clockwise","curve_y","offset","path","down_1","down_2","left","Popup","parent","custom_html","make","hide","pointer","show","Error","html","style","clientWidth","position_meta","HTMLElement","getBoundingClientRect","top","transform","opacity","VIEW_MODE","QUARTER_DAY","HALF_DAY","WEEK","Gantt","wrapper","tasks","setup_wrapper","setup_options","setup_tasks","change_view_mode","bind_events","svg_element","wrapper_element","$svg","$container","createElement","parentElement","popup_wrapper","default_options","view_modes","view_mode","date_format","custom_popup_html","assign","start","end","every","deps","trim","filter","random","toString","generate_id","setup_dependencies","dependency_map","t","refresh","mode","update_view_scale","setup_dates","render","setup_gantt_dates","setup_date_values","gantt_end","dates","cur_date","bind_grid_click","bind_bar_events","clear","setup_layers","make_grid","make_dates","make_bars","make_arrows","map_arrows_on_bars","set_width","set_scroll_position","layers","layer","make_grid_background","make_grid_rows","make_grid_header","make_grid_ticks","make_grid_highlights","grid_width","grid_height","grid","rows_layer","lines_layer","row_width","row_height","row_y","x1","y1","x2","y2","tick_x","tick_y","tick_height","tick_class","get_dates_to_draw","lower_x","lower_y","lower_text","upper_text","$upper_text","upper_x","upper_y","last_date","get_date_info","date_text","Day_lower","Week_lower","Month_lower","Year_lower","Day_upper","Week_upper","Month_upper","Year_upper","base_pos","x_pos","bars","task_id","dependency","get_task","Boolean","cur_width","actual_width","parent_element","scroll_pos","get_oldest_starting_date","scrollLeft","hide_popup","is_dragging","x_on_start","y_on_start","is_resizing_left","is_resizing_right","parent_bar_id","bar_wrapper","contains","offsetX","offsetY","ids","get_all_dependent_tasks","ox","oy","owidth","finaldx","bind_bar_progress","is_resizing","min_dx","max_dx","$handle","out","to_process","acc","querySelectorAll","el","modes","Array","isArray","some","find","popup","args","apply","prev_date"],"mappings":"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"} \ No newline at end of file diff --git a/index.html b/index.html index ce97e5e..34cb4d2 100644 --- a/index.html +++ b/index.html @@ -19,6 +19,9 @@ .heading { text-align: center; } + .gantt-target.dark { + background-color: #252525; + } diff --git a/src/dark.scss b/src/dark.scss new file mode 100644 index 0000000..4edc905 --- /dev/null +++ b/src/dark.scss @@ -0,0 +1,97 @@ +$bar-color-dark: #616161; +$bar-stroke-dark: #c6ccd2; +$border-color-dark: #616161; +$light-bg-dark: #3e3e3e; +$light-border-color-dark: #3e3e3e; +$text-muted-dark: #eee; +$text-light-dark: #ececec; +$text-color-dark: #f7f7f7; +$blue-dark: #8a8aff; + +.dark > .gantt-container .gantt { + .grid-header { + fill: #252525; + stroke: $border-color-dark; + } + .grid-row { + fill: #252525; + } + .grid-row:nth-child(even) { + fill: $light-bg-dark; + } + .row-line { + stroke: $light-border-color-dark; + } + .tick { + stroke: $border-color-dark; + } + .today-highlight { + opacity: 0.2; + } + + .arrow { + stroke: $text-muted-dark; + } + + .bar { + fill: $bar-color-dark; + stroke: none; + } + .bar-progress { + fill: $blue-dark; + } + .bar-invalid { + fill: transparent; + stroke: $bar-stroke-dark; + + &~.bar-label { + fill: $text-light-dark; + } + } + + .bar-label.big { + fill: $text-light-dark; + } + + .bar-wrapper { + &:hover { + .bar { + fill: lighten($bar-color-dark, 5); + } + + .bar-progress { + fill: lighten($blue-dark, 5); + } + } + + &.active { + .bar { + fill: lighten($bar-color-dark, 5); + } + + .bar-progress { + fill: lighten($blue-dark, 5); + } + } + } + + .upper-text { + fill: #a2a2a2; + } + .lower-text { + fill: $text-color-dark; + } +} + +.dark > .gantt-container { + .popup-wrapper { + background-color: #333; + + .title { + border-color: lighten($blue-dark, 5);; + } + .pointer { + border-top-color: #333; + } + } +} \ No newline at end of file diff --git a/src/gantt.scss b/src/gantt.scss index 2b1fc85..0034e78 100644 --- a/src/gantt.scss +++ b/src/gantt.scss @@ -1,3 +1,5 @@ +@import "./dark.scss"; + $bar-color: #b8c2cc !default; $bar-stroke: #8D99A6 !default; $border-color: #e0e0e0 !default;