fix: scrolling bug in infinite padding

This commit is contained in:
Safwan Samsudeen 2024-12-23 16:44:19 +05:30
parent 85399e7fdc
commit 0b33e88672
2 changed files with 44 additions and 29 deletions

View File

@ -115,7 +115,7 @@ const DEFAULT_OPTIONS = {
upper_header_height: 45, upper_header_height: 45,
lower_header_height: 30, lower_header_height: 30,
snap_at: null, snap_at: null,
infinite_padding: false, infinite_padding: true,
holidays: { 'var(--g-weekend-highlight-color)': 'weekend' }, holidays: { 'var(--g-weekend-highlight-color)': 'weekend' },
ignore: [], ignore: [],
language: 'en', language: 'en',

View File

@ -226,18 +226,21 @@ export default class Gantt {
if (typeof mode === 'string') { if (typeof mode === 'string') {
mode = this.options.view_modes.find((d) => d.name === mode); mode = this.options.view_modes.find((d) => d.name === mode);
} }
let old_scroll_op, old_scroll_pos;
const old_scroll_pos = this.$container.scrollLeft; if (change) {
const old_scroll_op = this.options.scroll_to; old_scroll_op = this.options.scroll_to;
this.options.scroll_to = null; this.options.scroll_to = null;
old_scroll_pos = this.$container.scrollLeft;
}
this.options.view_mode = mode.name; this.options.view_mode = mode.name;
this.config.view_mode = mode; this.config.view_mode = mode;
this.update_view_scale(mode); this.update_view_scale(mode);
this.setup_dates(change); this.setup_dates(change);
this.render(); this.render();
if (change) {
this.options.scroll_to = old_scroll_op; this.options.scroll_to = old_scroll_op;
this.$container.scrollLeft = old_scroll_pos; this.$container.scrollLeft = old_scroll_pos;
}
this.trigger_event('view_change', [mode]); this.trigger_event('view_change', [mode]);
} }
@ -353,7 +356,6 @@ export default class Gantt {
this.make_arrows(); this.make_arrows();
this.map_arrows_on_bars(); this.map_arrows_on_bars();
this.set_dimensions(); this.set_dimensions();
if (this.options.scroll_to !== false)
this.set_scroll_position(this.options.scroll_to); this.set_scroll_position(this.options.scroll_to);
} }
@ -881,6 +883,11 @@ export default class Gantt {
} }
set_scroll_position(date) { set_scroll_position(date) {
if (this.options.infinite_padding && (!date || date === 'start')) {
let [min_start, ..._] = this.get_start_end_positions();
this.$container.scrollLeft = min_start;
return;
}
if (!date || date === 'start') { if (!date || date === 'start') {
date = this.gantt_start; date = this.gantt_start;
} else if (date === 'end') { } else if (date === 'end') {
@ -891,8 +898,8 @@ export default class Gantt {
date = date_utils.parse(date); date = date_utils.parse(date);
} }
const parent_element = this.$svg.parentElement; // Weird bug where infinite padding results in one day offset in scroll
if (!parent_element) return; // Related to header-body displacement
const units_since_first_task = date_utils.diff( const units_since_first_task = date_utils.diff(
date, date,
this.gantt_start, this.gantt_start,
@ -901,7 +908,11 @@ export default class Gantt {
const scroll_pos = const scroll_pos =
(units_since_first_task / this.config.step) * (units_since_first_task / this.config.step) *
this.config.column_width; this.config.column_width;
parent_element.scrollTo({ left: scroll_pos - 4, behavior: 'smooth' });
this.$container.scrollTo({
left: scroll_pos - this.config.column_width / 6,
behavior: 'smooth',
});
// Calculate current scroll position's upper text // Calculate current scroll position's upper text
if (this.$current) { if (this.$current) {
@ -1026,6 +1037,21 @@ export default class Gantt {
} }
} }
get_start_end_positions() {
if (!this.bars.length) return [0, 0, 0];
let { x, width } = this.bars[0].group.getBBox();
let min_start = x;
let max_start = x;
let max_end = x + width;
Array.prototype.forEach.call(this.bars, function ({ group }, i) {
let { x, width } = group.getBBox();
if (x < min_start) min_start = x;
if (x > max_start) max_start = x;
if (x + width > max_end) max_end = x + width;
});
return [min_start, max_start, max_end];
}
bind_bar_events() { bind_bar_events() {
let is_dragging = false; let is_dragging = false;
let x_on_start = 0; let x_on_start = 0;
@ -1130,9 +1156,10 @@ export default class Gantt {
} }
$.on(this.$container, 'scroll', (e) => { $.on(this.$container, 'scroll', (e) => {
let elements = this.$container.querySelectorAll('.bar-wrapper');
let localBars = []; let localBars = [];
const ids = []; const ids = this.bars.map(({ group }) =>
group.getAttribute('data-id'),
);
let dx; let dx;
if (x_on_scroll_start) { if (x_on_scroll_start) {
dx = e.currentTarget.scrollLeft - x_on_scroll_start; dx = e.currentTarget.scrollLeft - x_on_scroll_start;
@ -1181,20 +1208,8 @@ export default class Gantt {
} }
x_on_scroll_start = e.currentTarget.scrollLeft; x_on_scroll_start = e.currentTarget.scrollLeft;
let min_start, max_end, max_start; let [min_start, max_start, max_end] =
if (elements.length) { this.get_start_end_positions();
let { x, width } = elements[0].getBBox();
min_start = x;
max_start = x;
max_end = x + width;
Array.prototype.forEach.call(elements, function (el, i) {
ids.push(el.getAttribute('data-id'));
let { x, width } = el.getBBox();
if (x < min_start) min_start = x;
if (x > max_start) max_start = x;
if (x + width > max_end) max_end = x + width;
});
}
if (x_on_scroll_start > max_end + 100) { if (x_on_scroll_start > max_end + 100) {
this.$adjust.innerHTML = '&larr;'; this.$adjust.innerHTML = '&larr;';