Skip to content

Commit 3688be1

Browse files
committed
enable dragging to change the task order
1 parent dc57669 commit 3688be1

File tree

3 files changed

+130
-48
lines changed

3 files changed

+130
-48
lines changed

src/arrow.js

+3-11
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,14 @@ export default class Arrow {
2323
}
2424

2525
const start_y =
26-
this.gantt.options.header_height +
27-
this.gantt.options.bar_height +
28-
(this.gantt.options.padding + this.gantt.options.bar_height) *
29-
this.from_task.task._index +
30-
this.gantt.options.padding;
26+
this.from_task.$bar.getY() + this.gantt.options.bar_height;
3127

3228
const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2;
3329
const end_y =
34-
this.gantt.options.header_height +
35-
this.gantt.options.bar_height / 2 +
36-
(this.gantt.options.padding + this.gantt.options.bar_height) *
37-
this.to_task.task._index +
38-
this.gantt.options.padding;
30+
this.to_task.$bar.getY() + this.gantt.options.bar_height / 2;
3931

4032
const from_is_below_to =
41-
this.from_task.task._index > this.to_task.task._index;
33+
this.from_task.$bar.getY() > this.to_task.$bar.getY();
4234
const curve = this.gantt.options.arrow_curve;
4335
const clockwise = from_is_below_to ? 1 : 0;
4436
const curve_y = from_is_below_to ? -curve : curve;

src/bar.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ export default class Bar {
219219
});
220220
}
221221

222-
update_bar_position({ x = null, width = null }) {
222+
update_bar_position({ x = null, width = null, y = null }) {
223223
const bar = this.$bar;
224224
if (x) {
225225
// get all x values of parent task
@@ -239,9 +239,12 @@ export default class Bar {
239239
if (width && width >= this.gantt.options.column_width) {
240240
this.update_attr(bar, 'width', width);
241241
}
242+
if (y) {
243+
this.update_attr(bar, 'y', y);
244+
}
242245
this.update_label_position();
243-
this.update_handle_position();
244246
this.update_progressbar_position();
247+
this.update_handle_position();
245248
this.update_arrow_position();
246249
}
247250

@@ -370,6 +373,7 @@ export default class Bar {
370373
update_progressbar_position() {
371374
if (this.invalid) return;
372375
this.$bar_progress.setAttribute('x', this.$bar.getX());
376+
this.$bar_progress.setAttribute('y', this.$bar.getY());
373377
this.$bar_progress.setAttribute(
374378
'width',
375379
this.$bar.getWidth() * (this.task.progress / 100)
@@ -387,6 +391,7 @@ export default class Bar {
387391
label.classList.remove('big');
388392
label.setAttribute('x', bar.getX() + bar.getWidth() / 2);
389393
}
394+
label.setAttribute('y', bar.getY() + bar.getHeight() / 2);
390395
}
391396

392397
update_handle_position() {
@@ -395,9 +400,15 @@ export default class Bar {
395400
this.handle_group
396401
.querySelector('.handle.left')
397402
.setAttribute('x', bar.getX() + 1);
403+
this.handle_group
404+
.querySelector('.handle.left')
405+
.setAttribute('y', bar.getY() + 1);
398406
this.handle_group
399407
.querySelector('.handle.right')
400408
.setAttribute('x', bar.getEndX() - 9);
409+
this.handle_group
410+
.querySelector('.handle.right')
411+
.setAttribute('y', bar.getY() + 1);
401412
const handle = this.group.querySelector('.handle.progress');
402413
handle &&
403414
handle.setAttribute('points', this.get_progress_polygon_points());

src/index.js

+114-35
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export default class Gantt {
8787
popup_trigger: 'click',
8888
custom_popup_html: null,
8989
language: 'en',
90+
sortable: false,
9091
};
9192
this.options = Object.assign({}, default_options, options);
9293
}
@@ -649,15 +650,40 @@ export default class Gantt {
649650
);
650651
}
651652

653+
sort_bars() {
654+
const changed_bars = [];
655+
if (!this.bars) {
656+
return changed_bars;
657+
}
658+
this.bars = this.bars.sort((b0, b1) => {
659+
return b0.$bar.getY() - b1.$bar.getY();
660+
});
661+
662+
this.tasks = this.bars.map((b, i) => {
663+
const task = b.task;
664+
if (task._index !== i) {
665+
changed_bars.push(b);
666+
}
667+
task._index = i;
668+
return task;
669+
});
670+
return changed_bars;
671+
}
672+
652673
bind_bar_events() {
653674
let is_dragging = false;
654675
let x_on_start = 0;
655676
let y_on_start = 0;
656677
let is_resizing_left = false;
657678
let is_resizing_right = false;
658679
let parent_bar_id = null;
659-
let bars = []; // instanceof Bar
660-
this.bar_being_dragged = null;
680+
let bars = []; // instanceof Bars, the dragged bar and its children
681+
const min_y = this.options.header_height;
682+
const max_y =
683+
this.options.header_height +
684+
this.tasks.length *
685+
(this.options.bar_height + this.options.padding);
686+
this.bar_being_dragged = null; // instanceof dragged bar
661687

662688
function action_in_progress() {
663689
return is_dragging || is_resizing_left || is_resizing_right;
@@ -684,16 +710,18 @@ export default class Gantt {
684710
parent_bar_id,
685711
...this.get_all_dependent_tasks(parent_bar_id),
686712
];
687-
bars = ids.map((id) => this.get_bar(id));
688-
689-
this.bar_being_dragged = parent_bar_id;
690-
691-
bars.forEach((bar) => {
713+
bars = ids.map((id) => {
714+
const bar = this.get_bar(id);
715+
if (parent_bar_id === id) {
716+
this.bar_being_dragged = bar;
717+
}
692718
const $bar = bar.$bar;
693719
$bar.ox = $bar.getX();
694720
$bar.oy = $bar.getY();
695721
$bar.owidth = $bar.getWidth();
696722
$bar.finaldx = 0;
723+
$bar.finaldy = 0;
724+
return bar;
697725
});
698726
});
699727

@@ -702,53 +730,104 @@ export default class Gantt {
702730
const dx = e.offsetX - x_on_start;
703731
const dy = e.offsetY - y_on_start;
704732

733+
this.hide_popup();
734+
735+
// update the dragged bar
736+
const bar_being_dragged = this.bar_being_dragged;
737+
bar_being_dragged.$bar.finaldx = this.get_snap_position(dx);
738+
if (is_resizing_left) {
739+
bar_being_dragged.update_bar_position({
740+
x:
741+
bar_being_dragged.$bar.ox +
742+
bar_being_dragged.$bar.finaldx,
743+
width:
744+
bar_being_dragged.$bar.owidth -
745+
bar_being_dragged.$bar.finaldx,
746+
});
747+
} else if (is_resizing_right) {
748+
bar_being_dragged.update_bar_position({
749+
width:
750+
bar_being_dragged.$bar.owidth +
751+
bar_being_dragged.$bar.finaldx,
752+
});
753+
} else if (is_dragging) {
754+
let y = bar_being_dragged.$bar.oy + dy;
755+
if (y < min_y) {
756+
y = min_y;
757+
} else if (y > max_y) {
758+
y = max_y;
759+
}
760+
bar_being_dragged.update_bar_position({
761+
x:
762+
bar_being_dragged.$bar.ox +
763+
bar_being_dragged.$bar.finaldx,
764+
y: this.options.sortable ? y : null,
765+
});
766+
}
767+
768+
// update children
705769
bars.forEach((bar) => {
770+
if (bar.task.id === parent_bar_id) {
771+
return;
772+
}
706773
const $bar = bar.$bar;
707774
$bar.finaldx = this.get_snap_position(dx);
708775
this.hide_popup();
709776
if (is_resizing_left) {
710-
if (parent_bar_id === bar.task.id) {
711-
bar.update_bar_position({
712-
x: $bar.ox + $bar.finaldx,
713-
width: $bar.owidth - $bar.finaldx,
714-
});
715-
} else {
716-
bar.update_bar_position({
717-
x: $bar.ox + $bar.finaldx,
718-
});
719-
}
720-
} else if (is_resizing_right) {
721-
if (parent_bar_id === bar.task.id) {
722-
bar.update_bar_position({
723-
width: $bar.owidth + $bar.finaldx,
724-
});
725-
}
777+
bar.update_bar_position({
778+
x: $bar.ox + $bar.finaldx,
779+
});
726780
} else if (is_dragging) {
727-
bar.update_bar_position({ x: $bar.ox + $bar.finaldx });
781+
bar.update_bar_position({
782+
x: $bar.ox + $bar.finaldx,
783+
});
728784
}
729785
});
786+
787+
// update y pos
788+
if (
789+
this.options.sortable &&
790+
is_dragging &&
791+
Math.abs(dy - bar_being_dragged.$bar.finaldy) >
792+
bar_being_dragged.height
793+
) {
794+
this.sort_bars().map((bar) => {
795+
const y = bar.compute_y();
796+
if (bar.task.id === parent_bar_id) {
797+
bar.$bar.finaldy = y - bar.$bar.oy;
798+
return;
799+
}
800+
bar.update_bar_position({ y: y });
801+
});
802+
}
730803
});
731804

732805
document.addEventListener('mouseup', (e) => {
806+
const dy = e.offsetY - y_on_start;
733807
if (is_dragging || is_resizing_left || is_resizing_right) {
734-
bars.forEach((bar) => bar.group.classList.remove('active'));
808+
bars.forEach((bar) => {
809+
bar.group.classList.remove('active');
810+
811+
const $bar = bar.$bar;
812+
if ($bar.finaldx) {
813+
bar.date_changed();
814+
bar.set_action_completed();
815+
}
816+
});
817+
const $bar = this.bar_being_dragged.$bar;
818+
if (this.options.sortable && dy !== $bar.finaldy) {
819+
this.bar_being_dragged.update_bar_position({
820+
y: $bar.oy + $bar.finaldy,
821+
});
822+
}
735823
}
736824

825+
this.bar_being_dragged = null;
737826
is_dragging = false;
738827
is_resizing_left = false;
739828
is_resizing_right = false;
740829
});
741830

742-
$.on(this.$svg, 'mouseup', (e) => {
743-
this.bar_being_dragged = null;
744-
bars.forEach((bar) => {
745-
const $bar = bar.$bar;
746-
if (!$bar.finaldx) return;
747-
bar.date_changed();
748-
bar.set_action_completed();
749-
});
750-
});
751-
752831
this.bind_bar_progress();
753832
}
754833

0 commit comments

Comments
 (0)