@progress/kendo-angular-gantt 0.3.0-dev.202201131518 → 0.3.0-dev.202201190830

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 (82) hide show
  1. package/dist/cdn/js/kendo-angular-gantt.js +2 -2
  2. package/dist/cdn/main.js +2 -2
  3. package/dist/es/editing/edit-dialog.component.js +3 -3
  4. package/dist/es/editing/edit.service.js +4 -2
  5. package/dist/es/gantt.component.js +191 -24
  6. package/dist/es/index.js +1 -0
  7. package/dist/es/models/events/task-delete-event.interface.js +4 -0
  8. package/dist/es/navigation/navigation-models.js +4 -0
  9. package/dist/es/navigation/navigation.service.js +390 -0
  10. package/dist/es/navigation/utils.js +77 -0
  11. package/dist/es/package-metadata.js +1 -1
  12. package/dist/es/rendering/gantt-milestone-task.component.js +7 -4
  13. package/dist/es/rendering/gantt-summary-task.component.js +22 -4
  14. package/dist/es/rendering/gantt-task-base.js +57 -6
  15. package/dist/es/rendering/gantt-task.component.js +9 -6
  16. package/dist/es/rendering/gantt-tasks-table-body.component.js +9 -5
  17. package/dist/es/timeline/gantt-timeline.component.js +10 -6
  18. package/dist/es/toolbar/toolbar.component.js +12 -13
  19. package/dist/es/toolbar/view-selector.component.js +1 -1
  20. package/dist/es/utils.js +14 -4
  21. package/dist/es2015/editing/edit-dialog.component.d.ts +1 -1
  22. package/dist/es2015/editing/edit-dialog.component.js +11 -3
  23. package/dist/es2015/editing/edit.service.d.ts +2 -3
  24. package/dist/es2015/editing/edit.service.js +4 -2
  25. package/dist/es2015/editing/utils.d.ts +2 -2
  26. package/dist/es2015/gantt.component.d.ts +75 -16
  27. package/dist/es2015/gantt.component.js +177 -26
  28. package/dist/es2015/index.d.ts +1 -0
  29. package/dist/es2015/index.js +1 -0
  30. package/dist/es2015/index.metadata.json +1 -1
  31. package/dist/es2015/models/events/task-click-event.interface.d.ts +3 -3
  32. package/dist/es2015/models/events/task-delete-event.interface.d.ts +21 -0
  33. package/dist/es2015/models/events/task-delete-event.interface.js +4 -0
  34. package/dist/es2015/models/events/task-edit-event.interface.d.ts +27 -10
  35. package/dist/es2015/models/models.d.ts +2 -0
  36. package/dist/es2015/navigation/navigation-models.d.ts +34 -0
  37. package/dist/es2015/navigation/navigation-models.js +4 -0
  38. package/dist/es2015/navigation/navigation.service.d.ts +126 -0
  39. package/dist/es2015/navigation/navigation.service.js +355 -0
  40. package/dist/es2015/navigation/utils.d.ts +26 -0
  41. package/dist/es2015/navigation/utils.js +69 -0
  42. package/dist/es2015/package-metadata.js +1 -1
  43. package/dist/es2015/rendering/gantt-milestone-task.component.d.ts +2 -1
  44. package/dist/es2015/rendering/gantt-milestone-task.component.js +18 -4
  45. package/dist/es2015/rendering/gantt-summary-task.component.d.ts +4 -1
  46. package/dist/es2015/rendering/gantt-summary-task.component.js +30 -4
  47. package/dist/es2015/rendering/gantt-task-base.d.ts +10 -2
  48. package/dist/es2015/rendering/gantt-task-base.js +48 -6
  49. package/dist/es2015/rendering/gantt-task.component.d.ts +3 -2
  50. package/dist/es2015/rendering/gantt-task.component.js +31 -9
  51. package/dist/es2015/rendering/gantt-tasks-table-body.component.d.ts +5 -3
  52. package/dist/es2015/rendering/gantt-tasks-table-body.component.js +23 -12
  53. package/dist/es2015/scrolling/scroll-sync.service.d.ts +1 -1
  54. package/dist/es2015/timeline/gantt-timeline.component.d.ts +5 -3
  55. package/dist/es2015/timeline/gantt-timeline.component.js +15 -6
  56. package/dist/es2015/toolbar/toolbar.component.d.ts +4 -5
  57. package/dist/es2015/toolbar/toolbar.component.js +12 -13
  58. package/dist/es2015/toolbar/view-selector.component.js +3 -1
  59. package/dist/es2015/utils.d.ts +10 -3
  60. package/dist/es2015/utils.js +14 -4
  61. package/dist/fesm2015/index.js +2311 -1610
  62. package/dist/fesm5/index.js +1722 -1013
  63. package/dist/npm/editing/edit-dialog.component.js +3 -3
  64. package/dist/npm/editing/edit.service.js +4 -2
  65. package/dist/npm/gantt.component.js +191 -24
  66. package/dist/npm/index.js +2 -0
  67. package/dist/npm/models/events/task-delete-event.interface.js +6 -0
  68. package/dist/npm/navigation/navigation-models.js +6 -0
  69. package/dist/npm/navigation/navigation.service.js +392 -0
  70. package/dist/npm/navigation/utils.js +79 -0
  71. package/dist/npm/package-metadata.js +1 -1
  72. package/dist/npm/rendering/gantt-milestone-task.component.js +7 -4
  73. package/dist/npm/rendering/gantt-summary-task.component.js +22 -4
  74. package/dist/npm/rendering/gantt-task-base.js +57 -6
  75. package/dist/npm/rendering/gantt-task.component.js +9 -6
  76. package/dist/npm/rendering/gantt-tasks-table-body.component.js +9 -5
  77. package/dist/npm/timeline/gantt-timeline.component.js +10 -6
  78. package/dist/npm/toolbar/toolbar.component.js +10 -11
  79. package/dist/npm/toolbar/view-selector.component.js +1 -1
  80. package/dist/npm/utils.js +14 -4
  81. package/dist/systemjs/kendo-angular-gantt.js +1 -1
  82. package/package.json +1 -1
@@ -3,17 +3,17 @@
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
5
  import { __decorate, __metadata, __param } from 'tslib';
6
- import { Input, EventEmitter, Injectable, Directive, Optional, TemplateRef, QueryList, ContentChildren, ContentChild, Component, forwardRef, SkipSelf, Host, Injector, NgZone, ViewChild, ElementRef, ViewContainerRef, HostBinding, Output, Renderer2, isDevMode, InjectionToken, Inject, ChangeDetectorRef, NgModule } from '@angular/core';
6
+ import { Injectable, NgZone, EventEmitter, ViewChild, ElementRef, ViewContainerRef, HostBinding, Input, TemplateRef, Output, Component, Renderer2, Directive, Optional, QueryList, ContentChildren, ContentChild, forwardRef, SkipSelf, Host, Injector, isDevMode, InjectionToken, Inject, ChangeDetectorRef, NgModule } from '@angular/core';
7
7
  import { ColumnBase, ColumnComponent, ColumnGroupComponent, SpanColumnComponent, TreeListComponent, DataBoundTreeComponent, ExpandableTreeComponent, FlatBindingDirective, HierarchyBindingDirective, ExpandableDirective, TreeListModule } from '@progress/kendo-angular-treelist';
8
8
  import { cloneDate, addWeeks, firstDayInWeek, addDays, getDate, lastDayOfMonth, firstDayOfMonth, addMonths, isEqual, MS_PER_HOUR, MS_PER_DAY } from '@progress/kendo-date-math';
9
- import { of, Subject, Subscription, fromEvent, forkJoin, EMPTY, isObservable } from 'rxjs';
9
+ import { Subject, Subscription, fromEvent, of, forkJoin, EMPTY, isObservable } from 'rxjs';
10
10
  import { validatePackage } from '@progress/kendo-licensing';
11
- import { closestInScope, matchesClasses, isDocumentAvailable, anyChanged, hasObservers, EventsModule, DraggableModule } from '@progress/kendo-angular-common';
11
+ import { closestInScope, matchesClasses, isDocumentAvailable, Keys, hasObservers, anyChanged, EventsModule, DraggableModule } from '@progress/kendo-angular-common';
12
+ import { map, distinctUntilChanged, take, filter, switchMap, expand, reduce } from 'rxjs/operators';
13
+ import { getter, touchEnabled } from '@progress/kendo-common';
12
14
  import { LocalizationService, ComponentMessages, L10N_PREFIX } from '@progress/kendo-angular-l10n';
13
15
  import { IntlService } from '@progress/kendo-angular-intl';
14
16
  import { orderBy } from '@progress/kendo-data-query';
15
- import { getter, touchEnabled } from '@progress/kendo-common';
16
- import { map, distinctUntilChanged, take, expand, reduce, filter, switchMap } from 'rxjs/operators';
17
17
  import { CommonModule } from '@angular/common';
18
18
  import { FormArray, FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
19
19
  import { SplitterModule, TabStripModule } from '@progress/kendo-angular-layout';
@@ -33,926 +33,1407 @@ const packageMetadata = {
33
33
  name: '@progress/kendo-angular-gantt',
34
34
  productName: 'Kendo UI for Angular',
35
35
  productCodes: ['KENDOUIANGULAR', 'KENDOUICOMPLETE'],
36
- publishDate: 1642086647,
36
+ publishDate: 1642580546,
37
37
  version: '',
38
38
  licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/?utm_medium=product&utm_source=kendoangular&utm_campaign=kendo-ui-angular-purchase-license-keys-warning'
39
39
  };
40
40
 
41
- /**
42
- * The base class for the column components of the Gantt.
43
- */
44
- class GanttColumnBase extends ColumnBase {
45
- constructor() {
46
- super(...arguments);
47
- /**
48
- * Toggles the locked (frozen) state of the columns.
49
- *
50
- * @default false
51
- * @hidden
52
- */
53
- this.locked = false;
54
- }
55
- }
56
- __decorate([
57
- Input(),
58
- __metadata("design:type", Boolean)
59
- ], GanttColumnBase.prototype, "locked", void 0);
60
- __decorate([
61
- Input(),
62
- __metadata("design:type", Boolean)
63
- ], GanttColumnBase.prototype, "lockable", void 0);
64
- __decorate([
65
- Input(),
66
- __metadata("design:type", Boolean)
67
- ], GanttColumnBase.prototype, "hidden", void 0);
68
- __decorate([
69
- Input(),
70
- __metadata("design:type", String)
71
- ], GanttColumnBase.prototype, "media", void 0);
72
- __decorate([
73
- Input(),
74
- __metadata("design:type", Object)
75
- ], GanttColumnBase.prototype, "style", void 0);
76
- __decorate([
77
- Input(),
78
- __metadata("design:type", Object)
79
- ], GanttColumnBase.prototype, "headerStyle", void 0);
80
- __decorate([
81
- Input(),
82
- __metadata("design:type", Object)
83
- ], GanttColumnBase.prototype, "footerStyle", void 0);
84
- __decorate([
85
- Input('class'),
86
- __metadata("design:type", Object)
87
- ], GanttColumnBase.prototype, "cssClass", void 0);
88
- __decorate([
89
- Input(),
90
- __metadata("design:type", Object)
91
- ], GanttColumnBase.prototype, "headerClass", void 0);
92
- __decorate([
93
- Input(),
94
- __metadata("design:type", Object)
95
- ], GanttColumnBase.prototype, "footerClass", void 0);
96
-
97
41
  /**
98
42
  * @hidden
99
43
  */
100
- let OptionChangesService = class OptionChangesService {
101
- /**
102
- * @hidden
103
- */
104
- constructor() {
105
- this.viewChanges = new EventEmitter();
106
- this.columnChanges = new EventEmitter();
44
+ let ScrollSyncService = class ScrollSyncService {
45
+ constructor(ngZone) {
46
+ this.ngZone = ngZone;
47
+ this.changes = new Subject();
48
+ this.elements = [];
49
+ this.subscriptions = new Subscription();
50
+ this.subscriptions.add(this.changes.subscribe(args => {
51
+ this.scroll(args);
52
+ }));
107
53
  }
108
- notifyColumnChanges() {
109
- this.columnChanges.emit();
54
+ registerElement(el, sourceType) {
55
+ this.elements.push({ element: el, sourceType });
56
+ if (sourceType === "timeline" || sourceType === "treelist") {
57
+ this.ngZone.runOutsideAngular(() => {
58
+ const obs = fromEvent(el, 'scroll').pipe(map(({ target: { scrollTop, scrollLeft } }) => ({
59
+ scrollTop,
60
+ scrollLeft,
61
+ sourceType
62
+ })));
63
+ const comparisonFn = sourceType === 'timeline' ?
64
+ (x, y) => (x.scrollTop === y.scrollTop) && (x.scrollLeft === y.scrollLeft) :
65
+ (x, y) => (x.scrollTop === y.scrollTop);
66
+ this.subscriptions.add(obs.pipe(distinctUntilChanged(comparisonFn))
67
+ .subscribe((event) => this.changes.next(event)));
68
+ });
69
+ }
110
70
  }
111
- notifyViewChanges() {
112
- this.viewChanges.emit();
71
+ ngOnDestroy() {
72
+ this.subscriptions.unsubscribe();
73
+ this.elements = null;
74
+ }
75
+ syncScrollTop(sourceType, targetType) {
76
+ const source = this.elements.find(element => element.sourceType === sourceType);
77
+ const target = this.elements.find(element => element.sourceType === targetType);
78
+ // Need to wait for the splitter pane's content to be rendered
79
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => target.element.scrollTop = source.element.scrollTop);
80
+ }
81
+ resetTimelineScrollLeft() {
82
+ const source = this.elements.find(element => element.sourceType === 'timeline');
83
+ source.element.scrollLeft = 0;
84
+ }
85
+ scroll({ scrollTop, scrollLeft, sourceType }) {
86
+ this.ngZone.runOutsideAngular(() => {
87
+ if (sourceType === 'timeline') {
88
+ const header = this.elements.find(element => element.sourceType === 'header').element;
89
+ header.scrollLeft = scrollLeft;
90
+ if (!this.syncingTimeline) {
91
+ this.syncingTreeList = true;
92
+ const treelist = this.elements.find(element => element.sourceType === 'treelist').element;
93
+ treelist.scrollTop = scrollTop;
94
+ }
95
+ this.syncingTimeline = false;
96
+ }
97
+ if (sourceType === 'treelist') {
98
+ if (!this.syncingTreeList) {
99
+ this.syncingTimeline = true;
100
+ const timeline = this.elements.find(element => element.sourceType === 'timeline').element;
101
+ timeline.scrollTop = scrollTop;
102
+ }
103
+ this.syncingTreeList = false;
104
+ }
105
+ });
113
106
  }
114
107
  };
115
- OptionChangesService = __decorate([
116
- Injectable()
117
- ], OptionChangesService);
108
+ ScrollSyncService = __decorate([
109
+ Injectable(),
110
+ __metadata("design:paramtypes", [NgZone])
111
+ ], ScrollSyncService);
118
112
 
119
113
  /**
120
- * Represents the column cell template of the Gantt.
121
- * Helps to customize the content of the cells. To define the cell template, nest an `<ng-template>` tag
122
- * with the `kendoGanttCellTemplate` directive inside the respective column tag.
123
- *
124
- * The template context is set to the current data item and the following additional fields are passed:
125
- * - `dataItem`&mdash;The current data item. Represents the default context that will be assigned to any template variable which utilizes the `let-x` syntax&mdash;for example, `let-dataItem`.
126
- * - `columnIndex`&mdash;The current column index. Use it as an alias for a template variable by utilizing the `let-columnIndex="columnIndex"` syntax.
127
- * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
128
- * - `cellContext`&mdash;An object used to pass context information to built-in directives.
129
- * - `hasChildren`&mdash;Specifies if the item has children.
130
- * - `isExpanded`&mdash;Specifies if the item is expanded.
131
- * - `level`&mdash;The hierarchy level of the item.
132
- * - `loading`&mdash;Specifies if the item children are currently loading.
133
- * - `rowIndex`&mdash;The current row index. Use it as an alias for a template variable by utilizing the `let-rowIndex="rowIndex"` syntax.
114
+ * @hidden
134
115
  */
135
- let CellTemplateDirective = class CellTemplateDirective {
136
- constructor(templateRef) {
137
- this.templateRef = templateRef;
138
- }
139
- };
140
- CellTemplateDirective = __decorate([
141
- Directive({
142
- selector: '[kendoGanttCellTemplate]'
143
- }),
144
- __param(0, Optional()),
145
- __metadata("design:paramtypes", [TemplateRef])
146
- ], CellTemplateDirective);
116
+ const DEFAULT_DEPENDENCY_MODEL_FIELDS = Object.freeze({
117
+ toId: 'toId',
118
+ fromId: 'fromId',
119
+ id: 'id',
120
+ type: 'type'
121
+ });
147
122
 
148
123
  /**
149
- * Represents the template for the column menu in the Gantt. Provides an option for
150
- * customizing the content of the column menu for all or for specific columns.
151
- * To define the content template, nest an `<ng-template>` tag with the
152
- * `kendoGanttColumnMenuTemplate` directive inside the `<kendo-gantt-column>` component.
124
+ * @hidden
125
+ */
126
+ const DEFAULT_TASK_MODEL_FIELDS = Object.freeze({
127
+ id: 'id',
128
+ start: 'start',
129
+ end: 'end',
130
+ title: 'title',
131
+ completionRatio: 'completionRatio',
132
+ children: 'children'
133
+ });
134
+
135
+ /**
136
+ * The dependency type when two tasks are connected.
153
137
  *
154
- * The column menu service and the current column are available as context variables:
155
- * - `service`&mdash;Represents the ColumnMenuService.
156
- * - `column`&mdash;Represents the Gantt column.
138
+ * The supported values are:
139
+ * * `FF`&mdash;from 'finish' to 'finish'
140
+ * * `FS`&mdash;from 'finish' to 'start'
141
+ * * `SS`&mdash;from 'start' to 'start'
142
+ * * `SF`&mdash;from 'start' to 'finish'
157
143
  */
158
- let ColumnMenuTemplateDirective = class ColumnMenuTemplateDirective {
159
- constructor(templateRef) {
160
- this.templateRef = templateRef;
161
- }
162
- };
163
- ColumnMenuTemplateDirective = __decorate([
164
- Directive({
165
- selector: '[kendoGanttColumnMenuTemplate]'
166
- }),
167
- __param(0, Optional()),
168
- __metadata("design:paramtypes", [TemplateRef])
169
- ], ColumnMenuTemplateDirective);
144
+ var DependencyType;
145
+ (function (DependencyType) {
146
+ DependencyType[DependencyType["FF"] = 0] = "FF";
147
+ DependencyType[DependencyType["FS"] = 1] = "FS";
148
+ DependencyType[DependencyType["SF"] = 2] = "SF";
149
+ DependencyType[DependencyType["SS"] = 3] = "SS"; // task B can't start before task A starts
150
+ })(DependencyType || (DependencyType = {}));
170
151
 
171
152
  /**
172
153
  * @hidden
173
- * Represents the filter-cell template.
174
- *
175
- * The template context is set to the filter descriptor and the following additional fields are passed:
176
- * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
177
- * - `filter`&mdash;The filter descriptor.
178
- * - `cellContext`&mdash;An object used to pass context information to built-in directives.
179
154
  */
180
- let FilterCellTemplateDirective = class FilterCellTemplateDirective {
181
- constructor(templateRef) {
182
- this.templateRef = templateRef;
183
- }
155
+ const isWorkDay = (date, start, end) => {
156
+ return date.getDay() >= start && date.getDay() <= end;
184
157
  };
185
- FilterCellTemplateDirective = __decorate([
186
- Directive({
187
- selector: '[kendoGanttFilterCellTemplate]'
188
- }),
189
- __param(0, Optional()),
190
- __metadata("design:paramtypes", [TemplateRef])
191
- ], FilterCellTemplateDirective);
192
-
193
158
  /**
194
- * Represents the filter-menu template.
195
- *
196
- * The column, current filter and the filter service are available as context variables:
197
- * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
198
- * - `filter`&mdash;The filter descriptor.
199
- * - `cellContext`&mdash;An object used to pass context information to built-in directives.
159
+ * @hidden
200
160
  */
201
- let FilterMenuTemplateDirective = class FilterMenuTemplateDirective {
202
- constructor(templateRef) {
203
- this.templateRef = templateRef;
204
- }
161
+ const isWorkHour = (date, start, end) => {
162
+ return date.getHours() >= start && date.getHours() <= end;
205
163
  };
206
- FilterMenuTemplateDirective = __decorate([
207
- Directive({
208
- selector: '[kendoGanttFilterMenuTemplate]'
209
- }),
210
- __param(0, Optional()),
211
- __metadata("design:paramtypes", [TemplateRef])
212
- ], FilterMenuTemplateDirective);
213
-
214
164
  /**
215
- * Represents the column footer cell template of the Gantt.
216
- *
217
- * Helps to customize the table footer cell for the column.
218
- * To define a footer template, nest an `<ng-template>` tag with the
219
- * [`kendoGanttFooterTemplate`]({% slug api_gantt_footertemplatedirective %}) directive inside the `<kendo-gantt-column>` tag.
165
+ * @hidden
166
+ */
167
+ const isPresent = (item) => item !== null && item !== undefined;
168
+ /**
169
+ * @hidden
220
170
  *
221
- * The current column, column index and field are available as context variables:
222
- * * `column`&mdash;Points to the instance of the current [`ColumnComponent`]({% slug api_gantt_ganttcolumncomponent %}).
223
- * * `columnIndex`&mdash;Defines the current column index.
224
- * * `field`&mdash;The name of the column field, if set.
171
+ * Normalized the data to an array in case a falsy value is passed
172
+ * or a TreeListDataResult object (applicable for the data-binding directives).
225
173
  */
226
- let FooterTemplateDirective = class FooterTemplateDirective {
227
- constructor(templateRef) {
228
- this.templateRef = templateRef;
174
+ const normalizeGanttData = (data) => {
175
+ if (!isPresent(data)) {
176
+ return [];
177
+ }
178
+ else if (Array.isArray(data.data)) {
179
+ return data.data;
180
+ }
181
+ else {
182
+ return data;
229
183
  }
230
184
  };
231
- FooterTemplateDirective = __decorate([
232
- Directive({
233
- selector: '[kendoGanttFooterTemplate]'
234
- }),
235
- __param(0, Optional()),
236
- __metadata("design:paramtypes", [TemplateRef])
237
- ], FooterTemplateDirective);
238
-
239
185
  /**
240
- * Represents the column header cell template of the Gantt.
241
- * Helps to customize the table header cell for the column.
242
- * To define a header template, nest an `<ng-template>` tag with the
243
- * [`kendoGanttHeaderTemplate`]({% slug api_gantt_headertemplatedirective %}) directive inside the `<kendo-gantt-column>` tag.
186
+ * @hidden
244
187
  *
245
- * The current column and column index are available as context variables:
246
- * * `column`&mdash;Points to the instance of the current [`ColumnComponent`]({% slug api_gantt_ganttcolumncomponent %}).
247
- * * `columnIndex`&mdash;Defines the current column index.
188
+ * Returns a new date with the specified hours, minutes, seconds and millliseconds set.
189
+ * Only the hours are required, the rest of the params are set to `0` by default.
248
190
  */
249
- let HeaderTemplateDirective = class HeaderTemplateDirective {
250
- constructor(templateRef) {
251
- this.templateRef = templateRef;
191
+ const setTime = (date, hours, minutes = 0, seconds = 0, milliseconds = 0) => {
192
+ if (!isPresent(date)) {
193
+ return null;
252
194
  }
195
+ const result = cloneDate(date);
196
+ result.setHours(hours);
197
+ result.setMinutes(minutes);
198
+ result.setSeconds(seconds);
199
+ result.setMilliseconds(milliseconds);
200
+ return result;
253
201
  };
254
- HeaderTemplateDirective = __decorate([
255
- Directive({
256
- selector: '[kendoGanttHeaderTemplate]'
257
- }),
258
- __param(0, Optional()),
259
- __metadata("design:paramtypes", [TemplateRef])
260
- ], HeaderTemplateDirective);
261
-
262
202
  /**
263
- * Represents the column edit-cell template of the Gantt.
264
- * Helps to customize the content of the edited cells. To define the cell template, nest an `<ng-template>`
265
- * tag with the `kendoGanttEditTemplate` directive inside a `<kendo-gantt-column>` tag.
203
+ * @hidden
266
204
  *
267
- * The template context contains the following fields:
268
- * - `column`&mdash;The current column instance.
269
- * - `dataItem`&mdash;The current data item.
270
- * - `cellContext`&mdash;An object used to pass context information to built-in directives.
271
- * - `formGroup`&mdash;The current [`FormGroup`]({{ site.data.urls.angular['formgroupapi'] }}).
272
- * If you use the Gantt inside [Template-Driven Forms]({{ site.data.urls.angular['forms'] }}), it will be `undefined`.
273
- * - `isNew`&mdash;The state of the current item.
274
- * - `rowIndex`&mdash;The current row index. If inside a new item row, `rowIndex` is `-1`.
205
+ * Returns the last day of a week.
206
+ * @param standingPoint - Any day of the target week.
207
+ * @param firstWeekDay - The week's starting day (e.g. Monday, Tuesday, etc.)
275
208
  */
276
- let EditTemplateDirective = class EditTemplateDirective {
277
- constructor(templateRef) {
278
- this.templateRef = templateRef;
209
+ const lastDayOfWeek = (standingPoint, firstWeekDay) => {
210
+ const followingWeek = addWeeks(standingPoint, 1);
211
+ const firstDayOfFollowingWeek = firstDayInWeek(followingWeek, firstWeekDay);
212
+ const lastDayOfTargetWeek = addDays(firstDayOfFollowingWeek, -1);
213
+ return lastDayOfTargetWeek;
214
+ };
215
+ /**
216
+ * Persists the intially resolved scrollbar width value.
217
+ */
218
+ let SCROLLBAR_WIDTH;
219
+ /**
220
+ * @hidden
221
+ *
222
+ * Gets the default scrollbar width accoring to the current environment.
223
+ */
224
+ const scrollbarWidth = () => {
225
+ if (!isDocumentAvailable()) {
226
+ return;
227
+ }
228
+ // calculate scrollbar width only once, then return the cached value
229
+ if (isNaN(SCROLLBAR_WIDTH)) {
230
+ const div = document.createElement('div');
231
+ div.style.cssText = 'overflow: scroll; overflow-x: hidden; zoom: 1; clear: both; display: block;';
232
+ div.innerHTML = '&nbsp;';
233
+ document.body.appendChild(div);
234
+ SCROLLBAR_WIDTH = div.offsetWidth - div.scrollWidth;
235
+ document.body.removeChild(div);
279
236
  }
237
+ return SCROLLBAR_WIDTH;
280
238
  };
281
- EditTemplateDirective = __decorate([
282
- Directive({
283
- selector: '[kendoGanttEditTemplate]'
284
- }),
285
- __param(0, Optional()),
286
- __metadata("design:paramtypes", [TemplateRef])
287
- ], EditTemplateDirective);
288
-
289
- var GanttColumnComponent_1;
290
- let GanttColumnComponent = GanttColumnComponent_1 = class GanttColumnComponent extends ColumnComponent {
291
- constructor(options, parent) {
292
- super(parent);
293
- this.options = options;
294
- this.headerTemplates = new QueryList();
295
- this.columnMenuTemplates = new QueryList();
296
- /**
297
- * Defines the filter type that is displayed inside the filter row. The default value is `text`.
298
- */
299
- this.filter = 'text';
300
- /**
301
- * Defines if a filter UI will be displayed for this column. The default value is `true`.
302
- */
303
- this.filterable = true;
304
- /**
305
- * @hidden
306
- *
307
- * Defines the editor type.
308
- * Used when the column enters the edit mode. The default value is `text`.
309
- */
310
- this.editor = 'text';
311
- /**
312
- * @hidden
313
- *
314
- * Defines whether the column is editable. The default value is `true`.
315
- */
316
- this.editable = true;
317
- /**
318
- * Toggles the locked (frozen) state of the columns.
319
- * @hidden
320
- * @default false
321
- */
322
- this.locked = false;
239
+ /**
240
+ * @hidden
241
+ */
242
+ const isColumnGroup = (column) => column.isColumnGroup;
243
+ /**
244
+ * @hidden
245
+ */
246
+ const isNumber = (contender) => typeof contender === 'number' && !isNaN(contender);
247
+ /**
248
+ * @hidden
249
+ */
250
+ const isString = (contender) => typeof contender === 'string';
251
+ /**
252
+ * @hidden
253
+ *
254
+ * Gets the closest timeline task wrapper element from an event target.
255
+ * Restricts the search up to the provided parent element from the second param.
256
+ */
257
+ const getClosestTaskWrapper = (element, parentScope) => {
258
+ return closestInScope(element, matchesClasses('k-task-wrap'), parentScope);
259
+ };
260
+ /**
261
+ * @hidden
262
+ *
263
+ * Checks whether the queried item or its parent items has a `k-task-wrap` selector.
264
+ * Restricts the search up to the provided parent element from the second param.
265
+ */
266
+ const isTaskWrapper = (contender, parentScope) => {
267
+ const taskWrapper = closestInScope(contender, matchesClasses('k-task-wrap'), parentScope);
268
+ return isPresent(taskWrapper);
269
+ };
270
+ /**
271
+ * @hidden
272
+ *
273
+ * Gets the closest timeline task element index from an event target.
274
+ * Uses the `data-task-index` attribute assigned to each task.
275
+ * Restricts the search up to the provided parent element from the second param.
276
+ */
277
+ const getClosestTaskIndex = (element, parentScope) => {
278
+ const task = closestInScope(element, matchesClasses('k-task-wrap'), parentScope);
279
+ if (!isPresent(task)) {
280
+ return null;
323
281
  }
324
- ngOnChanges() {
325
- this.options.notifyColumnChanges();
282
+ return Number(task.getAttribute('data-task-index'));
283
+ };
284
+ /**
285
+ * @hidden
286
+ *
287
+ * Checks whether the queried item or its parent items has a `k-task` selector.
288
+ * Restricts the search up to the provided parent element from the second param.
289
+ */
290
+ const isTask = (contender, parentScope) => {
291
+ const task = closestInScope(contender, matchesClasses('k-task'), parentScope);
292
+ return isPresent(task);
293
+ };
294
+ /**
295
+ * @hidden
296
+ *
297
+ * Checks whether the queried item or its parent items has a `k-toolbar` selector.
298
+ * Restricts the search up to the provided parent element from the second param.
299
+ */
300
+ const isToolbar = (contender, parentScope) => {
301
+ const toolbar = closestInScope(contender, matchesClasses('k-gantt-toolbar'), parentScope);
302
+ return isPresent(toolbar);
303
+ };
304
+ /**
305
+ * @hidden
306
+ *
307
+ * Checks whether the queried item or its parent items has a `k-task-actions` selector - used for the clear button.
308
+ * Restricts the search up to the provided parent element from the second param.
309
+ */
310
+ const isClearButton = (contender, parentScope) => {
311
+ const clearButtonContainer = closestInScope(contender, matchesClasses('k-task-actions'), parentScope);
312
+ return isPresent(clearButtonContainer);
313
+ };
314
+ /**
315
+ * @hidden
316
+ *
317
+ * Checks whether the queried item has a `k-task-dot` selector - used for the dependency drag clues.
318
+ */
319
+ const isDependencyDragClue = (element) => {
320
+ if (!isPresent(element)) {
321
+ return false;
326
322
  }
323
+ return element.classList.contains('k-task-dot');
327
324
  };
328
- __decorate([
329
- ContentChildren(HeaderTemplateDirective, { descendants: false }),
330
- __metadata("design:type", QueryList)
331
- ], GanttColumnComponent.prototype, "headerTemplates", void 0);
332
- __decorate([
333
- ContentChild(FooterTemplateDirective, { static: false }),
334
- __metadata("design:type", FooterTemplateDirective)
335
- ], GanttColumnComponent.prototype, "footerTemplate", void 0);
336
- __decorate([
337
- ContentChildren(ColumnMenuTemplateDirective),
338
- __metadata("design:type", QueryList)
339
- ], GanttColumnComponent.prototype, "columnMenuTemplates", void 0);
340
- __decorate([
341
- ContentChild(CellTemplateDirective, { static: false }),
342
- __metadata("design:type", CellTemplateDirective)
343
- ], GanttColumnComponent.prototype, "template", void 0);
344
- __decorate([
345
- ContentChild(EditTemplateDirective, { static: false }),
346
- __metadata("design:type", EditTemplateDirective)
347
- ], GanttColumnComponent.prototype, "editTemplate", void 0);
348
- __decorate([
349
- ContentChild(FilterCellTemplateDirective, { static: false }),
350
- __metadata("design:type", FilterCellTemplateDirective)
351
- ], GanttColumnComponent.prototype, "filterCellTemplate", void 0);
352
- __decorate([
353
- ContentChild(FilterMenuTemplateDirective, { static: false }),
354
- __metadata("design:type", FilterMenuTemplateDirective)
355
- ], GanttColumnComponent.prototype, "filterMenuTemplate", void 0);
356
- __decorate([
357
- Input(),
358
- __metadata("design:type", Object)
359
- ], GanttColumnComponent.prototype, "format", void 0);
360
- __decorate([
361
- Input(),
362
- __metadata("design:type", String)
363
- ], GanttColumnComponent.prototype, "filter", void 0);
364
- __decorate([
365
- Input(),
366
- __metadata("design:type", Boolean)
367
- ], GanttColumnComponent.prototype, "filterable", void 0);
368
- __decorate([
369
- Input(),
370
- __metadata("design:type", String)
371
- ], GanttColumnComponent.prototype, "editor", void 0);
372
- __decorate([
373
- Input(),
374
- __metadata("design:type", Boolean)
375
- ], GanttColumnComponent.prototype, "editable", void 0);
376
- __decorate([
377
- Input(),
378
- __metadata("design:type", Boolean)
379
- ], GanttColumnComponent.prototype, "locked", void 0);
380
- __decorate([
381
- Input(),
382
- __metadata("design:type", Boolean)
383
- ], GanttColumnComponent.prototype, "lockable", void 0);
384
- __decorate([
385
- Input(),
386
- __metadata("design:type", Boolean)
387
- ], GanttColumnComponent.prototype, "hidden", void 0);
388
- __decorate([
389
- Input(),
390
- __metadata("design:type", String)
391
- ], GanttColumnComponent.prototype, "media", void 0);
392
- __decorate([
393
- Input(),
394
- __metadata("design:type", Object)
395
- ], GanttColumnComponent.prototype, "style", void 0);
396
- __decorate([
397
- Input(),
398
- __metadata("design:type", Object)
399
- ], GanttColumnComponent.prototype, "headerStyle", void 0);
400
- __decorate([
401
- Input(),
402
- __metadata("design:type", Object)
403
- ], GanttColumnComponent.prototype, "footerStyle", void 0);
404
- __decorate([
405
- Input('class'),
406
- __metadata("design:type", Object)
407
- ], GanttColumnComponent.prototype, "cssClass", void 0);
408
- __decorate([
409
- Input(),
410
- __metadata("design:type", Object)
411
- ], GanttColumnComponent.prototype, "headerClass", void 0);
412
- __decorate([
413
- Input(),
414
- __metadata("design:type", Object)
415
- ], GanttColumnComponent.prototype, "footerClass", void 0);
416
- GanttColumnComponent = GanttColumnComponent_1 = __decorate([
417
- Component({
418
- selector: 'kendo-gantt-column',
419
- template: '',
420
- providers: [
421
- {
422
- provide: GanttColumnBase,
423
- useExisting: forwardRef(() => GanttColumnComponent_1)
424
- }
425
- ]
426
- }),
427
- __param(1, SkipSelf()), __param(1, Host()), __param(1, Optional()),
428
- __metadata("design:paramtypes", [OptionChangesService,
429
- GanttColumnBase])
430
- ], GanttColumnComponent);
431
-
432
- var GanttColumnGroupComponent_1;
433
- let GanttColumnGroupComponent = GanttColumnGroupComponent_1 = class GanttColumnGroupComponent extends ColumnGroupComponent {
434
- constructor(options, parent) {
435
- super(parent);
436
- this.options = options;
437
- /**
438
- * @hidden
439
- */
440
- this.children = new QueryList();
441
- /**
442
- * Toggles the locked (frozen) state of the columns.
443
- *
444
- * @default false
445
- * @hidden
446
- */
447
- this.locked = false;
448
- /**
449
- * Allows the column headers to be clicked and the `sortChange` event emitted.
450
- * You have to handle the `sortChange` event yourself and sort the data.
451
- */
452
- this.sortable = true;
453
- if (parent && parent.isSpanColumn) {
454
- throw new Error('ColumnGroupComponent cannot be nested inside SpanColumnComponent');
455
- }
325
+ /**
326
+ * @hidden
327
+ *
328
+ * Checks whether the queried item has a `k-task-dot` & `k-task-start` selector - used for the dependency drag start clues.
329
+ */
330
+ const isDependencyDragStartClue = (element) => {
331
+ if (!isPresent(element)) {
332
+ return false;
456
333
  }
457
- ngOnChanges() {
458
- this.options.notifyColumnChanges();
334
+ return element.classList.contains('k-task-dot') && element.classList.contains('k-task-start');
335
+ };
336
+ /**
337
+ * @hidden
338
+ *
339
+ * Gets the `DependencyType` for an attempted dependency create from the provided two elements.
340
+ * The two linked drag clue HTML elements are used to extract this data (via their CSS classes).
341
+ */
342
+ const getDependencyTypeFromTargetTasks = (fromTaskClue, toTaskClue) => {
343
+ if (!isDependencyDragClue(fromTaskClue) || !isDependencyDragClue(toTaskClue)) {
344
+ return null;
345
+ }
346
+ const fromTaskType = isDependencyDragStartClue(fromTaskClue) ? 'S' : 'F';
347
+ const toTaskType = isDependencyDragStartClue(toTaskClue) ? 'S' : 'F';
348
+ const dependencyTypeName = `${fromTaskType}${toTaskType}`;
349
+ switch (dependencyTypeName) {
350
+ case 'FF': return DependencyType.FF;
351
+ case 'FS': return DependencyType.FS;
352
+ case 'SF': return DependencyType.SF;
353
+ case 'SS': return DependencyType.SS;
354
+ default: return null;
459
355
  }
460
356
  };
461
- __decorate([
462
- ContentChildren(GanttColumnBase),
463
- __metadata("design:type", QueryList)
464
- ], GanttColumnGroupComponent.prototype, "children", void 0);
465
- __decorate([
466
- ContentChildren(HeaderTemplateDirective),
467
- __metadata("design:type", QueryList)
468
- ], GanttColumnGroupComponent.prototype, "headerTemplates", void 0);
469
- __decorate([
470
- Input(),
471
- __metadata("design:type", Boolean)
472
- ], GanttColumnGroupComponent.prototype, "locked", void 0);
473
- __decorate([
474
- Input(),
475
- __metadata("design:type", Boolean)
476
- ], GanttColumnGroupComponent.prototype, "lockable", void 0);
477
- __decorate([
478
- Input(),
479
- __metadata("design:type", Boolean)
480
- ], GanttColumnGroupComponent.prototype, "hidden", void 0);
481
- __decorate([
482
- Input(),
483
- __metadata("design:type", Object)
484
- ], GanttColumnGroupComponent.prototype, "sortable", void 0);
485
- __decorate([
486
- Input(),
487
- __metadata("design:type", String)
488
- ], GanttColumnGroupComponent.prototype, "media", void 0);
489
- __decorate([
490
- Input(),
491
- __metadata("design:type", Object)
492
- ], GanttColumnGroupComponent.prototype, "style", void 0);
493
- __decorate([
494
- Input(),
495
- __metadata("design:type", Object)
496
- ], GanttColumnGroupComponent.prototype, "headerStyle", void 0);
497
- __decorate([
498
- Input(),
499
- __metadata("design:type", Object)
500
- ], GanttColumnGroupComponent.prototype, "footerStyle", void 0);
501
- __decorate([
502
- Input('class'),
503
- __metadata("design:type", Object)
504
- ], GanttColumnGroupComponent.prototype, "cssClass", void 0);
505
- __decorate([
506
- Input(),
507
- __metadata("design:type", Object)
508
- ], GanttColumnGroupComponent.prototype, "headerClass", void 0);
509
- __decorate([
510
- Input(),
511
- __metadata("design:type", Object)
512
- ], GanttColumnGroupComponent.prototype, "footerClass", void 0);
513
- GanttColumnGroupComponent = GanttColumnGroupComponent_1 = __decorate([
514
- Component({
515
- selector: 'kendo-gantt-column-group',
516
- template: '',
517
- providers: [
518
- {
519
- provide: GanttColumnBase,
520
- useExisting: forwardRef(() => GanttColumnGroupComponent_1)
521
- }
522
- ]
523
- }),
524
- __param(1, SkipSelf()), __param(1, Host()), __param(1, Optional()),
525
- __metadata("design:paramtypes", [OptionChangesService,
526
- GanttColumnBase])
527
- ], GanttColumnGroupComponent);
528
-
529
- var GanttSpanColumnComponent_1;
530
- let GanttSpanColumnComponent = GanttSpanColumnComponent_1 = class GanttSpanColumnComponent extends SpanColumnComponent {
531
- constructor(options, parent) {
532
- super(parent);
533
- this.options = options;
534
- /**
535
- * @hidden
536
- */
537
- this.childColumns = new QueryList();
538
- this.template = new QueryList();
539
- this.editTemplate = new QueryList();
357
+ /**
358
+ * @hidden
359
+ *
360
+ * Checks whether the two provided drag clues belong to the same task element.
361
+ */
362
+ const sameTaskClues = (fromTaskClue, toTaskClue, parentScope) => {
363
+ if (!isPresent(fromTaskClue) || !isPresent(toTaskClue)) {
364
+ return false;
540
365
  }
541
- ngOnChanges() {
542
- this.options.notifyColumnChanges();
366
+ const fromTaskWrapper = getClosestTaskWrapper(fromTaskClue, parentScope);
367
+ const toTaskWrapper = getClosestTaskWrapper(toTaskClue, parentScope);
368
+ return fromTaskWrapper === toTaskWrapper;
369
+ };
370
+ /**
371
+ * @hidden
372
+ *
373
+ * Fits a contender number between a min and max range.
374
+ * If the contender is below the min value, the min value is returned.
375
+ * If the contender is above the max value, the max value is returned.
376
+ */
377
+ const fitToRange = (contender, min, max) => {
378
+ if (!isPresent(contender) || contender < min) {
379
+ return min;
380
+ }
381
+ else if (contender > max) {
382
+ return max;
383
+ }
384
+ else {
385
+ return contender;
543
386
  }
544
387
  };
545
- __decorate([
546
- ContentChildren(GanttColumnComponent),
547
- __metadata("design:type", QueryList)
548
- ], GanttSpanColumnComponent.prototype, "childColumns", void 0);
549
- __decorate([
550
- ContentChildren(CellTemplateDirective, { descendants: false }),
551
- __metadata("design:type", QueryList)
552
- ], GanttSpanColumnComponent.prototype, "template", void 0);
553
- __decorate([
554
- ContentChildren(EditTemplateDirective, { descendants: false }),
555
- __metadata("design:type", QueryList)
556
- ], GanttSpanColumnComponent.prototype, "editTemplate", void 0);
557
- __decorate([
558
- Input(),
559
- __metadata("design:type", Boolean)
560
- ], GanttSpanColumnComponent.prototype, "locked", void 0);
561
- __decorate([
562
- Input(),
563
- __metadata("design:type", Boolean)
564
- ], GanttSpanColumnComponent.prototype, "lockable", void 0);
565
- __decorate([
566
- Input(),
567
- __metadata("design:type", Boolean)
568
- ], GanttSpanColumnComponent.prototype, "editable", void 0);
569
- __decorate([
570
- Input(),
571
- __metadata("design:type", Boolean)
572
- ], GanttSpanColumnComponent.prototype, "hidden", void 0);
573
- __decorate([
574
- Input(),
575
- __metadata("design:type", String)
576
- ], GanttSpanColumnComponent.prototype, "media", void 0);
577
- __decorate([
578
- Input(),
579
- __metadata("design:type", Object)
580
- ], GanttSpanColumnComponent.prototype, "style", void 0);
581
- __decorate([
582
- Input(),
583
- __metadata("design:type", Object)
584
- ], GanttSpanColumnComponent.prototype, "headerStyle", void 0);
585
- __decorate([
586
- Input(),
587
- __metadata("design:type", Object)
588
- ], GanttSpanColumnComponent.prototype, "footerStyle", void 0);
589
- __decorate([
590
- Input('class'),
591
- __metadata("design:type", Object)
592
- ], GanttSpanColumnComponent.prototype, "cssClass", void 0);
593
- __decorate([
594
- Input(),
595
- __metadata("design:type", Object)
596
- ], GanttSpanColumnComponent.prototype, "headerClass", void 0);
597
- __decorate([
598
- Input(),
599
- __metadata("design:type", Object)
600
- ], GanttSpanColumnComponent.prototype, "footerClass", void 0);
601
- GanttSpanColumnComponent = GanttSpanColumnComponent_1 = __decorate([
602
- Component({
603
- selector: 'kendo-gantt-span-column',
604
- template: '',
605
- providers: [
606
- {
607
- provide: GanttColumnBase,
608
- useExisting: forwardRef(() => GanttSpanColumnComponent_1)
609
- }
610
- ]
611
- }),
612
- __param(1, SkipSelf()), __param(1, Host()), __param(1, Optional()),
613
- __metadata("design:paramtypes", [OptionChangesService,
614
- GanttColumnBase])
615
- ], GanttSpanColumnComponent);
616
-
617
- /**
618
- * @hidden
619
- */
620
- const hasChildren = () => false;
621
- /**
622
- * @hidden
623
- */
624
- const fetchChildren = () => of([]);
625
- /**
626
- * @hidden
627
- */
628
- const rowClassCallback = () => null;
629
388
  /**
630
389
  * @hidden
390
+ *
391
+ * Checks whether either of the two provided tasks is a parent of the other.
631
392
  */
632
- const taskClassCallback = () => null;
393
+ const areParentChild = (taskA, taskB) => {
394
+ let parentChildRelationship = false;
395
+ let taskAParent = taskA;
396
+ while (isPresent(taskAParent) && isPresent(taskAParent.data)) {
397
+ if (taskAParent.data === taskB.data) {
398
+ parentChildRelationship = true;
399
+ break;
400
+ }
401
+ taskAParent = taskAParent.parent;
402
+ }
403
+ let taskBParent = taskB;
404
+ while (!parentChildRelationship && isPresent(taskBParent) && isPresent(taskBParent.data)) {
405
+ if (taskBParent.data === taskA.data) {
406
+ parentChildRelationship = true;
407
+ break;
408
+ }
409
+ taskBParent = taskBParent.parent;
410
+ }
411
+ return parentChildRelationship;
412
+ };
633
413
  /**
634
414
  * @hidden
635
- */
636
- const isSelected = () => false;
637
-
638
- /**
639
- * The dependency type when two tasks are connected.
640
415
  *
641
- * The supported values are:
642
- * * `FF`&mdash;from 'finish' to 'finish'
643
- * * `FS`&mdash;from 'finish' to 'start'
644
- * * `SS`&mdash;from 'start' to 'start'
645
- * * `SF`&mdash;from 'start' to 'finish'
416
+ * Extracts an element from the provided client coords.
417
+ * Using the `event.target` is not reliable under mobile devices with the current implementation of the draggable, so use this instead.
646
418
  */
647
- var DependencyType;
648
- (function (DependencyType) {
649
- DependencyType[DependencyType["FF"] = 0] = "FF";
650
- DependencyType[DependencyType["FS"] = 1] = "FS";
651
- DependencyType[DependencyType["SF"] = 2] = "SF";
652
- DependencyType[DependencyType["SS"] = 3] = "SS"; // task B can't start before task A starts
653
- })(DependencyType || (DependencyType = {}));
419
+ const elementFromPoint = (clientX, clientY) => {
420
+ if (!isDocumentAvailable()) {
421
+ return null;
422
+ }
423
+ return document.elementFromPoint(clientX, clientY);
424
+ };
654
425
 
655
426
  /**
656
427
  * @hidden
657
428
  */
658
- class PreventableEvent {
429
+ let MappingService = class MappingService {
430
+ /**
431
+ * @hidden
432
+ */
659
433
  constructor() {
660
- this.prevented = false;
434
+ this._taskFields = Object.assign({}, DEFAULT_TASK_MODEL_FIELDS);
435
+ this._dependencyFields = Object.assign({}, DEFAULT_DEPENDENCY_MODEL_FIELDS);
661
436
  }
662
437
  /**
663
- * Prevents the default action for a specified event.
664
- * In this way, the source component suppresses
665
- * the built-in behavior that follows the event.
438
+ * Gets or sets the model fields for the task data items.
439
+ * Uses the default values for fields which are not specified.
666
440
  */
667
- preventDefault() {
668
- this.prevented = true;
441
+ set taskFields(fields) {
442
+ this._taskFields = Object.assign({}, DEFAULT_TASK_MODEL_FIELDS, fields);
443
+ }
444
+ get taskFields() {
445
+ return this._taskFields;
669
446
  }
670
447
  /**
671
- * Returns `true` if the event was prevented
672
- * by any of its subscribers.
673
- *
674
- * @returns `true` if the default action was prevented.
675
- * Otherwise, returns `false`.
448
+ * Gets or sets the model fields for the depenency data items.
449
+ * Uses the default values for fields which are not specified.
676
450
  */
677
- isDefaultPrevented() {
678
- return this.prevented;
451
+ set dependencyFields(fields) {
452
+ this._dependencyFields = Object.assign({}, DEFAULT_DEPENDENCY_MODEL_FIELDS, fields);
679
453
  }
680
- }
681
-
682
- /**
683
- * Called every time a user leaves an edited cell.
684
- */
685
- class CellCloseEvent extends PreventableEvent {
686
- constructor(options) {
687
- super();
688
- Object.assign(this, options);
454
+ get dependencyFields() {
455
+ return this._dependencyFields;
456
+ }
457
+ /**
458
+ * Retrieves the value for the specified task field.
459
+ * Supports nested fields as well (e.g. 'manager.id').
460
+ */
461
+ extractFromTask(dataItem, field) {
462
+ if (!isPresent(this.taskFields)) {
463
+ return null;
464
+ }
465
+ return getter(this.taskFields[field])(dataItem);
466
+ }
467
+ /**
468
+ * Retrieves the value for the specified dependency field.
469
+ * Supports nested fields as well (e.g. 'manager.id').
470
+ */
471
+ extractFromDependency(dataItem, field) {
472
+ if (!isPresent(this.dependencyFields)) {
473
+ return null;
474
+ }
475
+ return getter(this.dependencyFields[field])(dataItem);
689
476
  }
690
- }
691
-
692
- /**
693
- * @hidden
694
- */
695
- const isWorkDay = (date, start, end) => {
696
- return date.getDay() >= start && date.getDay() <= end;
697
- };
698
- /**
699
- * @hidden
700
- */
701
- const isWorkHour = (date, start, end) => {
702
- return date.getHours() >= start && date.getHours() <= end;
703
477
  };
478
+ MappingService = __decorate([
479
+ Injectable()
480
+ ], MappingService);
481
+
704
482
  /**
705
483
  * @hidden
706
484
  */
707
- const isPresent = (item) => item !== null && item !== undefined;
708
- /**
709
- * @hidden
710
- *
711
- * Normalized the data to an array in case a falsy value is passed
712
- * or a TreeListDataResult object (applicable for the data-binding directives).
713
- */
714
- const normalizeGanttData = (data) => {
715
- if (!isPresent(data)) {
716
- return [];
485
+ let DependencyDomService = class DependencyDomService {
486
+ constructor(mapper) {
487
+ this.mapper = mapper;
488
+ this.notifier = new Subject();
489
+ /**
490
+ * Maps each rendered task to its HTML element.
491
+ * Uses the task ID field value as key.
492
+ */
493
+ this.tasks = new Map();
717
494
  }
718
- else if (Array.isArray(data.data)) {
719
- return data.data;
495
+ /**
496
+ * Emits each time some of the tasks or the view have changed.
497
+ * Fires also on the first change of the table rows and the parent container.
498
+ */
499
+ get taskChanges() {
500
+ return this.notifier.asObservable();
720
501
  }
721
- else {
722
- return data;
502
+ get dependencyDomArgs() {
503
+ return {
504
+ tasks: this.tasks,
505
+ contentContainer: this.contentContainer,
506
+ timelineRow: this.timelineRow
507
+ };
723
508
  }
724
- };
725
- /**
726
- * @hidden
727
- *
728
- * Returns a new date with the specified hours, minutes, seconds and millliseconds set.
729
- * Only the hours are required, the rest of the params are set to `0` by default.
730
- */
731
- const setTime = (date, hours, minutes = 0, seconds = 0, milliseconds = 0) => {
732
- if (!isPresent(date)) {
733
- return null;
509
+ ngOnDestroy() {
510
+ this.tasks.clear();
511
+ this.tasks = null;
512
+ this.contentContainer = null;
734
513
  }
735
- const result = cloneDate(date);
736
- result.setHours(hours);
737
- result.setMinutes(minutes);
738
- result.setSeconds(seconds);
739
- result.setMilliseconds(milliseconds);
740
- return result;
741
- };
742
- /**
743
- * @hidden
744
- *
745
- * Returns the last day of a week.
746
- * @param standingPoint - Any day of the target week.
747
- * @param firstWeekDay - The week's starting day (e.g. Monday, Tuesday, etc.)
748
- */
749
- const lastDayOfWeek = (standingPoint, firstWeekDay) => {
750
- const followingWeek = addWeeks(standingPoint, 1);
751
- const firstDayOfFollowingWeek = firstDayInWeek(followingWeek, firstWeekDay);
752
- const lastDayOfTargetWeek = addDays(firstDayOfFollowingWeek, -1);
753
- return lastDayOfTargetWeek;
754
- };
755
- /**
756
- * Persists the intially resolved scrollbar width value.
757
- */
758
- let SCROLLBAR_WIDTH;
759
- /**
760
- * @hidden
761
- *
762
- * Gets the default scrollbar width accoring to the current environment.
763
- */
764
- const scrollbarWidth = () => {
765
- if (!isDocumentAvailable()) {
766
- return;
767
- }
768
- // calculate scrollbar width only once, then return the cached value
769
- if (isNaN(SCROLLBAR_WIDTH)) {
770
- const div = document.createElement('div');
771
- div.style.cssText = 'overflow: scroll; overflow-x: hidden; zoom: 1; clear: both; display: block;';
772
- div.innerHTML = '&nbsp;';
773
- document.body.appendChild(div);
774
- SCROLLBAR_WIDTH = div.offsetWidth - div.scrollWidth;
775
- document.body.removeChild(div);
776
- }
777
- return SCROLLBAR_WIDTH;
778
- };
779
- /**
780
- * @hidden
781
- */
782
- const isColumnGroup = (column) => column.isColumnGroup;
783
- /**
784
- * @hidden
785
- */
786
- const isNumber = (contender) => typeof contender === 'number' && !isNaN(contender);
787
- /**
788
- * @hidden
789
- */
790
- const isString = (contender) => typeof contender === 'string';
791
- /**
792
- * @hidden
793
- *
794
- * Gets the closest timeline task wrapper element from an event target.
795
- * Restricts the search up to the provided parent element from the second param.
796
- */
797
- const getClosestTaskWrapper = (element, parentScope) => {
798
- return closestInScope(element, matchesClasses('k-task-wrap'), parentScope);
799
- };
800
- /**
801
- * @hidden
802
- *
803
- * Checks whether the queried item or its parent items has a `k-task-wrap` selector.
804
- * Restricts the search up to the provided parent element from the second param.
805
- */
806
- const isTaskWrapper = (contender, parentScope) => {
807
- const taskWrapper = closestInScope(contender, matchesClasses('k-task-wrap'), parentScope);
808
- return isPresent(taskWrapper);
809
- };
810
- /**
811
- * @hidden
812
- *
813
- * Gets the closest timeline task element index from an event target.
814
- * Uses the `data-task-index` attribute assigned to each task.
815
- * Restricts the search up to the provided parent element from the second param.
816
- */
817
- const getClosestTaskIndex = (element, parentScope) => {
818
- const task = closestInScope(element, matchesClasses('k-task-wrap'), parentScope);
819
- if (!isPresent(task)) {
820
- return null;
821
- }
822
- return Number(task.getAttribute('data-task-index'));
823
- };
824
- /**
825
- * @hidden
826
- *
827
- * Checks whether the queried item or its parent items has a `k-task` selector.
828
- * Restricts the search up to the provided parent element from the second param.
829
- */
830
- const isTask = (contender, parentScope) => {
831
- const task = closestInScope(contender, matchesClasses('k-task'), parentScope);
832
- return isPresent(task);
833
- };
834
- /**
835
- * @hidden
836
- *
837
- * Checks whether the queried item or its parent items has a `k-task-actions` selector - used for the clear button.
838
- * Restricts the search up to the provided parent element from the second param.
839
- */
840
- const isClearButton = (contender, parentScope) => {
841
- const clearButtonContainer = closestInScope(contender, matchesClasses('k-task-actions'), parentScope);
842
- return isPresent(clearButtonContainer);
843
- };
844
- /**
845
- * @hidden
846
- *
847
- * Checks whether the queried item has a `k-task-dot` selector - used for the dependency drag clues.
848
- */
849
- const isDependencyDragClue = (element) => {
850
- if (!isPresent(element)) {
851
- return false;
514
+ registerTimelineRow(timelineRow) {
515
+ this.timelineRow = timelineRow;
516
+ this.notifyChanges();
852
517
  }
853
- return element.classList.contains('k-task-dot');
854
- };
855
- /**
856
- * @hidden
857
- *
858
- * Checks whether the queried item has a `k-task-dot` & `k-task-start` selector - used for the dependency drag start clues.
859
- */
860
- const isDependencyDragStartClue = (element) => {
861
- if (!isPresent(element)) {
862
- return false;
518
+ registerContentContainer(contentContainer) {
519
+ this.contentContainer = contentContainer;
520
+ this.notifyChanges();
863
521
  }
864
- return element.classList.contains('k-task-dot') && element.classList.contains('k-task-start');
865
- };
866
- /**
867
- * @hidden
868
- *
869
- * Gets the `DependencyType` for an attempted dependency create from the provided two elements.
870
- * The two linked drag clue HTML elements are used to extract this data (via their CSS classes).
871
- */
872
- const getDependencyTypeFromTargetTasks = (fromTaskClue, toTaskClue) => {
873
- if (!isDependencyDragClue(fromTaskClue) || !isDependencyDragClue(toTaskClue)) {
874
- return null;
522
+ registerTask(task, element) {
523
+ const id = this.mapper.extractFromTask(task, 'id');
524
+ this.tasks.set(id, element);
525
+ this.notifyChanges();
875
526
  }
876
- const fromTaskType = isDependencyDragStartClue(fromTaskClue) ? 'S' : 'F';
877
- const toTaskType = isDependencyDragStartClue(toTaskClue) ? 'S' : 'F';
878
- const dependencyTypeName = `${fromTaskType}${toTaskType}`;
879
- switch (dependencyTypeName) {
880
- case 'FF': return DependencyType.FF;
881
- case 'FS': return DependencyType.FS;
882
- case 'SF': return DependencyType.SF;
883
- case 'SS': return DependencyType.SS;
884
- default: return null;
527
+ unregisterTask(task) {
528
+ const id = this.mapper.extractFromTask(task, 'id');
529
+ this.tasks.delete(id);
530
+ this.notifyChanges();
885
531
  }
886
- };
887
- /**
888
- * @hidden
889
- *
890
- * Checks whether the two provided drag clues belong to the same task element.
891
- */
892
- const sameTaskClues = (fromTaskClue, toTaskClue, parentScope) => {
893
- if (!isPresent(fromTaskClue) || !isPresent(toTaskClue)) {
894
- return false;
532
+ /**
533
+ * Notifies all dependency directives that a change in one of the elements has occured.
534
+ */
535
+ notifyChanges() {
536
+ this.notifier.next(this.dependencyDomArgs);
895
537
  }
896
- const fromTaskWrapper = getClosestTaskWrapper(fromTaskClue, parentScope);
897
- const toTaskWrapper = getClosestTaskWrapper(toTaskClue, parentScope);
898
- return fromTaskWrapper === toTaskWrapper;
899
538
  };
539
+ DependencyDomService = __decorate([
540
+ Injectable(),
541
+ __metadata("design:paramtypes", [MappingService])
542
+ ], DependencyDomService);
543
+
900
544
  /**
901
545
  * @hidden
902
- *
903
- * Fits a contender number between a min and max range.
904
- * If the contender is below the min value, the min value is returned.
905
- * If the contender is above the max value, the max value is returned.
906
546
  */
907
- const fitToRange = (contender, min, max) => {
908
- if (contender > max) {
909
- return max;
910
- }
911
- else if (contender < min) {
912
- return min;
547
+ let GanttTimelineComponent = class GanttTimelineComponent {
548
+ constructor(scrollSyncService, dependencyDomService, renderer, zone) {
549
+ this.scrollSyncService = scrollSyncService;
550
+ this.dependencyDomService = dependencyDomService;
551
+ this.renderer = renderer;
552
+ this.zone = zone;
553
+ this.hostClass = true;
554
+ this.dependencies = [];
555
+ // as all drag-and-drop operations are on the timeline container, use a single draggable instance
556
+ this.timelineContainerPress = new EventEmitter();
557
+ this.timelineContainerDrag = new EventEmitter();
558
+ this.timelineContainerRelease = new EventEmitter();
559
+ this.subscriptions = new Subscription();
560
+ this.subscriptions.add(
561
+ // task changes indicates change in row content, number, height, etc.
562
+ this.dependencyDomService.taskChanges
563
+ .pipe(filter(args => isPresent(args.timelineRow)), switchMap(args => this.zone.onStable.pipe(take(1), map(() => args))) // ensure the content is rendered
564
+ )
565
+ .subscribe(({ timelineRow }) => {
566
+ const timelineRowHeight = isDocumentAvailable() ? timelineRow.getBoundingClientRect().height : 0;
567
+ this.renderer.setStyle(this.timelineColumns.nativeElement, 'height', `${(this.rows || []).length * timelineRowHeight}px`);
568
+ }));
913
569
  }
914
- else {
915
- return contender;
570
+ /**
571
+ * Specifies whether the draggable will attach or detach its pointer event listeners.
572
+ */
573
+ get draggableEnabled() {
574
+ return this.renderDependencyDragClues;
916
575
  }
917
- };
918
- /**
919
- * @hidden
920
- *
921
- * Checks whether either of the two provided tasks is a parent of the other.
922
- */
923
- const areParentChild = (taskA, taskB) => {
924
- let parentChildRelationship = false;
925
- let taskAParent = taskA;
926
- while (isPresent(taskAParent) && isPresent(taskAParent.data)) {
927
- if (taskAParent.data === taskB.data) {
928
- parentChildRelationship = true;
929
- break;
930
- }
931
- taskAParent = taskAParent.parent;
576
+ ngAfterViewInit() {
577
+ const timelineHeader = this.timelineHeaderWrap.nativeElement;
578
+ const rightContainer = this.timelineContent.nativeElement;
579
+ this.scrollSyncService.registerElement(rightContainer, 'timeline');
580
+ this.scrollSyncService.registerElement(timelineHeader, 'header');
581
+ this.dependencyDomService.registerContentContainer(this.tasksContainer.nativeElement);
932
582
  }
933
- let taskBParent = taskB;
934
- while (!parentChildRelationship && isPresent(taskBParent) && isPresent(taskBParent.data)) {
935
- if (taskBParent.data === taskA.data) {
936
- parentChildRelationship = true;
937
- break;
938
- }
939
- taskBParent = taskBParent.parent;
583
+ ngOnDestroy() {
584
+ this.subscriptions.unsubscribe();
940
585
  }
941
- return parentChildRelationship;
942
- };
943
- /**
944
- * @hidden
945
- *
946
- * Extracts an element from the provided client coords.
947
- * Using the `event.target` is not reliable under mobile devices with the current implementation of the draggable, so use this instead.
948
- */
949
- const elementFromPoint = (clientX, clientY) => {
950
- if (!isDocumentAvailable()) {
951
- return null;
586
+ isNonWorking(item) {
587
+ return item.hasOwnProperty('isWorking') && !item.isWorking;
952
588
  }
953
- return document.elementFromPoint(clientX, clientY);
954
589
  };
955
-
590
+ __decorate([
591
+ ViewChild('timelineContent', { static: true }),
592
+ __metadata("design:type", ElementRef)
593
+ ], GanttTimelineComponent.prototype, "timelineContent", void 0);
594
+ __decorate([
595
+ ViewChild('timelineColumns', { static: true }),
596
+ __metadata("design:type", ElementRef)
597
+ ], GanttTimelineComponent.prototype, "timelineColumns", void 0);
598
+ __decorate([
599
+ ViewChild('timelineHeaderWrap', { static: true }),
600
+ __metadata("design:type", ElementRef)
601
+ ], GanttTimelineComponent.prototype, "timelineHeaderWrap", void 0);
602
+ __decorate([
603
+ ViewChild('tasksContainer', { static: true }),
604
+ __metadata("design:type", ElementRef)
605
+ ], GanttTimelineComponent.prototype, "tasksContainer", void 0);
606
+ __decorate([
607
+ ViewChild('dragPopupContainer', { static: false, read: ViewContainerRef }),
608
+ __metadata("design:type", ViewContainerRef)
609
+ ], GanttTimelineComponent.prototype, "dragPopupContainer", void 0);
610
+ __decorate([
611
+ ViewChild('dependencyDragCreatePolyline', { static: false }),
612
+ __metadata("design:type", ElementRef)
613
+ ], GanttTimelineComponent.prototype, "dependencyDragCreatePolyline", void 0);
614
+ __decorate([
615
+ HostBinding('class.k-gantt-timeline'),
616
+ __metadata("design:type", Boolean)
617
+ ], GanttTimelineComponent.prototype, "hostClass", void 0);
618
+ __decorate([
619
+ Input(),
620
+ __metadata("design:type", Array)
621
+ ], GanttTimelineComponent.prototype, "rows", void 0);
622
+ __decorate([
623
+ Input(),
624
+ __metadata("design:type", Array)
625
+ ], GanttTimelineComponent.prototype, "slots", void 0);
626
+ __decorate([
627
+ Input(),
628
+ __metadata("design:type", Array)
629
+ ], GanttTimelineComponent.prototype, "groupSlots", void 0);
630
+ __decorate([
631
+ Input(),
632
+ __metadata("design:type", Number)
633
+ ], GanttTimelineComponent.prototype, "tableWidth", void 0);
634
+ __decorate([
635
+ Input(),
636
+ __metadata("design:type", String)
637
+ ], GanttTimelineComponent.prototype, "activeView", void 0);
638
+ __decorate([
639
+ Input(),
640
+ __metadata("design:type", TemplateRef)
641
+ ], GanttTimelineComponent.prototype, "taskContentTemplate", void 0);
642
+ __decorate([
643
+ Input(),
644
+ __metadata("design:type", TemplateRef)
645
+ ], GanttTimelineComponent.prototype, "taskTemplate", void 0);
646
+ __decorate([
647
+ Input(),
648
+ __metadata("design:type", TemplateRef)
649
+ ], GanttTimelineComponent.prototype, "summaryTaskTemplate", void 0);
650
+ __decorate([
651
+ Input(),
652
+ __metadata("design:type", Function)
653
+ ], GanttTimelineComponent.prototype, "taskClass", void 0);
654
+ __decorate([
655
+ Input(),
656
+ __metadata("design:type", Boolean)
657
+ ], GanttTimelineComponent.prototype, "renderDependencyDragClues", void 0);
658
+ __decorate([
659
+ Input(),
660
+ __metadata("design:type", Object)
661
+ ], GanttTimelineComponent.prototype, "dragScrollSettings", void 0);
662
+ __decorate([
663
+ Input(),
664
+ __metadata("design:type", Boolean)
665
+ ], GanttTimelineComponent.prototype, "selectable", void 0);
666
+ __decorate([
667
+ Input(),
668
+ __metadata("design:type", Function)
669
+ ], GanttTimelineComponent.prototype, "isTaskSelected", void 0);
670
+ __decorate([
671
+ Input(),
672
+ __metadata("design:type", Function)
673
+ ], GanttTimelineComponent.prototype, "isExpanded", void 0);
674
+ __decorate([
675
+ Input(),
676
+ __metadata("design:type", Array)
677
+ ], GanttTimelineComponent.prototype, "dependencies", void 0);
678
+ __decorate([
679
+ Output(),
680
+ __metadata("design:type", EventEmitter)
681
+ ], GanttTimelineComponent.prototype, "timelineContainerPress", void 0);
682
+ __decorate([
683
+ Output(),
684
+ __metadata("design:type", EventEmitter)
685
+ ], GanttTimelineComponent.prototype, "timelineContainerDrag", void 0);
686
+ __decorate([
687
+ Output(),
688
+ __metadata("design:type", EventEmitter)
689
+ ], GanttTimelineComponent.prototype, "timelineContainerRelease", void 0);
690
+ GanttTimelineComponent = __decorate([
691
+ Component({
692
+ selector: 'kendo-gantt-timeline',
693
+ template: `
694
+ <div class="k-timeline k-grid k-widget">
695
+ <div class="k-grid-header">
696
+ <div #timelineHeaderWrap class="k-grid-header-wrap">
697
+ <table
698
+ role="presentation"
699
+ [style.width.px]="tableWidth"
700
+ >
701
+ <tbody
702
+ kendoGanttHeaderTableBody
703
+ [groupSlots]="groupSlots"
704
+ [slots]="slots">
705
+ </tbody>
706
+ </table>
707
+ </div>
708
+ </div>
709
+ <!-- tabindex="-1" required for https://bugzilla.mozilla.org/show_bug.cgi?id=1069739 -->
710
+ <div
711
+ #timelineContent
712
+ class="k-grid-content"
713
+ tabindex="-1"
714
+ role="tree"
715
+ aria-roledescription="Timeline"
716
+ kendoGanttTimelineScrollable
717
+ [scrollSettings]="dragScrollSettings"
718
+ kendoDraggable
719
+ [enableDrag]="draggableEnabled"
720
+ (kendoPress)="timelineContainerPress.emit($event)"
721
+ (kendoDrag)="timelineContainerDrag.emit($event)"
722
+ (kendoRelease)="timelineContainerRelease.emit($event)"
723
+ >
724
+ <div class="k-gantt-tables">
725
+ <table
726
+ class="k-gantt-rows"
727
+ [style.width.px]="tableWidth"
728
+ role="presentation"
729
+ >
730
+ <tbody>
731
+ <tr *ngFor="let item of rows; let i = index;"
732
+ [class.k-alt]="i % 2"
733
+ >
734
+ <td></td>
735
+ </tr>
736
+ </tbody>
737
+ </table>
738
+
739
+ <table
740
+ #timelineColumns
741
+ class="k-gantt-columns"
742
+ role="presentation"
743
+ [style.width.px]="tableWidth"
744
+ >
745
+ <colgroup>
746
+ <col *ngFor="let item of slots">
747
+ </colgroup>
748
+
749
+ <tbody>
750
+ <tr>
751
+ <td *ngFor="let item of slots"
752
+ [class.k-nonwork-hour]="isNonWorking(item)"
753
+ >
754
+ </td>
755
+ </tr>
756
+ </tbody>
757
+ </table>
758
+
759
+ <table
760
+ #tasksContainer
761
+ class="k-gantt-tasks"
762
+ role="presentation"
763
+ style="border-collapse: collapse;"
764
+ [style.width.px]="tableWidth"
765
+ >
766
+ <tbody
767
+ kendoGanttTasksTableBody
768
+ [rows]="rows"
769
+ [activeView]="activeView"
770
+ [taskContentTemplate]="taskContentTemplate"
771
+ [taskTemplate]="taskTemplate"
772
+ [summaryTaskTemplate]="summaryTaskTemplate"
773
+ [taskClass]="taskClass"
774
+ [isExpanded]="isExpanded"
775
+ [selectable]="selectable"
776
+ [isTaskSelected]="isTaskSelected"
777
+ [renderDependencyDragClues]="renderDependencyDragClues"
778
+ >
779
+ </tbody>
780
+ </table>
781
+ </div>
782
+ <svg class="k-gantt-dependencies-svg">
783
+ <polyline
784
+ *ngFor="let dependency of dependencies"
785
+ kendoGanttDependency
786
+ [dependency]="dependency"
787
+ />
788
+ <polyline #dependencyDragCreatePolyline />
789
+ </svg>
790
+
791
+ <!-- placeholder for the dependency drag popup; its position is not arbitrary - the popup is intended to be absolutely positioned inside the .k-grid-content element -->
792
+ <ng-container #dragPopupContainer></ng-container>
793
+ </div>
794
+ </div>
795
+ `
796
+ }),
797
+ __metadata("design:paramtypes", [ScrollSyncService,
798
+ DependencyDomService,
799
+ Renderer2,
800
+ NgZone])
801
+ ], GanttTimelineComponent);
802
+
803
+ /**
804
+ * The base class for the column components of the Gantt.
805
+ */
806
+ class GanttColumnBase extends ColumnBase {
807
+ constructor() {
808
+ super(...arguments);
809
+ /**
810
+ * Toggles the locked (frozen) state of the columns.
811
+ *
812
+ * @default false
813
+ * @hidden
814
+ */
815
+ this.locked = false;
816
+ }
817
+ }
818
+ __decorate([
819
+ Input(),
820
+ __metadata("design:type", Boolean)
821
+ ], GanttColumnBase.prototype, "locked", void 0);
822
+ __decorate([
823
+ Input(),
824
+ __metadata("design:type", Boolean)
825
+ ], GanttColumnBase.prototype, "lockable", void 0);
826
+ __decorate([
827
+ Input(),
828
+ __metadata("design:type", Boolean)
829
+ ], GanttColumnBase.prototype, "hidden", void 0);
830
+ __decorate([
831
+ Input(),
832
+ __metadata("design:type", String)
833
+ ], GanttColumnBase.prototype, "media", void 0);
834
+ __decorate([
835
+ Input(),
836
+ __metadata("design:type", Object)
837
+ ], GanttColumnBase.prototype, "style", void 0);
838
+ __decorate([
839
+ Input(),
840
+ __metadata("design:type", Object)
841
+ ], GanttColumnBase.prototype, "headerStyle", void 0);
842
+ __decorate([
843
+ Input(),
844
+ __metadata("design:type", Object)
845
+ ], GanttColumnBase.prototype, "footerStyle", void 0);
846
+ __decorate([
847
+ Input('class'),
848
+ __metadata("design:type", Object)
849
+ ], GanttColumnBase.prototype, "cssClass", void 0);
850
+ __decorate([
851
+ Input(),
852
+ __metadata("design:type", Object)
853
+ ], GanttColumnBase.prototype, "headerClass", void 0);
854
+ __decorate([
855
+ Input(),
856
+ __metadata("design:type", Object)
857
+ ], GanttColumnBase.prototype, "footerClass", void 0);
858
+
859
+ /**
860
+ * @hidden
861
+ */
862
+ let OptionChangesService = class OptionChangesService {
863
+ /**
864
+ * @hidden
865
+ */
866
+ constructor() {
867
+ this.viewChanges = new EventEmitter();
868
+ this.columnChanges = new EventEmitter();
869
+ }
870
+ notifyColumnChanges() {
871
+ this.columnChanges.emit();
872
+ }
873
+ notifyViewChanges() {
874
+ this.viewChanges.emit();
875
+ }
876
+ };
877
+ OptionChangesService = __decorate([
878
+ Injectable()
879
+ ], OptionChangesService);
880
+
881
+ /**
882
+ * Represents the column cell template of the Gantt.
883
+ * Helps to customize the content of the cells. To define the cell template, nest an `<ng-template>` tag
884
+ * with the `kendoGanttCellTemplate` directive inside the respective column tag.
885
+ *
886
+ * The template context is set to the current data item and the following additional fields are passed:
887
+ * - `dataItem`&mdash;The current data item. Represents the default context that will be assigned to any template variable which utilizes the `let-x` syntax&mdash;for example, `let-dataItem`.
888
+ * - `columnIndex`&mdash;The current column index. Use it as an alias for a template variable by utilizing the `let-columnIndex="columnIndex"` syntax.
889
+ * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
890
+ * - `cellContext`&mdash;An object used to pass context information to built-in directives.
891
+ * - `hasChildren`&mdash;Specifies if the item has children.
892
+ * - `isExpanded`&mdash;Specifies if the item is expanded.
893
+ * - `level`&mdash;The hierarchy level of the item.
894
+ * - `loading`&mdash;Specifies if the item children are currently loading.
895
+ * - `rowIndex`&mdash;The current row index. Use it as an alias for a template variable by utilizing the `let-rowIndex="rowIndex"` syntax.
896
+ */
897
+ let CellTemplateDirective = class CellTemplateDirective {
898
+ constructor(templateRef) {
899
+ this.templateRef = templateRef;
900
+ }
901
+ };
902
+ CellTemplateDirective = __decorate([
903
+ Directive({
904
+ selector: '[kendoGanttCellTemplate]'
905
+ }),
906
+ __param(0, Optional()),
907
+ __metadata("design:paramtypes", [TemplateRef])
908
+ ], CellTemplateDirective);
909
+
910
+ /**
911
+ * Represents the template for the column menu in the Gantt. Provides an option for
912
+ * customizing the content of the column menu for all or for specific columns.
913
+ * To define the content template, nest an `<ng-template>` tag with the
914
+ * `kendoGanttColumnMenuTemplate` directive inside the `<kendo-gantt-column>` component.
915
+ *
916
+ * The column menu service and the current column are available as context variables:
917
+ * - `service`&mdash;Represents the ColumnMenuService.
918
+ * - `column`&mdash;Represents the Gantt column.
919
+ */
920
+ let ColumnMenuTemplateDirective = class ColumnMenuTemplateDirective {
921
+ constructor(templateRef) {
922
+ this.templateRef = templateRef;
923
+ }
924
+ };
925
+ ColumnMenuTemplateDirective = __decorate([
926
+ Directive({
927
+ selector: '[kendoGanttColumnMenuTemplate]'
928
+ }),
929
+ __param(0, Optional()),
930
+ __metadata("design:paramtypes", [TemplateRef])
931
+ ], ColumnMenuTemplateDirective);
932
+
933
+ /**
934
+ * @hidden
935
+ * Represents the filter-cell template.
936
+ *
937
+ * The template context is set to the filter descriptor and the following additional fields are passed:
938
+ * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
939
+ * - `filter`&mdash;The filter descriptor.
940
+ * - `cellContext`&mdash;An object used to pass context information to built-in directives.
941
+ */
942
+ let FilterCellTemplateDirective = class FilterCellTemplateDirective {
943
+ constructor(templateRef) {
944
+ this.templateRef = templateRef;
945
+ }
946
+ };
947
+ FilterCellTemplateDirective = __decorate([
948
+ Directive({
949
+ selector: '[kendoGanttFilterCellTemplate]'
950
+ }),
951
+ __param(0, Optional()),
952
+ __metadata("design:paramtypes", [TemplateRef])
953
+ ], FilterCellTemplateDirective);
954
+
955
+ /**
956
+ * Represents the filter-menu template.
957
+ *
958
+ * The column, current filter and the filter service are available as context variables:
959
+ * - `column`&mdash;The current column instance. Use it as an alias for a template variable by utilizing the `let-column="column"` syntax.
960
+ * - `filter`&mdash;The filter descriptor.
961
+ * - `cellContext`&mdash;An object used to pass context information to built-in directives.
962
+ */
963
+ let FilterMenuTemplateDirective = class FilterMenuTemplateDirective {
964
+ constructor(templateRef) {
965
+ this.templateRef = templateRef;
966
+ }
967
+ };
968
+ FilterMenuTemplateDirective = __decorate([
969
+ Directive({
970
+ selector: '[kendoGanttFilterMenuTemplate]'
971
+ }),
972
+ __param(0, Optional()),
973
+ __metadata("design:paramtypes", [TemplateRef])
974
+ ], FilterMenuTemplateDirective);
975
+
976
+ /**
977
+ * Represents the column footer cell template of the Gantt.
978
+ *
979
+ * Helps to customize the table footer cell for the column.
980
+ * To define a footer template, nest an `<ng-template>` tag with the
981
+ * [`kendoGanttFooterTemplate`]({% slug api_gantt_footertemplatedirective %}) directive inside the `<kendo-gantt-column>` tag.
982
+ *
983
+ * The current column, column index and field are available as context variables:
984
+ * * `column`&mdash;Points to the instance of the current [`ColumnComponent`]({% slug api_gantt_ganttcolumncomponent %}).
985
+ * * `columnIndex`&mdash;Defines the current column index.
986
+ * * `field`&mdash;The name of the column field, if set.
987
+ */
988
+ let FooterTemplateDirective = class FooterTemplateDirective {
989
+ constructor(templateRef) {
990
+ this.templateRef = templateRef;
991
+ }
992
+ };
993
+ FooterTemplateDirective = __decorate([
994
+ Directive({
995
+ selector: '[kendoGanttFooterTemplate]'
996
+ }),
997
+ __param(0, Optional()),
998
+ __metadata("design:paramtypes", [TemplateRef])
999
+ ], FooterTemplateDirective);
1000
+
1001
+ /**
1002
+ * Represents the column header cell template of the Gantt.
1003
+ * Helps to customize the table header cell for the column.
1004
+ * To define a header template, nest an `<ng-template>` tag with the
1005
+ * [`kendoGanttHeaderTemplate`]({% slug api_gantt_headertemplatedirective %}) directive inside the `<kendo-gantt-column>` tag.
1006
+ *
1007
+ * The current column and column index are available as context variables:
1008
+ * * `column`&mdash;Points to the instance of the current [`ColumnComponent`]({% slug api_gantt_ganttcolumncomponent %}).
1009
+ * * `columnIndex`&mdash;Defines the current column index.
1010
+ */
1011
+ let HeaderTemplateDirective = class HeaderTemplateDirective {
1012
+ constructor(templateRef) {
1013
+ this.templateRef = templateRef;
1014
+ }
1015
+ };
1016
+ HeaderTemplateDirective = __decorate([
1017
+ Directive({
1018
+ selector: '[kendoGanttHeaderTemplate]'
1019
+ }),
1020
+ __param(0, Optional()),
1021
+ __metadata("design:paramtypes", [TemplateRef])
1022
+ ], HeaderTemplateDirective);
1023
+
1024
+ /**
1025
+ * Represents the column edit-cell template of the Gantt.
1026
+ * Helps to customize the content of the edited cells. To define the cell template, nest an `<ng-template>`
1027
+ * tag with the `kendoGanttEditTemplate` directive inside a `<kendo-gantt-column>` tag.
1028
+ *
1029
+ * The template context contains the following fields:
1030
+ * - `column`&mdash;The current column instance.
1031
+ * - `dataItem`&mdash;The current data item.
1032
+ * - `cellContext`&mdash;An object used to pass context information to built-in directives.
1033
+ * - `formGroup`&mdash;The current [`FormGroup`]({{ site.data.urls.angular['formgroupapi'] }}).
1034
+ * If you use the Gantt inside [Template-Driven Forms]({{ site.data.urls.angular['forms'] }}), it will be `undefined`.
1035
+ * - `isNew`&mdash;The state of the current item.
1036
+ * - `rowIndex`&mdash;The current row index. If inside a new item row, `rowIndex` is `-1`.
1037
+ */
1038
+ let EditTemplateDirective = class EditTemplateDirective {
1039
+ constructor(templateRef) {
1040
+ this.templateRef = templateRef;
1041
+ }
1042
+ };
1043
+ EditTemplateDirective = __decorate([
1044
+ Directive({
1045
+ selector: '[kendoGanttEditTemplate]'
1046
+ }),
1047
+ __param(0, Optional()),
1048
+ __metadata("design:paramtypes", [TemplateRef])
1049
+ ], EditTemplateDirective);
1050
+
1051
+ var GanttColumnComponent_1;
1052
+ let GanttColumnComponent = GanttColumnComponent_1 = class GanttColumnComponent extends ColumnComponent {
1053
+ constructor(options, parent) {
1054
+ super(parent);
1055
+ this.options = options;
1056
+ this.headerTemplates = new QueryList();
1057
+ this.columnMenuTemplates = new QueryList();
1058
+ /**
1059
+ * Defines the filter type that is displayed inside the filter row. The default value is `text`.
1060
+ */
1061
+ this.filter = 'text';
1062
+ /**
1063
+ * Defines if a filter UI will be displayed for this column. The default value is `true`.
1064
+ */
1065
+ this.filterable = true;
1066
+ /**
1067
+ * @hidden
1068
+ *
1069
+ * Defines the editor type.
1070
+ * Used when the column enters the edit mode. The default value is `text`.
1071
+ */
1072
+ this.editor = 'text';
1073
+ /**
1074
+ * @hidden
1075
+ *
1076
+ * Defines whether the column is editable. The default value is `true`.
1077
+ */
1078
+ this.editable = true;
1079
+ /**
1080
+ * Toggles the locked (frozen) state of the columns.
1081
+ * @hidden
1082
+ * @default false
1083
+ */
1084
+ this.locked = false;
1085
+ }
1086
+ ngOnChanges() {
1087
+ this.options.notifyColumnChanges();
1088
+ }
1089
+ };
1090
+ __decorate([
1091
+ ContentChildren(HeaderTemplateDirective, { descendants: false }),
1092
+ __metadata("design:type", QueryList)
1093
+ ], GanttColumnComponent.prototype, "headerTemplates", void 0);
1094
+ __decorate([
1095
+ ContentChild(FooterTemplateDirective, { static: false }),
1096
+ __metadata("design:type", FooterTemplateDirective)
1097
+ ], GanttColumnComponent.prototype, "footerTemplate", void 0);
1098
+ __decorate([
1099
+ ContentChildren(ColumnMenuTemplateDirective),
1100
+ __metadata("design:type", QueryList)
1101
+ ], GanttColumnComponent.prototype, "columnMenuTemplates", void 0);
1102
+ __decorate([
1103
+ ContentChild(CellTemplateDirective, { static: false }),
1104
+ __metadata("design:type", CellTemplateDirective)
1105
+ ], GanttColumnComponent.prototype, "template", void 0);
1106
+ __decorate([
1107
+ ContentChild(EditTemplateDirective, { static: false }),
1108
+ __metadata("design:type", EditTemplateDirective)
1109
+ ], GanttColumnComponent.prototype, "editTemplate", void 0);
1110
+ __decorate([
1111
+ ContentChild(FilterCellTemplateDirective, { static: false }),
1112
+ __metadata("design:type", FilterCellTemplateDirective)
1113
+ ], GanttColumnComponent.prototype, "filterCellTemplate", void 0);
1114
+ __decorate([
1115
+ ContentChild(FilterMenuTemplateDirective, { static: false }),
1116
+ __metadata("design:type", FilterMenuTemplateDirective)
1117
+ ], GanttColumnComponent.prototype, "filterMenuTemplate", void 0);
1118
+ __decorate([
1119
+ Input(),
1120
+ __metadata("design:type", Object)
1121
+ ], GanttColumnComponent.prototype, "format", void 0);
1122
+ __decorate([
1123
+ Input(),
1124
+ __metadata("design:type", String)
1125
+ ], GanttColumnComponent.prototype, "filter", void 0);
1126
+ __decorate([
1127
+ Input(),
1128
+ __metadata("design:type", Boolean)
1129
+ ], GanttColumnComponent.prototype, "filterable", void 0);
1130
+ __decorate([
1131
+ Input(),
1132
+ __metadata("design:type", String)
1133
+ ], GanttColumnComponent.prototype, "editor", void 0);
1134
+ __decorate([
1135
+ Input(),
1136
+ __metadata("design:type", Boolean)
1137
+ ], GanttColumnComponent.prototype, "editable", void 0);
1138
+ __decorate([
1139
+ Input(),
1140
+ __metadata("design:type", Boolean)
1141
+ ], GanttColumnComponent.prototype, "locked", void 0);
1142
+ __decorate([
1143
+ Input(),
1144
+ __metadata("design:type", Boolean)
1145
+ ], GanttColumnComponent.prototype, "lockable", void 0);
1146
+ __decorate([
1147
+ Input(),
1148
+ __metadata("design:type", Boolean)
1149
+ ], GanttColumnComponent.prototype, "hidden", void 0);
1150
+ __decorate([
1151
+ Input(),
1152
+ __metadata("design:type", String)
1153
+ ], GanttColumnComponent.prototype, "media", void 0);
1154
+ __decorate([
1155
+ Input(),
1156
+ __metadata("design:type", Object)
1157
+ ], GanttColumnComponent.prototype, "style", void 0);
1158
+ __decorate([
1159
+ Input(),
1160
+ __metadata("design:type", Object)
1161
+ ], GanttColumnComponent.prototype, "headerStyle", void 0);
1162
+ __decorate([
1163
+ Input(),
1164
+ __metadata("design:type", Object)
1165
+ ], GanttColumnComponent.prototype, "footerStyle", void 0);
1166
+ __decorate([
1167
+ Input('class'),
1168
+ __metadata("design:type", Object)
1169
+ ], GanttColumnComponent.prototype, "cssClass", void 0);
1170
+ __decorate([
1171
+ Input(),
1172
+ __metadata("design:type", Object)
1173
+ ], GanttColumnComponent.prototype, "headerClass", void 0);
1174
+ __decorate([
1175
+ Input(),
1176
+ __metadata("design:type", Object)
1177
+ ], GanttColumnComponent.prototype, "footerClass", void 0);
1178
+ GanttColumnComponent = GanttColumnComponent_1 = __decorate([
1179
+ Component({
1180
+ selector: 'kendo-gantt-column',
1181
+ template: '',
1182
+ providers: [
1183
+ {
1184
+ provide: GanttColumnBase,
1185
+ useExisting: forwardRef(() => GanttColumnComponent_1)
1186
+ }
1187
+ ]
1188
+ }),
1189
+ __param(1, SkipSelf()), __param(1, Host()), __param(1, Optional()),
1190
+ __metadata("design:paramtypes", [OptionChangesService,
1191
+ GanttColumnBase])
1192
+ ], GanttColumnComponent);
1193
+
1194
+ var GanttColumnGroupComponent_1;
1195
+ let GanttColumnGroupComponent = GanttColumnGroupComponent_1 = class GanttColumnGroupComponent extends ColumnGroupComponent {
1196
+ constructor(options, parent) {
1197
+ super(parent);
1198
+ this.options = options;
1199
+ /**
1200
+ * @hidden
1201
+ */
1202
+ this.children = new QueryList();
1203
+ /**
1204
+ * Toggles the locked (frozen) state of the columns.
1205
+ *
1206
+ * @default false
1207
+ * @hidden
1208
+ */
1209
+ this.locked = false;
1210
+ /**
1211
+ * Allows the column headers to be clicked and the `sortChange` event emitted.
1212
+ * You have to handle the `sortChange` event yourself and sort the data.
1213
+ */
1214
+ this.sortable = true;
1215
+ if (parent && parent.isSpanColumn) {
1216
+ throw new Error('ColumnGroupComponent cannot be nested inside SpanColumnComponent');
1217
+ }
1218
+ }
1219
+ ngOnChanges() {
1220
+ this.options.notifyColumnChanges();
1221
+ }
1222
+ };
1223
+ __decorate([
1224
+ ContentChildren(GanttColumnBase),
1225
+ __metadata("design:type", QueryList)
1226
+ ], GanttColumnGroupComponent.prototype, "children", void 0);
1227
+ __decorate([
1228
+ ContentChildren(HeaderTemplateDirective),
1229
+ __metadata("design:type", QueryList)
1230
+ ], GanttColumnGroupComponent.prototype, "headerTemplates", void 0);
1231
+ __decorate([
1232
+ Input(),
1233
+ __metadata("design:type", Boolean)
1234
+ ], GanttColumnGroupComponent.prototype, "locked", void 0);
1235
+ __decorate([
1236
+ Input(),
1237
+ __metadata("design:type", Boolean)
1238
+ ], GanttColumnGroupComponent.prototype, "lockable", void 0);
1239
+ __decorate([
1240
+ Input(),
1241
+ __metadata("design:type", Boolean)
1242
+ ], GanttColumnGroupComponent.prototype, "hidden", void 0);
1243
+ __decorate([
1244
+ Input(),
1245
+ __metadata("design:type", Object)
1246
+ ], GanttColumnGroupComponent.prototype, "sortable", void 0);
1247
+ __decorate([
1248
+ Input(),
1249
+ __metadata("design:type", String)
1250
+ ], GanttColumnGroupComponent.prototype, "media", void 0);
1251
+ __decorate([
1252
+ Input(),
1253
+ __metadata("design:type", Object)
1254
+ ], GanttColumnGroupComponent.prototype, "style", void 0);
1255
+ __decorate([
1256
+ Input(),
1257
+ __metadata("design:type", Object)
1258
+ ], GanttColumnGroupComponent.prototype, "headerStyle", void 0);
1259
+ __decorate([
1260
+ Input(),
1261
+ __metadata("design:type", Object)
1262
+ ], GanttColumnGroupComponent.prototype, "footerStyle", void 0);
1263
+ __decorate([
1264
+ Input('class'),
1265
+ __metadata("design:type", Object)
1266
+ ], GanttColumnGroupComponent.prototype, "cssClass", void 0);
1267
+ __decorate([
1268
+ Input(),
1269
+ __metadata("design:type", Object)
1270
+ ], GanttColumnGroupComponent.prototype, "headerClass", void 0);
1271
+ __decorate([
1272
+ Input(),
1273
+ __metadata("design:type", Object)
1274
+ ], GanttColumnGroupComponent.prototype, "footerClass", void 0);
1275
+ GanttColumnGroupComponent = GanttColumnGroupComponent_1 = __decorate([
1276
+ Component({
1277
+ selector: 'kendo-gantt-column-group',
1278
+ template: '',
1279
+ providers: [
1280
+ {
1281
+ provide: GanttColumnBase,
1282
+ useExisting: forwardRef(() => GanttColumnGroupComponent_1)
1283
+ }
1284
+ ]
1285
+ }),
1286
+ __param(1, SkipSelf()), __param(1, Host()), __param(1, Optional()),
1287
+ __metadata("design:paramtypes", [OptionChangesService,
1288
+ GanttColumnBase])
1289
+ ], GanttColumnGroupComponent);
1290
+
1291
+ var GanttSpanColumnComponent_1;
1292
+ let GanttSpanColumnComponent = GanttSpanColumnComponent_1 = class GanttSpanColumnComponent extends SpanColumnComponent {
1293
+ constructor(options, parent) {
1294
+ super(parent);
1295
+ this.options = options;
1296
+ /**
1297
+ * @hidden
1298
+ */
1299
+ this.childColumns = new QueryList();
1300
+ this.template = new QueryList();
1301
+ this.editTemplate = new QueryList();
1302
+ }
1303
+ ngOnChanges() {
1304
+ this.options.notifyColumnChanges();
1305
+ }
1306
+ };
1307
+ __decorate([
1308
+ ContentChildren(GanttColumnComponent),
1309
+ __metadata("design:type", QueryList)
1310
+ ], GanttSpanColumnComponent.prototype, "childColumns", void 0);
1311
+ __decorate([
1312
+ ContentChildren(CellTemplateDirective, { descendants: false }),
1313
+ __metadata("design:type", QueryList)
1314
+ ], GanttSpanColumnComponent.prototype, "template", void 0);
1315
+ __decorate([
1316
+ ContentChildren(EditTemplateDirective, { descendants: false }),
1317
+ __metadata("design:type", QueryList)
1318
+ ], GanttSpanColumnComponent.prototype, "editTemplate", void 0);
1319
+ __decorate([
1320
+ Input(),
1321
+ __metadata("design:type", Boolean)
1322
+ ], GanttSpanColumnComponent.prototype, "locked", void 0);
1323
+ __decorate([
1324
+ Input(),
1325
+ __metadata("design:type", Boolean)
1326
+ ], GanttSpanColumnComponent.prototype, "lockable", void 0);
1327
+ __decorate([
1328
+ Input(),
1329
+ __metadata("design:type", Boolean)
1330
+ ], GanttSpanColumnComponent.prototype, "editable", void 0);
1331
+ __decorate([
1332
+ Input(),
1333
+ __metadata("design:type", Boolean)
1334
+ ], GanttSpanColumnComponent.prototype, "hidden", void 0);
1335
+ __decorate([
1336
+ Input(),
1337
+ __metadata("design:type", String)
1338
+ ], GanttSpanColumnComponent.prototype, "media", void 0);
1339
+ __decorate([
1340
+ Input(),
1341
+ __metadata("design:type", Object)
1342
+ ], GanttSpanColumnComponent.prototype, "style", void 0);
1343
+ __decorate([
1344
+ Input(),
1345
+ __metadata("design:type", Object)
1346
+ ], GanttSpanColumnComponent.prototype, "headerStyle", void 0);
1347
+ __decorate([
1348
+ Input(),
1349
+ __metadata("design:type", Object)
1350
+ ], GanttSpanColumnComponent.prototype, "footerStyle", void 0);
1351
+ __decorate([
1352
+ Input('class'),
1353
+ __metadata("design:type", Object)
1354
+ ], GanttSpanColumnComponent.prototype, "cssClass", void 0);
1355
+ __decorate([
1356
+ Input(),
1357
+ __metadata("design:type", Object)
1358
+ ], GanttSpanColumnComponent.prototype, "headerClass", void 0);
1359
+ __decorate([
1360
+ Input(),
1361
+ __metadata("design:type", Object)
1362
+ ], GanttSpanColumnComponent.prototype, "footerClass", void 0);
1363
+ GanttSpanColumnComponent = GanttSpanColumnComponent_1 = __decorate([
1364
+ Component({
1365
+ selector: 'kendo-gantt-span-column',
1366
+ template: '',
1367
+ providers: [
1368
+ {
1369
+ provide: GanttColumnBase,
1370
+ useExisting: forwardRef(() => GanttSpanColumnComponent_1)
1371
+ }
1372
+ ]
1373
+ }),
1374
+ __param(1, SkipSelf()), __param(1, Host()), __param(1, Optional()),
1375
+ __metadata("design:paramtypes", [OptionChangesService,
1376
+ GanttColumnBase])
1377
+ ], GanttSpanColumnComponent);
1378
+
1379
+ /**
1380
+ * @hidden
1381
+ */
1382
+ const hasChildren = () => false;
1383
+ /**
1384
+ * @hidden
1385
+ */
1386
+ const fetchChildren = () => of([]);
1387
+ /**
1388
+ * @hidden
1389
+ */
1390
+ const rowClassCallback = () => null;
1391
+ /**
1392
+ * @hidden
1393
+ */
1394
+ const taskClassCallback = () => null;
1395
+ /**
1396
+ * @hidden
1397
+ */
1398
+ const isSelected = () => false;
1399
+
1400
+ /**
1401
+ * @hidden
1402
+ */
1403
+ class PreventableEvent {
1404
+ constructor() {
1405
+ this.prevented = false;
1406
+ }
1407
+ /**
1408
+ * Prevents the default action for a specified event.
1409
+ * In this way, the source component suppresses
1410
+ * the built-in behavior that follows the event.
1411
+ */
1412
+ preventDefault() {
1413
+ this.prevented = true;
1414
+ }
1415
+ /**
1416
+ * Returns `true` if the event was prevented
1417
+ * by any of its subscribers.
1418
+ *
1419
+ * @returns `true` if the default action was prevented.
1420
+ * Otherwise, returns `false`.
1421
+ */
1422
+ isDefaultPrevented() {
1423
+ return this.prevented;
1424
+ }
1425
+ }
1426
+
1427
+ /**
1428
+ * Called every time a user leaves an edited cell.
1429
+ */
1430
+ class CellCloseEvent extends PreventableEvent {
1431
+ constructor(options) {
1432
+ super();
1433
+ Object.assign(this, options);
1434
+ }
1435
+ }
1436
+
956
1437
  /**
957
1438
  * @hidden
958
1439
  */
@@ -1107,84 +1588,6 @@ class TimelineBaseViewService {
1107
1588
  }
1108
1589
  }
1109
1590
 
1110
- /**
1111
- * @hidden
1112
- */
1113
- const DEFAULT_DEPENDENCY_MODEL_FIELDS = Object.freeze({
1114
- toId: 'toId',
1115
- fromId: 'fromId',
1116
- id: 'id',
1117
- type: 'type'
1118
- });
1119
-
1120
- /**
1121
- * @hidden
1122
- */
1123
- const DEFAULT_TASK_MODEL_FIELDS = Object.freeze({
1124
- id: 'id',
1125
- start: 'start',
1126
- end: 'end',
1127
- title: 'title',
1128
- completionRatio: 'completionRatio',
1129
- children: 'children'
1130
- });
1131
-
1132
- /**
1133
- * @hidden
1134
- */
1135
- let MappingService = class MappingService {
1136
- /**
1137
- * @hidden
1138
- */
1139
- constructor() {
1140
- this._taskFields = Object.assign({}, DEFAULT_TASK_MODEL_FIELDS);
1141
- this._dependencyFields = Object.assign({}, DEFAULT_DEPENDENCY_MODEL_FIELDS);
1142
- }
1143
- /**
1144
- * Gets or sets the model fields for the task data items.
1145
- * Uses the default values for fields which are not specified.
1146
- */
1147
- set taskFields(fields) {
1148
- this._taskFields = Object.assign({}, DEFAULT_TASK_MODEL_FIELDS, fields);
1149
- }
1150
- get taskFields() {
1151
- return this._taskFields;
1152
- }
1153
- /**
1154
- * Gets or sets the model fields for the depenency data items.
1155
- * Uses the default values for fields which are not specified.
1156
- */
1157
- set dependencyFields(fields) {
1158
- this._dependencyFields = Object.assign({}, DEFAULT_DEPENDENCY_MODEL_FIELDS, fields);
1159
- }
1160
- get dependencyFields() {
1161
- return this._dependencyFields;
1162
- }
1163
- /**
1164
- * Retrieves the value for the specified task field.
1165
- * Supports nested fields as well (e.g. 'manager.id').
1166
- */
1167
- extractFromTask(dataItem, field) {
1168
- if (!isPresent(this.taskFields)) {
1169
- return null;
1170
- }
1171
- return getter(this.taskFields[field])(dataItem);
1172
- }
1173
- /**
1174
- * Retrieves the value for the specified dependency field.
1175
- * Supports nested fields as well (e.g. 'manager.id').
1176
- */
1177
- extractFromDependency(dataItem, field) {
1178
- if (!isPresent(this.dependencyFields)) {
1179
- return null;
1180
- }
1181
- return getter(this.dependencyFields[field])(dataItem);
1182
- }
1183
- };
1184
- MappingService = __decorate([
1185
- Injectable()
1186
- ], MappingService);
1187
-
1188
1591
  /**
1189
1592
  * @hidden
1190
1593
  */
@@ -1353,157 +1756,23 @@ const services = {
1353
1756
  week: TimelineWeekViewService,
1354
1757
  month: TimelineMonthViewService
1355
1758
  };
1356
- /**
1357
- * @hidden
1358
- */
1359
- let TimelineViewService = class TimelineViewService {
1360
- constructor(injector) {
1361
- this.injector = injector;
1362
- this.viewChange = new EventEmitter();
1363
- }
1364
- service(view) {
1365
- const serviceType = services[view];
1366
- return serviceType ? this.injector.get(serviceType) : null;
1367
- }
1368
- };
1369
- TimelineViewService = __decorate([
1370
- Injectable(),
1371
- __metadata("design:paramtypes", [Injector])
1372
- ], TimelineViewService);
1373
-
1374
- /**
1375
- * @hidden
1376
- */
1377
- let ScrollSyncService = class ScrollSyncService {
1378
- constructor(ngZone) {
1379
- this.ngZone = ngZone;
1380
- this.changes = new Subject();
1381
- this.elements = [];
1382
- this.subscriptions = new Subscription();
1383
- this.subscriptions.add(this.changes.subscribe(args => {
1384
- this.scroll(args);
1385
- }));
1386
- }
1387
- registerElement(el, sourceType) {
1388
- this.elements.push({ element: el, sourceType });
1389
- if (sourceType === "timeline" || sourceType === "treelist") {
1390
- this.ngZone.runOutsideAngular(() => {
1391
- const obs = fromEvent(el, 'scroll').pipe(map(({ target: { scrollTop, scrollLeft } }) => ({
1392
- scrollTop,
1393
- scrollLeft,
1394
- sourceType
1395
- })));
1396
- const comparisonFn = sourceType === 'timeline' ?
1397
- (x, y) => (x.scrollTop === y.scrollTop) && (x.scrollLeft === y.scrollLeft) :
1398
- (x, y) => (x.scrollTop === y.scrollTop);
1399
- this.subscriptions.add(obs.pipe(distinctUntilChanged(comparisonFn))
1400
- .subscribe((event) => this.changes.next(event)));
1401
- });
1402
- }
1403
- }
1404
- ngOnDestroy() {
1405
- this.subscriptions.unsubscribe();
1406
- this.elements = null;
1407
- }
1408
- syncScrollTop(sourceType, targetType) {
1409
- const source = this.elements.find(element => element.sourceType === sourceType);
1410
- const target = this.elements.find(element => element.sourceType === targetType);
1411
- // Need to wait for the splitter pane's content to be rendered
1412
- this.ngZone.onStable.pipe(take(1)).subscribe(() => target.element.scrollTop = source.element.scrollTop);
1413
- }
1414
- resetTimelineScrollLeft() {
1415
- const source = this.elements.find(element => element.sourceType === 'timeline');
1416
- source.element.scrollLeft = 0;
1417
- }
1418
- scroll({ scrollTop, scrollLeft, sourceType }) {
1419
- this.ngZone.runOutsideAngular(() => {
1420
- if (sourceType === 'timeline') {
1421
- const header = this.elements.find(element => element.sourceType === 'header').element;
1422
- header.scrollLeft = scrollLeft;
1423
- if (!this.syncingTimeline) {
1424
- this.syncingTreeList = true;
1425
- const treelist = this.elements.find(element => element.sourceType === 'treelist').element;
1426
- treelist.scrollTop = scrollTop;
1427
- }
1428
- this.syncingTimeline = false;
1429
- }
1430
- if (sourceType === 'treelist') {
1431
- if (!this.syncingTreeList) {
1432
- this.syncingTimeline = true;
1433
- const timeline = this.elements.find(element => element.sourceType === 'timeline').element;
1434
- timeline.scrollTop = scrollTop;
1435
- }
1436
- this.syncingTreeList = false;
1437
- }
1438
- });
1439
- }
1440
- };
1441
- ScrollSyncService = __decorate([
1442
- Injectable(),
1443
- __metadata("design:paramtypes", [NgZone])
1444
- ], ScrollSyncService);
1445
-
1446
- /**
1447
- * @hidden
1448
- */
1449
- let DependencyDomService = class DependencyDomService {
1450
- constructor(mapper) {
1451
- this.mapper = mapper;
1452
- this.notifier = new Subject();
1453
- /**
1454
- * Maps each rendered task to its HTML element.
1455
- * Uses the task ID field value as key.
1456
- */
1457
- this.tasks = new Map();
1458
- }
1459
- /**
1460
- * Emits each time some of the tasks or the view have changed.
1461
- * Fires also on the first change of the table rows and the parent container.
1462
- */
1463
- get taskChanges() {
1464
- return this.notifier.asObservable();
1465
- }
1466
- get dependencyDomArgs() {
1467
- return {
1468
- tasks: this.tasks,
1469
- contentContainer: this.contentContainer,
1470
- timelineRow: this.timelineRow
1471
- };
1472
- }
1473
- ngOnDestroy() {
1474
- this.tasks.clear();
1475
- this.tasks = null;
1476
- this.contentContainer = null;
1477
- }
1478
- registerTimelineRow(timelineRow) {
1479
- this.timelineRow = timelineRow;
1480
- this.notifyChanges();
1481
- }
1482
- registerContentContainer(contentContainer) {
1483
- this.contentContainer = contentContainer;
1484
- this.notifyChanges();
1485
- }
1486
- registerTask(task, element) {
1487
- const id = this.mapper.extractFromTask(task, 'id');
1488
- this.tasks.set(id, element);
1489
- this.notifyChanges();
1490
- }
1491
- unregisterTask(task) {
1492
- const id = this.mapper.extractFromTask(task, 'id');
1493
- this.tasks.delete(id);
1494
- this.notifyChanges();
1759
+ /**
1760
+ * @hidden
1761
+ */
1762
+ let TimelineViewService = class TimelineViewService {
1763
+ constructor(injector) {
1764
+ this.injector = injector;
1765
+ this.viewChange = new EventEmitter();
1495
1766
  }
1496
- /**
1497
- * Notifies all dependency directives that a change in one of the elements has occured.
1498
- */
1499
- notifyChanges() {
1500
- this.notifier.next(this.dependencyDomArgs);
1767
+ service(view) {
1768
+ const serviceType = services[view];
1769
+ return serviceType ? this.injector.get(serviceType) : null;
1501
1770
  }
1502
1771
  };
1503
- DependencyDomService = __decorate([
1772
+ TimelineViewService = __decorate([
1504
1773
  Injectable(),
1505
- __metadata("design:paramtypes", [MappingService])
1506
- ], DependencyDomService);
1774
+ __metadata("design:paramtypes", [Injector])
1775
+ ], TimelineViewService);
1507
1776
 
1508
1777
  /**
1509
1778
  * @hidden
@@ -1512,9 +1781,11 @@ let EditService = class EditService {
1512
1781
  constructor(mapper) {
1513
1782
  this.mapper = mapper;
1514
1783
  this.showEditingDialog = new Subject();
1515
- this.showConfirmationDialog = new Subject();
1784
+ this.taskDelete = new Subject();
1516
1785
  this.editEvent = new Subject();
1517
1786
  this.addEvent = new Subject();
1787
+ this.predecessors = [];
1788
+ this.successors = [];
1518
1789
  this.updatedItems = [];
1519
1790
  this.deletedItems = [];
1520
1791
  this.itemIndex = (item, data) => {
@@ -1659,512 +1930,671 @@ GanttLocalizationService = __decorate([
1659
1930
  __metadata("design:paramtypes", [LocalizationService])
1660
1931
  ], GanttLocalizationService);
1661
1932
 
1933
+ // TODO: add those keys to `import { Keys } from '@progress/kendo-angular-common';`
1934
+ var NumpadKeys;
1935
+ (function (NumpadKeys) {
1936
+ NumpadKeys[NumpadKeys["Digit1"] = 97] = "Digit1";
1937
+ NumpadKeys[NumpadKeys["Digit2"] = 98] = "Digit2";
1938
+ NumpadKeys[NumpadKeys["Digit3"] = 99] = "Digit3";
1939
+ NumpadKeys[NumpadKeys["Digit4"] = 100] = "Digit4";
1940
+ })(NumpadKeys || (NumpadKeys = {}));
1662
1941
  /**
1663
1942
  * @hidden
1664
1943
  */
1665
- const DEFAULT_TREELIST_PANE_SETTINGS = Object.freeze({
1666
- collapsible: true,
1667
- collapsed: false
1668
- });
1944
+ const isArrowUpDownKey = (keyCode) => [
1945
+ Keys.ArrowUp,
1946
+ Keys.ArrowDown
1947
+ ].some(arrowKeyCode => keyCode === arrowKeyCode);
1669
1948
  /**
1670
1949
  * @hidden
1671
1950
  */
1672
- const DEFAULT_TIMELINE_PANE_SETTINGS = Object.freeze({
1673
- collapsible: true,
1674
- collapsed: false,
1675
- size: '50%',
1676
- resizable: true
1677
- });
1678
-
1679
- /**
1680
- * Represents a template that defines the whole content of the task component.
1681
- * To define the template, nest an `<ng-template>` tag
1682
- * with the `kendoGanttTaskTemplate` directive inside the `<kendo-gantt>` tag.
1683
- *
1684
- * The template context is set to the current data item. The following additional field is passed:
1685
- * - `elementWidth`&mdash;The current task wrapper element's calculated width in pixels based on its start and end date.
1686
- * Use it as an alias for a template variable by utilizing the `let-elementWidth="elementWidth"` syntax.
1687
- * Useful for calculations related to rendering custom elements representing the task progress.
1688
- *
1689
- * @example
1690
- * ```ts-preview
1691
- * _@Component({
1692
- * selector: 'my-app',
1693
- * template: `
1694
- * <kendo-gantt [kendoGanttHierarchyBinding]="data">
1695
- * <ng-template kendoGanttTaskTemplate let-dataItem let-elementWidth="elementWidth">
1696
- * {{ dataItem.title }} - {{ dataItem.completionRatio * 100 }}% complete
1697
- * </ng-template>
1698
- * </kendo-gantt>
1699
- * `
1700
- * })
1701
- * class AppComponent {
1702
- * public data: any[] = sampleTasks;
1703
- * }
1704
- * ```
1705
- */
1706
- let GanttTaskTemplateDirective = class GanttTaskTemplateDirective {
1707
- constructor(templateRef) {
1708
- this.templateRef = templateRef;
1709
- }
1710
- };
1711
- GanttTaskTemplateDirective = __decorate([
1712
- Directive({
1713
- selector: '[kendoGanttTaskTemplate]'
1714
- }),
1715
- __param(0, Optional()),
1716
- __metadata("design:paramtypes", [TemplateRef])
1717
- ], GanttTaskTemplateDirective);
1718
-
1719
- /**
1720
- * Represents a template that defines the whole content of the summary task component.
1721
- * To define the template, nest an `<ng-template>` tag
1722
- * with the `kendoGanttSummaryTaskTemplate` directive inside the `<kendo-gantt>` tag.
1723
- *
1724
- * The template context is set to the current data item. The following additional field is passed:
1725
- * - `elementWidth`&mdash;The current summary task wrapper element's calculated width in pixels based on its start and end date.
1726
- * Use it as an alias for a template variable by utilizing the `let-elementWidth="elementWidth"` syntax.
1727
- * Useful for calculations related to rendering custom elements representing the task progress.
1728
- *
1729
- * @example
1730
- * ```ts-preview
1731
- * _@Component({
1732
- * selector: 'my-app',
1733
- * template: `
1734
- * <kendo-gantt [kendoGanttHierarchyBinding]="data">
1735
- * <ng-template kendoGanttSummaryTaskTemplate let-dataItem let-elementWidth="elementWidth">
1736
- * <div style="color: white; font-size: 8px;">
1737
- * {{ dataItem.title }} - {{ dataItem.completionRatio * 100 }}% complete; width: {{ elementWidth }}
1738
- * </div>
1739
- * </ng-template>
1740
- * </kendo-gantt>
1741
- * `
1742
- * })
1743
- * class AppComponent {
1744
- * public data: any[] = sampleTasks;
1745
- * }
1746
- * ```
1747
- */
1748
- let GanttSummaryTaskTemplateDirective = class GanttSummaryTaskTemplateDirective {
1749
- constructor(templateRef) {
1750
- this.templateRef = templateRef;
1751
- }
1752
- };
1753
- GanttSummaryTaskTemplateDirective = __decorate([
1754
- Directive({
1755
- selector: '[kendoGanttSummaryTaskTemplate]'
1756
- }),
1757
- __param(0, Optional()),
1758
- __metadata("design:paramtypes", [TemplateRef])
1759
- ], GanttSummaryTaskTemplateDirective);
1760
-
1761
- /**
1762
- * Represents a template that defines the text content section of the task component.
1763
- * To define the template, nest an `<ng-template>` tag
1764
- * with the `kendoGanttTaskContentTemplate` directive inside the `<kendo-gantt>` tag.
1765
- *
1766
- * The template context is set to the current data item.
1767
- *
1768
- * @example
1769
- * ```ts-preview
1770
- * _@Component({
1771
- * selector: 'my-app',
1772
- * template: `
1773
- * <kendo-gantt [kendoGanttHierarchyBinding]="data">
1774
- * <ng-template kendoGanttTaskContentTemplate let-dataItem>
1775
- * {{ dataItem.title }} - {{ dataItem.completionRatio * 100 }}% complete
1776
- * </ng-template>
1777
- * </kendo-gantt>
1778
- * `
1779
- * })
1780
- * class AppComponent {
1781
- * public data: any[] = sampleTasks;
1782
- * }
1783
- * ```
1784
- */
1785
- let GanttTaskContentTemplateDirective = class GanttTaskContentTemplateDirective {
1786
- constructor(templateRef) {
1787
- this.templateRef = templateRef;
1788
- }
1789
- };
1790
- GanttTaskContentTemplateDirective = __decorate([
1791
- Directive({
1792
- selector: '[kendoGanttTaskContentTemplate]'
1793
- }),
1794
- __param(0, Optional()),
1795
- __metadata("design:paramtypes", [TemplateRef])
1796
- ], GanttTaskContentTemplateDirective);
1797
-
1951
+ const isNavigationKey = (keyCode) => [
1952
+ Keys.ArrowUp,
1953
+ Keys.ArrowDown,
1954
+ Keys.Home,
1955
+ Keys.End
1956
+ ].some(navigationKeyCode => keyCode === navigationKeyCode);
1798
1957
  /**
1799
- * Represents the toolbar template of the Gantt.
1800
- *
1801
- * The template context has the following field:
1802
- * - `position`&mdash;The position at which the toolbar template is rendered. The possible values are `'top'` and `'bottom'`.
1803
- *
1804
- * @example
1805
- * ```ts-preview
1806
- *
1807
- * _@Component({
1808
- * selector: 'my-app',
1809
- * template: `
1810
- * <div class="example-config">
1811
- * <input type="radio" id="top" name="position" class="k-radio" value="top" checked (click)="positionChange($event)"/>
1812
- * <label class="k-radio-label" for="top">Top</label><br/>
1813
- * <input type="radio" id="bottom" name="position" class="k-radio" value="bottom" (click)="positionChange($event)"/>
1814
- * <label class="k-radio-label" for="bottom">Bottom</label><br/>
1815
- * <input type="radio" id="both" name="position" value="both" class="k-radio" (click)="positionChange($event)"/>
1816
- * <label class="k-radio-label" for="both">Both</label><br/>
1817
- * </div>
1818
- * <kendo-gantt [[kendoGanttHierarchyBinding]="data"]="data" style="height: 400px">
1819
- * <ng-template kendoGanttToolbarTemplate [position]="position" let-position="position">
1820
- * <button (click)="onClick()" class="k-button">Custom action</button>
1821
- * </ng-template>
1822
- * </kendo-gantt>
1823
- * `
1824
- * })
1825
- *
1826
- * class AppComponent {
1827
- * public position: 'top' | 'bottom' | 'both' = 'top';
1828
- *
1829
- * public data = [{
1830
- * id: 7,
1831
- * title: "Software validation, research and implementation",
1832
- * orderId: 0,
1833
- * start: new Date("2014-06-02T00:00:00.000Z"),
1834
- * end: new Date("2014-07-12T00:00:00.000Z"),
1835
- * completionRatio: 0.45708333333333334,
1836
- * isExpanded: true,
1837
- * children: [{
1838
- * id: 11,
1839
- * title: "Research",
1840
- * orderId: 1,
1841
- * start: new Date("2014-06-02T00:00:00.000Z"),
1842
- * end: new Date("2014-06-07T00:00:00.000Z"),
1843
- * completionRatio: 0.5766666666666667,
1844
- * isExpanded: true,
1845
- * children: [{
1846
- * id: 19,
1847
- * title: "Validation with Customers",
1848
- * orderId: 0,
1849
- * start: new Date("2014-06-02T00:00:00.000Z"),
1850
- * end: new Date("2014-06-04T00:00:00.000Z"),
1851
- * completionRatio: 0.25,
1852
- * isExpanded: true
1853
- * },
1854
- * {
1855
- * id: 20,
1856
- * title: "Market Research",
1857
- * orderId: 1,
1858
- * start: new Date("2014-06-02T00:00:00.000Z"),
1859
- * end: new Date("2014-06-03T02:00:00.000Z"),
1860
- * completionRatio: 0.82,
1861
- * isExpanded: true
1862
- * },
1863
- * {
1864
- * id: 39,
1865
- * title: "Functional and Technical Specification",
1866
- * orderId: 2,
1867
- * start: new Date("2014-06-04T00:00:00.000Z"),
1868
- * end: new Date("2014-06-07T00:00:00.000Z"),
1869
- * completionRatio: 0.66,
1870
- * isExpanded: true
1871
- * }]
1872
- * }]
1873
- * };
1874
- *
1875
- * public positionChange({ target }): void {
1876
- * this.position = target.value;
1877
- * }
1878
- *
1879
- * public onClick(): void {
1880
- * console.log("button was clicked");
1881
- * }
1882
- * }
1883
- *
1884
- * ```
1885
- */
1886
- let ToolbarTemplateDirective = class ToolbarTemplateDirective {
1887
- constructor(templateRef) {
1888
- this.templateRef = templateRef;
1889
- this._position = "top";
1890
- }
1891
- /**
1892
- * Defines the Gantt Toolbar that will use this template.
1893
- *
1894
- * The possible values are:
1895
- * - `top`&mdash;The template will be rendered in the top toolbar (if present) only.
1896
- * - `bottom`&mdash;The template will be rendered in the bottom toolbar (if present) only.
1897
- * - `both`&mdash;The template will be rendered in both toolbars (if present).
1898
- */
1899
- set position(position) {
1900
- this._position = position;
1901
- }
1902
- get position() {
1903
- return this._position;
1958
+ * @hidden
1959
+ */
1960
+ const isExpandCollapseKey = (keyCode, altKey) => {
1961
+ return altKey && [
1962
+ Keys.ArrowLeft,
1963
+ Keys.ArrowRight
1964
+ ].some(navigationKeyCode => keyCode === navigationKeyCode);
1965
+ };
1966
+ /**
1967
+ * @hidden
1968
+ */
1969
+ const isViewDigitKey = (keyCode) => [
1970
+ Keys.Digit1,
1971
+ NumpadKeys.Digit1,
1972
+ Keys.Digit2,
1973
+ NumpadKeys.Digit2,
1974
+ Keys.Digit3,
1975
+ NumpadKeys.Digit3,
1976
+ Keys.Digit4,
1977
+ NumpadKeys.Digit4
1978
+ ].some(digitKeyCode => keyCode === digitKeyCode);
1979
+ /**
1980
+ * @hidden
1981
+ *
1982
+ * Returns the corresponding view index for the pressed digit key (Digit 1 => 0, Digit 2 => 1, etc.).
1983
+ */
1984
+ const getIndexFromViewDigitKeyCode = (keyCode) => {
1985
+ switch (keyCode) {
1986
+ case NumpadKeys.Digit1:
1987
+ case Keys.Digit1: return 0;
1988
+ case NumpadKeys.Digit2:
1989
+ case Keys.Digit2: return 1;
1990
+ case NumpadKeys.Digit3:
1991
+ case Keys.Digit3: return 2;
1992
+ case NumpadKeys.Digit4:
1993
+ case Keys.Digit4: return 3;
1994
+ default: return null;
1904
1995
  }
1905
1996
  };
1906
- __decorate([
1907
- Input('position'),
1908
- __metadata("design:type", String),
1909
- __metadata("design:paramtypes", [String])
1910
- ], ToolbarTemplateDirective.prototype, "position", null);
1911
- ToolbarTemplateDirective = __decorate([
1912
- Directive({
1913
- selector: '[kendoGanttToolbarTemplate]'
1914
- }),
1915
- __param(0, Optional()),
1916
- __metadata("design:paramtypes", [TemplateRef])
1917
- ], ToolbarTemplateDirective);
1918
1997
 
1919
1998
  /**
1920
1999
  * @hidden
1921
2000
  */
1922
- let GanttTimelineComponent = class GanttTimelineComponent {
1923
- constructor(scrollSyncService, dependencyDomService, renderer, zone) {
1924
- this.scrollSyncService = scrollSyncService;
1925
- this.dependencyDomService = dependencyDomService;
1926
- this.renderer = renderer;
2001
+ let NavigationService = class NavigationService {
2002
+ constructor(zone, renderer, scrollSyncService) {
1927
2003
  this.zone = zone;
1928
- this.hostClass = true;
1929
- this.dependencies = [];
1930
- // as all drag-and-drop operations are on the timeline container, use a single draggable instance
1931
- this.timelineContainerPress = new EventEmitter();
1932
- this.timelineContainerDrag = new EventEmitter();
1933
- this.timelineContainerRelease = new EventEmitter();
1934
- this.subscriptions = new Subscription();
1935
- this.subscriptions.add(
1936
- // task changes indicates change in row content, number, height, etc.
1937
- this.dependencyDomService.taskChanges
1938
- .pipe(filter(args => isPresent(args.timelineRow)), switchMap(args => this.zone.onStable.pipe(take(1), map(() => args))) // ensure the content is rendered
1939
- )
1940
- .subscribe(({ timelineRow }) => {
1941
- const timelineRowHeight = isDocumentAvailable() ? timelineRow.getBoundingClientRect().height : 0;
1942
- this.renderer.setStyle(this.timelineColumns.nativeElement, 'height', `${(this.rows || []).length * timelineRowHeight}px`);
1943
- }));
2004
+ this.renderer = renderer;
2005
+ this.scrollSyncService = scrollSyncService;
2006
+ /**
2007
+ * Notifies when the tasks' focused and interactive (tabindex) state has changed.
2008
+ *
2009
+ * All tasks are rendered with tabindex="-1".
2010
+ * When one is clicked, or when some navigation key keyboard key is pressed, it should be focused, assigned the focus class, and its tabindex updated to 0.
2011
+ * All other tasks should get -1 tabindex and have the focus class removed from them.
2012
+ */
2013
+ this.taskStatusChanges = new Subject();
2014
+ /**
2015
+ * Keeps track of whether the Timeline part is focused.
2016
+ * Used when the index of the task elements change (tasks are changed, pushed to, spliced from, etc.)
2017
+ * and their status should be updated accordingly.
2018
+ */
2019
+ this.isTimelineFocused = false;
2020
+ /**
2021
+ * Keeps track of which part has last been focused.
2022
+ * Used when calling `gantt.focus()` to determine which part of the component should receive focus.
2023
+ */
2024
+ this.treeListLastActive = false;
2025
+ /**
2026
+ * Keeps track of which part has last been focused.
2027
+ * Used when calling `gantt.focus()` to determine which part of the component should receive focus.
2028
+ */
2029
+ this.timelineLastActive = false;
2030
+ this._enabled = false;
2031
+ this._activeTimelineIndex = 0;
2032
+ this._activeTreeListCell = { rowIndex: 0, colIndex: 0 };
1944
2033
  }
1945
2034
  /**
1946
- * Specifies whether the draggable will attach or detach its pointer event listeners.
2035
+ * Specifies whether navigation is enabled.
1947
2036
  */
1948
- get draggableEnabled() {
1949
- return this.renderDependencyDragClues;
2037
+ get enabled() {
2038
+ return this._enabled;
1950
2039
  }
1951
- ngAfterViewInit() {
1952
- const timelineHeader = this.timelineHeaderWrap.nativeElement;
1953
- const rightContainer = this.timelineContent.nativeElement;
1954
- this.scrollSyncService.registerElement(rightContainer, 'timeline');
1955
- this.scrollSyncService.registerElement(timelineHeader, 'header');
1956
- this.dependencyDomService.registerContentContainer(this.tasksContainer.nativeElement);
2040
+ /**
2041
+ * Used to retrieve read-only data about the currently active task.
2042
+ */
2043
+ get activeTask() {
2044
+ return {
2045
+ activeIndex: this.activeTimelineIndex,
2046
+ isFocused: this.isTimelineFocused
2047
+ };
2048
+ }
2049
+ /**
2050
+ * Persists the expected TreeList focused cell coords.
2051
+ * When the tasks in the Timeline are navigated through, the expected TreeList focus target should also change,
2052
+ * in order to allow back-tabbing from the Timeline to the same row in the TreeList.
2053
+ */
2054
+ set activeTreeListCell(cell) {
2055
+ this._activeTreeListCell = cell;
2056
+ }
2057
+ get activeTreeListCell() {
2058
+ const firstAvailableIndex = 0;
2059
+ const lastAvailableRowIndex = this.treeListHeaderRowsCount + this.gantt.treeList.view.data.length - 1;
2060
+ const rowIndex = fitToRange(this._activeTreeListCell.rowIndex, firstAvailableIndex, lastAvailableRowIndex);
2061
+ const lastAvailableColIndex = this.gantt.columns.length;
2062
+ const colIndex = fitToRange(this._activeTreeListCell.colIndex, firstAvailableIndex, lastAvailableColIndex);
2063
+ return { rowIndex, colIndex };
2064
+ }
2065
+ /**
2066
+ * Persists the expected Timeline focused task index.
2067
+ * When the cells in the TreeList are navigated through, the expected Timeline focus target should also change,
2068
+ * in order to allow tabbing from the TreeList to the same row in the Timeline.
2069
+ */
2070
+ set activeTimelineIndex(index) {
2071
+ this._activeTimelineIndex = index;
2072
+ }
2073
+ get activeTimelineIndex() {
2074
+ const firstAvailableIndex = 0;
2075
+ const lastAvailableIndex = this.gantt.treeList.view.data.length - 1;
2076
+ return fitToRange(this._activeTimelineIndex, firstAvailableIndex, lastAvailableIndex);
2077
+ }
2078
+ /**
2079
+ * The TreeList row index takes into account the header and filter rows.
2080
+ * Used when translating Timeline task indices to TreeList row indices.
2081
+ */
2082
+ get treeListHeaderRowsCount() {
2083
+ // captures nested group header rows + filter row if we start supporting it at some point
2084
+ return this.treeListElement.querySelectorAll('.k-grid-header tr').length;
2085
+ }
2086
+ initialize({ gantt, host, treeListElement, timelineElement }) {
2087
+ // no private property setters in TypeScript, so use a getter and a poorly named private prop for this value
2088
+ this._enabled = true;
2089
+ this.gantt = gantt;
2090
+ this.host = host;
2091
+ this.treeListElement = treeListElement;
2092
+ this.timelineElement = timelineElement;
2093
+ // TODO: fix in the splitter package and remove
2094
+ // move the splitbar HTML element between the two panes to keep the visial tabbing order in tact
2095
+ const splitbar = this.host.querySelector('.k-splitbar');
2096
+ if (isPresent(splitbar) && isPresent(splitbar.previousElementSibling) && isPresent(splitbar.after)) {
2097
+ splitbar.after(splitbar.previousElementSibling);
2098
+ }
2099
+ this.zone.runOutsideAngular(() => {
2100
+ this.eventListenerDisposers = [
2101
+ this.renderer.listen(this.host, 'keydown', this.handleKeydown.bind(this)),
2102
+ this.renderer.listen(this.treeListElement, 'mousedown', this.focusTreeList.bind(this)),
2103
+ this.renderer.listen(this.treeListElement, 'focusin', this.handleTreeListFocusIn.bind(this)),
2104
+ this.renderer.listen(this.timelineElement, 'mousedown', this.handleTimelineMousedown.bind(this)),
2105
+ this.renderer.listen(this.timelineElement, 'focusin', this.handleTimelineFocusIn.bind(this)),
2106
+ this.renderer.listen(this.timelineElement, 'focusout', this.handleTimelineFocusOut.bind(this))
2107
+ ];
2108
+ });
1957
2109
  }
1958
2110
  ngOnDestroy() {
1959
- this.subscriptions.unsubscribe();
2111
+ if (isPresent(this.eventListenerDisposers)) {
2112
+ this.eventListenerDisposers.forEach(removeListener => removeListener());
2113
+ this.eventListenerDisposers = null;
2114
+ }
2115
+ this.gantt = null;
2116
+ this.host = null;
2117
+ this.treeListElement = null;
2118
+ this.timelineElement = null;
1960
2119
  }
1961
- isNonWorking(item) {
1962
- return item.hasOwnProperty('isWorking') && !item.isWorking;
2120
+ /**
2121
+ * Focuses either the last active TreeList cell, or the last active Timeline task,
2122
+ * dependening on which of the two last held focus.
2123
+ *
2124
+ * Focuses the first TreeList cell by default.
2125
+ */
2126
+ focusLastActiveItem() {
2127
+ if (this.gantt.data.length === 0 || (!this.treeListLastActive && !this.timelineLastActive)) {
2128
+ this.focusCell(0, 0);
2129
+ }
2130
+ else if (this.treeListLastActive) {
2131
+ const { rowIndex, colIndex } = this.activeTreeListCell;
2132
+ this.gantt.treeList.focusCell(rowIndex, colIndex);
2133
+ }
2134
+ else if (this.timelineLastActive) {
2135
+ this.focusTask(this.activeTimelineIndex);
2136
+ }
1963
2137
  }
1964
- };
1965
- __decorate([
1966
- ViewChild('timelineContent', { static: true }),
1967
- __metadata("design:type", ElementRef)
1968
- ], GanttTimelineComponent.prototype, "timelineContent", void 0);
1969
- __decorate([
1970
- ViewChild('timelineColumns', { static: true }),
1971
- __metadata("design:type", ElementRef)
1972
- ], GanttTimelineComponent.prototype, "timelineColumns", void 0);
1973
- __decorate([
1974
- ViewChild('timelineHeaderWrap', { static: true }),
1975
- __metadata("design:type", ElementRef)
1976
- ], GanttTimelineComponent.prototype, "timelineHeaderWrap", void 0);
1977
- __decorate([
1978
- ViewChild('tasksContainer', { static: true }),
1979
- __metadata("design:type", ElementRef)
1980
- ], GanttTimelineComponent.prototype, "tasksContainer", void 0);
1981
- __decorate([
1982
- ViewChild('dragPopupContainer', { static: false, read: ViewContainerRef }),
1983
- __metadata("design:type", ViewContainerRef)
1984
- ], GanttTimelineComponent.prototype, "dragPopupContainer", void 0);
1985
- __decorate([
1986
- ViewChild('dependencyDragCreatePolyline', { static: false }),
1987
- __metadata("design:type", ElementRef)
1988
- ], GanttTimelineComponent.prototype, "dependencyDragCreatePolyline", void 0);
1989
- __decorate([
1990
- HostBinding('class.k-gantt-timeline'),
1991
- __metadata("design:type", Boolean)
1992
- ], GanttTimelineComponent.prototype, "hostClass", void 0);
1993
- __decorate([
1994
- Input(),
1995
- __metadata("design:type", Array)
1996
- ], GanttTimelineComponent.prototype, "rows", void 0);
1997
- __decorate([
1998
- Input(),
1999
- __metadata("design:type", Array)
2000
- ], GanttTimelineComponent.prototype, "slots", void 0);
2001
- __decorate([
2002
- Input(),
2003
- __metadata("design:type", Array)
2004
- ], GanttTimelineComponent.prototype, "groupSlots", void 0);
2005
- __decorate([
2006
- Input(),
2007
- __metadata("design:type", Number)
2008
- ], GanttTimelineComponent.prototype, "tableWidth", void 0);
2009
- __decorate([
2010
- Input(),
2011
- __metadata("design:type", String)
2012
- ], GanttTimelineComponent.prototype, "activeView", void 0);
2013
- __decorate([
2014
- Input(),
2015
- __metadata("design:type", TemplateRef)
2016
- ], GanttTimelineComponent.prototype, "taskContentTemplate", void 0);
2017
- __decorate([
2018
- Input(),
2019
- __metadata("design:type", TemplateRef)
2020
- ], GanttTimelineComponent.prototype, "taskTemplate", void 0);
2021
- __decorate([
2022
- Input(),
2023
- __metadata("design:type", TemplateRef)
2024
- ], GanttTimelineComponent.prototype, "summaryTaskTemplate", void 0);
2025
- __decorate([
2026
- Input(),
2027
- __metadata("design:type", Function)
2028
- ], GanttTimelineComponent.prototype, "taskClass", void 0);
2029
- __decorate([
2030
- Input(),
2031
- __metadata("design:type", Function)
2032
- ], GanttTimelineComponent.prototype, "isTaskSelected", void 0);
2033
- __decorate([
2034
- Input(),
2035
- __metadata("design:type", Boolean)
2036
- ], GanttTimelineComponent.prototype, "renderDependencyDragClues", void 0);
2037
- __decorate([
2038
- Input(),
2039
- __metadata("design:type", Object)
2040
- ], GanttTimelineComponent.prototype, "dragScrollSettings", void 0);
2041
- __decorate([
2042
- Input(),
2043
- __metadata("design:type", Function)
2044
- ], GanttTimelineComponent.prototype, "hasChildren", void 0);
2045
- __decorate([
2046
- Input(),
2047
- __metadata("design:type", Array)
2048
- ], GanttTimelineComponent.prototype, "dependencies", void 0);
2049
- __decorate([
2050
- Output(),
2051
- __metadata("design:type", EventEmitter)
2052
- ], GanttTimelineComponent.prototype, "timelineContainerPress", void 0);
2053
- __decorate([
2054
- Output(),
2055
- __metadata("design:type", EventEmitter)
2056
- ], GanttTimelineComponent.prototype, "timelineContainerDrag", void 0);
2057
- __decorate([
2058
- Output(),
2059
- __metadata("design:type", EventEmitter)
2060
- ], GanttTimelineComponent.prototype, "timelineContainerRelease", void 0);
2061
- GanttTimelineComponent = __decorate([
2062
- Component({
2063
- selector: 'kendo-gantt-timeline',
2064
- template: `
2065
- <div class="k-timeline k-grid k-widget">
2066
- <div class="k-grid-header">
2067
- <div #timelineHeaderWrap class="k-grid-header-wrap">
2068
- <table
2069
- role="presentation"
2070
- [style.width.px]="tableWidth"
2071
- >
2072
- <tbody
2073
- kendoGanttHeaderTableBody
2074
- [groupSlots]="groupSlots"
2075
- [slots]="slots">
2076
- </tbody>
2077
- </table>
2078
- </div>
2079
- </div>
2080
- <div
2081
- #timelineContent
2082
- class="k-grid-content"
2083
- kendoGanttTimelineScrollable
2084
- [scrollSettings]="dragScrollSettings"
2085
- kendoDraggable
2086
- [enableDrag]="draggableEnabled"
2087
- (kendoPress)="timelineContainerPress.emit($event)"
2088
- (kendoDrag)="timelineContainerDrag.emit($event)"
2089
- (kendoRelease)="timelineContainerRelease.emit($event)"
2090
- >
2091
- <div class="k-gantt-tables">
2092
- <table
2093
- class="k-gantt-rows"
2094
- [style.width.px]="tableWidth"
2095
- role="presentation"
2096
- >
2097
- <tbody>
2098
- <tr *ngFor="let item of rows; let i = index;"
2099
- [class.k-alt]="i % 2"
2100
- >
2101
- <td></td>
2102
- </tr>
2103
- </tbody>
2104
- </table>
2138
+ /**
2139
+ * Focuses the targeted TreeList cell regardless of the last peresisted target.
2140
+ */
2141
+ focusCell(rowIndex, colIndex) {
2142
+ this.activeTreeListCell = { rowIndex, colIndex };
2143
+ this.activeTimelineIndex = rowIndex - this.treeListHeaderRowsCount;
2144
+ this.gantt.treeList.focusCell(this.activeTreeListCell.rowIndex, this.activeTreeListCell.colIndex);
2145
+ }
2146
+ /**
2147
+ * Focuses the targeted Timeline task regardless of the last peresisted target.
2148
+ */
2149
+ focusTask(index) {
2150
+ this.activeTimelineIndex = index;
2151
+ this.isTimelineFocused = true;
2152
+ this.activeTreeListCell = {
2153
+ rowIndex: index + this.treeListHeaderRowsCount,
2154
+ colIndex: this.activeTreeListCell.colIndex
2155
+ };
2156
+ this.notifyTaskStatusChange();
2157
+ }
2158
+ /**
2159
+ * Updates the focus target flags and notifies the active task to update its focused state.
2160
+ */
2161
+ handleTimelineFocusIn({ target }) {
2162
+ this.treeListLastActive = false;
2163
+ this.timelineLastActive = true;
2164
+ this.isTimelineFocused = true;
2165
+ if (isTask(target, this.timelineElement)) {
2166
+ this.notifyTaskStatusChange();
2167
+ }
2168
+ }
2169
+ /**
2170
+ * Updates the timeline focus state flag and notifies the active task to update its focused state.
2171
+ */
2172
+ handleTimelineFocusOut({ relatedTarget }) {
2173
+ this.isTimelineFocused = this.timelineElement.contains(relatedTarget);
2174
+ // update the task element only if the new focus target is not in the Timeline - focus change between tasks is handled in the focusin handler
2175
+ if (!isTask(relatedTarget, this.timelineElement)) {
2176
+ this.notifyTaskStatusChange();
2177
+ }
2178
+ }
2179
+ /**
2180
+ * Updates the focus target flags and corrects the TreeList focus target if needed.
2181
+ * As the TreeList will keep its last focused cell with tabindex="0",
2182
+ * this methods forcefully focuses the correct cell,
2183
+ * when navigating in the Timeline has updated the expected TreeList focus target.
2184
+ */
2185
+ handleTreeListFocusIn(event) {
2186
+ this.treeListLastActive = true;
2187
+ this.timelineLastActive = false;
2188
+ // if the previous focus target was in the TreeList, rely on its component navigation and just record the focused item index
2189
+ if (this.treeListElement.contains(event.relatedTarget)) {
2190
+ const { colIndex, rowIndex } = this.gantt.treeList.activeCell;
2191
+ this.activeTreeListCell = { colIndex, rowIndex };
2192
+ }
2193
+ else {
2194
+ // if the previous focus target was outside the TreeList, ensure the expected focus coords are used
2195
+ const { rowIndex, colIndex } = this.activeTreeListCell;
2196
+ this.gantt.treeList.focusCell(rowIndex, colIndex); // activates the target cell even if it has tabindex="-1"
2197
+ }
2198
+ this.activeTimelineIndex = this.gantt.treeList.activeCell.dataRowIndex;
2199
+ this.notifyTaskStatusChange();
2200
+ if (this.gantt.treeList.activeCell.dataRowIndex >= 0) {
2201
+ this.scrollHorizontallyToTask(this.activeTimelineIndex);
2202
+ this.scrollSyncService.syncScrollTop('treelist', 'timeline');
2203
+ }
2204
+ }
2205
+ handleKeydown(event) {
2206
+ const { keyCode, target, altKey } = event;
2207
+ const isTimelineActive = this.timelineElement.contains(target);
2208
+ if (isTimelineActive) {
2209
+ if (isArrowUpDownKey(keyCode)) {
2210
+ const direction = keyCode === Keys.ArrowUp ? -1 : 1;
2211
+ this.activeTimelineIndex = this.activeTimelineIndex + direction;
2212
+ this.activeTreeListCell = {
2213
+ rowIndex: this.activeTimelineIndex + this.treeListHeaderRowsCount,
2214
+ colIndex: this.activeTreeListCell.colIndex
2215
+ };
2216
+ }
2217
+ else if (keyCode === Keys.Home) {
2218
+ this.activeTimelineIndex = 0;
2219
+ this.activeTreeListCell = {
2220
+ rowIndex: this.activeTimelineIndex + this.treeListHeaderRowsCount,
2221
+ colIndex: this.activeTreeListCell.colIndex
2222
+ };
2223
+ }
2224
+ else if (keyCode === Keys.End) {
2225
+ const lastAvailableIndex = this.gantt.treeList.view.data.length - 1;
2226
+ this.activeTimelineIndex = lastAvailableIndex;
2227
+ this.activeTreeListCell = {
2228
+ rowIndex: this.activeTimelineIndex + this.treeListHeaderRowsCount,
2229
+ colIndex: this.activeTreeListCell.colIndex
2230
+ };
2231
+ }
2232
+ if (isNavigationKey(keyCode)) {
2233
+ this.scrollHorizontallyToTask(this.activeTimelineIndex);
2234
+ this.scrollSyncService.syncScrollTop('timeline', 'treelist');
2235
+ this.notifyTaskStatusChange();
2236
+ event.preventDefault();
2237
+ }
2238
+ if (keyCode === Keys.Space && hasObservers(this.gantt.selectionChange)) {
2239
+ const task = this.gantt.renderedTreeListItems[this.activeTimelineIndex];
2240
+ const selectionAction = this.gantt.getSelectionAction(event, task);
2241
+ if (isPresent(task) && !this.gantt.isSameSelection(selectionAction, task)) {
2242
+ this.zone.run(() => this.gantt.notifySelectionChange(task, selectionAction));
2243
+ }
2244
+ event.preventDefault();
2245
+ }
2246
+ if (keyCode === Keys.Enter && hasObservers(this.gantt.taskClick)) {
2247
+ const task = this.gantt.renderedTreeListItems[this.activeTimelineIndex];
2248
+ if (isPresent(task)) {
2249
+ this.zone.run(() => this.gantt.notifyTaskClick(event, task, this.activeTimelineIndex));
2250
+ }
2251
+ event.preventDefault();
2252
+ }
2253
+ if (isExpandCollapseKey(keyCode, altKey)) {
2254
+ const task = this.gantt.renderedTreeListItems[this.activeTimelineIndex];
2255
+ if (isPresent(task) && this.gantt.hasChildren(task)) {
2256
+ const shouldExpand = keyCode === Keys.ArrowRight;
2257
+ const isExpanded = this.gantt.isExpanded(task);
2258
+ const sameState = shouldExpand === isExpanded;
2259
+ if (!sameState) {
2260
+ this.zone.run(() => {
2261
+ const expandEvent = { dataItem: task };
2262
+ // order is not arbitrary
2263
+ // the TreeList emits the individual events first, then the combined `expandStateChange` event
2264
+ const individualEmitter = shouldExpand ? this.gantt.rowExpand : this.gantt.rowCollapse;
2265
+ individualEmitter.emit(expandEvent);
2266
+ this.gantt.expandStateChange.emit(Object.assign({}, expandEvent, { expand: shouldExpand }));
2267
+ this.gantt.updateView();
2268
+ this.scrollHorizontallyToTask(this.activeTimelineIndex);
2269
+ });
2270
+ }
2271
+ }
2272
+ event.preventDefault();
2273
+ }
2274
+ }
2275
+ const isTreeListActive = this.treeListElement.contains(target);
2276
+ if (keyCode === Keys.Delete && (isTimelineActive || isTreeListActive) && hasObservers(this.gantt.taskDelete)) {
2277
+ const taskIndex = isTreeListActive ?
2278
+ this.gantt.treeList.activeCell.dataRowIndex :
2279
+ this.activeTimelineIndex;
2280
+ const task = this.gantt.renderedTreeListItems[taskIndex];
2281
+ if (isPresent(task)) {
2282
+ this.zone.run(() => this.gantt.notifyTaskDelete(task));
2283
+ }
2284
+ }
2285
+ if (isViewDigitKey(keyCode) && !isToolbar(target, this.host) && !this.gantt.isInEditMode) {
2286
+ const targetViewIndex = getIndexFromViewDigitKeyCode(keyCode);
2287
+ const availableViews = this.gantt.views.toArray();
2288
+ const targetView = availableViews[targetViewIndex];
2289
+ if (isPresent(targetView) && targetView.type !== this.gantt.activeView) {
2290
+ this.zone.run(() => this.gantt.changeActiveView(targetView.type));
2291
+ }
2292
+ }
2293
+ }
2294
+ /**
2295
+ * Filters for task mousedown in the Timeline.
2296
+ */
2297
+ handleTimelineMousedown({ target }) {
2298
+ if (isTask(target, this.host) && !isClearButton(target, this.host)) {
2299
+ const taskIndex = getClosestTaskIndex(target, this.host);
2300
+ this.focusTask(taskIndex);
2301
+ }
2302
+ }
2303
+ /**
2304
+ * Scrolls horizontally to the beginning of the target task if the beginning of its content is not in the viewport.
2305
+ */
2306
+ scrollHorizontallyToTask(index) {
2307
+ const task = this.timelineElement.querySelectorAll('.k-task-wrap').item(index);
2308
+ if (!isPresent(task)) {
2309
+ return;
2310
+ }
2311
+ // scroll horizontally to the item if less than 200px from the beginning of its content are visible
2312
+ const targetVisibleWidth = 200;
2313
+ const isScrollBeforeTask = (this.timelineElement.clientWidth + this.timelineElement.scrollLeft) < (task.offsetLeft + targetVisibleWidth);
2314
+ const isScrollAfterTask = this.timelineElement.scrollLeft > task.offsetLeft;
2315
+ if (isScrollBeforeTask || isScrollAfterTask) {
2316
+ this.timelineElement.scrollLeft = task.offsetLeft;
2317
+ }
2318
+ }
2319
+ /**
2320
+ * Focus the TreeList on TreeList mousedown.
2321
+ * A nasty hack to trick `handleTreeListFocusIn` into regarding the previous focus target as again the TreeList.
2322
+ * Otherwise cell clicks are wrongly overwritten in `handleTreeListFocusIn` and the click focus target is not respected.
2323
+ */
2324
+ focusTreeList() {
2325
+ this.gantt.treeList.focus();
2326
+ }
2327
+ /**
2328
+ * Fires the `taskStatusChanges` event with active and focused status retrieved from
2329
+ * `this.activeTimelineIndex` and `this.isTimelineFocused`.
2330
+ */
2331
+ notifyTaskStatusChange() {
2332
+ this.taskStatusChanges.next(this.activeTask);
2333
+ }
2334
+ };
2335
+ NavigationService = __decorate([
2336
+ Injectable(),
2337
+ __metadata("design:paramtypes", [NgZone,
2338
+ Renderer2,
2339
+ ScrollSyncService])
2340
+ ], NavigationService);
2105
2341
 
2106
- <table
2107
- #timelineColumns
2108
- class="k-gantt-columns"
2109
- role="presentation"
2110
- [style.width.px]="tableWidth"
2111
- >
2112
- <colgroup>
2113
- <col *ngFor="let item of slots">
2114
- </colgroup>
2342
+ /**
2343
+ * @hidden
2344
+ */
2345
+ const DEFAULT_TREELIST_PANE_SETTINGS = Object.freeze({
2346
+ collapsible: true,
2347
+ collapsed: false
2348
+ });
2349
+ /**
2350
+ * @hidden
2351
+ */
2352
+ const DEFAULT_TIMELINE_PANE_SETTINGS = Object.freeze({
2353
+ collapsible: true,
2354
+ collapsed: false,
2355
+ size: '50%',
2356
+ resizable: true
2357
+ });
2115
2358
 
2116
- <tbody>
2117
- <tr>
2118
- <td *ngFor="let item of slots"
2119
- [class.k-nonwork-hour]="isNonWorking(item)"
2120
- >
2121
- </td>
2122
- </tr>
2123
- </tbody>
2124
- </table>
2359
+ /**
2360
+ * Represents a template that defines the whole content of the task component.
2361
+ * To define the template, nest an `<ng-template>` tag
2362
+ * with the `kendoGanttTaskTemplate` directive inside the `<kendo-gantt>` tag.
2363
+ *
2364
+ * The template context is set to the current data item. The following additional field is passed:
2365
+ * - `elementWidth`&mdash;The current task wrapper element's calculated width in pixels based on its start and end date.
2366
+ * Use it as an alias for a template variable by utilizing the `let-elementWidth="elementWidth"` syntax.
2367
+ * Useful for calculations related to rendering custom elements representing the task progress.
2368
+ *
2369
+ * @example
2370
+ * ```ts-preview
2371
+ * _@Component({
2372
+ * selector: 'my-app',
2373
+ * template: `
2374
+ * <kendo-gantt [kendoGanttHierarchyBinding]="data">
2375
+ * <ng-template kendoGanttTaskTemplate let-dataItem let-elementWidth="elementWidth">
2376
+ * {{ dataItem.title }} - {{ dataItem.completionRatio * 100 }}% complete
2377
+ * </ng-template>
2378
+ * </kendo-gantt>
2379
+ * `
2380
+ * })
2381
+ * class AppComponent {
2382
+ * public data: any[] = sampleTasks;
2383
+ * }
2384
+ * ```
2385
+ */
2386
+ let GanttTaskTemplateDirective = class GanttTaskTemplateDirective {
2387
+ constructor(templateRef) {
2388
+ this.templateRef = templateRef;
2389
+ }
2390
+ };
2391
+ GanttTaskTemplateDirective = __decorate([
2392
+ Directive({
2393
+ selector: '[kendoGanttTaskTemplate]'
2394
+ }),
2395
+ __param(0, Optional()),
2396
+ __metadata("design:paramtypes", [TemplateRef])
2397
+ ], GanttTaskTemplateDirective);
2125
2398
 
2126
- <table
2127
- #tasksContainer
2128
- class="k-gantt-tasks"
2129
- role="presentation"
2130
- style="border-collapse: collapse;"
2131
- [style.width.px]="tableWidth"
2132
- >
2133
- <tbody
2134
- kendoGanttTasksTableBody
2135
- [rows]="rows"
2136
- [activeView]="activeView"
2137
- [taskContentTemplate]="taskContentTemplate"
2138
- [taskTemplate]="taskTemplate"
2139
- [summaryTaskTemplate]="summaryTaskTemplate"
2140
- [taskClass]="taskClass"
2141
- [hasChildren]="hasChildren"
2142
- [isTaskSelected]="isTaskSelected"
2143
- [renderDependencyDragClues]="renderDependencyDragClues"
2144
- >
2145
- </tbody>
2146
- </table>
2147
- </div>
2148
- <svg class="k-gantt-dependencies-svg">
2149
- <polyline
2150
- *ngFor="let dependency of dependencies"
2151
- kendoGanttDependency
2152
- [dependency]="dependency"
2153
- />
2154
- <polyline #dependencyDragCreatePolyline />
2155
- </svg>
2399
+ /**
2400
+ * Represents a template that defines the whole content of the summary task component.
2401
+ * To define the template, nest an `<ng-template>` tag
2402
+ * with the `kendoGanttSummaryTaskTemplate` directive inside the `<kendo-gantt>` tag.
2403
+ *
2404
+ * The template context is set to the current data item. The following additional field is passed:
2405
+ * - `elementWidth`&mdash;The current summary task wrapper element's calculated width in pixels based on its start and end date.
2406
+ * Use it as an alias for a template variable by utilizing the `let-elementWidth="elementWidth"` syntax.
2407
+ * Useful for calculations related to rendering custom elements representing the task progress.
2408
+ *
2409
+ * @example
2410
+ * ```ts-preview
2411
+ * _@Component({
2412
+ * selector: 'my-app',
2413
+ * template: `
2414
+ * <kendo-gantt [kendoGanttHierarchyBinding]="data">
2415
+ * <ng-template kendoGanttSummaryTaskTemplate let-dataItem let-elementWidth="elementWidth">
2416
+ * <div style="color: white; font-size: 8px;">
2417
+ * {{ dataItem.title }} - {{ dataItem.completionRatio * 100 }}% complete; width: {{ elementWidth }}
2418
+ * </div>
2419
+ * </ng-template>
2420
+ * </kendo-gantt>
2421
+ * `
2422
+ * })
2423
+ * class AppComponent {
2424
+ * public data: any[] = sampleTasks;
2425
+ * }
2426
+ * ```
2427
+ */
2428
+ let GanttSummaryTaskTemplateDirective = class GanttSummaryTaskTemplateDirective {
2429
+ constructor(templateRef) {
2430
+ this.templateRef = templateRef;
2431
+ }
2432
+ };
2433
+ GanttSummaryTaskTemplateDirective = __decorate([
2434
+ Directive({
2435
+ selector: '[kendoGanttSummaryTaskTemplate]'
2436
+ }),
2437
+ __param(0, Optional()),
2438
+ __metadata("design:paramtypes", [TemplateRef])
2439
+ ], GanttSummaryTaskTemplateDirective);
2156
2440
 
2157
- <!-- placeholder for the dependency drag popup; its position is not arbitrary - the popup is intended to be absolutely positioned inside the .k-grid-content element -->
2158
- <ng-container #dragPopupContainer></ng-container>
2159
- </div>
2160
- </div>
2161
- `
2441
+ /**
2442
+ * Represents a template that defines the text content section of the task component.
2443
+ * To define the template, nest an `<ng-template>` tag
2444
+ * with the `kendoGanttTaskContentTemplate` directive inside the `<kendo-gantt>` tag.
2445
+ *
2446
+ * The template context is set to the current data item.
2447
+ *
2448
+ * @example
2449
+ * ```ts-preview
2450
+ * _@Component({
2451
+ * selector: 'my-app',
2452
+ * template: `
2453
+ * <kendo-gantt [kendoGanttHierarchyBinding]="data">
2454
+ * <ng-template kendoGanttTaskContentTemplate let-dataItem>
2455
+ * {{ dataItem.title }} - {{ dataItem.completionRatio * 100 }}% complete
2456
+ * </ng-template>
2457
+ * </kendo-gantt>
2458
+ * `
2459
+ * })
2460
+ * class AppComponent {
2461
+ * public data: any[] = sampleTasks;
2462
+ * }
2463
+ * ```
2464
+ */
2465
+ let GanttTaskContentTemplateDirective = class GanttTaskContentTemplateDirective {
2466
+ constructor(templateRef) {
2467
+ this.templateRef = templateRef;
2468
+ }
2469
+ };
2470
+ GanttTaskContentTemplateDirective = __decorate([
2471
+ Directive({
2472
+ selector: '[kendoGanttTaskContentTemplate]'
2473
+ }),
2474
+ __param(0, Optional()),
2475
+ __metadata("design:paramtypes", [TemplateRef])
2476
+ ], GanttTaskContentTemplateDirective);
2477
+
2478
+ /**
2479
+ * Represents the toolbar template of the Gantt.
2480
+ *
2481
+ * The template context has the following field:
2482
+ * - `position`&mdash;The position at which the toolbar template is rendered. The possible values are `'top'` and `'bottom'`.
2483
+ *
2484
+ * @example
2485
+ * ```ts-preview
2486
+ *
2487
+ * _@Component({
2488
+ * selector: 'my-app',
2489
+ * template: `
2490
+ * <div class="example-config">
2491
+ * <input type="radio" id="top" name="position" class="k-radio" value="top" checked (click)="positionChange($event)"/>
2492
+ * <label class="k-radio-label" for="top">Top</label><br/>
2493
+ * <input type="radio" id="bottom" name="position" class="k-radio" value="bottom" (click)="positionChange($event)"/>
2494
+ * <label class="k-radio-label" for="bottom">Bottom</label><br/>
2495
+ * <input type="radio" id="both" name="position" value="both" class="k-radio" (click)="positionChange($event)"/>
2496
+ * <label class="k-radio-label" for="both">Both</label><br/>
2497
+ * </div>
2498
+ * <kendo-gantt [[kendoGanttHierarchyBinding]="data"]="data" style="height: 400px">
2499
+ * <ng-template kendoGanttToolbarTemplate [position]="position" let-position="position">
2500
+ * <button (click)="onClick()" class="k-button">Custom action</button>
2501
+ * </ng-template>
2502
+ * </kendo-gantt>
2503
+ * `
2504
+ * })
2505
+ *
2506
+ * class AppComponent {
2507
+ * public position: 'top' | 'bottom' | 'both' = 'top';
2508
+ *
2509
+ * public data = [{
2510
+ * id: 7,
2511
+ * title: "Software validation, research and implementation",
2512
+ * orderId: 0,
2513
+ * start: new Date("2014-06-02T00:00:00.000Z"),
2514
+ * end: new Date("2014-07-12T00:00:00.000Z"),
2515
+ * completionRatio: 0.45708333333333334,
2516
+ * isExpanded: true,
2517
+ * children: [{
2518
+ * id: 11,
2519
+ * title: "Research",
2520
+ * orderId: 1,
2521
+ * start: new Date("2014-06-02T00:00:00.000Z"),
2522
+ * end: new Date("2014-06-07T00:00:00.000Z"),
2523
+ * completionRatio: 0.5766666666666667,
2524
+ * isExpanded: true,
2525
+ * children: [{
2526
+ * id: 19,
2527
+ * title: "Validation with Customers",
2528
+ * orderId: 0,
2529
+ * start: new Date("2014-06-02T00:00:00.000Z"),
2530
+ * end: new Date("2014-06-04T00:00:00.000Z"),
2531
+ * completionRatio: 0.25,
2532
+ * isExpanded: true
2533
+ * },
2534
+ * {
2535
+ * id: 20,
2536
+ * title: "Market Research",
2537
+ * orderId: 1,
2538
+ * start: new Date("2014-06-02T00:00:00.000Z"),
2539
+ * end: new Date("2014-06-03T02:00:00.000Z"),
2540
+ * completionRatio: 0.82,
2541
+ * isExpanded: true
2542
+ * },
2543
+ * {
2544
+ * id: 39,
2545
+ * title: "Functional and Technical Specification",
2546
+ * orderId: 2,
2547
+ * start: new Date("2014-06-04T00:00:00.000Z"),
2548
+ * end: new Date("2014-06-07T00:00:00.000Z"),
2549
+ * completionRatio: 0.66,
2550
+ * isExpanded: true
2551
+ * }]
2552
+ * }]
2553
+ * };
2554
+ *
2555
+ * public positionChange({ target }): void {
2556
+ * this.position = target.value;
2557
+ * }
2558
+ *
2559
+ * public onClick(): void {
2560
+ * console.log("button was clicked");
2561
+ * }
2562
+ * }
2563
+ *
2564
+ * ```
2565
+ */
2566
+ let ToolbarTemplateDirective = class ToolbarTemplateDirective {
2567
+ constructor(templateRef) {
2568
+ this.templateRef = templateRef;
2569
+ this._position = "top";
2570
+ }
2571
+ /**
2572
+ * Defines the Gantt Toolbar that will use this template.
2573
+ *
2574
+ * The possible values are:
2575
+ * - `top`&mdash;The template will be rendered in the top toolbar (if present) only.
2576
+ * - `bottom`&mdash;The template will be rendered in the bottom toolbar (if present) only.
2577
+ * - `both`&mdash;The template will be rendered in both toolbars (if present).
2578
+ */
2579
+ set position(position) {
2580
+ this._position = position;
2581
+ }
2582
+ get position() {
2583
+ return this._position;
2584
+ }
2585
+ };
2586
+ __decorate([
2587
+ Input('position'),
2588
+ __metadata("design:type", String),
2589
+ __metadata("design:paramtypes", [String])
2590
+ ], ToolbarTemplateDirective.prototype, "position", null);
2591
+ ToolbarTemplateDirective = __decorate([
2592
+ Directive({
2593
+ selector: '[kendoGanttToolbarTemplate]'
2162
2594
  }),
2163
- __metadata("design:paramtypes", [ScrollSyncService,
2164
- DependencyDomService,
2165
- Renderer2,
2166
- NgZone])
2167
- ], GanttTimelineComponent);
2595
+ __param(0, Optional()),
2596
+ __metadata("design:paramtypes", [TemplateRef])
2597
+ ], ToolbarTemplateDirective);
2168
2598
 
2169
2599
  /**
2170
2600
  * The base class for the column components of the Gantt.
@@ -2289,7 +2719,7 @@ const DEFAULT_DRAG_SCROLL_SETTINGS = {
2289
2719
  * ```
2290
2720
  */
2291
2721
  let GanttComponent = GanttComponent_1 = class GanttComponent {
2292
- constructor(timelineViewService, scrollSyncService, renderer, mapper, optionChangesService, dependencyDomService, editService, localizationService, hostElement, zone) {
2722
+ constructor(timelineViewService, scrollSyncService, renderer, mapper, optionChangesService, dependencyDomService, editService, localizationService, hostElement, zone, navigationService) {
2293
2723
  this.timelineViewService = timelineViewService;
2294
2724
  this.scrollSyncService = scrollSyncService;
2295
2725
  this.renderer = renderer;
@@ -2300,6 +2730,15 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2300
2730
  this.localizationService = localizationService;
2301
2731
  this.hostElement = hostElement;
2302
2732
  this.zone = zone;
2733
+ this.navigationService = navigationService;
2734
+ /**
2735
+ * @hidden
2736
+ */
2737
+ this.roleDescription = 'Gantt Chart';
2738
+ /**
2739
+ * @hidden
2740
+ */
2741
+ this.role = 'application';
2303
2742
  this.hostClasses = true;
2304
2743
  /**
2305
2744
  * Specifies a callback that determines if the given task is selected ([see example]({% slug selection_gantt %}#toc-custom-selection)).
@@ -2371,6 +2810,12 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2371
2810
  * The end of the work week (index based).
2372
2811
  */
2373
2812
  this.workWeekEnd = 5;
2813
+ /**
2814
+ * If set to `true`, the user can use dedicated shortcuts to interact with the Gantt.
2815
+ * By default, navigation is disabled for the TreeList and Timeline parts of the component,
2816
+ * ([see example]({% slug keyboard_navigation_gantt %})).
2817
+ */
2818
+ this.navigable = false;
2374
2819
  /**
2375
2820
  * Indicates whether the Gantt columns will be resized during initialization so that they fit their headers and row content.
2376
2821
  * Columns with autoSize set to false are excluded.
@@ -2414,7 +2859,8 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2414
2859
  */
2415
2860
  this.cellClose = new EventEmitter();
2416
2861
  /**
2417
- * Fires when the end user clicks the `Delete` button in the task editing dialog or the task delete icon.
2862
+ * Fires when the end user clicks the `Delete` button in the task editing dialog,
2863
+ * the task delete icon, or presses the `Delete` key on the keyboard when a task in the timeline is focused.
2418
2864
  * Use the event handler to open a confirmation dialog when necessary.
2419
2865
  */
2420
2866
  this.taskDelete = new EventEmitter();
@@ -2549,7 +2995,11 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2549
2995
  }));
2550
2996
  this.editService.getSelectedItem = this.getFirstSelectedItem.bind(this);
2551
2997
  this.editServiceSubscription.add(this.editService.showEditingDialog.subscribe(show => this.showEditingDialog = show));
2552
- this.editServiceSubscription.add(this.editService.showConfirmationDialog.subscribe(() => this.taskDelete.emit()));
2998
+ this.editServiceSubscription.add(this.editService.taskDelete.subscribe(task => {
2999
+ if (hasObservers(this.taskDelete)) {
3000
+ this.zone.run(() => this.notifyTaskDelete(task));
3001
+ }
3002
+ }));
2553
3003
  this.editServiceSubscription.add(this.editService.editEvent.subscribe(args => {
2554
3004
  this[args.editResultType].emit({
2555
3005
  taskFormGroup: args.taskFormGroup,
@@ -2560,6 +3010,9 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2560
3010
  this.showConfirmationDialog = this.showEditingDialog = false;
2561
3011
  this.editService.dataItem = this.editService.taskFormGroup = null;
2562
3012
  this.updateView();
3013
+ if (this.navigable) {
3014
+ this.focus();
3015
+ }
2563
3016
  }));
2564
3017
  this.editServiceSubscription.add(this.editService.addEvent.subscribe(args => {
2565
3018
  const selectedItem = this.getFirstSelectedItem();
@@ -2583,6 +3036,12 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2583
3036
  set toolbarTemplate(customToolbarTemplate) {
2584
3037
  this._customToolbarTemplate = customToolbarTemplate;
2585
3038
  }
3039
+ get hostRoleDescriptionAttr() {
3040
+ return this.roleDescription;
3041
+ }
3042
+ get hostRoleAttr() {
3043
+ return this.role;
3044
+ }
2586
3045
  get dir() {
2587
3046
  return this.direction;
2588
3047
  }
@@ -2760,6 +3219,15 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2760
3219
  }
2761
3220
  return this.treeList.view.data.map(item => item.data);
2762
3221
  }
3222
+ /**
3223
+ * @hidden
3224
+ */
3225
+ get viewItems() {
3226
+ if (!isPresent(this.treeList)) {
3227
+ return [];
3228
+ }
3229
+ return this.treeList.view.data;
3230
+ }
2763
3231
  /**
2764
3232
  * @hidden
2765
3233
  */
@@ -2803,6 +3271,12 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2803
3271
  get viewTypes() {
2804
3272
  return this.views.map(view => view.type);
2805
3273
  }
3274
+ /**
3275
+ * @hidden
3276
+ */
3277
+ get isInEditMode() {
3278
+ return this.showEditingDialog || this.showConfirmationDialog || this.treeList.isEditing();
3279
+ }
2806
3280
  ngOnChanges(changes) {
2807
3281
  if (anyChanged(['data', 'activeView', 'workWeekStart', 'workWeekEnd', 'workDayStart', 'workDayEnd'], changes)) {
2808
3282
  this.loadTimelineData();
@@ -2810,6 +3284,14 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2810
3284
  }
2811
3285
  ngAfterViewInit() {
2812
3286
  this.updateTreeListMargin();
3287
+ if (this.navigable) {
3288
+ this.navigationService.initialize({
3289
+ gantt: this,
3290
+ host: this.hostElement.nativeElement,
3291
+ treeListElement: this.treeList.wrapper.nativeElement,
3292
+ timelineElement: this.timeline.timelineContent.nativeElement
3293
+ });
3294
+ }
2813
3295
  const leftContainer = this.treeList.wrapper.nativeElement.querySelector('kendo-treelist-list > div');
2814
3296
  this.scrollSyncService.registerElement(leftContainer, 'treelist');
2815
3297
  }
@@ -2827,6 +3309,34 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2827
3309
  this.localizationSubscription.unsubscribe();
2828
3310
  }
2829
3311
  }
3312
+ /**
3313
+ * Focuses the last active cell or task in the Gantt.
3314
+ * If no item has previously been focused, the first cell of the TreeList part will receive focus,
3315
+ * ([see example]({% slug keyboard_navigation_gantt %}#toc-controlling-the-focus)).
3316
+ */
3317
+ focus() {
3318
+ if (this.navigable) {
3319
+ this.navigationService.focusLastActiveItem();
3320
+ }
3321
+ }
3322
+ /**
3323
+ * Focuses the targeted cell in the TreeList part of the component,
3324
+ * ([see example]({% slug keyboard_navigation_gantt %}#toc-controlling-the-focus)).
3325
+ */
3326
+ focusCell(rowIndex, colIndex) {
3327
+ if (this.navigable) {
3328
+ this.navigationService.focusCell(rowIndex, colIndex);
3329
+ }
3330
+ }
3331
+ /**
3332
+ * Focuses the targeted task in the Timeline part of the component,
3333
+ * ([see example]({% slug keyboard_navigation_gantt %}#toc-controlling-the-focus)).
3334
+ */
3335
+ focusTask(taskIndex) {
3336
+ if (this.navigable) {
3337
+ this.navigationService.focusTask(taskIndex);
3338
+ }
3339
+ }
2830
3340
  /**
2831
3341
  * Applies the minimum possible width for the specified column,
2832
3342
  * so that the whole text fits without wrapping. This method expects the Gantt
@@ -2911,6 +3421,15 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2911
3421
  openConfirmationDialog() {
2912
3422
  this.showConfirmationDialog = true;
2913
3423
  }
3424
+ /**
3425
+ * @hidden
3426
+ */
3427
+ handleConfirmationDialogClose() {
3428
+ this.showConfirmationDialog = false;
3429
+ if (this.navigable) {
3430
+ this.focus();
3431
+ }
3432
+ }
2914
3433
  /**
2915
3434
  * Opens a cell for editing.
2916
3435
  */
@@ -2995,7 +3514,7 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
2995
3514
  if (hasObservers(this.taskClick)) {
2996
3515
  const taskIndex = getClosestTaskIndex(target, gantt);
2997
3516
  const task = this.renderedTreeListItems[taskIndex];
2998
- this.zone.run(() => this.emitTaskClick(event, task, taskIndex));
3517
+ this.zone.run(() => this.notifyTaskClick(event, task, taskIndex));
2999
3518
  }
3000
3519
  }
3001
3520
  /**
@@ -3013,8 +3532,8 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
3013
3532
  if ((hasObservers(this.selectionChange) && !this.isSameSelection(selectionAction, task)) ||
3014
3533
  hasObservers(this.taskClick)) {
3015
3534
  this.zone.run(() => {
3016
- this.emitSelectionChange(task, selectionAction);
3017
- this.emitTaskClick(event, task, taskIndex);
3535
+ this.notifySelectionChange(task, selectionAction);
3536
+ this.notifyTaskClick(event, task, taskIndex);
3018
3537
  });
3019
3538
  }
3020
3539
  }
@@ -3051,7 +3570,7 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
3051
3570
  }
3052
3571
  const task = event.items.map(item => item.dataItem)[0]; // single selection only currently available
3053
3572
  const action = event.action;
3054
- this.emitSelectionChange(task, action);
3573
+ this.notifySelectionChange(task, action);
3055
3574
  }
3056
3575
  /**
3057
3576
  * @hidden
@@ -3102,7 +3621,7 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
3102
3621
  dataItem: task,
3103
3622
  originalEvent: event,
3104
3623
  sender: this,
3105
- rowIndex: taskIndex,
3624
+ index: taskIndex,
3106
3625
  type: 'dblclick'
3107
3626
  }));
3108
3627
  }
@@ -3113,16 +3632,35 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
3113
3632
  getText(token) {
3114
3633
  return this.localizationService.get(token);
3115
3634
  }
3116
- emitTaskClick(event, dataItem, itemIndex) {
3635
+ /**
3636
+ * @hidden
3637
+ */
3638
+ changeActiveView(view) {
3639
+ if (view !== this.activeView) {
3640
+ this.activeView = view;
3641
+ this.loadTimelineData();
3642
+ this.scrollSyncService.resetTimelineScrollLeft();
3643
+ this.activeViewChange.emit(view);
3644
+ }
3645
+ }
3646
+ /**
3647
+ * @hidden
3648
+ */
3649
+ notifyTaskClick(event, dataItem, itemIndex) {
3650
+ // simulates the TreeList `cellClick` event triggered by enter press (type: 'click')
3651
+ const type = event instanceof KeyboardEvent ? 'click' : event.type;
3117
3652
  this.taskClick.emit({
3118
3653
  originalEvent: event,
3119
3654
  dataItem: dataItem,
3120
- rowIndex: itemIndex,
3121
- type: event.type,
3655
+ index: itemIndex,
3656
+ type: type,
3122
3657
  sender: this
3123
3658
  });
3124
3659
  }
3125
- emitSelectionChange(dataItem, action) {
3660
+ /**
3661
+ * @hidden
3662
+ */
3663
+ notifySelectionChange(dataItem, action) {
3126
3664
  if (this.isSameSelection(action, dataItem)) {
3127
3665
  return;
3128
3666
  }
@@ -3133,6 +3671,29 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
3133
3671
  });
3134
3672
  this.treeList.updateView();
3135
3673
  }
3674
+ /**
3675
+ * @hidden
3676
+ */
3677
+ notifyTaskDelete(task) {
3678
+ this.editService.dataItem = task;
3679
+ this.taskDelete.emit({
3680
+ item: getEditItem(task, this.treeList.view.data, this.mapper),
3681
+ sender: this
3682
+ });
3683
+ }
3684
+ /**
3685
+ * @hidden
3686
+ */
3687
+ isSameSelection(action, dataItem) {
3688
+ return action === 'select' && this.isSelected(dataItem);
3689
+ }
3690
+ /**
3691
+ * @hidden
3692
+ */
3693
+ getSelectionAction({ ctrlKey, metaKey }, dataItem) {
3694
+ const shouldToggleSelection = ctrlKey || metaKey;
3695
+ return (shouldToggleSelection && this.isSelected(dataItem)) ? 'remove' : 'select';
3696
+ }
3136
3697
  updateTreeListGroupClass(columns = this.columns) {
3137
3698
  if (!isPresent(this.treeList)) {
3138
3699
  return;
@@ -3159,13 +3720,6 @@ let GanttComponent = GanttComponent_1 = class GanttComponent {
3159
3720
  }
3160
3721
  return this.views.find(view => view.type === this.activeView);
3161
3722
  }
3162
- isSameSelection(action, dataItem) {
3163
- return action === 'select' && this.isSelected(dataItem);
3164
- }
3165
- getSelectionAction({ ctrlKey, metaKey }, dataItem) {
3166
- const shouldToggleSelection = ctrlKey || metaKey;
3167
- return (shouldToggleSelection && this.isSelected(dataItem)) ? 'remove' : 'select';
3168
- }
3169
3723
  getFirstSelectedItem() {
3170
3724
  const isSelectedCallback = this.isSelected || isSelected;
3171
3725
  const loadedItems = this.renderedTreeListItems || [];
@@ -3241,6 +3795,24 @@ __decorate([
3241
3795
  ContentChildren(ToolbarTemplateDirective),
3242
3796
  __metadata("design:type", QueryList)
3243
3797
  ], GanttComponent.prototype, "toolbarTemplateChildren", void 0);
3798
+ __decorate([
3799
+ Input('aria-roledescription'),
3800
+ __metadata("design:type", String)
3801
+ ], GanttComponent.prototype, "roleDescription", void 0);
3802
+ __decorate([
3803
+ HostBinding('attr.aria-roledescription'),
3804
+ __metadata("design:type", String),
3805
+ __metadata("design:paramtypes", [])
3806
+ ], GanttComponent.prototype, "hostRoleDescriptionAttr", null);
3807
+ __decorate([
3808
+ Input('role'),
3809
+ __metadata("design:type", String)
3810
+ ], GanttComponent.prototype, "role", void 0);
3811
+ __decorate([
3812
+ HostBinding('attr.role'),
3813
+ __metadata("design:type", String),
3814
+ __metadata("design:paramtypes", [])
3815
+ ], GanttComponent.prototype, "hostRoleAttr", null);
3244
3816
  __decorate([
3245
3817
  HostBinding('class.k-gantt'),
3246
3818
  __metadata("design:type", Boolean)
@@ -3346,6 +3918,10 @@ __decorate([
3346
3918
  Input(),
3347
3919
  __metadata("design:type", Number)
3348
3920
  ], GanttComponent.prototype, "workWeekEnd", void 0);
3921
+ __decorate([
3922
+ Input(),
3923
+ __metadata("design:type", Boolean)
3924
+ ], GanttComponent.prototype, "navigable", void 0);
3349
3925
  __decorate([
3350
3926
  Input(),
3351
3927
  __metadata("design:type", Object),
@@ -3511,7 +4087,8 @@ GanttComponent = GanttComponent_1 = __decorate([
3511
4087
  MappingService,
3512
4088
  OptionChangesService,
3513
4089
  EditService,
3514
- TimelineScrollService
4090
+ TimelineScrollService,
4091
+ NavigationService
3515
4092
  ],
3516
4093
  template: `
3517
4094
  <ng-container kendoGanttLocalizedMessages
@@ -3738,6 +4315,7 @@ GanttComponent = GanttComponent_1 = __decorate([
3738
4315
  [data]="data"
3739
4316
  [hasChildren]="hasChildren"
3740
4317
  [fetchChildren]="fetchChildren"
4318
+ [navigable]="navigable"
3741
4319
  [isExpanded]="isExpanded"
3742
4320
  [autoSize]="columnsAutoSize"
3743
4321
  [columnMenu]="columnMenu"
@@ -3828,7 +4406,7 @@ GanttComponent = GanttComponent_1 = __decorate([
3828
4406
  *ngIf="views && views.length"
3829
4407
  [renderDependencyDragClues]="renderDependencyDragClues"
3830
4408
  [dragScrollSettings]="dragScrollSettings"
3831
- [rows]="renderedTreeListItems"
4409
+ [rows]="viewItems"
3832
4410
  [slots]="timelineSlots"
3833
4411
  [groupSlots]="timelineGroupSlots"
3834
4412
  [tableWidth]="tableWidth"
@@ -3838,7 +4416,8 @@ GanttComponent = GanttComponent_1 = __decorate([
3838
4416
  [summaryTaskTemplate]="summaryTaskTemplate?.templateRef"
3839
4417
  [taskClass]="taskClass"
3840
4418
  [dependencies]="dependencies"
3841
- [hasChildren]="hasChildren"
4419
+ [isExpanded]="isExpanded"
4420
+ [selectable]="selectable"
3842
4421
  [isTaskSelected]="isTaskSelected"
3843
4422
  [kendoEventsOutsideAngular]="{
3844
4423
  click: handleTimelineClick,
@@ -3866,12 +4445,12 @@ GanttComponent = GanttComponent_1 = __decorate([
3866
4445
  [width]="575"
3867
4446
  [height]="170"
3868
4447
  [title]="getText('confirmationDialogTitle')"
3869
- (close)="showConfirmationDialog = false;">
4448
+ (close)="handleConfirmationDialogClose()">
3870
4449
  <span>{{ getText('confirmationDialogContent') }}</span>
3871
4450
  <kendo-dialog-actions layout="normal">
3872
4451
  <kendo-treelist-spacer></kendo-treelist-spacer>
3873
4452
  <button kendoButton [primary]="true" (click)="handleDeleteConfirmation()">{{ getText('deleteButtonText') }}</button>
3874
- <button kendoButton (click)="showConfirmationDialog = false;">{{ getText('cancelButtonText') }}</button>
4453
+ <button kendoButton (click)="handleConfirmationDialogClose()">{{ getText('cancelButtonText') }}</button>
3875
4454
  </kendo-dialog-actions>
3876
4455
  </kendo-dialog>
3877
4456
  `
@@ -3885,7 +4464,8 @@ GanttComponent = GanttComponent_1 = __decorate([
3885
4464
  EditService,
3886
4465
  LocalizationService,
3887
4466
  ElementRef,
3888
- NgZone])
4467
+ NgZone,
4468
+ NavigationService])
3889
4469
  ], GanttComponent);
3890
4470
 
3891
4471
  /**
@@ -3908,8 +4488,8 @@ let GanttTasksTableBodyComponent = class GanttTasksTableBodyComponent {
3908
4488
  this.dependencyDomService.registerTimelineRow(timelineRow.nativeElement);
3909
4489
  }
3910
4490
  }
3911
- isMileStone(task) {
3912
- return !this.hasChildren(task) && isEqual(this.mapper.extractFromTask(task, 'start'), this.mapper.extractFromTask(task, 'end'));
4491
+ isMileStone(item) {
4492
+ return !item.hasChildren && isEqual(this.mapper.extractFromTask(item.data, 'start'), this.mapper.extractFromTask(item.data, 'end'));
3913
4493
  }
3914
4494
  };
3915
4495
  __decorate([
@@ -3917,6 +4497,10 @@ __decorate([
3917
4497
  __metadata("design:type", ElementRef),
3918
4498
  __metadata("design:paramtypes", [ElementRef])
3919
4499
  ], GanttTasksTableBodyComponent.prototype, "timelineRow", null);
4500
+ __decorate([
4501
+ Input(),
4502
+ __metadata("design:type", Boolean)
4503
+ ], GanttTasksTableBodyComponent.prototype, "selectable", void 0);
3920
4504
  __decorate([
3921
4505
  Input(),
3922
4506
  __metadata("design:type", Array)
@@ -3944,7 +4528,7 @@ __decorate([
3944
4528
  __decorate([
3945
4529
  Input(),
3946
4530
  __metadata("design:type", Function)
3947
- ], GanttTasksTableBodyComponent.prototype, "hasChildren", void 0);
4531
+ ], GanttTasksTableBodyComponent.prototype, "isExpanded", void 0);
3948
4532
  __decorate([
3949
4533
  Input(),
3950
4534
  __metadata("design:type", Function)
@@ -3961,35 +4545,42 @@ GanttTasksTableBodyComponent = __decorate([
3961
4545
  <td>
3962
4546
  <kendo-gantt-milestone-task
3963
4547
  *ngIf="isMileStone(item); else task"
3964
- [dataItem]="item"
4548
+ [dataItem]="item.data"
4549
+ [level]="item.level"
3965
4550
  [activeView]="activeView"
3966
4551
  [taskClass]="taskClass"
4552
+ [selectable]="selectable"
3967
4553
  [isSelected]="isTaskSelected"
3968
- [attr.data-task-index]="index"
4554
+ [index]="index"
3969
4555
  [renderDependencyDragClues]="renderDependencyDragClues"
3970
4556
  >
3971
4557
  </kendo-gantt-milestone-task>
3972
4558
  <ng-template #task>
3973
4559
  <kendo-gantt-summary-task
3974
- *ngIf="hasChildren(item)"
3975
- [dataItem]="item"
4560
+ *ngIf="item.hasChildren"
4561
+ [dataItem]="item.data"
4562
+ [level]="item.level"
3976
4563
  [template]="summaryTaskTemplate"
3977
4564
  [activeView]="activeView"
3978
4565
  [taskClass]="taskClass"
4566
+ [selectable]="selectable"
3979
4567
  [isSelected]="isTaskSelected"
3980
- [attr.data-task-index]="index"
4568
+ [isExpanded]="isExpanded"
4569
+ [index]="index"
3981
4570
  [renderDependencyDragClues]="renderDependencyDragClues"
3982
4571
  >
3983
4572
  </kendo-gantt-summary-task>
3984
4573
  <kendo-gantt-task
3985
- *ngIf="!hasChildren(item)"
3986
- [dataItem]="item"
4574
+ *ngIf="!item.hasChildren"
4575
+ [dataItem]="item.data"
4576
+ [level]="item.level"
3987
4577
  [taskContentTemplate]="taskContentTemplate"
3988
4578
  [taskTemplate]="taskTemplate"
3989
4579
  [activeView]="activeView"
3990
4580
  [taskClass]="taskClass"
4581
+ [selectable]="selectable"
3991
4582
  [isSelected]="isTaskSelected"
3992
- [attr.data-task-index]="index"
4583
+ [index]="index"
3993
4584
  [renderDependencyDragClues]="renderDependencyDragClues"
3994
4585
  >
3995
4586
  </kendo-gantt-task>
@@ -4035,22 +4626,32 @@ const slotUnitDuration = {
4035
4626
  week: MS_PER_DAY,
4036
4627
  month: MS_PER_DAY * 7
4037
4628
  };
4629
+ const FOCUSED_CLASS = 'k-focus';
4038
4630
  /**
4039
4631
  * @hidden
4040
4632
  */
4041
4633
  class GanttTaskBase {
4042
4634
  constructor(mapper, // left public to be available for usage in the templates
4043
- timelineViewService, dependencyDomService, optionChangesService, cdr) {
4635
+ timelineViewService, dependencyDomService, optionChangesService, cdr, navigationService) {
4044
4636
  this.mapper = mapper;
4045
4637
  this.timelineViewService = timelineViewService;
4046
4638
  this.dependencyDomService = dependencyDomService;
4047
4639
  this.optionChangesService = optionChangesService;
4048
4640
  this.cdr = cdr;
4641
+ this.navigationService = navigationService;
4049
4642
  this.wrapperClass = true;
4050
- this.viewChangesSubscription = new Subscription();
4051
- this.viewChangesSubscription.add(this.optionChangesService.viewChanges.subscribe(() => {
4052
- this.cdr.markForCheck();
4053
- }));
4643
+ this.subscriptions = new Subscription();
4644
+ this.subscriptions.add(this.optionChangesService.viewChanges
4645
+ .subscribe(() => this.cdr.markForCheck()));
4646
+ this.subscriptions.add(this.navigationService.taskStatusChanges
4647
+ .subscribe(this.updateActiveState.bind(this)));
4648
+ }
4649
+ get taskIndexAttribute() {
4650
+ return this.index;
4651
+ }
4652
+ get ariaSelected() {
4653
+ // assinging null will not render the attribute at all (desired in selectable="false" mode)
4654
+ return this.selectable ? String(this.isSelected(this.dataItem)) : null;
4054
4655
  }
4055
4656
  get slotUnitDuration() {
4056
4657
  return slotUnitDuration[this.activeView];
@@ -4094,18 +4695,38 @@ class GanttTaskBase {
4094
4695
  else if (isPresent(changes.activeView)) {
4095
4696
  this.dependencyDomService.notifyChanges();
4096
4697
  }
4698
+ if (this.navigationService.enabled && isPresent(changes.index)) {
4699
+ this.updateActiveState(this.navigationService.activeTask);
4700
+ }
4097
4701
  }
4098
4702
  ngOnDestroy() {
4099
4703
  if (isPresent(this.dataItem)) {
4100
4704
  this.dependencyDomService.unregisterTask(this.dataItem);
4101
4705
  }
4102
- this.viewChangesSubscription.unsubscribe();
4706
+ this.subscriptions.unsubscribe();
4707
+ }
4708
+ updateActiveState({ activeIndex, isFocused }) {
4709
+ const isActive = activeIndex === this.index;
4710
+ const tabindex = isActive ? '0' : '-1';
4711
+ this.taskElement.nativeElement.setAttribute('tabindex', tabindex);
4712
+ if (isActive && isFocused) {
4713
+ this.taskElement.nativeElement.focus();
4714
+ this.taskElement.nativeElement.classList.add(FOCUSED_CLASS);
4715
+ }
4716
+ else {
4717
+ this.taskElement.nativeElement.classList.remove(FOCUSED_CLASS);
4718
+ }
4103
4719
  }
4104
4720
  }
4105
4721
  __decorate([
4106
4722
  HostBinding('class.k-task-wrap'),
4107
4723
  __metadata("design:type", Boolean)
4108
4724
  ], GanttTaskBase.prototype, "wrapperClass", void 0);
4725
+ __decorate([
4726
+ HostBinding('attr.data-task-index'),
4727
+ __metadata("design:type", Number),
4728
+ __metadata("design:paramtypes", [])
4729
+ ], GanttTaskBase.prototype, "taskIndexAttribute", null);
4109
4730
  __decorate([
4110
4731
  ViewChild('task', { static: true }),
4111
4732
  __metadata("design:type", ElementRef)
@@ -4114,10 +4735,22 @@ __decorate([
4114
4735
  Input(),
4115
4736
  __metadata("design:type", Object)
4116
4737
  ], GanttTaskBase.prototype, "dataItem", void 0);
4738
+ __decorate([
4739
+ Input(),
4740
+ __metadata("design:type", Number)
4741
+ ], GanttTaskBase.prototype, "index", void 0);
4742
+ __decorate([
4743
+ Input(),
4744
+ __metadata("design:type", Number)
4745
+ ], GanttTaskBase.prototype, "level", void 0);
4117
4746
  __decorate([
4118
4747
  Input(),
4119
4748
  __metadata("design:type", Boolean)
4120
4749
  ], GanttTaskBase.prototype, "renderDependencyDragClues", void 0);
4750
+ __decorate([
4751
+ Input(),
4752
+ __metadata("design:type", Boolean)
4753
+ ], GanttTaskBase.prototype, "selectable", void 0);
4121
4754
  __decorate([
4122
4755
  Input(),
4123
4756
  __metadata("design:type", Function)
@@ -4141,14 +4774,14 @@ var GanttTaskComponent_1;
4141
4774
  * @hidden
4142
4775
  */
4143
4776
  let GanttTaskComponent = GanttTaskComponent_1 = class GanttTaskComponent extends GanttTaskBase {
4144
- constructor(editService, touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
4145
- super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr);
4777
+ constructor(editService, touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr, navigationService) {
4778
+ super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr, navigationService);
4146
4779
  this.editService = editService;
4147
4780
  this.touchEnabled = touchEnabled$$1;
4148
4781
  }
4149
4782
  onTaskDelete() {
4150
4783
  this.editService.dataItem = this.dataItem;
4151
- this.editService.showConfirmationDialog.next();
4784
+ this.editService.taskDelete.next(this.dataItem);
4152
4785
  }
4153
4786
  };
4154
4787
  __decorate([
@@ -4172,15 +4805,19 @@ GanttTaskComponent = GanttTaskComponent_1 = __decorate([
4172
4805
  <div
4173
4806
  #task
4174
4807
  class="k-task k-task-single"
4808
+ role="treeitem"
4175
4809
  [ngClass]="taskClass(dataItem)"
4176
4810
  [style.width.px]="taskWidth"
4177
4811
  [attr.title]="mapper.extractFromTask(dataItem, 'title')"
4178
4812
  [class.k-state-selected]="isSelected(dataItem)"
4813
+ [attr.aria-selected]="ariaSelected"
4814
+ [attr.aria-level]="level + 1"
4179
4815
  >
4180
4816
  <ng-container *ngIf="!taskTemplate">
4181
4817
  <div
4182
4818
  class="k-task-complete"
4183
4819
  [style.width.px]="completionOverlayWidth"
4820
+ aria-hidden="true"
4184
4821
  >
4185
4822
  </div>
4186
4823
  <div class="k-task-content">
@@ -4195,10 +4832,17 @@ GanttTaskComponent = GanttTaskComponent_1 = __decorate([
4195
4832
  >
4196
4833
  </ng-template>
4197
4834
  </div>
4198
- <span class="k-task-actions">
4835
+ <span
4836
+ class="k-task-actions"
4837
+ aria-hidden="true"
4838
+ >
4199
4839
  <span
4200
- (click)="onTaskDelete()"
4201
- class="k-link k-task-delete">
4840
+ class="k-link k-task-delete"
4841
+ [kendoEventsOutsideAngular]="{
4842
+ click: onTaskDelete
4843
+ }"
4844
+ [scope]="this"
4845
+ >
4202
4846
  <span class="k-icon k-i-close"></span>
4203
4847
  </span>
4204
4848
  </span>
@@ -4226,14 +4870,24 @@ GanttTaskComponent = GanttTaskComponent_1 = __decorate([
4226
4870
  >
4227
4871
  </div>
4228
4872
  </ng-container>
4229
- `
4873
+ `,
4874
+ styles: [`
4875
+ .k-task.k-focus {
4876
+ box-shadow: 0 0 4px 3px grey;
4877
+ outline: none;
4878
+ }
4879
+ .k-task.k-focus.k-state-selected {
4880
+ box-shadow: 0 0 4px 3px #ffaea8;
4881
+ }
4882
+ `]
4230
4883
  }),
4231
4884
  __param(1, Inject(TOUCH_ENABLED)),
4232
4885
  __metadata("design:paramtypes", [EditService, Boolean, MappingService,
4233
4886
  TimelineViewService,
4234
4887
  DependencyDomService,
4235
4888
  OptionChangesService,
4236
- ChangeDetectorRef])
4889
+ ChangeDetectorRef,
4890
+ NavigationService])
4237
4891
  ], GanttTaskComponent);
4238
4892
 
4239
4893
  var GanttSummaryTaskComponent_1;
@@ -4241,11 +4895,17 @@ var GanttSummaryTaskComponent_1;
4241
4895
  * @hidden
4242
4896
  */
4243
4897
  let GanttSummaryTaskComponent = GanttSummaryTaskComponent_1 = class GanttSummaryTaskComponent extends GanttTaskBase {
4244
- constructor(touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
4245
- super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr);
4898
+ constructor(touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr, navigationService) {
4899
+ super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr, navigationService);
4246
4900
  this.touchEnabled = touchEnabled$$1;
4247
4901
  this.summaryWrapperClass = true;
4248
4902
  }
4903
+ get ariaExpanded() {
4904
+ // if no callback is provided, all child items are displayed and the item is regarded as expanded
4905
+ // replicates the TreeList aria-expanded behavior
4906
+ const isExpanded = !isPresent(this.isExpanded) || this.isExpanded(this.dataItem);
4907
+ return String(isExpanded);
4908
+ }
4249
4909
  };
4250
4910
  __decorate([
4251
4911
  HostBinding('class.k-summary-wrap'),
@@ -4255,6 +4915,10 @@ __decorate([
4255
4915
  Input(),
4256
4916
  __metadata("design:type", TemplateRef)
4257
4917
  ], GanttSummaryTaskComponent.prototype, "template", void 0);
4918
+ __decorate([
4919
+ Input(),
4920
+ __metadata("design:type", Function)
4921
+ ], GanttSummaryTaskComponent.prototype, "isExpanded", void 0);
4258
4922
  GanttSummaryTaskComponent = GanttSummaryTaskComponent_1 = __decorate([
4259
4923
  Component({
4260
4924
  selector: 'kendo-gantt-summary-task',
@@ -4267,11 +4931,15 @@ GanttSummaryTaskComponent = GanttSummaryTaskComponent_1 = __decorate([
4267
4931
  template: `
4268
4932
  <div
4269
4933
  #task
4934
+ role="treeitem"
4270
4935
  class="k-task k-task-summary"
4271
4936
  [ngClass]="taskClass(dataItem)"
4272
4937
  [style.width.px]="taskWidth"
4273
4938
  [attr.title]="mapper.extractFromTask(dataItem, 'title')"
4274
4939
  [class.k-state-selected]="isSelected(dataItem)"
4940
+ [attr.aria-selected]="ariaSelected"
4941
+ [attr.aria-expanded]="ariaExpanded"
4942
+ [attr.aria-level]="level + 1"
4275
4943
  >
4276
4944
  <div *ngIf="!template; else summaryTemplate"
4277
4945
  class="k-task-summary-progress"
@@ -4304,14 +4972,24 @@ GanttSummaryTaskComponent = GanttSummaryTaskComponent_1 = __decorate([
4304
4972
  >
4305
4973
  </div>
4306
4974
  </ng-container>
4307
- `
4975
+ `,
4976
+ styles: [`
4977
+ .k-task.k-focus {
4978
+ box-shadow: 0 0 4px 3px grey;
4979
+ outline: none;
4980
+ }
4981
+ .k-task.k-focus.k-state-selected {
4982
+ box-shadow: 0 0 4px 3px #ffaea8;
4983
+ }
4984
+ `]
4308
4985
  }),
4309
4986
  __param(0, Inject(TOUCH_ENABLED)),
4310
4987
  __metadata("design:paramtypes", [Boolean, MappingService,
4311
4988
  TimelineViewService,
4312
4989
  DependencyDomService,
4313
4990
  OptionChangesService,
4314
- ChangeDetectorRef])
4991
+ ChangeDetectorRef,
4992
+ NavigationService])
4315
4993
  ], GanttSummaryTaskComponent);
4316
4994
 
4317
4995
  var GanttMilestoneTaskComponent_1;
@@ -4319,8 +4997,8 @@ var GanttMilestoneTaskComponent_1;
4319
4997
  * @hidden
4320
4998
  */
4321
4999
  let GanttMilestoneTaskComponent = GanttMilestoneTaskComponent_1 = class GanttMilestoneTaskComponent extends GanttTaskBase {
4322
- constructor(touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr) {
4323
- super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr);
5000
+ constructor(touchEnabled$$1, mapper, timelineViewService, dependencyDomService, optionChangesService, cdr, navigationService) {
5001
+ super(mapper, timelineViewService, dependencyDomService, optionChangesService, cdr, navigationService);
4324
5002
  this.touchEnabled = touchEnabled$$1;
4325
5003
  this.milestoneWrapperClass = true;
4326
5004
  }
@@ -4341,10 +5019,13 @@ GanttMilestoneTaskComponent = GanttMilestoneTaskComponent_1 = __decorate([
4341
5019
  template: `
4342
5020
  <div
4343
5021
  #task
5022
+ role="treeitem"
4344
5023
  class="k-task k-task-milestone"
4345
5024
  [ngClass]="taskClass(dataItem)"
4346
5025
  [attr.title]="mapper.extractFromTask(dataItem, 'title')"
4347
5026
  [class.k-state-selected]="isSelected(dataItem)"
5027
+ [attr.aria-selected]="ariaSelected"
5028
+ [attr.aria-level]="level + 1"
4348
5029
  >
4349
5030
  </div>
4350
5031
  <ng-container *ngIf="renderDependencyDragClues">
@@ -4359,14 +5040,24 @@ GanttMilestoneTaskComponent = GanttMilestoneTaskComponent_1 = __decorate([
4359
5040
  >
4360
5041
  </div>
4361
5042
  </ng-container>
4362
- `
5043
+ `,
5044
+ styles: [`
5045
+ .k-task.k-focus {
5046
+ box-shadow: 0 0 4px 3px grey;
5047
+ outline: none;
5048
+ }
5049
+ .k-task.k-focus.k-state-selected {
5050
+ box-shadow: 0 0 4px 3px #ffaea8;
5051
+ }
5052
+ `]
4363
5053
  }),
4364
5054
  __param(0, Inject(TOUCH_ENABLED)),
4365
5055
  __metadata("design:paramtypes", [Boolean, MappingService,
4366
5056
  TimelineViewService,
4367
5057
  DependencyDomService,
4368
5058
  OptionChangesService,
4369
- ChangeDetectorRef])
5059
+ ChangeDetectorRef,
5060
+ NavigationService])
4370
5061
  ], GanttMilestoneTaskComponent);
4371
5062
 
4372
5063
  /**
@@ -4562,10 +5253,10 @@ SelectableDirective = __decorate([
4562
5253
  * @hidden
4563
5254
  */
4564
5255
  let ToolbarComponent = class ToolbarComponent {
4565
- constructor(gantt, scrollSyncService) {
5256
+ constructor(gantt) {
4566
5257
  this.gantt = gantt;
4567
- this.scrollSyncService = scrollSyncService;
4568
5258
  this.context = {};
5259
+ this.role = 'toolbar';
4569
5260
  }
4570
5261
  set position(value) {
4571
5262
  this.context.position = this._position = value;
@@ -4581,13 +5272,14 @@ let ToolbarComponent = class ToolbarComponent {
4581
5272
  const templatePosition = ganttToolbarTemplate ? ganttToolbarTemplate.position : null;
4582
5273
  return ganttToolbarTemplate && (templatePosition === 'both' || templatePosition === this.position);
4583
5274
  }
4584
- onViewChange(e) {
4585
- this.gantt.activeView = e; // TODO: may be load the timeline data directly in an activeView setter?
4586
- this.gantt.loadTimelineData();
4587
- this.gantt.activeViewChange.emit(e);
4588
- this.scrollSyncService.resetTimelineScrollLeft();
5275
+ handleViewChange(view) {
5276
+ this.gantt.changeActiveView(view);
4589
5277
  }
4590
5278
  };
5279
+ __decorate([
5280
+ HostBinding('attr.role'),
5281
+ __metadata("design:type", String)
5282
+ ], ToolbarComponent.prototype, "role", void 0);
4591
5283
  __decorate([
4592
5284
  Input(),
4593
5285
  __metadata("design:type", Boolean)
@@ -4612,7 +5304,7 @@ ToolbarComponent = __decorate([
4612
5304
  *ngIf="showViewSelector"
4613
5305
  [views]="gantt.viewTypes"
4614
5306
  [activeView]="gantt.activeView"
4615
- (activeViewChange)="onViewChange($event)"></kendo-gantt-view-selector>
5307
+ (activeViewChange)="handleViewChange($event)"></kendo-gantt-view-selector>
4616
5308
  </ng-container>
4617
5309
  <ng-template
4618
5310
  *ngIf="renderTemplate"
@@ -4622,8 +5314,7 @@ ToolbarComponent = __decorate([
4622
5314
  </ng-template>
4623
5315
  `
4624
5316
  }),
4625
- __metadata("design:paramtypes", [GanttComponent,
4626
- ScrollSyncService])
5317
+ __metadata("design:paramtypes", [GanttComponent])
4627
5318
  ], ToolbarComponent);
4628
5319
 
4629
5320
  /**
@@ -4678,7 +5369,9 @@ ViewSelectorComponent = __decorate([
4678
5369
  Component({
4679
5370
  selector: 'kendo-gantt-view-selector',
4680
5371
  template: `
4681
- <select class="k-dropdown k-views-dropdown"
5372
+ <select
5373
+ class="k-dropdown k-views-dropdown"
5374
+ aria-label="View Selector"
4682
5375
  [value]="activeView"
4683
5376
  (change)="activeViewChange.emit($event.target.value)">
4684
5377
  <option *ngFor="let view of views" [value]="view">{{getViewTypeText(view)}}</option>
@@ -5602,8 +6295,8 @@ let EditDialogComponent = class EditDialogComponent {
5602
6295
  handleEditingResult(editResultType) {
5603
6296
  this.editService.triggerEditEvent(editResultType);
5604
6297
  }
5605
- onTaskDelete() {
5606
- this.editService.showConfirmationDialog.next();
6298
+ handleTaskDelete() {
6299
+ this.editService.taskDelete.next(this.editService.dataItem);
5607
6300
  }
5608
6301
  };
5609
6302
  __decorate([
@@ -5650,7 +6343,15 @@ EditDialogComponent = __decorate([
5650
6343
  </kendo-tabstrip>
5651
6344
 
5652
6345
  <kendo-dialog-actions layout="normal">
5653
- <button kendoButton (click)="onTaskDelete()">{{ getText('deleteButtonText') }}</button>
6346
+ <button
6347
+ kendoButton
6348
+ [kendoEventsOutsideAngular]="{
6349
+ click: handleTaskDelete
6350
+ }"
6351
+ [scope]="this"
6352
+ >
6353
+ {{ getText('deleteButtonText') }}
6354
+ </button>
5654
6355
  <kendo-treelist-spacer></kendo-treelist-spacer>
5655
6356
  <button kendoButton [primary]="true" (click)="handleEditingResult('save')">{{ getText('saveButtonText') }}</button>
5656
6357
  <button kendoButton (click)="handleEditingResult('cancel')">{{ getText('cancelButtonText') }}</button>
@@ -6408,4 +7109,4 @@ GanttModule = __decorate([
6408
7109
  * Generated bundle index. Do not edit.
6409
7110
  */
6410
7111
 
6411
- export { MappingService, OptionChangesService, TOUCH_ENABLED, DependencyDomService, GanttDependencyDirective, DragValidationTooltipComponent, GanttAddTaskComponent, DependenciesTableComponent, EditDialogComponent, EditService, TaskFieldsComponent, CustomMessagesComponent, GanttLocalizationService, LocalizedMessagesDirective, Messages, PreventableEvent, GanttHeaderTableBodyComponent, GanttMilestoneTaskComponent, GanttSummaryTaskComponent, GanttTaskBase, GanttTaskComponent, GanttTasksTableBodyComponent, ScrollSyncService, TimelineScrollableDirective, TimelineScrollService, GanttTimelineComponent, TimelineBaseViewService, TimelineDayViewComponent, TimelineDayViewService, TimelineMonthViewComponent, TimelineMonthViewService, TimelineViewService, TimelineWeekViewComponent, TimelineWeekViewService, ViewBase, ToolbarComponent, ViewSelectorComponent, GanttComponent, GanttModule, GanttHierarchyBindingDirective, GanttFlatBindingDirective, GanttExpandableDirective, DependencyDragCreateDirective, GanttTaskTemplateDirective, GanttTaskContentTemplateDirective, GanttSummaryTaskTemplateDirective, ToolbarTemplateDirective, SelectableDirective, DependencyType, CellCloseEvent, GanttColumnBase, GanttColumnComponent, GanttColumnGroupComponent, GanttSpanColumnComponent, CellTemplateDirective, HeaderTemplateDirective, FooterTemplateDirective, ColumnMenuTemplateDirective, FilterCellTemplateDirective, FilterMenuTemplateDirective, EditTemplateDirective };
7112
+ export { MappingService, OptionChangesService, TOUCH_ENABLED, DependencyDomService, GanttDependencyDirective, DragValidationTooltipComponent, GanttAddTaskComponent, DependenciesTableComponent, EditDialogComponent, EditService, TaskFieldsComponent, CustomMessagesComponent, GanttLocalizationService, LocalizedMessagesDirective, Messages, PreventableEvent, NavigationService, GanttHeaderTableBodyComponent, GanttMilestoneTaskComponent, GanttSummaryTaskComponent, GanttTaskBase, GanttTaskComponent, GanttTasksTableBodyComponent, ScrollSyncService, TimelineScrollableDirective, TimelineScrollService, GanttTimelineComponent, TimelineBaseViewService, TimelineDayViewComponent, TimelineDayViewService, TimelineMonthViewComponent, TimelineMonthViewService, TimelineViewService, TimelineWeekViewComponent, TimelineWeekViewService, ViewBase, ToolbarComponent, ViewSelectorComponent, GanttComponent, GanttModule, GanttHierarchyBindingDirective, GanttFlatBindingDirective, GanttExpandableDirective, DependencyDragCreateDirective, GanttTaskTemplateDirective, GanttTaskContentTemplateDirective, GanttSummaryTaskTemplateDirective, ToolbarTemplateDirective, SelectableDirective, DependencyType, CellCloseEvent, GanttColumnBase, GanttColumnComponent, GanttColumnGroupComponent, GanttSpanColumnComponent, CellTemplateDirective, HeaderTemplateDirective, FooterTemplateDirective, ColumnMenuTemplateDirective, FilterCellTemplateDirective, FilterMenuTemplateDirective, EditTemplateDirective };