tg-ganttchart 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/babel.config.js +5 -0
  2. package/package.json +1 -4
  3. package/src/.eslintrc.js +18 -0
  4. package/src/App.vue +780 -0
  5. package/src/GanttElastic.standalone.vue +48 -0
  6. package/src/GanttElastic.vue +2305 -0
  7. package/src/assets/logo.png +0 -0
  8. package/src/components/Calendar/Calendar.vue +559 -0
  9. package/src/components/Calendar/CalendarRow.vue +112 -0
  10. package/src/components/Chart/Chart.vue +117 -0
  11. package/src/components/Chart/DaysHighlight.vue +60 -0
  12. package/src/components/Chart/DependencyLines.vue +112 -0
  13. package/src/components/Chart/Grid.vue +205 -0
  14. package/src/components/Chart/ProgressBar.vue +110 -0
  15. package/src/components/Chart/Row/Epic.vue +131 -0
  16. package/src/components/Chart/Row/Milestone.vue +117 -0
  17. package/src/components/Chart/Row/Project.vue +132 -0
  18. package/src/components/Chart/Row/Story.vue +127 -0
  19. package/src/components/Chart/Row/Subtask.vue +117 -0
  20. package/src/components/Chart/Row/Task.mixin.js +47 -0
  21. package/src/components/Chart/Row/Task.vue +82 -0
  22. package/src/components/Chart/Text.vue +105 -0
  23. package/src/components/Expander.vue +114 -0
  24. package/src/components/GanttElastic.standalone.vue +48 -0
  25. package/src/components/GanttElastic.vue +1646 -0
  26. package/src/components/Header/GanttViewFilter.vue +154 -0
  27. package/src/components/Header/Header.vue +266 -0
  28. package/src/components/MainView.vue +283 -0
  29. package/src/components/TaskList/ItemColumn.vue +212 -0
  30. package/src/components/TaskList/TaskList.vue +45 -0
  31. package/src/components/TaskList/TaskListHeader.vue +143 -0
  32. package/src/components/TaskList/TaskListItem.vue +35 -0
  33. package/src/components/bundle.js +28 -0
  34. package/src/components/components/Calendar/Calendar.vue +332 -0
  35. package/src/components/components/Calendar/CalendarRow.vue +96 -0
  36. package/src/components/components/Chart/Chart.vue +111 -0
  37. package/src/components/components/Chart/DaysHighlight.vue +71 -0
  38. package/src/components/components/Chart/DependencyLines.vue +112 -0
  39. package/src/components/components/Chart/Grid.vue +164 -0
  40. package/src/components/components/Chart/ProgressBar.vue +110 -0
  41. package/src/components/components/Chart/Row/Milestone.vue +117 -0
  42. package/src/components/components/Chart/Row/Project.vue +131 -0
  43. package/src/components/components/Chart/Row/Task.mixin.js +46 -0
  44. package/src/components/components/Chart/Row/Task.vue +107 -0
  45. package/src/components/components/Chart/Text.vue +105 -0
  46. package/src/components/components/Expander.vue +126 -0
  47. package/src/components/components/Header/Header.vue +265 -0
  48. package/src/components/components/MainView.vue +282 -0
  49. package/src/components/components/TaskList/ItemColumn.vue +121 -0
  50. package/src/components/components/TaskList/TaskList.vue +45 -0
  51. package/src/components/components/TaskList/TaskListHeader.vue +143 -0
  52. package/src/components/components/TaskList/TaskListItem.vue +35 -0
  53. package/src/components/components/bundle.js +28 -0
  54. package/src/components/style.js +308 -0
  55. package/src/index.js +12 -0
  56. package/src/main.js +6 -0
  57. package/src/style.js +398 -0
  58. package/vue.config.js +42 -0
  59. package/dist/demo.html +0 -1
  60. package/dist/tgganttchart.common.js +0 -9232
  61. package/dist/tgganttchart.common.js.map +0 -1
  62. package/dist/tgganttchart.css +0 -1
  63. package/dist/tgganttchart.umd.js +0 -9243
  64. package/dist/tgganttchart.umd.js.map +0 -1
  65. package/dist/tgganttchart.umd.min.js +0 -7
  66. package/dist/tgganttchart.umd.min.js.map +0 -1
@@ -0,0 +1,154 @@
1
+ <!-- GanttViewFilter.vue -->
2
+ <template>
3
+ <div class="gantt-view-filter">
4
+ <div class="view-toggle-group">
5
+ <button @click="changeViewMode('day')" :class="{ active: viewMode === 'day' }" class="view-toggle-btn">
6
+ <span class="view-icon">📅</span>
7
+ <span class="view-label">Day</span>
8
+ </button>
9
+ <button @click="changeViewMode('week')" :class="{ active: viewMode === 'week' }" class="view-toggle-btn">
10
+ <span class="view-icon">📊</span>
11
+ <span class="view-label">Week</span>
12
+ </button>
13
+ <button @click="changeViewMode('month')" :class="{ active: viewMode === 'month' }" class="view-toggle-btn">
14
+ <span class="view-icon">🗓️</span>
15
+ <span class="view-label">Month</span>
16
+ </button>
17
+ <button @click="changeViewMode('quarter')" :class="{ active: viewMode === 'quarter' }" class="view-toggle-btn">
18
+ <span class="view-icon">📈</span>
19
+ <span class="view-label">Quarter</span>
20
+ </button>
21
+ </div>
22
+ </div>
23
+ </template>
24
+
25
+ <script>
26
+ export default {
27
+ name: 'GanttViewFilter',
28
+ data() {
29
+ return {
30
+ viewMode: 'day' // default view mode
31
+ };
32
+ },
33
+ methods: {
34
+ changeViewMode(mode) {
35
+ // eslint-disable-next-line no-debugger
36
+ debugger;
37
+ this.viewMode = mode;
38
+ // Emit an event to the parent component (App.vue) so it can update the Gantt chart
39
+ this.$emit('view-mode-changed', mode);
40
+ }
41
+ }
42
+ };
43
+ </script>
44
+
45
+ <style scoped>
46
+ .gantt-view-filter {
47
+ padding: 16px 20px;
48
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
49
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
50
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
51
+ }
52
+
53
+ .view-toggle-group {
54
+ display: flex;
55
+ gap: 8px;
56
+ justify-content: right;
57
+ align-items: center;
58
+ }
59
+
60
+ .view-toggle-btn {
61
+ display: flex;
62
+ align-items: center;
63
+ gap: 8px;
64
+ padding: 12px 20px;
65
+ cursor: pointer;
66
+ border: 2px solid rgba(255, 255, 255, 0.2);
67
+ background: rgba(255, 255, 255, 0.1);
68
+ border-radius: 12px;
69
+ color: white;
70
+ font-weight: 500;
71
+ font-size: 14px;
72
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
73
+ backdrop-filter: blur(10px);
74
+ position: relative;
75
+ overflow: hidden;
76
+ }
77
+
78
+ .view-toggle-btn::before {
79
+ content: '';
80
+ position: absolute;
81
+ top: 0;
82
+ left: -100%;
83
+ width: 100%;
84
+ height: 100%;
85
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
86
+ transition: left 0.5s;
87
+ }
88
+
89
+ .view-toggle-btn:hover::before {
90
+ left: 100%;
91
+ }
92
+
93
+ .view-toggle-btn:hover {
94
+ background: rgba(255, 255, 255, 0.2);
95
+ border-color: rgba(255, 255, 255, 0.4);
96
+ transform: translateY(-2px);
97
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
98
+ }
99
+
100
+ .view-toggle-btn.active {
101
+ background: rgba(255, 255, 255, 0.9);
102
+ color: #667eea;
103
+ border-color: rgba(255, 255, 255, 0.9);
104
+ transform: translateY(-2px);
105
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);
106
+ font-weight: 600;
107
+ }
108
+
109
+ .view-icon {
110
+ font-size: 16px;
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ }
115
+
116
+ .view-label {
117
+ font-size: 14px;
118
+ font-weight: inherit;
119
+ }
120
+
121
+ /* Responsive design */
122
+ @media (max-width: 768px) {
123
+ .gantt-view-filter {
124
+ padding: 12px 16px;
125
+ }
126
+
127
+ .view-toggle-group {
128
+ gap: 6px;
129
+ }
130
+
131
+ .view-toggle-btn {
132
+ padding: 10px 16px;
133
+ font-size: 13px;
134
+ }
135
+
136
+ .view-icon {
137
+ font-size: 14px;
138
+ }
139
+
140
+ .view-label {
141
+ font-size: 13px;
142
+ }
143
+ }
144
+
145
+ @media (max-width: 480px) {
146
+ .view-toggle-btn {
147
+ padding: 8px 12px;
148
+ }
149
+
150
+ .view-label {
151
+ display: none;
152
+ }
153
+ }
154
+ </style>
@@ -0,0 +1,266 @@
1
+ <template>
2
+ <div class="gantt-elastic__header" :style="{ ...style['header'] }">
3
+ <div class="gantt-elastic__header-title" :style="{ ...style['header-title'] }">
4
+ <div class="gantt-elastic__header-title--text" :style="{ ...style['header-title--text'] }"
5
+ v-if="!opts.title.html">
6
+ {{ opts.title.label }}
7
+ </div>
8
+ <div class="gantt-elastic__header-title--html" :style="{ ...style['header-title--html'] }" v-if="opts.title.html"
9
+ v-html="opts.title.label"></div>
10
+ </div>
11
+ <div class="gantt-elastic__header-options" :style="{ ...style['header-options'] }">
12
+ <button class="gantt-elastic__header-btn-recenter" :style="{ ...style['header-btn-recenter'] }"
13
+ @click.prevent="recenterPosition">
14
+ {{ opts.locale.Now }}
15
+ </button>
16
+ <label class="gantt-elastic__header-label" :style="{ ...style['header-label'] }">
17
+ {{ opts.locale["X-Scale"] }}
18
+ <div class="gantt-elastic__header-slider-wrapper" :style="{ ...style['header-slider-wrapper'] }">
19
+ <vue-slider class="gantt-elastic__header-slider" tooltip="none" :style="{ ...style['header-slider'] }"
20
+ :process-style="{ ...style['header-slider--process'] }"
21
+ :slider-style="{ ...style['header-slider--slider'] }" v-model="scale" :max="24" :min="2"
22
+ width="100px"></vue-slider>
23
+ </div>
24
+ </label>
25
+ <label class="gantt-elastic__header-label" :style="{ ...style['header-label'] }">
26
+ {{ opts.locale["Y-Scale"] }}
27
+ <div class="gantt-elastic__header-slider-wrapper" :style="{ ...style['header-slider-wrapper'] }">
28
+ <vue-slider class="gantt-elastic__header-slider" tooltip="none" :style="{ ...style['header-slider'] }"
29
+ :process-style="{ ...style['header-slider--process'] }"
30
+ :slider-style="{ ...style['header-slider--slider'] }" v-model="height" :max="100" :min="7"
31
+ width="100px"></vue-slider>
32
+ </div>
33
+ </label>
34
+ <label class="gantt-elastic__header-label" :style="{ ...style['header-label'] }">
35
+ {{ opts.locale["Before/After"] }}
36
+ <div class="gantt-elastic__header-slider-wrapper" :style="{ ...style['header-slider-wrapper'] }">
37
+ <vue-slider class="gantt-elastic__header-slider" tooltip="none" :style="{ ...style['header-slider'] }"
38
+ :process-style="{ ...style['header-slider--process'] }"
39
+ :slider-style="{ ...style['header-slider--slider'] }" v-model="scope" :max="31" :min="0"
40
+ width="100px"></vue-slider>
41
+ </div>
42
+ </label>
43
+ <label class="gantt-elastic__header-label" :style="{ ...style['header-label'] }">
44
+ {{ opts.locale["Task list width"] }}
45
+ <div class="gantt-elastic__header-slider-wrapper" :style="{ ...style['header-slider-wrapper'] }">
46
+ <vue-slider class="gantt-elastic__header-slider" tooltip="none" :style="{ ...style['header-slider'] }"
47
+ :process-style="{ ...style['header-slider--process'] }"
48
+ :slider-style="{ ...style['header-slider--slider'] }" v-model="divider" :max="100" :min="0"
49
+ width="100px"></vue-slider>
50
+ </div>
51
+ </label>
52
+ <label class="gantt-elastic__header-task-list-switch--wrapper"
53
+ :style="{ ...style['header-task-list-switch--label'] }">
54
+ <switches class="gantt-elastic__header-task-list-switch" :style="{ ...style['header-task-list-switch'] }"
55
+ v-model="root.state.options.taskList.display"></switches>
56
+ {{ opts.locale["Display task list"] }}
57
+ </label>
58
+ </div>
59
+ </div>
60
+ </template>
61
+
62
+ <script>
63
+ import vueSlider from "vue-slider-component";
64
+ import "vue-slider-component/theme/default.css";
65
+ import Switches from "vue-switches";
66
+
67
+ const defaultStyle = {
68
+ header: {
69
+ margin: "0px auto",
70
+ background: "#f3f5f747",
71
+ padding: "10px",
72
+ overflow: "hidden",
73
+ clear: "both",
74
+ display: "flex",
75
+ "justify-content": "space-between"
76
+ },
77
+ "header-title": { float: "left" },
78
+ "header-options": { float: "right" },
79
+ "header-title--text": {
80
+ "font-size": "20px",
81
+ "vertical-align": "middle",
82
+ "font-weight": "400",
83
+ "line-height": "35px",
84
+ "padding-left": "22px",
85
+ "letter-spacing": "1px"
86
+ },
87
+ "header-title--html": {
88
+ "font-size": "20px",
89
+ "vertical-align": "middle",
90
+ "font-weight": "400",
91
+ "line-height": "35px",
92
+ "padding-left": "22px",
93
+ "letter-spacing": "1px"
94
+ },
95
+ "header-btn-recenter": {
96
+ background: "#95A5A6",
97
+ border: "none",
98
+ outline: "none",
99
+ cursor: "pointer",
100
+ color: "white",
101
+ "border-radius": "3px",
102
+ "margin-right": "27px",
103
+ "font-size": "16px",
104
+ padding: "8px 12px"
105
+ },
106
+ "header-slider": {
107
+ "box-sizing": "content-box"
108
+ },
109
+ "header-slider-wrapper": {
110
+ display: "inline-block",
111
+ "vertical-align": "middle"
112
+ },
113
+ "header-slider--slider": { "box-sizing": "content-box" },
114
+ "header-slider--process": { "box-sizing": "content-box" },
115
+ "header-task-list-switch--label": { "box-sizing": "content-box" },
116
+ "header-task-list-switch": {
117
+ margin: "0px 15px",
118
+ "vertical-align": "middle"
119
+ },
120
+ "header-label": {}
121
+ };
122
+ const defaultOptions = {
123
+ title: {
124
+ label: "ajay",
125
+ html: true
126
+ },
127
+ locale: {
128
+ Now: "Now",
129
+ "X-Scale": "Zoom-X",
130
+ "Y-Scale": "Zoom-Y",
131
+ "Task list width": "Task list",
132
+ "Before/After": "Expand",
133
+ "Display task list": "Show task list"
134
+ }
135
+ };
136
+ export default {
137
+ name: "GanttHeader",
138
+ components: {
139
+ vueSlider,
140
+ Switches
141
+ },
142
+ props: ["options", "dynamicStyle"],
143
+ inject: ["root"],
144
+ data() {
145
+ return {
146
+ scaleTimeoutId: null,
147
+ firstScale: false,
148
+ localScale: 0,
149
+ localHeight: 0,
150
+ localBefore: 0,
151
+ localPercent: 0,
152
+ sliderOptions: {
153
+ xScale: {
154
+ value: 0
155
+ }
156
+ },
157
+ style: {},
158
+ opts: {}
159
+ };
160
+ },
161
+ created() {
162
+ debugger; // eslint-disable-line no-debugger
163
+ defaultOptions.title.label = this.root.projectName
164
+ this.localScale = this.root.state.options.times.timeZoom;
165
+ this.localHeight = this.root.state.options.row.height;
166
+ this.localBefore = this.root.state.options.scope.before;
167
+ this.localPercent = this.root.state.options.taskList.percent;
168
+ this.sliderOptions.xScale.value = this.root.state.options.times.timeZoom;
169
+ this.style = this.root.mergeDeep({}, defaultStyle, this.dynamicStyle);
170
+ this.opts = this.root.mergeDeep({}, defaultOptions, this.options);
171
+ },
172
+ methods: {
173
+ getImage() {
174
+ this.root.getImage("image/png").then(imgB64 => {
175
+ const link = document.createElement("a");
176
+ link.href = imgB64;
177
+ link.download = "gantt-elastic.png";
178
+ document.body.appendChild(link);
179
+ link.click();
180
+ document.body.removeChild(link);
181
+ });
182
+ },
183
+ recenterPosition() {
184
+ this.root.$emit("recenterPosition");
185
+ },
186
+ setScale(value) {
187
+ if (this.scaleTimeoutId !== null) {
188
+ clearTimeout(this.scaleTimeoutId);
189
+ this.scaleTimeoutId = null;
190
+ }
191
+ // debouncing
192
+ if (this.firstScale) {
193
+ this.scaleTimeoutId = setTimeout(() => {
194
+ this.root.$emit("times-timeZoom-change", value);
195
+ this.scaleTimeoutId = null;
196
+ }, 50);
197
+ } else {
198
+ this.root.$emit("times-timeZoom-change", value);
199
+ this.firstScale = true;
200
+ }
201
+ }
202
+ },
203
+ computed: {
204
+ /**
205
+ * If there is a component slot specified for header
206
+ * @returns {bool}
207
+ */
208
+ beforeOptionsIsComponent() {
209
+ const headerSlot = this.options.slots.header;
210
+ if (
211
+ typeof headerSlot.beforeOptions === "object" &&
212
+ !Array.isArray(headerSlot.beforeOptions)
213
+ ) {
214
+ return true;
215
+ }
216
+ return false;
217
+ },
218
+ /**
219
+ * If there is a slot with beforeOptions html content
220
+ * @returns {bool}
221
+ */
222
+ beforeOptionsIsHtml() {
223
+ if (typeof this.options.slots.header.beforeOptions === "string") {
224
+ return true;
225
+ }
226
+ return false;
227
+ },
228
+ scale: {
229
+ get() {
230
+ return this.localScale;
231
+ },
232
+ set(value) {
233
+ this.localScale = Number(value);
234
+ this.setScale(this.localScale);
235
+ }
236
+ },
237
+ height: {
238
+ get() {
239
+ return this.localHeight;
240
+ },
241
+ set(value) {
242
+ this.localHeight = Number(value);
243
+ this.root.$emit("row-height-change", Number(value));
244
+ }
245
+ },
246
+ scope: {
247
+ get() {
248
+ return this.localBefore;
249
+ },
250
+ set(value) {
251
+ this.localBefore = Number(value);
252
+ this.root.$emit("scope-change", Number(value));
253
+ }
254
+ },
255
+ divider: {
256
+ get() {
257
+ return this.localPercent;
258
+ },
259
+ set(value) {
260
+ this.localPercent = Number(value);
261
+ this.root.$emit("taskList-width-change", Number(value));
262
+ }
263
+ }
264
+ }
265
+ };
266
+ </script>
@@ -0,0 +1,283 @@
1
+
2
+ <template>
3
+ <div class="gantt-elastic__main-view" :style="{ ...root.style['main-view'] }">
4
+ <div
5
+ class="gantt-elastic__main-container-wrapper"
6
+ :style="{ ...root.style['main-container-wrapper'], height: root.state.options.height + 'px' }"
7
+ >
8
+ <div
9
+ class="gantt-elastic__main-container"
10
+ :style="{
11
+ ...root.style['main-container'],
12
+ width: root.state.options.clientWidth + 'px',
13
+ height: root.state.options.height + 'px'
14
+ }"
15
+ ref="mainView"
16
+ >
17
+ <div
18
+ class="gantt-elastic__container"
19
+ :style="{ ...root.style['container'] }"
20
+ @mousemove="mouseMove"
21
+ @mouseup="mouseUp"
22
+ >
23
+ <div
24
+ ref="taskList"
25
+ class="gantt-elastic__task-list-container"
26
+ :style="{
27
+ ...root.style['task-list-container'],
28
+ width: root.state.options.taskList.finalWidth + 'px',
29
+ height: root.state.options.height + 'px'
30
+ }"
31
+ v-show="root.state.options.taskList.display"
32
+ >
33
+ <task-list></task-list>
34
+ </div>
35
+ <div
36
+ class="gantt-elastic__main-view-container"
37
+ :style="{ ...root.style['main-view-container'] }"
38
+ ref="chartContainer"
39
+ @mousedown="chartMouseDown"
40
+ @touchstart="chartMouseDown"
41
+ @mouseup="chartMouseUp"
42
+ @touchend="chartMouseUp"
43
+ @mousemove.prevent="chartMouseMove"
44
+ @touchmove.prevent="chartMouseMove"
45
+ @wheel.prevent="chartWheel"
46
+ >
47
+ <chart></chart>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ <div
52
+ class="gantt-elastic__chart-scroll-container gantt-elastic__chart-scroll-container--vertical"
53
+ :style="{
54
+ ...root.style['chart-scroll-container'],
55
+ ...root.style['chart-scroll-container--vertical'],
56
+ ...verticalStyle
57
+ }"
58
+ ref="chartScrollContainerVertical"
59
+ @scroll="onVerticalScroll"
60
+ >
61
+ <div
62
+ class="gantt-elastic__chart-scroll--vertical"
63
+ :style="{ width: '1px', height: root.state.options.allVisibleTasksHeight + 'px' }"
64
+ ></div>
65
+ </div>
66
+ </div>
67
+ <div
68
+ class="gantt-elastic__chart-scroll-container gantt-elastic__chart-scroll-container--horizontal"
69
+ :style="{
70
+ ...root.style['chart-scroll-container'],
71
+ ...root.style['chart-scroll-container--horizontal'],
72
+ marginLeft: getMarginLeft
73
+ }"
74
+ @scroll="onHorizontalScroll"
75
+ ref="chartScrollContainerHorizontal"
76
+ >
77
+ <div
78
+ class="gantt-elastic__chart-scroll--horizontal"
79
+ :style="{ height: '1px', width: root.state.options.width + 'px' }"
80
+ >
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </template>
85
+
86
+ <script>
87
+ import TaskList from './TaskList/TaskList.vue';
88
+ import Chart from './Chart/Chart.vue';
89
+
90
+ let ignoreScrollEvents = false;
91
+
92
+ export default {
93
+ name: 'MainView',
94
+ components: {
95
+ TaskList,
96
+ Chart
97
+ },
98
+ inject: ['root'],
99
+ data() {
100
+ return {
101
+ defs: '',
102
+ mousePos: {
103
+ x: 0,
104
+ y: 0,
105
+ movementX: 0,
106
+ movementY: 0,
107
+ lastX: 0,
108
+ lastY: 0,
109
+ positiveX: 0,
110
+ positiveY: 0,
111
+ currentX: 0,
112
+ currentY: 0
113
+ }
114
+ };
115
+ },
116
+ /**
117
+ * Mounted
118
+ */
119
+ mounted() {
120
+ this.viewBoxWidth = this.$el.clientWidth;
121
+ this.root.state.refs.mainView = this.$refs.mainView;
122
+ this.root.state.refs.chartContainer = this.$refs.chartContainer;
123
+ this.root.state.refs.taskList = this.$refs.taskList;
124
+ this.root.state.refs.chartScrollContainerHorizontal = this.$refs.chartScrollContainerHorizontal;
125
+ this.root.state.refs.chartScrollContainerVertical = this.$refs.chartScrollContainerVertical;
126
+ document.addEventListener('mouseup', this.chartMouseUp.bind(this));
127
+ document.addEventListener('mousemove', this.chartMouseMove.bind(this));
128
+ document.addEventListener('touchmove', this.chartMouseMove.bind(this));
129
+ document.addEventListener('touchend', this.chartMouseUp.bind(this));
130
+ },
131
+ computed: {
132
+ /**
133
+ * Get margin left
134
+ *
135
+ * @returns {string}
136
+ */
137
+ getMarginLeft() {
138
+ if (!this.root.state.options.taskList.display) {
139
+ return '0px';
140
+ }
141
+ return this.root.state.options.taskList.finalWidth + 'px';
142
+ },
143
+
144
+ /**
145
+ * Get vertical style
146
+ *
147
+ * @returns {object}
148
+ */
149
+ verticalStyle() {
150
+ return {
151
+ width: this.root.state.options.scrollBarHeight + 'px',
152
+ height: this.root.state.options.rowsHeight + 'px',
153
+ 'margin-top': this.root.state.options.calendar.height + this.root.state.options.calendar.gap + 'px'
154
+ };
155
+ },
156
+
157
+ /**
158
+ * Get view box
159
+ *
160
+ * @returns {string}
161
+ */
162
+ getViewBox() {
163
+ if (this.root.state.options.clientWidth) {
164
+ return `0 0 ${this.root.state.options.clientWidth - this.root.state.options.scrollBarHeight} ${
165
+ this.root.state.options.height
166
+ }`;
167
+ }
168
+ return `0 0 0 ${this.root.state.options.height}`;
169
+ }
170
+ },
171
+ methods: {
172
+ /**
173
+ * Emit event when mouse is moving inside main view
174
+ */
175
+ mouseMove(event) {
176
+ this.root.$emit('main-view-mousemove', event);
177
+ },
178
+
179
+ /**
180
+ * Emit mouseup event inside main view
181
+ */
182
+ mouseUp(event) {
183
+ this.root.$emit('main-view-mouseup', event);
184
+ },
185
+
186
+ /**
187
+ * Horizontal scroll event handler
188
+ */
189
+ onHorizontalScroll(ev) {
190
+ this.root.$emit('chart-scroll-horizontal', ev);
191
+ },
192
+
193
+ /**
194
+ * Vertical scroll event handler
195
+ */
196
+ onVerticalScroll(ev) {
197
+ this.root.$emit('chart-scroll-vertical', ev);
198
+ },
199
+
200
+ /**
201
+ * Mouse wheel event handler
202
+ */
203
+ chartWheel(ev) {
204
+ this.root.$emit('chart-wheel', ev);
205
+ },
206
+
207
+ /**
208
+ * Chart mousedown event handler
209
+ * Initiates drag scrolling mode
210
+ */
211
+ chartMouseDown(ev) {
212
+ if (typeof ev.touches !== 'undefined') {
213
+ this.mousePos.x = this.mousePos.lastX = ev.touches[0].screenX;
214
+ this.mousePos.y = this.mousePos.lastY = ev.touches[0].screenY;
215
+ this.mousePos.movementX = 0;
216
+ this.mousePos.movementY = 0;
217
+ this.mousePos.currentX = this.$refs.chartScrollContainerHorizontal.scrollLeft;
218
+ this.mousePos.currentY = this.$refs.chartScrollContainerVertical.scrollTop;
219
+ }
220
+ this.root.state.options.scroll.scrolling = true;
221
+ },
222
+
223
+ /**
224
+ * Chart mouseup event handler
225
+ * Deactivates drag scrolling mode
226
+ */
227
+ chartMouseUp(ev) {
228
+ this.root.state.options.scroll.scrolling = false;
229
+ },
230
+
231
+ /**
232
+ * Chart mousemove event handler
233
+ * When in drag scrolling mode this method calculate scroll movement
234
+ */
235
+ chartMouseMove(ev) {
236
+ if (this.root.state.options.scroll.scrolling) {
237
+ ev.preventDefault();
238
+ ev.stopImmediatePropagation();
239
+ ev.stopPropagation();
240
+ const touch = typeof ev.touches !== 'undefined';
241
+ let movementX, movementY;
242
+ if (touch) {
243
+ const screenX = ev.touches[0].screenX;
244
+ const screenY = ev.touches[0].screenY;
245
+ movementX = this.mousePos.x - screenX;
246
+ movementY = this.mousePos.y - screenY;
247
+ this.mousePos.lastX = screenX;
248
+ this.mousePos.lastY = screenY;
249
+ } else {
250
+ movementX = ev.movementX;
251
+ movementY = ev.movementY;
252
+ }
253
+ const horizontal = this.$refs.chartScrollContainerHorizontal;
254
+ const vertical = this.$refs.chartScrollContainerVertical;
255
+ let x = 0,
256
+ y = 0;
257
+ if (touch) {
258
+ x = this.mousePos.currentX + movementX * this.root.state.options.scroll.dragXMoveMultiplier;
259
+ } else {
260
+ x = horizontal.scrollLeft - movementX * this.root.state.options.scroll.dragXMoveMultiplier;
261
+ }
262
+ horizontal.scrollLeft = x;
263
+ if (touch) {
264
+ y = this.mousePos.currentY + movementY * this.root.state.options.scroll.dragYMoveMultiplier;
265
+ } else {
266
+ y = vertical.scrollTop - movementY * this.root.state.options.scroll.dragYMoveMultiplier;
267
+ }
268
+ vertical.scrollTop = y;
269
+ }
270
+ }
271
+ },
272
+
273
+ /**
274
+ * Before destroy event - clean up
275
+ */
276
+ // beforeDestroy() {
277
+ // document.removeEventListener('mouseup', this.chartMouseUp);
278
+ // document.removeEventListener('mousemove', this.chartMouseMove);
279
+ // document.removeEventListener('touchmove', this.chartMouseMove);
280
+ // document.removeEventListener('touchend', this.chartMouseUp);
281
+ // }
282
+ };
283
+ </script>