@syncfusion/ej2-gantt 22.1.37 → 22.1.38

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.
@@ -1467,8 +1467,16 @@ class DateProcessor {
1467
1467
  viewData.forEach((data) => {
1468
1468
  taskRange = [];
1469
1469
  const task = data.ganttProperties;
1470
- const tempStartDate = this.getValidStartDate(task);
1471
- const tempEndDate = this.getValidEndDate(task);
1470
+ let tempStartDate;
1471
+ let tempEndDate;
1472
+ if (isNullOrUndefined(task.startDate) && isNullOrUndefined(task.endDate)) {
1473
+ tempStartDate = null;
1474
+ tempEndDate = null;
1475
+ }
1476
+ else {
1477
+ tempStartDate = this.getValidStartDate(task);
1478
+ tempEndDate = this.getValidEndDate(task);
1479
+ }
1472
1480
  addDateToList(minStartDate);
1473
1481
  addDateToList(maxEndDate);
1474
1482
  addDateToList(tempStartDate);
@@ -5142,7 +5150,6 @@ class GanttChart {
5142
5150
  this.updateWidthAndHeight();
5143
5151
  this.reRenderConnectorLines();
5144
5152
  getValue('chartRow', args).setAttribute('aria-expanded', 'false');
5145
- this.parent.trigger('collapsed', args);
5146
5153
  }
5147
5154
  /**
5148
5155
  * To expand gantt rows
@@ -5196,7 +5203,6 @@ class GanttChart {
5196
5203
  this.updateWidthAndHeight();
5197
5204
  this.reRenderConnectorLines();
5198
5205
  getValue('chartRow', args).setAttribute('aria-expanded', 'true');
5199
- this.parent.trigger('expanded', args);
5200
5206
  }
5201
5207
  renderMultiTaskbar(record) {
5202
5208
  if (this.parent.enableMultiTaskbar) {
@@ -5240,20 +5246,27 @@ class GanttChart {
5240
5246
  removeClass([targetElement[t]], 'e-row-expand');
5241
5247
  }
5242
5248
  }
5243
- const childRecords = record.childRecords;
5244
- const chartRows = this.getChartRows();
5245
- const rows = [];
5246
- for (let i = 0; i < chartRows.length; i++) {
5247
- if (chartRows[i].classList.contains('gridrowtaskId'
5248
- + record.ganttProperties.rowUniqueID + 'level' + (record.level + 1))) {
5249
- rows.push(chartRows[i]);
5249
+ if (!this.parent.enableVirtualization) {
5250
+ const childRecords = record.childRecords;
5251
+ const chartRows = this.getChartRows();
5252
+ const rows = [];
5253
+ for (let i = 0; i < chartRows.length; i++) {
5254
+ if (chartRows[i].classList.contains("gridrowtaskId" +
5255
+ record.ganttProperties.rowUniqueID +
5256
+ "level" +
5257
+ (record.level + 1))) {
5258
+ rows.push(chartRows[i]);
5259
+ }
5250
5260
  }
5251
- }
5252
- for (let i = 0; i < rows.length; i++) {
5253
- rows[i].style.display = displayType;
5254
- if ((childRecords[i].childRecords && childRecords[i].childRecords.length)
5255
- && (action === 'collapse' || childRecords[i].expanded || this.isExpandAll)) {
5256
- this.expandCollapseChartRows(action, rows[i], childRecords[i], true);
5261
+ for (let i = 0; i < rows.length; i++) {
5262
+ rows[i].style.display = displayType;
5263
+ if (childRecords[i].childRecords &&
5264
+ childRecords[i].childRecords.length &&
5265
+ (action === "collapse" ||
5266
+ childRecords[i].expanded ||
5267
+ this.isExpandAll)) {
5268
+ this.expandCollapseChartRows(action, rows[i], childRecords[i], true);
5269
+ }
5257
5270
  }
5258
5271
  }
5259
5272
  }
@@ -6093,6 +6106,8 @@ class Timeline {
6093
6106
  this.parent.showSpinner();
6094
6107
  }
6095
6108
  this.changeTimelineSettings(newTimeline);
6109
+ this.isZoomToFit = false;
6110
+ this.parent.isTimelineRoundOff = this.isZoomToFit ? false : isNullOrUndefined(this.parent.projectStartDate) ? true : false;
6096
6111
  }
6097
6112
  bottomTierCellWidthCalc(mode, zoomLevel, date) {
6098
6113
  let convertedMilliSeconds;
@@ -7610,25 +7625,60 @@ class GanttTreeGrid {
7610
7625
  collapsing(args) {
7611
7626
  // Collapsing event
7612
7627
  const callBackPromise = new Deferred();
7628
+ let collapsingArgs;
7629
+ const record = getValue('data', args);
7630
+ const recordLength = record.length;
7613
7631
  if (!this.parent.ganttChartModule.isExpandCollapseFromChart) {
7614
- const collapsingArgs = this.createExpandCollapseArgs(args);
7615
- this.parent.ganttChartModule.collapseGanttRow(collapsingArgs);
7616
- setValue('cancel', getValue('cancel', collapsingArgs), args);
7632
+ if (!isNullOrUndefined(recordLength)) {
7633
+ for (let i = 0; i < recordLength; i++) {
7634
+ collapsingArgs = this.createExpandCollapseArgs(args, record[i]);
7635
+ this.parent.ganttChartModule.collapseGanttRow(collapsingArgs);
7636
+ }
7637
+ setValue('cancel', getValue('cancel', collapsingArgs), args);
7638
+ }
7639
+ else {
7640
+ collapsingArgs = this.createExpandCollapseArgs(args, null);
7641
+ this.parent.ganttChartModule.collapseGanttRow(collapsingArgs);
7642
+ setValue('cancel', getValue('cancel', collapsingArgs), args);
7643
+ }
7617
7644
  }
7618
7645
  }
7619
7646
  expanding(args) {
7620
7647
  // Expanding event
7621
7648
  const callBackPromise = new Deferred();
7649
+ let expandingArgs;
7650
+ const record = getValue('data', args);
7651
+ const recordLength = record.length;
7622
7652
  if (!this.parent.ganttChartModule.isExpandCollapseFromChart) {
7623
- const expandingArgs = this.createExpandCollapseArgs(args);
7624
- this.parent.ganttChartModule.expandGanttRow(expandingArgs);
7625
- setValue('cancel', getValue('cancel', expandingArgs), args);
7653
+ if (!isNullOrUndefined(recordLength)) {
7654
+ for (let i = 0; i < recordLength; i++) {
7655
+ expandingArgs = this.createExpandCollapseArgs(args, record[i]);
7656
+ this.parent.ganttChartModule.expandGanttRow(expandingArgs);
7657
+ }
7658
+ setValue('cancel', getValue('cancel', expandingArgs), args);
7659
+ }
7660
+ else {
7661
+ expandingArgs = this.createExpandCollapseArgs(args, null);
7662
+ this.parent.ganttChartModule.expandGanttRow(expandingArgs);
7663
+ setValue('cancel', getValue('cancel', expandingArgs), args);
7664
+ }
7626
7665
  }
7627
7666
  }
7628
7667
  collapsed(args) {
7629
7668
  if (!this.parent.ganttChartModule.isExpandCollapseFromChart && !this.parent.isExpandCollapseLevelMethod) {
7630
- const collapsedArgs = this.createExpandCollapseArgs(args);
7631
- this.parent.ganttChartModule.collapsedGanttRow(collapsedArgs);
7669
+ let collapsedArgs;
7670
+ const record = getValue('data', args);
7671
+ const recordLength = record.length;
7672
+ if (!isNullOrUndefined(recordLength)) {
7673
+ for (let i = 0; i < recordLength; i++) {
7674
+ collapsedArgs = this.createExpandCollapseArgs(args, record[i]);
7675
+ this.parent.ganttChartModule.collapsedGanttRow(collapsedArgs);
7676
+ }
7677
+ }
7678
+ else {
7679
+ collapsedArgs = this.createExpandCollapseArgs(args, null);
7680
+ this.parent.ganttChartModule.collapsedGanttRow(collapsedArgs);
7681
+ }
7632
7682
  if (this.parent.viewType === 'ResourceView' && !this.parent.allowTaskbarOverlap && collapsedArgs['gridRow']) {
7633
7683
  collapsedArgs['gridRow'].style.height = collapsedArgs['chartRow'].style.height;
7634
7684
  this.parent.contentHeight = this.parent.enableRtl ? this.parent['element'].getElementsByClassName('e-content')[2].children[0]['offsetHeight'] :
@@ -7642,19 +7692,29 @@ class GanttTreeGrid {
7642
7692
  else {
7643
7693
  this.parent.hideSpinner();
7644
7694
  }
7695
+ this.parent.trigger('collapsed', args);
7645
7696
  }
7646
7697
  expanded(args) {
7647
7698
  if (!this.parent.ganttChartModule.isExpandCollapseFromChart && !this.parent.isExpandCollapseLevelMethod) {
7648
- if (!args['data'].length) {
7649
- const expandedArgs = this.createExpandCollapseArgs(args);
7650
- this.parent.ganttChartModule.expandedGanttRow(expandedArgs);
7651
- if (this.parent.viewType === 'ResourceView' && !this.parent.allowTaskbarOverlap && args['row']) {
7652
- args['row'].style.height = this.parent.rowHeight + 'px';
7653
- this.parent.contentHeight = this.parent.enableRtl ? this.parent['element'].getElementsByClassName('e-content')[2].children[0]['offsetHeight'] :
7654
- this.parent['element'].getElementsByClassName('e-content')[0].children[0]['offsetHeight'];
7655
- document.getElementsByClassName('e-chart-rows-container')[0]['style'].height = this.parent.contentHeight + 'px';
7699
+ let expandedArgs;
7700
+ const record = getValue('data', args);
7701
+ const recordLength = record.length;
7702
+ if (!isNullOrUndefined(recordLength)) {
7703
+ for (let i = 0; i < recordLength; i++) {
7704
+ expandedArgs = this.createExpandCollapseArgs(args, record[i]);
7705
+ this.parent.ganttChartModule.expandedGanttRow(expandedArgs);
7656
7706
  }
7657
7707
  }
7708
+ else {
7709
+ expandedArgs = this.createExpandCollapseArgs(args, null);
7710
+ this.parent.ganttChartModule.expandedGanttRow(expandedArgs);
7711
+ }
7712
+ if (this.parent.viewType === 'ResourceView' && !this.parent.allowTaskbarOverlap && args['row']) {
7713
+ args['row'].style.height = this.parent.rowHeight + 'px';
7714
+ this.parent.contentHeight = this.parent.enableRtl ? this.parent['element'].getElementsByClassName('e-content')[2].children[0]['offsetHeight'] :
7715
+ this.parent['element'].getElementsByClassName('e-content')[0].children[0]['offsetHeight'];
7716
+ document.getElementsByClassName('e-chart-rows-container')[0]['style'].height = this.parent.contentHeight + 'px';
7717
+ }
7658
7718
  }
7659
7719
  if (!isNullOrUndefined(this.parent.loadingIndicator) && this.parent.loadingIndicator.indicatorType === "Shimmer") {
7660
7720
  this.parent.hideMaskRow();
@@ -7662,6 +7722,7 @@ class GanttTreeGrid {
7662
7722
  else {
7663
7723
  this.parent.hideSpinner();
7664
7724
  }
7725
+ this.parent.trigger('expanded', args);
7665
7726
  }
7666
7727
  actionBegin(args) {
7667
7728
  this.parent.notify('actionBegin', args);
@@ -7685,13 +7746,23 @@ class GanttTreeGrid {
7685
7746
  actionFailure(args) {
7686
7747
  this.parent.trigger('actionFailure', args);
7687
7748
  }
7688
- createExpandCollapseArgs(args) {
7689
- const record = getValue('data', args);
7690
- const gridRow = getValue('row', args);
7749
+ createExpandCollapseArgs(args, currentRecord) {
7691
7750
  let chartRow;
7692
- chartRow = this.parent.ganttChartModule.getChartRows()[this.parent.currentViewData.indexOf(record)];
7693
- const eventArgs = { data: record, gridRow: gridRow, chartRow: chartRow, cancel: false };
7694
- return eventArgs;
7751
+ const record = getValue('data', args);
7752
+ const recordLength = record.length;
7753
+ if (!isNullOrUndefined(recordLength)) {
7754
+ const gridRow = getValue('row', args);
7755
+ chartRow = this.parent.ganttChartModule.getChartRows()[this.parent.currentViewData.indexOf(currentRecord)];
7756
+ const eventArgs = { data: currentRecord, gridRow: gridRow, chartRow: chartRow, cancel: false };
7757
+ return eventArgs;
7758
+ }
7759
+ else {
7760
+ const record_1 = getValue('data', args);
7761
+ const gridRow = getValue('row', args);
7762
+ chartRow = this.parent.ganttChartModule.getChartRows()[this.parent.currentViewData.indexOf(record_1)];
7763
+ const eventArgs = { data: record_1, gridRow: gridRow, chartRow: chartRow, cancel: false };
7764
+ return eventArgs;
7765
+ }
7695
7766
  }
7696
7767
  treeActionComplete(args) {
7697
7768
  const updatedArgs = extend({}, args);
@@ -11153,6 +11224,9 @@ class Dependency {
11153
11224
  ganttRecord = predecessorsCollection[count];
11154
11225
  if ((!ganttRecord.hasChildRecords && !this.parent.allowParentDependency) || this.parent.allowParentDependency) {
11155
11226
  this.updatePredecessorHelper(ganttRecord, predecessorsCollection);
11227
+ if (!ganttRecord.ganttProperties.isAutoSchedule) {
11228
+ this.parent.connectorLineEditModule['calculateOffset'](ganttRecord);
11229
+ }
11156
11230
  }
11157
11231
  }
11158
11232
  }
@@ -11582,6 +11656,9 @@ class Dependency {
11582
11656
  if (validationOn !== 'predecessor' && this.parent.isValidationEnabled) {
11583
11657
  this.validateChildGanttRecord(parentGanttRecord, record);
11584
11658
  }
11659
+ else if (!record.ganttProperties.isAutoSchedule && this.parent.UpdateOffsetOnTaskbarEdit) {
11660
+ this.parent.connectorLineEditModule['calculateOffset'](record);
11661
+ }
11585
11662
  if (parentGanttRecord.expanded === false || record.expanded === false) {
11586
11663
  if (record) {
11587
11664
  this.validatePredecessor(record, undefined, 'successor');
@@ -30306,65 +30383,79 @@ class ContextMenu$2 {
30306
30383
  }
30307
30384
  switch (this.item) {
30308
30385
  case 'TaskInformation':
30309
- if (isNaN(Number(this.rowData.ganttProperties.rowUniqueID))) {
30310
- this.parent.openEditDialog(this.rowData.ganttProperties.rowUniqueID);
30311
- }
30312
- else {
30313
- this.parent.openEditDialog(Number(this.rowData.ganttProperties.rowUniqueID));
30386
+ if (!isNullOrUndefined(this.rowData)) {
30387
+ if (isNaN(Number(this.rowData.ganttProperties.rowUniqueID))) {
30388
+ this.parent.openEditDialog(this.rowData.ganttProperties.rowUniqueID);
30389
+ }
30390
+ else {
30391
+ this.parent.openEditDialog(Number(this.rowData.ganttProperties.rowUniqueID));
30392
+ }
30314
30393
  }
30315
30394
  break;
30316
30395
  case 'Above':
30317
30396
  case 'Below':
30318
30397
  case 'Child':
30319
- position = this.item;
30320
- data = extend({}, {}, this.rowData.taskData, true);
30321
- taskfields = this.parent.taskFields;
30322
- if (data[taskfields.startDate]) {
30323
- this.parent.setRecordValue(taskfields.startDate, this.rowData.ganttProperties.startDate, data, true);
30324
- }
30325
- if (data[taskfields.endDate]) {
30326
- this.parent.setRecordValue(taskfields.endDate, this.rowData.ganttProperties.endDate, data, true);
30327
- }
30328
- if (!isNullOrUndefined(taskfields.dependency)) {
30329
- data[taskfields.dependency] = null;
30330
- }
30331
- if (!isNullOrUndefined(taskfields.child) && data[taskfields.child]) {
30332
- delete data[taskfields.child];
30333
- }
30334
- if (!isNullOrUndefined(taskfields.parentID) && data[taskfields.parentID]) {
30335
- data[taskfields.parentID] = null;
30398
+ if (!isNullOrUndefined(this.rowData)) {
30399
+ position = this.item;
30400
+ data = extend({}, {}, this.rowData.taskData, true);
30401
+ taskfields = this.parent.taskFields;
30402
+ if (data[taskfields.startDate]) {
30403
+ this.parent.setRecordValue(taskfields.startDate, this.rowData.ganttProperties.startDate, data, true);
30404
+ }
30405
+ if (data[taskfields.endDate]) {
30406
+ this.parent.setRecordValue(taskfields.endDate, this.rowData.ganttProperties.endDate, data, true);
30407
+ }
30408
+ if (!isNullOrUndefined(taskfields.dependency)) {
30409
+ data[taskfields.dependency] = null;
30410
+ }
30411
+ if (!isNullOrUndefined(taskfields.child) && data[taskfields.child]) {
30412
+ delete data[taskfields.child];
30413
+ }
30414
+ if (!isNullOrUndefined(taskfields.parentID) && data[taskfields.parentID]) {
30415
+ data[taskfields.parentID] = null;
30416
+ }
30417
+ if (this.rowData) {
30418
+ const rowIndex = this.parent.updatedRecords.indexOf(this.rowData);
30419
+ this.parent.addRecord(data, position, rowIndex);
30420
+ }
30336
30421
  }
30337
- if (this.rowData) {
30338
- const rowIndex = this.parent.updatedRecords.indexOf(this.rowData);
30339
- this.parent.addRecord(data, position, rowIndex);
30422
+ else if (this.parent.flatData.length === 0) {
30423
+ this.parent.addRecord();
30340
30424
  }
30341
30425
  break;
30342
30426
  case 'Milestone':
30343
30427
  case 'ToMilestone':
30344
- this.parent.convertToMilestone(this.rowData.ganttProperties.rowUniqueID);
30428
+ if (!isNullOrUndefined(this.rowData)) {
30429
+ this.parent.convertToMilestone(this.rowData.ganttProperties.rowUniqueID);
30430
+ }
30431
+ else if (this.parent.flatData.length === 0) {
30432
+ this.parent.addRecord();
30433
+ }
30345
30434
  break;
30346
30435
  case 'DeleteTask':
30347
30436
  this.parent.editModule.deleteRecord(this.rowData);
30348
30437
  break;
30349
30438
  case 'ToTask':
30350
- data = extend({}, {}, this.rowData.taskData, true);
30351
- taskfields = this.parent.taskFields;
30352
- if (!isNullOrUndefined(taskfields.duration)) {
30353
- const ganttProp = this.rowData.ganttProperties;
30354
- data[taskfields.duration] = '1 ' + ganttProp.durationUnit;
30355
- }
30356
- else {
30357
- data[taskfields.startDate] = new Date(this.rowData.taskData[taskfields.startDate]);
30358
- const endDate = new Date(this.rowData.taskData[taskfields.startDate]);
30359
- endDate.setDate(endDate.getDate() + 1);
30360
- data[taskfields.endDate] = endDate;
30361
- }
30362
- if (!isNullOrUndefined(data[taskfields.milestone])) {
30363
- if (data[taskfields.milestone] === true) {
30364
- data[taskfields.milestone] = false;
30439
+ if (!isNullOrUndefined(this.rowData)) {
30440
+ data = extend({}, {}, this.rowData.taskData, true);
30441
+ taskfields = this.parent.taskFields;
30442
+ if (!isNullOrUndefined(taskfields.duration)) {
30443
+ const ganttProp = this.rowData.ganttProperties;
30444
+ data[taskfields.duration] = '1 ' + ganttProp.durationUnit;
30365
30445
  }
30446
+ else {
30447
+ data[taskfields.startDate] = new Date(this.rowData.taskData[taskfields.startDate]);
30448
+ const endDate = new Date(this.rowData.taskData[taskfields.startDate]);
30449
+ endDate.setDate(endDate.getDate() + 1);
30450
+ data[taskfields.endDate] = endDate;
30451
+ }
30452
+ if (!isNullOrUndefined(data[taskfields.milestone])) {
30453
+ if (data[taskfields.milestone] === true) {
30454
+ data[taskfields.milestone] = false;
30455
+ }
30456
+ }
30457
+ this.parent.updateRecordByID(data);
30366
30458
  }
30367
- this.parent.updateRecordByID(data);
30368
30459
  break;
30369
30460
  case 'Cancel':
30370
30461
  this.parent.cancelEdit();
@@ -30517,7 +30608,7 @@ class ContextMenu$2 {
30517
30608
  this.contextMenu.enableItems(['Add', 'Save', 'Convert', 'Delete Dependency', 'Delete Task', 'TaskMode', 'Indent', 'Outdent', 'SplitTask', 'MergeTask'], false);
30518
30609
  }
30519
30610
  if ((isNullOrUndefined(args.gridRow) && isNullOrUndefined(args.chartRow)) || this.contentMenuItems.length === 0) {
30520
- if (!isNullOrUndefined(args.parentItem) && !isNullOrUndefined(menuElement)) {
30611
+ if (!isNullOrUndefined(args.parentItem) && !isNullOrUndefined(menuElement) || !isNullOrUndefined(closest(target, '.e-content'))) {
30521
30612
  args.cancel = false;
30522
30613
  }
30523
30614
  else {
@@ -30556,7 +30647,7 @@ class ContextMenu$2 {
30556
30647
  args.disableItems = this.disableItems;
30557
30648
  args.hideItems = this.hideItems;
30558
30649
  args.hideChildItems = [];
30559
- if (args.rowData.level === 0 && this.parent.viewType === 'ResourceView') {
30650
+ if (!isNullOrUndefined(args.rowData) && args.rowData.level === 0 && this.parent.viewType === 'ResourceView') {
30560
30651
  args.cancel = true;
30561
30652
  return;
30562
30653
  }
@@ -30598,6 +30689,9 @@ class ContextMenu$2 {
30598
30689
  if (!this.parent.editSettings.allowEditing || !this.parent.editModule) {
30599
30690
  this.updateItemVisibility(item.text);
30600
30691
  }
30692
+ if (this.parent.flatData.length === 0) {
30693
+ this.hideItems.push(item.text);
30694
+ }
30601
30695
  break;
30602
30696
  case 'Add':
30603
30697
  if (!this.parent.editSettings.allowAdding || !this.parent.editModule) {
@@ -30609,14 +30703,14 @@ class ContextMenu$2 {
30609
30703
  this.hideItems.push(item.text);
30610
30704
  break;
30611
30705
  case 'Convert':
30612
- if (this.rowData.hasChildRecords) {
30706
+ if (!isNullOrUndefined(this.rowData) && this.rowData.hasChildRecords) {
30613
30707
  this.hideItems.push(item.text);
30614
30708
  }
30615
30709
  else if (!this.parent.editSettings.allowEditing || !this.parent.editModule) {
30616
30710
  this.updateItemVisibility(item.text);
30617
30711
  }
30618
30712
  else {
30619
- if (!this.rowData.ganttProperties.isMilestone) {
30713
+ if (!isNullOrUndefined(this.rowData) && !this.rowData.ganttProperties.isMilestone) {
30620
30714
  subMenu.push(this.createItemModel(content, 'ToMilestone', this.getLocale('toMilestone')));
30621
30715
  }
30622
30716
  else {
@@ -30624,11 +30718,14 @@ class ContextMenu$2 {
30624
30718
  }
30625
30719
  item.items = subMenu;
30626
30720
  }
30721
+ if (this.parent.flatData.length === 0) {
30722
+ this.hideItems.push(item.text);
30723
+ }
30627
30724
  break;
30628
30725
  case 'DeleteDependency':
30629
30726
  {
30630
30727
  const items = this.getPredecessorsItems();
30631
- if (this.rowData.hasChildRecords) {
30728
+ if (!isNullOrUndefined(this.rowData) && this.rowData.hasChildRecords) {
30632
30729
  this.hideItems.push(item.text);
30633
30730
  }
30634
30731
  else if (!this.parent.editSettings.allowDeleting || items.length === 0 || !this.parent.editModule) {
@@ -30643,6 +30740,9 @@ class ContextMenu$2 {
30643
30740
  if (!this.parent.editSettings.allowDeleting || !this.parent.editModule) {
30644
30741
  this.updateItemVisibility(item.text);
30645
30742
  }
30743
+ if (this.parent.flatData.length === 0) {
30744
+ this.hideItems.push(item.text);
30745
+ }
30646
30746
  break;
30647
30747
  case 'TaskMode':
30648
30748
  if (this.parent.taskMode !== 'Custom') {