feat: auto change view mode, fix multiple bugs

This commit is contained in:
Safwan Samsudeen 2024-04-25 20:28:59 +05:30
parent 2fd3aefd79
commit 0ee9b6ad69
8 changed files with 239 additions and 72 deletions

30
dist/frappe-gantt.css vendored
View File

@ -82,16 +82,30 @@
position: absolute;
width: fit-content;
}
.gantt-container #today-button {
position: sticky;
left: 10px;
top: 5px;
background-color: #2c94ec;
border: none;
color: #fff;
.gantt-container .upper-text {
position: absolute;
width: fit-content;
}
.gantt-container .current-upper {
position: fixed;
}
.gantt-container .side-header {
position: fixed;
padding: 0 10px;
background: white;
}
.gantt-container .today-button,
.gantt-container .viewmode-select {
background-color: #fff;
border: 1px solid black;
color: #111;
padding: 4px 10px;
font-size: 14px;
border-radius: 2px;
border-radius: 5px;
}
.gantt-container .viewmode-select {
padding: 3px 5px;
margin-right: 4px;
}
.gantt {

119
dist/frappe-gantt.js vendored
View File

@ -1277,7 +1277,6 @@ var Gantt = (function () {
task._end = date_utils.parse(task.end);
let diff = date_utils.diff(task._end, task._start, "year");
if (diff < 0) {
console.log(task._end, task._start);
throw Error("start of task can't be after end of task: in task #, " + (i + 1))
}
// make task invalid if duration too large
@ -1565,19 +1564,59 @@ var Gantt = (function () {
}
make_grid_header() {
const curHeader = document.querySelector('.grid-header');
if (curHeader) {
curHeader.remove();
}
let $header = document.createElement("div");
$header.style.height = this.options.header_height + 10 + "px";
$header.style.width = this.dates.length * this.options.column_width + "px";
$header.classList.add('grid-header');
this.$header = $header;
this.$svg.parentElement.appendChild($header);
this.$container.appendChild($header);
let $upper_header = document.createElement("div");
$upper_header.classList.add('upper-header');
this.$upper_header = $upper_header;
this.$header.appendChild($upper_header);
let $lower_header = document.createElement("div");
$lower_header.classList.add('lower-header');
this.$lower_header = $lower_header;
this.$header.appendChild($lower_header);
let $side_header = document.createElement('div');
$side_header.classList.add('side-header');
// Create view mode change select
const $select = document.createElement("select");
$select.classList.add('viewmode-select');
for (const key in VIEW_MODE) {
const $option = document.createElement("option");
$option.value = VIEW_MODE[key];
$option.textContent = VIEW_MODE[key];
$select.appendChild($option);
}
$select.value = this.options.view_mode;
$select.addEventListener("change", (function () {
this.change_view_mode($select.value);
}).bind(this));
$side_header.appendChild($select);
// Create today button
let $today_button = document.createElement('button');
$today_button.id = 'today-button';
$today_button.classList.add('today-button');
$today_button.textContent = 'Today';
$today_button.onclick = this.scroll_today.bind(this);
this.$header.appendChild($today_button);
$side_header.appendChild($today_button);
this.$header.appendChild($side_header);
const { left, y } = $header.getBoundingClientRect();
const width = Math.min(this.$header.clientWidth, this.$container.clientWidth);
$side_header.style.left = left + this.$container.scrollLeft + width - $side_header.clientWidth + 'px';
$side_header.style.top = y + 5 + 'px';
}
make_grid_ticks() {
@ -1721,21 +1760,23 @@ var Gantt = (function () {
}
make_dates() {
this.upper_texts_x = {};
for (let date of this.get_dates_to_draw()) {
let $lower_text = document.createElement('div');
$lower_text.classList.add('lower-text');
$lower_text.style.left = date.lower_x + 'px';
$lower_text.style.top = date.lower_y + 'px';
$lower_text.innerText = date.lower_text;
this.$header.appendChild($lower_text);
this.$lower_header.appendChild($lower_text);
if (date.upper_text) {
this.upper_texts_x[date.upper_text] = date.upper_x;
let $upper_text = document.createElement('div');
$upper_text.classList.add('lower-text');
$upper_text.classList.add('upper-text');
$upper_text.style.left = date.upper_x + 'px';
$upper_text.style.top = date.upper_y + 'px';
$upper_text.innerText = date.upper_text;
this.$header.appendChild($upper_text);
this.$upper_header.appendChild($upper_text);
// remove out-of-bound dates
if (date.upper_x > this.layers.grid.getBBox().width) {
@ -1755,9 +1796,8 @@ var Gantt = (function () {
return dates;
}
get_date_info(date, last_date_info, i) {
get_date_info(date, last_date_info) {
let last_date = last_date_info ? last_date_info.date : date_utils.add(date, 1, "day");
const date_text = {
Hour_lower: date_utils.format(date, "HH", this.options.language),
"Quarter Day_lower": date_utils.format(date, "HH", this.options.language),
@ -1787,7 +1827,7 @@ var Gantt = (function () {
: date_utils.format(date, "D", this.options.language)
: "",
Day_upper:
date.getMonth() !== last_date.getMonth()
date.getMonth() !== last_date.getMonth() || !last_date_info
? date_utils.format(date, "MMMM", this.options.language)
: "",
Week_upper:
@ -1809,26 +1849,25 @@ var Gantt = (function () {
? last_date_info.base_pos_x + last_date_info.column_width
: 0,
lower_y: this.options.header_height - 15,
upper_y: this.options.header_height - 35,
upper_y: this.options.header_height - 40,
};
const x_pos = {
Hour_lower: this.options.column_width / 2,
Hour_upper: this.options.column_width * 12,
"Quarter Day_lower": this.options.column_width / 2,
"Quarter Day_upper": this.options.column_width * 2,
"Half Day_lower": this.options.column_width / 2,
"Half Day_upper": this.options.column_width,
Day_lower: this.options.column_width / 2,
Day_upper: (this.options.column_width * 30) / 2,
Hour_lower: column_width / 2,
Hour_upper: column_width * 12,
"Quarter Day_lower": column_width / 2,
"Quarter Day_upper": column_width * 2,
"Half Day_lower": column_width / 2,
"Half Day_upper": column_width,
Day_lower: column_width / 2,
Day_upper: column_width / 2,
Week_lower: 0,
Week_upper: (this.options.column_width * 4) / 2,
Week_upper: (column_width * 4) / 2,
Month_lower: column_width / 2,
Month_upper: (column_width * 12) / 2,
Year_lower: this.options.column_width / 2,
Year_upper: (this.options.column_width * 30) / 2,
Month_upper: column_width / 2,
Year_lower: column_width / 2,
Year_upper: (column_width * 30) / 2,
};
console.log(base_pos.x, x_pos[`${this.options.view_mode}_lower`],);
return {
date,
column_width,
@ -1910,7 +1949,7 @@ var Gantt = (function () {
(hours_before_first_task / this.options.step) *
this.options.column_width -
this.options.column_width;
console.log(parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' }));
parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' });
}
scroll_today() {
@ -1990,6 +2029,34 @@ var Gantt = (function () {
dx = e.currentTarget.scrollLeft - x_on_scroll_start;
}
const daysSinceStart = e.currentTarget.scrollLeft / this.options.column_width * this.options.step / 24;
let format_str = "D MMM";
if (["Year", "Month"].includes(this.options.view_mode)) format_str = 'YYYY';
else if (["Day", "Week"].includes(this.options.view_mode)) format_str = 'MMMM';
else if (this.view_is('Half Day')) format_str = 'D';
else if (this.view_is('Hour')) format_str = "D MMMM";
let currentUpper = date_utils.format(
date_utils.add(this.gantt_start, daysSinceStart, 'day'),
format_str
);
const upperTexts = Array.from(document.querySelectorAll('.upper-text'));
const $el = upperTexts.find(el => el.textContent === currentUpper);
if ($el && !$el.classList.contains('current-upper')) {
const $current = document.querySelector('.current-upper');
if ($current) {
$current.classList.remove('current-upper');
$current.style.left = this.upper_texts_x[$current.textContent] + 'px';
$current.style.top = this.options.header_height - 40 + 'px';
}
$el.classList.add('current-upper');
let dimensions = this.$svg.getBoundingClientRect();
$el.style.left = dimensions.x + this.$container.scrollLeft + 10 + 'px';
$el.style.top = dimensions.y + this.options.header_height - 40 + 'px';
}
Array.prototype.forEach.call(elements, function (el, i) {
ids.push(el.getAttribute('data-id'));
});

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
.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-container .grid-header{background-color:#fff;position:sticky;top:0;left:0}.gantt-container .lower-text,.gantt-container .upper-text{font-size:14px;text-anchor:middle;color:#666}.gantt-container .lower-text{position:absolute;width:fit-content}.gantt-container #today-button{position:sticky;left:10px;top:5px;background-color:#2c94ec;border:none;color:#fff;padding:4px 10px;font-size:14px;border-radius:2px}.gantt{user-select:none;-webkit-user-select:none;position:absolute}.gantt .grid-background{fill:none}.gantt .grid-row{fill:#fff}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.2}.gantt .tick.thick{stroke:#000;stroke-width:.5}.gantt .today-highlight{fill:#f6e796;opacity:.5}.gantt .week-highlight{fill:#f6e796;opacity:.5}.gantt .holiday-highlight{fill:#f3f4f7;opacity:.5}.gantt .month-highlight{fill:#f6e796;opacity:.5}.gantt .year-highlight{fill:#f6e796;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar-wrapper .bar{fill:#fff;stroke:#fff;stroke-width:0;transition:stroke-width .3s ease}.gantt .bar-progress{fill:#dedfe0}.gantt .date-highlight{fill:#e8e8e8;display:none}.gantt .bar-expected-progress{fill:#c4c4e9}.gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#fff;stroke-width:1;stroke-dasharray:5}.gantt .bar-invalid~.bar-label{fill:#fff}.gantt .bar-label{fill:#111;dominant-baseline:central;font-family:Helvetica;font-size:14px;font-weight:400}.gantt .bar-label.big{fill:#111;text-anchor:start}.gantt .bar-wrapper.important .bar{fill:#94c4f4}.gantt .bar-wrapper.important .bar-progress{fill:#2c94ec}.gantt .bar-wrapper.important .bar-label{fill:#fff}.gantt .bar-wrapper.important .handle{fill:#94c4f4}.gantt .handle{fill:#dcdce4;cursor:ew-resize;opacity:0;visibility:hidden;transition:opacity .3s ease}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper.active .handle{visibility:visible;opacity:1}.gantt .bar-wrapper .bar{-webkit-filter:drop-shadow(3px 3px 2px rgba(0, 0, 0, 0.7));filter:drop-shadow(0 0 2px rgba(17, 43, 66, 0.16));border-radius:3px}.gantt .bar-wrapper:hover .bar{transition:transform .3s ease}.gantt .bar-wrapper:hover .date-highlight{display:block}.gantt .hide{display:none}.gantt-container{position:relative;overflow:auto;font-size:12px;height:500px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:#000;padding:0;color:#959da5;border-radius:3px;border:1px solid #000;width:max-content}.gantt-container .popup-wrapper.hidden{opacity:0 !important}.gantt-container .popup-wrapper .title{border-bottom:1px solid #dedfe0;padding:10px;text-align:center;color:#fff}.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-bottom-color:rgba(0,0,0,.8)}
.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-container .grid-header{background-color:#fff;position:sticky;top:0;left:0}.gantt-container .lower-text,.gantt-container .upper-text{font-size:14px;text-anchor:middle;color:#666}.gantt-container .lower-text{position:absolute;width:fit-content}.gantt-container .upper-text{position:absolute;width:fit-content}.gantt-container .current-upper{position:fixed}.gantt-container .side-header{position:fixed;padding:0 10px;background:#fff}.gantt-container .today-button,.gantt-container .viewmode-select{background-color:#fff;border:1px solid #000;color:#111;padding:4px 10px;font-size:14px;border-radius:5px}.gantt-container .viewmode-select{padding:3px 5px;margin-right:4px}.gantt{user-select:none;-webkit-user-select:none;position:absolute}.gantt .grid-background{fill:none}.gantt .grid-row{fill:#fff}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.2}.gantt .tick.thick{stroke:#000;stroke-width:.5}.gantt .today-highlight{fill:#f6e796;opacity:.5}.gantt .week-highlight{fill:#f6e796;opacity:.5}.gantt .holiday-highlight{fill:#f3f4f7;opacity:.5}.gantt .month-highlight{fill:#f6e796;opacity:.5}.gantt .year-highlight{fill:#f6e796;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar-wrapper .bar{fill:#fff;stroke:#fff;stroke-width:0;transition:stroke-width .3s ease}.gantt .bar-progress{fill:#dedfe0}.gantt .date-highlight{fill:#e8e8e8;display:none}.gantt .bar-expected-progress{fill:#c4c4e9}.gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#fff;stroke-width:1;stroke-dasharray:5}.gantt .bar-invalid~.bar-label{fill:#fff}.gantt .bar-label{fill:#111;dominant-baseline:central;font-family:Helvetica;font-size:14px;font-weight:400}.gantt .bar-label.big{fill:#111;text-anchor:start}.gantt .bar-wrapper.important .bar{fill:#94c4f4}.gantt .bar-wrapper.important .bar-progress{fill:#2c94ec}.gantt .bar-wrapper.important .bar-label{fill:#fff}.gantt .bar-wrapper.important .handle{fill:#94c4f4}.gantt .handle{fill:#dcdce4;cursor:ew-resize;opacity:0;visibility:hidden;transition:opacity .3s ease}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper.active .handle{visibility:visible;opacity:1}.gantt .bar-wrapper .bar{-webkit-filter:drop-shadow(3px 3px 2px rgba(0, 0, 0, 0.7));filter:drop-shadow(0 0 2px rgba(17, 43, 66, 0.16));border-radius:3px}.gantt .bar-wrapper:hover .bar{transition:transform .3s ease}.gantt .bar-wrapper:hover .date-highlight{display:block}.gantt .hide{display:none}.gantt-container{position:relative;overflow:auto;font-size:12px;height:500px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:#000;padding:0;color:#959da5;border-radius:3px;border:1px solid #000;width:max-content}.gantt-container .popup-wrapper.hidden{opacity:0 !important}.gantt-container .popup-wrapper .title{border-bottom:1px solid #dedfe0;padding:10px;text-align:center;color:#fff}.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-bottom-color:rgba(0,0,0,.8)}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -37,16 +37,34 @@ $light-blue: #c4c4e9 !default;
width: fit-content;
}
#today-button {
position: sticky;
left: 10px;
top: 5px;
background-color: $progress-important;
border: none;
color: $text-light;
.upper-text {
position: absolute;
width: fit-content;
}
.current-upper {
position: fixed;
}
.side-header {
position: fixed;
padding: 0 10px;
background: white;
}
.today-button,
.viewmode-select {
background-color: $text-light;
border: 1px solid black;
color: $text-dark;
padding: 4px 10px;
font-size: 14px;
border-radius: 2px;
border-radius: 5px;
}
.viewmode-select {
padding: 3px 5px;
margin-right: 4px;
}
}

View File

@ -136,7 +136,6 @@ export default class Gantt {
task._end = date_utils.parse(task.end);
let diff = date_utils.diff(task._end, task._start, "year");
if (diff < 0) {
console.log(task._end, task._start)
throw Error("start of task can't be after end of task: in task #, " + (i + 1))
}
// make task invalid if duration too large
@ -424,19 +423,60 @@ export default class Gantt {
}
make_grid_header() {
let $header = document.createElement("div");
const curHeader = document.querySelector('.grid-header')
if (curHeader) {
curHeader.remove()
};
let $header = document.createElement("div");
$header.style.height = this.options.header_height + 10 + "px";
$header.style.width = this.dates.length * this.options.column_width + "px";
$header.classList.add('grid-header')
this.$header = $header
this.$svg.parentElement.appendChild($header)
this.$container.appendChild($header)
let $upper_header = document.createElement("div");
$upper_header.classList.add('upper-header')
this.$upper_header = $upper_header
this.$header.appendChild($upper_header)
let $lower_header = document.createElement("div");
$lower_header.classList.add('lower-header')
this.$lower_header = $lower_header
this.$header.appendChild($lower_header)
let $side_header = document.createElement('div')
$side_header.classList.add('side-header')
// Create view mode change select
const $select = document.createElement("select");
$select.classList.add('viewmode-select')
for (const key in VIEW_MODE) {
const $option = document.createElement("option");
$option.value = VIEW_MODE[key];
$option.textContent = VIEW_MODE[key];
$select.appendChild($option);
}
$select.value = this.options.view_mode
$select.addEventListener("change", (function () {
this.change_view_mode($select.value)
}).bind(this));
$side_header.appendChild($select)
// Create today button
let $today_button = document.createElement('button')
$today_button.id = 'today-button'
$today_button.classList.add('today-button')
$today_button.textContent = 'Today'
$today_button.onclick = this.scroll_today.bind(this)
this.$header.appendChild($today_button)
$side_header.appendChild($today_button)
this.$header.appendChild($side_header)
const { left, y } = $header.getBoundingClientRect();
const width = Math.min(this.$header.clientWidth, this.$container.clientWidth)
$side_header.style.left = left + this.$container.scrollLeft + width - $side_header.clientWidth + 'px';
$side_header.style.top = y + 5 + 'px';
}
make_grid_ticks() {
@ -580,21 +620,23 @@ export default class Gantt {
}
make_dates() {
this.upper_texts_x = {}
for (let date of this.get_dates_to_draw()) {
let $lower_text = document.createElement('div');
$lower_text.classList.add('lower-text')
$lower_text.style.left = date.lower_x + 'px'
$lower_text.style.top = date.lower_y + 'px'
$lower_text.innerText = date.lower_text
this.$header.appendChild($lower_text)
this.$lower_header.appendChild($lower_text)
if (date.upper_text) {
this.upper_texts_x[date.upper_text] = date.upper_x
let $upper_text = document.createElement('div');
$upper_text.classList.add('lower-text')
$upper_text.classList.add('upper-text')
$upper_text.style.left = date.upper_x + 'px'
$upper_text.style.top = date.upper_y + 'px'
$upper_text.innerText = date.upper_text
this.$header.appendChild($upper_text)
this.$upper_header.appendChild($upper_text)
// remove out-of-bound dates
if (date.upper_x > this.layers.grid.getBBox().width) {
@ -614,9 +656,8 @@ export default class Gantt {
return dates;
}
get_date_info(date, last_date_info, i) {
get_date_info(date, last_date_info) {
let last_date = last_date_info ? last_date_info.date : date_utils.add(date, 1, "day")
const date_text = {
Hour_lower: date_utils.format(date, "HH", this.options.language),
"Quarter Day_lower": date_utils.format(date, "HH", this.options.language),
@ -646,7 +687,7 @@ export default class Gantt {
: date_utils.format(date, "D", this.options.language)
: "",
Day_upper:
date.getMonth() !== last_date.getMonth()
date.getMonth() !== last_date.getMonth() || !last_date_info
? date_utils.format(date, "MMMM", this.options.language)
: "",
Week_upper:
@ -668,26 +709,25 @@ export default class Gantt {
? last_date_info.base_pos_x + last_date_info.column_width
: 0,
lower_y: this.options.header_height - 15,
upper_y: this.options.header_height - 35,
upper_y: this.options.header_height - 40,
};
const x_pos = {
Hour_lower: this.options.column_width / 2,
Hour_upper: this.options.column_width * 12,
"Quarter Day_lower": this.options.column_width / 2,
"Quarter Day_upper": this.options.column_width * 2,
"Half Day_lower": this.options.column_width / 2,
"Half Day_upper": this.options.column_width,
Day_lower: this.options.column_width / 2,
Day_upper: (this.options.column_width * 30) / 2,
Hour_lower: column_width / 2,
Hour_upper: column_width * 12,
"Quarter Day_lower": column_width / 2,
"Quarter Day_upper": column_width * 2,
"Half Day_lower": column_width / 2,
"Half Day_upper": column_width,
Day_lower: column_width / 2,
Day_upper: column_width / 2,
Week_lower: 0,
Week_upper: (this.options.column_width * 4) / 2,
Week_upper: (column_width * 4) / 2,
Month_lower: column_width / 2,
Month_upper: (column_width * 12) / 2,
Year_lower: this.options.column_width / 2,
Year_upper: (this.options.column_width * 30) / 2,
Month_upper: column_width / 2,
Year_lower: column_width / 2,
Year_upper: (column_width * 30) / 2,
};
console.log(base_pos.x, x_pos[`${this.options.view_mode}_lower`],)
return {
date,
column_width,
@ -769,7 +809,7 @@ export default class Gantt {
(hours_before_first_task / this.options.step) *
this.options.column_width -
this.options.column_width;
console.log(parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' }))
parent_element.scrollTo({ left: scroll_pos, behavior: 'smooth' })
}
scroll_today() {
@ -849,6 +889,34 @@ export default class Gantt {
dx = e.currentTarget.scrollLeft - x_on_scroll_start;
}
const daysSinceStart = e.currentTarget.scrollLeft / this.options.column_width * this.options.step / 24;
let format_str = "D MMM"
if (["Year", "Month"].includes(this.options.view_mode)) format_str = 'YYYY'
else if (["Day", "Week"].includes(this.options.view_mode)) format_str = 'MMMM'
else if (this.view_is('Half Day')) format_str = 'D'
else if (this.view_is('Hour')) format_str = "D MMMM"
let currentUpper = date_utils.format(
date_utils.add(this.gantt_start, daysSinceStart, 'day'),
format_str
);
const upperTexts = Array.from(document.querySelectorAll('.upper-text'));
const $el = upperTexts.find(el => el.textContent === currentUpper)
if ($el && !$el.classList.contains('current-upper')) {
const $current = document.querySelector('.current-upper')
if ($current) {
$current.classList.remove('current-upper')
$current.style.left = this.upper_texts_x[$current.textContent] + 'px';
$current.style.top = this.options.header_height - 40 + 'px';
}
$el.classList.add('current-upper')
let dimensions = this.$svg.getBoundingClientRect()
$el.style.left = dimensions.x + this.$container.scrollLeft + 10 + 'px';
$el.style.top = dimensions.y + this.options.header_height - 40 + 'px';
}
Array.prototype.forEach.call(elements, function (el, i) {
ids.push(el.getAttribute('data-id'));
});