feat: auto change view mode, fix multiple bugs
This commit is contained in:
parent
2fd3aefd79
commit
0ee9b6ad69
30
dist/frappe-gantt.css
vendored
30
dist/frappe-gantt.css
vendored
@ -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
119
dist/frappe-gantt.js
vendored
@ -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'));
|
||||
});
|
||||
|
||||
2
dist/frappe-gantt.js.map
vendored
2
dist/frappe-gantt.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-gantt.min.css
vendored
2
dist/frappe-gantt.min.css
vendored
@ -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)}
|
||||
2
dist/frappe-gantt.min.js
vendored
2
dist/frappe-gantt.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-gantt.min.js.map
vendored
2
dist/frappe-gantt.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
120
src/index.js
120
src/index.js
@ -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'));
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user