Change Bar hover behaviour, Bar animation
This commit is contained in:
parent
e55107ee82
commit
390fd2d324
8
dist/frappe-gantt.css
vendored
8
dist/frappe-gantt.css
vendored
@ -68,12 +68,16 @@
|
||||
.gantt .bar-wrapper {
|
||||
cursor: pointer; }
|
||||
.gantt .bar-wrapper:hover .bar {
|
||||
stroke-width: 2; }
|
||||
fill: #a9b5c1; }
|
||||
.gantt .bar-wrapper:hover .bar-progress {
|
||||
fill: #8a8aff; }
|
||||
.gantt .bar-wrapper:hover .handle {
|
||||
visibility: visible;
|
||||
opacity: 1; }
|
||||
.gantt .bar-wrapper.active .bar {
|
||||
stroke-width: 2; }
|
||||
fill: #a9b5c1; }
|
||||
.gantt .bar-wrapper.active .bar-progress {
|
||||
fill: #8a8aff; }
|
||||
|
||||
.gantt .lower-text, .gantt .upper-text {
|
||||
font-size: 12px;
|
||||
|
||||
120
dist/frappe-gantt.js
vendored
120
dist/frappe-gantt.js
vendored
@ -245,7 +245,64 @@ function createSVG(tag, attrs) {
|
||||
return elem;
|
||||
}
|
||||
|
||||
function animateSVG(svgElement, attr, from, to) {
|
||||
const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);
|
||||
|
||||
if (animatedSvgElement === svgElement) {
|
||||
// triggered 2nd time programmatically
|
||||
// trigger artificial click event
|
||||
const event = document.createEvent('HTMLEvents');
|
||||
event.initEvent('click', true, true);
|
||||
event.eventName = 'click';
|
||||
animatedSvgElement.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
function getAnimationElement(
|
||||
svgElement,
|
||||
attr,
|
||||
from,
|
||||
to,
|
||||
dur = '0.4s',
|
||||
begin = '0.1s'
|
||||
) {
|
||||
const animEl = svgElement.querySelector('animate');
|
||||
if (animEl) {
|
||||
$.attr(animEl, {
|
||||
attributeName: attr,
|
||||
from,
|
||||
to,
|
||||
dur,
|
||||
begin: 'click + ' + begin // artificial click
|
||||
});
|
||||
return svgElement;
|
||||
}
|
||||
|
||||
const animateElement = createSVG('animate', {
|
||||
attributeName: attr,
|
||||
from,
|
||||
to,
|
||||
dur,
|
||||
begin,
|
||||
calcMode: 'spline',
|
||||
values: from + ';' + to,
|
||||
keyTimes: '0; 1',
|
||||
keySplines: cubic_bezier('ease-out')
|
||||
});
|
||||
svgElement.appendChild(animateElement);
|
||||
|
||||
return svgElement;
|
||||
}
|
||||
|
||||
function cubic_bezier(name) {
|
||||
return {
|
||||
ease: '.25 .1 .25 1',
|
||||
linear: '0 0 1 1',
|
||||
'ease-in': '.42 0 1 1',
|
||||
'ease-out': '0 0 .58 1',
|
||||
'ease-in-out': '.42 0 .58 1'
|
||||
}[name];
|
||||
}
|
||||
|
||||
$.on = (element, event, selector, callback) => {
|
||||
if (!callback) {
|
||||
@ -385,6 +442,8 @@ class Bar {
|
||||
append_to: this.bar_group
|
||||
});
|
||||
|
||||
animateSVG(this.$bar, 'width', 0, this.width);
|
||||
|
||||
if (this.invalid) {
|
||||
this.$bar.classList.add('bar-invalid');
|
||||
}
|
||||
@ -402,6 +461,8 @@ class Bar {
|
||||
class: 'bar-progress',
|
||||
append_to: this.bar_group
|
||||
});
|
||||
|
||||
animateSVG(this.$bar_progress, 'width', 0, this.progress_width);
|
||||
}
|
||||
|
||||
draw_label() {
|
||||
@ -412,7 +473,8 @@ class Bar {
|
||||
class: 'bar-label',
|
||||
append_to: this.bar_group
|
||||
});
|
||||
this.update_label_position();
|
||||
// labels get BBox in the next tick
|
||||
requestAnimationFrame(() => this.update_label_position());
|
||||
}
|
||||
|
||||
draw_resize_handles() {
|
||||
@ -467,27 +529,35 @@ class Bar {
|
||||
bind() {
|
||||
if (this.invalid) return;
|
||||
this.setup_click_event();
|
||||
this.show_details();
|
||||
// this.bind_resize_progress();
|
||||
}
|
||||
|
||||
show_details() {
|
||||
this.group.onclick = e => {
|
||||
setup_click_event() {
|
||||
$.on(this.group, 'click', e => {
|
||||
if (this.action_completed) {
|
||||
// just finished a move action, wait for a few seconds
|
||||
return;
|
||||
}
|
||||
|
||||
const start_date = date_utils.format(this.task._start, 'MMM D');
|
||||
const end_date = date_utils.format(this.task._end, 'MMM D');
|
||||
const subtitle = start_date + ' - ' + end_date;
|
||||
if (this.group.classList.contains('active')) {
|
||||
this.gantt.trigger_event('click', [this.task]);
|
||||
}
|
||||
this.gantt.unselect_all();
|
||||
this.group.classList.toggle('active');
|
||||
|
||||
this.gantt.show_popup({
|
||||
target_element: this.$bar,
|
||||
title: this.task.name,
|
||||
subtitle: subtitle
|
||||
});
|
||||
};
|
||||
this.show_popup();
|
||||
});
|
||||
}
|
||||
|
||||
show_popup() {
|
||||
const start_date = date_utils.format(this.task._start, 'MMM D');
|
||||
const end_date = date_utils.format(this.task._end, 'MMM D');
|
||||
const subtitle = start_date + ' - ' + end_date;
|
||||
|
||||
this.gantt.show_popup({
|
||||
target_element: this.$bar,
|
||||
title: this.task.name,
|
||||
subtitle: subtitle
|
||||
});
|
||||
}
|
||||
|
||||
update_bar_position({ x = null, width = null }) {
|
||||
@ -517,20 +587,6 @@ class Bar {
|
||||
// this.update_details_position();
|
||||
}
|
||||
|
||||
setup_click_event() {
|
||||
this.group.onclick = () => {
|
||||
if (this.action_completed) {
|
||||
// just finished a move action, wait for a few seconds
|
||||
return;
|
||||
}
|
||||
if (this.group.classList.contains('active')) {
|
||||
this.gantt.trigger_event('click', [this.task]);
|
||||
}
|
||||
this.gantt.unselect_all();
|
||||
this.group.classList.toggle('active');
|
||||
};
|
||||
}
|
||||
|
||||
date_changed() {
|
||||
const { new_start_date, new_end_date } = this.compute_start_end_date();
|
||||
this.task._start = new_start_date;
|
||||
@ -662,6 +718,7 @@ class Bar {
|
||||
update_label_position() {
|
||||
const bar = this.$bar,
|
||||
label = this.group.querySelector('.bar-label');
|
||||
|
||||
if (label.getBBox().width > bar.getWidth()) {
|
||||
label.classList.add('big');
|
||||
label.setAttribute('x', bar.getX() + bar.getWidth() + 5);
|
||||
@ -849,6 +906,7 @@ class Popup {
|
||||
this.pointer.style.top =
|
||||
this.title.clientHeight / 2 -
|
||||
this.pointer.getBoundingClientRect().height +
|
||||
2 +
|
||||
'px';
|
||||
}
|
||||
|
||||
@ -1421,7 +1479,7 @@ class Gantt {
|
||||
bind_grid_click() {
|
||||
this.layers.grid.onclick = () => {
|
||||
this.unselect_all();
|
||||
this.popup && this.popup.hide();
|
||||
this.hide_popup();
|
||||
};
|
||||
}
|
||||
|
||||
@ -1661,6 +1719,10 @@ class Gantt {
|
||||
this.popup.show(options);
|
||||
}
|
||||
|
||||
hide_popup() {
|
||||
this.popup && this.popup.hide();
|
||||
}
|
||||
|
||||
trigger_event(event, args) {
|
||||
if (this.options['on_' + event]) {
|
||||
this.options['on_' + event].apply(null, args);
|
||||
|
||||
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
58
src/Bar.js
58
src/Bar.js
@ -1,5 +1,5 @@
|
||||
import date_utils from './date_utils';
|
||||
import { createSVG } from './svg_utils';
|
||||
import { $, createSVG, animateSVG } from './svg_utils';
|
||||
|
||||
export default class Bar {
|
||||
constructor(gantt, task) {
|
||||
@ -85,6 +85,8 @@ export default class Bar {
|
||||
append_to: this.bar_group
|
||||
});
|
||||
|
||||
animateSVG(this.$bar, 'width', 0, this.width);
|
||||
|
||||
if (this.invalid) {
|
||||
this.$bar.classList.add('bar-invalid');
|
||||
}
|
||||
@ -102,6 +104,8 @@ export default class Bar {
|
||||
class: 'bar-progress',
|
||||
append_to: this.bar_group
|
||||
});
|
||||
|
||||
animateSVG(this.$bar_progress, 'width', 0, this.progress_width);
|
||||
}
|
||||
|
||||
draw_label() {
|
||||
@ -112,7 +116,8 @@ export default class Bar {
|
||||
class: 'bar-label',
|
||||
append_to: this.bar_group
|
||||
});
|
||||
this.update_label_position();
|
||||
// labels get BBox in the next tick
|
||||
requestAnimationFrame(() => this.update_label_position());
|
||||
}
|
||||
|
||||
draw_resize_handles() {
|
||||
@ -167,27 +172,35 @@ export default class Bar {
|
||||
bind() {
|
||||
if (this.invalid) return;
|
||||
this.setup_click_event();
|
||||
this.show_details();
|
||||
// this.bind_resize_progress();
|
||||
}
|
||||
|
||||
show_details() {
|
||||
this.group.onclick = e => {
|
||||
setup_click_event() {
|
||||
$.on(this.group, 'click', e => {
|
||||
if (this.action_completed) {
|
||||
// just finished a move action, wait for a few seconds
|
||||
return;
|
||||
}
|
||||
|
||||
const start_date = date_utils.format(this.task._start, 'MMM D');
|
||||
const end_date = date_utils.format(this.task._end, 'MMM D');
|
||||
const subtitle = start_date + ' - ' + end_date;
|
||||
if (this.group.classList.contains('active')) {
|
||||
this.gantt.trigger_event('click', [this.task]);
|
||||
}
|
||||
this.gantt.unselect_all();
|
||||
this.group.classList.toggle('active');
|
||||
|
||||
this.gantt.show_popup({
|
||||
target_element: this.$bar,
|
||||
title: this.task.name,
|
||||
subtitle: subtitle
|
||||
});
|
||||
};
|
||||
this.show_popup();
|
||||
});
|
||||
}
|
||||
|
||||
show_popup() {
|
||||
const start_date = date_utils.format(this.task._start, 'MMM D');
|
||||
const end_date = date_utils.format(this.task._end, 'MMM D');
|
||||
const subtitle = start_date + ' - ' + end_date;
|
||||
|
||||
this.gantt.show_popup({
|
||||
target_element: this.$bar,
|
||||
title: this.task.name,
|
||||
subtitle: subtitle
|
||||
});
|
||||
}
|
||||
|
||||
update_bar_position({ x = null, width = null }) {
|
||||
@ -217,20 +230,6 @@ export default class Bar {
|
||||
// this.update_details_position();
|
||||
}
|
||||
|
||||
setup_click_event() {
|
||||
this.group.onclick = () => {
|
||||
if (this.action_completed) {
|
||||
// just finished a move action, wait for a few seconds
|
||||
return;
|
||||
}
|
||||
if (this.group.classList.contains('active')) {
|
||||
this.gantt.trigger_event('click', [this.task]);
|
||||
}
|
||||
this.gantt.unselect_all();
|
||||
this.group.classList.toggle('active');
|
||||
};
|
||||
}
|
||||
|
||||
date_changed() {
|
||||
const { new_start_date, new_end_date } = this.compute_start_end_date();
|
||||
this.task._start = new_start_date;
|
||||
@ -362,6 +361,7 @@ export default class Bar {
|
||||
update_label_position() {
|
||||
const bar = this.$bar,
|
||||
label = this.group.querySelector('.bar-label');
|
||||
|
||||
if (label.getBBox().width > bar.getWidth()) {
|
||||
label.classList.add('big');
|
||||
label.setAttribute('x', bar.getX() + bar.getWidth() + 5);
|
||||
|
||||
@ -92,7 +92,11 @@ $handle-color: #ddd;
|
||||
|
||||
&:hover {
|
||||
.bar {
|
||||
stroke-width: 2;
|
||||
fill: darken($bar-color, 5);
|
||||
}
|
||||
|
||||
.bar-progress {
|
||||
fill: darken($blue, 5);
|
||||
}
|
||||
|
||||
.handle {
|
||||
@ -103,7 +107,11 @@ $handle-color: #ddd;
|
||||
|
||||
&.active {
|
||||
.bar {
|
||||
stroke-width: 2;
|
||||
fill: darken($bar-color, 5);
|
||||
}
|
||||
|
||||
.bar-progress {
|
||||
fill: darken($blue, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -566,7 +566,7 @@ export default class Gantt {
|
||||
bind_grid_click() {
|
||||
this.layers.grid.onclick = () => {
|
||||
this.unselect_all();
|
||||
this.popup && this.popup.hide();
|
||||
this.hide_popup();
|
||||
};
|
||||
}
|
||||
|
||||
@ -806,6 +806,10 @@ export default class Gantt {
|
||||
this.popup.show(options);
|
||||
}
|
||||
|
||||
hide_popup() {
|
||||
this.popup && this.popup.hide();
|
||||
}
|
||||
|
||||
trigger_event(event, args) {
|
||||
if (this.options['on_' + event]) {
|
||||
this.options['on_' + event].apply(null, args);
|
||||
|
||||
@ -55,6 +55,7 @@ export default class Popup {
|
||||
this.pointer.style.top =
|
||||
this.title.clientHeight / 2 -
|
||||
this.pointer.getBoundingClientRect().height +
|
||||
2 +
|
||||
'px';
|
||||
}
|
||||
|
||||
|
||||
@ -37,8 +37,8 @@ function getAnimationElement(
|
||||
attr,
|
||||
from,
|
||||
to,
|
||||
dur = '0.3s',
|
||||
begin = '0s'
|
||||
dur = '0.4s',
|
||||
begin = '0.1s'
|
||||
) {
|
||||
const animEl = svgElement.querySelector('animate');
|
||||
if (animEl) {
|
||||
@ -57,13 +57,27 @@ function getAnimationElement(
|
||||
from,
|
||||
to,
|
||||
dur,
|
||||
begin
|
||||
begin,
|
||||
calcMode: 'spline',
|
||||
values: from + ';' + to,
|
||||
keyTimes: '0; 1',
|
||||
keySplines: cubic_bezier('ease-out')
|
||||
});
|
||||
svgElement.appendChild(animateElement);
|
||||
|
||||
return svgElement;
|
||||
}
|
||||
|
||||
function cubic_bezier(name) {
|
||||
return {
|
||||
ease: '.25 .1 .25 1',
|
||||
linear: '0 0 1 1',
|
||||
'ease-in': '.42 0 1 1',
|
||||
'ease-out': '0 0 .58 1',
|
||||
'ease-in-out': '.42 0 .58 1'
|
||||
}[name];
|
||||
}
|
||||
|
||||
$.on = (element, event, selector, callback) => {
|
||||
if (!callback) {
|
||||
callback = selector;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user