'
+ }
+ },
+ { id: "Node2",offsetX: 400,offsetY: 250,width: 100,height: 100
+ },
+
+ ];
+ diagram = new Diagram({
+ width: '100%',
+ height: '700px',
+ rulerSettings:{showRulers:true},
+ nodes:nodes,
+ getNodeDefaults: (obj: NodeModel, diagram: Diagram) => {
+ obj.height = 100;
+ return obj;
+ }
+ });
+ diagram.appendTo('#diagramShadow');
+
+ let overview: Overview = new Overview({
+ sourceID: 'diagramShadow',
+ });
+ overview.appendTo('#overviewShadow');
+
+
+ });
+
+ afterAll((): void => {
+ overview.destroy();
+ diagram.destroy();
+ ele.remove();
+ ove.remove();
+ });
+
+ it('Drag the html node in diagram', (done: Function) => {
+ let html = diagram.nameTable['Node1'];
+ let overview = (document.getElementById('overviewShadow') as any).ej2_instances[0];
+ let overviewRect = document.getElementById(overview.canvas.id + 'overviewrect');
+ let x = Number(overviewRect.getAttribute('x'));
+ let y = Number(overviewRect.getAttribute('y'));
+ let width = Number(overviewRect.getAttribute('width'));
+ let height = Number(overviewRect.getAttribute('height'));
+ diagram.select([html]);
+ let diagramCanvas: HTMLElement = document.getElementById(diagram.element.id + 'content');
+ mouseEvents.mouseMoveEvent(diagramCanvas,html.offsetX,html.offsetY);
+ mouseEvents.mouseDownEvent(diagramCanvas,html.offsetX,html.offsetY);
+ mouseEvents.mouseMoveEvent(diagramCanvas,html.offsetX + 10,html.offsetY + 10);
+ mouseEvents.mouseUpEvent(diagramCanvas,html.offsetX + 10,html.offsetY + 10);
+ let curX = Number(overviewRect.getAttribute('x'));
+ let curY = Number(overviewRect.getAttribute('y'));
+ let curWidth = Number(overviewRect.getAttribute('width'));
+ let curHeight = Number(overviewRect.getAttribute('height'));
+ expect(x === curX && y === curY && width === curWidth && height === curHeight).toBe(true);
+ done();
+ });
+
+ });
});
\ No newline at end of file
diff --git a/controls/diagrams/src/diagram/interaction/command-manager.ts b/controls/diagrams/src/diagram/interaction/command-manager.ts
index e353203603..e1a51065eb 100644
--- a/controls/diagrams/src/diagram/interaction/command-manager.ts
+++ b/controls/diagrams/src/diagram/interaction/command-manager.ts
@@ -42,7 +42,7 @@ import { Snapping } from '../objects/snapping';
import { LayoutAnimation } from '../objects/layout-animation';
import { Container } from '../core/containers/container';
import { Canvas } from '../core/containers/canvas';
-import { getDiagramElement, getAdornerLayerSvg, getHTMLLayer, getAdornerLayer, getSelectorElement } from '../utility/dom-util';
+import { getDiagramElement, getAdornerLayerSvg, getHTMLLayer, getAdornerLayer, getSelectorElement, setAttributeHtml } from '../utility/dom-util';
import { Point } from '../primitives/point';
import { Size } from '../primitives/size';
import { getObjectType, getPoint, intersect2, getOffsetOfConnector, canShowCorner } from './../utility/diagram-util';
@@ -6000,10 +6000,41 @@ Remove terinal segment in initial
}
this.diagram.diagramActions = this.diagram.diagramActions & ~(DiagramAction.PreventZIndexOnDragging | DiagramAction.DragUsingMouse);
this.diagram.refreshCanvasLayers();
+ //Bug 872140: Dragging HTML nodes in a diagram leaves shadows on the overview
+ this.checkHtmlObjectDrag(obj);
return true;
}
return false;
- }
+ };
+ // Checks if any HTML object is being dragged and reset the canvas to clear the shadow of the HTML node border.
+ private checkHtmlObjectDrag(obj: SelectorModel | NodeModel | ConnectorModel){
+ let isHtmlObjDragged = false;
+ if(this.diagram.views && this.diagram.views.length > 1){
+ if(obj instanceof Selector){
+ isHtmlObjDragged = obj.nodes.some(node => node.shape && node.shape.type === 'HTML');
+ } else if((obj as NodeModel).shape && (obj as NodeModel).shape.type === 'HTML') {
+ isHtmlObjDragged = true;
+ }
+ if(isHtmlObjDragged){
+ this.resetOverviewCanvas();
+ }
+ }
+ };
+ //Resetting Overview canvas
+ private resetOverviewCanvas(){
+ for (const temp of this.diagram.views) {
+ const view: View = this.diagram.views[temp];
+ if (!(view instanceof Diagram)) {
+ const rect: HTMLElement = document.getElementById((view as any).canvas.id + 'overviewrect');
+ const x = Number(rect.getAttribute('x'));
+ const y = Number(rect.getAttribute('y'));
+ const width = Number(rect.getAttribute('width'));
+ const height = Number(rect.getAttribute('height'));
+ const attr: Object = { x: x, y: y, width: Math.max(1, width), height: Math.max(1, height) };
+ setAttributeHtml(rect, attr);
+ }
+ }
+ };
/** @private */
public scaleSelectedItems(sx: number, sy: number, pivot: PointModel): boolean {
let obj: SelectorModel | NodeModel | ConnectorModel = this.diagram.selectedItems;
diff --git a/controls/documenteditor/CHANGELOG.md b/controls/documenteditor/CHANGELOG.md
index 54df18862d..45e132388b 100644
--- a/controls/documenteditor/CHANGELOG.md
+++ b/controls/documenteditor/CHANGELOG.md
@@ -2,6 +2,29 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### DocumentEditor
+
+#### Bug Fixes
+
+- `#I545513` - Added the preservation support for table style property in Document editor.
+- `#I548396` - Resolved the page number not refreshed issue while delete page.
+- `#I549835` - Resolved the document lagging issue.
+- `#I553758` - Resolved the editing issue in the attached document, which contains a chart.
+- `#I556874` - Resolved the script error issue when performing undo action on table.
+- `#I558460` - Resolved the tab rendering issue in the attached document.
+- `#I558529` - Resolved the form field editing issue in read only mode.
+- `#I558289` - Resolved the list numbering issue.
+- `#I558259` - Resolved the content formatting issue when removing hyperlink.
+- `#I559197` - Resolved the drag and drop issue.
+- `#I559912` - Resolved the image removed issue when selecting an image and perform enter action.
+- `#I561716` - Resolved the duplicate image string added to sfdt issue while drag and drop.
+- `#I561052` - Resolved the cursor position issue in mobile mode.
+- `#I563837` - Resolved the table overlapping issue in the attached document.
+- `#F186648` - Resolved the script error issue while opening a attached document.
+- `#F186745` - Resolved the table splitting issue in the merge cell.
+
## 25.1.35 (2024-03-15)
### DocumentEditor
diff --git a/controls/documenteditor/package.json b/controls/documenteditor/package.json
index 280ffb3ff6..0502a08220 100644
--- a/controls/documenteditor/package.json
+++ b/controls/documenteditor/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-documenteditor",
- "version": "19.92.0",
+ "version": "25.1.35",
"description": "Feature-rich document editor control with built-in support for context menu, options pane and dialogs.",
"keywords": [
"ej2",
diff --git a/controls/documenteditor/spec/implementation/collaboration/footnote_endnote.spec.ts b/controls/documenteditor/spec/implementation/collaboration/footnote_endnote.spec.ts
index df45f8fa91..868ed6ccc6 100644
--- a/controls/documenteditor/spec/implementation/collaboration/footnote_endnote.spec.ts
+++ b/controls/documenteditor/spec/implementation/collaboration/footnote_endnote.spec.ts
@@ -1,115 +1,115 @@
-import { DocumentEditorContainer, ContainerContentChangeEventArgs, CONTROL_CHARACTERS } from '../../../src/index';
-import { createElement } from '@syncfusion/ej2-base';
-import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
-/**
- * Footnote endnote collaborative editing spec
- */
-describe('Enable track changes in collaborative editing', () => {
- let container: DocumentEditorContainer;
- let element: HTMLElement;
- let args: ContainerContentChangeEventArgs;
- beforeAll(() => {
- element = createElement('div');
- document.body.appendChild(element);
- DocumentEditorContainer.Inject(Toolbar);
- container = new DocumentEditorContainer();
- container.appendTo(element);
- container.documentEditor.enableCollaborativeEditing = true;
- });
- afterAll(() => {
- expect(() => { container.destroy(); }).not.toThrowError();
- expect(element.childNodes.length).toBe(0);
- document.body.removeChild(element);
- document.body.innerHTML = '';
- element = undefined;
- container = undefined;
- });
+// import { DocumentEditorContainer, ContainerContentChangeEventArgs, CONTROL_CHARACTERS } from '../../../src/index';
+// import { createElement } from '@syncfusion/ej2-base';
+// import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
+// /**
+// * Footnote endnote collaborative editing spec
+// */
+// describe('Enable track changes in collaborative editing', () => {
+// let container: DocumentEditorContainer;
+// let element: HTMLElement;
+// let args: ContainerContentChangeEventArgs;
+// beforeAll(() => {
+// element = createElement('div');
+// document.body.appendChild(element);
+// DocumentEditorContainer.Inject(Toolbar);
+// container = new DocumentEditorContainer();
+// container.appendTo(element);
+// container.documentEditor.enableCollaborativeEditing = true;
+// });
+// afterAll(() => {
+// expect(() => { container.destroy(); }).not.toThrowError();
+// expect(element.childNodes.length).toBe(0);
+// document.body.removeChild(element);
+// document.body.innerHTML = '';
+// element = undefined;
+// container = undefined;
+// });
- it('insert footnote', () => {
- console.log('insert footnote');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.selection.select('0;0;4', '0;0;4');
- container.documentEditor.editor.insertFootnote();
- expect(argsEle.operations[0].markerData.type).toBe("Footnote");
- expect(argsEle.operations[0].length).toBe(4);
- expect(argsEle.operations[0].text).toBe(CONTROL_CHARACTERS.Marker_Start);
- });
+// it('insert footnote', () => {
+// console.log('insert footnote');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.selection.select('0;0;4', '0;0;4');
+// container.documentEditor.editor.insertFootnote();
+// expect(argsEle.operations[0].markerData.type).toBe("Footnote");
+// expect(argsEle.operations[0].length).toBe(4);
+// expect(argsEle.operations[0].text).toBe(CONTROL_CHARACTERS.Marker_Start);
+// });
- it('footnote undo/redo', () => {
- console.log('footnote undo/redo');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.selection.select('0;0;4', '0;0;4');
- container.documentEditor.editor.insertFootnote();
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations[0].length).toBe(4);
- expect(argsEle.operations[0].action).toBe('Delete');
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].type).toBe('Paste');
- expect(argsEle.operations[0].pasteContent).toBeDefined();
- //Undo redo delete footnote
- container.documentEditor.selection.select('0;0;5', '0;0;5');
- container.documentEditor.editor.onBackSpace();
- expect(argsEle.operations[0].length).toBe(4);
- expect(argsEle.operations[0].action).toBe('Delete');
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations[0].type).toBe('Paste');
- expect(argsEle.operations[0].pasteContent).toBeDefined();
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].length).toBe(4);
- expect(argsEle.operations[0].action).toBe('Delete');
- });
+// it('footnote undo/redo', () => {
+// console.log('footnote undo/redo');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.selection.select('0;0;4', '0;0;4');
+// container.documentEditor.editor.insertFootnote();
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations[0].length).toBe(4);
+// expect(argsEle.operations[0].action).toBe('Delete');
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].type).toBe('Paste');
+// expect(argsEle.operations[0].pasteContent).toBeDefined();
+// //Undo redo delete footnote
+// container.documentEditor.selection.select('0;0;5', '0;0;5');
+// container.documentEditor.editor.onBackSpace();
+// expect(argsEle.operations[0].length).toBe(4);
+// expect(argsEle.operations[0].action).toBe('Delete');
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations[0].type).toBe('Paste');
+// expect(argsEle.operations[0].pasteContent).toBeDefined();
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].length).toBe(4);
+// expect(argsEle.operations[0].action).toBe('Delete');
+// });
- it('insert endnote', () => {
- console.log('insert endnote');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.selection.select('0;0;4', '0;0;4');
- container.documentEditor.editor.insertEndnote();
- expect(argsEle.operations[0].markerData.type).toBe("Endnote");
- expect(argsEle.operations[0].length).toBe(4);
- expect(argsEle.operations[0].text).toBe(CONTROL_CHARACTERS.Marker_Start);
- });
+// it('insert endnote', () => {
+// console.log('insert endnote');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.selection.select('0;0;4', '0;0;4');
+// container.documentEditor.editor.insertEndnote();
+// expect(argsEle.operations[0].markerData.type).toBe("Endnote");
+// expect(argsEle.operations[0].length).toBe(4);
+// expect(argsEle.operations[0].text).toBe(CONTROL_CHARACTERS.Marker_Start);
+// });
- it('endnote undo/redo', () => {
- console.log('endnote undo/redo');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.selection.select('0;0;4', '0;0;4');
- container.documentEditor.editor.insertEndnote();
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations[0].length).toBe(4);
- expect(argsEle.operations[0].action).toBe('Delete');
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].type).toBe('Paste');
- expect(argsEle.operations[0].pasteContent).toBeDefined();
- //Undo redo delete endtnote
- // Undo is not working correctly after backspace.
- // container.documentEditor.selection.select('0;0;5', '0;0;5');
- // container.documentEditor.editor.onBackSpace();
- // expect(argsEle.operations[0].length).toBe(4);
- // expect(argsEle.operations[0].action).toBe('Delete');
- // container.documentEditor.editorHistory.undo();
- // expect(argsEle.operations[0].type).toBe('Paste');
- // expect(argsEle.operations[0].pasteContent).toBeDefined();
- // container.documentEditor.editorHistory.redo();
- // expect(argsEle.operations[0].length).toBe(4);
- // expect(argsEle.operations[0].action).toBe('Delete');
- });
-});
\ No newline at end of file
+// it('endnote undo/redo', () => {
+// console.log('endnote undo/redo');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.selection.select('0;0;4', '0;0;4');
+// container.documentEditor.editor.insertEndnote();
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations[0].length).toBe(4);
+// expect(argsEle.operations[0].action).toBe('Delete');
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].type).toBe('Paste');
+// expect(argsEle.operations[0].pasteContent).toBeDefined();
+// //Undo redo delete endtnote
+// // Undo is not working correctly after backspace.
+// // container.documentEditor.selection.select('0;0;5', '0;0;5');
+// // container.documentEditor.editor.onBackSpace();
+// // expect(argsEle.operations[0].length).toBe(4);
+// // expect(argsEle.operations[0].action).toBe('Delete');
+// // container.documentEditor.editorHistory.undo();
+// // expect(argsEle.operations[0].type).toBe('Paste');
+// // expect(argsEle.operations[0].pasteContent).toBeDefined();
+// // container.documentEditor.editorHistory.redo();
+// // expect(argsEle.operations[0].length).toBe(4);
+// // expect(argsEle.operations[0].action).toBe('Delete');
+// });
+// });
\ No newline at end of file
diff --git a/controls/documenteditor/spec/implementation/collaboration/formatting.spec.ts b/controls/documenteditor/spec/implementation/collaboration/formatting.spec.ts
index 93fa955362..e4428c2ffd 100644
--- a/controls/documenteditor/spec/implementation/collaboration/formatting.spec.ts
+++ b/controls/documenteditor/spec/implementation/collaboration/formatting.spec.ts
@@ -1,164 +1,164 @@
-import { DocumentEditorContainer, ContainerContentChangeEventArgs, WCharacterFormat, WParagraphFormat, WSectionFormat, WTableFormat, WRowFormat, WCellFormat } from '../../../src/index';
-import { createElement } from '@syncfusion/ej2-base';
-import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
-/**
- * Formatting Collaborative editing spec
- */
-describe('Formatting in collaborative editing', () => {
- let container: DocumentEditorContainer;
- let element: HTMLElement;
- let args: ContainerContentChangeEventArgs;
- beforeAll(() => {
- element = createElement('div');
- document.body.appendChild(element);
- DocumentEditorContainer.Inject(Toolbar);
- container = new DocumentEditorContainer();
- container.appendTo(element);
- container.documentEditor.enableCollaborativeEditing = true;
- });
- afterAll(() => {
- expect(() => { container.destroy(); }).not.toThrowError();
- expect(element.childNodes.length).toBe(0);
- document.body.removeChild(element);
- document.body.innerHTML = '';
- element = undefined;
- container = undefined;
- });
+// import { DocumentEditorContainer, ContainerContentChangeEventArgs, WCharacterFormat, WParagraphFormat, WSectionFormat, WTableFormat, WRowFormat, WCellFormat } from '../../../src/index';
+// import { createElement } from '@syncfusion/ej2-base';
+// import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
+// /**
+// * Formatting Collaborative editing spec
+// */
+// describe('Formatting in collaborative editing', () => {
+// let container: DocumentEditorContainer;
+// let element: HTMLElement;
+// let args: ContainerContentChangeEventArgs;
+// beforeAll(() => {
+// element = createElement('div');
+// document.body.appendChild(element);
+// DocumentEditorContainer.Inject(Toolbar);
+// container = new DocumentEditorContainer();
+// container.appendTo(element);
+// container.documentEditor.enableCollaborativeEditing = true;
+// });
+// afterAll(() => {
+// expect(() => { container.destroy(); }).not.toThrowError();
+// expect(element.childNodes.length).toBe(0);
+// document.body.removeChild(element);
+// document.body.innerHTML = '';
+// element = undefined;
+// container = undefined;
+// });
- it('Undo/Redo character formatting', () => {
- console.log('Undo/Redo character formatting');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (args.operations.length > 0) {
- argsEle = args;
- }
- }
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.selection.select('0;0;4', '0;0;10');
- container.documentEditor.selection.characterFormat.bold = true;
- expect(argsEle.operations[0].type).toBe("CharacterFormat");
- expect(argsEle.operations[0].format).toBe("{\"bold\":true}");
- container.documentEditor.editorHistory.undo();
- let format: WCharacterFormat = new WCharacterFormat(undefined);
- let characterFormat: any = JSON.parse(argsEle.operations[0].format);
- container.documentEditor.documentHelper.owner.parser.parseCharacterFormat(0, characterFormat, format);
- expect(format.bold).toBe(false);
- container.documentEditor.editorHistory.redo();
- characterFormat = JSON.parse(argsEle.operations[0].format);
- container.documentEditor.documentHelper.owner.parser.parseCharacterFormat(0, characterFormat, format);
- expect(format.bold).toBe(true);
- });
+// it('Undo/Redo character formatting', () => {
+// console.log('Undo/Redo character formatting');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (args.operations.length > 0) {
+// argsEle = args;
+// }
+// }
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.selection.select('0;0;4', '0;0;10');
+// container.documentEditor.selection.characterFormat.bold = true;
+// expect(argsEle.operations[0].type).toBe("CharacterFormat");
+// expect(argsEle.operations[0].format).toBe("{\"bold\":true}");
+// container.documentEditor.editorHistory.undo();
+// let format: WCharacterFormat = new WCharacterFormat(undefined);
+// let characterFormat: any = JSON.parse(argsEle.operations[0].format);
+// container.documentEditor.documentHelper.owner.parser.parseCharacterFormat(0, characterFormat, format);
+// expect(format.bold).toBe(false);
+// container.documentEditor.editorHistory.redo();
+// characterFormat = JSON.parse(argsEle.operations[0].format);
+// container.documentEditor.documentHelper.owner.parser.parseCharacterFormat(0, characterFormat, format);
+// expect(format.bold).toBe(true);
+// });
- it('Undo/Redo paragraph formatting', () => {
- console.log('Undo/Redo paragraph formatting');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (args.operations.length > 0) {
- argsEle = args;
- }
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.selection.select('0;0;4', '0;0;4');
- container.documentEditor.selection.paragraphFormat.textAlignment = "Center";
- expect(argsEle.operations[0].type).toBe("ParagraphFormat");
- expect(argsEle.operations[0].format).toBe("{\"textAlignment\":\"Center\"}");
- container.documentEditor.editorHistory.undo();
- let format: WParagraphFormat = new WParagraphFormat(undefined);
- container.documentEditor.documentHelper.owner.parser.parseParagraphFormat(0, JSON.parse(argsEle.operations[0].format), format);
- expect(format.textAlignment).toBe("Left");
- container.documentEditor.editorHistory.redo();
- container.documentEditor.documentHelper.owner.parser.parseParagraphFormat(0, JSON.parse(argsEle.operations[0].format), format);
- expect(format.textAlignment).toBe("Center");
- });
+// it('Undo/Redo paragraph formatting', () => {
+// console.log('Undo/Redo paragraph formatting');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (args.operations.length > 0) {
+// argsEle = args;
+// }
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.selection.select('0;0;4', '0;0;4');
+// container.documentEditor.selection.paragraphFormat.textAlignment = "Center";
+// expect(argsEle.operations[0].type).toBe("ParagraphFormat");
+// expect(argsEle.operations[0].format).toBe("{\"textAlignment\":\"Center\"}");
+// container.documentEditor.editorHistory.undo();
+// let format: WParagraphFormat = new WParagraphFormat(undefined);
+// container.documentEditor.documentHelper.owner.parser.parseParagraphFormat(0, JSON.parse(argsEle.operations[0].format), format);
+// expect(format.textAlignment).toBe("Left");
+// container.documentEditor.editorHistory.redo();
+// container.documentEditor.documentHelper.owner.parser.parseParagraphFormat(0, JSON.parse(argsEle.operations[0].format), format);
+// expect(format.textAlignment).toBe("Center");
+// });
- it('Undo/Redo Section formatting', () => {
- console.log('Undo/Redo Section formatting');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (args.operations.length > 0) {
- argsEle = args;
- }
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.selection.sectionFormat.topMargin = 108;
- expect(argsEle.operations[0].type).toBe("SectionFormat");
- expect(argsEle.operations[0].format).toBe("{\"topMargin\":108}");
- container.documentEditor.editorHistory.undo();
- let sectionFormat: WSectionFormat = new WSectionFormat();
- container.documentEditor.documentHelper.owner.parser.parseSectionFormat(0, JSON.parse(argsEle.operations[0].format), sectionFormat);
- expect(sectionFormat.topMargin).toBe(72);
- container.documentEditor.editorHistory.redo();
- sectionFormat = new WSectionFormat();
- container.documentEditor.documentHelper.owner.parser.parseSectionFormat(0, JSON.parse(argsEle.operations[0].format), sectionFormat);
- expect(sectionFormat.topMargin).toBe(108);
- });
+// it('Undo/Redo Section formatting', () => {
+// console.log('Undo/Redo Section formatting');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (args.operations.length > 0) {
+// argsEle = args;
+// }
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.selection.sectionFormat.topMargin = 108;
+// expect(argsEle.operations[0].type).toBe("SectionFormat");
+// expect(argsEle.operations[0].format).toBe("{\"topMargin\":108}");
+// container.documentEditor.editorHistory.undo();
+// let sectionFormat: WSectionFormat = new WSectionFormat();
+// container.documentEditor.documentHelper.owner.parser.parseSectionFormat(0, JSON.parse(argsEle.operations[0].format), sectionFormat);
+// expect(sectionFormat.topMargin).toBe(72);
+// container.documentEditor.editorHistory.redo();
+// sectionFormat = new WSectionFormat();
+// container.documentEditor.documentHelper.owner.parser.parseSectionFormat(0, JSON.parse(argsEle.operations[0].format), sectionFormat);
+// expect(sectionFormat.topMargin).toBe(108);
+// });
- it('Undo/Redo Table formatting', () => {
- console.log('Undo/Redo Table formatting');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (args.operations.length > 0) {
- argsEle = args;
- }
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertTable(2, 2);
- container.documentEditor.selection.tableFormat.leftIndent = 30;
- expect(argsEle.operations[0].offset).toBe(1);
- expect(argsEle.operations[0].type).toBe("TableFormat");
- expect(argsEle.operations[0].format).toBe("{\"leftIndent\":30}");
- container.documentEditor.editorHistory.undo();
- let tableFormat: WTableFormat = new WTableFormat();
- container.documentEditor.documentHelper.owner.parser.parseTableFormat(JSON.parse(argsEle.operations[0].format), tableFormat, 0);
- expect(tableFormat.leftIndent).toBe(0);
- container.documentEditor.editorHistory.redo();
- container.documentEditor.documentHelper.owner.parser.parseTableFormat(JSON.parse(argsEle.operations[0].format), tableFormat, 0);
- expect(tableFormat.leftIndent).toBe(30);
- });
+// it('Undo/Redo Table formatting', () => {
+// console.log('Undo/Redo Table formatting');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (args.operations.length > 0) {
+// argsEle = args;
+// }
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertTable(2, 2);
+// container.documentEditor.selection.tableFormat.leftIndent = 30;
+// expect(argsEle.operations[0].offset).toBe(1);
+// expect(argsEle.operations[0].type).toBe("TableFormat");
+// expect(argsEle.operations[0].format).toBe("{\"leftIndent\":30}");
+// container.documentEditor.editorHistory.undo();
+// let tableFormat: WTableFormat = new WTableFormat();
+// container.documentEditor.documentHelper.owner.parser.parseTableFormat(JSON.parse(argsEle.operations[0].format), tableFormat, 0);
+// expect(tableFormat.leftIndent).toBe(0);
+// container.documentEditor.editorHistory.redo();
+// container.documentEditor.documentHelper.owner.parser.parseTableFormat(JSON.parse(argsEle.operations[0].format), tableFormat, 0);
+// expect(tableFormat.leftIndent).toBe(30);
+// });
- it('Undo/Redo Row formatting', () => {
- console.log('Undo/Redo Row formatting');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (args.operations.length > 0) {
- argsEle = args;
- }
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertTable(2, 2);
- container.documentEditor.selection.rowFormat.heightType = 'AtLeast';
- container.documentEditor.selection.rowFormat.height = 30;
- expect(argsEle.operations[0].offset).toBe(4);
- expect(argsEle.operations[0].type).toBe("RowFormat");
- expect(argsEle.operations[0].format).toBe("{\"height\":30}");
- container.documentEditor.editorHistory.undo();
- let rowFormat: WRowFormat = new WRowFormat();
- container.documentEditor.documentHelper.owner.parser.parseRowFormat(JSON.parse(argsEle.operations[0].format), rowFormat, 0);
- expect(rowFormat.height).toBe(0);
- container.documentEditor.editorHistory.redo();
- container.documentEditor.documentHelper.owner.parser.parseRowFormat(JSON.parse(argsEle.operations[0].format), rowFormat, 0);
- expect(rowFormat.height).toBe(30);
- });
+// it('Undo/Redo Row formatting', () => {
+// console.log('Undo/Redo Row formatting');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (args.operations.length > 0) {
+// argsEle = args;
+// }
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertTable(2, 2);
+// container.documentEditor.selection.rowFormat.heightType = 'AtLeast';
+// container.documentEditor.selection.rowFormat.height = 30;
+// expect(argsEle.operations[0].offset).toBe(4);
+// expect(argsEle.operations[0].type).toBe("RowFormat");
+// expect(argsEle.operations[0].format).toBe("{\"height\":30}");
+// container.documentEditor.editorHistory.undo();
+// let rowFormat: WRowFormat = new WRowFormat();
+// container.documentEditor.documentHelper.owner.parser.parseRowFormat(JSON.parse(argsEle.operations[0].format), rowFormat, 0);
+// expect(rowFormat.height).toBe(0);
+// container.documentEditor.editorHistory.redo();
+// container.documentEditor.documentHelper.owner.parser.parseRowFormat(JSON.parse(argsEle.operations[0].format), rowFormat, 0);
+// expect(rowFormat.height).toBe(30);
+// });
- it('Undo/Redo Cell formatting', () => {
- console.log('Undo/Redo Cell formatting');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (args.operations.length > 0) {
- argsEle = args;
- }
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertTable(2, 2);
- container.documentEditor.selection.cellFormat.preferredWidth = 300;
- expect(argsEle.operations[0].offset).toBe(3);
- expect(argsEle.operations[0].type).toBe("CellFormat");
- expect(argsEle.operations[0].format).toBe("{\"preferredWidth\":300}");
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations[0].format).toBe("{\"preferredWidth\":234}");
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].format).toBe("{\"preferredWidth\":300}");
- });
-});
\ No newline at end of file
+// it('Undo/Redo Cell formatting', () => {
+// console.log('Undo/Redo Cell formatting');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (args.operations.length > 0) {
+// argsEle = args;
+// }
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertTable(2, 2);
+// container.documentEditor.selection.cellFormat.preferredWidth = 300;
+// expect(argsEle.operations[0].offset).toBe(3);
+// expect(argsEle.operations[0].type).toBe("CellFormat");
+// expect(argsEle.operations[0].format).toBe("{\"preferredWidth\":300}");
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations[0].format).toBe("{\"preferredWidth\":234}");
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].format).toBe("{\"preferredWidth\":300}");
+// });
+// });
\ No newline at end of file
diff --git a/controls/documenteditor/spec/implementation/collaboration/remote_action.spec.ts b/controls/documenteditor/spec/implementation/collaboration/remote_action.spec.ts
index bbf9b17e90..d05ad2f621 100644
--- a/controls/documenteditor/spec/implementation/collaboration/remote_action.spec.ts
+++ b/controls/documenteditor/spec/implementation/collaboration/remote_action.spec.ts
@@ -1,49 +1,49 @@
-import { DocumentEditorContainer, ContainerContentChangeEventArgs, DocumentEditor, ActionInfo, CONTROL_CHARACTERS, TableWidget, TableRowWidget, TableCellWidget, CollaborativeEditingHandler } from '../../../src/index';
-import { createElement, isNullOrUndefined } from '@syncfusion/ej2-base';
-import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
-/**
- * Apply remote action Collaborative editing spec
- */
-describe('Apply remote action in collaborative editing', () => {
- let container: DocumentEditorContainer;
- let element: HTMLElement;
- let args: ContainerContentChangeEventArgs;
- beforeAll(() => {
- DocumentEditor.Inject(CollaborativeEditingHandler);
- element = createElement('div');
- document.body.appendChild(element);
- DocumentEditorContainer.Inject(Toolbar);
- container = new DocumentEditorContainer();
- container.appendTo(element);
- container.documentEditor.enableCollaborativeEditing = true;
- });
- afterAll(() => {
- container.destroy();
- expect(element.childNodes.length).toBe(0);
- document.body.removeChild(element);
- expect(() => { container.destroy(); }).not.toThrowError();
- document.body.innerHTML = '';
- element = undefined;
- container = undefined;
- });
+// import { DocumentEditorContainer, ContainerContentChangeEventArgs, DocumentEditor, ActionInfo, CONTROL_CHARACTERS, TableWidget, TableRowWidget, TableCellWidget, CollaborativeEditingHandler } from '../../../src/index';
+// import { createElement, isNullOrUndefined } from '@syncfusion/ej2-base';
+// import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
+// /**
+// * Apply remote action Collaborative editing spec
+// */
+// describe('Apply remote action in collaborative editing', () => {
+// let container: DocumentEditorContainer;
+// let element: HTMLElement;
+// let args: ContainerContentChangeEventArgs;
+// beforeAll(() => {
+// DocumentEditor.Inject(CollaborativeEditingHandler);
+// element = createElement('div');
+// document.body.appendChild(element);
+// DocumentEditorContainer.Inject(Toolbar);
+// container = new DocumentEditorContainer();
+// container.appendTo(element);
+// container.documentEditor.enableCollaborativeEditing = true;
+// });
+// afterAll(() => {
+// container.destroy();
+// expect(element.childNodes.length).toBe(0);
+// document.body.removeChild(element);
+// expect(() => { container.destroy(); }).not.toThrowError();
+// document.body.innerHTML = '';
+// element = undefined;
+// container = undefined;
+// });
- it('Apply Remote action as row', () => {
- console.log('Insert Row in romote action');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (args.operations.length > 0) {
- argsEle = args;
- }
- }
- const actions: ActionInfo = { "currentUser": "Mugunthan Anbalagan", "roomName": "Paragraph Formatting.docx", "connectionId": "_3ET94I_P_UjEeJDbGAuLQ", "version": 1, "operations": [{ "action": "Insert", "offset": 5, "text": "\u0013", "length": 1, "skipOperation": false, "format": "{\"height\":0,\"allowBreakAcrossPages\":true,\"heightType\":\"Auto\",\"isHeader\":false,\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"diagonalDown\":{},\"diagonalUp\":{},\"horizontal\":{},\"vertical\":{}},\"gridBefore\":0,\"gridBeforeWidth\":0,\"gridBeforeWidthType\":\"Point\",\"gridAfter\":0,\"gridAfterWidth\":0,\"gridAfterWidthType\":\"Point\",\"leftIndent\":0}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CellFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"diagonalDown\":{},\"diagonalUp\":{},\"horizontal\":{},\"vertical\":{}},\"shading\":{},\"preferredWidth\":111.475,\"preferredWidthType\":\"Point\",\"cellWidth\":111.475,\"columnSpan\":1,\"rowSpan\":1,\"verticalAlignment\":\"Top\"}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "ParagraphFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"horizontal\":{},\"vertical\":{}},\"leftIndent\":0,\"rightIndent\":0,\"firstLineIndent\":0,\"textAlignment\":\"Left\",\"beforeSpacing\":0,\"afterSpacing\":0,\"spaceBeforeAuto\":false,\"spaceAfterAuto\":false,\"lineSpacing\":1,\"lineSpacingType\":\"Multiple\",\"styleName\":\"Normal\",\"outlineLevel\":\"BodyText\",\"bidi\":false,\"keepLinesTogether\":false,\"keepWithNext\":false,\"contextualSpacing\":false,\"widowControl\":true}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CharacterFormat", "length": 0, "skipOperation": false, "format": "{\"bold\":false,\"italic\":false,\"fontSize\":12,\"fontFamily\":\"Times New Roman\",\"underline\":\"None\",\"strikethrough\":\"None\",\"baselineAlignment\":\"Normal\",\"highlightColor\":\"NoColor\",\"fontColor\":\"#00000000\",\"bidi\":false,\"bdo\":\"None\",\"boldBidi\":false,\"italicBidi\":false,\"fontSizeBidi\":12,\"fontFamilyBidi\":\"Times New Roman\",\"allCaps\":false,\"localeIdBidi\":1025,\"complexScript\":false,\"fontFamilyAscii\":\"Times New Roman\",\"fontFamilyNonFarEast\":\"Times New Roman\",\"fontFamilyFarEast\":\"Times New Roman\",\"characterSpacing\":0,\"scaling\":100}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CellFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"diagonalDown\":{},\"diagonalUp\":{},\"horizontal\":{},\"vertical\":{}},\"shading\":{},\"preferredWidth\":111.475,\"preferredWidthType\":\"Point\",\"cellWidth\":111.475,\"columnSpan\":1,\"rowSpan\":1,\"verticalAlignment\":\"Top\"}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "ParagraphFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"horizontal\":{},\"vertical\":{}},\"leftIndent\":0,\"rightIndent\":0,\"firstLineIndent\":0,\"textAlignment\":\"Left\",\"beforeSpacing\":0,\"afterSpacing\":0,\"spaceBeforeAuto\":false,\"spaceAfterAuto\":false,\"lineSpacing\":1,\"lineSpacingType\":\"Multiple\",\"styleName\":\"Normal\",\"outlineLevel\":\"BodyText\",\"bidi\":false,\"keepLinesTogether\":false,\"keepWithNext\":false,\"contextualSpacing\":false,\"widowControl\":true}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CharacterFormat", "length": 0, "skipOperation": false, "format": "{\"bold\":false,\"italic\":false,\"fontSize\":12,\"fontFamily\":\"Times New Roman\",\"underline\":\"None\",\"strikethrough\":\"None\",\"baselineAlignment\":\"Normal\",\"highlightColor\":\"NoColor\",\"fontColor\":\"#00000000\",\"bidi\":false,\"bdo\":\"None\",\"boldBidi\":false,\"italicBidi\":false,\"fontSizeBidi\":12,\"fontFamilyBidi\":\"Times New Roman\",\"allCaps\":false,\"localeIdBidi\":1025,\"complexScript\":false,\"fontFamilyAscii\":\"Times New Roman\",\"fontFamilyNonFarEast\":\"Times New Roman\",\"fontFamilyFarEast\":\"Times New Roman\",\"characterSpacing\":0,\"scaling\":100}" }] };
- container.documentEditor.editorModule.insertTable(2, 2);
- container.documentEditor.editorModule.insertTable(2, 2);
- //Inserting row in nested table
- let connections: CollaborativeEditingHandler;
- if (isNullOrUndefined(container.documentEditor.collaborativeEditingHandlerModule)) {
- connections = new CollaborativeEditingHandler(container.documentEditor);
- }
- connections.applyRemoteAction('action', actions);
- expect(((((container.documentEditor.documentHelper.pages[0].bodyWidgets[0].childWidgets[0] as TableWidget).childWidgets[0] as TableRowWidget).childWidgets[0] as TableCellWidget).childWidgets[0] as TableWidget).childWidgets.length).toBe(3);
- });
-});
\ No newline at end of file
+// it('Apply Remote action as row', () => {
+// console.log('Insert Row in romote action');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (args.operations.length > 0) {
+// argsEle = args;
+// }
+// }
+// const actions: ActionInfo = { "currentUser": "Mugunthan Anbalagan", "roomName": "Paragraph Formatting.docx", "connectionId": "_3ET94I_P_UjEeJDbGAuLQ", "version": 1, "operations": [{ "action": "Insert", "offset": 5, "text": "\u0013", "length": 1, "skipOperation": false, "format": "{\"height\":0,\"allowBreakAcrossPages\":true,\"heightType\":\"Auto\",\"isHeader\":false,\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"diagonalDown\":{},\"diagonalUp\":{},\"horizontal\":{},\"vertical\":{}},\"gridBefore\":0,\"gridBeforeWidth\":0,\"gridBeforeWidthType\":\"Point\",\"gridAfter\":0,\"gridAfterWidth\":0,\"gridAfterWidthType\":\"Point\",\"leftIndent\":0}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CellFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"diagonalDown\":{},\"diagonalUp\":{},\"horizontal\":{},\"vertical\":{}},\"shading\":{},\"preferredWidth\":111.475,\"preferredWidthType\":\"Point\",\"cellWidth\":111.475,\"columnSpan\":1,\"rowSpan\":1,\"verticalAlignment\":\"Top\"}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "ParagraphFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"horizontal\":{},\"vertical\":{}},\"leftIndent\":0,\"rightIndent\":0,\"firstLineIndent\":0,\"textAlignment\":\"Left\",\"beforeSpacing\":0,\"afterSpacing\":0,\"spaceBeforeAuto\":false,\"spaceAfterAuto\":false,\"lineSpacing\":1,\"lineSpacingType\":\"Multiple\",\"styleName\":\"Normal\",\"outlineLevel\":\"BodyText\",\"bidi\":false,\"keepLinesTogether\":false,\"keepWithNext\":false,\"contextualSpacing\":false,\"widowControl\":true}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CharacterFormat", "length": 0, "skipOperation": false, "format": "{\"bold\":false,\"italic\":false,\"fontSize\":12,\"fontFamily\":\"Times New Roman\",\"underline\":\"None\",\"strikethrough\":\"None\",\"baselineAlignment\":\"Normal\",\"highlightColor\":\"NoColor\",\"fontColor\":\"#00000000\",\"bidi\":false,\"bdo\":\"None\",\"boldBidi\":false,\"italicBidi\":false,\"fontSizeBidi\":12,\"fontFamilyBidi\":\"Times New Roman\",\"allCaps\":false,\"localeIdBidi\":1025,\"complexScript\":false,\"fontFamilyAscii\":\"Times New Roman\",\"fontFamilyNonFarEast\":\"Times New Roman\",\"fontFamilyFarEast\":\"Times New Roman\",\"characterSpacing\":0,\"scaling\":100}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CellFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"diagonalDown\":{},\"diagonalUp\":{},\"horizontal\":{},\"vertical\":{}},\"shading\":{},\"preferredWidth\":111.475,\"preferredWidthType\":\"Point\",\"cellWidth\":111.475,\"columnSpan\":1,\"rowSpan\":1,\"verticalAlignment\":\"Top\"}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "ParagraphFormat", "length": 1, "skipOperation": false, "format": "{\"borders\":{\"top\":{},\"left\":{},\"right\":{},\"bottom\":{},\"horizontal\":{},\"vertical\":{}},\"leftIndent\":0,\"rightIndent\":0,\"firstLineIndent\":0,\"textAlignment\":\"Left\",\"beforeSpacing\":0,\"afterSpacing\":0,\"spaceBeforeAuto\":false,\"spaceAfterAuto\":false,\"lineSpacing\":1,\"lineSpacingType\":\"Multiple\",\"styleName\":\"Normal\",\"outlineLevel\":\"BodyText\",\"bidi\":false,\"keepLinesTogether\":false,\"keepWithNext\":false,\"contextualSpacing\":false,\"widowControl\":true}" }, { "action": "Insert", "offset": 5, "text": "\u0014", "type": "CharacterFormat", "length": 0, "skipOperation": false, "format": "{\"bold\":false,\"italic\":false,\"fontSize\":12,\"fontFamily\":\"Times New Roman\",\"underline\":\"None\",\"strikethrough\":\"None\",\"baselineAlignment\":\"Normal\",\"highlightColor\":\"NoColor\",\"fontColor\":\"#00000000\",\"bidi\":false,\"bdo\":\"None\",\"boldBidi\":false,\"italicBidi\":false,\"fontSizeBidi\":12,\"fontFamilyBidi\":\"Times New Roman\",\"allCaps\":false,\"localeIdBidi\":1025,\"complexScript\":false,\"fontFamilyAscii\":\"Times New Roman\",\"fontFamilyNonFarEast\":\"Times New Roman\",\"fontFamilyFarEast\":\"Times New Roman\",\"characterSpacing\":0,\"scaling\":100}" }] };
+// container.documentEditor.editorModule.insertTable(2, 2);
+// container.documentEditor.editorModule.insertTable(2, 2);
+// //Inserting row in nested table
+// let connections: CollaborativeEditingHandler;
+// if (isNullOrUndefined(container.documentEditor.collaborativeEditingHandlerModule)) {
+// connections = new CollaborativeEditingHandler(container.documentEditor);
+// }
+// connections.applyRemoteAction('action', actions);
+// expect(((((container.documentEditor.documentHelper.pages[0].bodyWidgets[0].childWidgets[0] as TableWidget).childWidgets[0] as TableRowWidget).childWidgets[0] as TableCellWidget).childWidgets[0] as TableWidget).childWidgets.length).toBe(3);
+// });
+// });
\ No newline at end of file
diff --git a/controls/documenteditor/spec/implementation/collaboration/single_length_ops.spec.ts b/controls/documenteditor/spec/implementation/collaboration/single_length_ops.spec.ts
index 8fb4c4cd0f..dadbedd4fc 100644
--- a/controls/documenteditor/spec/implementation/collaboration/single_length_ops.spec.ts
+++ b/controls/documenteditor/spec/implementation/collaboration/single_length_ops.spec.ts
@@ -1,41 +1,41 @@
-import { DocumentEditorContainer, ContainerContentChangeEventArgs, CONTROL_CHARACTERS, WCharacterFormat } from '../../../src/index';
-import { createElement } from '@syncfusion/ej2-base';
-import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
-/**
- * insert text
- */
-describe('Insert single length text', () => {
- let container: DocumentEditorContainer;
- let element: HTMLElement;
- let args: ContainerContentChangeEventArgs;
- beforeAll(() => {
- element = createElement('div');
- document.body.appendChild(element);
- DocumentEditorContainer.Inject(Toolbar);
- container = new DocumentEditorContainer();
- container.appendTo(element);
- container.documentEditor.enableCollaborativeEditing = true;
- });
- afterAll(() => {
- expect(() => { container.destroy(); }).not.toThrowError();
- expect(element.childNodes.length).toBe(0);
- document.body.removeChild(element);
- document.body.innerHTML = '';
- element = undefined;
- container = undefined;
- });
+// import { DocumentEditorContainer, ContainerContentChangeEventArgs, CONTROL_CHARACTERS, WCharacterFormat } from '../../../src/index';
+// import { createElement } from '@syncfusion/ej2-base';
+// import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
+// /**
+// * insert text
+// */
+// describe('Insert single length text', () => {
+// let container: DocumentEditorContainer;
+// let element: HTMLElement;
+// let args: ContainerContentChangeEventArgs;
+// beforeAll(() => {
+// element = createElement('div');
+// document.body.appendChild(element);
+// DocumentEditorContainer.Inject(Toolbar);
+// container = new DocumentEditorContainer();
+// container.appendTo(element);
+// container.documentEditor.enableCollaborativeEditing = true;
+// });
+// afterAll(() => {
+// expect(() => { container.destroy(); }).not.toThrowError();
+// expect(element.childNodes.length).toBe(0);
+// document.body.removeChild(element);
+// document.body.innerHTML = '';
+// element = undefined;
+// container = undefined;
+// });
- it('insert enter', () => {
- console.log('insert enter');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.editor.insertText('Syncfusion Software');
- container.documentEditor.selection.select('0;0;4', '0;0;4');
- container.documentEditor.editor.onEnter();
- expect(argsEle.operations[0].action).toBe('Insert');
- expect(argsEle.operations[0].length).toBe(1);
- expect(argsEle.operations[0].text).toBe(CONTROL_CHARACTERS.Paragraph);
- });
-});
\ No newline at end of file
+// it('insert enter', () => {
+// console.log('insert enter');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.editor.insertText('Syncfusion Software');
+// container.documentEditor.selection.select('0;0;4', '0;0;4');
+// container.documentEditor.editor.onEnter();
+// expect(argsEle.operations[0].action).toBe('Insert');
+// expect(argsEle.operations[0].length).toBe(1);
+// expect(argsEle.operations[0].text).toBe(CONTROL_CHARACTERS.Paragraph);
+// });
+// });
\ No newline at end of file
diff --git a/controls/documenteditor/spec/implementation/collaboration/table_paste_option.spec.ts b/controls/documenteditor/spec/implementation/collaboration/table_paste_option.spec.ts
index 2bccfa1944..ba8c17d3c9 100644
--- a/controls/documenteditor/spec/implementation/collaboration/table_paste_option.spec.ts
+++ b/controls/documenteditor/spec/implementation/collaboration/table_paste_option.spec.ts
@@ -1,158 +1,158 @@
-import { DocumentEditorContainer, ContainerContentChangeEventArgs, CONTROL_CHARACTERS, HelperMethods, Operation } from '../../../src/index';
-import { createElement } from '@syncfusion/ej2-base';
-import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
-/**
- * Footnote endnote collaborative editing spec
- */
-describe('Table paste options in collaborative editing', () => {
- let container: DocumentEditorContainer;
- let element: HTMLElement;
- let args: ContainerContentChangeEventArgs;
- let pasteValue: string = "UEsDBBQAAAAIABZlM1jb23r+FQQAAOFOAAAEAAAAc2ZkdOxcS2/bMAz+K4F2DQo7ie0mt2FFjkWx7bb14Gds1C/IcrM16H8fKcpumqZt3KBDkTIHi5IoyZIofhIdcSOqWmVFdhf/SCIlFkq28Vg0cSgWvzYi0E+pn0rWQGyEH8gbsbDHIo0gbkEIzzMMoTgEQSQb5MshCs9GJ+ZrZHKgZuSGoO4KlcQA7Ykvlv4tl+J+LOTqqOKqPqp4cNzL3x5VGviOKB1FXXG7K249VxzZ2wHswJ8XYuGczWCCOkIVhikgApi2pSdMsAGggSPTz5bqJnFJmjto2sbyCXCKb36eBTITEN3qmmVBQkDFAxNmJoQakOrqQHq7lsTfiSfxTkK5k+KHVD8MpG1Np0ghx8RyJkhjA0SHNAUN8NsW9bzWvc2z0oyJ7Kmkp4LGEH5HNAG8JIY+hXo6MCM3o1TlOlCUfbMuKcQ1BuEaX6AfH/NWT9fhqxNsP1p3B7E/rLOD2B/W1QHsKG4Z6Z4cssQFzA1J04ES9PEF5n7cda4K2yIu1eiU+xhHmarkCfbw+v4alkJIABlWOUoyCLhcG6IGSbcd5+wcNdnUcmzP8c4xGfoOFd7Ssmbk3ELOg8ArHQZ10SBdNQAZQVdBkq4epRkRcN+M66XAqMioyKjIqMio2KOiAzrSBcx1bMcFOGRYPH1YfDTljIt8WuTTIp8W+bT4+LTIuPjZcfFabxPZ8s6Wd7a8s+WdLe9seWfLO1ve3/eb9alspdjyzt+j+Xs0f4/m79HPf49mC8Ong0W2vDMuMi4yLjIuMi7ycZEt7/yf95e3aWx5Z8s7W97Z8s6Wd7a8s+WdLe98E4xvgvFNML4JduRNMLa8s+Wd74LxXTC+C8Z3wfguGOPiJ/6j1pP/vOMWCpjKNs+hjRi3V0SrIDdOaNpEUaPkhYTGZ+5MXW82nfTOSXaTd12VQPneK4fxraEvH+69jH/QAA5wn2ENc59hDXOfYX0cSXmLmxnj5CGtaVZS4tCacqBDmZ9ZETejy3g9+l4Vfvl2xzL+/srIscS+jPKZnP/qX+b8Bf8y3tx2XdexPG9izWceu5vR7ma0/klxnFFjxeYsl8JsTV090D2FhznXnmgSJNmbaxJVkqcp1EJEoeIhCjUPUVGCQg1hFRNhxE7W5N2nbiiMS3gXkAaQJ8rPujAmvhWuGvFV+kEWojSjeIO8XfmrWIA6fUloegl5TSKMdtSehnB5ajWn19HS/BCaGvWX/PVoZmhEXFay8HN4q/LPdoydQh0z/nq/qDUpDvFFnPhtrkZXvvRX0q/T0bIqlcCJjxRIqJHawlREyqemmJYtlMFUFeRiyleS3LolCSnrBNrYCKBhXre9Mf1u0bMJNIMNoabalz/r8qESkw9xkJT4XWoNqwKYYK2AIMJeAbHkHwAAAP//AwBQSwECLQAUAAAACAAWZTNY29t6/hUEAADhTgAABAAAAAAAAAAAACAAAAAAAAAAc2ZkdFBLBQYAAAAAAQABADIAAAA3BAAAAAA=";
- beforeAll(() => {
- element = createElement('div');
- document.body.appendChild(element);
- DocumentEditorContainer.Inject(Toolbar);
- container = new DocumentEditorContainer();
- container.appendTo(element);
- container.documentEditor.enableCollaborativeEditing = true;
- });
- afterAll(() => {
- expect(() => { container.destroy(); }).not.toThrowError();
- expect(element.childNodes.length).toBe(0);
- document.body.removeChild(element);
- document.body.innerHTML = '';
- element = undefined;
- container = undefined;
- });
+// import { DocumentEditorContainer, ContainerContentChangeEventArgs, CONTROL_CHARACTERS, HelperMethods, Operation } from '../../../src/index';
+// import { createElement } from '@syncfusion/ej2-base';
+// import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
+// /**
+// * Footnote endnote collaborative editing spec
+// */
+// describe('Table paste options in collaborative editing', () => {
+// let container: DocumentEditorContainer;
+// let element: HTMLElement;
+// let args: ContainerContentChangeEventArgs;
+// let pasteValue: string = "UEsDBBQAAAAIABZlM1jb23r+FQQAAOFOAAAEAAAAc2ZkdOxcS2/bMAz+K4F2DQo7ie0mt2FFjkWx7bb14Gds1C/IcrM16H8fKcpumqZt3KBDkTIHi5IoyZIofhIdcSOqWmVFdhf/SCIlFkq28Vg0cSgWvzYi0E+pn0rWQGyEH8gbsbDHIo0gbkEIzzMMoTgEQSQb5MshCs9GJ+ZrZHKgZuSGoO4KlcQA7Ykvlv4tl+J+LOTqqOKqPqp4cNzL3x5VGviOKB1FXXG7K249VxzZ2wHswJ8XYuGczWCCOkIVhikgApi2pSdMsAGggSPTz5bqJnFJmjto2sbyCXCKb36eBTITEN3qmmVBQkDFAxNmJoQakOrqQHq7lsTfiSfxTkK5k+KHVD8MpG1Np0ghx8RyJkhjA0SHNAUN8NsW9bzWvc2z0oyJ7Kmkp4LGEH5HNAG8JIY+hXo6MCM3o1TlOlCUfbMuKcQ1BuEaX6AfH/NWT9fhqxNsP1p3B7E/rLOD2B/W1QHsKG4Z6Z4cssQFzA1J04ES9PEF5n7cda4K2yIu1eiU+xhHmarkCfbw+v4alkJIABlWOUoyCLhcG6IGSbcd5+wcNdnUcmzP8c4xGfoOFd7Ssmbk3ELOg8ArHQZ10SBdNQAZQVdBkq4epRkRcN+M66XAqMioyKjIqMio2KOiAzrSBcx1bMcFOGRYPH1YfDTljIt8WuTTIp8W+bT4+LTIuPjZcfFabxPZ8s6Wd7a8s+WdLe9seWfLO1ve3/eb9alspdjyzt+j+Xs0f4/m79HPf49mC8Ong0W2vDMuMi4yLjIuMi7ycZEt7/yf95e3aWx5Z8s7W97Z8s6Wd7a8s+WdLe98E4xvgvFNML4JduRNMLa8s+Wd74LxXTC+C8Z3wfguGOPiJ/6j1pP/vOMWCpjKNs+hjRi3V0SrIDdOaNpEUaPkhYTGZ+5MXW82nfTOSXaTd12VQPneK4fxraEvH+69jH/QAA5wn2ENc59hDXOfYX0cSXmLmxnj5CGtaVZS4tCacqBDmZ9ZETejy3g9+l4Vfvl2xzL+/srIscS+jPKZnP/qX+b8Bf8y3tx2XdexPG9izWceu5vR7ma0/klxnFFjxeYsl8JsTV090D2FhznXnmgSJNmbaxJVkqcp1EJEoeIhCjUPUVGCQg1hFRNhxE7W5N2nbiiMS3gXkAaQJ8rPujAmvhWuGvFV+kEWojSjeIO8XfmrWIA6fUloegl5TSKMdtSehnB5ajWn19HS/BCaGvWX/PVoZmhEXFay8HN4q/LPdoydQh0z/nq/qDUpDvFFnPhtrkZXvvRX0q/T0bIqlcCJjxRIqJHawlREyqemmJYtlMFUFeRiyleS3LolCSnrBNrYCKBhXre9Mf1u0bMJNIMNoabalz/r8qESkw9xkJT4XWoNqwKYYK2AIMJeAbHkHwAAAP//AwBQSwECLQAUAAAACAAWZTNY29t6/hUEAADhTgAABAAAAAAAAAAAACAAAAAAAAAAc2ZkdFBLBQYAAAAAAQABADIAAAA3BAAAAAA=";
+// beforeAll(() => {
+// element = createElement('div');
+// document.body.appendChild(element);
+// DocumentEditorContainer.Inject(Toolbar);
+// container = new DocumentEditorContainer();
+// container.appendTo(element);
+// container.documentEditor.enableCollaborativeEditing = true;
+// });
+// afterAll(() => {
+// expect(() => { container.destroy(); }).not.toThrowError();
+// expect(element.childNodes.length).toBe(0);
+// document.body.removeChild(element);
+// document.body.innerHTML = '';
+// element = undefined;
+// container = undefined;
+// });
- it('insert table paste insert column option', () => {
- console.log('insert table paste insert column option');
- let operations: Operation[] = [];
- let addpaste: boolean = false;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (addpaste) {
- operations.push(...args.operations);
- }
- }
- container.documentEditor.editorModule.insertTable(2, 2);
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;0;1;0;0", "0;0;0;1;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;1;0;0", "0;0;1;1;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;0;0;0;0", "0;0;0;0;0;0");
- addpaste = true;
- container.documentEditor.editorModule.pasteContents(HelperMethods.getSfdtDocument({ sfdt: pasteValue }));
- expect(operations[0].action).toBe('Delete');
- expect(operations[0].length).toBe(51);
- expect(operations[0].offset).toBe(1);
- expect(operations[1].action).toBe('Insert');
- expect(operations[1].length).toBe(209);
- expect(operations[1].offset).toBe(1);
- expect(operations[1].pasteContent).toBeDefined();
- operations = [];
- });
+// it('insert table paste insert column option', () => {
+// console.log('insert table paste insert column option');
+// let operations: Operation[] = [];
+// let addpaste: boolean = false;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (addpaste) {
+// operations.push(...args.operations);
+// }
+// }
+// container.documentEditor.editorModule.insertTable(2, 2);
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;0;1;0;0", "0;0;0;1;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;1;0;0", "0;0;1;1;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;0;0;0;0", "0;0;0;0;0;0");
+// addpaste = true;
+// container.documentEditor.editorModule.pasteContents(HelperMethods.getSfdtDocument({ sfdt: pasteValue }));
+// expect(operations[0].action).toBe('Delete');
+// expect(operations[0].length).toBe(51);
+// expect(operations[0].offset).toBe(1);
+// expect(operations[1].action).toBe('Insert');
+// expect(operations[1].length).toBe(209);
+// expect(operations[1].offset).toBe(1);
+// expect(operations[1].pasteContent).toBeDefined();
+// operations = [];
+// });
- it('insert table paste overwrite cell option', () => {
- console.log('insert table paste overwrite cell option');
- let operations: Operation[] = [];
- let addpaste: boolean = false;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (addpaste) {
- operations.push(...args.operations);
- }
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertTable(2, 2);
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;0;1;0;0", "0;0;0;1;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;1;0;0", "0;0;1;1;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
- addpaste = true;
- container.documentEditor.editorModule.pasteContents(HelperMethods.getSfdtDocument({ sfdt: pasteValue }));
- expect(operations[0].action).toBe('Delete');
- expect(operations[0].length).toBe(51);
- expect(operations[0].offset).toBe(1);
- expect(operations[1].action).toBe('Insert');
- expect(operations[1].length).toBe(182);
- expect(operations[1].offset).toBe(1);
- expect(operations[1].pasteContent).toBeDefined();
- operations = [];
- });
+// it('insert table paste overwrite cell option', () => {
+// console.log('insert table paste overwrite cell option');
+// let operations: Operation[] = [];
+// let addpaste: boolean = false;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (addpaste) {
+// operations.push(...args.operations);
+// }
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertTable(2, 2);
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;0;1;0;0", "0;0;0;1;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;1;0;0", "0;0;1;1;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
+// addpaste = true;
+// container.documentEditor.editorModule.pasteContents(HelperMethods.getSfdtDocument({ sfdt: pasteValue }));
+// expect(operations[0].action).toBe('Delete');
+// expect(operations[0].length).toBe(51);
+// expect(operations[0].offset).toBe(1);
+// expect(operations[1].action).toBe('Insert');
+// expect(operations[1].length).toBe(182);
+// expect(operations[1].offset).toBe(1);
+// expect(operations[1].pasteContent).toBeDefined();
+// operations = [];
+// });
- it('insert table paste option', () => {
- console.log('insert table paste option');
- let operations: Operation[] = [];
- let addpaste: boolean = false;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- if (addpaste) {
- operations.push(...args.operations);
- }
- }
- container.documentEditor.openBlank();
- container.documentEditor.editorModule.insertTable(2, 2);
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;0;1;0;0", "0;0;0;1;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;1;0;0", "0;0;1;1;0;0");
- container.documentEditor.editorModule.insertText('Syncfusion');
- container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
- container.documentEditor.editorModule.pasteContents(HelperMethods.getSfdtDocument({ sfdt: pasteValue }));
- addpaste = true;
- container.documentEditor.editorModule.copiedTextContent = "Document editor Document editor Document editor Document editor Document editor Document editor Document editor Document editor Document editor";
- container.documentEditor.editor.applyTablePasteOptions('InsertAsRows');
- expect(operations[0].action).toBe('Delete');
- expect(operations[0].length).toBe(182);
- expect(operations[0].offset).toBe(1);
- expect(operations[1].action).toBe('Insert');
- expect(operations[1].length).toBe(51);
- expect(operations[1].offset).toBe(1);
- expect(operations[1].pasteContent).toBeDefined();
- expect(operations[2].action).toBe('Delete');
- expect(operations[2].length).toBe(51);
- expect(operations[2].offset).toBe(1);
- expect(operations[3].action).toBe('Insert');
- expect(operations[3].length).toBe(207);
- expect(operations[3].offset).toBe(1);
- expect(operations[3].pasteContent).toBeDefined();
- operations = [];
- container.documentEditor.editor.applyTablePasteOptions('OverwriteCells');
- expect(operations[0].action).toBe('Delete');
- expect(operations[0].length).toBe(207);
- expect(operations[0].offset).toBe(1);
- expect(operations[1].action).toBe('Insert');
- expect(operations[1].length).toBe(51);
- expect(operations[1].offset).toBe(1);
- expect(operations[1].pasteContent).toBeDefined();
- expect(operations[2].action).toBe('Delete');
- expect(operations[2].length).toBe(51);
- expect(operations[2].offset).toBe(1);
- expect(operations[3].action).toBe('Insert');
- expect(operations[3].length).toBe(182);
- expect(operations[3].offset).toBe(1);
- expect(operations[3].pasteContent).toBeDefined();
- operations = [];
- container.documentEditor.editor.applyTablePasteOptions('NestTable');
- expect(operations[0].action).toBe('Delete');
- expect(operations[0].length).toBe(182);
- expect(operations[0].offset).toBe(1);
- expect(operations[1].action).toBe('Insert');
- expect(operations[1].length).toBe(51);
- expect(operations[1].offset).toBe(1);
- expect(operations[1].pasteContent).toBeDefined();
- expect(operations[2].action).toBe('Insert');
- expect(operations[2].length).toBe(157);
- expect(operations[2].offset).toBe(29);
- expect(operations[2].pasteContent).toBeDefined();
- addpaste = false;
- });
-});
\ No newline at end of file
+// it('insert table paste option', () => {
+// console.log('insert table paste option');
+// let operations: Operation[] = [];
+// let addpaste: boolean = false;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// if (addpaste) {
+// operations.push(...args.operations);
+// }
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.editorModule.insertTable(2, 2);
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;0;1;0;0", "0;0;0;1;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;1;0;0", "0;0;1;1;0;0");
+// container.documentEditor.editorModule.insertText('Syncfusion');
+// container.documentEditor.selection.select("0;0;1;0;0;0", "0;0;1;0;0;0");
+// container.documentEditor.editorModule.pasteContents(HelperMethods.getSfdtDocument({ sfdt: pasteValue }));
+// addpaste = true;
+// container.documentEditor.editorModule.copiedTextContent = "Document editor Document editor Document editor Document editor Document editor Document editor Document editor Document editor Document editor";
+// container.documentEditor.editor.applyTablePasteOptions('InsertAsRows');
+// expect(operations[0].action).toBe('Delete');
+// expect(operations[0].length).toBe(182);
+// expect(operations[0].offset).toBe(1);
+// expect(operations[1].action).toBe('Insert');
+// expect(operations[1].length).toBe(51);
+// expect(operations[1].offset).toBe(1);
+// expect(operations[1].pasteContent).toBeDefined();
+// expect(operations[2].action).toBe('Delete');
+// expect(operations[2].length).toBe(51);
+// expect(operations[2].offset).toBe(1);
+// expect(operations[3].action).toBe('Insert');
+// expect(operations[3].length).toBe(207);
+// expect(operations[3].offset).toBe(1);
+// expect(operations[3].pasteContent).toBeDefined();
+// operations = [];
+// container.documentEditor.editor.applyTablePasteOptions('OverwriteCells');
+// expect(operations[0].action).toBe('Delete');
+// expect(operations[0].length).toBe(207);
+// expect(operations[0].offset).toBe(1);
+// expect(operations[1].action).toBe('Insert');
+// expect(operations[1].length).toBe(51);
+// expect(operations[1].offset).toBe(1);
+// expect(operations[1].pasteContent).toBeDefined();
+// expect(operations[2].action).toBe('Delete');
+// expect(operations[2].length).toBe(51);
+// expect(operations[2].offset).toBe(1);
+// expect(operations[3].action).toBe('Insert');
+// expect(operations[3].length).toBe(182);
+// expect(operations[3].offset).toBe(1);
+// expect(operations[3].pasteContent).toBeDefined();
+// operations = [];
+// container.documentEditor.editor.applyTablePasteOptions('NestTable');
+// expect(operations[0].action).toBe('Delete');
+// expect(operations[0].length).toBe(182);
+// expect(operations[0].offset).toBe(1);
+// expect(operations[1].action).toBe('Insert');
+// expect(operations[1].length).toBe(51);
+// expect(operations[1].offset).toBe(1);
+// expect(operations[1].pasteContent).toBeDefined();
+// expect(operations[2].action).toBe('Insert');
+// expect(operations[2].length).toBe(157);
+// expect(operations[2].offset).toBe(29);
+// expect(operations[2].pasteContent).toBeDefined();
+// addpaste = false;
+// });
+// });
\ No newline at end of file
diff --git a/controls/documenteditor/spec/implementation/collaboration/trackchange.spec.ts b/controls/documenteditor/spec/implementation/collaboration/trackchange.spec.ts
index 0145ece746..a0a718cfd5 100644
--- a/controls/documenteditor/spec/implementation/collaboration/trackchange.spec.ts
+++ b/controls/documenteditor/spec/implementation/collaboration/trackchange.spec.ts
@@ -1,193 +1,193 @@
-import { DocumentEditorContainer, ContainerContentChangeEventArgs } from '../../../src/index';
-import { createElement } from '@syncfusion/ej2-base';
-import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
-/**
- * Track changes collaborative editing spec
- */
-describe('Enable track changes in collaborative editing', () => {
- let container: DocumentEditorContainer;
- let element: HTMLElement;
- let args: ContainerContentChangeEventArgs;
- beforeAll(() => {
- element = createElement('div');
- document.body.appendChild(element);
- DocumentEditorContainer.Inject(Toolbar);
- container = new DocumentEditorContainer();
- container.appendTo(element);
- container.documentEditor.enableCollaborativeEditing = true;
- });
- afterAll(() => {
- expect(() => { container.destroy(); }).not.toThrowError();
- expect(element.childNodes.length).toBe(0);
- document.body.removeChild(element);
- document.body.innerHTML = '';
- element = undefined;
- container = undefined;
- });
+// import { DocumentEditorContainer, ContainerContentChangeEventArgs } from '../../../src/index';
+// import { createElement } from '@syncfusion/ej2-base';
+// import { Toolbar } from '../../../src/document-editor-container/tool-bar/tool-bar';
+// /**
+// * Track changes collaborative editing spec
+// */
+// describe('Enable track changes in collaborative editing', () => {
+// let container: DocumentEditorContainer;
+// let element: HTMLElement;
+// let args: ContainerContentChangeEventArgs;
+// beforeAll(() => {
+// element = createElement('div');
+// document.body.appendChild(element);
+// DocumentEditorContainer.Inject(Toolbar);
+// container = new DocumentEditorContainer();
+// container.appendTo(element);
+// container.documentEditor.enableCollaborativeEditing = true;
+// });
+// afterAll(() => {
+// expect(() => { container.destroy(); }).not.toThrowError();
+// expect(element.childNodes.length).toBe(0);
+// document.body.removeChild(element);
+// document.body.innerHTML = '';
+// element = undefined;
+// container = undefined;
+// });
- it('Undo/Redo insert text', () => {
- console.log('Undo/Redo insert text when enable track changes');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.enableTrackChanges = true;
- container.documentEditor.editorModule.insertText('S');
- expect(argsEle.operations[0].markerData).toBeDefined();
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations.length).toBe(1);
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].type).toBe('Paste')
- expect(argsEle.operations[0].pasteContent).toBeDefined();
- });
+// it('Undo/Redo insert text', () => {
+// console.log('Undo/Redo insert text when enable track changes');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.enableTrackChanges = true;
+// container.documentEditor.editorModule.insertText('S');
+// expect(argsEle.operations[0].markerData).toBeDefined();
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations.length).toBe(1);
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].type).toBe('Paste')
+// expect(argsEle.operations[0].pasteContent).toBeDefined();
+// });
- it('Undo/Redo delete text', () => {
- console.log('Undo/Redo delete text when enable track changes');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.enableTrackChanges = false;
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.enableTrackChanges = true;
- container.documentEditor.selection.select('0;0;2', '0;0;2');
- container.documentEditor.editorModule.onBackSpace();
- expect(argsEle.operations[0].markerData).toBeDefined();
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations[0].action).toBe('Delete');
- expect(argsEle.operations[0].markerData.isSkipTracking).toBe(true);
- expect(argsEle.operations[1].type).toBe('Paste')
- expect(argsEle.operations[1].pasteContent).toBeDefined();
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].action).toBe('Format');
- expect(argsEle.operations[0].markerData).toBeDefined();
- });
+// it('Undo/Redo delete text', () => {
+// console.log('Undo/Redo delete text when enable track changes');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.enableTrackChanges = false;
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.enableTrackChanges = true;
+// container.documentEditor.selection.select('0;0;2', '0;0;2');
+// container.documentEditor.editorModule.onBackSpace();
+// expect(argsEle.operations[0].markerData).toBeDefined();
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations[0].action).toBe('Delete');
+// expect(argsEle.operations[0].markerData.isSkipTracking).toBe(true);
+// expect(argsEle.operations[1].type).toBe('Paste')
+// expect(argsEle.operations[1].pasteContent).toBeDefined();
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].action).toBe('Format');
+// expect(argsEle.operations[0].markerData).toBeDefined();
+// });
- it('Undo/Redo Split revision', () => {
- console.log('Undo/Redo split revision track changes');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.enableTrackChanges = false;
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.enableTrackChanges = true;
- container.documentEditor.selection.select('0;0;2', '0;0;7');
- container.documentEditor.editorModule.onBackSpace();
- expect(argsEle.operations[0].markerData).toBeDefined();
- container.documentEditor.selection.select('0;0;4', '0;0;4');
- container.documentEditor.editorModule.insertText('a');
- let insertRevisionID: string = argsEle.operations[0].markerData.revisionId;
- expect(argsEle.operations[0].markerData.splittedRevisions.length).toBe(1);
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations[0].action).toBe('Delete');
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].type).toBe('Paste')
- expect(argsEle.operations[0].pasteContent).toBeDefined();
- });
+// it('Undo/Redo Split revision', () => {
+// console.log('Undo/Redo split revision track changes');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.enableTrackChanges = false;
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.enableTrackChanges = true;
+// container.documentEditor.selection.select('0;0;2', '0;0;7');
+// container.documentEditor.editorModule.onBackSpace();
+// expect(argsEle.operations[0].markerData).toBeDefined();
+// container.documentEditor.selection.select('0;0;4', '0;0;4');
+// container.documentEditor.editorModule.insertText('a');
+// let insertRevisionID: string = argsEle.operations[0].markerData.revisionId;
+// expect(argsEle.operations[0].markerData.splittedRevisions.length).toBe(1);
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations[0].action).toBe('Delete');
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].type).toBe('Paste')
+// expect(argsEle.operations[0].pasteContent).toBeDefined();
+// });
- it('Backspace on muliple paragraph', () => {
- console.log('Backspace on muliple paragraph');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.enableTrackChanges = false;
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.editor.onEnter();
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.editor.onEnter();
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.enableTrackChanges = true;
- container.documentEditor.selection.select('0;0;0', '0;2;10');
- container.documentEditor.editorModule.onBackSpace();
- expect(argsEle.operations[0].markerData).toBeDefined();
- expect(argsEle.operations[0].markerData.revisionType).toBe('Deletion');
- expect(argsEle.operations[0].markerData.splittedRevisions.length).toBe(4);
- });
+// it('Backspace on muliple paragraph', () => {
+// console.log('Backspace on muliple paragraph');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.enableTrackChanges = false;
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.editor.onEnter();
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.editor.onEnter();
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.enableTrackChanges = true;
+// container.documentEditor.selection.select('0;0;0', '0;2;10');
+// container.documentEditor.editorModule.onBackSpace();
+// expect(argsEle.operations[0].markerData).toBeDefined();
+// expect(argsEle.operations[0].markerData.revisionType).toBe('Deletion');
+// expect(argsEle.operations[0].markerData.splittedRevisions.length).toBe(4);
+// });
- it('Selection with insert', () => {
- console.log('Selection with insert');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.enableTrackChanges = false;
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.enableTrackChanges = true;
- container.documentEditor.selection.select('0;0;0', '0;0;10');
- container.documentEditor.editorModule.insertText('S');
- expect(argsEle.operations[0].action).toBe('Format');
- expect(argsEle.operations[0].length).toBe(10);
- expect(argsEle.operations[0].markerData.revisionType).toBe('Deletion');
- expect(argsEle.operations[1].action).toBe('Insert');
- expect(argsEle.operations[1].offset).toBe(11);
- expect(argsEle.operations[1].markerData.revisionType).toBe('Insertion');
- });
+// it('Selection with insert', () => {
+// console.log('Selection with insert');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.enableTrackChanges = false;
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.enableTrackChanges = true;
+// container.documentEditor.selection.select('0;0;0', '0;0;10');
+// container.documentEditor.editorModule.insertText('S');
+// expect(argsEle.operations[0].action).toBe('Format');
+// expect(argsEle.operations[0].length).toBe(10);
+// expect(argsEle.operations[0].markerData.revisionType).toBe('Deletion');
+// expect(argsEle.operations[1].action).toBe('Insert');
+// expect(argsEle.operations[1].offset).toBe(11);
+// expect(argsEle.operations[1].markerData.revisionType).toBe('Insertion');
+// });
- it('Selection with insert revision and delete', () => {
- console.log('Selection with insert revision and delete');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.enableTrackChanges = false;
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.enableTrackChanges = true;
- container.documentEditor.selection.select('0;0;1', '0;0;1');
- container.documentEditor.editorModule.insertText('S');
- container.documentEditor.selection.select('0;0;3', '0;0;3');
- container.documentEditor.editorModule.insertText('S');
- container.documentEditor.selection.select('0;0;5', '0;0;5');
- container.documentEditor.editorModule.insertText('S');
- container.documentEditor.selection.select('0;0;0', '0;0;13');
- container.documentEditor.editorModule.onBackSpace();
- expect(argsEle.operations.length).toBe(4);
- expect(argsEle.operations[0].action).toBe('Delete');
- expect(argsEle.operations[0].offset).toBe(6);
- expect(argsEle.operations[1].action).toBe('Delete');
- expect(argsEle.operations[1].offset).toBe(4);
- expect(argsEle.operations[2].action).toBe('Delete');
- expect(argsEle.operations[2].offset).toBe(2);
- expect(argsEle.operations[3].action).toBe('Format');
- expect(argsEle.operations[3].offset).toBe(1);
- expect(argsEle.operations[3].length).toBe(10);
- expect(argsEle.operations[3].markerData).toBeDefined();
- });
+// it('Selection with insert revision and delete', () => {
+// console.log('Selection with insert revision and delete');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.enableTrackChanges = false;
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.enableTrackChanges = true;
+// container.documentEditor.selection.select('0;0;1', '0;0;1');
+// container.documentEditor.editorModule.insertText('S');
+// container.documentEditor.selection.select('0;0;3', '0;0;3');
+// container.documentEditor.editorModule.insertText('S');
+// container.documentEditor.selection.select('0;0;5', '0;0;5');
+// container.documentEditor.editorModule.insertText('S');
+// container.documentEditor.selection.select('0;0;0', '0;0;13');
+// container.documentEditor.editorModule.onBackSpace();
+// expect(argsEle.operations.length).toBe(4);
+// expect(argsEle.operations[0].action).toBe('Delete');
+// expect(argsEle.operations[0].offset).toBe(6);
+// expect(argsEle.operations[1].action).toBe('Delete');
+// expect(argsEle.operations[1].offset).toBe(4);
+// expect(argsEle.operations[2].action).toBe('Delete');
+// expect(argsEle.operations[2].offset).toBe(2);
+// expect(argsEle.operations[3].action).toBe('Format');
+// expect(argsEle.operations[3].offset).toBe(1);
+// expect(argsEle.operations[3].length).toBe(10);
+// expect(argsEle.operations[3].markerData).toBeDefined();
+// });
- it('Selection with insert revision and delete', () => {
- console.log('Selection with insert revision and delete');
- let argsEle: ContainerContentChangeEventArgs;
- container.contentChange = function (args: ContainerContentChangeEventArgs) {
- argsEle = args;
- }
- container.documentEditor.openBlank();
- container.documentEditor.enableTrackChanges = false;
- container.documentEditor.editorModule.insertText('Syncfusion Software');
- container.documentEditor.enableTrackChanges = true;
- container.documentEditor.selection.select('0;0;1', '0;0;1');
- container.documentEditor.editorModule.insertText('S');
- container.documentEditor.selection.select('0;0;3', '0;0;3');
- container.documentEditor.editorModule.insertText('S');
- container.documentEditor.selection.select('0;0;5', '0;0;5');
- container.documentEditor.editorModule.insertText('S');
- container.documentEditor.selection.select('0;0;0', '0;0;13');
- container.documentEditor.editorModule.onBackSpace();
- container.documentEditor.editorHistory.undo();
- expect(argsEle.operations[0].length).toBe(10);
- expect(argsEle.operations[0].action).toBe('Delete');
- expect(argsEle.operations[0].offset).toBe(1);
- expect(argsEle.operations[1].type).toBe('Paste')
- expect(argsEle.operations[1].pasteContent).toBeDefined();
- container.documentEditor.editorHistory.redo();
- expect(argsEle.operations[0].action).toBe('Format');
- expect(argsEle.operations[0].markerData).toBeDefined();
- });
-});
\ No newline at end of file
+// it('Selection with insert revision and delete', () => {
+// console.log('Selection with insert revision and delete');
+// let argsEle: ContainerContentChangeEventArgs;
+// container.contentChange = function (args: ContainerContentChangeEventArgs) {
+// argsEle = args;
+// }
+// container.documentEditor.openBlank();
+// container.documentEditor.enableTrackChanges = false;
+// container.documentEditor.editorModule.insertText('Syncfusion Software');
+// container.documentEditor.enableTrackChanges = true;
+// container.documentEditor.selection.select('0;0;1', '0;0;1');
+// container.documentEditor.editorModule.insertText('S');
+// container.documentEditor.selection.select('0;0;3', '0;0;3');
+// container.documentEditor.editorModule.insertText('S');
+// container.documentEditor.selection.select('0;0;5', '0;0;5');
+// container.documentEditor.editorModule.insertText('S');
+// container.documentEditor.selection.select('0;0;0', '0;0;13');
+// container.documentEditor.editorModule.onBackSpace();
+// container.documentEditor.editorHistory.undo();
+// expect(argsEle.operations[0].length).toBe(10);
+// expect(argsEle.operations[0].action).toBe('Delete');
+// expect(argsEle.operations[0].offset).toBe(1);
+// expect(argsEle.operations[1].type).toBe('Paste')
+// expect(argsEle.operations[1].pasteContent).toBeDefined();
+// container.documentEditor.editorHistory.redo();
+// expect(argsEle.operations[0].action).toBe('Format');
+// expect(argsEle.operations[0].markerData).toBeDefined();
+// });
+// });
\ No newline at end of file
diff --git a/controls/documenteditor/spec/implementation/editor_6.spec.ts b/controls/documenteditor/spec/implementation/editor_6.spec.ts
index 70ab1b04e3..7554c38e56 100644
--- a/controls/documenteditor/spec/implementation/editor_6.spec.ts
+++ b/controls/documenteditor/spec/implementation/editor_6.spec.ts
@@ -313,3 +313,794 @@ console.log('Undo - Enter -after apply character format and paragraph is not emp
expect(editor.selection.characterFormat.fontSize).toBe(11);
});
});
+
+describe('Table Style validation', () => {
+ let editor: DocumentEditor = undefined;
+ beforeAll(() => {
+ let ele: HTMLElement = createElement('div', { id: 'container' });
+ document.body.appendChild(ele);
+ editor = new DocumentEditor({ enableEditor: true, isReadOnly: false });
+ DocumentEditor.Inject(Editor, Selection, EditorHistory); editor.enableEditorHistory = true;
+ (editor.documentHelper as any).containerCanvasIn = TestHelper.containerCanvas;
+ (editor.documentHelper as any).selectionCanvasIn = TestHelper.selectionCanvas;
+ (editor.documentHelper.render as any).pageCanvasIn = TestHelper.pageCanvas;
+ (editor.documentHelper.render as any).selectionCanvasIn = TestHelper.pageSelectionCanvas;
+ editor.appendTo('#container');
+ });
+ afterAll((done) => {
+ editor.destroy();
+ document.body.removeChild(document.getElementById('container'));
+ editor = undefined;
+ setTimeout(function () {
+ document.body.innerHTML = '';
+ done();
+ }, 1000);
+ });
+
+ it('Document opening with table style test', () => {
+ console.log('Document opening with table style test');
+ expect(() => { editor.open(getJson()); }).not.toThrowError();
+ });
+
+ function getJson(): string {
+ const json: any = {
+ "optimizeSfdt": false,
+ "sections": [
+ {
+ "blocks": [
+ {
+ "inlines": []
+ },
+ {
+ "rows": [
+ {
+ "rowFormat": {
+ "allowBreakAcrossPages": true,
+ "isHeader": false,
+ "height": 0.0,
+ "heightType": "AtLeast",
+ "borders": {
+ "left": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "right": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "top": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "bottom": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "vertical": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "horizontal": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "diagonalDown": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "diagonalUp": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ }
+ },
+ "leftIndent": 13.25
+ },
+ "cells": [
+ {
+ "blocks": [
+ {
+ "characterFormat": {
+ "fontSize": 11.0,
+ "fontFamily": "Arial",
+ "fontSizeBidi": 11.0,
+ "fontFamilyBidi": "Arial",
+ "fontFamilyAscii": "Arial",
+ "fontFamilyFarEast": "minorHAnsi",
+ "fontFamilyNonFarEast": "Arial"
+ },
+ "paragraphFormat": {
+ "lineSpacing": 1.0,
+ "lineSpacingType": "Multiple"
+ },
+ "inlines": []
+ }
+ ],
+ "cellFormat": {
+ "columnSpan": 1,
+ "rowSpan": 1,
+ "preferredWidth": 31.25,
+ "preferredWidthType": "Point",
+ "verticalAlignment": "Top",
+ "borders": {
+ "left": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "right": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "top": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "bottom": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "vertical": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "horizontal": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "diagonalDown": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "diagonalUp": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ }
+ },
+ "cellWidth": 31.25
+ }
+ },
+ {
+ "blocks": [
+ {
+ "characterFormat": {
+ "fontSize": 11.0,
+ "fontFamily": "Arial",
+ "fontSizeBidi": 11.0,
+ "fontFamilyBidi": "Arial",
+ "fontFamilyAscii": "Arial",
+ "fontFamilyFarEast": "minorHAnsi",
+ "fontFamilyNonFarEast": "Arial"
+ },
+ "paragraphFormat": {
+ "lineSpacing": 1.0,
+ "lineSpacingType": "Multiple"
+ },
+ "inlines": [
+ {
+ "text": "Video content production and editing ",
+ "characterFormat": {
+ "fontSize": 11.0,
+ "fontFamily": "Arial",
+ "fontSizeBidi": 11.0,
+ "fontFamilyBidi": "Arial",
+ "fontFamilyAscii": "Arial",
+ "fontFamilyFarEast": "minorHAnsi",
+ "fontFamilyNonFarEast": "Arial"
+ }
+ }
+ ]
+ }
+ ],
+ "cellFormat": {
+ "columnSpan": 1,
+ "rowSpan": 1,
+ "preferredWidth": 436.25,
+ "preferredWidthType": "Point",
+ "verticalAlignment": "Top",
+ "borders": {
+ "left": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "right": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "top": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "bottom": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "vertical": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "horizontal": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "diagonalDown": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "diagonalUp": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ }
+ },
+ "cellWidth": 436.25
+ }
+ }
+ ]
+ }
+ ],
+ "title": null,
+ "description": null,
+ "tableFormat": {
+ "allowAutoFit": true,
+ "leftIndent": 13.25,
+ "tableAlignment": "Left",
+ "preferredWidth": 467.5,
+ "preferredWidthType": "Point",
+ "borders": {
+ "left": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "right": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "top": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "bottom": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "vertical": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "horizontal": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": true
+ },
+ "diagonalDown": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ },
+ "diagonalUp": {
+ "lineStyle": "None",
+ "lineWidth": 0.0,
+ "shadow": false,
+ "space": 0.0,
+ "hasNoneStyle": false
+ }
+ },
+ "bidi": false,
+ "horizontalPositionAbs": "Left",
+ "horizontalPosition": 0.0,
+ "styleName": "Table Grid"
+ }
+ },
+ {
+ "inlines": []
+ }
+ ],
+ "headersFooters": {
+ "firstPageHeader": {
+ "blocks": [
+ {
+ "inlines": []
+ }
+ ]
+ },
+ "firstPageFooter": {
+ "blocks": [
+ {
+ "inlines": []
+ }
+ ]
+ }
+ },
+ "sectionFormat": {
+ "headerDistance": 36.0,
+ "footerDistance": 36.0,
+ "pageWidth": 612.0,
+ "pageHeight": 792.0,
+ "leftMargin": 72.0,
+ "rightMargin": 72.0,
+ "topMargin": 72.0,
+ "bottomMargin": 72.0,
+ "differentFirstPage": false,
+ "differentOddAndEvenPages": false,
+ "bidi": false,
+ "restartPageNumbering": true,
+ "pageStartingNumber": 1,
+ "endnoteNumberFormat": "LowerCaseRoman",
+ "footNoteNumberFormat": "Arabic",
+ "restartIndexForFootnotes": "DoNotRestart",
+ "restartIndexForEndnotes": "DoNotRestart",
+ "pageNumberStyle": "Arabic",
+ "breakCode": "NewPage"
+ }
+ }
+ ],
+ "characterFormat": {
+ "fontSize": 11.0,
+ "fontFamily": "Arial",
+ "fontSizeBidi": 11.0,
+ "fontFamilyBidi": "Arial",
+ "fontFamilyAscii": "Arial",
+ "fontFamilyFarEast": "Arial",
+ "fontFamilyNonFarEast": "Arial",
+ "localeId": 9,
+ "localeIdFarEast": 1033,
+ "localeIdBidi": 1025
+ },
+ "paragraphFormat": {
+ "lineSpacing": 1.149999976158142,
+ "lineSpacingType": "Multiple"
+ },
+ "background": {
+ "color": "#FFFFFFFF"
+ },
+ "styles": [
+ {
+ "type": "Paragraph",
+ "name": "Normal",
+ "next": "Normal"
+ },
+ {
+ "type": "Paragraph",
+ "name": "Heading 1",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "fontSize": 20.0,
+ "fontSizeBidi": 20.0
+ },
+ "paragraphFormat": {
+ "beforeSpacing": 20.0,
+ "afterSpacing": 6.0,
+ "outlineLevel": "Level1",
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Paragraph",
+ "name": "Heading 2",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "fontSize": 16.0,
+ "fontSizeBidi": 16.0
+ },
+ "paragraphFormat": {
+ "beforeSpacing": 18.0,
+ "afterSpacing": 6.0,
+ "outlineLevel": "Level2",
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Paragraph",
+ "name": "Heading 3",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "fontSize": 14.0,
+ "fontColor": "#434343FF",
+ "fontSizeBidi": 14.0
+ },
+ "paragraphFormat": {
+ "beforeSpacing": 16.0,
+ "afterSpacing": 4.0,
+ "outlineLevel": "Level3",
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Paragraph",
+ "name": "Heading 4",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "fontSize": 12.0,
+ "fontColor": "#666666FF",
+ "fontSizeBidi": 12.0
+ },
+ "paragraphFormat": {
+ "beforeSpacing": 14.0,
+ "afterSpacing": 4.0,
+ "outlineLevel": "Level4",
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Paragraph",
+ "name": "Heading 5",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "fontColor": "#666666FF"
+ },
+ "paragraphFormat": {
+ "beforeSpacing": 12.0,
+ "afterSpacing": 4.0,
+ "outlineLevel": "Level5",
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Paragraph",
+ "name": "Heading 6",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "italic": true,
+ "fontColor": "#666666FF"
+ },
+ "paragraphFormat": {
+ "beforeSpacing": 12.0,
+ "afterSpacing": 4.0,
+ "outlineLevel": "Level6",
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Character",
+ "name": "Default Paragraph Font"
+ },
+ {
+ "type": "Table",
+ "name": "Normal Table",
+ "next": "Normal Table"
+ },
+ {
+ "type": "Paragraph",
+ "name": "Title",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "fontSize": 26.0,
+ "fontSizeBidi": 26.0
+ },
+ "paragraphFormat": {
+ "afterSpacing": 3.0,
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Paragraph",
+ "name": "Subtitle",
+ "basedOn": "Normal",
+ "next": "Normal",
+ "characterFormat": {
+ "fontSize": 15.0,
+ "fontColor": "#666666FF",
+ "fontSizeBidi": 15.0
+ },
+ "paragraphFormat": {
+ "afterSpacing": 16.0,
+ "keepWithNext": true,
+ "keepLinesTogether": true
+ }
+ },
+ {
+ "type": "Table",
+ "name": "a",
+ "basedOn": "Normal Table",
+ "next": "a"
+ },
+ {
+ "type": "Character",
+ "name": "Hyperlink",
+ "basedOn": "Default Paragraph Font",
+ "characterFormat": {
+ "underline": "Single",
+ "fontColor": "#0000FFFF"
+ }
+ },
+ {
+ "type": "Paragraph",
+ "name": "List Paragraph",
+ "basedOn": "Normal",
+ "next": "List Paragraph",
+ "paragraphFormat": {
+ "leftIndent": 36.0,
+ "contextualSpacing": true
+ }
+ },
+ {
+ "type": "Table",
+ "name": "Table Grid",
+ "basedOn": "Normal Table",
+ "next": "Table Grid"
+ }
+ ],
+ "defaultTabWidth": 36.0,
+ "formatting": false,
+ "trackChanges": false,
+ "protectionType": "NoProtection",
+ "enforcement": false,
+ "dontUseHTMLParagraphAutoSpacing": false,
+ "alignTablesRowByRow": false,
+ "formFieldShading": true,
+ "footnotes": {
+ "separator": [
+ {
+ "paragraphFormat": {
+ "lineSpacing": 1.0,
+ "lineSpacingType": "Multiple"
+ },
+ "inlines": [
+ {
+ "text": "\u0003"
+ }
+ ]
+ }
+ ],
+ "continuationSeparator": [
+ {
+ "paragraphFormat": {
+ "lineSpacing": 1.0,
+ "lineSpacingType": "Multiple"
+ },
+ "inlines": [
+ {
+ "text": "\u0004"
+ }
+ ]
+ }
+ ],
+ "continuationNotice": [
+ {
+ "inlines": []
+ }
+ ]
+ },
+ "endnotes": {
+ "separator": [
+ {
+ "paragraphFormat": {
+ "lineSpacing": 1.0,
+ "lineSpacingType": "Multiple"
+ },
+ "inlines": [
+ {
+ "text": "\u0003"
+ }
+ ]
+ }
+ ],
+ "continuationSeparator": [
+ {
+ "paragraphFormat": {
+ "lineSpacing": 1.0,
+ "lineSpacingType": "Multiple"
+ },
+ "inlines": [
+ {
+ "text": "\u0004"
+ }
+ ]
+ }
+ ],
+ "continuationNotice": [
+ {
+ "inlines": []
+ }
+ ]
+ },
+ "compatibilityMode": "Word2013",
+ "allowSpaceOfSameStyleInTable": false,
+ "themeFontLanguages": {
+ "localeId": 1033,
+ "localeIdBidi": 1025
+ },
+ "themes": {
+ "fontScheme": {
+ "fontSchemeName": "Office",
+ "majorFontScheme": {
+ "fontSchemeList": [
+ {
+ "name": "latin",
+ "typeface": "Calibri"
+ },
+ {
+ "name": "ea"
+ },
+ {
+ "name": "cs"
+ }
+ ],
+ "fontTypeface": {
+ "Jpan": "MS ゴシック",
+ "Hang": "맑은 고딕",
+ "Hans": "宋体",
+ "Hant": "新細明體",
+ "Arab": "Times New Roman",
+ "Hebr": "Times New Roman",
+ "Thai": "Angsana New",
+ "Ethi": "Nyala",
+ "Beng": "Vrinda",
+ "Gujr": "Shruti",
+ "Khmr": "MoolBoran",
+ "Knda": "Tunga",
+ "Guru": "Raavi",
+ "Cans": "Euphemia",
+ "Cher": "Plantagenet Cherokee",
+ "Yiii": "Microsoft Yi Baiti",
+ "Tibt": "Microsoft Himalaya",
+ "Thaa": "MV Boli",
+ "Deva": "Mangal",
+ "Telu": "Gautami",
+ "Taml": "Latha",
+ "Syrc": "Estrangelo Edessa",
+ "Orya": "Kalinga",
+ "Mlym": "Kartika",
+ "Laoo": "DokChampa",
+ "Sinh": "Iskoola Pota",
+ "Mong": "Mongolian Baiti",
+ "Viet": "Times New Roman",
+ "Uigh": "Microsoft Uighur",
+ "Geor": "Sylfaen"
+ }
+ },
+ "minorFontScheme": {
+ "fontSchemeList": [
+ {
+ "name": "latin",
+ "typeface": "Cambria"
+ },
+ {
+ "name": "ea"
+ },
+ {
+ "name": "cs"
+ }
+ ],
+ "fontTypeface": {
+ "Jpan": "MS 明朝",
+ "Hang": "맑은 고딕",
+ "Hans": "宋体",
+ "Hant": "新細明體",
+ "Arab": "Arial",
+ "Hebr": "Arial",
+ "Thai": "Cordia New",
+ "Ethi": "Nyala",
+ "Beng": "Vrinda",
+ "Gujr": "Shruti",
+ "Khmr": "DaunPenh",
+ "Knda": "Tunga",
+ "Guru": "Raavi",
+ "Cans": "Euphemia",
+ "Cher": "Plantagenet Cherokee",
+ "Yiii": "Microsoft Yi Baiti",
+ "Tibt": "Microsoft Himalaya",
+ "Thaa": "MV Boli",
+ "Deva": "Mangal",
+ "Telu": "Gautami",
+ "Taml": "Latha",
+ "Syrc": "Estrangelo Edessa",
+ "Orya": "Kalinga",
+ "Mlym": "Kartika",
+ "Laoo": "DokChampa",
+ "Sinh": "Iskoola Pota",
+ "Mong": "Mongolian Baiti",
+ "Viet": "Arial",
+ "Uigh": "Microsoft Uighur",
+ "Geor": "Sylfaen"
+ }
+ }
+ }
+ }
+ };
+ return JSON.stringify(json);
+ }
+});
diff --git a/controls/documenteditor/src/document-editor/base/types.ts b/controls/documenteditor/src/document-editor/base/types.ts
index fbee956e1d..1be9d71d12 100644
--- a/controls/documenteditor/src/document-editor/base/types.ts
+++ b/controls/documenteditor/src/document-editor/base/types.ts
@@ -894,7 +894,11 @@ export type StyleType =
/**
* Character style.
*/
- 'Character';
+ 'Character' |
+ /**
+ * Table style.
+ */
+ 'Table';
/**
* Specifies table row placement.
diff --git a/controls/documenteditor/src/document-editor/implementation/collaboration/collaboration.ts b/controls/documenteditor/src/document-editor/implementation/collaboration/collaboration.ts
index 2d14e3af5c..94f7d3ef9f 100644
--- a/controls/documenteditor/src/document-editor/implementation/collaboration/collaboration.ts
+++ b/controls/documenteditor/src/document-editor/implementation/collaboration/collaboration.ts
@@ -285,7 +285,6 @@ export class CollaborativeEditingHandler {
let currentEditMode: boolean = this.documentEditor.commentReviewPane.commentPane.isEditMode;
let currenteditorHistory = this.documentEditor.editorHistoryModule.lastOperation;
let currentTextArea: HTMLTextAreaElement;
- let isFieldOperation: boolean = false;
if (!isNullOrUndefined(this.documentEditor.commentReviewPane.commentPane.currentEditingComment)) {
currentTextArea = this.documentEditor.commentReviewPane.commentPane.currentEditingComment.textArea as HTMLTextAreaElement;
}
@@ -297,7 +296,7 @@ export class CollaborativeEditingHandler {
this.documentEditor.currentUser = markerData.author;
}
if (!isNullOrUndefined(markerData) && !isNullOrUndefined(markerData.isSkipTracking) && markerData.isSkipTracking && this.documentEditor.enableTrackChanges) {
- this.documentEditor.editorModule.isSkipOperationsBuild = true;
+ this.documentEditor.skipSettingsOps = true;
this.documentEditor.enableTrackChanges = false;
}
if (action.operations[i].skipOperation || (!isNullOrUndefined(action.operations[i].markerData) && action.operations[i].markerData.skipOperation)) {
@@ -505,7 +504,7 @@ export class CollaborativeEditingHandler {
this.documentEditor.editorModule.insertElementsInternal(this.documentEditor.selectionModule.start, [element]);
this.documentEditor.editorModule.fireContentChange();
} else if (markerData.type && markerData.type === 'Field') {
- isFieldOperation = true;
+ this.documentEditor.editor.isFieldOperation = true;
let type: number = op2.text === CONTROL_CHARACTERS.Marker_Start ? 0 : op2.text === CONTROL_CHARACTERS.Marker_End ? 1 : op2.text === CONTROL_CHARACTERS.Field_Separator ? 2 : undefined;
if (!isNullOrUndefined(type) && isNullOrUndefined(markerData.checkBoxValue)) {
var field = new FieldElementBox(type);
@@ -735,7 +734,7 @@ export class CollaborativeEditingHandler {
}
this.documentEditor.editorModule.revisionData = [];
if(this.documentEditor.enableTrackChanges != trackingCurrentValue) {
- this.documentEditor.editorModule.isSkipOperationsBuild = true;
+ this.documentEditor.skipSettingsOps = true;
this.documentEditor.enableTrackChanges = trackingCurrentValue;
}
this.documentEditor.currentUser = currentUser;
@@ -761,9 +760,9 @@ export class CollaborativeEditingHandler {
this.documentEditor.optionsPaneModule.searchIconClickInternal();
}
}
- if (isFieldOperation) {
+ if (this.documentEditor.editor.isFieldOperation) {
this.documentEditor.editorModule.layoutWholeDocument();
- isFieldOperation = false;
+ this.documentEditor.editor.isFieldOperation = false;
}
if (!isNullOrUndefined(this.rowWidget)) {
let ownerTable: TableWidget = this.rowWidget.ownerTable.combineWidget(this.documentEditor.viewer) as TableWidget;
@@ -1465,8 +1464,10 @@ export class CollaborativeEditingHandler {
let data: ActionInfo = dataObject[i]
if (data.connectionId === this.connectionId) {
this.acknowledgementReceived();
+ this.logMessage(this.isSyncServerChanges ? 'SignalR Server sync' + data.version : 'SignalR Same user sync:' + data.version);
} else {
this.handleRemoteOperation(data);
+ this.logMessage('Received: ' + JSON.stringify(JSON.stringify(data)));
}
this.updateVersion(data.version);
this.logMessage('Server sync ack:' + data.version);
diff --git a/controls/documenteditor/src/document-editor/implementation/editor-history/base-history-info.ts b/controls/documenteditor/src/document-editor/implementation/editor-history/base-history-info.ts
index 098d1e26a7..ba6828f39c 100644
--- a/controls/documenteditor/src/document-editor/implementation/editor-history/base-history-info.ts
+++ b/controls/documenteditor/src/document-editor/implementation/editor-history/base-history-info.ts
@@ -204,26 +204,22 @@ export class BaseHistoryInfo {
}
public updateSelection(): void {
- this.updateCollaborativeSelection();
+ this.updateCollaborativeSelection(this.owner.selectionModule.start.clone(), this.owner.selectionModule.end.clone());
let blockInfo: ParagraphInfo = this.owner.selectionModule.getParagraphInfo(this.owner.selectionModule.start);
this.selectionStart = this.owner.selectionModule.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString());
blockInfo = this.owner.selectionModule.getParagraphInfo(this.owner.selectionModule.end);
this.selectionEnd = this.owner.selectionModule.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString());
}
- private updateCollaborativeSelection(): void {
+ private updateCollaborativeSelection(start: TextPosition, end: TextPosition): void {
if (this.owner.enableCollaborativeEditing && !this.owner.editorModule.isRemoteAction) {
//TODO: Need to consider formard and backward selection
- let start: TextPosition;
- let end: TextPosition;
if (this.action == 'RemoveEditRange') {
let startEdit: EditRangeStartElementBox = this.owner.selectionModule.getEditRangeStartElement();
let position: PositionInfo = this.owner.selectionModule.getPosition(startEdit);
start = position.startPosition;
end = position.endPosition;
} else {
- start = this.owner.selectionModule.start.clone();
- end = this.owner.selectionModule.end.clone();
this.updateTableSelection(start, end);
}
this.startIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(start);
@@ -247,7 +243,7 @@ export class BaseHistoryInfo {
} else {
this.endIndex -= this.owner.selectionModule.getTableRelativeValue(end, start);
}
- if (this.action === 'BackSpace' || this.action === 'Delete') {
+ // if (this.action === 'BackSpace' || this.action === 'Delete') {
let isParagraphStart: boolean = isForward ? (start.paragraph.equals(end.paragraph) && start.isAtParagraphStart) : (start.paragraph.equals(end.paragraph) && end.isAtParagraphStart);
if ((isParagraphStart || !start.paragraph.equals(end.paragraph))) {
if (isForward) {
@@ -256,7 +252,7 @@ export class BaseHistoryInfo {
this.startIndex += this.paraInclude(start);
}
}
- }
+ // }
this.splitOperationForDelete(start, end);
// Code for Comparing the offset calculated using old approach and optimized approach
// throwCustomError(this.newStartIndex !== this.startIndex, "New StartIndex " + this.newStartIndex + " and old StartIndex " + this.startIndex + " doesnot match");
@@ -504,8 +500,11 @@ export class BaseHistoryInfo {
if (!isNullOrUndefined(this.insertPosition)) {
this.insertIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(this.insertPosition);
}
+ this.startIndex = this.insertIndex;
if (!isNullOrUndefined(this.endPosition)) {
- this.updateCollaborativeSelection();
+ let startPosition: TextPosition = this.owner.selection.getTextPosBasedOnLogicalIndex(this.insertPosition);
+ let endPosition: TextPosition = this.owner.selection.getTextPosBasedOnLogicalIndex(this.endPosition);
+ this.updateCollaborativeSelection(startPosition, endPosition);
}
this.startIndex = this.insertIndex;
}
@@ -525,6 +524,8 @@ export class BaseHistoryInfo {
}
}
this.isRemovedNodes = true;
+ } else {
+ this.isRemovedNodes = false;
}
this.removedNodesIn = [];
if (isNullOrUndefined(this.endPosition)) {
@@ -613,13 +614,15 @@ export class BaseHistoryInfo {
// Use this property to skip deletion if already selected content deleted case.
let isRemoveContent: boolean = false;
if (this.endRevisionLogicalIndex && deletedNodes.length > 0) {
+ let currentPosition: TextPosition = sel.getTextPosBasedOnLogicalIndex(this.endRevisionLogicalIndex);
if (this.editorHistory.isUndoing || (this.editorHistory.isRedoing && insertTextPosition.isAtSamePosition(endTextPosition))) {
- let currentPosition: TextPosition = sel.getTextPosBasedOnLogicalIndex(this.endRevisionLogicalIndex);
sel.selectPosition(insertTextPosition, currentPosition);
- if(this.owner.enableCollaborativeEditing) {
- this.endIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(currentPosition);
- }
}
+ this.collabEnd = this.endRevisionLogicalIndex;
+ if (this.owner.enableCollaborativeEditing) {
+ this.endIndex = this.owner.selectionModule.getAbsolutePositionFromRelativePosition(currentPosition);
+ this.endIndex += this.paraInclude(currentPosition);
+ }
if (this.editorHistory.isUndoing) {
this.owner.editorModule.deleteSelectedContents(sel, true);
isRemoveContent = true;
@@ -1968,6 +1971,7 @@ export class BaseHistoryInfo {
}
operation.markerData.splittedRevisions.push(this.markerData[j]);
this.markerData.splice(j, 1);
+ j--;
}
}
}
@@ -2107,10 +2111,6 @@ export class BaseHistoryInfo {
if (this.editorHistory.isUndoing && this.isRemovedNodes) {
operations.push(this.getUndoRedoOperation(action));
} else {
- if (this.editorHistory.isRedoing && action === 'InsertTable') {
- this.insertedNodes.reverse();
- this.insertedNodes.splice(0, 1);
- }
let tableRowOperation: Operation[] = this.buildTableRowCellOperation(action);
for (let i: number = 0; i < tableRowOperation.length; i++) {
operations.push(tableRowOperation[i]);
@@ -2180,7 +2180,19 @@ export class BaseHistoryInfo {
} else {
if (this.removedNodes.length > 0) {
if (this.owner.enableTrackChanges) {
- operations = this.getDeleteOperationsForTrackChanges();
+ if (this.editorHistory.isRedoing) {
+ if (this.removedNodes.length > 0) {
+ let deleteOperation: Operation = this.getDeleteOperation(action);
+ deleteOperation.markerData = { isSkipTracking: true };
+ operations.push(deleteOperation);
+ }
+ if (this.isRemovedNodes) {
+ let operationCollection: Operation[] = this.getDeleteContent(action);
+ operations = [...operations, ...operationCollection];
+ }
+ } else {
+ operations = this.getDeleteOperationsForTrackChanges();
+ }
} else {
let deleteOperation: Operation = this.getDeleteOperation(action);
operations.push(deleteOperation);
@@ -2209,6 +2221,7 @@ export class BaseHistoryInfo {
}
}
}
+ this.markerData = [];
break;
case 'ResolveComment':
case 'EditComment':
@@ -2612,7 +2625,7 @@ export class BaseHistoryInfo {
if (!isNullOrUndefined(element)) {
do {
let insertedText;
- let Data: MarkerInfo;
+ let data: MarkerInfo;
let elementLength;
let characterFormat;
let type;
@@ -2629,31 +2642,45 @@ export class BaseHistoryInfo {
if (element.fieldType === 0 && element.formFieldData) {
type = this.formFieldType;
- Data = this.markerData.pop();
- if (isNullOrUndefined(Data)) {
- Data = {};
+ if (element.revisions.length > 0) {
+ data = this.owner.editorModule.getRevisionMarkerData(data, element.revisions[0]);
}
- Data.type = 'Field';
- Data.formFieldData = JSON.stringify(element.formFieldData);
+ if (isNullOrUndefined(data)) {
+ data = {};
+ }
+ data.type = 'Field';
+ data.formFieldData = JSON.stringify(element.formFieldData);
} else {
- Data = this.markerData.pop();
- if (isNullOrUndefined(Data)) {
- Data = {};
+ if(element.revisions.length > 0) {
+ data = this.owner.editorModule.getRevisionMarkerData(data, element.revisions[0]);
+ }
+ if (isNullOrUndefined(data)) {
+ data = {};
}
- Data.type = 'Field';
+ data.type = 'Field';
}
elementLength = element.length;
} else if (this.fieldBegin.formFieldData && element instanceof BookmarkElementBox) {
+ if (element.revisions.length > 0) {
+ data = this.owner.editorModule.getRevisionMarkerData(data, element.revisions[0]);
+ }
insertedText = element.bookmarkType === 0 ? CONTROL_CHARACTERS.Marker_Start : CONTROL_CHARACTERS.Marker_End;
- Data = { 'bookmarkName': element.name, 'type': 'Bookmark' };
+ if (isNullOrUndefined(data)) {
+ data = {};
+ }
+ data.bookmarkName = element.name;
+ data.type = 'Bookmark';
elementLength = element.length;
} else if (element instanceof TextElementBox) {
insertedText = element.text;
elementLength = element.length;
- Data = this.markerData.pop();
+ if (element.revisions.length > 0) {
+ data = this.owner.editorModule.getRevisionMarkerData(data, element.revisions[0]);
+ }
}
if (!(element instanceof BookmarkElementBox)) {
- let characterData: any = this.owner.sfdtExportModule.writeCharacterFormat(element.characterFormat, 0);
+ let characterData: any = {};
+ HelperMethods.writeCharacterFormat(characterData, true, element.characterFormat, undefined, true);
characterFormat = JSON.stringify(characterData);
}
let operation: Operation = {
@@ -2662,12 +2689,12 @@ export class BaseHistoryInfo {
type: type,
text: insertedText,
length: elementLength,
- markerData: Data,
+ markerData: data,
format: characterFormat
}
operations.push(operation);
elementOffset += element.length;
- Data = undefined;
+ data = undefined;
type = undefined;
characterFormat = undefined;
if (element instanceof FieldElementBox && element.fieldType === 1) {
@@ -2675,14 +2702,21 @@ export class BaseHistoryInfo {
if (this.fieldBegin.formFieldData && element.nextNode instanceof BookmarkElementBox) {
let elementBox: BookmarkElementBox = element.nextNode;
insertedText = elementBox.bookmarkType === 0 ? CONTROL_CHARACTERS.Marker_Start : CONTROL_CHARACTERS.Marker_End;
- Data = { 'bookmarkName': elementBox.name, 'type': 'Bookmark' };
+ if (element.revisions.length > 0) {
+ data = this.owner.editorModule.getRevisionMarkerData(data, elementBox.revisions[0]);
+ }
+ if (isNullOrUndefined(data)) {
+ data = {};
+ }
+ data.bookmarkName = elementBox.name;
+ data.type = 'Bookmark';
elementLength = elementBox.length;
let operation: Operation = {
action: 'Insert',
offset: elementOffset,
text: insertedText,
length: elementLength,
- markerData: Data
+ markerData: data
};
operations.push(operation);
}
@@ -2705,7 +2739,7 @@ export class BaseHistoryInfo {
paraEnd.offset = endPosition.offset - 1;
let isParaSelected: boolean = startPosition.isAtParagraphStart && paraEnd.isAtParagraphEnd;
if (isParaSelected && (!startPosition.currentWidget.paragraph.isInsideTable)) {
- operations.push(this.getInsertOperation('Enter'));
+ operations.push(this.getInsertOperation('Enter', false, true));
operations.push(this.getUndoRedoOperation(action));
} else if (startPosition.paragraph == endPosition.paragraph) {
if (startPosition.isAtSamePosition(endPosition)) {
@@ -2975,7 +3009,7 @@ export class BaseHistoryInfo {
* @private
* @returns {Operation}
*/
- public getInsertOperation(action: Action, setEndIndex?: boolean): Operation {
+ public getInsertOperation(action: Action, setEndIndex?: boolean, skipMarkerData?: boolean): Operation {
let insertedText: string = action === 'Enter' ? '\n' : this.insertedText;
let length: number;
if (action === 'InsertTable' || action === 'InsertTableBelow' || action === 'InsertRowAbove' || action === 'InsertRowBelow'
@@ -2999,7 +3033,7 @@ export class BaseHistoryInfo {
imageData: this.insertedData,
format: this.format,
}
- if (!isNullOrUndefined(this.markerData)) {
+ if (!isNullOrUndefined(this.markerData) && !skipMarkerData) {
operation.markerData = this.markerData.pop();
}
if (this.insertedElement instanceof FootnoteElementBox) {
@@ -3084,21 +3118,22 @@ export class BaseHistoryInfo {
this.insertIndex -= 1;
}
}
+ if (this.insertedNodes.length > 1 && action === 'InsertTable') {
+ let enterOperation: Operation = this.getInsertOperation('Enter', false, true);
+ if (isNullOrUndefined(enterOperation.markerData)) {
+ enterOperation.markerData = {};
+ }
+ enterOperation.markerData.isSkipTracking = true;
+ operations.push(enterOperation);
+ }
for (let i: number = 0; i < this.insertedNodes.length; i++) {
- if (this.insertedNodes[i] instanceof ParagraphWidget && action === 'InsertTable') {
- let enterOperation: Operation = this.getInsertOperation('Enter');
- if (isNullOrUndefined(enterOperation.markerData)) {
- enterOperation.markerData = {};
- }
- enterOperation.markerData.isSkipTracking = true;
- operations.push(enterOperation);
- } else if (this.insertedNodes[i] instanceof TableWidget) {
+ if (this.insertedNodes[i] instanceof TableWidget) {
let tableWidget: TableWidget = (this.insertedNodes[i] as TableWidget).combineWidget(this.owner.viewer) as TableWidget;
this.tableRelatedLength = action === 'InsertTableBelow' ? 0 : 1;
this.insertedText = CONTROL_CHARACTERS.Table;
let tableFormat: any = this.owner.sfdtExportModule ? this.owner.sfdtExportModule.writeTableFormat(tableWidget.tableFormat, 0) : {};
this.format = JSON.stringify(tableFormat);
- operations.push(this.getInsertOperation(action));
+ operations.push(this.getInsertOperation(action, false, true));
for (let j: number = 0; j < tableWidget.childWidgets.length; j++) {
let row: TableRowWidget = tableWidget.childWidgets[j] as TableRowWidget;
operations.push(this.buildRowOperation(row, action));
@@ -3234,7 +3269,7 @@ export class BaseHistoryInfo {
this.owner.sfdtExportModule.assignRowFormat(rowFormat, row.rowFormat, 0);
}
this.format = JSON.stringify(rowFormat);
- if(row.rowFormat.revisions.length > 0) {
+ if (action === 'InsertTable' && row.rowFormat.revisions.length > 0) {
let revision: Revision = row.rowFormat.revisions[row.rowFormat.revisions.length - 1];
let lastRevision: MarkerInfo = this.markerData[this.markerData.length - 1];
if (!(!isNullOrUndefined(lastRevision) && lastRevision.revisionId === revision.revisionID)) {
@@ -3244,7 +3279,6 @@ export class BaseHistoryInfo {
this.tableRelatedLength = 1;
let operation: Operation = this.getInsertOperation(action);
this.format = undefined;
- this.markerData = [];
return operation
}
/**
@@ -3270,7 +3304,7 @@ export class BaseHistoryInfo {
this.type = 'CellFormat';
let cellFormat: any = !isNullOrUndefined(this.owner.sfdtExportModule) ? this.owner.sfdtExportModule.writeCellFormat(cell.cellFormat, 0) : {};
this.format = JSON.stringify(cellFormat);
- operations.push(this.getInsertOperation(action));
+ operations.push(this.getInsertOperation(action, false, true));
if (!isCellInserted) {
return operations;
}
@@ -3278,12 +3312,12 @@ export class BaseHistoryInfo {
this.type = 'ParagraphFormat';
let paragraphFormat: any = this.owner.sfdtExportModule.writeParagraphFormat((cell.childWidgets[0] as ParagraphWidget).paragraphFormat, 0, true);
this.format = JSON.stringify(paragraphFormat);
- operations.push(this.getInsertOperation(action));
+ operations.push(this.getInsertOperation(action, false, true));
this.tableRelatedLength = 0;
this.type = 'CharacterFormat';
let characterData: any = this.owner.sfdtExportModule.writeCharacterFormat((cell.childWidgets[0] as ParagraphWidget).characterFormat, 0, true);
this.format = JSON.stringify(characterData);
- operations.push(this.getInsertOperation(action));
+ operations.push(this.getInsertOperation(action, false, true));
this.format = undefined;
this.type = undefined;
return operations;
@@ -3389,13 +3423,13 @@ export class BaseHistoryInfo {
* @private
* @returns {Operation}
*/
- public getFormatOperation(element?: ElementBox, action?: string): Operation {
+ public getFormatOperation(element?: ElementBox, action?: string, skipIncrement?: boolean): Operation {
if (this.startIndex > this.endIndex) {
[this.startIndex, this.endIndex] = [this.endIndex, this.startIndex];
}
let length: number = 0;
- if (this.endIndex === this.startIndex && this.action !== 'StyleName' && this.action !== 'DeleteBookmark' && this.action !== 'RemoveEditRange' && this.action !== 'InsertHyperlink') {
- if (this.action === 'BackSpace') {
+ if (this.endIndex === this.startIndex && !skipIncrement && this.action !== 'DeleteBookmark' && this.action !== 'RemoveEditRange' && this.action !== 'InsertHyperlink') {
+ if(this.action === 'BackSpace') {
this.startIndex--;
} else {
this.endIndex++;
@@ -3698,17 +3732,19 @@ export class BaseHistoryInfo {
}
let formatOperation: Operation;
if (action === 'ListFormat') {
- formatOperation = this.getFormatOperation(undefined, action);
+ formatOperation = this.getFormatOperation(undefined, undefined, true);
+ formatOperation.type = 'ListFormat';
this.createListFormat(action, formatOperation);
} else {
- formatOperation = this.getFormatOperation();
+ formatOperation = this.getFormatOperation(undefined, undefined, true);
}
operations.push(formatOperation);
}
} else {
let operation: Operation;
if (action === 'ListFormat') {
- operation = this.getFormatOperation(undefined, action);
+ operation = this.getFormatOperation(undefined, undefined, true);
+ operation.type = 'ListFormat';
this.createListFormat(action, operation);
} else {
if (start.paragraph.isInsideTable && isCell) {
@@ -3718,7 +3754,7 @@ export class BaseHistoryInfo {
this.endIndex = this.startIndex + length;
this.writeBorderFormat(isBorder, isShading, start.paragraph.associatedCell);
}
- operation = this.getFormatOperation();
+ operation = this.getFormatOperation(undefined, undefined, true);
}
operations.push(operation);
}
diff --git a/controls/documenteditor/src/document-editor/implementation/editor-history/history-info.ts b/controls/documenteditor/src/document-editor/implementation/editor-history/history-info.ts
index f6f87e4b17..97a121586c 100644
--- a/controls/documenteditor/src/document-editor/implementation/editor-history/history-info.ts
+++ b/controls/documenteditor/src/document-editor/implementation/editor-history/history-info.ts
@@ -119,8 +119,17 @@ export class HistoryInfo extends BaseHistoryInfo {
}
} else {
if (this.editorHistory.isUndoing) {
- for (let i: number = 0; i < 3; i++) {
- operations.push(this.getDeleteOperation('Delete'));
+ for (let i: number = 0; i < this.modifiedActions.length; i++) {
+ let currentHistory = this.modifiedActions[parseInt(i.toString(), 10)];
+ currentHistory.endIndex = currentHistory.startIndex;
+ //Basically for pagebreak and column break there will three paragraph difference. So for transformation we sended three backspace operation.
+ operations.push(currentHistory.getDeleteOperation('Delete'));
+ operations.push(currentHistory.getDeleteOperation('Delete'));
+ operations.push(currentHistory.getDeleteOperation('Delete'));
+ if (currentHistory.isRemovedNodes) {
+ let operationCollection: Operation[] = currentHistory.getDeleteContent('BackSpace');
+ operations = [...operations, ...operationCollection];
+ }
}
} else {
for (let i: number = 0; i < this.modifiedActions.length; i++) {
@@ -129,9 +138,12 @@ export class HistoryInfo extends BaseHistoryInfo {
operations.push(currentHistory.getDeleteOperation(action));
}
}
- operations.push(this.getInsertOperation('Enter'));
+ let operation: Operation = this.getInsertOperation('Enter');
+ operation.markerData = { skipOperation: true };
+ //Basically for pagebreak and column break there will three paragraph difference. So for transformation we sended three insert operation.
+ operations.push(operation);
operations.push(this.getInsertOperation(action));
- operations.push(this.getInsertOperation('Enter'));
+ operations.push(operation);
}
}
break;
diff --git a/controls/documenteditor/src/document-editor/implementation/editor/editor.ts b/controls/documenteditor/src/document-editor/implementation/editor/editor.ts
index 48bd1250d8..ecc798ae80 100644
--- a/controls/documenteditor/src/document-editor/implementation/editor/editor.ts
+++ b/controls/documenteditor/src/document-editor/implementation/editor/editor.ts
@@ -238,6 +238,14 @@ export class Editor {
public isXmlMapped: boolean = false;
private isAutoList: boolean = false;
private combineLastBlock: boolean = false;
+ /**
+ * @private
+ */
+ public remotePasteRevision: Revision[] = [];
+ /**
+ * @private
+ */
+ public isFieldOperation: boolean = false;
/**
* @private
* @returns {boolean} - Returns the restrict formatting
@@ -2493,7 +2501,7 @@ export class Editor {
this.editorHistory.updateHistory();
this.editorHistory.updateComplexHistory();
}
- if (isNullOrUndefined(revisionType) || revisionType === 'Insertion') {
+ if ((isNullOrUndefined(revisionType) || revisionType === 'Insertion') && !this.isFieldOperation) {
this.reLayout(selection);
}
this.documentHelper.isTextInput = false;
@@ -2700,8 +2708,8 @@ export class Editor {
let currentRevision: Revision = revisions[i];
if (!this.isRevisionAlreadyIn(elementToInclude, currentRevision) || elementToInclude instanceof WCharacterFormat) {
elementToInclude.revisions.splice(0, 0, currentRevision);
- if (this.editorHistory && !isNullOrUndefined(this.editorHistory.currentBaseHistoryInfo)) {
- // this.editorHistory.currentBaseHistoryInfo.markerData.push(this.getMarkerData(undefined, undefined, currentRevision));
+ if (this.editorHistory && !isNullOrUndefined(this.editorHistory.currentBaseHistoryInfo) && this.editorHistory.currentBaseHistoryInfo.markerData.length === 0) {
+ this.editorHistory.currentBaseHistoryInfo.markerData.push(this.getMarkerData(undefined, undefined, currentRevision));
}
if (elementToInclude instanceof FootnoteElementBox) {
this.insertRevisionForFootnoteWidget(elementToInclude, currentRevision);
@@ -3091,7 +3099,11 @@ export class Editor {
item.revisions.push(revision);
revision.range.push(item);
}
- this.updateRevisionCollection(revision);
+ if (this.isRemoteAction && this.documentHelper.owner.parser.isPaste) {
+ this.remotePasteRevision.push(revision);
+ } else {
+ this.updateRevisionCollection(revision);
+ }
return revision;
}
@@ -3448,6 +3460,13 @@ export class Editor {
return lastPara;
}
+ private updatePasteRevision(): void {
+ for (let i: number = 0; i < this.remotePasteRevision.length; i++) {
+ this.updateRevisionCollection(this.remotePasteRevision[i]);
+ }
+ this.remotePasteRevision = [];
+ }
+
private updateRevisionCollection(revision: Revision): void {
let isInserted: boolean = false;
let paraIndex: TextPosition = undefined;
@@ -3529,17 +3548,6 @@ export class Editor {
}
}
this.documentHelper.updateAuthorIdentity();
- } else {
- if (this.isRemoteAction) {
- if (this.owner.trackChangesPane.revisions.indexOf(revision) < 0) {
- let currentChangeView: ChangesSingleView = new ChangesSingleView(this.owner, this.owner.trackChangesPane);
- this.owner.trackChangesPane.changesInfoDiv.appendChild(currentChangeView.createSingleChangesDiv(revision));
- this.owner.trackChangesPane.revisions.push(revision);
- this.owner.trackChangesPane.changes.add(revision, currentChangeView);
- this.owner.trackChangesPane.renderedChanges.add(revision, currentChangeView);
- }
- }
- this.documentHelper.updateAuthorIdentity();
}
}
/**
@@ -4444,7 +4452,7 @@ export class Editor {
if (selection.start.paragraph.isEmpty()) {
return selection.start.paragraph.characterFormat;
} else {
- let info: ElementInfo = selection.start.currentWidget.getInline(selection.start.offset, 0);
+ let info: ElementInfo = selection.start.currentWidget.getInline(selection.start.offset + 1, 0);
return info.element.characterFormat;
}
}
@@ -5329,7 +5337,11 @@ export class Editor {
if (!isNullOrUndefined(parser.revisionCollection)) {
parser.revisionCollection = undefined;
}
- parser.revisionCollection = new Dictionary
();
+ if (this.isRemoteAction) {
+ parser.revisionCollection = this.documentHelper.revisionsInternal;
+ } else {
+ parser.revisionCollection = new Dictionary();
+ }
let revisionCollection: Dictionary = parser.revisionCollection;
if (!(this.documentHelper.owner.sfdtExportModule.copyWithTrackChange && parser.isCutPerformed)) {
if (pasteContent[revisionsProperty[this.keywordIndex]].length >= 1) {
@@ -5343,7 +5355,7 @@ export class Editor {
}
}
}
- if (revisionCheck) {
+ if (revisionCheck && !this.isRemoteAction) {
let revision: Revision = revisionCollection.get(pasteContent[revisionsProperty[this.keywordIndex]][i][revisionIdProperty[this.keywordIndex]]);
revisionChanges.push(revision);
}
@@ -5658,6 +5670,10 @@ export class Editor {
this.documentHelper.owner.parser.parseImages(images);
}
this.pasteContentsInternal(this.getBlocks(content, true), true, currentFormat);
+ if (this.isRemoteAction) {
+ this.updatePasteRevision();
+ this.owner.trackChangesPane.updateTrackChanges();
+ }
if (content[commentsProperty[this.keywordIndex]] && content[commentsProperty[this.keywordIndex]].length > 0) {
this.documentHelper.layout.layoutComments(this.documentHelper.comments);
}
@@ -5728,7 +5744,7 @@ export class Editor {
//if (!this.isSkipHistory) {
this.initHistory('Paste');
//}
- if (!selection.isEmpty || this.documentHelper.isListTextSelected) {
+ if ((!selection.isEmpty && (!this.owner.documentHelper.isDragging || !this.owner.selection.isImageSelected)) || this.documentHelper.isListTextSelected) {
isRemoved = this.removeSelectedContentInternal(selection, selection.start, selection.end);
}
if (isRemoved) {
@@ -6218,7 +6234,7 @@ export class Editor {
this.owner.enableLocalPaste?
isNullOrUndefined((widget as ParagraphWidget).isCreatedUsingHtmlSpanTag)? false: !(widget as ParagraphWidget).isCreatedUsingHtmlSpanTag
: (widget as ParagraphWidget).isCreatedUsingHtmlSpanTag);
- if (widget instanceof ParagraphWidget && (isPara || (j === widgets.length - 1 && (this.isInsertingTOC || isConsiderLastBlock || this.owner.documentHelper.isDragging)))
+ if (widget instanceof ParagraphWidget && (isPara || (j === widgets.length - 1 && (this.isInsertingTOC || isConsiderLastBlock || this.owner.documentHelper.isDragging || this.isRemoteAction)))
&& (!isNullOrUndefined(widget.paragraphFormat.listFormat)
&& isNullOrUndefined(widget.paragraphFormat.listFormat.list)
&& widget.paragraphFormat.listFormat.listId === -1)) {
@@ -6388,17 +6404,23 @@ export class Editor {
} else {
owner = table.containerWidget;
}
-
+ if (table.isInsideTable) {
+ owner = owner.combineWidget(this.owner.viewer);
+ }
//remove old table revisions if it is present.
this.constructRevisionsForTable(table, false);
if (!skipRemoving) {
this.removeBlock(table, true);
}
this.removeRevisionFromTable(table);
- //Inserts table in the current table position.
+ if (owner instanceof TableCellWidget) {
+ owner = owner.combineWidget(this.owner.viewer);
+ } else {
+ let curretBlock: BlockWidget = this.documentHelper.layout.checkAndGetBlock(owner, insertIndex);
+ insertIndex = owner.childWidgets.indexOf(curretBlock);
+ }
+ //Inserts table in the current table position.
let blockAdvCollection: IWidget[] = owner.childWidgets;
- let curretBlock: BlockWidget = this.documentHelper.layout.checkAndGetBlock(owner, insertIndex);
- insertIndex = owner.childWidgets.indexOf(curretBlock);
blockAdvCollection.splice(insertIndex, 0, newTable);
newTable.index = table.index;
table.containerWidget = undefined;
@@ -6784,6 +6806,25 @@ export class Editor {
}
if (this.isPaste) {
+ if (this.isRemoteAction) {
+ let revision: Revision[] = (paragraphFormat.ownerBase as ParagraphWidget).characterFormat.revisions;
+ let isBreak: boolean = false;
+ for (let i: number = 0; i < revision.length; i++) {
+ paragraph.characterFormat.revisions.push(revision[i]);
+ let range: object[] = revision[i].range;
+ for (let j: number = 0; j < range.length; j++) {
+ if (range[j] instanceof WCharacterFormat && (range[j] as WCharacterFormat) == (paragraphFormat.ownerBase as ParagraphWidget).characterFormat) {
+ range.splice(j, 1);
+ range.push(paragraph.characterFormat);
+ isBreak = true;
+ break;
+ }
+ }
+ if (isBreak) {
+ break;
+ }
+ }
+ }
this.viewer.updateClientAreaForBlock(paragraph, true);
paragraph.x = this.viewer.clientActiveArea.x;
}
@@ -10562,7 +10603,7 @@ export class Editor {
this.insertRevision(currentElement, 'Insertion');
}
}
- if (isNullOrUndefined(value)) {
+ if (isNullOrUndefined(value) && isNullOrUndefined(property)) {
format.clearFormat();
if (!isNullOrUndefined(this.editorHistory) && !isNullOrUndefined(this.editorHistory.currentBaseHistoryInfo)) {
this.editorHistory.currentBaseHistoryInfo.insertedFormat = format[property];
@@ -15054,7 +15095,7 @@ export class Editor {
startListLevel = this.documentHelper.layout.getListLevel(tempList, levelNumber);
if (levelNumber > 0) {
initialListLevel = this.documentHelper.layout.getListLevel(tempList, 0);
- isSameList = !isNullOrUndefined(initialListLevel) && levelNumber > 0 && selection.start.isInSameParagraph(selection.end);
+ isSameList = !isNullOrUndefined(initialListLevel) && levelNumber > 0 && selection.start.isInSameListParagraph(selection.end);
}
let abstractList: WAbstractList = tempList.abstractList;
if (!abstractList) {
@@ -15114,7 +15155,7 @@ export class Editor {
selection.paragraphFormat.listLevelNumber = 0;
}
selection.paragraphFormat.setList(list);
- } else if (isSameList && !isNullOrUndefined(list)) {
+ } else if (isSameList && !isNullOrUndefined(list) && !isUpdate) {
let tempList: WList = this.documentHelper.getListById(currentParagraph.paragraphFormat.listFormat.listId);
let listLevel: WListLevel = this.documentHelper.layout.getListLevel(tempList, levelNumber);
if (listLevelPattern === 'Bullet') {
@@ -15261,11 +15302,16 @@ export class Editor {
let commentStartToInsert = this.checkAndRemoveComments();
this.initHistory('Enter');
let isRemoved: boolean = true;
- if (!selection.isEmpty) {
+ if (!selection.isEmpty && !selection.isImageSelected) {
// this.initHistoryWithSelection(selection, 'Enter');
isRemoved = this.removeSelectedContents(selection);
}
if (isRemoved) {
+ if (selection.isImageSelected && !selection.isForward) {
+ let start = selection.start;
+ selection.start = selection.end;
+ selection.end = start;
+ }
selection.owner.isShiftingEnabled = true;
this.updateInsertPosition();
let blockInfo: ParagraphInfo = this.selection.getParagraphInfo(selection.start);
@@ -17746,7 +17792,7 @@ export class Editor {
} else if (elementBox instanceof FootnoteElementBox) {
this.editorHistory.currentBaseHistoryInfo.insertedText = CONTROL_CHARACTERS.Marker_Start;
this.editorHistory.currentBaseHistoryInfo.markerData.push(this.getMarkerData(elementBox));
- } else if (elementBox instanceof BookmarkElementBox || elementBox instanceof EditRangeStartElementBox || elementBox instanceof EditRangeEndElementBox || elementBox instanceof FieldElementBox || elementBox instanceof TextElementBox) {
+ } else if (elementBox instanceof BookmarkElementBox || elementBox instanceof EditRangeStartElementBox || elementBox instanceof EditRangeEndElementBox || elementBox instanceof FieldElementBox || elementBox instanceof TextElementBox && elementBox.removedIds.length == 0) {
this.editorHistory.currentBaseHistoryInfo.markerData.push(this.getMarkerData(elementBox, this.editorHistory.isUndoing));
if (elementBox instanceof FieldElementBox && elementBox.fieldType === 0) {
this.editorHistory.currentBaseHistoryInfo.fieldBegin = elementBox;
@@ -18697,18 +18743,26 @@ export class Editor {
}
}
if (this.owner.enableTrackChanges && !isNullOrUndefined(revision)) {
- if (isNullOrUndefined(markerData)) {
- markerData = {};
- }
- markerData.revisionId = revision.revisionID;
- markerData.revisionType = revision.revisionType;
- markerData.author = revision.author;
- markerData.date = revision.date;
- markerData.skipOperation = skip;
- markerData.isAcceptOrReject = isAcceptOrReject;
+ markerData = this.getRevisionMarkerData(markerData, revision, skip, isAcceptOrReject);
}
return markerData;
}
+ /**
+ * @private
+ * @returns {any}
+ */
+ public getRevisionMarkerData(markerData: any, revision: Revision, skip?: boolean, isAcceptOrReject?: string): any {
+ if (isNullOrUndefined(markerData)) {
+ markerData = {};
+ }
+ markerData.revisionId = revision.revisionID;
+ markerData.revisionType = revision.revisionType;
+ markerData.author = revision.author;
+ markerData.date = revision.date;
+ markerData.skipOperation = skip;
+ markerData.isAcceptOrReject = isAcceptOrReject;
+ return markerData;
+ }
/**
* @param index
* @private
diff --git a/controls/documenteditor/src/document-editor/implementation/editor/image-resizer.ts b/controls/documenteditor/src/document-editor/implementation/editor/image-resizer.ts
index 8aef2a842c..fb4de2c347 100644
--- a/controls/documenteditor/src/document-editor/implementation/editor/image-resizer.ts
+++ b/controls/documenteditor/src/document-editor/implementation/editor/image-resizer.ts
@@ -1095,7 +1095,7 @@ export class ImageResizer {
this.currentImageElementBox.height = parseFloat(this.imageResizerDiv.style.height) / this.documentHelper.zoomFactor;
this.owner.isShiftingEnabled = true;
this.owner.editorModule.setOffsetValue(this.owner.selectionModule);
- this.documentHelper.layout.reLayoutParagraph(this.currentImageElementBox.line.paragraph, 0, 0);
+ this.documentHelper.layout.layoutBodyWidgetCollection(this.currentImageElementBox.line.paragraph.index, this.currentImageElementBox.line.paragraph.containerWidget, this.currentImageElementBox.line.paragraph, false);
this.updateHistoryForImageResizer();
this.owner.editorModule.reLayout(this.owner.selectionModule, true);
this.viewer.updateScrollBars();
diff --git a/controls/documenteditor/src/document-editor/implementation/format/style.ts b/controls/documenteditor/src/document-editor/implementation/format/style.ts
index 3ac3ea4a7c..36d74295e2 100644
--- a/controls/documenteditor/src/document-editor/implementation/format/style.ts
+++ b/controls/documenteditor/src/document-editor/implementation/format/style.ts
@@ -124,6 +124,26 @@ export class WCharacterStyle extends WStyle {
this.characterFormat.copyFormat(charStyle.characterFormat);
}
}
+/**
+ * @private
+ */
+export class WTableStyle extends WStyle {
+ public constructor(node?: Object) {
+ super();
+ this.ownerBase = node;
+ }
+ /**
+ * Disposes the internal objects which are maintained.
+ * @private
+ */
+ public destroy(): void {
+ this.ownerBase = undefined;
+ this.name = undefined;
+ this.next = undefined;
+ this.basedOn = undefined;
+ this.link = undefined;
+ }
+}
/**
* @private
*/
@@ -160,7 +180,7 @@ export class WStyles {
let style: Object = this.collection[parseInt(i.toString(), 10)];
if (style instanceof WCharacterStyle) {
(style as WCharacterStyle).clear();
- } else {
+ } else if (style instanceof WParagraphStyle) {
(style as WParagraphStyle).clear();
}
}
@@ -195,12 +215,14 @@ export class WStyles {
for (const style of styles) {
const returnStyle: any = {};
const returnStyleObject: any = {};
- if(type == "Paragraph") {
+ if (type == "Paragraph") {
returnStyleObject.paragraphFormat = {};
HelperMethods.writeParagraphFormat(returnStyleObject.paragraphFormat, true, (style as any).paragraphFormat);
}
- returnStyleObject.characterFormat = {};
- HelperMethods.writeCharacterFormat(returnStyleObject.characterFormat, true, (style as any).characterFormat);
+ if (type !== "Table") {
+ returnStyleObject.characterFormat = {};
+ HelperMethods.writeCharacterFormat(returnStyleObject.characterFormat, true, (style as any).characterFormat);
+ }
returnStyle.name = style.name;
returnStyle.style = JSON.stringify(returnStyleObject);
if (!isNullOrUndefined(type)) {
@@ -224,8 +246,10 @@ export class WStyles {
let style: Object = this.collection[parseInt(i.toString(), 10)];
if (style instanceof WCharacterStyle) {
(style as WCharacterStyle).destroy();
- } else {
+ } else if (style instanceof WParagraphStyle) {
(style as WParagraphStyle).destroy();
+ } else if (style instanceof WTableStyle) {
+ (style as WTableStyle).destroy();
}
}
}
diff --git a/controls/documenteditor/src/document-editor/implementation/selection/selection-helper.ts b/controls/documenteditor/src/document-editor/implementation/selection/selection-helper.ts
index 5de677dd3f..743770092e 100644
--- a/controls/documenteditor/src/document-editor/implementation/selection/selection-helper.ts
+++ b/controls/documenteditor/src/document-editor/implementation/selection/selection-helper.ts
@@ -325,6 +325,17 @@ export class TextPosition {
}
return this.paragraph === textPosition.paragraph;
}
+ /**
+ * Return true if start and end is in same list
+ *
+ * @private
+ */
+ public isInSameListParagraph(textPosition: TextPosition): boolean {
+ if (isNullOrUndefined(textPosition)) {
+ throw new Error('textPosition is undefined.');
+ }
+ return this.paragraph.paragraphFormat.listFormat.listId === textPosition.paragraph.paragraphFormat.listFormat.listId;
+ }
/**
* Return true is current text position exist before given text position
*
diff --git a/controls/documenteditor/src/document-editor/implementation/selection/selection.ts b/controls/documenteditor/src/document-editor/implementation/selection/selection.ts
index e03613cf00..e5ddb443b1 100644
--- a/controls/documenteditor/src/document-editor/implementation/selection/selection.ts
+++ b/controls/documenteditor/src/document-editor/implementation/selection/selection.ts
@@ -6805,6 +6805,9 @@ export class Selection {
this.extendBackward();
}
} else {
+ if (!isNullOrUndefined(this.owner.imageResizerModule)) {
+ this.owner.imageResizerModule.selectedImageWidget.clear();
+ }
this.selectInternal(widget, element, index, caretPosition);
}
}
@@ -11788,7 +11791,6 @@ export class Selection {
}
}
offset += element.length;
-
}
}
}
diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts b/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts
index 3fd92f5168..af5b342743 100644
--- a/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts
+++ b/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts
@@ -2055,8 +2055,8 @@ export class Layout {
}
if (isNullOrUndefined(bookmrkElement.properties)) {
if (!isNullOrUndefined(this.documentHelper.selection) && this.documentHelper.selection.isRenderBookmarkAtEnd(bookmrkElement.reference)) {
- var row = bookmrkElement.reference.paragraph.associatedCell.ownerRow;
- row.isRenderBookmarkEnd = true;
+ let cell: TableCellWidget = bookmrkElement.reference.paragraph.associatedCell;
+ cell.isRenderBookmarkEnd = true;
}
} else{
if (!isNullOrUndefined(element.paragraph.associatedCell)) {
@@ -2076,7 +2076,7 @@ export class Layout {
}
}
if (!isNullOrUndefined(endCell)) {
- endCell.isRenderBookmarkEnd = true;
+ endRow.isRenderBookmarkEnd = true;
}
}
}
@@ -6937,7 +6937,7 @@ export class Layout {
if (!isRowSpanEnd) {
if (this.isVerticalMergedCellContinue(row) && (tableRowWidget.y === viewer.clientArea.y
|| tableRowWidget.y === this.viewer.clientArea.y + tableRowWidget.ownerTable.headerHeight)) {
- this.insertSplittedCellWidgets(viewer, tableWidgets, tableRowWidget, tableRowWidget.indexInOwner - 1);
+ this.insertSplittedCellWidgets(viewer, tableWidgets, tableRowWidget, tableRowWidget.index - 1);
}
this.addWidgetToTable(viewer, tableWidgets, rowWidgets, tableRowWidget, footnoteElements);
continue;
@@ -6989,6 +6989,13 @@ export class Layout {
if (isNullOrUndefined(splittedWidget) && tableRowWidget.y === viewer.clientArea.y) {
this.addWidgetToTable(viewer, tableWidgets, rowWidgets, tableRowWidget, footnoteElements);
}
+ } else if (heightType === 'AtLeast' && HelperMethods.convertPointToPixel(row.rowFormat.height) > viewer.clientArea.bottom && tableRowWidget.ownerTable.wrapTextAround && tableRowWidget.y - HelperMethods.convertPointToPixel(tableRowWidget.ownerTable.positioning.verticalPosition) === viewer.clientArea.y && tableRowWidget.bodyWidget.firstChild === tableRowWidget.ownerTable) {
+ splittedWidget = this.splitWidgets(tableRowWidget, viewer, tableWidgets, rowWidgets, splittedWidget, isLastRow, footnoteElements, lineIndexInCell, cellIndex, isMultiColumnSplit);
+ if (isNullOrUndefined(splittedWidget)) {
+ this.addWidgetToTable(viewer, tableWidgets, rowWidgets, tableRowWidget, footnoteElements);
+ count++;
+ continue;
+ }
}
} else if (heightType === 'Exactly' && tableRowWidget.y === viewer.clientArea.y) {
this.addWidgetToTable(viewer, tableWidgets, rowWidgets, tableRowWidget, footnoteElements);
@@ -7449,7 +7456,6 @@ export class Layout {
if (!isNullOrUndefined(rowWidget)) {
let left: number = rowWidget.x;
let tableWidth: number = 0;
- let cellIndex: number = 0;
let cellspace: number = 0;
let linestyle: boolean = false;
tableWidth = HelperMethods.convertPointToPixel(rowWidget.ownerTable.tableHolder.tableWidth);
@@ -7462,10 +7468,18 @@ export class Layout {
i--;
continue;
}
+ // Bug 871725: Empty cell widget must be inserted if the table split into next page.
+ if (tableCollection.length == 1) {
+ break;
+ }
const length: number = rowWidget.childWidgets.length;
this.insertEmptySplittedCellWidget(rowWidget, tableCollection, left, i, previousRowIndex);
if (length < rowWidget.childWidgets.length) {
- if (i === cellIndex) {
+ if (isNullOrUndefined(rowWidget.previousRenderedWidget) || !(rowWidget.previousRenderedWidget instanceof TableRowWidget)) {
+ break;
+ }
+ let prevRowWidget: TableRowWidget = rowWidget.previousRenderedWidget as TableRowWidget;
+ if ((prevRowWidget.lastChild as TableCellWidget).columnIndex === (rowWidget.lastChild as TableCellWidget).columnIndex && (rowWidget.ownerTable.tableFormat.allowAutoFit ? (prevRowWidget.lastChild as TableCellWidget).cellFormat.columnSpan === 1 : true)) {
break;
}
i--;
@@ -7476,6 +7490,9 @@ export class Layout {
if (cellspace > 0 || cellWidget.columnIndex === cellWidget.ownerTable.tableHolder.columns.length - 1 ||
cellWidget.index === (cellWidget.containerWidget as TableRowWidget).childWidgets.length - 1) {
if (!cellWidget.ownerTable.tableFormat.allowAutoFit) {
+ const leftBorderWidth: number = HelperMethods.convertPointToPixel(TableCellWidget.getCellLeftBorder(cellWidget).getLineWidth());
+ const rightBorderWidth: number = HelperMethods.convertPointToPixel(TableCellWidget.getCellRightBorder(cellWidget).getLineWidth());
+ cellWidget.rightBorderWidth = !cellWidget.ownerTable.isBidiTable ? rightBorderWidth : leftBorderWidth;
left += cellWidget.rightBorderWidth;
}
if (!this.isInsertTable()) {
@@ -7483,7 +7500,6 @@ export class Layout {
}
}
left -= (isRightStyleNone && !linestyle) ? 0 : (cellWidget.rightBorderWidth);
- cellIndex++;
if (i === rowWidget.childWidgets.length - 1 && Math.round(left) < Math.round(rowWidget.x + tableWidth)) {
if (this.insertRowSpannedWidget(rowWidget, viewer, left, i + 1)) {
continue;
@@ -8944,8 +8960,7 @@ export class Layout {
if (!isNullOrUndefined(table.previousWidget) || table.isInHeaderFooter || table.isInsideTable) {
this.viewer.clientActiveArea = clientActiveAreaForTableWrap.clone();
this.viewer.clientArea = clientAreaForTableWrap.clone();
- let position: TablePosition = table.positioning;
- if (this.viewer.clientActiveArea.height < table.height && table.width >= this.viewer.clientActiveArea.width && position.verticalAlignment == "None" && position.horizontalAlignment == "Left" && position.horizontalOrigin == "Margin" && position.verticalOrigin == "Margin" && position.horizontalPosition == 0 && position.verticalPosition <= 0) {
+ if (!table.isLayouted && this.viewer.clientActiveArea.height < table.height && table.width >= this.viewer.clientActiveArea.width) {
this.moveBlocksToNextPage(table.previousWidget as BlockWidget, false);
}
} else {
@@ -9536,7 +9551,7 @@ export class Layout {
}
// if (viewer instanceof PageLayoutViewer) {
this.documentHelper.removeEmptyPages();
- this.updateFieldElements();
+ this.updateFieldElements(reLayout);
const firstPage = this.documentHelper.pages[0]
if(firstPage.bodyWidgets[0].sectionIndex > 0) {
let page = firstPage;
@@ -9578,26 +9593,33 @@ export class Layout {
}
}
- public updateFieldElements(): void {
+ public updateFieldElements(reLayout?: boolean): void {
for (let i: number = 0; i < this.documentHelper.fields.length; i++) {
const fieldBegin: FieldElementBox = this.documentHelper.fields[i];
if(this.viewer instanceof PageLayoutViewer || (this.viewer instanceof WebLayoutViewer && !(fieldBegin.line.paragraph.bodyWidget instanceof HeaderFooterWidget))){
if (!isNullOrUndefined(this.documentHelper.selection)) {
const fieldCode: string = this.documentHelper.selection.getFieldCode(fieldBegin);
- if (!isNullOrUndefined(fieldCode) && (fieldCode.toLowerCase().match('numpages') || fieldCode.toLowerCase().match('sectionpages')) && !isNullOrUndefined(fieldBegin.fieldSeparator)) {
+ const regex: RegExp = /^(?!.*\bhyperlink\b).*\bpage\b.*$/;
+ if (!isNullOrUndefined(fieldCode) && (fieldCode.toLowerCase().match('numpages') || fieldCode.toLowerCase().match('sectionpages') || (regex.test(fieldCode.toLowerCase()) && reLayout)) && !isNullOrUndefined(fieldBegin.fieldSeparator)) {
const textElement: FieldTextElementBox = fieldBegin.fieldSeparator.nextNode as FieldTextElementBox;
if (!isNullOrUndefined(textElement)) {
const prevPageNum: string = textElement.text;
- textElement.text = this.documentHelper.pages.length.toString();
const paragraph: ParagraphWidget = fieldBegin.line.paragraph;
- if (!isNullOrUndefined(paragraph.bodyWidget) && !isNullOrUndefined(paragraph.bodyWidget.page) && paragraph.bodyWidget.page.index !== -1
- && prevPageNum !== textElement.text) {
- const lineIndex: number = paragraph.childWidgets.indexOf(fieldBegin.line);
- const elementIndex: number = fieldBegin.line.children.indexOf(textElement);
- if (paragraph.isInsideTable) {
- this.reLayoutParagraph(paragraph, lineIndex, elementIndex);
+ if (!isNullOrUndefined(paragraph.bodyWidget) && !isNullOrUndefined(paragraph.bodyWidget.page) && paragraph.bodyWidget.page.index !== -1) {
+ if (regex.test(fieldCode.toLowerCase())) {
+ let index: number = paragraph.bodyWidget.page.index + 1;
+ textElement.text = index.toString();
} else {
- this.reLayoutLine(paragraph, lineIndex, false, false, true);
+ textElement.text = this.documentHelper.pages.length.toString();
+ }
+ if (prevPageNum !== textElement.text) {
+ const lineIndex: number = paragraph.childWidgets.indexOf(fieldBegin.line);
+ const elementIndex: number = fieldBegin.line.children.indexOf(textElement);
+ if (paragraph.isInsideTable) {
+ this.reLayoutParagraph(paragraph, lineIndex, elementIndex);
+ } else {
+ this.reLayoutLine(paragraph, lineIndex, false, false, true);
+ }
}
}
}
diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/page.ts b/controls/documenteditor/src/document-editor/implementation/viewer/page.ts
index 58197a88b1..aef042cbcb 100644
--- a/controls/documenteditor/src/document-editor/implementation/viewer/page.ts
+++ b/controls/documenteditor/src/document-editor/implementation/viewer/page.ts
@@ -4746,7 +4746,7 @@ export abstract class ElementBox {
* @private
*/
public contentControlProperties: ContentControlProperties;
-
+
/**
* @private
*/
diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/render.ts b/controls/documenteditor/src/document-editor/implementation/viewer/render.ts
index f3cf4e2d0d..8b2671c06a 100644
--- a/controls/documenteditor/src/document-editor/implementation/viewer/render.ts
+++ b/controls/documenteditor/src/document-editor/implementation/viewer/render.ts
@@ -865,12 +865,7 @@ export class Renderer {
let lastPara: ParagraphWidget = this.documentHelper.selection.getLastParagraph(widget) as ParagraphWidget;
let lastLine: LineWidget = lastPara.lastChild as LineWidget;
let position: Point = this.documentHelper.selection.getEndPosition(lastPara);
- if (this.documentHelper.owner.documentEditorSettings.showHiddenMarks && !this.isPrinting) {
- let xLeft = this.documentHelper.textHelper.getWidth(String.fromCharCode(164), lastLine.paragraph.characterFormat) + position.x;
- this.renderBookmark(this.getScaledValue(xLeft, 1), this.getScaledValue(position.y, 2), this.getScaledValue(lastLine.height - lastLine.margin.bottom), 1);
- } else {
- this.renderBookmark(this.getScaledValue(position.x, 1), this.getScaledValue(position.y, 2), this.getScaledValue(lastLine.height - lastLine.margin.bottom), 1);
- }
+ this.renderBookmark(this.getScaledValue(position.x, 1), this.getScaledValue(position.y, 2), this.getScaledValue(lastLine.height - lastLine.margin.bottom), 1);
}
}
}
@@ -2052,6 +2047,7 @@ export class Renderer {
tabString = '-';
break;
case 'Underscore':
+ case 'Single':
tabString = '_';
break;
}
diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/sfdt-reader.ts b/controls/documenteditor/src/document-editor/implementation/viewer/sfdt-reader.ts
index 772bac825b..fe97b498fc 100644
--- a/controls/documenteditor/src/document-editor/implementation/viewer/sfdt-reader.ts
+++ b/controls/documenteditor/src/document-editor/implementation/viewer/sfdt-reader.ts
@@ -5,7 +5,7 @@ import { WListLevel } from '../list/list-level';
import { WAbstractList } from '../list/abstract-list';
import { WLevelOverride } from '../list/level-override';
import { WCharacterFormat, WListFormat, WParagraphFormat, WCellFormat, WTableFormat, WSectionFormat, WRowFormat, WColumnFormat } from '../format/index';
-import { WBorder, WBorders, WShading, WCharacterStyle, WParagraphStyle, WStyles, WStyle, WTabStop } from '../format/index';
+import { WBorder, WBorders, WShading, WCharacterStyle, WParagraphStyle, WStyles, WStyle, WTabStop, WTableStyle } from '../format/index';
import { LayoutViewer, DocumentHelper } from './viewer';
import {
Widget, LineWidget, ParagraphWidget, ImageElementBox, BodyWidget, TextElementBox, TableCellWidget,
@@ -310,7 +310,7 @@ export class SfdtReader {
revisionCheck = false;
}
}
- if (revisionCheck) {
+ if (revisionCheck && !this.documentHelper.owner.editorModule.isRemoteAction) {
revisions.push(revision);
}
}
@@ -341,6 +341,9 @@ export class SfdtReader {
revision.range.push(item);
}
item.revisions.push(revision);
+ if (this.isPaste && this.documentHelper.owner.editorModule.isRemoteAction && item instanceof WRowFormat) {
+ this.documentHelper.owner.editorModule.remotePasteRevision.push(revision);
+ }
}
}
}
@@ -446,6 +449,10 @@ export class SfdtReader {
wStyle = new WCharacterStyle();
wStyle.type = 'Character';
}
+ if (this.getStyleType(style[typeProperty[this.keywordIndex]]) === 'Table') {
+ wStyle = new WTableStyle();
+ wStyle.type = 'Table';
+ }
if (!isNullOrUndefined(style[nameProperty[this.keywordIndex]])) {
wStyle.name = style[nameProperty[this.keywordIndex]];
}
@@ -469,7 +476,7 @@ export class SfdtReader {
} else {
if (wStyle.type === 'Paragraph') {
styleString = JSON.parse('{"type":"Paragraph","name":"Normal","next":"Normal"}');
- } else {
+ } else if (wStyle.type === 'Character') {
styleString = JSON.parse('{"type": "Character","name": "Default Paragraph Font"}');
}
}
@@ -549,7 +556,7 @@ export class SfdtReader {
if (!isNullOrUndefined(resetKeyIndex) && resetKeyIndex) {
this.keywordIndex = keyIndex;
}
- if(!isNullOrUndefined(wStyle)) {
+ if (!isNullOrUndefined(wStyle) && wStyle.type !== 'Table') {
this.documentHelper.addToStylesMap(wStyle);
}
}
@@ -733,7 +740,7 @@ export class SfdtReader {
if (block[inlinesProperty[this.keywordIndex]].length > 0) {
hasValidElmts = this.parseParagraph(block[inlinesProperty[this.keywordIndex]], paragraph, writeInlineFormat, undefined, isFootnoteEndnote && i === 0);
if (block.hasOwnProperty(isCreatedUsingHtmlSpanTagProperty[this.keywordIndex])) {
- paragraph.isCreatedUsingHtmlSpanTag = block[isCreatedUsingHtmlSpanTagProperty[this.keywordIndex]];
+ paragraph.isCreatedUsingHtmlSpanTag = HelperMethods.parseBoolValue(block[isCreatedUsingHtmlSpanTagProperty[this.keywordIndex]]);
}
}
if (!(isSectionBreak && block === data[data.length - 1] && block[inlinesProperty[this.keywordIndex]].length === 0 && !hasValidElmts)) {
@@ -1102,7 +1109,7 @@ export class SfdtReader {
isContentControl = true;
}
if (data.hasOwnProperty(isCreatedUsingHtmlSpanTagProperty[this.keywordIndex])) {
- paragraph.isCreatedUsingHtmlSpanTag = data[isCreatedUsingHtmlSpanTagProperty[this.keywordIndex]];
+ paragraph.isCreatedUsingHtmlSpanTag = HelperMethods.parseBoolValue(data[isCreatedUsingHtmlSpanTagProperty[this.keywordIndex]]);
}
let hasValidElmts: boolean = false;
let revision: Revision;
@@ -2913,6 +2920,8 @@ export class SfdtReader {
return 'Paragraph';
case 1:
return 'Character';
+ case 2:
+ return 'Table';
default:
return styleType as StyleType;
}
diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts b/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts
index c04dbeb10b..b451e639d3 100644
--- a/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts
+++ b/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts
@@ -2400,7 +2400,7 @@ export class DocumentHelper {
if (isNullOrUndefined(formField)) {
formField = this.selection.getCurrentFormField();
}
- if (!this.isDocumentProtected && this.owner.enableFormField) {
+ if (!this.isDocumentProtected && this.owner.enableFormField && !this.owner.isReadOnlyMode) {
const formatType: FormFieldType = this.selection.getFormFieldType(formField);
if (formatType) {
if (formatType.toString() !== '') {
@@ -3043,8 +3043,8 @@ export class DocumentHelper {
if (isNullOrUndefined(touchOffsetValues)) {
touchOffsetValues = event.changedTouches[0];
}
- let offsetX: number = touchOffsetValues.pageX - offset.left;
- let offsetY: number = touchOffsetValues.pageY - offset.top;
+ let offsetX: number = touchOffsetValues.clientX - offset.left;
+ let offsetY: number = touchOffsetValues.clientY - offset.top;
return new Point(offsetX, offsetY);
}
/**
diff --git a/controls/documenteditor/src/document-editor/implementation/writer/sfdt-export.ts b/controls/documenteditor/src/document-editor/implementation/writer/sfdt-export.ts
index 9ce253d949..fdc33efe5d 100644
--- a/controls/documenteditor/src/document-editor/implementation/writer/sfdt-export.ts
+++ b/controls/documenteditor/src/document-editor/implementation/writer/sfdt-export.ts
@@ -41,6 +41,7 @@ export class SfdtExport {
private startColumnIndex: number = undefined;
private endColumnIndex: number = undefined;
private lists: number[] = undefined;
+ private images: number[] = undefined;
private document: any = undefined;
private writeInlineStyles: boolean = undefined;
private nextBlock: any;
@@ -105,6 +106,7 @@ export class SfdtExport {
this.startLine = undefined;
this.endLine = undefined;
this.lists = undefined;
+ this.images = undefined;
this.document = undefined;
this.endCell = undefined;
this.startColumnIndex = undefined;
@@ -331,6 +333,7 @@ export class SfdtExport {
*/
public Initialize(): void {
this.lists = [];
+ this.images = [];
this.document = {};
this.document.optimizeSfdt = this.owner.documentEditorSettings.optimizeSfdt;
this.document[sectionsProperty[this.keywordIndex]] = [];
@@ -943,6 +946,7 @@ export class SfdtExport {
this.writeChart(element, inline);
} else if (element instanceof ImageElementBox) {
inline[imageStringProperty[this.keywordIndex]] = element.imageString;
+ this.images.push(parseInt(element.imageString, 10));
inline[metaFileImageStringProperty[this.keywordIndex]] = element.metaFileImageString;
inline[isMetaFileProperty[this.keywordIndex]] = HelperMethods.getBoolInfo(element.isMetaFile, this.keywordIndex);
inline[isCompressedProperty[this.keywordIndex]] = element.isCompressed;
@@ -2001,6 +2005,9 @@ export class SfdtExport {
wStyle[typeProperty[this.keywordIndex]] = this.keywordIndex == 1 ? this.getStyleTypeEnumValue(style.type) : style.type;
wStyle[characterFormatProperty[this.keywordIndex]] = this.writeCharacterFormat((style as any).characterFormat, this.keywordIndex);
}
+ if (style.type === 'Table') {
+ wStyle[typeProperty[this.keywordIndex]] = this.keywordIndex == 1 ? this.getStyleTypeEnumValue(style.type) : style.type;
+ }
if (!isNullOrUndefined(style.basedOn)) {
wStyle[basedOnProperty[this.keywordIndex]] = style.basedOn.name;
}
@@ -2052,10 +2059,11 @@ export class SfdtExport {
}
public writeImages(documentHelper: DocumentHelper): void {
this.document[imagesProperty[this.keywordIndex]] = {};
- documentHelper.images.keys.forEach(key => {
- let base64ImageString: string[] = this.documentHelper.images.get(key);
+ for (let i = 0; i < this.images.length; i++) {
+ let key: number = this.images[i];
+ let base64ImageString: string[] = documentHelper.images.get(key);
this.document[imagesProperty[this.keywordIndex]][key] = base64ImageString;
- });
+ }
}
private writeComment(comments: CommentElementBox): any {
let comment: any = {};
@@ -2397,6 +2405,8 @@ export class SfdtExport {
return 0;
case 'Character':
return 1;
+ case 'Table':
+ return 2;
}
}
private getProtectionTypeEnumValue(protectionType: ProtectionType): number {
@@ -2872,6 +2882,7 @@ export class SfdtExport {
*/
public destroy(): void {
this.lists = undefined;
+ this.images = undefined;
this.endLine = undefined;
this.startLine = undefined;
this.endOffset = undefined;
diff --git a/controls/documenteditor/src/document-editor/implementation/writer/word-export.ts b/controls/documenteditor/src/document-editor/implementation/writer/word-export.ts
index 5516582212..203bc25b5f 100644
--- a/controls/documenteditor/src/document-editor/implementation/writer/word-export.ts
+++ b/controls/documenteditor/src/document-editor/implementation/writer/word-export.ts
@@ -4664,6 +4664,11 @@ export class WordExport {
// }
// SerializeDocxProps(tempDocxProps, 'tblStyleRowBandSize');
// SerializeDocxProps(tempDocxProps, 'tblStyleColBandSize');
+ if (!isNullOrUndefined(table[tableFormatProperty[this.keywordIndex]][styleNameProperty[this.keywordIndex]])) {
+ writer.writeStartElement(undefined, "tblStyle", this.wNamespace);
+ writer.writeAttributeString('w', 'val', this.wNamespace, table[tableFormatProperty[this.keywordIndex]][styleNameProperty[this.keywordIndex]]);
+ writer.writeEndElement();
+ }
this.serializeTablePositioning(writer, table);
this.serializeTableWidth(writer, table);
this.serializeTableAlignment(writer, table[tableFormatProperty[this.keywordIndex]]);
@@ -6148,7 +6153,7 @@ export class WordExport {
for (let i: number = 0; i < this.mStyles.length; i++) {
let style: any = this.mStyles[i];
writer.writeStartElement(undefined, 'style', this.wNamespace);
- let type: string = style[typeProperty[this.keywordIndex]] === (this.keywordIndex == 1 ? 0 : 'Paragraph') ? 'paragraph' : 'character';
+ let type: string = this.getStyleType(style[typeProperty[this.keywordIndex]]);
writer.writeAttributeString('w', 'type', this.wNamespace, type);
writer.writeAttributeString('w', 'styleId', this.wNamespace, style[nameProperty[this.keywordIndex]]);
//name
@@ -6185,7 +6190,9 @@ export class WordExport {
writer.writeEndElement();
}
// let value = (style.characterFormat as WCharacterFormat).newgetCharacterFormat();
- this.serializeCharacterFormat(writer, style[characterFormatProperty[this.keywordIndex]]);
+ if (style[typeProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 2 : 'Table')) {
+ this.serializeCharacterFormat(writer, style[characterFormatProperty[this.keywordIndex]]);
+ }
writer.writeEndElement(); //end of Style
}
}
@@ -6334,6 +6341,18 @@ export class WordExport {
}
return color;
}
+ private getStyleType(styleType: any): string {
+ switch (styleType) {
+ case 'Character':
+ case 1:
+ return 'character';
+ case 'Table':
+ case 2:
+ return 'table';
+ default:
+ return 'paragraph';
+ }
+ }
// Get the underline style as string
private getUnderlineStyle(underlineStyle: number | string): string {
switch (underlineStyle) {
diff --git a/controls/drawings/CHANGELOG.md b/controls/drawings/CHANGELOG.md
index 2acfa8a2a3..bdb5c8b8a9 100644
--- a/controls/drawings/CHANGELOG.md
+++ b/controls/drawings/CHANGELOG.md
@@ -2,7 +2,7 @@
## [Unreleased]
-## 25.1.35 (2024-03-15)
+## 25.1.37 (2024-03-26)
### Drawings
diff --git a/controls/dropdowns/CHANGELOG.md b/controls/dropdowns/CHANGELOG.md
index b64be12415..051719328c 100644
--- a/controls/dropdowns/CHANGELOG.md
+++ b/controls/dropdowns/CHANGELOG.md
@@ -2,6 +2,18 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### MultiSelect
+
+#### Bug Fixes
+
+- `#I560783` - Fixed issue where clearing the searched value would automatically select another value.
+
+- `#I524283` - Fixed issue where popup was not aligned properly when opening on top of the component.
+
+- `#I565659` - Fixed an issue in Multiselect Checkbox mode where the height of the dropdown input would change when selecting and unselecting items.
+
## 25.1.35 (2024-03-15)
### ComboBox
diff --git a/controls/dropdowns/package.json b/controls/dropdowns/package.json
index 87bc01be1c..dc22636958 100644
--- a/controls/dropdowns/package.json
+++ b/controls/dropdowns/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-dropdowns",
- "version": "18.66.23",
+ "version": "25.1.35",
"description": "Essential JS 2 DropDown Components",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
@@ -56,13 +56,9 @@
"ej2-multiselect",
"ej2-combobox"
],
- "repository": {
- "type": "git",
- "url": "https://github.com/syncfusion/ej2-javascript-ui-controls"
- },
"scripts": {
"build": "gulp build",
"test": "gulp test"
},
"typings": "index.d.ts"
-}
+}
\ No newline at end of file
diff --git a/controls/dropdowns/spec/multi-select/checkbox-selection.spec.ts b/controls/dropdowns/spec/multi-select/checkbox-selection.spec.ts
index 9de695d0bc..66ba1a70f5 100644
--- a/controls/dropdowns/spec/multi-select/checkbox-selection.spec.ts
+++ b/controls/dropdowns/spec/multi-select/checkbox-selection.spec.ts
@@ -3437,6 +3437,73 @@ describe('EJ2-44211- The focus class maintained after move the focus to another
}, 800);
});
});
+describe('875197', () => {
+ let listObj: MultiSelect;
+ let count: number = 0;
+ let mouseEventArgs: any = { preventDefault: function () { }, target: null, stopPropagation: function () {} };
+ let element: HTMLInputElement = createElement('input', { id: 'multiselect', attrs: { type: "text" } });
+ let datasource: { [key: string]: Object }[] = [
+ { Name: 'Australia', Code: 'AU' },
+ { Name: 'Bermuda', Code: 'BM' },
+ { Name: 'Canada', Code: 'CA' },
+ { Name: 'Cameroon', Code: 'CM' },
+ { Name: 'Denmark', Code: 'DK' },
+ { Name: 'France', Code: 'FR' },
+ { Name: 'Finland', Code: 'FI' },
+ { Name: 'Germany', Code: 'DE' },
+ { Name: 'Greenland', Code: 'GL' },
+ { Name: 'Hong Kong', Code: 'HK' },
+ { Name: 'India', Code: 'IN' },
+ { Name: 'Italy', Code: 'IT' },
+ { Name: 'Japan', Code: 'JP' },
+ ];
+ let originalTimeout: number;
+ beforeAll(() => {
+ for (let i = 0; i < 27; i++) {
+ const brElement = document.createElement('br');
+ document.body.appendChild(brElement);
+ }
+ document.body.appendChild(element);
+ listObj = new MultiSelect({
+ dataSource: datasource,
+ fields: { text: 'Name', value: 'Code' },
+ showDropDownIcon: true,
+ showSelectAll: true,
+ allowFiltering: true,
+ mode: 'CheckBox',
+ });
+ listObj.appendTo(element);
+ });
+ afterAll(() => {
+ for (let i = 0; i < 27; i++) {
+ const brElement = document.querySelector('br');
+ if (brElement) {
+ brElement.remove();
+ }
+ }
+ if (element) {
+ listObj.destroy();
+ element.remove();
+ }
+ });
+ it('when click the serach text to prevent the list selection', () => {
+ mouseEventArgs.type = 'mousedown';
+ mouseEventArgs.target = (listObj).overAllWrapper;
+ (listObj).wrapperClick(mouseEventArgs);
+ (listObj).checkBoxSelectionModule.filterInput.value = "g";
+ keyboardEventArgs.altKey = false;
+ keyboardEventArgs.keyCode = 71;
+ (listObj).keyDownStatus = true;
+ (listObj).onInput(keyboardEventArgs);
+ (listObj).keyUp(keyboardEventArgs);
+ (listObj).checkBoxSelectionModule.clearText(mouseEventArgs);
+ mouseEventArgs.type = 'mouseup';
+ mouseEventArgs.target = (listObj).popupWrapper;
+ (listObj).checkBoxSelectionModule.preventListSelection(mouseEventArgs);
+ (listObj).onMouseClick(mouseEventArgs);
+ expect((listObj).list.querySelectorAll('.e-active').length).toBe(0);
+ });
+});
describe('EJ2-54401- Select all checkbox is not displayed properly while selecting an item from the list ', () => {
let listObj: any;
let checkObj: any;
@@ -3533,4 +3600,4 @@ describe('EJ2-54401- Select all checkbox is not displayed properly while selecti
done();
}, 450);
});
-});
\ No newline at end of file
+});
diff --git a/controls/dropdowns/src/multi-select/checkbox-selection.ts b/controls/dropdowns/src/multi-select/checkbox-selection.ts
index 067cd27eb7..25a1f26720 100644
--- a/controls/dropdowns/src/multi-select/checkbox-selection.ts
+++ b/controls/dropdowns/src/multi-select/checkbox-selection.ts
@@ -39,6 +39,7 @@ export class CheckBoxSelection {
public list: HTMLElement;
private activeLi: HTMLElement[] = [];
private activeEle: HTMLElement[] = [];
+ private boundPreventListSelection: () => void;
public constructor(parent?: IMulitSelect) {
this.parent = parent;
this.removeEventListener();
@@ -326,14 +327,22 @@ export class CheckBoxSelection {
if (this.parent.allowFiltering && (this.parent.targetInputElement as HTMLInputElement).value === '') {
this.parent.search(null);
}
- this.parent.refreshPopup();
this.parent.refreshListItems(null);
+ this.parent.refreshPopup();
(this.clearIconElement as HTMLElement).style.visibility = 'hidden';
this.filterInput.focus();
this.setReorder(e);
+ this.boundPreventListSelection = this.preventListSelection.bind(this);
+ this.parent.popupWrapper.addEventListener('mouseup', this.boundPreventListSelection, true);
e.preventDefault();
}
+ private preventListSelection(e: MouseEvent): void {
+ e.stopPropagation();
+ this.parent.popupWrapper.removeEventListener('mouseup', this.boundPreventListSelection, true);
+ this.boundPreventListSelection = null;
+ }
+
private setDeviceSearchBox(): void {
this.parent.popupObj.element.classList.add(device);
this.parent.popupObj.element.classList.add(mobileFilter);
diff --git a/controls/dropdowns/src/multi-select/multi-select-model.d.ts b/controls/dropdowns/src/multi-select/multi-select-model.d.ts
index c582fd414c..6ee5777284 100644
--- a/controls/dropdowns/src/multi-select/multi-select-model.d.ts
+++ b/controls/dropdowns/src/multi-select/multi-select-model.d.ts
@@ -1,4 +1,4 @@
-import { DropDownBase, SelectEventArgs, dropDownBaseClasses, PopupEventArgs, FilteringEventArgs } from '../drop-down-base/drop-down-base';import { FocusEventArgs, BeforeOpenEventArgs, FilterType, FieldSettings, ResultData } from '../drop-down-base/drop-down-base';import { FieldSettingsModel } from '../drop-down-base/drop-down-base-model';import { Popup, createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups';import { IInput, FloatLabelType, Input } from '@syncfusion/ej2-inputs';import { attributes, setValue, SanitizeHtmlHelper, getValue } from '@syncfusion/ej2-base';import { NotifyPropertyChanges, extend } from '@syncfusion/ej2-base';import { EventHandler, Property, Event, compile, L10n, EmitType, KeyboardEventArgs } from '@syncfusion/ej2-base';import { Animation, AnimationModel, Browser, prepend, Complex } from '@syncfusion/ej2-base';import { Search } from '../common/incremental-search';import { append, addClass, removeClass, closest, detach, remove, select, selectAll } from '@syncfusion/ej2-base';import { getUniqueID, formatUnit, isNullOrUndefined, isUndefined, ModuleDeclaration } from '@syncfusion/ej2-base';import { DataManager, Query, Predicate, JsonAdaptor, DataOptions } from '@syncfusion/ej2-data';import { SortOrder } from '@syncfusion/ej2-lists';import { createFloatLabel, removeFloating, floatLabelFocus, floatLabelBlur, encodePlaceholder } from './float-label';
+import { DropDownBase, SelectEventArgs, dropDownBaseClasses, PopupEventArgs, FilteringEventArgs } from '../drop-down-base/drop-down-base';import { FocusEventArgs, BeforeOpenEventArgs, FilterType, FieldSettings, ResultData } from '../drop-down-base/drop-down-base';import { FieldSettingsModel } from '../drop-down-base/drop-down-base-model';import { isCollide, Popup, createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups';import { IInput, FloatLabelType, Input } from '@syncfusion/ej2-inputs';import { attributes, setValue, SanitizeHtmlHelper, getValue } from '@syncfusion/ej2-base';import { NotifyPropertyChanges, extend } from '@syncfusion/ej2-base';import { EventHandler, Property, Event, compile, L10n, EmitType, KeyboardEventArgs } from '@syncfusion/ej2-base';import { Animation, AnimationModel, Browser, prepend, Complex } from '@syncfusion/ej2-base';import { Search } from '../common/incremental-search';import { append, addClass, removeClass, closest, detach, remove, select, selectAll } from '@syncfusion/ej2-base';import { getUniqueID, formatUnit, isNullOrUndefined, isUndefined, ModuleDeclaration } from '@syncfusion/ej2-base';import { DataManager, Query, Predicate, JsonAdaptor, DataOptions } from '@syncfusion/ej2-data';import { SortOrder } from '@syncfusion/ej2-lists';import { createFloatLabel, removeFloating, floatLabelFocus, floatLabelBlur, encodePlaceholder } from './float-label';
import {visualMode,MultiSelectChangeEventArgs,RemoveEventArgs,ISelectAllEventArgs,TaggingEventArgs,CustomValueEventArgs} from "./multi-select";
import {DropDownBaseModel} from "../drop-down-base/drop-down-base-model";
diff --git a/controls/dropdowns/src/multi-select/multi-select.ts b/controls/dropdowns/src/multi-select/multi-select.ts
index 811a495f09..5641ee9cca 100644
--- a/controls/dropdowns/src/multi-select/multi-select.ts
+++ b/controls/dropdowns/src/multi-select/multi-select.ts
@@ -3,7 +3,7 @@
import { DropDownBase, SelectEventArgs, dropDownBaseClasses, PopupEventArgs, FilteringEventArgs } from '../drop-down-base/drop-down-base';
import { FocusEventArgs, BeforeOpenEventArgs, FilterType, FieldSettings, ResultData } from '../drop-down-base/drop-down-base';
import { FieldSettingsModel } from '../drop-down-base/drop-down-base-model';
-import { Popup, createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups';
+import { isCollide, Popup, createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups';
import { IInput, FloatLabelType, Input } from '@syncfusion/ej2-inputs';
import { attributes, setValue, SanitizeHtmlHelper, getValue } from '@syncfusion/ej2-base';
import { NotifyPropertyChanges, extend } from '@syncfusion/ej2-base';
@@ -3391,6 +3391,7 @@ export class MultiSelect extends DropDownBase implements IInput {
}
}
});
+ this.checkCollision(this.popupWrapper);
this.popupContentElement = this.popupObj.element.querySelector('.e-content');
if (this.mode === 'CheckBox' && Browser.isDevice && this.allowFiltering) {
@@ -3401,6 +3402,15 @@ export class MultiSelect extends DropDownBase implements IInput {
}
}
}
+ private checkCollision(popupEle: HTMLElement): void {
+ if (!(this.mode === 'CheckBox' && Browser.isDevice && this.allowFiltering)) {
+ const collision: string[] = isCollide(popupEle);
+ if (collision.length > 0) {
+ popupEle.style.marginTop = -parseInt(getComputedStyle(popupEle).marginTop, 10) + 'px';
+ }
+ this.popupObj.resolveCollision();
+ }
+ }
private setHeaderTemplate(): void {
let compiledString: Function;
if (this.header) {
diff --git a/controls/dropdowns/styles/multi-select/_fluent-definition.scss b/controls/dropdowns/styles/multi-select/_fluent-definition.scss
index 6cc123e956..db4c79a8b8 100644
--- a/controls/dropdowns/styles/multi-select/_fluent-definition.scss
+++ b/controls/dropdowns/styles/multi-select/_fluent-definition.scss
@@ -241,6 +241,6 @@ $ddl-small-clear-icon-width: 12px !default;
.e-bigger .e-multiselect.e-control-container .e-multi-select-wrapper.e-down-icon .e-clear-icon,
.e-bigger.e-multiselect.e-control-container .e-multi-select-wrapper.e-down-icon .e-clear-icon {
- margin-top: -1.5em;
+ margin-top: -1.6em;
}
}
diff --git a/controls/dropdowns/styles/multi-select/_material-dark-definition.scss b/controls/dropdowns/styles/multi-select/_material-dark-definition.scss
index 9d2f8af0e6..32c4dacba4 100644
--- a/controls/dropdowns/styles/multi-select/_material-dark-definition.scss
+++ b/controls/dropdowns/styles/multi-select/_material-dark-definition.scss
@@ -228,3 +228,14 @@ $ddl-multiselect-filled-float-input-min-height-bigger: 36px !default;
$ddl-multiselect-filled-floatlabel-fontsize-bigger: 12px !default;
$filled-multiselect-chip-bg-color: $grey-800 !default;
$filled-multiselect-chip-hover-bg-color: $grey-700 !default;
+
+@include export-module('multiselect-material-dark') {
+ .e-multiselect.e-input-group.e-checkbox .e-multi-select-wrapper input[type = 'text'] {
+ padding: 1px 0;
+ }
+
+ .e-small .e-multiselect.e-input-group.e-checkbox .e-multi-select-wrapper input[type = 'text'],
+ .e-small.e-multiselect.e-input-group.e-checkbox .e-multi-select-wrapper input[type = 'text'] {
+ padding: 0;
+ }
+}
diff --git a/controls/dropdowns/styles/multi-select/_material-definition.scss b/controls/dropdowns/styles/multi-select/_material-definition.scss
index fce1c99ecc..e5b6d482c9 100644
--- a/controls/dropdowns/styles/multi-select/_material-definition.scss
+++ b/controls/dropdowns/styles/multi-select/_material-definition.scss
@@ -221,3 +221,14 @@ $outline-multiselect-disabled-font-color: rgba($grey-light-font, .38) !default;
$outline-multiselect-disabled-chip-bg-color: $grey-100 !default;
$filled-multiselect-chip-bg-color: darken($grey-300, 7%) !default;
$filled-multiselect-chip-hover-bg-color: darken($grey-300, 7%) !default;
+
+@include export-module('multiselect-material') {
+ .e-multiselect.e-input-group.e-checkbox .e-multi-select-wrapper input[type = 'text'] {
+ padding: 1px 0;
+ }
+
+ .e-small .e-multiselect.e-input-group.e-checkbox .e-multi-select-wrapper input[type = 'text'],
+ .e-small.e-multiselect.e-input-group.e-checkbox .e-multi-select-wrapper input[type = 'text'] {
+ padding: 0;
+ }
+}
diff --git a/controls/ej2/package.json b/controls/ej2/package.json
index 2e9bb2cd83..b156c9d6f8 100644
--- a/controls/ej2/package.json
+++ b/controls/ej2/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2",
- "version": "17.417.0",
+ "version": "25.5.0",
"description": "A modern JavaScript UI toolkit that has been built from the ground up to be lightweight, responsive, modular and touch friendly. It is written in TypeScript and has no external dependencies.",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/excelexport/CHANGELOG.md b/controls/excelexport/CHANGELOG.md
index d22d496af1..7981a40f64 100644
--- a/controls/excelexport/CHANGELOG.md
+++ b/controls/excelexport/CHANGELOG.md
@@ -2,15 +2,7 @@
## [Unreleased]
-## 24.2.4 (2024-02-06)
-
-### Excel Export
-
-#### Bug Fixes
-
-- Fixed the new line character after end row being rendered improperly in CSV export.
-
-## 24.1.41 (2023-12-18)
+## 25.1.35 (2024-03-15)
### Excel Export
@@ -24,6 +16,8 @@
- Fixed the text with double quotes being rendered improperly in CSV export.
+- Fixed the New line character being rendered improperly in CSV export.
+
## 21.1.35 (2023-03-23)
### Excel Export
diff --git a/controls/excelexport/package.json b/controls/excelexport/package.json
index 469a55b00d..2c832a1c02 100644
--- a/controls/excelexport/package.json
+++ b/controls/excelexport/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-excel-export",
- "version": "24.2.4",
+ "version": "25.1.35",
"description": "Essential Javascript 2 Excel Export Library",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
@@ -12,6 +12,7 @@
"@syncfusion/ej2-compression": "*"
},
"devDependencies": {
+ "@syncfusion/ej2-staging": "^1.0.1",
"@types/chai": "3.4.28",
"@types/es6-promise": "0.0.28",
"@types/jasmine": "2.5.43",
diff --git a/controls/filemanager/package.json b/controls/filemanager/package.json
index 08362521da..9e84fc9252 100644
--- a/controls/filemanager/package.json
+++ b/controls/filemanager/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-filemanager",
- "version": "18.28.1",
+ "version": "25.1.35",
"description": "Essential JS 2 FileManager Component",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/gantt/CHANGELOG.md b/controls/gantt/CHANGELOG.md
index 8c7db611dd..4311be7203 100644
--- a/controls/gantt/CHANGELOG.md
+++ b/controls/gantt/CHANGELOG.md
@@ -2,6 +2,29 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### GanttChart
+
+#### Bug fixes
+
+- `#F187206` - The delete action not working in remote data when `timezone` using in sample.
+- `#I566491` - The exception is thrown when the resource ID mapping is empty issue has been fixed.
+- `#I565418` - Start date defaulting to incorrect value when remove the start Date in add dialog.
+- `#I566632` - Duration calculations are incorrect in edit or add dialog in decimals issue has been fixed.
+- `#I565751` - The chart does not refresh when any record is edited by cell editing issue has been fixed.
+- `#I566333` - Gantt chart disappeared while insert action with `timlineVirtualization` issue has been fixed.
+- `#F186355` - Taskbar template not showing in resource view issue has been fixed.
+- `#I562492` - `actionBegin` arguments miss the last record while dragging issue has been fixed.
+- `#I556547` - Top and bottom tier shows null when using custom zooming level issue has been fixed.
+- `#I566539` - Console error occurs while saving data in add dialog box with validation rule issue has been
+fixed.
+- `#I553748` - Timeline dates validated wrongly after cell editing with timeline virtualization enabled issue has been fixed.
+- `#I565439` - Work calculations are incorrect for parent task in project view issue has been fixed.
+- `#I553710`,`#I565824` - Weekends are not highlighted while `timlineVirtualization` is enabled issue has been fixed.
+- `#I565359` - When `allowEditing` is disabled in a resource view, a console error is thrown issue has been fixed.
+- `#I560166` - The context menu using "add child" for any task, dependency line validation is not working properly.
+
## 25.1.35 (2024-03-15)
### GanttChart
diff --git a/controls/gantt/package.json b/controls/gantt/package.json
index a54b2d3bc4..3f03a20d4b 100644
--- a/controls/gantt/package.json
+++ b/controls/gantt/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-gantt",
- "version": "24.2.7",
+ "version": "25.1.35",
"description": "Essential JS 2 Gantt Component",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/gantt/spec/action/dialog-edit.spec.ts b/controls/gantt/spec/action/dialog-edit.spec.ts
index df22a534ba..d82c909aa5 100644
--- a/controls/gantt/spec/action/dialog-edit.spec.ts
+++ b/controls/gantt/spec/action/dialog-edit.spec.ts
@@ -5117,3 +5117,448 @@ describe('Dialog editing - predecessor Tab with decimal', () => {
}
});
});
+describe('CR-875373:Start date defaulting to incorrect value when remove the startDate in add dialog issues', function () {
+ let ganttObj: Gantt;
+ beforeAll(function (done) {
+ ganttObj = createGantt({
+ dataSource: [
+ {
+ TaskID: 1,
+ TaskName: 'Product Concept',
+ StartDate: new Date('04/02/2019'),
+ EndDate: new Date('04/21/2019'),
+ subtasks: [
+ { TaskID: 2, TaskName: 'Defining the product and its usage', StartDate: new Date('04/02/2019'), Duration: 3, Progress: 30 },
+ { TaskID: 3, TaskName: 'Defining target audience', StartDate: new Date('04/02/2019'), Duration: 3 },
+ { TaskID: 4, TaskName: 'Prepare product sketch and notes', StartDate: new Date('04/02/2019'), Duration: 3, Predecessor: "2", Progress: 30 },
+ ]
+ }
+ ],
+ allowSorting: true,
+ allowSelection: true,
+ taskFields: {
+ id: 'TaskID',
+ name: 'TaskName',
+ startDate: 'StartDate',
+ duration: 'Duration',
+ progress: 'Progress',
+ endDate: 'EndDate',
+ child: 'subtasks',
+ },
+ editSettings: {
+ allowAdding: true,
+ allowEditing: true,
+ allowDeleting: true,
+ allowTaskbarEditing: true,
+ showDeleteConfirmDialog: true
+ },
+ toolbar: ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'Indent', 'Outdent'],
+ }, done);
+ });
+ afterAll(function () {
+ if (ganttObj) {
+ destroyGantt(ganttObj);
+ }
+ })
+ beforeEach(function (done) {
+ setTimeout(done, 1000);
+ });
+it('Verifying endDate after dialog add without startDate', () => {
+ ganttObj.openAddDialog();
+ ganttObj.dataBind();
+ let startDate: any = (document.getElementById(ganttObj.element.id + 'StartDate')).ej2_instances[0];
+ startDate.value = '';
+ startDate.dataBind();
+ let saveRecord: HTMLElement = document.querySelector('#' + ganttObj.element.id + '_dialog > div.e-footer-content > button.e-control.e-btn.e-lib.e-primary.e-flat') as HTMLElement;
+ triggerMouseEvent(saveRecord, 'click');
+ expect(ganttObj.getFormatedDate(ganttObj.flatData[0].ganttProperties.endDate, 'M/d/yyyy')).toEqual('4/2/2019');
+ });
+});
+ describe('Duration column Dialog editing with decimal', () => {
+ let ganttObj: Gantt;
+ let numericParams = { params: { decimals: 2 } };
+ beforeAll((done: Function) => {
+ ganttObj = createGantt({
+ dataSource: [{ TaskID: 5, TaskName: 'Concept Approval', StartDate: new Date('04/02/2019'), Duration: 1 }],
+ allowSorting: true,
+ allowReordering: true,
+ enableContextMenu: true,
+ taskFields: {
+ id: 'TaskID',
+ name: 'TaskName',
+ startDate: 'StartDate',
+ duration: 'Duration',
+ progress: 'Progress',
+ dependency: 'Predecessor',
+ baselineStartDate: "BaselineStartDate",
+ baselineEndDate: "BaselineEndDate",
+ child: 'subtasks',
+ indicators: 'Indicators'
+ },
+ renderBaseline: true,
+ baselineColor: 'red',
+ editSettings: {
+ allowAdding: true,
+ allowEditing: true,
+ allowDeleting: true,
+ allowTaskbarEditing: true,
+ showDeleteConfirmDialog: true
+ },
+ columns: [
+ { field: 'TaskID', headerText: 'Task ID' },
+ { field: 'TaskName', headerText: 'Task Name', allowReordering: false },
+ { field: 'StartDate', headerText: 'Start Date', allowSorting: false },
+ { field: 'Duration', headerText: 'Duration',edit:numericParams,editType:'numericedit' },
+ { field: 'Progress', headerText: 'Progress', allowFiltering: false },
+ { field: 'CustomColumn', headerText: 'CustomColumn' }
+ ],
+ toolbar: ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll', 'Search', 'ZoomIn', 'ZoomOut', 'ZoomToFit',
+ 'PrevTimeSpan', 'NextTimeSpan', 'ExcelExport', 'CsvExport', 'PdfExport'],
+ allowExcelExport: true,
+ allowPdfExport: true,
+ allowSelection: true,
+ allowRowDragAndDrop: true,
+ selectedRowIndex: 1,
+ splitterSettings: {
+ position: "50%",
+ },
+ selectionSettings: {
+ mode: 'Row',
+ type: 'Single',
+ enableToggle: false
+ },
+ tooltipSettings: {
+ showTooltip: true
+ },
+ filterSettings: {
+ type: 'Menu'
+ },
+ allowFiltering: true,
+ gridLines: "Both",
+ showColumnMenu: true,
+ highlightWeekends: true,
+ timelineSettings: {
+ showTooltip: true,
+ topTier: {
+ unit: 'Week',
+ format: 'dd/MM/yyyy'
+ },
+ bottomTier: {
+ unit: 'Day',
+ count: 1
+ }
+ },
+ eventMarkers: [
+ {
+ day: '04/10/2019',
+ cssClass: 'e-custom-event-marker',
+ label: 'Project approval and kick-off'
+ }
+ ],
+ holidays: [{
+ from: "04/04/2019",
+ to: "04/05/2019",
+ label: " Public holidays",
+ cssClass: "e-custom-holiday"
+ },
+ {
+ from: "04/12/2019",
+ to: "04/12/2019",
+ label: " Public holiday",
+ cssClass: "e-custom-holiday"
+ }],
+ searchSettings: { fields: ['TaskName', 'Duration']
+ },
+ labelSettings: {
+ leftLabel: 'TaskID',
+ rightLabel: 'Task Name: ${taskData.TaskName}',
+ taskLabel: '${Progress}%'
+ },
+ allowResizing: true,
+ readOnly: false,
+ taskbarHeight: 20,
+ rowHeight: 40,
+ height: '550px',
+ allowUnscheduledTasks: true,
+ projectStartDate: new Date('03/25/2019'),
+ projectEndDate: new Date('05/30/2019'),
+ }, done);
+ });
+ afterAll(() => {
+ if (ganttObj) {
+ destroyGantt(ganttObj);
+ }
+ });
+ beforeEach((done: Function) => {
+ setTimeout(done, 500);
+ ganttObj.openEditDialog('5');
+ });
+ it('editing with decimal', () => {
+ ganttObj.actionComplete = (args: any): void => {
+ if (args.requestType == "save") {
+ expect(args.data.ganttProperties.duration).toBe(0.25)
+ }
+ }
+ ganttObj.dataBind();
+ let durationField: any = document.querySelector('#' + ganttObj.element.id + 'Duration') as HTMLInputElement;
+ if (durationField) {
+ let textObj: any = (document.getElementById(ganttObj.element.id + 'Duration')).ej2_instances[0];
+ textObj.value = '0.25';
+ textObj.dataBind();
+ let save: HTMLElement = document.querySelectorAll('#' + ganttObj.element.id + '_dialog > div.e-footer-content > button.e-control')[1] as HTMLElement;
+ triggerMouseEvent(save, 'click');
+ }
+ });
+});
+describe('Add new record with validation rule', () => {
+ let ganttObj: Gantt;
+ beforeAll((done: Function) => {
+ ganttObj = createGantt({
+ dataSource: [],
+ allowSorting: true,
+ allowReordering: true,
+ enableContextMenu: true,
+ taskFields: {
+ id: 'TaskID',
+ name: 'TaskName',
+ startDate: 'StartDate',
+ duration: 'Duration',
+ progress: 'Progress',
+ dependency: 'Predecessor',
+ baselineStartDate: "BaselineStartDate",
+ baselineEndDate: "BaselineEndDate",
+ child: 'subtasks',
+ indicators: 'Indicators'
+ },
+ renderBaseline: true,
+ baselineColor: 'red',
+ editSettings: {
+ allowAdding: true,
+ allowEditing: true,
+ allowDeleting: true,
+ allowTaskbarEditing: true,
+ showDeleteConfirmDialog: true
+ },
+ columns: [
+ { field: 'TaskID', headerText: 'Task ID' },
+ { field: 'TaskName', headerText: 'Task Name', allowReordering: false },
+ { field: 'StartDate', headerText: 'Start Date', allowSorting: false },
+ { field: 'Duration', headerText: 'Duration', allowEditing: false },
+ { field: 'Progress', headerText: 'Progress', allowFiltering: false },
+ {
+ field: 'CustomColumn', headerText: 'CustomColumn', editType: 'numericedit', validationRules: {
+ number: true,
+ min: 20, required: true
+ }
+ }
+ ],
+ editDialogFields: [
+ { type: 'General', headerText: 'General' },
+ { type: 'Dependency' },
+ { type: 'Resources' },
+ { type: 'Notes' }
+ ],
+ addDialogFields: [
+ { type: 'General', headerText: 'General',fields:['TaskID','TaskName','CustomColumn'] },
+ { type: 'Dependency' },
+ { type: 'Resources' },
+ { type: 'Notes' }
+ ],
+ sortSettings: {
+ columns: [{ field: 'TaskID', direction: 'Ascending' },
+ { field: 'TaskName', direction: 'Ascending' }]
+ },
+ toolbar: ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll', 'Search', 'ZoomIn', 'ZoomOut', 'ZoomToFit',
+ 'PrevTimeSpan', 'NextTimeSpan', 'ExcelExport', 'CsvExport', 'PdfExport'],
+ allowExcelExport: true,
+ allowPdfExport: true,
+ allowSelection: true,
+ allowRowDragAndDrop: true,
+ selectedRowIndex: 1,
+ splitterSettings: {
+ position: "50%",
+ // columnIndex: 4
+ },
+ selectionSettings: {
+ mode: 'Row',
+ type: 'Single',
+ enableToggle: false
+ },
+ tooltipSettings: {
+ showTooltip: true
+ },
+ filterSettings: {
+ type: 'Excel'
+ },
+ allowFiltering: true,
+ gridLines: "Both",
+ showColumnMenu: true,
+ highlightWeekends: true,
+ timelineSettings: {
+ showTooltip: true,
+ topTier: {
+ unit: 'Week',
+ format: 'dd/MM/yyyy'
+ },
+ bottomTier: {
+ unit: 'Day',
+ count: 1
+ }
+ },
+ eventMarkers: [
+ {
+ day: '04/10/2019',
+ cssClass: 'e-custom-event-marker',
+ label: 'Project approval and kick-off'
+ }
+ ],
+ holidays: [{
+ from: "04/04/2019",
+ to: "04/05/2019",
+ label: " Public holidays",
+ cssClass: "e-custom-holiday"
+
+ },
+ {
+ from: "04/12/2019",
+ to: "04/12/2019",
+ label: " Public holiday",
+ cssClass: "e-custom-holiday"
+
+ }],
+ searchSettings:
+ {
+ fields: ['TaskName', 'Duration']
+ },
+ labelSettings: {
+ leftLabel: 'TaskID',
+ rightLabel: 'Task Name: ${taskData.TaskName}',
+ taskLabel: '${Progress}%'
+ },
+ allowResizing: true,
+ readOnly: false,
+ taskbarHeight: 20,
+ rowHeight: 40,
+ height: '550px',
+ allowUnscheduledTasks: true,
+ projectStartDate: new Date('03/25/2019'),
+ projectEndDate: new Date('05/30/2019'),
+ }, done);
+ });
+ afterAll(() => {
+ if (ganttObj) {
+ destroyGantt(ganttObj);
+ }
+ });
+ beforeEach((done: Function) => {
+ setTimeout(done, 500);
+ ganttObj.openAddDialog();
+ });
+ it('add record', () => {
+ ganttObj.actionComplete = (args: any): void => {
+ if (args.requestType == "refresh") {
+ expect(ganttObj.currentViewData.length).toBe(0);
+ }
+ }
+ ganttObj.dataBind();
+ let saveRecord: HTMLElement = document.querySelector('#' + ganttObj.element.id + '_dialog > div.e-footer-content > button.e-control.e-btn.e-lib.e-primary.e-flat') as HTMLElement;
+ triggerMouseEvent(saveRecord, 'click');
+ });
+});
+describe('Edit cell with timeline virtualization', () => {
+ let ganttObj: Gantt;
+ let SelfReferenceData = [
+ { TaskID: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019'), Notes: 'xxxxx' },
+ { TaskID: 2, TaskName: 'Identify Site location Empty note', StartDate: new Date('03/29/2019'), Duration: 4, Progress: 50, ParentId: 1, Notes: '' },
+ { TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50, ParentId: 1 },
+ { TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2019'), Duration: 4, Progress: 50, Predecessor: '2', ParentId: 1 },
+ { TaskID: 5, TaskName: 'Project Estimation', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
+ { TaskID: 6, TaskName: 'Develop floor plan for estimation', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50, ParentId: 5 },
+ { TaskID: 7, TaskName: 'List materials_info', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50, ParentId: 5, Notes: 'yyyyyyy' },
+ { TaskID: 8, TaskName: 'Estimation approval', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 50, ParentId: 5 }
+ ];
+ beforeAll((done: Function) => {
+ ganttObj = createGantt(
+ {
+ dataSource: SelfReferenceData,
+ enableTimelineVirtualization: true,
+ allowExcelExport: true,
+ height: '450px',
+ enableImmutableMode: true,
+ highlightWeekends: true,
+ allowResizing: true,
+ showColumnMenu: true,
+ allowFiltering: true,
+ allowSorting: true,
+ allowReordering: true,
+ allowRowDragAndDrop: true,
+ taskFields: {
+ id: 'TaskID',
+ name: 'TaskName',
+ startDate: 'StartDate',
+ endDate: 'EndDate',
+ duration: 'Duration',
+ progress: 'Progress',
+ dependency: 'Predecessor',
+ notes: 'Notes',
+ parentID: 'ParentId'
+ },
+ editSettings: {
+ allowAdding: true,
+ allowEditing: true,
+ allowDeleting: true,
+ allowTaskbarEditing: true,
+ showDeleteConfirmDialog: true
+ },
+ editDialogFields: [
+ { type: 'General' },
+ { type: 'Dependency' },
+ { type: 'Notes' },
+ ],
+ treeColumnIndex: 1,
+ toolbar: ['Add', 'Edit', 'Delete', 'CriticalPath', 'ExcelExport', 'PdfExport', { text: 'Quick Filter', id: 'Quick Filter' }, { text: 'Clear Filter', id: 'Clear Filter' }],
+ columns: [
+ { field: 'TaskID', width: 50 },
+ { field: 'TaskName', width: 250 },
+ { field: 'StartDate' },
+ { field: 'EndDate' },
+ { field: 'Duration' },
+ { field: 'Predecessor' },
+ { field: 'Progress' },
+ { field: 'Notes' },
+ ],
+ selectionSettings: {
+ type: 'Multiple'
+ },
+ splitterSettings: {
+ columnIndex: 4
+ },
+ enableContextMenu: true,
+ projectStartDate: new Date('03/24/2019'),
+ projectEndDate: new Date('07/06/2019')
+ }, done);
+ });
+ afterAll(() => {
+ if (ganttObj) {
+ destroyGantt(ganttObj);
+ }
+ });
+ beforeEach((done: Function) => {
+ ganttObj.openEditDialog(1);
+ setTimeout(done, 500);
+ });
+ it('edit start date cell', () => {
+ ganttObj.actionComplete = (args: any): void => {
+ if(args.action === "DialogEditing")
+ expect(ganttObj.getFormatedDate(ganttObj.timelineModule.timelineEndDate, 'MM/dd/yyyy')).toBe('04/07/2024');
+ };
+ let StartDate: any = document.querySelector('#' + ganttObj.element.id + 'StartDate') as HTMLInputElement;
+ if (StartDate) {
+ let SD: any = (document.getElementById(ganttObj.element.id + 'StartDate')).ej2_instances[0];
+ SD.value = new Date('03/22/2024');
+ SD.dataBind();
+ let save: HTMLElement = document.querySelectorAll('#' + ganttObj.element.id + '_dialog > div.e-footer-content > button.e-control')[0] as HTMLElement;
+ triggerMouseEvent(save, 'click');
+ }
+ });
+});
\ No newline at end of file
diff --git a/controls/gantt/spec/base/predecessor.spec.ts b/controls/gantt/spec/base/predecessor.spec.ts
index d21cbd5a52..5521db0a01 100644
--- a/controls/gantt/spec/base/predecessor.spec.ts
+++ b/controls/gantt/spec/base/predecessor.spec.ts
@@ -1051,3 +1051,151 @@ describe('AlphaID predecessor', () => {
destroyGantt(ganttObj);
});
});
+describe('predecessor validation', () => {
+ let ganttObj: Gantt;
+ var projectNewData = [
+ {
+ TaskID: 1,
+ TaskName: 'Product Concept',
+ StartDate: new Date('04/02/2019'),
+ EndDate: new Date('04/21/2019'),
+ subtasks: [
+ { TaskID: 4, TaskName: 'Prepare product sketch and notes', StartDate: new Date('04/02/2019'), Duration: 3, Predecessor: "2", Progress: 30 },
+ ]
+ },
+ { TaskID: 5, TaskName: 'Concept Approval', StartDate: new Date('04/02/2019'), Duration: 0, Predecessor: "3,4" },
+ {
+ TaskID: 6,
+ TaskName: 'Market Research',
+ StartDate: new Date('04/02/2019'),
+ EndDate: new Date('04/21/2019'),
+ subtasks: [
+ {
+ TaskID: 7,
+ TaskName: 'Demand Analysis',
+ StartDate: new Date('04/04/2019'),
+ EndDate: new Date('04/21/2019'),
+ subtasks: [
+ { TaskID: 9, TaskName: 'Market opportunity analysis', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: "5" }
+ ]
+ },
+ { TaskID: 10, TaskName: 'Competitor Analysis', StartDate: new Date('04/04/2019'), Duration: 4, Predecessor: "7,8", Progress: 30 },
+ ]
+ },
+ ];
+ beforeAll((done: Function) => {
+ ganttObj = createGantt(
+ {
+ dataSource: projectNewData,
+ allowSorting: true,
+ allowReordering: true,
+ enableContextMenu: true,
+ taskFields: {
+ id: 'TaskID',
+ name: 'TaskName',
+ startDate: 'StartDate',
+ duration: 'Duration',
+ progress: 'Progress',
+ dependency: 'Predecessor',
+ baselineStartDate: "BaselineStartDate",
+ baselineEndDate: "BaselineEndDate",
+ child: 'subtasks',
+ indicators: 'Indicators'
+ },
+ renderBaseline: true,
+ baselineColor: 'red',
+ editSettings: {
+ allowAdding: true,
+ allowEditing: true,
+ allowDeleting: true,
+ allowTaskbarEditing: true,
+ showDeleteConfirmDialog: true
+ },
+ columns: [
+ { field: 'TaskID', headerText: 'Task ID' },
+ { field: 'TaskName', headerText: 'Task Name', allowReordering: false },
+ { field: 'StartDate', headerText: 'Start Date', allowSorting: false },
+ { field: 'Duration', headerText: 'Duration', allowEditing: false },
+ { field: 'Progress', headerText: 'Progress', allowFiltering: false },
+ { field: 'CustomColumn', headerText: 'CustomColumn' }
+ ],
+ sortSettings: {
+ columns: [{ field: 'TaskID', direction: 'Ascending' },
+ { field: 'TaskName', direction: 'Ascending' }]
+ },
+ toolbar: ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll', 'Search', 'ZoomIn', 'ZoomOut', 'ZoomToFit',
+ 'PrevTimeSpan', 'NextTimeSpan', 'ExcelExport', 'CsvExport', 'PdfExport'],
+ allowExcelExport: true,
+ allowPdfExport: true,
+ allowSelection: true,
+ allowRowDragAndDrop: true,
+ selectedRowIndex: 1,
+ splitterSettings: {
+ position: "50%",
+ },
+ selectionSettings: {
+ mode: 'Row',
+ type: 'Single',
+ enableToggle: false
+ },
+ tooltipSettings: {
+ showTooltip: true
+ },
+ filterSettings: {
+ type: 'Menu'
+ },
+ allowFiltering: true,
+ gridLines: "Both",
+ showColumnMenu: true,
+ highlightWeekends: true,
+ timelineSettings: {
+ showTooltip: true,
+ topTier: {
+ unit: 'Week',
+ format: 'dd/MM/yyyy'
+ },
+ bottomTier: {
+ unit: 'Day',
+ count: 1
+ }
+ },
+ holidays: [{
+ from: "04/04/2019",
+ to: "04/05/2019",
+ label: " Public holidays",
+ cssClass: "e-custom-holiday"
+ },
+ {
+ from: "04/12/2019",
+ to: "04/12/2019",
+ label: " Public holiday",
+ cssClass: "e-custom-holiday"
+ }],
+ allowResizing: true,
+ readOnly: false,
+ taskbarHeight: 20,
+ rowHeight: 40,
+ height: '550px',
+ allowUnscheduledTasks: true,
+ projectStartDate: new Date('03/25/2019'),
+ projectEndDate: new Date('05/30/2019'),
+ }, done);
+ });
+ beforeEach((done: Function) => {
+ setTimeout(done, 500);
+ });
+ it('Check predecessor length', (done) => {
+ ganttObj.taskbarEdited = (args: any) => {
+ expect(ganttObj.getFormatedDate(ganttObj.currentViewData[4].ganttProperties.startDate, 'MM/dd/yyyy')).toBe('04/02/2019');
+ };
+ ganttObj.dataBind();
+ let dragElement: HTMLElement = ganttObj.element.querySelector('#' + ganttObj.element.id + 'GanttTaskTableBody > tr:nth-child(2) > td > div.e-taskbar-main-container > div.e-taskbar-right-resizer.e-icon') as HTMLElement;
+ triggerMouseEvent(dragElement, 'mousedown', dragElement.offsetLeft, dragElement.offsetTop);
+ triggerMouseEvent(dragElement, 'mousemove', -100, 0);
+ triggerMouseEvent(dragElement, 'mouseup');
+ done();
+ });
+ afterAll(() => {
+ destroyGantt(ganttObj);
+ });
+});
\ No newline at end of file
diff --git a/controls/gantt/spec/base/resource-view.spec.ts b/controls/gantt/spec/base/resource-view.spec.ts
index 1dc3719a20..c8c61dad42 100644
--- a/controls/gantt/spec/base/resource-view.spec.ts
+++ b/controls/gantt/spec/base/resource-view.spec.ts
@@ -3098,3 +3098,92 @@ describe("Project view duration editing", () => {
expect(ganttObj.currentViewData[2].ganttProperties.duration).toBe(null);
});
});
+describe('CR-Task:875889-Exception when resource ID mapping is empty', () => {
+ let ganttObj: Gantt;
+ let resourceCollection = [
+ { resourceId: 1, resourceName: 'Martin Tamer', resourceGroup: 'Planning Team' },
+ ];
+ beforeAll((done: Function) => {
+ ganttObj = createGantt(
+ {
+ dataSource: [
+ {
+ TaskID: 1,
+ TaskName: 'Project initiation',
+ StartDate: new Date('03/29/2019'),
+ EndDate: new Date('04/02/2019'),
+ subtasks: []
+ },
+ {
+ TaskID: 5,
+ TaskName: 'Project estimation',
+ StartDate: new Date('03/29/2019'),
+ EndDate: new Date('04/21/2019')
+ }
+ ],
+ resources: resourceCollection,
+ viewType: 'ResourceView',
+ showOverAllocation: true,
+ enableContextMenu: true,
+ allowSorting: true,
+ allowReordering: true,
+ taskFields: {
+ id: 'TaskID',
+ name: 'TaskName',
+ startDate: 'StartDate',
+ endDate: 'EndDate',
+ duration: 'Duration',
+ progress: 'Progress',
+ dependency: 'Predecessor',
+ resourceInfo: 'resources',
+ child: 'subtasks'
+ },
+ resourceFields: {
+ id: 'resourceId'
+ },
+ editSettings: {
+ allowAdding: true,
+ allowEditing: true,
+ allowDeleting: true,
+ allowTaskbarEditing: true,
+ showDeleteConfirmDialog: true
+ },
+ columns: [
+ { field: 'TaskID', visible: false },
+ { field: 'TaskName', headerText: 'Name', width: 250 },
+ { field: 'work', headerText: 'Work' },
+ { field: 'Progress' },
+ { field: 'resourceGroup', headerText: 'Group' },
+ { field: 'StartDate' },
+ { field: 'Duration' },
+ ],
+ splitterSettings: {
+ columnIndex: 3
+ },
+ timelineSettings: {
+ showTooltip: true,
+ topTier: {
+ unit: 'Week',
+ format: 'dd/MM/yyyy'
+ },
+ bottomTier: {
+ unit: 'Day',
+ count: 1
+ }
+ },
+ allowResizing: true,
+ allowFiltering: true,
+ allowSelection: true,
+ highlightWeekends: true,
+ treeColumnIndex: 1,
+ height: '550px'
+ }, done);
+ });
+ it('Checking unassigned childrecords length', () => {
+ expect(ganttObj.currentViewData[1].ganttProperties.taskName).toBe("Unassigned Task");
+ expect(ganttObj.currentViewData[1].childRecords.length).toBe(2);
+ });
+ afterAll(() => {
+ destroyGantt(ganttObj);
+ });
+});
\ No newline at end of file
diff --git a/controls/gantt/spec/renderer/nonworking-day.spec.ts b/controls/gantt/spec/renderer/nonworking-day.spec.ts
index ba31a1302a..aaffd49e9b 100644
--- a/controls/gantt/spec/renderer/nonworking-day.spec.ts
+++ b/controls/gantt/spec/renderer/nonworking-day.spec.ts
@@ -1,10 +1,14 @@
/**
* Gantt base spec
*/
-import { Gantt, DayMarkers } from '../../src/index';
+import { Gantt, DayMarkers, Edit, Toolbar, ContextMenu, Sort, VirtualScroll,Selection } from '../../src/index';
import * as cls from '../../src/gantt/base/css-constants';
import { baselineData,projectData } from '../base/data-source.spec';
-import { createGantt, destroyGantt } from '../base/gantt-util.spec';
+import { createGantt, destroyGantt,triggerMouseEvent } from '../base/gantt-util.spec';
+interface EJ2Instance extends HTMLElement {
+ ej2_instances: Object[];
+}
+
describe('Gantt spec for non -working-day', () => {
describe('Gantt base module', () => {
Gantt.Inject(DayMarkers);
@@ -152,4 +156,116 @@ describe('Gantt spec for non -working-day', () => {
];
});
});
-});
\ No newline at end of file
+});
+describe('874399 - weekend is not visible', function () {
+ Gantt.Inject(Edit, Toolbar,ContextMenu,Sort,Selection, VirtualScroll);
+ let ganttObj: Gantt;
+ let data: Object[] = [
+ { TaskID: 1, TaskName: 'Project Initiation_1', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
+ { TaskID: 2, TaskName: 'Identify Site location_1', StartDate: new Date('03/29/2019'), Duration: 6, Progress: 70, ParentId: 1 },
+ { TaskID: 3, TaskName: 'Perform Soil test_1', StartDate: new Date('04/02/2019'), Duration: 7, Progress: 70, ParentId: 1 },
+ { TaskID: 4, TaskName: 'Soil test approval_1', StartDate: new Date('04/02/2019'), Duration: 8, Progress: 70, Predecessor: '2', ParentId: 1 },
+ { TaskID: 5, TaskName: 'Project Estimation_1', StartDate: new Date('04/02/2019'), EndDate: new Date('04/21/2019') },
+ { TaskID: 6, TaskName: 'Develop floor plan for estimation_1', StartDate: new Date('04/04/2019'), Duration: 9, Progress: 70, ParentId: 5 },
+ { TaskID: 7, TaskName: 'List materials_1', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 70, ParentId: 5 },
+ { TaskID: 8, TaskName: 'Estimation approval_1', StartDate: new Date('04/04/2019'), Duration: 3, Progress: 70, ParentId: 5 }
+ ];
+
+ beforeAll(function (done) {
+ ganttObj = createGantt({
+ dataSource: data,
+ enableContextMenu: true,
+ taskFields: {
+ id: 'TaskID',
+ name: 'TaskName',
+ startDate: 'StartDate',
+ endDate: 'EndDate',
+ duration: 'Duration',
+ progress: 'Progress',
+ dependency: 'Predecessor',
+ notes: 'Notes',
+ parentID: 'ParentId'
+ },
+ editSettings: {
+ allowAdding: true,
+ allowEditing: true,
+ allowDeleting: true,
+ allowTaskbarEditing: true,
+ showDeleteConfirmDialog: true
+ },
+ columns: [
+ { field: 'TaskID' },
+ { field: 'TaskName', width: 80 },
+ { field: 'StartDate', width: 120 },
+ { field: 'EndDate', width: 120 },
+ { field: 'Duration', width: 90 },
+ { field: 'TaskType', visible: false }
+ ],
+ enableTimelineVirtualization:true,
+ sortSettings: {
+ columns: [{ field: 'TaskID', direction: 'Ascending' },
+ { field: 'TaskName', direction: 'Ascending' }]
+ },
+ splitterSettings: {
+ columnIndex: 4
+ },
+ toolbar: ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll', 'Search', 'ZoomIn', 'ZoomOut', 'ZoomToFit',],
+ allowSelection: true,
+ allowRowDragAndDrop: true,
+ selectedRowIndex: 1,
+ selectionSettings: {
+ mode: 'Row',
+ type: 'Single',
+ enableToggle: false
+ },
+ tooltipSettings: {
+ showTooltip: true
+ },
+ filterSettings: {
+ type: 'Menu'
+ },
+ allowFiltering: true,
+ gridLines: "Both",
+ showColumnMenu: true,
+ highlightWeekends: true,
+ timelineSettings: {
+ showTooltip: true,
+ topTier: {
+ unit: 'Week',
+ format: 'dd/MM/yyyy'
+ },
+ bottomTier: {
+ unit: 'Day',
+ count: 1
+ }
+ },
+ allowResizing: true,
+ readOnly: false,
+ taskbarHeight: 20,
+ rowHeight: 40,
+ height: '550px',
+ allowUnscheduledTasks: true,
+ projectStartDate: new Date('03/24/2019'),
+ projectEndDate: new Date('07/06/2024')
+ }, done);
+ });
+ afterAll(function () {
+ if (ganttObj) {
+ destroyGantt(ganttObj);
+ }
+ });
+ beforeEach((done: Function) => {
+ setTimeout(done, 1000);
+ });
+ it('editing startdate', () => {
+ ganttObj.dataBind();
+ let startDate: HTMLElement = ganttObj.element.querySelector('#treeGrid' + ganttObj.element.id + '_gridcontrol_content_table > tbody > tr:nth-child(1) > td:nth-child(4)') as HTMLElement;
+ triggerMouseEvent(startDate, 'dblclick');
+ let input: any = (document.querySelector('#treeGrid' + ganttObj.element.id + '_gridcontrolStartDate')as any).ej2_instances[0];
+ input.value = new Date('03/04/2024');
+ let element: HTMLElement = ganttObj.element.querySelector('#treeGrid' + ganttObj.element.id + '_gridcontrol_content_table > tbody > tr:nth-child(3) > td:nth-child(2)') as HTMLElement;
+ triggerMouseEvent(element, 'click');
+ ganttObj.selectRow(0);
+ expect(ganttObj.ganttChartModule.chartBodyContent.querySelector(`.${cls.weekend}`)['style'].left).toBe('0px');
+ });
+});
\ No newline at end of file
diff --git a/controls/gantt/src/gantt/actions/connector-line-edit.ts b/controls/gantt/src/gantt/actions/connector-line-edit.ts
index 60a8a98402..e1287fa69e 100644
--- a/controls/gantt/src/gantt/actions/connector-line-edit.ts
+++ b/controls/gantt/src/gantt/actions/connector-line-edit.ts
@@ -685,14 +685,15 @@ export class ConnectorLineEdit {
} else if (args.validateMode.preserveLinkWithEditing) {
let connectedTaskId:any;
if (this.parent.UpdateOffsetOnTaskbarEdit) {
- this.calculateOffset(ganttRecord);
let taskId:any = ganttRecord.ganttProperties.taskId;
- ganttRecord.ganttProperties.predecessor.forEach(predecessor => {
- if (taskId == predecessor.from) {
- connectedTaskId = predecessor.to
- return
- }
- });
+ if (ganttRecord.ganttProperties.predecessor) {
+ ganttRecord.ganttProperties.predecessor.forEach(predecessor => {
+ if (taskId == predecessor.from) {
+ connectedTaskId = predecessor.to
+ return
+ }
+ });
+ }
}
this.parent.editModule.updateEditedTask(args.editEventArgs);
this.processPredecessors(connectedTaskId)
diff --git a/controls/gantt/src/gantt/actions/dependency.ts b/controls/gantt/src/gantt/actions/dependency.ts
index 1873eeea21..3fc47e1298 100644
--- a/controls/gantt/src/gantt/actions/dependency.ts
+++ b/controls/gantt/src/gantt/actions/dependency.ts
@@ -903,6 +903,9 @@ export class Dependency {
|| id.toString() === predecessor.from)
&& (!validationOn || validationOn === 'predecessor')) {
this.validateChildGanttRecord(parentGanttRecord, record);
+ if (this.parent.editModule['editedRecord'] && this.parent.editModule['editedRecord'].hasChildRecords && !this.parent.editModule['editedRecord'].parentItem) {
+ this.isValidatedParentTaskID = record.ganttProperties.taskId;
+ }
}
}
@@ -933,6 +936,13 @@ export class Dependency {
}
if (validationOn !== 'predecessor' && this.parent.isValidationEnabled) {
this.validateChildGanttRecord(parentGanttRecord, record);
+ if (record && record.hasChildRecords && this.isValidatedParentTaskID != record.ganttProperties.taskId) {
+ this.updateChildItems(record);
+ this.isValidatedParentTaskID = record.ganttProperties.taskId;
+ }
+ if (this.parent.editModule['editedRecord'] && this.parent.editModule['editedRecord'].hasChildRecords && !this.parent.editModule['editedRecord'].parentItem) {
+ this.isValidatedParentTaskID = record.ganttProperties.taskId;
+ }
}
else if (!record.ganttProperties.isAutoSchedule && this.parent.UpdateOffsetOnTaskbarEdit) {
this.parent.connectorLineEditModule['calculateOffset'](record);
@@ -941,15 +951,20 @@ export class Dependency {
if (record) { this.validatePredecessor(record, undefined, 'successor'); }
continue;
}
- if (record) {
+ if (record) {
if (this.parent.editModule.isFirstCall) {
this.storeId = JSON.parse(JSON.stringify(this.parent.ids));
this.parent.editModule.isFirstCall = false
}
- let index: any = (this.storeId && this.storeId.indexOf(record[this.parent.taskFields.id].toString()) !== -1) ? this.storeId.indexOf(record[this.parent.taskFields.id].toString()) : -1;
- if (index !== -1) {
- this.storeId = this.storeId.slice(0, index).concat(this.storeId.slice(index + 1));
- this.validatePredecessor(record, undefined, 'successor');
+ if (this.storeId) {
+ let index = (this.storeId.indexOf(record[this.parent.taskFields.id].toString()) !== -1) ? this.storeId.indexOf(record[this.parent.taskFields.id].toString()) : -1;
+ if (index !== -1) {
+ this.storeId = this.storeId.slice(0, index).concat(this.storeId.slice(index + 1));
+ this.validatePredecessor(record, undefined, 'successor');
+ }
+ }
+ else {
+ this.validatePredecessor(record, undefined, 'successor');
}
}
}
@@ -969,12 +984,24 @@ export class Dependency {
}
}
else if ((!record.hasChildRecords && taskBarModule.taskBarEditAction == 'ChildDrag') ||
- (record.hasChildRecords && taskBarModule.taskBarEditAction == 'ParentDrag')) {
+ (record.hasChildRecords && (taskBarModule.taskBarEditAction == 'ChildDrag' || taskBarModule.taskBarEditAction == 'ParentDrag'))) {
this.updateChildItems(record);
this.isValidatedParentTaskID = record.ganttProperties.taskId;
}
- if (!ganttProp.hasChildRecords) {
+ if (record.parentItem) {
this.parent.dataOperation.updateParentItems(record, true);
+ const parentData: IGanttData = this.parent.getParentTask(record.parentItem);
+ const index: number = (this.storeId && this.storeId.indexOf(parentData[this.parent.taskFields.id].toString()) !== -1) ? this.storeId.indexOf(parentData[this.parent.taskFields.id].toString()) : -1;
+ if (parentData.ganttProperties.predecessor && parentData.ganttProperties.predecessor.length > 0 && index !== -1) {
+ for (let i: number = 0; i < parentData.ganttProperties.predecessor.length; i++) {
+ if (parentData.ganttProperties.predecessor[i as number].to != parentData.ganttProperties.taskId.toString()) {
+ const childRec: IGanttData = this.parent.flatData[this.parent.ids.indexOf(parentData.ganttProperties.predecessor[i as number].to)];
+ if (childRec) {
+ this.validateChildGanttRecord(record, childRec);
+ }
+ }
+ }
+ }
}
}
else if (record && record.hasChildRecords && this.isValidatedParentTaskID != record.ganttProperties.taskId && !ganttProp) {
@@ -1063,6 +1090,9 @@ export class Dependency {
this.validatedChildItems.push(childRecords[i as number]);
}
}
+ if (!this.parent.isLoad && childRecords[i as number].ganttProperties.predecessor && childRecords[i as number].ganttProperties.predecessor.length > 0) {
+ this.validatePredecessor(childRecords[i as number],[], '');
+ }
}
}
if (childRecords.length) {
diff --git a/controls/gantt/src/gantt/actions/dialog-edit.ts b/controls/gantt/src/gantt/actions/dialog-edit.ts
index a0dcdefbf8..be8006ed5c 100644
--- a/controls/gantt/src/gantt/actions/dialog-edit.ts
+++ b/controls/gantt/src/gantt/actions/dialog-edit.ts
@@ -73,11 +73,8 @@ export class DialogEdit {
private storeColumn:any;
private taskfields:any;
private storeValidTab:any;
- private singleTab:boolean;
private storeDependencyTab:HTMLElement;
private storeResourceTab:HTMLElement;
- private isAddingDialog : boolean;
- private isEditingDialog :boolean;
private firstOccuringTab:string;
private numericOrString: any;
private types: IDependencyEditData[];
@@ -490,112 +487,62 @@ export class DialogEdit {
target.style.pointerEvents = 'none';
if ((this.localeObj.getConstant('cancel')).toLowerCase() === (e.target as HTMLInputElement).innerText.trim().toLowerCase()) {
if (this.dialog && !this.dialogObj.isDestroyed) {
+ this.CustomformObj = null;
+ this.formObj = null;
this.dialogObj.hide();
this.dialogClose();
}
} else {
- if (this.singleTab && this.CustomformObj) {
+ if (this.CustomformObj) {
if (!this.CustomformObj.validate()) {
target.style.pointerEvents = '';
return;
}
- } else {
- if (this.CustomformObj) {
- if (this.isAddingDialog ) {
- if (this.parent.addDialogFields.length > 1 && this.parent.addDialogFields[0].type == "Custom" && !this.formObj) {
- if (!this.CustomformObj.validate()) {
- target.style.pointerEvents = '';
- return;
- }
- }
- } else if (this.isEditingDialog ) {
- if (this.parent.editDialogFields.length > 1 && this.parent.editDialogFields[0].type == "Custom" && !this.formObj) {
- if (!this.CustomformObj.validate()) {
- target.style.pointerEvents = '';
- return;
- }
- }
- }
- if (!this.formObj.validate() && !this.CustomformObj.validate()) {
+ }
+ if (this.formObj) {
+ let formValid = this.formObj.validate();
+ if (!formValid) {
+ target.style.pointerEvents = '';
+ return;
+ }
+ }
+ if (this.storeDependencyTab || this.firstOccuringTab === "Dependency") {
+ let dependencyTab;
+ if (this.firstOccuringTab === "Dependency") {
+ let element = (e.target as Element).closest('#' + this.parent.element.id + '_dialog');
+ dependencyTab = element.querySelector('.e-gridform');
+ } else {
+ dependencyTab = this.storeDependencyTab.querySelector('.e-gridform');
+ }
+ if (dependencyTab) {
+ let dependencyTabValid = dependencyTab['ej2_instances'][0].validate();
+ if (!dependencyTabValid) {
target.style.pointerEvents = '';
return;
}
}
- if (this.formObj) {
- let formValid = this.formObj.validate();
- if (this.storeDependencyTab) {
- let dependencyTab = this.storeDependencyTab.querySelector('.e-gridform');
- if (dependencyTab) {
- let dependencyTabValid = dependencyTab['ej2_instances'][0].validate();
- if (!formValid || !dependencyTabValid) {
- target.style.pointerEvents = '';
- return;
- }
- }
- }
- if (this.storeResourceTab) {
- let resourceTab = this.storeResourceTab.querySelector('.e-gridform');
- if (resourceTab) {
- let resourceTabValid = resourceTab['ej2_instances'][0].validate();
- if (!formValid || !resourceTabValid) {
- target.style.pointerEvents = '';
- return;
- }
- }
- }
- if (!formValid) {
+ }
+ if (this.storeResourceTab || this.firstOccuringTab === "Resources") {
+ let resourceTab;
+ if (this.firstOccuringTab === "Resources") {
+ let element = (e.target as Element).closest('#' + this.parent.element.id + '_dialog');
+ resourceTab = element.querySelector('.e-gridform');
+ } else {
+ resourceTab = this.storeResourceTab.querySelector('.e-gridform');
+ }
+
+ if (resourceTab) {
+ let resourceTabValid = resourceTab['ej2_instances'][0].validate();
+ if (!resourceTabValid) {
target.style.pointerEvents = '';
return;
}
- } else if (this.storeDependencyTab || this.firstOccuringTab == "Dependency") {
- if (this.firstOccuringTab == "Dependency") {
- let element = (e.target as Element).closest('#'+this.parent.element.id+'_dialog');
- let dependencyTab = element.querySelector('.e-gridform');
- if (dependencyTab) {
- let dependencyTabValid = dependencyTab['ej2_instances'][0].validate();
- if (!dependencyTabValid) {
- target.style.pointerEvents = '';
- return;
- }
- }
- } else {
- let dependencyTab = this.storeDependencyTab.querySelector('.e-gridform');
- if (dependencyTab) {
- let dependencyTabValid = dependencyTab['ej2_instances'][0].validate();
- if (!dependencyTabValid) {
- target.style.pointerEvents = '';
- return;
- }
- }
- }
- } else if (this.storeResourceTab || this.firstOccuringTab == "Resources") {
- if (this.firstOccuringTab == "Resources") {
- let element = (e.target as Element).closest('#'+this.parent.element.id+'_dialog');
- let resourceTab = element.querySelector('.e-gridform');
- if (resourceTab) {
- let resourceTabValid = resourceTab['ej2_instances'][0].validate();
- if (!resourceTabValid) {
- target.style.pointerEvents = '';
- return;
- }
- }
- } else {
- let resourceTab = this.storeResourceTab.querySelector('.e-gridform');
- if (resourceTab) {
- let resourceTabValid = resourceTab['ej2_instances'][0].validate();
- if (!resourceTabValid) {
- target.style.pointerEvents = '';
- return;
- }
- }
- }
}
}
this.initiateDialogSave();
+ this.CustomformObj = null;
+ this.formObj = null;
target.style.pointerEvents = 'auto';
- this.singleTab = false;
- this.isAddingDialog = false;
- this.isEditingDialog = false;
}
}
/**
@@ -821,6 +768,8 @@ export class DialogEdit {
const columns: any[] = this.parent.treeGrid.grid.getColumns();
const isValidateColumn: boolean = columns.some(obj => obj.validationRules);
if (isValidateColumn) {
+ this.CustomformObj = null;
+ this.formObj = null;
this.changeFormObj(actionCompleteArgs.element, false);
}
this.parent.trigger('actionComplete', actionCompleteArgs, (actionCompleteArg: CObject) => {
@@ -873,92 +822,50 @@ export class DialogEdit {
this.validateColumn(this.storeColumn, this.taskfields, this.storeValidTab);
}
- if ((this.isFromAddDialog || this.isFromEditDialog) && this.isSingleCustomTab()) {
- isCustomTab = true;
- this.singleTab = true;
- }
- if (this.isFromAddDialog) {
- if (this.parent.addDialogFields.length > 1) {
- if (this.parent.addDialogFields[0].type === 'Resources'
- || this.parent.addDialogFields[0].type === 'Dependency') {
- this.firstOccuringTab = this.parent.addDialogFields[0].type;
- }
- }
- if (this.parent.addDialogFields.length == 1) {
- this.firstOccuringTab = this.parent.addDialogFields[0].type;
- }
- }
- else if (this.isFromEditDialog) {
- if (this.parent.editDialogFields.length > 1) {
- if (this.parent.editDialogFields[0].type === 'Resources'
- || this.parent.editDialogFields[0].type === 'Dependency') {
- this.firstOccuringTab = this.parent.editDialogFields[0].type;
- }
+ if (this.isFromAddDialog && this.parent.addDialogFields && this.parent.addDialogFields.length > 0) {
+ const firstFieldType = this.parent.addDialogFields[0].type;
+ if (firstFieldType === 'Resources' || firstFieldType === 'Dependency') {
+ this.firstOccuringTab = firstFieldType;
}
- if (this.parent.editDialogFields.length == 1) {
- this.firstOccuringTab = this.parent.editDialogFields[0].type;
+ } else if (this.isFromEditDialog && this.parent.editDialogFields && this.parent.editDialogFields.length > 0) {
+ const firstFieldType = this.parent.editDialogFields[0].type;
+ if (firstFieldType === 'Resources' || firstFieldType === 'Dependency') {
+ this.firstOccuringTab = firstFieldType;
}
}
- if (this.isFromEditDialog) {
- if (this.parent.editDialogFields.length > 1) {
- if (this.parent.editDialogFields[0].type == 'Custom') {
- isCustomTab = true
- }
- }
- }
- if (this.isFromAddDialog) {
- if (this.parent.addDialogFields.length > 1) {
- if (this.parent.addDialogFields[0].type == 'Custom') {
- isCustomTab = true
- }
- }
- }
- if (isCustomTab) {
- this.CustomformObj = (actionCompleteArgs as HTMLElement).querySelector('.e-edit-form-row');
- if (this.CustomformObj === null) {
- return;
- }
-
- let validationRulesArray: { [key: string]: { [rule: string]: any } } = {};
-
- for (let i: number = 0; i < this.customFieldColumn.length; i++) {
- const column = this.customFieldColumn[parseInt(i.toString(), 10)];
- if (!column.visible) {
- continue;
+ if (!this.CustomformObj || !this.formObj) {
+ const customFieldColumns = this.customFieldColumn;
+ const taskFieldColumns = this.taskFieldColumn;
+ if (!this.CustomformObj && customFieldColumns && customFieldColumns.length > 0) {
+ const validationRulesArray: { [key: string]: { [rule: string]: any } } = {};
+ for (let i:number = 0; i < customFieldColumns.length; i++) {
+ const customColumn = customFieldColumns[i as number]; // Rename the variable
+ if (customColumn.visible && customColumn.validationRules) {
+ validationRulesArray[customColumn.field] = customColumn.validationRules;
+ }
}
- if (column.validationRules) {
- validationRulesArray[column.field] = column.validationRules;
+ if (Object.keys(validationRulesArray).length > 0) {
+ this.CustomformObj = actionCompleteArgs.querySelector('#'+this.parent.element.id+'Custom0TabContainer') as HTMLElement;
+ if (this.CustomformObj) {
+ this.CustomformObj = this.createFormObj(this.CustomformObj, validationRulesArray);
+ }
}
}
-
- if (Object.keys(validationRulesArray).length > 0) {
- this.CustomformObj = this.createFormObj(this.CustomformObj, validationRulesArray);
- }
- } else {
- this.formObj = (actionCompleteArgs as HTMLElement).querySelector('.e-edit-form-row');
- if (this.formObj === null) {
- return;
- }
-
- let validationRulesArray: { [key: string]: { [rule: string]: any } } = {};
-
- for (let i: number = 0; i < this.taskFieldColumn.length; i++) {
- const column = this.taskFieldColumn[parseInt(i.toString(), 10)];
- if (!column.visible) {
- continue;
+ if (!this.formObj && taskFieldColumns && taskFieldColumns.length > 0) {
+ const validationRulesArray: { [key: string]: { [rule: string]: any } } = {};
+ for (let i:number = 0; i < taskFieldColumns.length; i++) {
+ const taskColumn = taskFieldColumns[i as number]; // Rename the variable
+ if (taskColumn.visible && taskColumn.validationRules) {
+ validationRulesArray[taskColumn.field] = taskColumn.validationRules;
+ }
}
- if (column.validationRules) {
- validationRulesArray[column.field] = column.validationRules;
+ if (Object.keys(validationRulesArray).length > 0) {
+ this.formObj = actionCompleteArgs.querySelector('#'+this.parent.element.id+'GeneralTabContainer') as HTMLElement;
+ if (this.formObj) {
+ this.formObj = this.createFormObj(this.formObj, validationRulesArray);
+ }
}
}
-
- if (Object.keys(validationRulesArray).length > 0) {
- this.formObj = this.createFormObj(this.formObj, validationRulesArray);
- }
- }
- if (this.isFromAddDialog == true || this.isFromEditDialog) {
- this.isAddingDialog = this.isFromAddDialog
- this.isEditingDialog = this.isFromEditDialog
}
this.isFromAddDialog = false;
this.isFromEditDialog = false;
@@ -976,44 +883,24 @@ export class DialogEdit {
return null;
}
- private isSingleCustomTab(): boolean {
- const dialogFields = this.isFromAddDialog
- ? this.parent.addDialogFields
- : this.parent.editDialogFields;
-
- return this.isFromAddDialog || this.isFromEditDialog
- ? dialogFields.length === 1 && dialogFields[0].type === 'Custom'
- : false;
- }
-
private validateColumn(storeColumn: any, taskfields: any, storeValidTab: any) {
- storeColumn.forEach((column: { field: any }) => {
- const field = column.field;
- let isValueMatching = false;
- const taskfieldValues: (string | number)[] = [];
- if (this.parent.customColumns.indexOf(field) === -1) {
- isValueMatching = true;
- }
- if (isValueMatching) {
- if ((this.isFromAddDialog || this.isFromEditDialog) && storeValidTab) {
- if (storeValidTab.some((obj: { fields: string }) => obj.fields.includes(column.field))) {
- this.taskFieldColumn.push(column);
- }
+ if (storeValidTab) {
+ storeValidTab.forEach((element: any) => {
+ const targetArray = element.type === "General" ? this.taskFieldColumn : this.customFieldColumn;
+ element.fields.forEach((field: any) => {
+ targetArray.push(this.parent.getColumnByField(field, storeColumn));
+ });
+ });
+ } else {
+ storeColumn.forEach((column: { field: any }) => {
+ if (column.field.includes(this.parent.customColumns)) {
+ this.customFieldColumn.push(column);
} else {
this.taskFieldColumn.push(column);
}
- } else {
- if ((this.isFromAddDialog || this.isFromEditDialog) && storeValidTab) {
- if (storeValidTab.some((obj: { fields: string }) => obj.fields.includes(column.field))) {
- this.customFieldColumn.push(column);
- }
- } else {
- this.customFieldColumn.push(column);
- }
- }
- });
+ });
+ }
}
-
private createFormObj(form: HTMLFormElement, rules: { [name: string]: { [rule: string]: Object } }): FormValidator {
return new FormValidator(form, {
rules: rules,
@@ -1234,11 +1121,9 @@ export class DialogEdit {
numeric.min = 0;
numeric.max = 100;
}
- if (taskSettings.work === column.field) {
- numeric.change = (args: CObject): void => {
- this.validateScheduleFields(args, column, ganttObj);
- };
- }
+ numeric.change = (args: CObject): void => {
+ this.validateScheduleFields(args, column, ganttObj);
+ };
fieldsModel[column.field] = numeric;
break;
}
@@ -1387,30 +1272,41 @@ export class DialogEdit {
let tempValue: string | Date | number;
const taskField: TaskFieldsModel = this.parent.taskFields;
if (col.editType === 'stringedit') {
- const textBox: TextBox = (dialog.querySelector('#' + ganttId + columnName)).ej2_instances[0];
- tempValue = !isNullOrUndefined(col.edit) && !isNullOrUndefined(col.edit.read) ? (col.edit.read as () => void)() :
- !isNullOrUndefined(col.valueAccessor) ? (col.valueAccessor as Function) (columnName, ganttObj.editModule.dialogModule.editedRecord, col) : // eslint-disable-line
- this.parent.dataOperation.getDurationString(ganttProp.duration, ganttProp.durationUnit);
- if (textBox.value !== tempValue.toString() && taskField.duration === columnName) {
- textBox.value = tempValue as string;
- textBox.dataBind();
- } else if (taskField.startDate === columnName || taskField.endDate === columnName) {
- textBox.value = taskField.startDate === columnName ? ganttProp.startDate.toString() : ganttProp.endDate.toString();
- textBox.dataBind();
+ const element = dialog.querySelector('#' + ganttId + columnName);
+ if (element) {
+ const textBox = (element).ej2_instances[0];
+ if (textBox) {
+ tempValue = !isNullOrUndefined(col.edit) && !isNullOrUndefined(col.edit.read) ? (col.edit.read as () => void)() :
+ !isNullOrUndefined(col.valueAccessor) ? (col.valueAccessor as Function)(columnName, ganttObj.editModule.dialogModule.editedRecord, col) :
+ this.parent.dataOperation.getDurationString(ganttProp.duration, ganttProp.durationUnit);
+ if (textBox.value !== tempValue.toString() && taskField.duration === columnName) {
+ textBox.value = tempValue as string;
+ textBox.dataBind();
+ } else if (taskField.startDate === columnName || taskField.endDate === columnName) {
+ textBox.value = taskField.startDate === columnName ? ganttProp.startDate.toString() : ganttProp.endDate.toString();
+ textBox.dataBind();
+ }
+ }
}
} else if (col.editType === 'datepickeredit' || col.editType === 'datetimepickeredit') {
- const picker: DatePicker = col.editType === 'datepickeredit' ?
- (dialog.querySelector('#' + ganttId + columnName)).ej2_instances[0] :
- (dialog.querySelector('#' + ganttId + columnName)).ej2_instances[0];
- tempValue = ganttProp[ganttField as string];
- if (((isNullOrUndefined(picker.value)) && !isNullOrUndefined(tempValue)) ||
- (isNullOrUndefined(tempValue) && !isNullOrUndefined(picker.value)) ||
- (picker.value !== tempValue && !isNullOrUndefined(picker.value) && !isNullOrUndefined(tempValue)
- && picker.value.toString() !== tempValue.toString())) {
- picker.value = tempValue as Date;
- picker.dataBind();
- }
- } else if (col.editType === 'numericedit') {
+ const element = dialog.querySelector('#' + ganttId + columnName);
+ if (element) {
+ const picker = col.editType === 'datepickeredit' ?
+ ((element).ej2_instances[0]) :
+ ((element).ej2_instances[0]);
+ if (picker) {
+ tempValue = ganttProp[ganttField as string];
+ if (((isNullOrUndefined(picker.value)) && !isNullOrUndefined(tempValue)) ||
+ (isNullOrUndefined(tempValue) && !isNullOrUndefined(picker.value)) ||
+ (picker.value !== tempValue && !isNullOrUndefined(picker.value) && !isNullOrUndefined(tempValue)
+ && picker.value.toString() !== tempValue.toString())) {
+ picker.value = tempValue as Date;
+ picker.dataBind();
+ }
+ }
+ }
+ }
+ else if (col.editType === 'numericedit') {
const numericTextBox: NumericTextBox = (
dialog.querySelector('#' + ganttId + columnName)).ej2_instances[0];
tempValue = ganttProp[ganttField as string];
@@ -2755,7 +2651,12 @@ export class DialogEdit {
inputModel.checked = false;
}
} else {
- inputModel.value = ganttData[column.field];
+ if (!this.parent.taskFields[column.field] && column.editType == 'numericedit' && (ganttData[column.field] === "" || ganttData[column.field] === 0)) {
+ inputModel.value = 0;
+ }
+ else {
+ inputModel.value = ganttData[column.field];
+ }
}
}
if (!isNullOrUndefined(column.edit) && isNullOrUndefined(column.edit.params)) {
@@ -3003,6 +2904,7 @@ export class DialogEdit {
/**
* If any update on edited task do it here
*/
+ this.parent.editModule['editedRecord'] = this.rowData;
this.parent.dataOperation.updateWidthLeft(this.rowData);
const editArgs: ITaskbarEditedEventArgs = {
data: this.rowData,
@@ -3010,6 +2912,7 @@ export class DialogEdit {
};
this.parent.editModule.initiateUpdateAction(editArgs);
} else {
+ this.parent.editModule['editedRecord'] = this.addedRecord;
if (this.parent.viewType === 'ResourceView') {
const newRecords: Object = extend({}, this.addedRecord, true);
if (newRecords[this.parent.taskFields.resourceInfo].length) {
@@ -3084,15 +2987,10 @@ export class DialogEdit {
controlObj.value = valueString;
}
const column: GanttColumnModel = ganttObj.columnByField[fieldName as string];
- if (fieldName == this.parent.taskFields.duration) {
- if (parseInt(this.rowData[fieldName as string]) != parseInt(controlObj.value as string)) {
- this.disableUndo = true;
- }
- }
- else {
- if (this.rowData[fieldName as string] != controlObj.value) {
- this.disableUndo = true;
- }
+ if (fieldName === this.parent.taskFields.duration ?
+ parseInt(this.rowData[fieldName as string]) !== parseInt(controlObj.value as string) :
+ this.rowData[fieldName as string] !== controlObj.value) {
+ this.disableUndo = true;
}
if (!isNullOrUndefined(column.edit) && isNullOrUndefined(column.edit.params)) {
let read: Function = column.edit.read as Function;
diff --git a/controls/gantt/src/gantt/actions/edit.ts b/controls/gantt/src/gantt/actions/edit.ts
index 5c3095fd2f..f5b1dca529 100644
--- a/controls/gantt/src/gantt/actions/edit.ts
+++ b/controls/gantt/src/gantt/actions/edit.ts
@@ -66,6 +66,7 @@ export class Edit {
public taskbarEditModule: TaskbarEdit;
public dialogModule: DialogEdit;
public isResourceTaskDeleted: boolean = false;
+ private editedRecord: IGanttData;
constructor(parent?: Gantt) {
this.parent = parent;
this.parent.predecessorModule.validatedChildItems = [];
@@ -932,6 +933,7 @@ export class Edit {
*/
public updateEditedTask(args: ITaskbarEditedEventArgs): void {
const ganttRecord: IGanttData = args.data;
+ this.editedRecord = ganttRecord;
if (this.parent.autoCalculateDateScheduling) {
this.updateParentChildRecord(ganttRecord);
}
@@ -941,6 +943,9 @@ export class Edit {
const child: IGanttData = this.parent.predecessorModule.validatedChildItems[i as number];
if (child.ganttProperties.predecessor && child.ganttProperties.predecessor.length > 0) {
this.parent.editedTaskBarItem = child;
+ if (!this.isValidatedEditedRecord) {
+ this.isFirstCall = true;
+ }
this.parent.predecessorModule.validatePredecessor(child, [], '');
}
}
@@ -956,12 +961,12 @@ export class Edit {
this.parent.predecessorModule.validatePredecessor(ganttRecord, [], '');
}
this.isValidatedEditedRecord = false;
- this.parent.predecessorModule.isValidatedParentTaskID = '';
}
- if (this.parent.allowParentDependency && ganttRecord.hasChildRecords && this.parent.previousRecords[ganttRecord.uniqueID].ganttProperties.startDate &&
+ if (this.parent.allowParentDependency && this.parent.predecessorModule.isValidatedParentTaskID != ganttRecord.ganttProperties.taskId && ganttRecord.hasChildRecords && this.parent.previousRecords[ganttRecord.uniqueID].ganttProperties.startDate &&
(args.action === "DrawConnectorLine")) {
this.parent.predecessorModule['updateChildItems'](ganttRecord);
}
+ this.parent.predecessorModule.isValidatedParentTaskID = '';
if(this.parent.undoRedoModule && this.parent.undoRedoModule['isUndoRedoPerformed']) {
for (let i: number = 0; i < ganttRecord.childRecords.length; i++) {
if (ganttRecord.childRecords[i as number].ganttProperties.predecessor) {
@@ -1683,20 +1688,10 @@ export class Edit {
for (let j: number = 0; j < this.dialogModule['indexes'].deletedIndexes.length; j++) {
if (this.dialogModule['indexes'].deletedIndexes[j as number].data.parentUniqueID == draggedRecord.parentUniqueID && draggedRecord.ganttProperties.taskId == this.dialogModule['indexes'].deletedIndexes[j as number].data.ganttProperties.taskId) {
let toIndex: number = this.dialogModule['indexes'].deletedIndexes[j as number].index;
- if (this.dialogModule['indexes'].deletedIndexes[j as number].position == 'above') {
- childRecordsLength = toIndex;
- }
- else {
- childRecordsLength = toIndex + 1;
- }
+ this.dialogModule['indexes'].deletedIndexes[j as number].position == 'above' ? (childRecordsLength = toIndex) : (childRecordsLength = toIndex + 1);
for (let i: number = 0; i < droppedRecord.childRecords.length; i++) {
if ('T' + droppedRecord.childRecords[i as number].ganttProperties.taskId == this.dialogModule['indexes'].deletedIndexes[j as number].id) {
- if (this.dialogModule['indexes'].deletedIndexes[j as number].position == 'above') {
- spliceIndex = i;
- }
- else {
- spliceIndex = i + 1;
- }
+ this.dialogModule['indexes'].deletedIndexes[j as number].position == 'above' ? (spliceIndex = i) : spliceIndex = i + 1;
break;
}
}
@@ -2305,7 +2300,9 @@ export class Edit {
if (isRemoteData(this.parent.dataSource)) {
const data: DataManager = this.parent.dataSource as DataManager;
if (this.parent.timezone) {
- updateDates(eventArg.modifiedTaskData as IGanttData, this.parent);
+ (eventArg.modifiedRecords as IGanttData[]).forEach((modifiedRecord: IGanttData) => {
+ updateDates(modifiedRecord, this.parent);
+ });
}
const updatedData: object = {
deletedRecords: getTaskData(eventArg.data as IGanttData[], null, null, this.parent), // to check
@@ -3948,7 +3945,7 @@ export class Edit {
const fromRecord: IGanttData = this.parent.getRecordByID(droppedRec.ganttProperties.predecessor[count as number].from);
const toRecord: IGanttData = this.parent.getRecordByID(droppedRec.ganttProperties.predecessor[count as number].to);
const validPredecessor: boolean = this.parent.connectorLineEditModule.validateParentPredecessor(fromRecord, toRecord);
- if (droppedRec.ganttProperties.predecessor && !validPredecessor) {
+ if (droppedRec.ganttProperties.predecessor && (!validPredecessor || !this.parent.allowParentDependency)) {
this.parent.editModule.removePredecessorOnDelete(droppedRec);
droppedRec.ganttProperties.predecessor.splice(count, 1);
droppedRec.ganttProperties.predecessorsName = null;
diff --git a/controls/gantt/src/gantt/actions/rowdragdrop.ts b/controls/gantt/src/gantt/actions/rowdragdrop.ts
index 238de6e285..1723eae77b 100644
--- a/controls/gantt/src/gantt/actions/rowdragdrop.ts
+++ b/controls/gantt/src/gantt/actions/rowdragdrop.ts
@@ -386,7 +386,7 @@ export class RowDD {
const fromRecord: IGanttData = this.parent.getRecordByID(droppedRecord.ganttProperties.predecessor[count as number].from);
const toRecord: IGanttData = this.parent.getRecordByID(droppedRecord.ganttProperties.predecessor[count as number].to)
const validPredecessor: boolean = this.parent.connectorLineEditModule.validateParentPredecessor(fromRecord, toRecord);
- if (droppedRecord.ganttProperties.predecessor && !validPredecessor) {
+ if (droppedRecord.ganttProperties.predecessor && (!validPredecessor || !this.parent.allowParentDependency)) {
this.parent.editModule.removePredecessorOnDelete(droppedRecord);
droppedRecord.ganttProperties.predecessor.splice(0, 1);
if (droppedRecord.ganttProperties.predecessorsName) {
@@ -733,6 +733,7 @@ export class RowDD {
this.parent.setRecordValue('level' , this.draggedRecord.level , this.draggedRecord);
this.updateChildRecordLevel(draggedRecord, level);
}
+ droppedRecord.expanded = true;
}
}
private deleteDragRow(): void {
diff --git a/controls/gantt/src/gantt/actions/undo-redo.ts b/controls/gantt/src/gantt/actions/undo-redo.ts
index 0fe22de1de..56d0bce4ce 100644
--- a/controls/gantt/src/gantt/actions/undo-redo.ts
+++ b/controls/gantt/src/gantt/actions/undo-redo.ts
@@ -271,7 +271,7 @@ export class UndoRedo {
}
}
else if (updateAction['action'] === 'Add') {
- const isShowDeleteConfirmDialog: boolean = extend([], this.parent.editSettings.showDeleteConfirmDialog, [], true)[0];
+ const isShowDeleteConfirmDialog: boolean = extend([], [this.parent.editSettings.showDeleteConfirmDialog], [], true)[0];
this.parent.editSettings.showDeleteConfirmDialog = false;
let deleteRec: IGanttData = updateAction['addedRecords'];
if (this.parent.viewType === 'ResourceView' && updateAction['addedRecords'].length == 1 && (updateAction['addedRecords'][0] as IGanttData).parentItem) {
@@ -534,7 +534,7 @@ export class UndoRedo {
}
}
}
- const isShowDeleteConfirmDialog: boolean = extend([], this.parent.editSettings.showDeleteConfirmDialog, [], true)[0];
+ const isShowDeleteConfirmDialog: boolean = extend([], [this.parent.editSettings.showDeleteConfirmDialog], [], true)[0];
this.parent.editSettings.showDeleteConfirmDialog = false;
this.parent.deleteRecord(updateAction['deleteRecords']);
this.parent.editSettings.showDeleteConfirmDialog = isShowDeleteConfirmDialog;
diff --git a/controls/gantt/src/gantt/base/date-processor.ts b/controls/gantt/src/gantt/base/date-processor.ts
index 4f843560e5..611d24f493 100644
--- a/controls/gantt/src/gantt/base/date-processor.ts
+++ b/controls/gantt/src/gantt/base/date-processor.ts
@@ -114,7 +114,13 @@ export class DateProcessor {
if (hour > this.parent.defaultEndTime) {
this.setTime(this.parent.defaultEndTime, cloneEndDate);
} else if (hour <= this.parent.defaultStartTime && !validateAsMilestone) {
- cloneEndDate.setDate(cloneEndDate.getDate() - 1);
+ let taskfields = this.parent.taskFields;
+ if(this.parent.editModule && this.parent.editModule['editedRecord'] && (!this.parent.editModule['editedRecord'][taskfields.startDate] && this.parent.editModule['editedRecord'][taskfields.endDate])) {
+ cloneEndDate.setDate(cloneEndDate.getDate());
+ }
+ else {
+ cloneEndDate.setDate(cloneEndDate.getDate() - 1);
+ }
this.setTime(this.parent.defaultEndTime, cloneEndDate);
} else if (hour > this.parent.defaultStartTime && hour < this.parent.defaultEndTime) {
for (let index: number = 0; index < this.parent.workingTimeRanges.length; index++) {
diff --git a/controls/gantt/src/gantt/base/gantt-chart.ts b/controls/gantt/src/gantt/base/gantt-chart.ts
index 9bc34a7553..27c60df8e0 100644
--- a/controls/gantt/src/gantt/base/gantt-chart.ts
+++ b/controls/gantt/src/gantt/base/gantt-chart.ts
@@ -330,8 +330,15 @@ export class GanttChart {
const wrapper1: HTMLElement = getValue('wrapper', this.parent.ganttChartModule.virtualRender);
const treegridVirtualHeight: string = (this.parent.treeGrid.element.getElementsByClassName('e-virtualtable')[0] as HTMLElement).style.transform;
const virtualTable: string = (document.getElementsByClassName('e-virtualtable')[1] as HTMLElement).style.transform;
- if (this.parent.enableTimelineVirtualization && virtualTable !== "") {
- const translateXValue: string = virtualTable.match(/translate.*\((.+)\)/)[1].split(', ')[0];
+ if (this.parent.enableTimelineVirtualization) {
+ let translateXValue: string;
+ if (virtualTable !== "") {
+ translateXValue = virtualTable.match(/translate.*\((.+)\)/)[1].split(', ')[0];
+ }
+ else {
+ const chartTransform: string = (this.parent.ganttChartModule.scrollElement.getElementsByClassName('e-virtualtable')[0] as HTMLElement).style.transform;
+ translateXValue = chartTransform.match(/translate.*\((.+)\)/)[1].split(', ')[0];
+ }
const translateYValue: string = treegridVirtualHeight.match(/translate.*\((.+)\)/)[1].split(', ')[1];
wrapper1.style.transform = `translate(${translateXValue}, ${translateYValue})`;
}
diff --git a/controls/gantt/src/gantt/base/gantt-model.d.ts b/controls/gantt/src/gantt/base/gantt-model.d.ts
index c2c077c3fe..dd29e47563 100644
--- a/controls/gantt/src/gantt/base/gantt-model.d.ts
+++ b/controls/gantt/src/gantt/base/gantt-model.d.ts
@@ -129,7 +129,7 @@ export interface GanttModel extends ComponentModel{
/**
* `undoRedoActions` Defines action items that retain for undo and redo operation.
*
- * @default null
+ * @default ['Sorting','Add','ColumnReorder','ColumnResize','ColumnState','Delete','Edit','Filtering','Indent','Outdent','NextTimeSpan','PreviousTimeSpan','RowDragAndDrop','Search']
*/
undoRedoActions?: GanttAction[];
diff --git a/controls/gantt/src/gantt/base/gantt.ts b/controls/gantt/src/gantt/base/gantt.ts
index 90fe5d32be..63b2b05de1 100644
--- a/controls/gantt/src/gantt/base/gantt.ts
+++ b/controls/gantt/src/gantt/base/gantt.ts
@@ -453,9 +453,9 @@ export class Gantt extends Component
/**
* `undoRedoActions` Defines action items that retain for undo and redo operation.
*
- * @default null
+ * @default ['Sorting','Add','ColumnReorder','ColumnResize','ColumnState','Delete','Edit','Filtering','Indent','Outdent','NextTimeSpan','PreviousTimeSpan','RowDragAndDrop','Search']
*/
- @Property()
+ @Property(['Sorting','Add','ColumnReorder','ColumnResize','ColumnState','Delete','Edit','Filtering','Indent','Outdent','NextTimeSpan','PreviousTimeSpan','RowDragAndDrop','Search'])
public undoRedoActions: GanttAction[];
/**
@@ -2574,7 +2574,7 @@ export class Gantt extends Component
},
{
topTier: { unit: 'Week', format: 'MMM dd, yyyy', count: 1 },
- bottomTier: { unit: 'Day', format: null, count: 1 }, timelineUnitSize: 33, level: 11,
+ bottomTier: { unit: 'Day', format: 'd', count: 1 }, timelineUnitSize: 33, level: 11,
timelineViewMode: 'Week', weekStartDay: _WeekStartDay, updateTimescaleView: true, weekendBackground: null, showTooltip: true
},
{
@@ -3587,7 +3587,7 @@ export class Gantt extends Component
zoomToFit: 'Zoom to fit',
excelExport: 'Excel export',
csvExport: 'CSV export',
- pdfExport: 'Pdf export',
+ pdfExport: 'PDF export',
expandAll: 'Expand all',
collapseAll: 'Collapse all',
nextTimeSpan: 'Next timespan',
diff --git a/controls/gantt/src/gantt/base/task-processor.ts b/controls/gantt/src/gantt/base/task-processor.ts
index bc4971e1d0..e4af6f61ee 100644
--- a/controls/gantt/src/gantt/base/task-processor.ts
+++ b/controls/gantt/src/gantt/base/task-processor.ts
@@ -161,8 +161,9 @@ export class TaskProcessor extends DateProcessor {
this.constructResourceViewDataSource(resources, hierarchicalData, unassignedTasks);
if (unassignedTasks.length > 0) {
const record: Object = {};
+ let resourceName: string = this.parent.resourceFields.name || 'resourceName';
record[this.parent.resourceFields.id] = 0;
- record[this.parent.resourceFields.name] = this.parent.localeObj.getConstant('unassignedTask');
+ record[resourceName as string] = this.parent.localeObj.getConstant('unassignedTask');
record[this.parent.taskFields.child] = unassignedTasks;
resources.push(record);
}
@@ -385,7 +386,12 @@ export class TaskProcessor extends DateProcessor {
}
} else if (!isNullOrUndefined(data[resourceFields.id])) {
id = data[resourceFields.id];
- name = data[resourceFields.name];
+ if (isNullOrUndefined(data[resourceFields.name]) && data['resourceName'] === "Unassigned Task"){
+ name = data['resourceName'];
+ }
+ else{
+ name = data[resourceFields.name];
+ }
this.addTaskData(ganttData, data, false);
}
this.parent.setRecordValue('taskId', id, ganttProperties, true);
@@ -697,7 +703,7 @@ export class TaskProcessor extends DateProcessor {
public updateWorkWithDuration(ganttData: IGanttData): void {
const resources: Object[] = ganttData.ganttProperties.resourceInfo;
let work: number = 0;
- if (!isNullOrUndefined(resources)) {
+ if (!isNullOrUndefined(resources) && !ganttData.hasChildRecords) {
const resourcesLength: number = resources.length;
let index: number;
let resourceUnit: number;
@@ -1342,11 +1348,11 @@ export class TaskProcessor extends DateProcessor {
this.parent.ganttChartModule.scrollObject['isSetScrollLeft'])) && !isFromTimelineVirtulization) {
isValid = false;
}
- if (!this.parent.editModule && this.parent.enableTimelineVirtualization && isValid && !this.parent.timelineModule['performedTimeSpanAction']) {
+ if (this.parent.enableTimelineVirtualization && isValid && !this.parent.timelineModule['performedTimeSpanAction']) {
leftValueForStartDate = (this.parent.enableTimelineVirtualization && this.parent.ganttChartModule.scrollObject.element.scrollLeft != 0)
? this.parent.ganttChartModule.scrollObject.getTimelineLeft() : null;
}
- const timelineStartDate: Date = (this.parent.editModule && this.parent.enableTimelineVirtualization && !isNullOrUndefined(leftValueForStartDate))
+ const timelineStartDate: Date = (this.parent.enableTimelineVirtualization && !isNullOrUndefined(leftValueForStartDate))
? new Date((this.parent.timelineModule['dateByLeftValue'](leftValueForStartDate)).toString()) : new Date(this.parent.timelineModule.timelineStartDate);
if (timelineStartDate) {
let leftValue: number = (date.getTime() - timelineStartDate.getTime()) / (1000 * 60 * 60 * 24) * this.parent.perDayWidth;
diff --git a/controls/gantt/src/gantt/base/utils.ts b/controls/gantt/src/gantt/base/utils.ts
index 76e9f9a405..56beadf418 100644
--- a/controls/gantt/src/gantt/base/utils.ts
+++ b/controls/gantt/src/gantt/base/utils.ts
@@ -126,18 +126,20 @@ export function getTaskData(
*/
export function updateDates(record: IGanttData, parent: Gantt): void {
// let startDate: Date = (record as IGanttData).taskData[parent.taskFields.startDate];
- (record as IGanttData).taskData[parent.taskFields.startDate] = parent.dateValidationModule.remove(
- (record as IGanttData).ganttProperties.startDate, parent.timezone);
- if (parent.taskFields.endDate != null) {
- (record as IGanttData).taskData[parent.taskFields.endDate] = parent.dateValidationModule.remove(
- (record as IGanttData).ganttProperties.endDate, parent.timezone);
- }
- if (parent.taskFields.baselineEndDate || parent.taskFields.baselineStartDate) {
- (record as IGanttData).taskData[parent.taskFields.baselineStartDate] = parent.dateValidationModule.remove(
- (record as IGanttData).ganttProperties.baselineStartDate, parent.timezone);
+ if (record && !isNullOrUndefined((record as IGanttData).ganttProperties)) {
+ (record as IGanttData).taskData[parent.taskFields.startDate] = parent.dateValidationModule.remove(
+ (record as IGanttData).ganttProperties.startDate, parent.timezone);
+ if (parent.taskFields.endDate != null) {
+ (record as IGanttData).taskData[parent.taskFields.endDate] = parent.dateValidationModule.remove(
+ (record as IGanttData).ganttProperties.endDate, parent.timezone);
+ }
+ if (parent.taskFields.baselineEndDate || parent.taskFields.baselineStartDate) {
+ (record as IGanttData).taskData[parent.taskFields.baselineStartDate] = parent.dateValidationModule.remove(
+ (record as IGanttData).ganttProperties.baselineStartDate, parent.timezone);
- (record as IGanttData).taskData[parent.taskFields.baselineEndDate] = parent.dateValidationModule.remove(
- (record as IGanttData).ganttProperties.baselineEndDate, parent.timezone);
+ (record as IGanttData).taskData[parent.taskFields.baselineEndDate] = parent.dateValidationModule.remove(
+ (record as IGanttData).ganttProperties.baselineEndDate, parent.timezone);
+ }
}
return null;
}
diff --git a/controls/gantt/src/gantt/export/pdf-taskbar.ts b/controls/gantt/src/gantt/export/pdf-taskbar.ts
index ed6d2418af..6029dda775 100644
--- a/controls/gantt/src/gantt/export/pdf-taskbar.ts
+++ b/controls/gantt/src/gantt/export/pdf-taskbar.ts
@@ -107,7 +107,6 @@ export class PdfGanttTaskbarCollection {
public indicators: IIndicator[];
public labelSettings: ILabel;
public taskbarTemplate : ITemplateDetails;
- public rightLabelBoundsTemplates: number;
public previousWidthofLeftValue: number;
public previousWidthofLeftImage: number;
public totalLeftWidth: number;
@@ -187,29 +186,19 @@ export class PdfGanttTaskbarCollection {
let font: PdfFont = new PdfStandardFont(this.fontFamily, 9, PdfFontStyle.Regular);
const fontColor: PdfPen = null;
const fontBrush: PdfBrush = new PdfSolidBrush(this.progressFontColor);
- let customizedFont : PdfFont;
- let customizedFontBrush : PdfBrush;
- let customizedFontColor : PdfPen;
- if(!isNullOrUndefined(taskbar.taskbarTemplate.value)){
- if(taskbar.taskbarTemplate.fontStyle.fontFamily && taskbar.taskbarTemplate.fontStyle.fontSize){
- customizedFont = new PdfStandardFont(taskbar.taskbarTemplate.fontStyle.fontFamily,taskbar.taskbarTemplate.fontStyle.fontSize,taskbar.taskbarTemplate.fontStyle.fontStyle);
- }else{
- customizedFont = font;
- }
- if(taskbar.taskbarTemplate.fontStyle.fontColor){
- customizedFontBrush = new PdfSolidBrush(taskbar.taskbarTemplate.fontStyle.fontColor);
- }
- else{
- customizedFontBrush = fontBrush;
- }
- if(taskbar.taskbarTemplate.fontStyle.fontBrush){
- customizedFontColor = new PdfPen(taskbar.taskbarTemplate.fontStyle.fontBrush);
- }
- else{
- customizedFontColor = fontColor;
- }
- }
- if (!isNullOrUndefined(this.parent.pdfExportModule['helper']['exportProps'].ganttStyle) &&
+ let customizedFont: PdfFont;
+ let customizedFontBrush: PdfBrush;
+ let customizedFontColor: PdfPen;
+ customizedFont = !isNullOrUndefined(taskbar.taskbarTemplate.value) && taskbar.taskbarTemplate.fontStyle && taskbar.taskbarTemplate.fontStyle.fontFamily && taskbar.taskbarTemplate.fontStyle.fontSize
+ ? new PdfStandardFont(taskbar.taskbarTemplate.fontStyle.fontFamily, taskbar.taskbarTemplate.fontStyle.fontSize, taskbar.taskbarTemplate.fontStyle.fontStyle)
+ : font;
+ customizedFontBrush = !isNullOrUndefined(taskbar.taskbarTemplate.value) && taskbar.taskbarTemplate.fontStyle && taskbar.taskbarTemplate.fontStyle.fontColor
+ ? new PdfSolidBrush(taskbar.taskbarTemplate.fontStyle.fontColor)
+ : fontBrush;
+ customizedFontColor = !isNullOrUndefined(taskbar.taskbarTemplate.value) && taskbar.taskbarTemplate.fontStyle && taskbar.taskbarTemplate.fontStyle.fontBrush
+ ? new PdfPen(taskbar.taskbarTemplate.fontStyle.fontBrush)
+ : fontColor;
+ if (!isNullOrUndefined(this.parent.pdfExportModule['helper']['exportProps'].ganttStyle) &&
this.parent.pdfExportModule['helper']['exportProps'].ganttStyle.font) {
font = this.parent.pdfExportModule['helper']['exportProps'].ganttStyle.font;
}
diff --git a/controls/gantt/src/gantt/renderer/chart-rows.ts b/controls/gantt/src/gantt/renderer/chart-rows.ts
index 0a18f09474..b32889c343 100644
--- a/controls/gantt/src/gantt/renderer/chart-rows.ts
+++ b/controls/gantt/src/gantt/renderer/chart-rows.ts
@@ -39,6 +39,7 @@ export class ChartRows extends DateProcessor {
private refreshedTr: Element[] = [];
private refreshedData: IGanttData[] = [];
private isUpdated: boolean = true;
+ private taskBaselineTemplateNode: NodeList = null;
constructor(ganttObj?: Gantt) {
super(ganttObj);
this.parent = ganttObj;
@@ -1506,25 +1507,42 @@ export class ChartRows extends DateProcessor {
*/
public getGanttChartRow(i: number, tempTemplateData: IGanttData): Node {
this.templateData = tempTemplateData;
- let taskBaselineTemplateNode: NodeList = null;
const parentTrNode: NodeList = this.getTableTrNode(i);
const leftLabelNode: NodeList = this.getLeftLabelNode(i);
- const taskbarContainerNode: NodeList = this.taskbarContainer();
+ let taskbarContainerNode: NodeList | NodeList[] = this.taskbarContainer();
(taskbarContainerNode[0]).setAttribute('aria-label', this.generateAriaLabel(this.templateData));
(taskbarContainerNode[0]).setAttribute('rowUniqueId', this.templateData.ganttProperties.rowUniqueID);
let connectorLineLeftNode: NodeList;
- if (!this.templateData.hasChildRecords && !this.parent.allowParentDependency) {
- const connectorLineLeftNode: NodeList = this.getLeftPointNode();
+ let connectorLineRightNode: NodeList;
+ connectorLineLeftNode = this.getLeftPointNode();
+ if ((this.templateData.ganttProperties.isAutoSchedule && this.parent.viewType === 'ProjectView') || !this.templateData.hasChildRecords) {
taskbarContainerNode[0].appendChild([].slice.call(connectorLineLeftNode)[0]);
}
- else if (this.parent.allowParentDependency) {
- connectorLineLeftNode = this.getLeftPointNode();
- if ((this.templateData.ganttProperties.isAutoSchedule && this.parent.viewType === 'ProjectView') || !this.templateData.hasChildRecords) {
- taskbarContainerNode[0].appendChild([].slice.call(connectorLineLeftNode)[0]);
- }
- }
if (this.templateData.hasChildRecords) {
- const parentTaskbarTemplateNode: NodeList = this.getParentTaskbarNode(i, taskbarContainerNode);
+ let parentTaskbarTemplateNode: NodeList;
+ if (!this.parent.enableMultiTaskbar || (this.parent.enableMultiTaskbar && this.templateData.expanded)) {
+ parentTaskbarTemplateNode = this.getParentTaskbarNode(i, taskbarContainerNode);
+ }
+ else {
+ taskbarContainerNode = [];
+ for (let j: number = 0; j < this.templateData.childRecords.length; j++) {
+ this.templateData = this.templateData.childRecords[j as number];
+ let taskbarContainerNode1: NodeList | NodeList[] = this.taskbarContainer();
+ (taskbarContainerNode1[0]).setAttribute('aria-label', this.generateAriaLabel(this.templateData));
+ (taskbarContainerNode1[0]).setAttribute('rowUniqueId', this.templateData.ganttProperties.rowUniqueID);
+ if (!this.parent.allowParentDependency) {
+ connectorLineLeftNode = this.getLeftPointNode();
+ taskbarContainerNode1[0].appendChild([].slice.call(connectorLineLeftNode)[0]);
+ }
+ else {
+ connectorLineLeftNode = this.getLeftPointNode();
+ if ((this.templateData.ganttProperties.isAutoSchedule) || !this.templateData.hasChildRecords) {
+ taskbarContainerNode1[0].appendChild([].slice.call(connectorLineLeftNode)[0]);
+ }
+ }
+ this.appendChildTaskbars(tempTemplateData,i,taskbarContainerNode1,connectorLineRightNode,taskbarContainerNode);
+ }
+ }
if (!this.templateData.ganttProperties.isAutoSchedule) {
const manualTaskbar: NodeList = this.getManualTaskbar();
if (!isNullOrUndefined(manualTaskbar[0])) {
@@ -1533,130 +1551,68 @@ export class ChartRows extends DateProcessor {
const connectorLineRightNode: NodeList = this.getRightPointNode();
manualTaskbar[0].appendChild([].slice.call(connectorLineRightNode)[0]);
}
- taskbarContainerNode[0].appendChild([].slice.call(manualTaskbar)[0]);
+ (taskbarContainerNode[0] as any).appendChild([].slice.call(manualTaskbar)[0]);
}
}
if ((this.templateData.ganttProperties.autoDuration !== 0) && !this.templateData.ganttProperties.isMilestone && parentTaskbarTemplateNode && parentTaskbarTemplateNode.length > 0) {
append(parentTaskbarTemplateNode, taskbarContainerNode[0] as Element);
}
else if((this.templateData.ganttProperties.duration === 0 && this.templateData.ganttProperties.isMilestone && this.templateData.ganttProperties.isAutoSchedule)){
- const milestoneTemplateNode: NodeList = this.getMilestoneNode(i, taskbarContainerNode);
+ const milestoneTemplateNode: NodeList = this.getMilestoneNode(i, taskbarContainerNode as NodeList);
if (milestoneTemplateNode && milestoneTemplateNode.length > 0) {
append(milestoneTemplateNode, taskbarContainerNode[0] as Element);
}
}
if (this.parent.renderBaseline && this.templateData.ganttProperties.baselineStartDate &&
this.templateData.ganttProperties.baselineEndDate) {
- taskBaselineTemplateNode = ((this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.baselineEndDate.getTime()) || (
+ this.taskBaselineTemplateNode = ((this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.baselineEndDate.getTime()) || (
(!isNullOrUndefined(this.templateData.ganttProperties.baselineStartDate) && !isNullOrUndefined(this.templateData.ganttProperties.startDate) && (this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.startDate.getTime()))
&& (!isNullOrUndefined(this.templateData.ganttProperties.baselineEndDate) && !isNullOrUndefined(this.templateData.ganttProperties.endDate) && (this.templateData.ganttProperties.baselineEndDate.getTime() === this.templateData.ganttProperties.endDate.getTime())) &&
this.templateData.ganttProperties.isMilestone))
? this.getMilestoneBaselineNode() : this.getTaskBaselineNode();
}
- } else if (this.templateData.ganttProperties.isMilestone) {
- const milestoneTemplateNode: NodeList = this.getMilestoneNode(i, taskbarContainerNode);
- if (milestoneTemplateNode && milestoneTemplateNode.length > 0) {
- append(milestoneTemplateNode, taskbarContainerNode[0] as Element);
+ if (!this.parent.enableMultiTaskbar || (this.parent.enableMultiTaskbar && this.templateData.expanded)) {
+ if (this.parent.allowParentDependency && ((this.templateData.ganttProperties.isAutoSchedule && this.parent.viewType === 'ProjectView') || !this.templateData.hasChildRecords)) {
+ connectorLineRightNode = this.getRightPointNode();
+ (taskbarContainerNode[0] as any).appendChild([].slice.call(connectorLineRightNode)[0]);
}
- if (this.parent.renderBaseline && this.templateData.ganttProperties.baselineStartDate &&
- this.templateData.ganttProperties.baselineEndDate) {
- taskBaselineTemplateNode = ((this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.baselineEndDate.getTime()) || (
- (!isNullOrUndefined(this.templateData.ganttProperties.baselineStartDate) && !isNullOrUndefined(this.templateData.ganttProperties.startDate) && (this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.startDate.getTime()))
- && (!isNullOrUndefined(this.templateData.ganttProperties.baselineEndDate) && !isNullOrUndefined(this.templateData.ganttProperties.endDate) && (this.templateData.ganttProperties.baselineEndDate.getTime() === this.templateData.ganttProperties.endDate.getTime())) &&
- this.templateData.ganttProperties.isMilestone))
- ? this.getMilestoneBaselineNode() : this.getTaskBaselineNode();
+ else if (!this.parent.allowParentDependency) {
+ connectorLineRightNode = this.getRightPointNode();
+ (taskbarContainerNode[0] as any).appendChild([].slice.call(connectorLineRightNode)[0]);
}
- } else {
- const scheduledTask: Boolean = isScheduledTask(this.templateData.ganttProperties);// eslint-disable-line
- let childTaskbarProgressResizeNode: NodeList = null; let childTaskbarRightResizeNode: NodeList = null;
- let childTaskbarLeftResizeNode: NodeList = null;
- if (!isNullOrUndefined(scheduledTask)) {
- if (scheduledTask || this.templateData.ganttProperties.duration) {
- if (scheduledTask && (isNullOrUndefined(this.templateData.ganttProperties.segments)
- || this.templateData.ganttProperties.segments.length <= 0)) {
- childTaskbarProgressResizeNode = this.childTaskbarProgressResizer();
- childTaskbarLeftResizeNode = this.childTaskbarLeftResizer();
- childTaskbarRightResizeNode = this.childTaskbarRightResizer();
- }
- }
- const childTaskbarTemplateNode: NodeList = this.getChildTaskbarNode(i, taskbarContainerNode);
- if (childTaskbarLeftResizeNode) {
- taskbarContainerNode[0].appendChild([].slice.call(childTaskbarLeftResizeNode)[0]);
- }
- if (childTaskbarTemplateNode && childTaskbarTemplateNode.length > 0) {
- if (this.templateData.ganttProperties.segments && this.templateData.ganttProperties.segments.length > 0) {
- const length: number = this.templateData.ganttProperties.segments.length;
- const connector: string = ('');
- let segmentConnector: NodeList = null;
- segmentConnector = this.createDivElement(connector);
- taskbarContainerNode[0].appendChild([].slice.call(segmentConnector)[0]);
- for (let i: number = 0; i < length; i++) {
- append(childTaskbarTemplateNode, taskbarContainerNode[0] as Element);
- }
- } else {
- append(childTaskbarTemplateNode, taskbarContainerNode[0] as Element);
- }
- }
- if (childTaskbarProgressResizeNode) {
- taskbarContainerNode[0].appendChild([].slice.call(childTaskbarProgressResizeNode)[0]);
- }
- if (childTaskbarRightResizeNode) {
- taskbarContainerNode[0].appendChild([].slice.call(childTaskbarRightResizeNode)[0]);
- }
- }
- if (this.parent.renderBaseline && this.templateData.ganttProperties.baselineStartDate &&
- this.templateData.ganttProperties.baselineEndDate) {
- taskBaselineTemplateNode = ((this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.baselineEndDate.getTime()) || (
- (!isNullOrUndefined(this.templateData.ganttProperties.baselineStartDate) && !isNullOrUndefined(this.templateData.ganttProperties.startDate) && (this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.startDate.getTime()))
- && (!isNullOrUndefined(this.templateData.ganttProperties.baselineEndDate) && !isNullOrUndefined(this.templateData.ganttProperties.endDate) && (this.templateData.ganttProperties.baselineEndDate.getTime() === this.templateData.ganttProperties.endDate.getTime())) &&
- this.templateData.ganttProperties.isMilestone))
- ? this.getMilestoneBaselineNode() : this.getTaskBaselineNode();
- }
- }
- let connectorLineRightNode: NodeList;
- if (this.parent.allowParentDependency && ((this.templateData.ganttProperties.isAutoSchedule && this.parent.viewType === 'ProjectView') || !this.templateData.hasChildRecords)) {
- connectorLineRightNode = this.getRightPointNode();
- taskbarContainerNode[0].appendChild([].slice.call(connectorLineRightNode)[0]);
}
- else if (!this.parent.allowParentDependency) {
- connectorLineRightNode = this.getRightPointNode();
- taskbarContainerNode[0].appendChild([].slice.call(connectorLineRightNode)[0]);
+ } else {
+ this.appendChildTaskbars(tempTemplateData,i,taskbarContainerNode,connectorLineRightNode);
}
const rightLabelNode: NodeList = this.getRightLabelNode(i);
- parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(leftLabelNode)[0]);
- parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(taskbarContainerNode)[0]);
- if (this.templateData.ganttProperties.indicators && this.templateData.ganttProperties.indicators.length > 0) {
- let taskIndicatorNode: NodeList;
- let taskIndicatorTextFunction: Function;
- let taskIndicatorTextNode: NodeList;
- const indicators: IIndicator[] = this.templateData.ganttProperties.indicators;
- for (let indicatorIndex: number = 0; indicatorIndex < indicators.length; indicatorIndex++) {
- taskIndicatorNode = this.getIndicatorNode(indicators[indicatorIndex as number]);
- (taskIndicatorNode[0]).setAttribute('aria-label',indicators[indicatorIndex as number].name);
- if (indicators[indicatorIndex as number].name.indexOf('$') > -1 || indicators[indicatorIndex as number].name.indexOf('#') > -1) {
- taskIndicatorTextFunction = this.templateCompiler(indicators[indicatorIndex as number].name);
- taskIndicatorTextNode = taskIndicatorTextFunction(
- extend({ index: i }, this.templateData), this.parent, 'indicatorLabelText');
- } else {
- const text: HTMLElement = createElement('Text');
- text.innerHTML = indicators[indicatorIndex as number].name;
- if (this.parent.enableHtmlSanitizer && typeof (indicators[indicatorIndex as number].name) === 'string') {
- indicators[indicatorIndex as number].name = SanitizeHtmlHelper.sanitize(indicators[indicatorIndex as number].name);
- }
- taskIndicatorTextNode = text.childNodes;
- }
- taskIndicatorNode[0].appendChild([].slice.call(taskIndicatorTextNode)[0]);
- (taskIndicatorNode[0] as HTMLElement).title =
- !isNullOrUndefined(indicators[indicatorIndex as number].tooltip) ? indicators[indicatorIndex as number].tooltip : '';
- parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(taskIndicatorNode)[0]);
+ if (this.parent.enableMultiTaskbar && this.templateData.hasChildRecords && !this.templateData.expanded) {
+ const collapseParent: HTMLElement = createElement('div', {
+ className: 'e-collapse-parent'
+ });
+ parentTrNode[0].childNodes[0].childNodes[0].appendChild(collapseParent);
+ for (let j:number = 0; j < taskbarContainerNode.length; j++) {
+ addClass([taskbarContainerNode[j as number] as HTMLElement], 'collpse-parent-border');
+ parentTrNode[0].childNodes[0].childNodes[0].childNodes[0].appendChild([].slice.call(taskbarContainerNode)[j as number]);
+ }
+ parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(leftLabelNode)[0]);
+ if (this.templateData.ganttProperties.indicators && this.templateData.ganttProperties.indicators.length > 0) {
+ this.appendIndicators(i,parentTrNode);
}
}
- if (rightLabelNode && rightLabelNode.length > 0) {
- parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(rightLabelNode)[0]);
+ else {
+ parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(leftLabelNode)[0]);
+ parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(taskbarContainerNode)[0]);
+ if (this.templateData.ganttProperties.indicators && this.templateData.ganttProperties.indicators.length > 0) {
+ this.appendIndicators(i,parentTrNode);
+ }
+ if (rightLabelNode && rightLabelNode.length > 0) {
+ parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(rightLabelNode)[0]);
+ }
}
- if (!isNullOrUndefined(taskBaselineTemplateNode)) {
- parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(taskBaselineTemplateNode)[0]);
+ if (!isNullOrUndefined(this.taskBaselineTemplateNode)) {
+ parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(this.taskBaselineTemplateNode)[0]);
}
+ this.taskBaselineTemplateNode = null;
const tRow: Node = parentTrNode[0].childNodes[0];
this.setAriaRowIndex(tempTemplateData, tRow);
return tRow;
@@ -1717,6 +1673,112 @@ export class ChartRows extends DateProcessor {
}
}
}
+
+ private appendIndicators(i: number, parentTrNode: NodeList) {
+ let taskIndicatorNode: NodeList;
+ let taskIndicatorTextFunction: Function;
+ let taskIndicatorTextNode: NodeList;
+ const indicators: IIndicator[] = this.templateData.ganttProperties.indicators;
+ for (let indicatorIndex: number = 0; indicatorIndex < indicators.length; indicatorIndex++) {
+ taskIndicatorNode = this.getIndicatorNode(indicators[indicatorIndex as number]);
+ (taskIndicatorNode[0]).setAttribute('aria-label', indicators[indicatorIndex as number].name);
+ if (indicators[indicatorIndex as number].name.indexOf('$') > -1 || indicators[indicatorIndex as number].name.indexOf('#') > -1) {
+ taskIndicatorTextFunction = this.templateCompiler(indicators[indicatorIndex as number].name);
+ taskIndicatorTextNode = taskIndicatorTextFunction(
+ extend({ index: i }, this.templateData), this.parent, 'indicatorLabelText');
+ } else {
+ const text: HTMLElement = createElement('Text');
+ text.innerHTML = indicators[indicatorIndex as number].name;
+ if (this.parent.enableHtmlSanitizer && typeof (indicators[indicatorIndex as number].name) === 'string') {
+ indicators[indicatorIndex as number].name = SanitizeHtmlHelper.sanitize(indicators[indicatorIndex as number].name);
+ }
+ taskIndicatorTextNode = text.childNodes;
+ }
+ taskIndicatorNode[0].appendChild([].slice.call(taskIndicatorTextNode)[0]);
+ (taskIndicatorNode[0] as HTMLElement).title =
+ !isNullOrUndefined(indicators[indicatorIndex as number].tooltip) ? indicators[indicatorIndex as number].tooltip : '';
+ parentTrNode[0].childNodes[0].childNodes[0].appendChild([].slice.call(taskIndicatorNode)[0]);
+ }
+ }
+
+ private appendChildTaskbars(tempTemplateData: IGanttData, i: number, taskbarContainerNode: NodeList, connectorLineRightNode: NodeList, taskbarCollection?: NodeList | NodeList[]) {
+ if (this.templateData.ganttProperties.isMilestone) {
+ const milestoneTemplateNode: NodeList = this.getMilestoneNode(i, taskbarContainerNode);
+ if (milestoneTemplateNode && milestoneTemplateNode.length > 0) {
+ append(milestoneTemplateNode, taskbarContainerNode[0] as Element);
+ }
+ if (this.parent.renderBaseline && this.templateData.ganttProperties.baselineStartDate &&
+ this.templateData.ganttProperties.baselineEndDate) {
+ this.taskBaselineTemplateNode = ((this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.baselineEndDate.getTime()) || (
+ (!isNullOrUndefined(this.templateData.ganttProperties.baselineStartDate) && !isNullOrUndefined(this.templateData.ganttProperties.startDate) && (this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.startDate.getTime()))
+ && (!isNullOrUndefined(this.templateData.ganttProperties.baselineEndDate) && !isNullOrUndefined(this.templateData.ganttProperties.endDate) && (this.templateData.ganttProperties.baselineEndDate.getTime() === this.templateData.ganttProperties.endDate.getTime())) &&
+ this.templateData.ganttProperties.isMilestone))
+ ? this.getMilestoneBaselineNode() : this.getTaskBaselineNode();
+ }
+ if (taskbarCollection) {
+ (taskbarCollection as any).push(taskbarContainerNode[0]);
+ this.templateData = tempTemplateData;
+ }
+ } else {
+ const scheduledTask: Boolean = isScheduledTask(this.templateData.ganttProperties);// eslint-disable-line
+ let childTaskbarProgressResizeNode: NodeList = null; let childTaskbarRightResizeNode: NodeList = null;
+ let childTaskbarLeftResizeNode: NodeList = null;
+ if (!isNullOrUndefined(scheduledTask)) {
+ if (scheduledTask || this.templateData.ganttProperties.duration) {
+ if (scheduledTask && (isNullOrUndefined(this.templateData.ganttProperties.segments)
+ || this.templateData.ganttProperties.segments.length <= 0)) {
+ childTaskbarProgressResizeNode = this.childTaskbarProgressResizer();
+ childTaskbarLeftResizeNode = this.childTaskbarLeftResizer();
+ childTaskbarRightResizeNode = this.childTaskbarRightResizer();
+ }
+ }
+ const childTaskbarTemplateNode: NodeList = this.getChildTaskbarNode(i, taskbarContainerNode);
+ if (childTaskbarLeftResizeNode) {
+ taskbarContainerNode[0].appendChild([].slice.call(childTaskbarLeftResizeNode)[0]);
+ }
+ if (childTaskbarTemplateNode && childTaskbarTemplateNode.length > 0) {
+ if (this.templateData.ganttProperties.segments && this.templateData.ganttProperties.segments.length > 0) {
+ const length: number = this.templateData.ganttProperties.segments.length;
+ const connector: string = ('');
+ let segmentConnector: NodeList = null;
+ segmentConnector = this.createDivElement(connector);
+ taskbarContainerNode[0].appendChild([].slice.call(segmentConnector)[0]);
+ for (let i: number = 0; i < length; i++) {
+ append(childTaskbarTemplateNode, taskbarContainerNode[0] as Element);
+ }
+ } else {
+ append(childTaskbarTemplateNode, taskbarContainerNode[0] as Element);
+ }
+ }
+ if (childTaskbarProgressResizeNode) {
+ taskbarContainerNode[0].appendChild([].slice.call(childTaskbarProgressResizeNode)[0]);
+ }
+ if (childTaskbarRightResizeNode) {
+ taskbarContainerNode[0].appendChild([].slice.call(childTaskbarRightResizeNode)[0]);
+ }
+ }
+ if (this.parent.renderBaseline && this.templateData.ganttProperties.baselineStartDate &&
+ this.templateData.ganttProperties.baselineEndDate) {
+ this.taskBaselineTemplateNode = ((this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.baselineEndDate.getTime()) || (
+ (!isNullOrUndefined(this.templateData.ganttProperties.baselineStartDate) && !isNullOrUndefined(this.templateData.ganttProperties.startDate) && (this.templateData.ganttProperties.baselineStartDate.getTime() === this.templateData.ganttProperties.startDate.getTime()))
+ && (!isNullOrUndefined(this.templateData.ganttProperties.baselineEndDate) && !isNullOrUndefined(this.templateData.ganttProperties.endDate) && (this.templateData.ganttProperties.baselineEndDate.getTime() === this.templateData.ganttProperties.endDate.getTime())) &&
+ this.templateData.ganttProperties.isMilestone))
+ ? this.getMilestoneBaselineNode() : this.getTaskBaselineNode();
+ }
+ }
+ if (this.parent.allowParentDependency && ((this.templateData.ganttProperties.isAutoSchedule && this.parent.viewType === 'ProjectView') || !this.templateData.hasChildRecords)) {
+ connectorLineRightNode = this.getRightPointNode();
+ (taskbarContainerNode[0] as any).appendChild([].slice.call(connectorLineRightNode)[0]);
+ }
+ else if (!this.parent.allowParentDependency) {
+ connectorLineRightNode = this.getRightPointNode();
+ (taskbarContainerNode[0] as any).appendChild([].slice.call(connectorLineRightNode)[0]);
+ }
+ if (taskbarCollection) {
+ (taskbarCollection as any).push(taskbarContainerNode[0]);
+ this.templateData = tempTemplateData;
+ }
+ }
/**
*
* @param {Element} trElement .
@@ -2211,7 +2273,10 @@ export class ChartRows extends DateProcessor {
else {
index = this.parent.currentViewData.indexOf(items[i as number]);
}
- this.refreshRow(index, isValidateRange, isUndoRedo);
+ if (!this.parent.enableMultiTaskbar ||
+ (this.parent.enableMultiTaskbar && (items[i as number].expanded || !this.parent.isLoad))) {
+ this.refreshRow(index, isValidateRange, isUndoRedo);
+ }
}
this.parent.ganttChartModule.updateLastRowBottomWidth();
}
diff --git a/controls/gantt/src/gantt/renderer/timeline.ts b/controls/gantt/src/gantt/renderer/timeline.ts
index fbb30b463d..152a167b73 100644
--- a/controls/gantt/src/gantt/renderer/timeline.ts
+++ b/controls/gantt/src/gantt/renderer/timeline.ts
@@ -722,7 +722,7 @@ export class Timeline {
if (this.parent.enableTimelineVirtualization && (this.wholeTimelineWidth > this.parent.element.offsetWidth * 3)) {
for (let count: number = 0; count < loopCount; count++) {
table = createElement('table', { className: cls.timelineHeaderTableContainer, styles: 'display: block;' });
- table.setAttribute('role', 'presentation');
+ table.setAttribute('role', 'none');
thead = createElement('thead', { className: cls.timelineHeaderTableBody, styles: 'display:block; border-collapse:collapse' });
tr = createElement('tr', { innerHTML: this.createTimelineTemplate(tier) });
td = createElement('td');
@@ -752,7 +752,7 @@ export class Timeline {
else {
for (let count: number = 0; count < loopCount; count++) {
table = createElement('table', { className: cls.timelineHeaderTableContainer, styles: 'display: block;' });
- table.setAttribute('role', 'presentation');
+ table.setAttribute('role', 'none');
thead = createElement('thead', { className: cls.timelineHeaderTableBody, styles: 'display:block; border-collapse:collapse' });
tr = createElement('tr', { innerHTML: this.createTimelineTemplate(tier) });
td = createElement('td');
@@ -1462,7 +1462,7 @@ export class Timeline {
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), 1);
endDate = new Date(endDate.getFullYear(), endDate.getMonth() + 1, 0);
} else if (tierMode === 'Week') {
- const dayIndex: number = this.parent.timelineModule.customTimelineSettings.weekStartDay;
+ const dayIndex: number = !isNullOrUndefined(this.customTimelineSettings.weekStartDay) ? this.parent.timelineModule.customTimelineSettings.weekStartDay : 0;
const roundOffStartDate: number = startDate.getDay() < dayIndex ?
(startDate.getDate()) - (7 - dayIndex + startDate.getDay()) :
(startDate.getDate()) - startDate.getDay() + dayIndex;
@@ -1634,7 +1634,7 @@ export class Timeline {
} else {
minStartDate = this.timelineStartDate;
}
- if (!isNullOrUndefined(maxEndLeft) && (maxEndLeft >= (this.totalTimelineWidth - this.bottomTierCellWidth) ||
+ if (!isNullOrUndefined(maxEndLeft) && (maxEndLeft >= ((this.parent.enableTimelineVirtualization ? this.wholeTimelineWidth : this.totalTimelineWidth) - this.bottomTierCellWidth) ||
maxEndLeft >= validEndLeft)) {
isChanged = isChanged === 'prevTimeSpan' ? 'both' : 'nextTimeSpan';
maxEndDate = maxEndDate < this.timelineEndDate ? this.timelineEndDate : maxEndDate;
diff --git a/controls/gantt/src/gantt/renderer/virtual-content-render.ts b/controls/gantt/src/gantt/renderer/virtual-content-render.ts
index 14735f5226..4577c36b2e 100644
--- a/controls/gantt/src/gantt/renderer/virtual-content-render.ts
+++ b/controls/gantt/src/gantt/renderer/virtual-content-render.ts
@@ -45,6 +45,22 @@ export class VirtualContentRenderer {
*/
public adjustTable(): void {
const content: HTMLElement = this.parent.treeGrid.getContent().querySelector('.e-content').querySelector('.e-virtualtable');
- this.parent.ganttChartModule.virtualRender.wrapper.style.transform = content.style.transform;
+ if (this.parent.enableTimelineVirtualization) {
+ const virtualTable: string = (document.getElementsByClassName('e-virtualtable')[1] as HTMLElement).style.transform;
+ const treegridVirtualHeight: string = (this.parent.treeGrid.element.getElementsByClassName('e-virtualtable')[0] as HTMLElement).style.transform;
+ let translateXValue: string;
+ if (virtualTable !== "") {
+ translateXValue = virtualTable.match(/translate.*\((.+)\)/)[1].split(', ')[0];
+ }
+ else {
+ const chartTransform: string = (this.parent.ganttChartModule.scrollElement.getElementsByClassName('e-virtualtable')[0] as HTMLElement).style.transform;
+ translateXValue = chartTransform.match(/translate.*\((.+)\)/)[1].split(', ')[0];
+ }
+ const translateYValue: string = treegridVirtualHeight.match(/translate.*\((.+)\)/)[1].split(', ')[1];
+ this.parent.ganttChartModule.virtualRender.wrapper.style.transform = `translate(${translateXValue}, ${translateYValue})`;
+ }
+ else {
+ this.parent.ganttChartModule.virtualRender.wrapper.style.transform = content.style.transform;
+ }
}
}
diff --git a/controls/grids/CHANGELOG.md b/controls/grids/CHANGELOG.md
index 89e7d9b712..1ceb223125 100644
--- a/controls/grids/CHANGELOG.md
+++ b/controls/grids/CHANGELOG.md
@@ -2,6 +2,22 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### Grid
+
+#### Bug fixes
+
+- `#I565411` - Resolved the issue where the action complete event was not being triggered in the Infinite Scrolling.
+- `#I553471` - The issue of misleading text in Grid toolbar search when focus is lost has been resolved.
+- `#I562553` - The `getRows` method returning undefined for all the rows in the `rowTemplate` feature has been resolved.
+- `#I559289` - Resolved the issue where the validation message displayed immediately upon opening the dropdown instead of on focus out.
+- `#I558905` - The issue of white spaces being shown when the virtual scroll grid's height is set in pixels has been resolved.
+- `#I566680` - Resolved the Hierarchy grid export issue when the child grid's enable filter property is enabled.
+- `#I540683` - The issue of a script error being thrown when the last column contains auto width and `minWidth` in a Grid with `allowResizing` has been fixed.
+- `#I558576` - Resolved the issue where the sorting `popup` did not open when clicking the sort icon has been fixed.
+- `#FB51479` - The issue where the cell was automatically saved when opening the dropdown in Batch edit mode has been fixed.
+
## 25.1.35 (2024-03-15)
### Grid
diff --git a/controls/grids/package.json b/controls/grids/package.json
index 724a7a9013..0fbf1d6d97 100644
--- a/controls/grids/package.json
+++ b/controls/grids/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-grids",
- "version": "1.193.11",
+ "version": "25.1.35",
"description": "Feature-rich JavaScript datagrid (datatable) control with built-in support for editing, filtering, grouping, paging, sorting, and exporting to Excel.",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/grids/spec/grid/actions/batch.edit.spec.ts b/controls/grids/spec/grid/actions/batch.edit.spec.ts
index 209796a953..cd80540521 100644
--- a/controls/grids/spec/grid/actions/batch.edit.spec.ts
+++ b/controls/grids/spec/grid/actions/batch.edit.spec.ts
@@ -4647,6 +4647,44 @@ describe('EJ2-72030 - Batch Edited cell value not saved during tab out from last
gridObj = null;
});
});
+describe('EJ2-871057 - Add button is not getting focused on first click in Batch Editing Sample =>', () => {
+ let gridObj: Grid;
+ let batchAdd: (args: any) => void;
+ beforeAll((done: Function) => {
+ gridObj = createGrid(
+ {
+ dataSource: data.slice(0, 5),
+ editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Batch' },
+ allowPaging: true,
+ toolbar: ['Add', 'Delete', 'Update', 'Cancel'],
+ columns: [
+ { field: 'OrderID', isPrimaryKey: true, headerText: 'Order ID', textAlign: 'Right', validationRules: { required: true, number: true }, width: 120 },
+ { field: 'CustomerID', headerText: 'Customer ID', validationRules: { required: true }, width: 140 },
+ { field: 'Freight', headerText: 'Freight', textAlign: 'Right', editType: 'numericedit', width: 120, format: 'C2', validationRules: { required: true } },
+ ],
+ }, done);
+ });
+
+ it('Add record 1', (done: Function) => {
+ batchAdd = (args?: Object): void => {
+ expect(gridObj.element.querySelectorAll('.e-insertedrow').length).toBe(1);
+ gridObj.batchAdd = null;
+ done();
+ };
+ gridObj.batchAdd = batchAdd;
+ gridObj.addRecord();
+ });
+ it('Add record 2', (done: Function) => {
+ gridObj.addRecord();
+ expect(gridObj.element.querySelectorAll('.e-insertedrow').length).toBe(1);
+ done();
+ });
+
+ afterAll(() => {
+ destroy(gridObj);
+ gridObj = batchAdd = null;
+ });
+});
describe('EJ2-837195 - Inline and Batch Edit mode behave differently when column.allowEditing is false =>', () => {
let gridObj: Grid;
diff --git a/controls/grids/spec/grid/actions/infinite-scroll.spec.ts b/controls/grids/spec/grid/actions/infinite-scroll.spec.ts
index 84a17407e3..c05ca5fa80 100644
--- a/controls/grids/spec/grid/actions/infinite-scroll.spec.ts
+++ b/controls/grids/spec/grid/actions/infinite-scroll.spec.ts
@@ -288,15 +288,19 @@ describe('Infinite scroll cache mode compare with other features => ', () => {
it('Single sort orderID asc testing', (done: Function) => {
expect(gridObj.pageSettings.currentPage).not.toBe(1);
let actionComplete = (args: any): any => {
- expect(cols[0].querySelectorAll('.e-ascending').length).toBe(1);
- expect(sortSettings.columns[0].field).toBe('FIELD2');
- expect(sortSettings.columns[0].direction).toBe('Ascending');
- expect(gridObj.getContent().firstElementChild.scrollTop).toBe(0);
- expect(gridObj.pageSettings.currentPage).toBe(1);
- expect((gridObj.infiniteScrollModule as any).infiniteCache[4]).toBeUndefined();
- expect((gridObj.infiniteScrollModule as any).infiniteCache[3]).toBeDefined();
- expect(gridObj.getHeaderContent().querySelectorAll('.e-columnheader')[0].querySelectorAll('.e-sortnumber').length).toBe(0);
- done();
+ if (args.requestType === 'infiniteScroll') {
+ expect(gridObj.pageSettings.currentPage).toBe(4);
+ } else {
+ expect(cols[0].querySelectorAll('.e-ascending').length).toBe(1);
+ expect(sortSettings.columns[0].field).toBe('FIELD2');
+ expect(sortSettings.columns[0].direction).toBe('Ascending');
+ expect(gridObj.getContent().firstElementChild.scrollTop).toBe(0);
+ expect(gridObj.pageSettings.currentPage).toBe(1);
+ expect((gridObj.infiniteScrollModule as any).infiniteCache[4]).toBeUndefined();
+ expect((gridObj.infiniteScrollModule as any).infiniteCache[3]).toBeDefined();
+ expect(gridObj.getHeaderContent().querySelectorAll('.e-columnheader')[0].querySelectorAll('.e-sortnumber').length).toBe(0);
+ done();
+ }
};
let actionBegin = (args: any): any => {
expect(args.target).not.toBeNull();
diff --git a/controls/grids/spec/grid/actions/search.spec.ts b/controls/grids/spec/grid/actions/search.spec.ts
index 5ba3d23126..c4f054a573 100644
--- a/controls/grids/spec/grid/actions/search.spec.ts
+++ b/controls/grids/spec/grid/actions/search.spec.ts
@@ -468,6 +468,50 @@ describe('Search module=>', () => {
});
});
+ describe('EJ2-872387- Misleading Text in Grid Toolbar Search when Focus is Lost', () => {
+ let gridObj: Grid;
+ let actionBegin: (args?: Object) => void;
+ beforeAll((done: Function) => {
+ gridObj = createGrid(
+ {
+ dataSource: data.slice(0,5),
+ toolbar: ['Search'],
+ columns: [
+ {
+ field: 'OrderID',
+ headerText: 'OrderID',
+ width: 140,
+ },
+ {
+ field: 'CustomerID',
+ headerText: 'Customer Name',
+ width: 140,
+ },
+ ],
+ height: 350,
+ }, done);
+ });
+ it('search on focus out', (done: Function) => {
+ actionBegin = (args: any): void => {
+ if (args.requestType === 'searching') {
+ expect(args.searchString).toBe('vinet');
+ gridObj.actionBegin = null;
+ done();
+ }
+ };
+ gridObj.actionBegin = actionBegin;
+ let searchBar: HTMLInputElement = gridObj.element.querySelector('#' + gridObj.element.id + '_searchbar');
+ searchBar.focus();
+ searchBar.value = 'vinet';
+ gridObj.element.querySelector('th').click();
+ searchBar = null;
+ });
+ afterAll(() => {
+ destroy(gridObj);
+ gridObj = actionBegin = null;
+ });
+ });
+
describe('846444 - Searching value with Trailing Zero not working', () => {
let gridObj: Grid;
let actionComplete: () => void;
diff --git a/controls/grids/spec/grid/actions/virtualscroll.spec.ts b/controls/grids/spec/grid/actions/virtualscroll.spec.ts
index fe26975085..62dba703e3 100644
--- a/controls/grids/spec/grid/actions/virtualscroll.spec.ts
+++ b/controls/grids/spec/grid/actions/virtualscroll.spec.ts
@@ -1575,3 +1575,24 @@ describe('EJ2-859411-Scroll using the down arrow key by focusing the template, t
grid = dataBound = null;
});
});
+
+describe('EJ2-873384-When the Grid height is set in pixels, whitespaces are shown while scrolling up and down', () => {
+ let grid: Grid;
+ beforeAll((done: Function) => {
+ grid = createGrid(
+ {
+ dataSource: largeDataset.slice(0,60),
+ columns: [{ field: 'Field0', headerText: 'Field0', width: 120 }],
+ enableVirtualization: true,
+ height: '600px'
+ },done);
+ });
+ it('ensure pageSize', (done: Function) => {
+ expect(grid.pageSettings.pageSize).toBeGreaterThan(12);
+ done();
+ });
+ afterAll(() => {
+ destroy(grid);
+ grid = null;
+ });
+});
diff --git a/controls/grids/spec/grid/base/grid.spec.ts b/controls/grids/spec/grid/base/grid.spec.ts
index 6770528752..58e99e0766 100644
--- a/controls/grids/spec/grid/base/grid.spec.ts
+++ b/controls/grids/spec/grid/base/grid.spec.ts
@@ -2257,3 +2257,35 @@ describe('dateonly =>', () => {
gridObj = null;
});
});
+
+// used for code coverage
+describe('EJ2-871826: Error when using Stacked Header with Column Template and updating dataSource dynamically in React =>', () => {
+ let gridObj: Grid;
+ beforeAll((done: Function) => {
+ gridObj = createGrid(
+ {
+ dataSource: data.slice(0, 1),
+ columns: [
+ {
+ field: 'OrderID', isPrimaryKey: true, headerText: 'Order ID', width: 120
+ },
+ {headerText: 'Details', textAlign: 'Center', columns:[
+ {field: 'CustomerID', headerText: 'Customer ID', textAlign: 'Center', width: '80'},
+ {field: 'EmployeeID', headerText: 'Employee ID', textAlign: 'Center', width: '60'},
+ ]},
+ ],
+ }, done);
+ });
+ it('execute column setProperties method', (done: Function) => {
+ const col: Column = {headerText: 'Details', textAlign: 'Center', columns:[
+ {field: 'CustomerID', headerText: 'Customer ID', textAlign: 'Center', width: '80'},
+ {field: 'EmployeeID', headerText: 'Employee ID', textAlign: 'Center', width: '100'},
+ ]} as Column;
+ (gridObj.columns[1] as Column).setProperties(col);
+ done();
+ });
+ afterAll(() => {
+ destroy(gridObj);
+ gridObj = null;
+ });
+});
diff --git a/controls/grids/spec/grid/renderer/responsive-dialog-renderer.spec.ts b/controls/grids/spec/grid/renderer/responsive-dialog-renderer.spec.ts
index 3d2cd1c8e5..1478a85cd5 100644
--- a/controls/grids/spec/grid/renderer/responsive-dialog-renderer.spec.ts
+++ b/controls/grids/spec/grid/renderer/responsive-dialog-renderer.spec.ts
@@ -920,4 +920,38 @@ describe('Adaptive renderer', () => {
gridObj = null;
});
});
+
+ describe('EJ2-873156 - If Sort option is clicked on the mobile device, Filter Pop up is being Opened', () => {
+ let gridObj: any;
+ beforeAll((done: Function) => {
+ gridObj = createGrid(
+ {
+ dataSource: data,
+ enableAdaptiveUI: true,
+ rowRenderingMode: 'Vertical',
+ allowFiltering: true,
+ allowSorting: true,
+ allowPaging: true,
+ filterSettings: { type: 'Excel' },
+ height: 400,
+ columns: [
+ { headerText: 'OrderID', field: 'OrderID', isPrimaryKey: true, width: 120 },
+ { headerText: 'CustomerID', field: 'CustomerID', width: 120 },
+ { headerText: 'EmployeeID', field: 'EmployeeID', width: 120 },
+ { headerText: 'ShipCountry', field: 'ShipCountry', width: 120 },
+ { headerText: 'ShipCity', field: 'ShipCity', width: 120 },
+ ]
+ }, done);
+ });
+
+ it('Ensuring the sorting popup', () => {
+ (document.getElementsByClassName('e-tbar-btn')[1]as HTMLElement).click();
+ expect(document.getElementsByClassName('e-ressortdiv').length).toBe(1);
+ });
+
+ afterAll(() => {
+ destroy(gridObj);
+ gridObj = null;
+ });
+ });
});
\ No newline at end of file
diff --git a/controls/grids/src/grid/actions/batch-edit.ts b/controls/grids/src/grid/actions/batch-edit.ts
index 61291c987b..28bf1bd9f5 100644
--- a/controls/grids/src/grid/actions/batch-edit.ts
+++ b/controls/grids/src/grid/actions/batch-edit.ts
@@ -542,6 +542,9 @@ export class BatchEdit {
this.saveCell();
this.parent.notify(events.editNextValCell, {});
}
+ if (this.validateFormObj()) {
+ return;
+ }
if (this.initialRender) {
const visibleColumns: Column[] = gObj.getVisibleColumns();
for (let i: number = 0; i < visibleColumns.length; i++) {
diff --git a/controls/grids/src/grid/actions/data.ts b/controls/grids/src/grid/actions/data.ts
index d50e806f4d..0c7cb9454d 100644
--- a/controls/grids/src/grid/actions/data.ts
+++ b/controls/grids/src/grid/actions/data.ts
@@ -75,11 +75,8 @@ export class Data implements IDataProcessor {
gObj.setProperties({ query: new Query() }, true);
} else {
this.isQueryInvokedFromData = true;
- if (gObj.isVue) {
- gObj.setProperties({ query: gObj.query instanceof Query ? gObj.query : new Query() }, true);
- }
- else {
- gObj.query = gObj.query instanceof Query ? gObj.query : new Query();
+ if (!(gObj.query instanceof Query)) {
+ gObj.query = new Query();
}
}
}
diff --git a/controls/grids/src/grid/actions/excel-export.ts b/controls/grids/src/grid/actions/excel-export.ts
index 0d9cc8b963..f06e04ae7b 100644
--- a/controls/grids/src/grid/actions/excel-export.ts
+++ b/controls/grids/src/grid/actions/excel-export.ts
@@ -913,7 +913,7 @@ export class ExcelExport {
if (!isNullOrUndefined(cell.attributes.index)) {
columnsDetails = this.parent.getColumnByIndex(cell.attributes.index as number);
}
- if (cell.cellType === CellType.DetailFooterIntent || columnsDetails.type === 'checkbox') {
+ if (cell.cellType === CellType.DetailFooterIntent || columnsDetails.type === 'checkbox' || columnsDetails.commands) {
continue;
}
if ((cell.visible || this.includeHiddenColumn)) {
diff --git a/controls/grids/src/grid/actions/filter.ts b/controls/grids/src/grid/actions/filter.ts
index f09726e026..87d5c8e48f 100644
--- a/controls/grids/src/grid/actions/filter.ts
+++ b/controls/grids/src/grid/actions/filter.ts
@@ -387,7 +387,10 @@ export class Filter implements IAction {
}
private refreshFilterValue(): void {
- this.parent.removeEventListener(events.beforeDataBound, this.refreshFilterValueFn);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ if (!isNullOrUndefined((this.parent as any).modelObserver.boundedEvents)) {
+ this.parent.removeEventListener(events.beforeDataBound, this.refreshFilterValueFn);
+ }
if (this.filterSettings.type === 'FilterBar' && this.filterSettings.columns.length &&
!this.parent.getCurrentViewRecords().length) {
this.initialEnd();
diff --git a/controls/grids/src/grid/actions/infinite-scroll.ts b/controls/grids/src/grid/actions/infinite-scroll.ts
index d18fd54a7f..d0348c3c71 100644
--- a/controls/grids/src/grid/actions/infinite-scroll.ts
+++ b/controls/grids/src/grid/actions/infinite-scroll.ts
@@ -119,6 +119,7 @@ export class InfiniteScroll implements IAction {
this.parent.on(events.contentReady, this.selectNewRow, this);
this.parent.on(events.captionActionComplete, this.captionActionComplete, this);
this.parent.on(events.setVirtualPageQuery, this.setGroupCollapsePageQuery, this);
+ this.parent.on(events.infiniteScrollComplete, this.onActionComplete, this);
this.actionBeginFunction = this.actionBegin.bind(this);
this.actionCompleteFunction = this.actionComplete.bind(this);
this.dataBoundFunction = this.dataBound.bind(this);
@@ -159,6 +160,7 @@ export class InfiniteScroll implements IAction {
this.parent.off(events.contentReady, this.selectNewRow);
this.parent.off(events.captionActionComplete, this.captionActionComplete);
this.parent.off(events.setVirtualPageQuery, this.setGroupCollapsePageQuery);
+ this.parent.off(events.infiniteScrollComplete, this.onActionComplete);
this.parent.removeEventListener(events.actionBegin, this.actionBeginFunction);
this.parent.removeEventListener(events.actionComplete, this.actionCompleteFunction);
this.parent.removeEventListener(events.dataBound, this.dataBoundFunction);
@@ -666,6 +668,18 @@ export class InfiniteScroll implements IAction {
}
}
+ /**
+ * The function used to trigger onActionComplete
+ *
+ * @param {NotifyArgs} e - specifies the NotifyArgs
+ * @returns {void}
+ * @hidden
+ */
+ public onActionComplete(e: NotifyArgs): void {
+ const args: Object = { type: events.actionComplete };
+ this.parent.trigger(events.actionComplete, extend(e, args));
+ }
+
private resetInfiniteEdit(): void {
if (this.parent.enableInfiniteScrolling && this.isNormaledit) {
if ((this.parent.editSettings.allowEditing && this.isEdit) || (this.parent.editSettings.allowAdding && this.isAdd)) {
diff --git a/controls/grids/src/grid/actions/toolbar.ts b/controls/grids/src/grid/actions/toolbar.ts
index 9f25358328..9193d75e0b 100644
--- a/controls/grids/src/grid/actions/toolbar.ts
+++ b/controls/grids/src/grid/actions/toolbar.ts
@@ -716,6 +716,11 @@ export class Toolbar {
private onFocusOut(e: FocusEvent): void {
(e.target as HTMLElement).tabIndex = -1;
+ if (e.target && (e.target as HTMLElement).id === this.parent.element.id + '_searchbar' &&
+ !(e.relatedTarget && ((e.relatedTarget as HTMLElement).id === this.parent.element.id + '_clearbutton' ||
+ (e.relatedTarget as HTMLElement).id === this.parent.element.id + '_searchbutton'))) {
+ this.search();
+ }
}
private setFocusToolbarItem(element: Element): void {
diff --git a/controls/grids/src/grid/actions/virtual-scroll.ts b/controls/grids/src/grid/actions/virtual-scroll.ts
index 0b6c9ccf9d..9659497a7a 100644
--- a/controls/grids/src/grid/actions/virtual-scroll.ts
+++ b/controls/grids/src/grid/actions/virtual-scroll.ts
@@ -45,7 +45,7 @@ export class VirtualScroll implements IAction {
const rowHeight: number = this.parent.getRowHeight();
const vHeight: string | number = this.parent.height.toString().indexOf('%') < 0 ? this.parent.height :
this.parent.element.getBoundingClientRect().height;
- this.blockSize = ~~(vHeight / rowHeight);
+ this.blockSize = ~~(parseFloat(vHeight.toString()) / rowHeight);
const height: number = this.blockSize * 2;
const size: number = this.parent.pageSettings.pageSize;
this.parent.setProperties({ pageSettings: { pageSize: size < height ? height : size }}, true);
diff --git a/controls/grids/src/grid/base/constant.ts b/controls/grids/src/grid/base/constant.ts
index a08b9cb77b..9c15c30155 100644
--- a/controls/grids/src/grid/base/constant.ts
+++ b/controls/grids/src/grid/base/constant.ts
@@ -576,3 +576,5 @@ export const renderResponsiveChangeAction: string = 'render-Responsive-Change-Ac
export const renderResponsiveColumnChooserDiv: string = 'render-Responsive-Column-Chooser-Div';
/** @hidden */
export const showAddNewRowFocus: string = 'show-Add-New-Row-Focus';
+/** @hidden */
+export const infiniteScrollComplete: string = 'infinitescroll-complete';
diff --git a/controls/grids/src/grid/base/grid.ts b/controls/grids/src/grid/base/grid.ts
index ef988dba54..f2e65dca00 100644
--- a/controls/grids/src/grid/base/grid.ts
+++ b/controls/grids/src/grid/base/grid.ts
@@ -6529,6 +6529,7 @@ export class Grid extends Component implements INotifyPropertyChang
* @returns {void}
*/
public resetIndentWidth(): void {
+ if (this.isDestroyed) { return; }
if (ispercentageWidth(this)) {
this.getHeaderTable().querySelector('.e-emptycell').removeAttribute('indentRefreshed');
this.widthService.setWidthToColumns();
@@ -7346,8 +7347,8 @@ export class Grid extends Component implements INotifyPropertyChang
(ariaOwns)) !== (e.target as Element).getAttribute('aria-owns')))
&& !this.keyPress && this.isEdit && !Browser.isDevice) {
if (this.editSettings.mode === 'Batch' && !(((parentsUntil(relatedTarget, 'e-ddl') || parentsUntil(relatedTarget, 'e-ddt')) &&
- parentsUntil(relatedTarget, 'e-multi-select-list-wrapper')) && parentsUntil(relatedTarget, 'e-input-group'))
- && (parentsUntil(relatedTarget, 'e-uploader') || !(relatedTarget &&
+ (parentsUntil(relatedTarget, 'e-multi-select-list-wrapper') || parentsUntil(relatedTarget, 'e-input-filter'))) &&
+ parentsUntil(relatedTarget, 'e-input-group')) && (parentsUntil(relatedTarget, 'e-uploader') || !(relatedTarget &&
isNullOrUndefined(parentsUntil(relatedTarget, 'e-input-group'))))) {
this.editModule.saveCell();
this.notify(events.editNextValCell, {});
diff --git a/controls/grids/src/grid/models/column.ts b/controls/grids/src/grid/models/column.ts
index 64fdc6e4cc..5bd5529ad7 100644
--- a/controls/grids/src/grid/models/column.ts
+++ b/controls/grids/src/grid/models/column.ts
@@ -633,7 +633,15 @@ export class Column {
//Angular two way binding
const keys: string[] = Object.keys(column);
for (let i: number = 0; i < keys.length; i++) {
- this[keys[parseInt(i.toString(), 10)]] = column[keys[parseInt(i.toString(), 10)]];
+ if (keys[parseInt(i.toString(), 10)] === 'columns') {
+ const cols: Column[] = column[keys[parseInt(i.toString(), 10)]];
+ for (let j: number = 0; j < cols.length; j++) {
+ ((this.columns as Column[]).find((col: Column) => { return col.field === cols[parseInt(j.toString(), 10)]
+ .field; }) as Column).setProperties(cols[parseInt(j.toString(), 10)]);
+ }
+ } else {
+ this[keys[parseInt(i.toString(), 10)]] = column[keys[parseInt(i.toString(), 10)]];
+ }
//Refresh the react columnTemplates on state change
if (this.parent && this.parent.isReact) {
if (keys[parseInt(i.toString(), 10)] === 'template') {
diff --git a/controls/grids/src/grid/renderer/content-renderer.ts b/controls/grids/src/grid/renderer/content-renderer.ts
index aa405bb090..ead739e953 100644
--- a/controls/grids/src/grid/renderer/content-renderer.ts
+++ b/controls/grids/src/grid/renderer/content-renderer.ts
@@ -488,7 +488,7 @@ export class ContentRender implements IRenderer {
thisRef.parent.trigger(events.rowDataBound, arg);
if (modelData[parseInt(i.toString(), 10)].isDataRow || (thisRef.parent.enableVirtualization &&
thisRef.parent.groupSettings.enableLazyLoading)) {
- thisRef.rowElements.push(tr);
+ thisRef.rowElements.push(arg.row);
}
thisRef.ariaService.setOptions(thisRef.parent.element, {
colcount: gObj.getColumns().length.toString() });
@@ -532,7 +532,11 @@ export class ContentRender implements IRenderer {
}
if (modelData[parseInt(i.toString(), 10)].isDataRow || (this.parent.enableVirtualization &&
this.parent.groupSettings.enableLazyLoading)) {
- this.rowElements.push(tr);
+ if (!isNullOrUndefined(gObj.rowTemplate) && (gObj.isAngular || gObj.isVue3 || gObj.isVue)) {
+ this.rowElements.push(trElement ? trElement : tr);
+ } else {
+ this.rowElements.push(tr);
+ }
}
this.ariaService.setOptions(this.parent.element, { colcount: gObj.getColumns().length.toString() });
}
diff --git a/controls/grids/src/grid/renderer/edit-renderer.ts b/controls/grids/src/grid/renderer/edit-renderer.ts
index b3442e8847..f9c24981af 100644
--- a/controls/grids/src/grid/renderer/edit-renderer.ts
+++ b/controls/grids/src/grid/renderer/edit-renderer.ts
@@ -122,13 +122,14 @@ export class EditRender {
this.focus.onClick({ target: closest(elem, 'td') }, true);
} else {
const isFocus: boolean = (this.parent.enableVirtualization || this.parent.enableColumnVirtualization) && this.parent.editSettings.mode === 'Normal' ? false : true;
+ const focusElement: HTMLElement = elem.parentElement.classList.contains('e-ddl') ? elem.parentElement : elem;
if ((isFocus || ((this.parent.enableVirtualization || this.parent.enableColumnVirtualization) && this.parent.editSettings.newRowPosition === 'Bottom'
&& parentsUntil(elem, literals.addedRow))) && (!this.parent.editSettings.showAddNewRow ||
(this.parent.editSettings.showAddNewRow && (!parentsUntil(elem, literals.addedRow)) || this.parent.addNewRowFocus))) {
- elem.focus();
+ focusElement.focus();
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- (elem as any).focus({ preventScroll: true });
+ (focusElement as any).focus({ preventScroll: true });
}
}
if (elem.classList.contains('e-defaultcell')) {
diff --git a/controls/grids/src/grid/renderer/header-renderer.ts b/controls/grids/src/grid/renderer/header-renderer.ts
index 562b893c01..fbd08ac94d 100644
--- a/controls/grids/src/grid/renderer/header-renderer.ts
+++ b/controls/grids/src/grid/renderer/header-renderer.ts
@@ -727,7 +727,8 @@ export class HeaderRender implements IRenderer {
btnObj.appendTo(button);
button.onclick = (e: MouseEvent) => {
if ((e.target as HTMLElement).classList.contains('e-ressort-btn')
- || (e.target as HTMLElement).classList.contains('e-ressort-icon')) {
+ || (e.target as HTMLElement).classList.contains('e-ressort-icon') ||
+ (e.target as HTMLElement).querySelector('.e-ressort-icon')) {
this.parent.showResponsiveCustomSort();
} else {
this.parent.showResponsiveCustomFilter();
diff --git a/controls/grids/src/grid/services/focus-strategy.ts b/controls/grids/src/grid/services/focus-strategy.ts
index f486bfe6f1..9225658817 100644
--- a/controls/grids/src/grid/services/focus-strategy.ts
+++ b/controls/grids/src/grid/services/focus-strategy.ts
@@ -1351,6 +1351,10 @@ export class ContentFocus implements IFocus {
!info.element.classList.contains('e-detailcell') ? this.getFocusable(info.element) : info.element;
info.elementToFocus = info.element.classList.contains('e-detailcell') && info.element.querySelector('.e-childgrid')
? info.element.querySelector('.e-childgrid') : info.elementToFocus;
+ if (this.parent.editSettings.mode === 'Batch' && this.parent.isEdit && info.elementToFocus.tagName.toLowerCase() === 'input'
+ && info.elementToFocus.parentElement.classList.contains('e-ddl')) {
+ info.elementToFocus = info.elementToFocus.parentElement;
+ }
info.outline = true;
info.uid = info.element.parentElement.getAttribute('data-uid');
return info;
diff --git a/controls/grids/styles/excel-filter/_layout.scss b/controls/grids/styles/excel-filter/_layout.scss
index e322c122bf..910338407f 100644
--- a/controls/grids/styles/excel-filter/_layout.scss
+++ b/controls/grids/styles/excel-filter/_layout.scss
@@ -2,6 +2,9 @@
/*! Excel-Filter layout */
.sf-grid .e-excelfilter {
+ &.e-dialog .e-dlg-content {
+ padding-left: 0;
+ }
.e-dlg-content {
overflow: visible;
padding: 0;
@@ -471,7 +474,7 @@
user-select: none;
}
- & :not(.sf-grid) .e-dialog .e-dlg-content {
+ &.e-dialog .e-dlg-content {
padding-left: $grid-checkbox-content-padding-left;
@if $grid-xlfl-skin == 'material3' {
padding-right: 16px;
diff --git a/controls/grids/styles/grid/_material3-definition.scss b/controls/grids/styles/grid/_material3-definition.scss
index 8c49d8c506..08bf9b1125 100644
--- a/controls/grids/styles/grid/_material3-definition.scss
+++ b/controls/grids/styles/grid/_material3-definition.scss
@@ -599,9 +599,9 @@ $grid-group-drop-area-hover-border-color: $border-dark !default;
$grid-adatptive-apply-btn-disable: $primary-bg-color-disabled !default;
$grid-sortnumber-font-size: 11px !default;
$grid-reorderarrow-margin-top: -6px !default;
-$grid-reorder-arrow-top-margin: -1px !default;
+$grid-reorder-arrow-top-margin: 1px !default;
$grid-reorder-downarrow-top-margin: -2px !default;
-$grid-reorder-virtualarrow-top-margin: 1px !default;
+$grid-reorder-virtualarrow-top-margin: -.45px !default;
$grid-reorder-virtualdownarrow-top-margin: -2px !default;
$grid-reorderdownarrow-margin-top: 3.7px !default;
$grid-bigger-toolbar-icon-size: 20px !default;
diff --git a/controls/imageeditor/CHANGELOG.md b/controls/imageeditor/CHANGELOG.md
index bb69431493..79d5065895 100644
--- a/controls/imageeditor/CHANGELOG.md
+++ b/controls/imageeditor/CHANGELOG.md
@@ -2,6 +2,14 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### Image Editor
+
+#### Bug Fixes
+
+- `#I565340` - The issue with "Script error thrown when attempting to reopen a base64 URL using a custom toolbar in mobile mode" has been resolved.
+
## 25.1.35 (2024-03-15)
### Image Editor
diff --git a/controls/imageeditor/package.json b/controls/imageeditor/package.json
index 7b762a7990..a53c1902d3 100644
--- a/controls/imageeditor/package.json
+++ b/controls/imageeditor/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-image-editor",
- "version": "23.1.39",
+ "version": "25.1.35",
"description": "Essential JS 2 ImageEditor",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/imageeditor/spec/image-editor.spec.ts b/controls/imageeditor/spec/image-editor.spec.ts
index 49c82a6c7d..ebf0336073 100644
--- a/controls/imageeditor/spec/image-editor.spec.ts
+++ b/controls/imageeditor/spec/image-editor.spec.ts
@@ -8137,5 +8137,75 @@ describe('ImageEditor', () => {
done();
}, 100);
});
+ it('Coverage improvement - random combinations 1', (done) => {
+ imageEditor = new ImageEditor({
+ height: '450px',
+ toolbarUpdating: function (args) {
+ if (args.toolbarType === 'rectangle') {
+ args.toolbarItems = ['strokeColor'];
+ }
+ }
+ }, '#image-editor');
+ imageEditor.open('https://www.shutterstock.com/image-photo/linked-together-life-cropped-shot-600w-2149264221.jpg');
+ setTimeout(() => {
+ setTimeout(() => {
+ imageEditor.cloneShape('shape_1');
+ imageEditor.getShapeSettings();
+ }, 500);
+ imageEditor.drawImage('https://www.shutterstock.com/image-photo/linked-together-life-cropped-shot-600w-2149264221.jpg', 500, 100, 200, 80, false, 90);
+ done();
+ }, 100);
+ });
+ it('Coverage improvement - random combinations 2', (done) => {
+ imageEditor = new ImageEditor({
+ height: '450px',
+ zoomSettings: { minZoomFactor: 0.1, maxZoomFactor: 50 },
+ toolbarUpdating: function (args) {
+ if (args.toolbarType === 'rectangle') {
+ args.toolbarItems = ['strokeColor'];
+ }
+ }
+ }, '#image-editor');
+ imageEditor.open('https://www.shutterstock.com/image-photo/linked-together-life-cropped-shot-600w-2149264221.jpg');
+ setTimeout(() => {
+ imageEditor.drawRectangle(350, 200, 650, 400, 15, 'red', 'green');
+ imageEditor.select('custom');
+ imageEditor.rotate(90);
+ imageEditor.zoom(1.5);
+ imageEditor.crop();
+ imageEditor.reset();
+ imageEditor.drawText(350, 100, 'Syncfusion', 'Arial', 70, true, true, '#40e040');
+ imageEditor.selectShape('shape_1');
+ imageEditor.enableTextEditing();
+ imageEditor.reset();
+ imageEditor.select('custom');
+ imageEditor.rotate(90);
+ imageEditor.crop();
+ imageEditor.straightenImage(10);
+ imageEditor.select('custom');
+ imageEditor.select('3:4');
+ imageEditor.crop();
+ imageEditor.reset();
+ imageEditor.zoom(0.8);
+ const finetuneBtn: any = document.querySelectorAll('#image-editor_adjustment')[0];
+ finetuneBtn.click();
+ setTimeout(() => {});
+ imageEditor.reset();
+ imageEditor.drawText(350, 100, 'Syncfusion', 'Arial', 70, true, true, '#40e040', true);
+ imageEditor.enableTextEditing();
+ imageEditor.reset();
+ imageEditor.drawLine(350, 300, 300, 100, 20, 'red');
+ expect(imageEditor.objColl[imageEditor.objColl.length - 1].shape).toEqual('line');
+ imageEditor.drawArrow(350, 300, 300, 100, 20, 'red', 'Arrow', 'SolidArrow');
+ expect(imageEditor.objColl[imageEditor.objColl.length - 1].shape).toEqual('arrow');
+ imageEditor.drawPath([{x: 400, y: 300}, {x: 600, y: 400}, {x: 700, y: 300}], 20, 'red');
+ expect(imageEditor.objColl[imageEditor.objColl.length - 1].shape).toEqual('path');
+ imageEditor.getShapeSettings();
+ imageEditor.getImageFilter('Invert');
+ imageEditor.canUndo();
+ imageEditor.canRedo();
+ done();
+ }, 100);
+ });
});
});
diff --git a/controls/imageeditor/src/image-editor/action/shape.ts b/controls/imageeditor/src/image-editor/action/shape.ts
index 1918b81420..6d8e8cb06e 100644
--- a/controls/imageeditor/src/image-editor/action/shape.ts
+++ b/controls/imageeditor/src/image-editor/action/shape.ts
@@ -720,6 +720,8 @@ export class Shape {
endX: parent.activeObj.activePoint.startX + parent.activeObj.activePoint.width,
endY: parent.activeObj.activePoint.startY + parent.activeObj.activePoint.height,
width: selectionSettings.width, height: selectionSettings.height };
+ parent.activeObj.activePoint.endX = parent.activeObj.activePoint.startX + parent.activeObj.activePoint.width;
+ parent.activeObj.activePoint.endY = parent.activeObj.activePoint.startY + parent.activeObj.activePoint.height;
}
private updateShapeChangeEventArgs(shapeSettings: ShapeSettings): void {
@@ -775,6 +777,7 @@ export class Shape {
if (shapeSettings.degree) {
parent.activeObj.rotatedAngle = shapeSettings.degree * (Math.PI / 180);
}
+ this.updateFontRatio(parent.activeObj);
break;
case 'rectangle':
case 'image':
diff --git a/controls/imageeditor/src/image-editor/action/transform.ts b/controls/imageeditor/src/image-editor/action/transform.ts
index ceed16d2ae..975cbd358b 100644
--- a/controls/imageeditor/src/image-editor/action/transform.ts
+++ b/controls/imageeditor/src/image-editor/action/transform.ts
@@ -1453,8 +1453,9 @@ export class Transform {
toolbarHeight = obj['toolbarHeight'];
}
}
- if (Browser.isDevice && straightenObj['bool']) {
- cxtTbarHeight = parent.element.querySelector('#' + parent.element.id + '_contextualToolbarArea').clientHeight;
+ const ctxTbarArea: HTMLElement = parent.element.querySelector('#' + parent.element.id + '_contextualToolbarArea');
+ if (Browser.isDevice && straightenObj['bool'] && ctxTbarArea) {
+ cxtTbarHeight = ctxTbarArea.clientHeight;
}
parent.notify('toolbar', { prop: 'setToolbarHeight', value: {height: toolbarHeight }});
if (Browser.isDevice) {
diff --git a/controls/imageeditor/src/image-editor/action/undo-redo.ts b/controls/imageeditor/src/image-editor/action/undo-redo.ts
index 3f4703107a..1578ff6336 100644
--- a/controls/imageeditor/src/image-editor/action/undo-redo.ts
+++ b/controls/imageeditor/src/image-editor/action/undo-redo.ts
@@ -736,26 +736,6 @@ export class UndoRedo {
parent.currObjType.isCustomCrop = false;
}
- private getImageAction(operation: string): string {
- if (['brightness', 'contrast', 'saturation', 'opacity', 'blur', 'hue'].indexOf(operation) !== -1) {
- return 'FinetuneApplied';
- } else if (['chrome', 'cold', 'warm', 'grayscale', 'blackandwhite', 'sepia', 'invert'].indexOf(operation) !== -1) {
- return 'FilterApplied';
- } else if (operation === 'frame') {
- return 'FrameApplied';
- } else if (operation === 'resize') {
- return 'ImageResized';
- } else if (['deleteFreehandDrawing', 'deleteObj'].indexOf(operation) !== -1) {
- return 'ShapeDeleted';
- } else if (operation === 'crop') {
- return 'Cropped';
- } else if (['shapeInsert', 'freehanddraw', 'freehand-draw'].indexOf(operation) !== -1) {
- return 'ShapeInserted';
- } else {
- return 'ShapeCustomized';
- }
- }
-
private updateUrc(operation: string, previousObj: CurrentObject, previousObjColl: SelectionPoint[],
previousPointColl: Point[], previousSelPointColl: Point[],
previousCropObj: CurrentObject, previousText?: string,
diff --git a/controls/imageeditor/src/image-editor/base/image-editor.ts b/controls/imageeditor/src/image-editor/base/image-editor.ts
index 49f727a0f4..95770ba406 100644
--- a/controls/imageeditor/src/image-editor/base/image-editor.ts
+++ b/controls/imageeditor/src/image-editor/base/image-editor.ts
@@ -1196,7 +1196,7 @@ export class ImageEditor extends Component implements INotifyPro
private createDropUploader(): void {
const uploadObj: Uploader = new Uploader({
- dropArea: document.getElementsByClassName('e-canvas-wrapper')[0] as HTMLElement,
+ dropArea: this.element.getElementsByClassName('e-canvas-wrapper')[0] as HTMLElement,
allowedExtensions: '.jpg, .jpeg, .png,.svg',
multiple: false,
selected: (args: ChangeEventArgs) => {
@@ -1485,7 +1485,8 @@ export class ImageEditor extends Component implements INotifyPro
private notifyResetForAllModules(): void {
const modules: ModuleDeclaration[] = this.requiredModules();
for (let i: number = 0; i < modules.length; i++) {
- this.notify(modules[i as number].member, { prop: 'reset', onPropertyChange: false});
+ const module: string = modules[i as number].member;
+ this.notify(module === 'toolbar-module' ? 'toolbar' : module, { prop: 'reset', onPropertyChange: false});
}
}
@@ -2293,8 +2294,19 @@ export class ImageEditor extends Component implements INotifyPro
this.notify('shape', { prop: 'selectShape', onPropertyChange: false, value: {id: setting.id, obj: obj }});
this.notify('selection', { prop: 'getFreehandDrawEditing', onPropertyChange: false, value: {obj: freehandObj }});
if (obj['isSelected']) {
+ const tempFontSize: number = this.activeObj.textSettings.fontSize;
this.notify('shape', { prop: 'updateShapeChangeEventArgs', onPropertyChange: false,
value: {shapeSettings: setting }});
+ if (this.activeObj.shape === 'text' && tempFontSize) {
+ const diff: number = this.activeObj.textSettings.fontSize - tempFontSize;
+ if (diff !== 0) {
+ this.activeObj.activePoint.height += diff;
+ this.activeObj.activePoint.startY -= (diff / 2);
+ this.activeObj.activePoint.endY += (diff / 2);
+ this.notify('draw', { prop: 'updateActiveObject', onPropertyChange: false, value: { actPoint: this.activeObj.activePoint, obj: this.activeObj,
+ isMouseMove: null, x: null, y: null } });
+ }
+ }
const activeObj: SelectionPoint = extend({}, this.activeObj, {}, true) as SelectionPoint;
this.notify('shape', { prop: 'refreshActiveObj', onPropertyChange: false });
this.notify('draw', { prop: 'render-image', value: { isMouseWheel: null, isPreventClearRect: null, isFrame: null } });
diff --git a/controls/imageeditor/src/image-editor/renderer/toolbar.ts b/controls/imageeditor/src/image-editor/renderer/toolbar.ts
index ba42e74dba..c4684d91c9 100644
--- a/controls/imageeditor/src/image-editor/renderer/toolbar.ts
+++ b/controls/imageeditor/src/image-editor/renderer/toolbar.ts
@@ -275,12 +275,6 @@ export class ToolbarModule {
case 'setSelectedFreehandColor':
this.selFhdColor = args.value['color'];
break;
- case 'getCurrentFilter':
- args.value['obj']['currentFilter'] = parent.currentFilter;
- break;
- case 'setCurrentFilter':
- parent.currentFilter = args.value['filter'];
- break;
case 'setInitialAdjustmentValue':
parent.initialAdjustmentValue = args.value['value'];
break;
@@ -303,9 +297,6 @@ export class ToolbarModule {
case 'refreshSlider':
this.refreshSlider();
break;
- case 'renderSlider':
- this.renderSlider(args.value['type']);
- break;
case 'getCurrAdjustmentValue':
parent.getCurrAdjustmentValue(args.value['type']);
break;
@@ -315,18 +306,6 @@ export class ToolbarModule {
case 'refreshShapeDrawing':
this.refreshShapeDrawing();
break;
- case 'getCropToolbar':
- args.value['obj']['isCropToolbar'] = parent.isCropToolbar;
- break;
- case 'getPrevCurrSelectionPoint':
- args.value['obj']['prevCurrSelectionPoint'] = parent.prevCurrSelectionPoint;
- break;
- case 'setPrevCurrSelectionPoint':
- parent.prevCurrSelectionPoint = args.value['point'];
- break;
- case 'updateCropTransformItems':
- parent.updateCropTransformItems();
- break;
case 'setEnableDisableUndoRedo':
this.preventEnableDisableUr = args.value['isPrevent'];
break;
@@ -373,7 +352,7 @@ export class ToolbarModule {
private reset(): void {
const parent: ImageEditor = this.parent;
- this.defToolbarItems = []; this.toolbarHeight = 46; parent.prevCurrSelectionPoint = null;
+ this.toolbarHeight = 46; parent.prevCurrSelectionPoint = null;
this.zoomBtnHold = null; this.currToolbar = ''; parent.cxtTbarHeight = null;
this.currentToolbar = 'main'; this.selFhdColor = '#42a5f5'; parent.currentFilter = '';
this.preventZoomBtn = parent.isCropToolbar = this.preventEnableDisableUr = this.isFrameToolbar = false;
diff --git a/controls/imageeditor/styles/image-editor/_layout.scss b/controls/imageeditor/styles/image-editor/_layout.scss
index 2e0a883d05..963894beca 100644
--- a/controls/imageeditor/styles/image-editor/_layout.scss
+++ b/controls/imageeditor/styles/image-editor/_layout.scss
@@ -512,6 +512,9 @@
.e-ie-finetune-slider-wrap {
top: calc(50% - 15px) !important; /* stylelint-disable-line declaration-no-important */
+ @if $skin-name == 'Material3' or $skin-name == 'tailwind' {
+ top: calc(50% - 14px) !important; /* stylelint-disable-line declaration-no-important */
+ }
}
.e-transparency-slider-wrap {
diff --git a/controls/inputs/CHANGELOG.md b/controls/inputs/CHANGELOG.md
index 0ad612b7aa..4ae60b15ba 100644
--- a/controls/inputs/CHANGELOG.md
+++ b/controls/inputs/CHANGELOG.md
@@ -2,7 +2,7 @@
## [Unreleased]
-## 25.1.35 (2024-03-15)
+## 25.1.37 (2024-03-26)
### Signature
diff --git a/controls/kanban/CHANGELOG.md b/controls/kanban/CHANGELOG.md
index 1cd9f8dce3..2d2cfb150e 100644
--- a/controls/kanban/CHANGELOG.md
+++ b/controls/kanban/CHANGELOG.md
@@ -2,6 +2,32 @@
## [Unreleased]
+## 25.1.35 (2024-03-15)
+
+### Kanban
+
+#### Bug Fixes
+
+- `#I525892` - Now, the card template works properly upon drag-and-drop action in Kanban with remote data.
+
+- `#I550208` - Now, the swimlane header template will work properly in the mobile view.
+
+## 24.1.47 (2024-01-23)
+
+### Kanban
+
+#### Bug Fixes
+
+- `#I544423` - Now, the Kanban column header title shows properly when the column is collapsed.
+
+## 24.1.46 (2024-01-17)
+
+### Kanban
+
+#### Bug Fixes
+
+- `#I535989` - Now, drop clone works properly when slowly dragging and dropping the cards in the last position in the Kanban column.
+
## 24.1.41 (2023-12-18)
### Kanban
@@ -16,9 +42,9 @@
#### Bug Fixes
-`#I513537` - Now, localization of the "Cards" text was done. When you drag the multiple cards, it show up.
+- `#I513537` - Now, localization of the "Cards" text was done. When you drag the multiple cards, it show up.
-`#I515897` - Now, when the `cancel` argument is set to true in the `dialogClose` event in the kanban, it works properly.
+- `#I515897` - Now, when the `cancel` argument is set to true in the `dialogClose` event in the kanban, it works properly.
## 23.1.36 (2023-09-15)
@@ -26,9 +52,9 @@
#### Bug Fixes
-`#I492818` - Now, fast scrolling from top to bottom of the column continuously works properly.
+- `#I492818` - Now, fast scrolling from top to bottom of the column continuously works properly.
-`#I495751` - Now, dragging a card to the first position in the Kanban works properly without flickering.
+- `#I495751` - Now, dragging a card to the first position in the Kanban works properly without flickering.
## 22.1.34 (2023-06-21)
@@ -44,7 +70,7 @@
#### Bug Fixes
-`#F181441` - Resolved a issue, where a console error was thrown when dragging into the column header on the Kanban.
+- `#F181441` - Resolved a issue, where a console error was thrown when dragging into the column header on the Kanban.
## 21.1.37 (2023-03-29)
diff --git a/controls/kanban/package.json b/controls/kanban/package.json
index 5cbd93bdce..902b87dbb1 100644
--- a/controls/kanban/package.json
+++ b/controls/kanban/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-kanban",
- "version": "23.1.36",
+ "version": "25.1.35",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
"main": "./dist/ej2-kanban.umd.min.js",
diff --git a/controls/kanban/src/kanban/base/layout-render.ts b/controls/kanban/src/kanban/base/layout-render.ts
index bf91c48563..c46acd9c74 100644
--- a/controls/kanban/src/kanban/base/layout-render.ts
+++ b/controls/kanban/src/kanban/base/layout-render.ts
@@ -231,9 +231,18 @@ export class LayoutRender extends MobileLayout {
private initializeSwimlaneTree(): void {
if (this.parent.swimlaneSettings.keyField && this.parent.isAdaptive && this.parent.kanbanData.length !== 0) {
+ const swimlaneHeaderName: HTMLElement = this.parent.element.querySelector('.' + cls.TOOLBAR_SWIMLANE_NAME_CLASS);
this.swimlaneRow = [this.kanbanRows[this.swimlaneIndex]];
this.renderSwimlaneTree();
- this.parent.element.querySelector('.' + cls.TOOLBAR_SWIMLANE_NAME_CLASS).innerHTML = this.swimlaneRow[0].textField;
+ if (this.parent.swimlaneSettings.template) {
+ const cardCount: number = this.swimlaneData[this.swimlaneRow[0].keyField].length;
+ const templateArgs: HeaderArgs = extend({}, this.swimlaneRow[0], { count: cardCount }, true) as HeaderArgs;
+ const swimlaneTemplate: HTMLElement[] = this.parent.templateParser(
+ this.parent.swimlaneSettings.template)(templateArgs, this.parent, 'swimlaneTemplate', '', false);
+ swimlaneHeaderName.appendChild(swimlaneTemplate[0]);
+ } else {
+ swimlaneHeaderName.innerHTML = this.swimlaneRow[0].textField;
+ }
}
}
diff --git a/controls/layouts/CHANGELOG.md b/controls/layouts/CHANGELOG.md
index 69aded70a3..6f4fa7e009 100644
--- a/controls/layouts/CHANGELOG.md
+++ b/controls/layouts/CHANGELOG.md
@@ -2,13 +2,31 @@
## [Unreleased]
-## 24.2.4 (2024-02-06)
+## 25.1.37 (2024-03-26)
-### Dashboard Layout
+### DashboardLayout
#### Bug Fixes
-- `#FB49154` - The console error in the Dashboard Layout component when resizing the browser window has been resolved.
+- `#I564184` - Resolved the issue with the dynamically added panel not being persisted when `enablePersistence` is enabled in the Dashboard Layout.
+
+## 25.1.35 (2024-03-15)
+
+### Timeline
+
+The Timeline control enables users to display a series of data in chronological order, providing a visually compelling and user-friendly experience. This showcases user activities, tracking progress, narrating historical timelines, and more.
+
+#### Key features
+
+- **Orientation** - Display items in a horizontal or vertical orientation.
+
+- **Opposite content** - Display additional information opposite to the item content.
+
+- **Items alignment** - Items' content and opposite content can be aligned - before, after, alternate, or alternate reverse.
+
+- **Reverse timeline** - Shows the timeline items in the reverse order.
+
+- **Templates** - Customize the default appearance, including styling the dot item, templated content, and more.
## 20.4.48 (2023-02-01)
diff --git a/controls/layouts/README.md b/controls/layouts/README.md
index 41ef0bdabd..9743f8a012 100644
--- a/controls/layouts/README.md
+++ b/controls/layouts/README.md
@@ -2,7 +2,7 @@
# ej2-layouts
-The layout package contains cards, avatars, splitter and Dashboard Layout controls.
+The layout package contains cards, avatars, splitter, timeline and Dashboard Layout controls.
* The `card` is a small container in which user can show defined content in specific structure.
@@ -10,6 +10,8 @@ The layout package contains cards, avatars, splitter and Dashboard Layout contro
* The `splitter` is container control which used to construct different layouts using multiple and nested panes.
+* The `timeline` is a tool for displaying chronological information effortlessly within your application. It offers a visually compelling and user-friendly experience for showcasing user activities, tracking progress, or narrating historical timelines.
+
* The `DashboardLayout` is a grid structured layout control that helps to create a dashboard with panels. Panels hold the UI components and allow resize, reorder, drag-n-drop, remove and add options. This allows users to easily place the components at the desired position within the grid layout.
![Layout](https://ej2.syncfusion.com/products/images/layout/readme.png)
@@ -42,6 +44,10 @@ Following list of controls are available in the package
* [Getting Started](https://ej2.syncfusion.com/documentation/splitter/getting-started/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm)
* [View Online Demos](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/splitter/default.html)
+* [JavaScript Timeline](https://www.syncfusion.com/javascript-ui-controls/js-timeline?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm) - Used to build timelines to showcases user activities, tracking progress, narrating historical timelines, and more.
+ * [Getting Started](https://ej2.syncfusion.com/documentation/timeline/getting-started/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm)
+ * [View Online Demos](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/timeline/default.html)
+
* [JavaScript Dashboard Layout](https://www.syncfusion.com/javascript-ui-controls/js-dashboard-layout?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm) - Used to build dashboards with panels that holds the UI components and allow resize, reorder, drag-n-drop, remove and add options.
* [Getting Started](https://ej2.syncfusion.com/documentation/dashboard-layout/getting-started/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm)
* [View Online Demos](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboard-layout/default.html)
@@ -70,6 +76,7 @@ These components are available in following list of:
## Key Features
* Card
+
* [Header](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/card/basic.html) - Header supports to include title, subtitle along with image.
* [Images and Title](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/card/reveal.html) - Support to include images with customizable caption positions in it.
@@ -90,6 +97,7 @@ These components are available in following list of:
* xlarge
* Splitter
+
* [Multiple Panes](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/splitter/default.html) - Provided an option to configure more than two panes.
* [Resizable Panes](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/splitter/code-editor-layout.html) - Supports resizable to adjust its pane size dynamically.
@@ -100,15 +108,27 @@ These components are available in following list of:
* [Nested Panes](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/splitter/code-editor-layout.html) - Another splitter can be integrated within panes to create a complex layout.
- * Dashboard Layout
+* Timeline
+
+ * [Orientation](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/timeline/api.html) - Display items in a horizontal or vertical orientation.
+
+ * [Opposite content](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/timeline/api.html) - Display additional information opposite to the item content.
+
+ * [Items alignment](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/timeline/api.html) - Items content and opposite content can be aligned - before, after, alternate, or alternate reverse.
+
+ * [Reverse timeline](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/timeline/api.html) - Shows the timeline items in the reverse order.
+
+ * [Templates](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/timeline/template.html) - Customize the default appearance, including styling the dot item, templated content, and more.
+
+* Dashboard Layout
- * [Drag and Drop](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/properties.html) - Allows drag and drop of panels at the desired location within the dashboard.
+ * [Drag and Drop](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/properties.html) - Allows drag and drop of panels at the desired location within the dashboard.
- * [Floating](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/properties.html) - Floats the panels upward when the dragging option is enabled.
+ * [Floating](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/properties.html) - Floats the panels upward when the dragging option is enabled.
- * [Resizing](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/properties.html) - Support to resize the panels in any direction as per the requirement.
+ * [Resizing](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/properties.html) - Support to resize the panels in any direction as per the requirement.
- * [MediaQuery](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/default.html) - Allows the panels to be stacked when the specified resolution is met.
+ * [MediaQuery](https://ej2.syncfusion.com/demos/?utm_source=npm&utm_medium=listing&utm_campaign=javascript-layout-npm#/material/dashboardlayout/default.html) - Allows the panels to be stacked when the specified resolution is met.
## Support
diff --git a/controls/layouts/package.json b/controls/layouts/package.json
index 249ca95eb4..15505c412c 100644
--- a/controls/layouts/package.json
+++ b/controls/layouts/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-layouts",
- "version": "24.2.4",
+ "version": "25.1.35",
"description": "A package of Essential JS 2 layout pure CSS components such as card and avatar. The card is used as small container to show content in specific structure, whereas the avatars are icons, initials or figures representing particular person.",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
@@ -11,6 +11,7 @@
"@syncfusion/ej2-base": "*"
},
"devDependencies": {
+ "@syncfusion/ej2-staging": "^1.0.1",
"@types/chai": "^3.4.28",
"@types/jasmine": "2.8.9",
"@types/jasmine-ajax": "^3.1.27",
diff --git a/controls/layouts/spec/dashboard-layout.spec.ts b/controls/layouts/spec/dashboard-layout.spec.ts
index 6caf7d6e6e..7ef4c2dba2 100644
--- a/controls/layouts/spec/dashboard-layout.spec.ts
+++ b/controls/layouts/spec/dashboard-layout.spec.ts
@@ -314,7 +314,7 @@ describe('GridLayout', () => {
cellSpacing: [10, 10],
showGridLines: true,
panels: [{
- id: "one", sizeX: 2, sizeY: 1, row: 1, col: 0, header: "", cssClass:"test"
+ id: "one", sizeX: 2, sizeY: 1, row: 1, col: 0, header: "",cssClass:"test"
},
{
id: "two", sizeX: 2, sizeY: 1, row: 0, col: 0, content: "2
"
@@ -726,7 +726,6 @@ describe('GridLayout', () => {
expect(gridLayOut.element.children[0].offsetHeight).toBe(101);
expect(gridLayOut.element.offsetHeight).toBe(gridLayOut.element.children[0].offsetHeight);
});
-
it('addpanel with root element height with mediaquery null test case ', () => {
let content = generateTemplate('0');
gridLayOut = new DashboardLayout({
@@ -8047,4 +8046,4 @@ describe('GridLayout', () => {
detach(ele);
}
});
- });
+ });
\ No newline at end of file
diff --git a/controls/layouts/spec/splitter.spec.ts b/controls/layouts/spec/splitter.spec.ts
index 91eb1a967d..b230cce75c 100644
--- a/controls/layouts/spec/splitter.spec.ts
+++ b/controls/layouts/spec/splitter.spec.ts
@@ -5252,8 +5252,8 @@ describe('Splitter Control', () => {
splitterObj.paneSettings[0].size = '200px';
splitterObj.dataBind();
expect(splitterObj.allPanes[0].style.flexBasis).toBe('200px');
- expect(splitterObj.allPanes[1].style.flexBasis).toBe('149px');
- expect(splitterObj.allPanes[2].style.flexBasis).toBe('149px');
+ expect(splitterObj.allPanes[1].style.flexBasis).toBe('');
+ expect(splitterObj.allPanes[2].style.flexBasis).toBe('');
splitterObj.destroy();
});
it('Check flexible pane size -Pixel -one flexible pane', function () {
@@ -5266,7 +5266,7 @@ describe('Splitter Control', () => {
splitterObj.dataBind();
expect(splitterObj.allPanes[0].style.flexBasis).toBe('200px');
expect(splitterObj.allPanes[1].style.flexBasis).toBe('100px');
- expect(splitterObj.allPanes[2].style.flexBasis).toBe('298px');
+ expect(splitterObj.allPanes[2].style.flexBasis).toBe('');
splitterObj.destroy();
});
it('Check flexible pane size -Percentage - Two flexible pane', function () {
@@ -5278,8 +5278,8 @@ describe('Splitter Control', () => {
splitterObj.paneSettings[0].size = '50%';
splitterObj.dataBind();
expect(splitterObj.allPanes[0].style.flexBasis).toBe('50%');
- expect(splitterObj.allPanes[1].style.flexBasis).toBe('124px');
- expect(splitterObj.allPanes[2].style.flexBasis).toBe('124px');
+ expect(splitterObj.allPanes[1].style.flexBasis).toBe('');
+ expect(splitterObj.allPanes[2].style.flexBasis).toBe('');
splitterObj.destroy();
});
it('Check flexible pane size -Percentage - one flexible pane', function () {
@@ -5292,7 +5292,7 @@ describe('Splitter Control', () => {
splitterObj.dataBind();
expect(splitterObj.allPanes[0].style.flexBasis).toBe('50%');
expect(splitterObj.allPanes[1].style.flexBasis).toBe('20%');
- expect(splitterObj.allPanes[2].style.flexBasis).toBe('248px');
+ expect(splitterObj.allPanes[2].style.flexBasis).toBe('');
splitterObj.destroy();
});
});
diff --git a/controls/layouts/spec/timeline.spec.ts b/controls/layouts/spec/timeline.spec.ts
new file mode 100644
index 0000000000..6d15b4b5d8
--- /dev/null
+++ b/controls/layouts/spec/timeline.spec.ts
@@ -0,0 +1,843 @@
+import { createElement, remove, isNullOrUndefined} from '@syncfusion/ej2-base';
+import { Timeline, TimelineItemModel, TimelineRenderingEventArgs } from '../src/timeline/index';
+import { getMemoryProfile, inMB, profile } from './common.spec';
+
+describe('Timeline', () => {
+ beforeAll(() => {
+ const isDef: any = (o: any) => o !== undefined && o !== null;
+ if (!isDef(window.performance)) {
+ console.log('Unsupported environment, window.performance.memory is unavailable');
+ this.skip(); // skips test (in Chai)
+ return;
+ }
+ });
+
+ describe('DOM', () => {
+ let timeline: Timeline;
+ let timelineElement: HTMLElement;
+
+ beforeEach(() => {
+ timelineElement = createElement('div', { id: 'timeline'});
+ document.body.appendChild(timelineElement);
+ });
+
+ afterEach(() => {
+ if (timeline) {
+ timeline.destroy();
+ timeline = undefined;
+ }
+ remove(timelineElement);
+ });
+
+ it('Default timeline testing', () => {
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}]
+ });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ timeline.orientation = 'horizontal';
+ timeline.dataBind();
+ expect(timelineElement.classList.contains('.e-vertical')).toEqual(false);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ timeline.orientation = 'vertical';
+ timeline.dataBind();
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal')).toEqual(false);
+ });
+
+ it('Horizontal timeline testing', () => {
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}]
+ });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ });
+
+ it('Custom Icon', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-people'},
+ {dotCss: 'e-icons e-signature'},
+ {dotCss: 'e-icons e-location'},
+ {dotCss: 'e-icons e-cut'}
+ ];
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-dot');
+ expect((liElementArray[0] as HTMLElement).classList.contains('e-people')).toEqual(true);
+ expect((liElementArray[1] as HTMLElement).classList.contains('e-signature')).toEqual(true);
+ expect((liElementArray[2] as HTMLElement).classList.contains('e-location')).toEqual(true);
+ expect((liElementArray[3] as HTMLElement).classList.contains('e-cut')).toEqual(true);
+ });
+
+ it('Get component name testing', () => {
+ timeline = new Timeline({items: [{}, {}, {}, {}]});
+ timeline.appendTo('#timeline');
+ expect(timeline.getModuleName()).toEqual('timeline');
+ });
+
+ it('Timeline testing with Persistence', () => {
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}],
+ enablePersistence: true
+ });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-timeline') != null).toEqual(true);
+ });
+
+ it('Generic div Element ID generation', () => {
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}]
+ });
+ const timelineEle1 = createElement('div', {});
+ document.body.appendChild(timelineEle1);
+ timeline.appendTo(timelineEle1);
+ expect(timelineEle1.getAttribute('id') != timelineElement.getAttribute('id')).toEqual(true);
+ expect(isNullOrUndefined(timelineEle1.id)).toBe(false);
+ timeline.destroy();
+ timeline = undefined;
+ remove(timelineEle1);
+ });
+ });
+
+ describe('DOM Properties', () => {
+ let timeline: Timeline;
+ let timelineElement: HTMLElement;
+
+ beforeEach(() => {
+ timelineElement = createElement('div', { id: 'timeline'});
+ document.body.appendChild(timelineElement);
+ });
+
+ afterEach(() => {
+ if (timeline) {
+ timeline.destroy();
+ timeline = undefined;
+ }
+ remove(timelineElement);
+ });
+
+ it('cssClass', () => {
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}],
+ cssClass: 'testClass'
+ });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.classList.contains('testClass')).toBe(true);
+ timeline.cssClass = 'newClass';
+ timeline.dataBind();
+ expect(timelineElement.classList.contains('newClass')).toBe(true);
+ expect(timelineElement.classList.contains('testClass')).toBe(false);
+ });
+
+ it('Item with cssClass', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-people', cssClass: 'testClass'},
+ {dotCss: 'e-icons e-signature'},
+ {dotCss: 'e-icons e-location'},
+ {dotCss: 'e-icons e-cut'}
+ ];
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelector('.e-timeline-item').classList).toContain('testClass');
+ });
+
+ it('Item with disabled', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-people', disabled: true},
+ {dotCss: 'e-icons e-signature'},
+ {dotCss: 'e-icons e-location'},
+ {dotCss: 'e-icons e-cut'}
+ ];
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelector('.e-timeline-item').classList).toContain('e-item-disabled');
+ timeline.items[0].disabled = false;
+ timeline.dataBind();
+ expect(timelineElement.querySelector('.e-timeline-item').classList.contains('e-item-disabled')).toBe(false);
+ });
+
+ it('RTL', () => {
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}],
+ enableRtl: true
+ });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.classList.contains('e-rtl')).toEqual(true);
+ timeline.enableRtl = false;
+ timeline.dataBind();
+ expect(timelineElement.classList.contains('e-rtl')).toEqual(false);
+ timeline.enableRtl = true;
+ timeline.dataBind();
+ expect(timelineElement.classList.contains('e-rtl')).toEqual(true);
+ });
+
+ it('text content', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-after')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with reverse feature', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, reverse: true });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-timeline-reverse')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-after')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ timeline.reverse = false;
+ timeline.dataBind();
+ expect(timelineElement.classList.contains('e-timeline-reverse')).toEqual(false);
+ timeline.reverse = true;
+ timeline.dataBind();
+ expect(timelineElement.classList.contains('e-timeline-reverse')).toEqual(true);
+ });
+
+ it('custom icon with text content', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-people', content: 'Ordered'},
+ {dotCss: 'e-icons e-signature', content: 'Processing'},
+ {dotCss: 'e-icons e-location', content: 'Shipped'},
+ {dotCss: 'e-icons e-cut', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-after')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-dot');
+ expect((liIconElementArray[0] as HTMLElement).classList.contains('e-people')).toEqual(true);
+ expect((liIconElementArray[1] as HTMLElement).classList.contains('e-signature')).toEqual(true);
+ expect((liIconElementArray[2] as HTMLElement).classList.contains('e-location')).toEqual(true);
+ expect((liIconElementArray[3] as HTMLElement).classList.contains('e-cut')).toEqual(true);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with before position', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'before' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-before')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with alternate position', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternate' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternate')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with alternate reverse position', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternatereverse' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternatereverse')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with opposite content', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-after')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('timeline content as js renderer ', () => {
+ const customData: TimelineItemModel[] = [
+ {content: '#itemContent'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ let content = 'Ordered';
+ const renderer = createElement('script', { id: 'itemContent', innerHTML: content });
+ renderer.setAttribute('type', 'text/x-jsrender');
+ document.body.appendChild(renderer);
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ content = null;
+ remove(renderer);
+ });
+
+ it('timeline content with opposite content as js renderer ', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '#itemContent', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ let oppositeContent = '09:30 am';
+ const renderer = createElement('script', { id: 'itemContent', innerHTML: oppositeContent });
+ renderer.setAttribute('type', 'text/x-jsrender');
+ document.body.appendChild(renderer);
+ timeline = new Timeline({ items: customData });
+ timeline.appendTo('#timeline');
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ oppositeContent = null;
+ remove(renderer);
+ });
+
+ it('text content with opposite content with before', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'before' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-before')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with opposite content with alternate', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternate' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternate')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with opposite content with alternate reverse', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternatereverse' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternatereverse')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-vertical') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-after')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('custom icon with text content', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-people', content: 'Ordered'},
+ {dotCss: 'e-icons e-signature', content: 'Processing'},
+ {dotCss: 'e-icons e-location', content: 'Shipped'},
+ {dotCss: 'e-icons e-cut', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-after')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-dot');
+ expect((liIconElementArray[0] as HTMLElement).classList.contains('e-people')).toEqual(true);
+ expect((liIconElementArray[1] as HTMLElement).classList.contains('e-signature')).toEqual(true);
+ expect((liIconElementArray[2] as HTMLElement).classList.contains('e-location')).toEqual(true);
+ expect((liIconElementArray[3] as HTMLElement).classList.contains('e-cut')).toEqual(true);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with before position', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'before', orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-before')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with alternate position', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternate', orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternate')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with alternate reverse position', () => {
+ const customData: TimelineItemModel[] = [
+ {content: 'Ordered'},
+ {content: 'Processing'},
+ {content: 'Shipped'},
+ {content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternatereverse', orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternatereverse')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with opposite content', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-after')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with opposite content with before', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'before', orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-before')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with opposite content with alternate', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternate', orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternate')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('text content with opposite content with alternate reverse', () => {
+ const customData: TimelineItemModel[] = [
+ {oppositeContent: '09:30 am', content: 'Ordered'},
+ {oppositeContent: '10:30 am', content: 'Processing'},
+ {oppositeContent: '11:30 am', content: 'Shipped'},
+ {oppositeContent: '12:30 am', content: 'Delivered'}
+ ];
+ timeline = new Timeline({ items: customData, align: 'alternatereverse', orientation: 'horizontal' });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.classList.contains('e-timeline')).toEqual(true);
+ expect(timelineElement.classList.contains('e-align-alternatereverse')).toEqual(true);
+ expect(timelineElement.classList.contains('.e-horizontal') != null).toEqual(true);
+ expect(timelineElement.querySelector('.e-timeline-items') != null).toEqual(true);
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-opposite-content').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-dot').length).toBe(4);
+ expect(timelineElement.querySelectorAll('.e-content').length).toBe(4);
+ const liIconElementArray: any = timelineElement.querySelectorAll('.e-opposite-content');
+ expect((liIconElementArray[0] as HTMLElement).innerText).toEqual('09:30 am');
+ expect((liIconElementArray[1] as HTMLElement).innerText).toEqual('10:30 am');
+ expect((liIconElementArray[2] as HTMLElement).innerText).toEqual('11:30 am');
+ expect((liIconElementArray[3] as HTMLElement).innerText).toEqual('12:30 am');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-content');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Ordered');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Processing');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Shipped');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Delivered');
+ });
+
+ it('created Property', () => {
+ let isCreated: boolean = false;
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}],
+ created: () => { isCreated = true; }
+ });
+ timeline.appendTo('#timeline');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-timeline-item');
+ expect(isCreated).toEqual(true);
+ });
+
+ it('beforeItemRender Property', () => {
+ let count: number = 0;
+ timeline = new Timeline({
+ items: [{}, {}, {}, {}],
+ beforeItemRender: (e: TimelineRenderingEventArgs) => {
+ count++;
+ expect(e.element.classList).toContain('e-timeline-item');
+ }
+ });
+ timeline.appendTo('#timeline');
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect(count).toBe(4);
+ });
+
+ it('timeline with template support', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-folder', content: 'Item 1'},
+ {dotCss: 'e-icons e-folder', content: 'Item 2'},
+ {dotCss: 'e-icons e-folder', content: 'Item 3'},
+ {dotCss: 'e-icons e-folder', content: 'Item 4'}
+ ];
+ timeline = new Timeline({ items: customData, template: '${itemIndex}' });
+ timeline.appendTo('#timeline');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-timeline-item');
+ expect(timelineElement.querySelectorAll('.e-timeline-item').length).toBe(4);
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('0');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('1');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('2');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('3');
+ timeline.template = 'Item ${itemIndex}';
+ timeline.dataBind();
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Item 0');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Item 1');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Item 2');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Item 3');
+ });
+
+ it('timeline Template as js renderer ', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-folder', content: 'Item 1'},
+ {dotCss: 'e-icons e-folder', content: 'Item 2'},
+ {dotCss: 'e-icons e-folder', content: 'Item 3'},
+ {dotCss: 'e-icons e-folder', content: 'Item 4'}
+ ];
+ let template = 'Item ${itemIndex}';
+ const renderer = createElement('script', { id: 'itemTemp', innerHTML: template });
+ renderer.setAttribute('type', 'text/x-jsrender');
+ document.body.appendChild(renderer);
+ timeline = new Timeline({ items: customData, template: '#itemTemp' });
+ timeline.appendTo('#timeline');
+ const liElementArray: any = timelineElement.querySelectorAll('.e-timeline-item');
+ expect(timelineElement.querySelector('.e-timeline-item').firstElementChild.classList).toContain('tempContent');
+ expect((liElementArray[0] as HTMLElement).innerText).toEqual('Item 0');
+ expect((liElementArray[1] as HTMLElement).innerText).toEqual('Item 1');
+ expect((liElementArray[2] as HTMLElement).innerText).toEqual('Item 2');
+ expect((liElementArray[3] as HTMLElement).innerText).toEqual('Item 3');
+ template = null;
+ remove(renderer);
+ });
+
+ it('timeline Template as HTMLElement ', () => {
+ const customData: TimelineItemModel[] = [
+ {dotCss: 'e-icons e-folder', content: 'Item 1'},
+ {dotCss: 'e-icons e-folder', content: 'Item 2'},
+ {dotCss: 'e-icons e-folder', content: 'Item 3'},
+ {dotCss: 'e-icons e-folder', content: 'Item 4'}
+ ];
+ const template = 'Item ${itemIndex}';
+ const tempContent = createElement('div', { id: 'itemTemp', className: 'tempContent', innerHTML: template });
+ document.body.appendChild(tempContent);
+ timeline = new Timeline({ items: customData, template: '#itemTemp' });
+ timeline.appendTo('#timeline');
+ expect(document.querySelector('.tempContent') === null).toEqual(false);
+ timeline.template = '#labelTemp1';
+ timeline.dataBind();
+ remove(tempContent);
+ });
+
+ it('memory leak', () => {
+ profile.sample();
+ const average: any = inMB(profile.averageChange);
+ // check average change in memory samples to not be over 10MB
+ expect(average).toBeLessThan(10);
+ const memory: any = inMB(getMemoryProfile());
+ // check the final memory usage against the first usage, there should be little change if everything was properly deallocated
+ expect(memory).toBeLessThan(profile.samples[0] + 0.25);
+ });
+ });
+});
diff --git a/controls/layouts/src/dashboard-layout/dashboard-layout.ts b/controls/layouts/src/dashboard-layout/dashboard-layout.ts
index 043e060a32..76f86093f0 100644
--- a/controls/layouts/src/dashboard-layout/dashboard-layout.ts
+++ b/controls/layouts/src/dashboard-layout/dashboard-layout.ts
@@ -3269,6 +3269,7 @@ export class DashboardLayout extends Component implements INotifyPr
if (Array.isArray(getValue(key, this)) && key === 'panels') {
// eslint-disable-next-line
this.mergePanels(dataObj[key], this[key]);
+ (this)[key as keyof DashboardLayout] = dataObj[key as keyof DashboardLayout];
}
}
}
diff --git a/controls/layouts/src/index.ts b/controls/layouts/src/index.ts
index c7c4ac22d5..484b8db25a 100644
--- a/controls/layouts/src/index.ts
+++ b/controls/layouts/src/index.ts
@@ -3,4 +3,4 @@
*/
export * from './splitter/index';
export * from './dashboard-layout/index';
-
+export * from './timeline/index';
diff --git a/controls/layouts/src/splitter/splitter.ts b/controls/layouts/src/splitter/splitter.ts
index 529516eb1f..ef49612f50 100644
--- a/controls/layouts/src/splitter/splitter.ts
+++ b/controls/layouts/src/splitter/splitter.ts
@@ -554,7 +554,9 @@ export class Splitter extends Component {
- staticPaneWidth - (this.border * 2);
const avgDiffWidth: number = flexPaneWidth / flexPaneIndexes.length;
for (let j: number = 0; j < flexPaneIndexes.length; j++) {
- this.allPanes[flexPaneIndexes[j as number]].style.flexBasis = avgDiffWidth + 'px';
+ if (this.allPanes[flexPaneIndexes[j as number]].style.flexBasis !== '') {
+ this.allPanes[flexPaneIndexes[j as number]].style.flexBasis = avgDiffWidth + 'px';
+ }
}
this.allPanes[index as number].classList.add(STATIC_PANE);
}
@@ -1359,7 +1361,9 @@ export class Splitter extends Component {
if (paneCount - 1 === i) {
const staticPaneCount: number = this.element.querySelectorAll('.' + STATIC_PANE).length;
if (staticPaneCount === paneCount) {
- removeClass([this.allPanes[i as number]], STATIC_PANE);
+ if (this.allPanes[i as number].style.flexBasis === '') {
+ removeClass([this.allPanes[i as number]], STATIC_PANE);
+ }
}
}
}
diff --git a/controls/layouts/src/timeline/index.ts b/controls/layouts/src/timeline/index.ts
new file mode 100644
index 0000000000..28e7925b83
--- /dev/null
+++ b/controls/layouts/src/timeline/index.ts
@@ -0,0 +1,3 @@
+/** Timeline export modules */
+export * from './timeline';
+export * from './timeline-model';
diff --git a/controls/layouts/src/timeline/timeline-model.d.ts b/controls/layouts/src/timeline/timeline-model.d.ts
new file mode 100644
index 0000000000..ef468bf984
--- /dev/null
+++ b/controls/layouts/src/timeline/timeline-model.d.ts
@@ -0,0 +1,140 @@
+import { Component, INotifyPropertyChanged, ChildProperty, Collection, BaseEventArgs, Event, EmitType, NotifyPropertyChanges, Property, getUniqueID, addClass, attributes, isNullOrUndefined, select, compile, remove, removeClass, append } from '@syncfusion/ej2-base';
+import {TimelineOrientation,TimelineAlign,TimelineRenderingEventArgs} from "./timeline";
+import {ComponentModel} from '@syncfusion/ej2-base';
+
+/**
+ * Interface for a class TimelineItem
+ */
+export interface TimelineItemModel {
+
+ /**
+ * Defines one or more CSS classes to include an icon or image in the Timeline item.
+ *
+ * @default ''
+ */
+ dotCss?: string;
+
+ /**
+ * Defines the text content or template for the Timeline item. The current itemIndex passed as context to build the content.
+ *
+ * @default ''
+ * @angularType string | object
+ * @reactType string | function | JSX.Element
+ * @vueType string | function
+ * @aspType string
+ */
+ content?: string | Function;
+
+ /**
+ * Defines the additional text content or template to be displayed opposite side of the item. The current itemIndex passed as context to build the content.
+ *
+ * @default ''
+ * @angularType string | object
+ * @reactType string | function | JSX.Element
+ * @vueType string | function
+ * @aspType string
+ */
+ oppositeContent?: string | Function;
+
+ /**
+ * Defines whether to enable or disable the timeline item.
+ *
+ * @default false
+ */
+ disabled?: boolean;
+
+ /**
+ * Defines the CSS class to customize the Timeline item appearance.
+ *
+ * @default ''
+ */
+ cssClass?: string;
+
+}
+
+/**
+ * Interface for a class Timeline
+ */
+export interface TimelineModel extends ComponentModel{
+
+ /**
+ * Defines the orientation type of the Timeline.
+ *
+ * The possible values are:
+ * * Horizontal
+ * * vertical
+ *
+ * {% codeBlock src='timeline/orientation/index.md' %}{% endcodeBlock %}
+ *
+ * @isenumeration true
+ * @default TimelineOrientation.Vertical
+ * @asptype TimelineOrientation
+ */
+ orientation?: string | TimelineOrientation;
+
+ /**
+ * Defines the alignment of item content within the Timeline.
+ *
+ * The possible values are:
+ * * Before
+ * * After
+ * * Alternate
+ * * AlternateReverse
+ *
+ * {% codeBlock src='timeline/align/index.md' %}{% endcodeBlock %}
+ *
+ * @isenumeration true
+ * @default TimelineAlign.After
+ * @asptype TimelineAlign
+ */
+ align?: string | TimelineAlign;
+
+ /**
+ * Defines the list of items.
+ *
+ * @default []
+ */
+ items?: TimelineItemModel[];
+
+ /**
+ * Defines the CSS class to customize the Timeline appearance.
+ *
+ * @default ''
+ */
+ cssClass?: string;
+
+ /**
+ * Defines whether to show the timeline items in reverse order or not.
+ *
+ * @default false
+ */
+ reverse?: boolean;
+
+ /**
+ * Defines the template content for each timeline item. The template context will contain the item model.
+ *
+ * {% codeBlock src='timeline/template/index.md' %}{% endcodeBlock %}
+ *
+ * @default ''
+ * @angularType string | object
+ * @reactType string | function | JSX.Element
+ * @vueType string | function
+ * @aspType string
+ */
+ template?: string | Function;
+
+ /**
+ * Event callback that is raised after rendering the timeline.
+ *
+ * @event created
+ */
+ created?: EmitType;
+
+ /**
+ * Event triggers before rendering each item.
+ *
+ * @event beforeItemRender
+ */
+ beforeItemRender?: EmitType;
+
+}
\ No newline at end of file
diff --git a/controls/layouts/src/timeline/timeline.ts b/controls/layouts/src/timeline/timeline.ts
new file mode 100644
index 0000000000..f298919b8c
--- /dev/null
+++ b/controls/layouts/src/timeline/timeline.ts
@@ -0,0 +1,484 @@
+import { Component, INotifyPropertyChanged, ChildProperty, Collection, BaseEventArgs, Event, EmitType, NotifyPropertyChanges, Property, getUniqueID, addClass, attributes, isNullOrUndefined, select, compile, remove, removeClass, append } from '@syncfusion/ej2-base';
+import { TimelineModel, TimelineItemModel } from '../timeline';
+
+const ITEMLISTCONTAINER: string = 'e-timeline-items';
+const ITEMCONTAINER: string = 'e-timeline-item';
+const OPPOSITECONTENT: string = 'e-opposite-content';
+const DOTCONTAINER: string = 'e-dot-item';
+const DOTCONTENT: string = 'e-dot';
+const CONTENT: string = 'e-content';
+const ITEMCONNECTOR: string = 'e-connector';
+const VERTICAL: string = 'e-vertical';
+const HORIZONTAL: string = 'e-horizontal';
+const TIMELINEREVERSE: string = 'e-timeline-reverse';
+const RTL: string = 'e-rtl';
+const DISABLED: string = 'e-item-disabled';
+const TEMPLATE: string = 'e-item-template';
+
+/**
+ * Defines the orientation type of the Timeline.
+ */
+export enum TimelineOrientation {
+ /**
+ * Items are displayed horizontally.
+ */
+ Horizontal = 'Horizontal',
+ /**
+ * Items are displayed vertically.
+ */
+ Vertical = 'Vertical'
+}
+
+/**
+ * Specifies the alignment of item content within the Timeline.
+ */
+export enum TimelineAlign {
+ /**
+ * Aligns item content to the top and opposite content to the bottom when the Timeline is in a horizontal orientation, or the content to the left and opposite content to the right when the Timeline is in a vertical orientation.
+ */
+ Before = 'Before',
+ /**
+ * Aligns item content to the bottom and opposite content to the top when the Timeline is in a horizontal orientation, or the content to the right and opposite content to the left when the Timeline is in a vertical orientation.
+ */
+ After = 'After',
+ /**
+ * Aligns item content alternatively, regardless of the Timeline's orientation.
+ */
+ Alternate = 'Alternate',
+ /**
+ * Aligns item content in alternate reverse, regardless of the Timeline's orientation.
+ */
+ AlternateReverse = 'AlternateReverse'
+}
+
+/**
+ * Specifies the items of the Timeline.
+ */
+export class TimelineItem extends ChildProperty {
+ /**
+ * Defines one or more CSS classes to include an icon or image in the Timeline item.
+ *
+ * @default ''
+ */
+ @Property('')
+ public dotCss: string;
+
+ /**
+ * Defines the text content or template for the Timeline item. The current itemIndex passed as context to build the content.
+ *
+ * @default ''
+ * @angularType string | object
+ * @reactType string | function | JSX.Element
+ * @vueType string | function
+ * @aspType string
+ */
+ @Property('')
+ public content: string | Function;
+
+ /**
+ * Defines the additional text content or template to be displayed opposite side of the item. The current itemIndex passed as context to build the content.
+ *
+ * @default ''
+ * @angularType string | object
+ * @reactType string | function | JSX.Element
+ * @vueType string | function
+ * @aspType string
+ */
+ @Property('')
+ public oppositeContent: string | Function;
+
+ /**
+ * Defines whether to enable or disable the timeline item.
+ *
+ * @default false
+ */
+ @Property(false)
+ public disabled: boolean;
+
+ /**
+ * Defines the CSS class to customize the Timeline item appearance.
+ *
+ * @default ''
+ */
+ @Property('')
+ public cssClass: string;
+}
+
+/**
+ * Provides information about beforeItemRender event callback.
+ */
+export interface TimelineRenderingEventArgs extends BaseEventArgs {
+ /**
+ * Provides the timeline element.
+ */
+ element: HTMLElement;
+
+ /**
+ * Provides the index of the current item.
+ */
+ index: number;
+}
+
+/**
+ * The Timeline component presents a series of events or activities in chronological order, allowing users to track the progression of time.
+ *
+ * ```html
+ *
+ * ```
+ * ```typescript
+ *
+ * ```
+ */
+@NotifyPropertyChanges
+export class Timeline extends Component implements INotifyPropertyChanged {
+
+ /**
+ * Defines the orientation type of the Timeline.
+ *
+ * The possible values are:
+ * * Horizontal
+ * * vertical
+ *
+ * {% codeBlock src='timeline/orientation/index.md' %}{% endcodeBlock %}
+ *
+ * @isenumeration true
+ * @default TimelineOrientation.Vertical
+ * @asptype TimelineOrientation
+ */
+ @Property(TimelineOrientation.Vertical)
+ public orientation: string | TimelineOrientation;
+
+ /**
+ * Defines the alignment of item content within the Timeline.
+ *
+ * The possible values are:
+ * * Before
+ * * After
+ * * Alternate
+ * * AlternateReverse
+ *
+ * {% codeBlock src='timeline/align/index.md' %}{% endcodeBlock %}
+ *
+ * @isenumeration true
+ * @default TimelineAlign.After
+ * @asptype TimelineAlign
+ */
+ @Property(TimelineAlign.After)
+ public align: string | TimelineAlign;
+
+ /**
+ * Defines the list of items.
+ *
+ * @default []
+ */
+ @Collection([], TimelineItem)
+ public items: TimelineItemModel[];
+
+ /**
+ * Defines the CSS class to customize the Timeline appearance.
+ *
+ * @default ''
+ */
+ @Property('')
+ public cssClass: string;
+
+ /**
+ * Defines whether to show the timeline items in reverse order or not.
+ *
+ * @default false
+ */
+ @Property(false)
+ public reverse: boolean;
+
+ /**
+ * Defines the template content for each timeline item. The template context will contain the item model.
+ *
+ * {% codeBlock src='timeline/template/index.md' %}{% endcodeBlock %}
+ *
+ * @default ''
+ * @angularType string | object
+ * @reactType string | function | JSX.Element
+ * @vueType string | function
+ * @aspType string
+ */
+ @Property('')
+ public template: string | Function;
+
+ /**
+ * Event callback that is raised after rendering the timeline.
+ *
+ * @event created
+ */
+ @Event()
+ public created: EmitType;
+
+ /**
+ * Event triggers before rendering each item.
+ *
+ * @event beforeItemRender
+ */
+ @Event()
+ public beforeItemRender: EmitType;
+
+ /* Private variables */
+ private timelineListEle: HTMLElement;
+ private templateFunction: Function;
+ private isReact?: boolean;
+
+ /**
+ * * Constructor for creating the Timeline component.
+ *
+ * @param {TimelineModel} options - Specifies the Timeline model.
+ * @param {string | HTMLElement} element - Specifies the element to render as component.
+ * @private
+ */
+ constructor(options?: TimelineModel, element?: string | HTMLElement) {
+ super(options, element);
+ }
+
+ protected preRender(): void {
+ if (!this.element.id) { this.element.id = getUniqueID('e-' + this.getModuleName()); }
+ }
+
+ /**
+ * To get component name.
+ *
+ * @returns {string} - Module Name
+ * @private
+ */
+ public getModuleName(): string {
+ return 'timeline';
+ }
+
+ /**
+ * This method is abstract member of the Component.
+ *
+ * @private
+ * @returns {string}
+ */
+ protected getPersistData(): string {
+ return this.addOnPersist([]);
+ }
+
+ protected render(): void {
+ attributes(this.element, { 'role': 'navigation', 'aria-label': this.element.id });
+ this.timelineListEle = this.createElement('ol', { className: ITEMLISTCONTAINER });
+ this.updateOrientation();
+ this.updateCssClass(this.cssClass);
+ this.updateAlign();
+ this.updateReverse();
+ this.updateRtl();
+ this.updateTemplateFunction();
+ this.renderItems();
+ this.element.appendChild(this.timelineListEle);
+ }
+
+
+
+ protected updateOrientation(): void {
+ const orientation = this.orientation.toLowerCase();
+ if (orientation === 'horizontal' || orientation === 'vertical') {
+ this.element.classList.remove(HORIZONTAL, VERTICAL);
+ this.element.classList.add('e-' + orientation);
+ }
+ }
+
+ protected updateCssClass(addCss: string, removeCss: string = ""): void {
+ let cssClasses: string[];
+ if (removeCss) {
+ cssClasses = removeCss.trim().split(' ');
+ this.element.classList.remove(...cssClasses);
+ }
+ if (addCss) {
+ cssClasses = addCss.trim().split(' ');
+ this.element.classList.add(...cssClasses);
+ }
+ }
+
+ protected updateRtl(): void {
+ this.element.classList[this.enableRtl ? 'add' : 'remove'](RTL);
+ }
+
+ protected updateAlign(): void {
+ const align: string = this.align.toLowerCase();
+ if (align === 'before' || align === 'after' || align === 'alternate' || align === 'alternatereverse') {
+ this.element.classList.remove('e-align-before', 'e-align-after', 'e-align-alternate', 'e-align-alternatereverse');
+ this.element.classList.add('e-align-' + align);
+ }
+ }
+
+ protected updateReverse(): void {
+ this.element.classList[this.reverse ? 'add' : 'remove'](TIMELINEREVERSE);
+ }
+
+ private renderItems(): void {
+ for (let index: number = 0; index < this.items.length; index++) {
+ const item: TimelineItemModel = this.items[parseInt(index.toString(), 10)];
+ const timelineItem: HTMLElement = this.createElement('li', { className: ITEMCONTAINER + ' ' + ITEMCONNECTOR });
+ if (!this.template) {
+ const oppositeTextEle = this.createElement('div', { className: OPPOSITECONTENT });
+ if (item.oppositeContent) {
+ const oppositeCtn: string | Function = this.getTemplateFunction(item.oppositeContent);
+ if (typeof oppositeCtn === 'string') {
+ oppositeTextEle.innerText = oppositeCtn;
+ } else {
+ append(oppositeCtn({ item: item, itemIndex: index }), oppositeTextEle);
+ }
+ }
+ timelineItem.appendChild(oppositeTextEle);
+ const dotContainer: HTMLElement = this.createElement('div', { className: DOTCONTAINER });
+ const dotEleCss: string = item.dotCss ? DOTCONTENT + ' ' + item.dotCss.trim() : DOTCONTENT;
+ const dotEle: HTMLElement = this.createElement('div', { className: dotEleCss });
+ dotContainer.appendChild(dotEle);
+ timelineItem.appendChild(dotContainer);
+ const contentEle = this.createElement('div', { className: CONTENT });
+ if (item.content){
+ const ctn: string | Function = this.getTemplateFunction(item.content);
+ if (typeof ctn === 'string') {
+ contentEle.innerText = ctn;
+ } else {
+ append(ctn({ item: item, itemIndex: index }), contentEle);
+ }
+ }
+ timelineItem.appendChild(contentEle);
+ if (item.cssClass) { timelineItem.classList.add(...item.cssClass.trim().split(' ')); }
+ if (item.disabled) { timelineItem.classList.add(DISABLED); }
+ }
+ else {
+ this.renderItemContent(index, false, timelineItem);
+ }
+ const eventArgs: TimelineRenderingEventArgs = { element: timelineItem, index: index };
+ this.trigger('beforeItemRender', eventArgs, (args: TimelineRenderingEventArgs) => { this.timelineListEle.appendChild(args.element); });
+
+ }
+ }
+
+ private updateTemplateFunction(): void {
+ this.templateFunction = this.template ? this.getTemplateFunction(this.template, false) as Function : null;
+ }
+
+ private renderItemContent(index: number, isrerender: boolean, timelineItem?: HTMLElement): void {
+ const listItems: NodeListOf = this.timelineListEle.querySelectorAll('li');
+ if (isrerender) {
+ this.removeItemContent(listItems[parseInt((index).toString(), 10)] as HTMLElement);
+ }
+ if (this.template) {
+ isrerender ? listItems[parseInt((index).toString(), 10)].classList.add(TEMPLATE) :
+ timelineItem.classList.add(TEMPLATE);
+ const item: TimelineItemModel = this.items[parseInt(index.toString(), 10)];
+ append(this.templateFunction({ item: item, itemIndex: index }, this, 'timelineTemplate', (this.element.id + '_timelineTemplate'), this.isStringTemplate), isrerender ? listItems[parseInt((index).toString(), 10)] : timelineItem);
+ }
+ this.renderReactTemplates();
+ }
+
+ private removeItemContent(ele: HTMLElement): void {
+ ele.classList.remove(TEMPLATE);
+ const firstChild: HTMLElement = ele.firstElementChild as HTMLElement;
+ for (let i: number = 0; i < ele.childElementCount; i++) {
+ firstChild.remove();
+ }
+ }
+
+ /**
+ * Gets template content based on the template property value.
+ *
+ * @param {string | Function} template - Template property value.
+ * @returns {Function} - Return template function.
+ * @hidden
+ */
+ private getTemplateFunction(template: string | Function, notCompile: boolean = true): string | Function {
+ if (typeof template === 'string') {
+ let content: string = '';
+ try {
+ const tempEle: HTMLElement = select(template);
+ if (tempEle) {
+ //Return innerHTML incase of jsrenderer script else outerHTML
+ content = tempEle.tagName === 'SCRIPT' ? tempEle.innerHTML : tempEle.outerHTML;
+ notCompile = false;
+ } else {
+ content = template;
+ }
+ } catch (e) {
+ content = template;
+ }
+ return notCompile ? content : compile(content);
+ } else {
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ return compile(template as any);
+ }
+ }
+
+ private removeItemElements(): void {
+ const listItems: NodeListOf = this.timelineListEle.querySelectorAll('li');
+ for (let i: number = 0; i < listItems.length; i++) {
+ remove(listItems[parseInt(i.toString(), 10)]);
+ }
+ }
+
+ private updateElementClassArray(): void {
+ const classArray: string[] = [RTL, 'e-align-before', 'e-align-after', 'e-outline', 'e-fill', 'e-align-alternate',
+ 'e-align-alternatereverse', TIMELINEREVERSE, HORIZONTAL, VERTICAL];
+ removeClass([this.element], classArray);
+ }
+
+ private updateContent(): void {
+ if (this.isReact) { this.clearTemplate(['timelineTemplate']); }
+ for (let i: number = 0; i < this.items.length; i++) {
+ this.renderItemContent(i, true);
+ }
+ }
+
+ public destroy(): void {
+ super.destroy();
+ // unwires the events and detach the li elements
+ this.removeItemElements();
+ this.element.removeAttribute("role");
+ this.element.removeAttribute("aria-label");
+ this.clearTemplate();
+ if (this.timelineListEle) { remove(this.timelineListEle); }
+ this.timelineListEle = null;
+ this.updateElementClassArray();
+ }
+
+ /**
+ * Called internally if any of the property value changed.
+ *
+ * @param {TimelineModel} newProp - Specifies new properties
+ * @param {TimelineModel} oldProp - Specifies old properties
+ * @returns {void}
+ * @private
+ */
+ public onPropertyChanged(newProp: TimelineModel, oldProp?: TimelineModel): void {
+ for (const prop of Object.keys(newProp)) {
+ switch (prop) {
+ case 'items': {
+ this.removeItemElements();
+ this.renderItems();
+ break;
+ }
+ case 'orientation':
+ this.updateOrientation();
+ break;
+ case 'align':
+ this.updateAlign();
+ break;
+ case 'enableRtl':
+ this.updateRtl();
+ break;
+ case 'cssClass':
+ this.updateCssClass(newProp.cssClass, oldProp.cssClass);
+ break;
+ case 'reverse':
+ this.element.classList[this.reverse ? 'add' : 'remove'](TIMELINEREVERSE);
+ break;
+ case 'template':
+ this.updateTemplateFunction();
+ this.updateContent();
+ break;
+ }
+ }
+ }
+}
diff --git a/controls/layouts/styles/avatar/_bds-definition.scss b/controls/layouts/styles/avatar/_bds-definition.scss
new file mode 100644
index 0000000000..60f45fff52
--- /dev/null
+++ b/controls/layouts/styles/avatar/_bds-definition.scss
@@ -0,0 +1,32 @@
+// Avatar Base
+$avatar-base-border-radius: 8px !default;
+$avatar-base-background-color: $content-bg-color-alt3 !default;
+$avatar-base-font-size: $text-sm !default;
+$avatar-base-width: 40px !default;
+$avatar-base-height: 40px !default;
+$avatar-base-line-height: 22px !default;
+$avatar-base-text-color: $content-text-color-alt2 !default;
+$avatar-base-font-weight: $font-weight-medium !default;
+$avatar-base-img-height: 100% !default;
+
+// Circle Avatar
+$avatar-circle-border-radius: 50% !default;
+
+// Avatar size
+$avatar-xsmall-font-size: $text-xxs !default;
+$avatar-small-font-size: $text-xs !default;
+$avatar-large-font-size: $text-lg !default;
+$avatar-xlarge-font-size: $text-xl !default;
+
+// Avatar Line Height
+$avatar-base-xsmall-line-height: 16px !default;
+$avatar-base-small-line-height: 18px !default;
+$avatar-base-large-line-height: 28px !default;
+$avatar-base-xlarge-line-height: 28px !default;
+
+//border
+$avatar-border: $avatar-border-color !default;
+
+.e-avatar {
+ border: 1px solid $avatar-border;
+}
diff --git a/controls/layouts/styles/bootstrap-dark.scss b/controls/layouts/styles/bootstrap-dark.scss
index 86b78aee96..91bf827fcf 100644
--- a/controls/layouts/styles/bootstrap-dark.scss
+++ b/controls/layouts/styles/bootstrap-dark.scss
@@ -2,3 +2,4 @@
@import 'card/bootstrap-dark.scss';
@import 'splitter/bootstrap-dark.scss';
@import 'dashboard-layout/bootstrap-dark.scss';
+@import 'timeline/bootstrap-dark.scss';
diff --git a/controls/layouts/styles/bootstrap.scss b/controls/layouts/styles/bootstrap.scss
index 743dc105ea..0d75254e48 100644
--- a/controls/layouts/styles/bootstrap.scss
+++ b/controls/layouts/styles/bootstrap.scss
@@ -2,3 +2,4 @@
@import 'card/bootstrap.scss';
@import 'splitter/bootstrap.scss';
@import 'dashboard-layout/bootstrap.scss';
+@import 'timeline/bootstrap.scss';
diff --git a/controls/layouts/styles/bootstrap4.scss b/controls/layouts/styles/bootstrap4.scss
index 9eb19329ac..652ea44e7f 100644
--- a/controls/layouts/styles/bootstrap4.scss
+++ b/controls/layouts/styles/bootstrap4.scss
@@ -2,3 +2,4 @@
@import 'card/bootstrap4.scss';
@import 'splitter/bootstrap4.scss';
@import 'dashboard-layout/bootstrap4.scss';
+@import 'timeline/bootstrap4.scss';
diff --git a/controls/layouts/styles/bootstrap5-dark.scss b/controls/layouts/styles/bootstrap5-dark.scss
index 312b75d869..9e20ef2b1b 100644
--- a/controls/layouts/styles/bootstrap5-dark.scss
+++ b/controls/layouts/styles/bootstrap5-dark.scss
@@ -2,3 +2,4 @@
@import 'card/bootstrap5-dark.scss';
@import 'splitter/bootstrap5-dark.scss';
@import 'dashboard-layout/bootstrap5-dark.scss';
+@import 'timeline/bootstrap5-dark.scss';
diff --git a/controls/layouts/styles/bootstrap5.scss b/controls/layouts/styles/bootstrap5.scss
index b376db493a..9dcf752280 100644
--- a/controls/layouts/styles/bootstrap5.scss
+++ b/controls/layouts/styles/bootstrap5.scss
@@ -2,3 +2,4 @@
@import 'card/bootstrap5.scss';
@import 'splitter/bootstrap5.scss';
@import 'dashboard-layout/bootstrap5.scss';
+@import 'timeline/bootstrap5.scss';
diff --git a/controls/layouts/styles/card/_bds-definition.scss b/controls/layouts/styles/card/_bds-definition.scss
new file mode 100644
index 0000000000..dec2091893
--- /dev/null
+++ b/controls/layouts/styles/card/_bds-definition.scss
@@ -0,0 +1,123 @@
+//Layout Variables Start
+$card-img-brdr-radious: 50% !default;
+$card-brdr-radious: 6px !default;
+$card-action-btn-txt-transform: none !default;
+
+// Font
+$card-header-font: $text-sm !default;
+$card-title-font: 16px !default;
+$card-action-btn-icon-font: $text-sm !default;
+$card-action-btn-font: $text-sm !default;
+$card-content-font-size: $text-sm !default;
+$card-content-bigger-font-size: $text-base !default;
+$card-header-title-font: $text-sm !default;
+$card-header-sub-title-font: $text-sm !default;
+
+// Mouse
+$card-content-line-height: $leading-normal !default;
+$card-nrml-lheight: 24px !default;
+$card-nrml-mheight: 36px !default;
+$card-header-padding: 18px !default;
+$card-header-lheight: $leading-tight !default;
+$card-title-nrml-padding: 18px !default;
+$card-title-nrml-lheight: $leading-normal !default;
+$card-hor-image-margin: 2px !default;
+$card-sep-margin: 12px 0 !default;
+$card-header-minheight: 22.5px !default;
+$card-header-nrml-padding: 18px 18px 12px 18px !default;
+$card-header-txt-nrml-padding: 0 0 0 18px !default;
+$card-header-txt-title-lheight: $leading-normal !default;
+$card-header-txt-title-nrml-padding: 2px 0 0 !default;
+$card-header-txt-subtitle-lheight: $leading-normal !default;
+$card-header-image-width: 46px !default;
+$card-header-image-height: 46px !default;
+$card-image-mheight: 112.5px !default;
+$card-image-title-lheight: 30px !default;
+$card-image-title-mheight: 30px !default;
+$card-action-nrml-vertical-padding: 18px 18px !default;
+$card-action-nrml-btn-vertical-margin: 0 0 6px 0 !default;
+$card-action-btn-nrml-height: 30px !default;
+$card-action-btn-nrml-margin: 0 0 0 6px !default;
+$card-action-btn-nrml-padding: 0 6px !default;
+$card-nrml-content-padding: 0 18px 12px 18px !default;
+$card-header-txt-nrml-title-font: $text-sm !default;
+$card-header-txt-nrml-subtitle-font: $text-sm !default;
+$card-image-title-font: $text-base !default;
+$card-action-btn-icon-width: 24px !default; //Need to check UI
+$card-action-btn-icon-height: 24px !default; //Need to check UI
+// Touch
+$card-bigger-lheight: 48px !default;
+$card-bigger-mheight: 48px !default;
+$card-header-bigger-padding: 24px 24px 16px 24px !default;
+$card-header-bigger-lheight: $leading-normal !default;
+$card-title-bigger-margin: 8px 24px 16px 24px !default;
+$card-title-bigger-lheight: $leading-normal !default;
+$card-hor-image-bigger-margin: 2px !default;
+$card-sep-bigger-margin: 16px 0 !default;
+$card-header-bigger-minheight: 30px !default;
+$card-header-bigger-padding: 24px !default;
+$card-header-txt-bigger-padding: 0 0 0 24px !default;
+$card-header-txt-title-bigger-lheight: $leading-normal !default;
+$card-header-txt-title-bigger-padding: 4px 0 0 !default;
+$card-header-txt-subtitle-bigger-lheight: $leading-normal !default;
+$card-header-image-bigger-width: 46px !default;
+$card-header-image-bigger-height: 50px !default;
+$card-image-bigger-mheight: 150px !default;
+$card-image-title-bigger-lheight: $leading-tight !default; //Need to check UI
+$card-image-title-bigger-mheight: 40px !default; //Need to check UI
+$card-img-title-bigger-padding: 12px 16px !default;
+$card-action-bigger-padding: 24px 24px !default;
+$card-action-bigger-vertical-padding: 12px 24px 24px 24px !default;
+$card-action-bigger-btn-vertical-margin: 0 0 8px 0 !default;//Need to check UI
+$card-action-btn-bigger-height: 38px !default;
+$card-action-btn-bigger-margin: 0 0 0 8px !default;
+$card-action-btn-bigger-padding: 0 6px !default;
+$card-bigger-content-padding: 0 24px 16px 24px !default;
+$card-header-txt-bigger-title-font: $text-sm !default;
+$card-header-txt-bigger-subtitle-font: $text-base !default;
+$card-image-title-bigger-font: 18px !default;
+$card-action-btn-bigger-icon-width: 24px !default; //Need to chek UI
+$card-action-btn-bigger-icon-height: 24px !default; //Need to check UI
+$card-image-title-nrml-padding: 8px 16px !default;
+$card-action-nrml-padding: 18px 18px !default;
+$card-highlight-color: $primary !default;
+
+//Layout Variables End
+
+//Theme Variables Start
+$card-bg-color: $content-bg-color !default;
+$card-focus-bg-color: $content-bg-color-alt2 !default;
+$card-hover-bg-color: $content-bg-color-alt2 !default;
+$card-active-bg-color: $content-bg-color-alt2 !default;
+$card-focus-brdr-color: $border-light !default;
+$card-hover-brdr-color: $border-light !default;
+$card-active-brdr-color: $border-light !default;
+$card-brdr-size: 1px !default;
+$card-brdr-type: solid !default;
+$card-brdr-color: $border-light !default;
+$card-sep-brdr-size: 1px !default;
+$card-sep-brdr-type: solid !default;
+$card-sep-brdr-color: $border-light !default;
+$card-image-title-color: $content-text-color !default;
+$card-image-title-bg: $overlay-bg-color !default;
+$card-action-btn-bg-color: $transparent !default;
+$card-action-btn-font-color: $primary !default;
+$card-action-btn-border: 1px solid $primary !default;
+$card-action-btn-hover-bg: $primary !default;
+$card-action-btn-hover-border: 1px solid $secondary-border-color-hover !default;
+$card-action-btn-hover-font: $white !default;
+$card-action-btn-focus-bg: $secondary-bg-color-focus !default;
+$card-action-btn-focus-border: 1px solid !default;
+$card-action-btn-focus-font: $secondary-text-color-focus !default;
+$card-action-btn-pressed-bg: $secondary-bg-color-pressed !default;
+$card-action-btn-pressed-border: 1px solid $secondary-border-color-pressed !default;
+$card-action-btn-pressed-font: $secondary-text-color-pressed !default;
+$card-font-color: $content-text-color !default;
+$card-header-txt-title-color: $content-text-color !default;
+$card-header-txt-subtitle-color: $content-text-color-alt2 !default;
+$card-content-font-color: $content-text-color-alt1 !default;
+$card-box-shadow: $shadow !default;
+$card-action-btn-icon-color: $primary !default; //Doubt
+$card-hover-box-shadow: $shadow !default;
+
+//Theme Variables End
diff --git a/controls/layouts/styles/card/_layout.scss b/controls/layouts/styles/card/_layout.scss
index 19259da124..6c5a120500 100644
--- a/controls/layouts/styles/card/_layout.scss
+++ b/controls/layouts/styles/card/_layout.scss
@@ -177,14 +177,14 @@
&:hover {
@if $skin-name == 'fabric' or $skin-name == 'highcontrast' {
- border-width: 2px;
+ border-width: 1px;
padding: 1px;
}
}
&:active {
@if $skin-name == 'fabric' or $skin-name == 'highcontrast' {
- border-width: 2px;
+ border-width: 1px;
padding: 0;
}
}
diff --git a/controls/layouts/styles/card/_theme.scss b/controls/layouts/styles/card/_theme.scss
index 27dd12f981..a3f04226c0 100644
--- a/controls/layouts/styles/card/_theme.scss
+++ b/controls/layouts/styles/card/_theme.scss
@@ -61,25 +61,45 @@
.e-card-btn,
a {
- background-color: $card-action-btn-bg-color;
+ @if $skin-name == 'Material3' {
+ background: $card-action-btn-bg-color;
+ }
+ @else {
+ background-color: $card-action-btn-bg-color;
+ }
border: $card-action-btn-border;
color: $card-action-btn-font-color;
outline: 0;
&:hover {
- background-color: $card-action-btn-hover-bg;
+ @if $skin-name == 'Material3' {
+ background: $card-action-btn-hover-bg;
+ }
+ @else {
+ background-color: $card-action-btn-hover-bg;
+ }
border: $card-action-btn-hover-border;
color: $card-action-btn-hover-font;
}
&:focus {
- background-color: $card-action-btn-focus-bg;
+ @if $skin-name == 'Material3' {
+ background: $card-action-btn-focus-bg;
+ }
+ @else {
+ background-color: $card-action-btn-focus-bg;
+ }
border: $card-action-btn-focus-border;
color: $card-action-btn-focus-font;
}
&:active {
- background-color: $card-action-btn-pressed-bg;
+ @if $skin-name == 'Material3' {
+ background: $card-action-btn-pressed-bg;
+ }
+ @else {
+ background-color: $card-action-btn-pressed-bg;
+ }
border: $card-action-btn-pressed-border;
color: $card-action-btn-pressed-font;
}
diff --git a/controls/layouts/styles/dashboard-layout/_bds-definition.scss b/controls/layouts/styles/dashboard-layout/_bds-definition.scss
new file mode 100644
index 0000000000..07fd690672
--- /dev/null
+++ b/controls/layouts/styles/dashboard-layout/_bds-definition.scss
@@ -0,0 +1,109 @@
+/*! component's theme wise override tailwind-definitions and variables */
+
+// Generic
+$icon-zero: 0 !default;
+$icon-border-radius: 50% !default;
+$grid-layout-position: relative !default;
+$panel-position: absolute !default;
+$panel-box-sizing: border-box !default;
+
+// Header styles
+
+// Mouse
+$panel-header-height: 38px !default;
+$panel-header-padding: 8px 18px !default;
+$panel-header-line-height: 22px !default;
+$panel-header-bg-color: $content-bg-color-alt1 !default;
+$panel-header-color: $content-text-color !default;
+$panel-header-font-size: $text-sm !default;
+$panel-header-font-weight: $font-weight-medium !default;
+$panel-header-border-bottom: none !default;
+$panel-header-border-radius: 6px !default;
+$panel-header-font-family: $font-family !default;
+$panel-header-white-space: nowrap !default;
+$panel-header-overflow: hidden !default;
+$panel-header-text-overflow: ellipsis !default;
+
+// Touch
+$panel-bigger-header-height: 40px !default;
+$panel-bigger-header-padding: 8px 18px !default;
+$panel-bigger-header-line-height: 24px !default;
+$panel-bigger-header-color: $content-text-color !default;
+$panel-bigger-header-font-size: $text-base !default;
+$panel-bigger-header-font-weight: $font-weight-medium !default;
+$panel-bigger-content-padding: 16px !default;
+
+// Panel styles
+$panel-border: 1px solid $border-light !default;
+$panel-border-radius: 6px !default;
+$panel-full-height: 100% !default;
+$panel-full-width: 100% !default;
+$panel-hover-border: 1px solid $border-dark !default;
+$panel-active-border: 1px solid $primary-border-color !default;
+$panel-content-padding: 12px !default;
+
+// icons styles
+$panel-resize-one-dimensional-icon-height: 8px !default;
+$panel-resize-one-dimensional-icon-width: 8px !default;
+$panel-resize-one-dimensional-icon-background: none !default;
+$panel-resize-one-dimensional-icon-border: none !default;
+$panel-resize-one-dimensional-icon-shadow: none !default;
+
+$panel-resize-two-dimensional-icon-height: 8px !default;
+$panel-resize-two-dimensional-icon-width: 8px !default;
+$panel-resize-two-dimensional-inner-icon-height: 8px !default;
+$panel-resize-two-dimensional-inner-icon-width: 8px !default;
+$panel-resize-two-dimensional-icon-background: none !default;
+$panel-resize-two-dimensional-icon-color: $icon-color-disabled !default;
+$panel-resize-two-dimensional-icon-border: none !default;
+$panel-resize-two-dimensional-icon-shadow: none !default;
+
+// south-east-icon-styles
+$panel-south-east-icon-right: 2px !default;
+$panel-south-east-icon-bottom: 2px !default;
+
+// south-west-icon-style
+$panel-south-west-icon-left: 2px !default;
+$panel-south-west-icon-bottom: 2px !default;
+
+// north-east-icon-styles
+$panel-north-east-icon-right: 2px !default;
+$panel-north-east-icon-top: 2px !default;
+
+// north-west-icon-styles
+$panel-north-west-icon-left: 2px !default;
+$panel-north-west-icon-top: 2px !default;
+
+// droppable area border
+$panel-drop-border-radius: 6px !default;
+
+// dragging element style
+$panel-dragging-cursor: move !default;
+$panel-drag-prevent: none !default;
+
+// Blazor ContentTemplate styles
+$panel-content-template-height: inherit !default;
+$panel-content-template-width: inherit !default;
+
+/* stylelint-disable */
+$panel-dragging-zindex: 1111 !important !default;
+$panel-drag-prevent: none !default;
+
+$element-width-complete: 100% !important !default;
+
+// colors
+
+// Panel styles
+$panel-active-background: $content-bg-color-alt2 !default;
+$panel-hover-box-shadow: $shadow-lg !default;
+$panel-active-drag-box-shadow: $shadow !default;
+$panel-background: $content-bg-color !default;
+$panel-box-shadow: $shadow;
+
+// droppable area border
+$panel-drop-background: $content-bg-color-alt3 !default;
+$panel-drop-border: 1px $border-dark dashed !default;
+
+//gridlines
+$gridline-background: $content-bg-color-alt1 !default;
+$gridline-border: $border !default;
diff --git a/controls/layouts/styles/dashboard-layout/icons/_bds.scss b/controls/layouts/styles/dashboard-layout/icons/_bds.scss
new file mode 100644
index 0000000000..f4de358297
--- /dev/null
+++ b/controls/layouts/styles/dashboard-layout/icons/_bds.scss
@@ -0,0 +1,80 @@
+@include export-module('dashboardlayout-bds-icons') {
+ .e-dashboardlayout.e-control {
+ & .e-panel {
+
+ & .e-resize.e-single,
+ & .e-resize.e-double {
+ &.e-east {
+ height: 100%;
+ padding: 20px 0;
+ right: 1px;
+ top: 0;
+ width: 12px;
+ }
+
+ &.e-west {
+ height: 100%;
+ left: 0;
+ padding: 20px 0;
+ top: 0;
+ width: 12px;
+ }
+
+ &.e-north {
+ height: 12px;
+ padding: 0 20px;
+ top: 1px;
+ width: 100%;
+ }
+
+ &.e-south {
+ bottom: 1px;
+ height: 12px;
+ padding: 0 20px;
+ width: 100%;
+ }
+
+ &.e-south-east {
+ bottom: 0;
+ right: 1px;
+ z-index: 10;
+ }
+
+ &.e-north-west {
+ left: 2px;
+ top: 2px;
+ z-index: 10;
+ }
+
+ &.e-north-east {
+ right: 2px;
+ top: 2px;
+ z-index: 10;
+ }
+
+ &.e-south-west {
+ bottom: 1px;
+ left: 1px;
+ z-index: 10;
+ }
+
+ &.e-south-east::before {
+ bottom: 4px;
+ content: '\e761';
+ font-size: 12px;
+ position: absolute;
+ right: 4px;
+ }
+
+ &.e-south-west::before {
+ bottom: 4px;
+ content: '\e761';
+ font-size: 12px;
+ left: 4px;
+ position: absolute;
+ transform: rotateY(180deg);
+ }
+ }
+ }
+ }
+}
diff --git a/controls/layouts/styles/fabric-dark.scss b/controls/layouts/styles/fabric-dark.scss
index c1d36397b8..4de7155757 100644
--- a/controls/layouts/styles/fabric-dark.scss
+++ b/controls/layouts/styles/fabric-dark.scss
@@ -2,3 +2,4 @@
@import 'card/fabric-dark.scss';
@import 'splitter/fabric-dark.scss';
@import 'dashboard-layout/fabric-dark.scss';
+@import 'timeline/fabric-dark.scss';
diff --git a/controls/layouts/styles/fabric.scss b/controls/layouts/styles/fabric.scss
index b1eebe4061..e1c3db6c8f 100644
--- a/controls/layouts/styles/fabric.scss
+++ b/controls/layouts/styles/fabric.scss
@@ -2,3 +2,4 @@
@import 'card/fabric.scss';
@import 'splitter/fabric.scss';
@import 'dashboard-layout/fabric.scss';
+@import 'timeline/fabric.scss';
diff --git a/controls/layouts/styles/fluent-dark.scss b/controls/layouts/styles/fluent-dark.scss
index f4006cffe5..b5a569beb9 100644
--- a/controls/layouts/styles/fluent-dark.scss
+++ b/controls/layouts/styles/fluent-dark.scss
@@ -2,3 +2,4 @@
@import 'card/fluent-dark.scss';
@import 'splitter/fluent-dark.scss';
@import 'dashboard-layout/fluent-dark.scss';
+@import 'timeline/fluent-dark.scss';
diff --git a/controls/layouts/styles/fluent.scss b/controls/layouts/styles/fluent.scss
index 626403675d..bf9617dbaf 100644
--- a/controls/layouts/styles/fluent.scss
+++ b/controls/layouts/styles/fluent.scss
@@ -2,3 +2,4 @@
@import 'card/fluent.scss';
@import 'splitter/fluent.scss';
@import 'dashboard-layout/fluent.scss';
+@import 'timeline/fluent.scss';
diff --git a/controls/layouts/styles/highcontrast-light.scss b/controls/layouts/styles/highcontrast-light.scss
index 235335b7d3..796450f169 100644
--- a/controls/layouts/styles/highcontrast-light.scss
+++ b/controls/layouts/styles/highcontrast-light.scss
@@ -2,3 +2,4 @@
@import 'card/highcontrast-light.scss';
@import 'splitter/highcontrast-light.scss';
@import 'dashboard-layout/highcontrast-light.scss';
+@import 'timeline/highcontrast-light.scss';
diff --git a/controls/layouts/styles/highcontrast.scss b/controls/layouts/styles/highcontrast.scss
index 06d8eddc61..afeb425280 100644
--- a/controls/layouts/styles/highcontrast.scss
+++ b/controls/layouts/styles/highcontrast.scss
@@ -2,3 +2,4 @@
@import 'card/highcontrast.scss';
@import 'splitter/highcontrast.scss';
@import 'dashboard-layout/highcontrast.scss';
+@import 'timeline/highcontrast.scss';
diff --git a/controls/layouts/styles/material-dark.scss b/controls/layouts/styles/material-dark.scss
index 8b69150f0f..80da9957d1 100644
--- a/controls/layouts/styles/material-dark.scss
+++ b/controls/layouts/styles/material-dark.scss
@@ -2,3 +2,4 @@
@import 'card/material-dark.scss';
@import 'splitter/material-dark.scss';
@import 'dashboard-layout/material-dark.scss';
+@import 'timeline/material-dark.scss';
diff --git a/controls/layouts/styles/material.scss b/controls/layouts/styles/material.scss
index 7542594b55..dcc57aa65b 100644
--- a/controls/layouts/styles/material.scss
+++ b/controls/layouts/styles/material.scss
@@ -2,3 +2,4 @@
@import 'card/material.scss';
@import 'splitter/material.scss';
@import 'dashboard-layout/material.scss';
+@import 'timeline/material.scss';
diff --git a/controls/layouts/styles/material3-dark.scss b/controls/layouts/styles/material3-dark.scss
index 01f3b57e63..33812b9eff 100644
--- a/controls/layouts/styles/material3-dark.scss
+++ b/controls/layouts/styles/material3-dark.scss
@@ -4,3 +4,4 @@
@import 'card/material3-dark.scss';
@import 'splitter/material3-dark.scss';
@import 'dashboard-layout/material3-dark.scss';
+@import 'timeline/material3-dark.scss';
diff --git a/controls/layouts/styles/material3.scss b/controls/layouts/styles/material3.scss
index 2dead8ad6b..e2b264cb30 100644
--- a/controls/layouts/styles/material3.scss
+++ b/controls/layouts/styles/material3.scss
@@ -4,3 +4,4 @@
@import 'card/material3.scss';
@import 'splitter/material3.scss';
@import 'dashboard-layout/material3.scss';
+@import 'timeline/material3.scss';
diff --git a/controls/layouts/styles/splitter/_bds-definition.scss b/controls/layouts/styles/splitter/_bds-definition.scss
new file mode 100644
index 0000000000..ccc513b2f7
--- /dev/null
+++ b/controls/layouts/styles/splitter/_bds-definition.scss
@@ -0,0 +1,31 @@
+//Layout Variables Start
+$splitpane-font-size: $text-sm !default;
+$splitpane-font-weight: $font-weight-normal !default;
+$splitpane-font-family: $font-family !default;
+$splitbar-icon-size: 14px !default;
+$splitbar-icon-gap: 18px !default;
+$bigger-splitbar-icon-gap: 20px !default;
+$bigger-splitpane-font-size: $text-base !default;
+$bigger-splitbar-icon-size: 16px !default;
+
+//Layout Variables End
+
+//Theme Variables Start
+$navigation-arrow-background: $transparent !default;
+$navigation-icon-background-hover: $primary !default;
+$navigation-icon-border-hover: $primary !default;
+$splitter-border-color: $border-light !default;
+$splitter-background-color: $primary-text-color !default;
+$splitpane-font-color: $content-text-color !default;
+$splitbar-border-color: $border-light !default;
+$splitbar-hover-border-color: $primary !default;
+$resize-icon-hover-color: $splitbar-hover-border-color !default;
+$splitbar-icon-color: $icon-color !default;
+$collapse-icon-bg-color: $primary-text-color !default;
+$resize-icon-bg-color: $content-bg-color !default;
+$split-bar-border-left: 1px solid $border-light !default;
+$split-bar-border-right: 1px solid $border-light !default;
+$split-bar-hover-border-left: 1px solid $splitbar-hover-border-color !default;
+$split-bar-hover-border-right: 1px solid $splitbar-hover-border-color !default;
+
+//Theme Variables End
diff --git a/controls/layouts/styles/splitter/icons/_bds.scss b/controls/layouts/styles/splitter/icons/_bds.scss
new file mode 100644
index 0000000000..503910e25b
--- /dev/null
+++ b/controls/layouts/styles/splitter/icons/_bds.scss
@@ -0,0 +1,39 @@
+@include export-module('splitter-material-icons') {
+ .e-splitter {
+ .e-split-bar {
+ &.e-split-bar-horizontal {
+ .e-resize-handler::before {
+ content: '\e7e3';
+ font-family: 'e-icons';
+ font-size: $splitbar-icon-size;
+ }
+ }
+
+ &.e-split-bar-vertical {
+ & .e-resize-handler::before {
+ content: '\e7fd';
+ font-family: 'e-icons';
+ font-size: $splitbar-icon-size;
+ }
+ }
+ }
+ }
+
+ .e-bigger {
+ .e-splitter {
+ .e-split-bar {
+ .e-resize-handler::before {
+ font-size: $bigger-splitbar-icon-size;
+ }
+ }
+ }
+
+ &.e-splitter {
+ .e-split-bar {
+ .e-resize-handler::before {
+ font-size: $bigger-splitbar-icon-size;
+ }
+ }
+ }
+ }
+}
diff --git a/controls/layouts/styles/tailwind-dark.scss b/controls/layouts/styles/tailwind-dark.scss
index 609e92a91d..215bd1f88e 100644
--- a/controls/layouts/styles/tailwind-dark.scss
+++ b/controls/layouts/styles/tailwind-dark.scss
@@ -2,3 +2,4 @@
@import 'card/tailwind-dark.scss';
@import 'splitter/tailwind-dark.scss';
@import 'dashboard-layout/tailwind-dark.scss';
+@import 'timeline/tailwind-dark.scss';
diff --git a/controls/layouts/styles/tailwind.scss b/controls/layouts/styles/tailwind.scss
index fd0ec885d2..8389299e52 100644
--- a/controls/layouts/styles/tailwind.scss
+++ b/controls/layouts/styles/tailwind.scss
@@ -2,3 +2,4 @@
@import 'card/tailwind.scss';
@import 'splitter/tailwind.scss';
@import 'dashboard-layout/tailwind.scss';
+@import 'timeline/tailwind.scss';
diff --git a/controls/layouts/styles/timeline/_all.scss b/controls/layouts/styles/timeline/_all.scss
new file mode 100644
index 0000000000..a0fe77dcde
--- /dev/null
+++ b/controls/layouts/styles/timeline/_all.scss
@@ -0,0 +1,2 @@
+@import 'layout.scss';
+@import 'theme.scss';
diff --git a/controls/layouts/styles/timeline/_bds-definition.scss b/controls/layouts/styles/timeline/_bds-definition.scss
new file mode 100644
index 0000000000..8b1b27447c
--- /dev/null
+++ b/controls/layouts/styles/timeline/_bds-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $content-text-color-alt2 !default;
+$timeline-dot-background-color: $content-bg-color !default;
+$timeline-dot-border-color: rgba($border-light) !default;
+$timeline-content-font-color: $content-text-color !default;
+$timeline-opposite-content-font-color: $content-text-color-alt1 !default;
+$timeline-item-disabled-color: $content-text-color-disabled !default;
diff --git a/controls/layouts/styles/timeline/_bootstrap-dark-definition.scss b/controls/layouts/styles/timeline/_bootstrap-dark-definition.scss
new file mode 100644
index 0000000000..13f13f08da
--- /dev/null
+++ b/controls/layouts/styles/timeline/_bootstrap-dark-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $grey-dark-font !default;
+$timeline-dot-background-color: $gray-light !default;
+$timeline-dot-border-color: $grey-ad !default;
+$timeline-content-font-color: $grey-dark-font !default;
+$timeline-opposite-content-font-color: $grey-dark-font !default;
+$timeline-item-disabled-color: $grey-lighter !default;
diff --git a/controls/layouts/styles/timeline/_bootstrap-definition.scss b/controls/layouts/styles/timeline/_bootstrap-definition.scss
new file mode 100644
index 0000000000..cbcecf0bfe
--- /dev/null
+++ b/controls/layouts/styles/timeline/_bootstrap-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $grey-light-font !default;
+$timeline-dot-background-color: $grey-white !default;
+$timeline-dot-border-color: $grey-e6 !default;
+$timeline-content-font-color: $grey-light-font !default;
+$timeline-opposite-content-font-color: $grey-light-font !default;
+$timeline-item-disabled-color: $grey-ad !default;
diff --git a/controls/layouts/styles/timeline/_bootstrap4-definition.scss b/controls/layouts/styles/timeline/_bootstrap4-definition.scss
new file mode 100644
index 0000000000..0dbd5c14a7
--- /dev/null
+++ b/controls/layouts/styles/timeline/_bootstrap4-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $gray-700 !default;
+$timeline-dot-background-color: $white !default;
+$timeline-dot-border-color: $gray-300 !default;
+$timeline-content-font-color: $gray-900 !default;
+$timeline-opposite-content-font-color: $gray-900 !default;
+$timeline-item-disabled-color: $gray-500 !default;
diff --git a/controls/layouts/styles/timeline/_bootstrap5-dark-definition.scss b/controls/layouts/styles/timeline/_bootstrap5-dark-definition.scss
new file mode 100644
index 0000000000..941247df8f
--- /dev/null
+++ b/controls/layouts/styles/timeline/_bootstrap5-dark-definition.scss
@@ -0,0 +1 @@
+@import './bootstrap5-definition.scss';
diff --git a/controls/layouts/styles/timeline/_bootstrap5-definition.scss b/controls/layouts/styles/timeline/_bootstrap5-definition.scss
new file mode 100644
index 0000000000..c7fb45ae11
--- /dev/null
+++ b/controls/layouts/styles/timeline/_bootstrap5-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $content-text-color !default;
+$timeline-dot-background-color: $content-bg-color !default;
+$timeline-dot-border-color: $border-light !default;
+$timeline-content-font-color: $content-text-color-alt1 !default;
+$timeline-opposite-content-font-color: $content-text-color-alt2 !default;
+$timeline-item-disabled-color: $content-text-color-disabled !default;
diff --git a/controls/layouts/styles/timeline/_fabric-dark-definition.scss b/controls/layouts/styles/timeline/_fabric-dark-definition.scss
new file mode 100644
index 0000000000..d2e768f4ca
--- /dev/null
+++ b/controls/layouts/styles/timeline/_fabric-dark-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $base-font !default;
+$timeline-dot-background-color: $neutral-white !default;
+$timeline-dot-border-color: $neutral-tertiary-alt !default;
+$timeline-content-font-color: $neutral-light-font !default;
+$timeline-opposite-content-font-color: $neutral-light-font !default;
+$timeline-item-disabled-color: $neutral-tertiary-alt !default;
diff --git a/controls/layouts/styles/timeline/_fabric-definition.scss b/controls/layouts/styles/timeline/_fabric-definition.scss
new file mode 100644
index 0000000000..7c394d672d
--- /dev/null
+++ b/controls/layouts/styles/timeline/_fabric-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $base-font !default;
+$timeline-dot-background-color: $neutral-white !default;
+$timeline-dot-border-color: $neutral-quintenaryalt !default;
+$timeline-content-font-color: $theme-light-font !default;
+$timeline-opposite-content-font-color: $theme-light-font !default;
+$timeline-item-disabled-color: $neutral-tertiary !default;
diff --git a/controls/layouts/styles/timeline/_fluent-dark-definition.scss b/controls/layouts/styles/timeline/_fluent-dark-definition.scss
new file mode 100644
index 0000000000..0548f68542
--- /dev/null
+++ b/controls/layouts/styles/timeline/_fluent-dark-definition.scss
@@ -0,0 +1 @@
+@import './fluent-definition.scss';
diff --git a/controls/layouts/styles/timeline/_fluent-definition.scss b/controls/layouts/styles/timeline/_fluent-definition.scss
new file mode 100644
index 0000000000..881f23cdbc
--- /dev/null
+++ b/controls/layouts/styles/timeline/_fluent-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $content-text-color !default;
+$timeline-dot-background-color: $content-bg-color !default;
+$timeline-dot-border-color: $border-light !default;
+$timeline-content-font-color: $content-text-color-alt1 !default;
+$timeline-opposite-content-font-color: $content-text-color-alt1 !default;
+$timeline-item-disabled-color: $content-text-color-disabled !default;
diff --git a/controls/layouts/styles/timeline/_fusionnew-definition.scss b/controls/layouts/styles/timeline/_fusionnew-definition.scss
new file mode 100644
index 0000000000..881f23cdbc
--- /dev/null
+++ b/controls/layouts/styles/timeline/_fusionnew-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $content-text-color !default;
+$timeline-dot-background-color: $content-bg-color !default;
+$timeline-dot-border-color: $border-light !default;
+$timeline-content-font-color: $content-text-color-alt1 !default;
+$timeline-opposite-content-font-color: $content-text-color-alt1 !default;
+$timeline-item-disabled-color: $content-text-color-disabled !default;
diff --git a/controls/layouts/styles/timeline/_highcontrast-definition.scss b/controls/layouts/styles/timeline/_highcontrast-definition.scss
new file mode 100644
index 0000000000..025ec5d6a4
--- /dev/null
+++ b/controls/layouts/styles/timeline/_highcontrast-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $content-font !default;
+$timeline-dot-background-color: $bg-base-0 !default;
+$timeline-dot-border-color: $border-alt !default;
+$timeline-content-font-color: $content-font !default;
+$timeline-opposite-content-font-color: $content-font !default;
+$timeline-item-disabled-color: $selection-bg !default;
diff --git a/controls/layouts/styles/timeline/_highcontrast-light-definition.scss b/controls/layouts/styles/timeline/_highcontrast-light-definition.scss
new file mode 100644
index 0000000000..025ec5d6a4
--- /dev/null
+++ b/controls/layouts/styles/timeline/_highcontrast-light-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $content-font !default;
+$timeline-dot-background-color: $bg-base-0 !default;
+$timeline-dot-border-color: $border-alt !default;
+$timeline-content-font-color: $content-font !default;
+$timeline-opposite-content-font-color: $content-font !default;
+$timeline-item-disabled-color: $selection-bg !default;
diff --git a/controls/layouts/styles/timeline/_layout.scss b/controls/layouts/styles/timeline/_layout.scss
new file mode 100644
index 0000000000..d55256c19a
--- /dev/null
+++ b/controls/layouts/styles/timeline/_layout.scss
@@ -0,0 +1,273 @@
+@include export-module('timeline-layout') {
+ .e-timeline {
+ --dot-size: #{$timeline-dot-size};
+ --dot-outer-space: 0;
+ --dot-border: 1px;
+ --connector-size: 1px;
+ --dot-radius: 50%;
+ height: inherit;
+ width: 100%;
+
+ [class ^= 'e-dot ']::before,
+ .e-dot-item,
+ .e-dot {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ [class ^= 'e-dot ']::before {
+ min-width: $timeline-dot-icon-size;
+ min-height: $timeline-dot-icon-size;
+ border-radius: var(--dot-radius);
+ }
+
+ .e-timeline-items {
+ display: inline-flex;
+ flex-direction: column;
+ list-style: none;
+ flex-wrap: nowrap;
+ padding: 0;
+ width: inherit;
+ height: inherit;
+ }
+
+ .e-timeline-item {
+ display: flex;
+ flex-direction: row;
+ position: relative;
+ align-items: flex-start;
+ width: inherit;
+ height: inherit;
+ }
+
+ .e-timeline-item.e-connector::after {
+ top: 0;
+ bottom: 0;
+ left: calc(50% - var(--connector-size));
+ right: auto;
+ content: '';
+ position: absolute;
+ z-index: 999;
+ border-width: var(--connector-size);
+ border-style: solid;
+ }
+
+ .e-timeline-item.e-connector.e-item-template::after {
+ content: unset;
+ }
+
+ .e-dot-item {
+ position: relative;
+ flex: 0 1 calc(var(--dot-size) * 3);
+ z-index: 1000;
+ }
+
+ .e-dot {
+ min-width: var(--dot-size);
+ min-height: var(--dot-size);
+ border-radius: var(--dot-radius);
+ outline: var(--dot-outer-space) solid;
+ border: var(--dot-border) solid;
+ font-size: $timeline-dot-font-size;
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
+
+ .e-opposite-content,
+ .e-content {
+ flex: 1 1 50%;
+ }
+
+ .e-opposite-content {
+ font-size: $timeline-opposite-content-font-size;
+ text-align: right;
+ }
+
+ .e-content {
+ text-align: left;
+ font-size: $timeline-content-font-size;
+ font-weight: 500;
+ }
+
+ .e-timeline-item:first-child::after {
+ top: 0;
+ }
+
+ .e-timeline-item:last-child::after {
+ bottom: calc(var(--dot-size) * 2);
+ }
+
+ &.e-vertical {
+
+ &.e-align-before .e-timeline-item,
+ &.e-align-alternate .e-timeline-item:nth-of-type(even),
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) {
+ flex-direction: row-reverse;
+ }
+
+ &.e-timeline-reverse .e-timeline-items {
+ flex-direction: column-reverse;
+ }
+
+ &.e-align-before .e-timeline-items .e-opposite-content,
+ &.e-align-after .e-timeline-items .e-content {
+ text-align: left;
+ }
+
+ .e-timeline-item.e-connector:last-child::after {
+ content: unset;
+ }
+
+ &.e-timeline-reverse {
+ .e-timeline-item.e-connector:first-child::after {
+ content: unset;
+ }
+
+ .e-timeline-item.e-connector:last-child::after {
+ content: '';
+ bottom: 0;
+ }
+ }
+
+ &.e-align-after .e-opposite-content,
+ &.e-align-before .e-content,
+ &.e-rtl.e-align-after .e-content,
+ &.e-rtl.e-align-alternate .e-timeline-item:nth-of-type(odd) .e-content,
+ &.e-rtl.e-align-alternatereverse .e-timeline-item:nth-of-type(even) .e-content,
+ &.e-align-alternate .e-timeline-item:nth-of-type(even) .e-content,
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) .e-content,
+ &.e-rtl.e-align-alternate .e-timeline-item:nth-of-type(even) .e-opposite-content,
+ &.e-rtl.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) .e-opposite-content,
+ &.e-rtl.e-align-before .e-opposite-content,
+ &.e-align-alternate .e-opposite-content,
+ &.e-align-alternatereverse .e-opposite-content {
+ text-align: right;
+ }
+
+ &.e-align-before .e-opposite-content,
+ &.e-align-after .e-content,
+ &.e-rtl.e-align-after .e-opposite-content,
+ &.e-align-alternate .e-timeline-item:nth-of-type(odd) .e-content,
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(even) .e-content,
+ &.e-align-alternate .e-timeline-item:nth-of-type(even) .e-opposite-content,
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) .e-opposite-content,
+ &.e-rtl.e-align-alternate .e-timeline-item:nth-of-type(even) .e-content,
+ &.e-rtl.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) .e-content,
+ &.e-rtl.e-align-before .e-content,
+ &.e-rtl.e-align-alternate .e-opposite-content,
+ &.e-rtl.e-align-alternatereverse .e-opposite-content {
+ text-align: left;
+ }
+
+ .e-dot-item {
+ width: calc(var(--dot-size) * 2);
+ }
+ }
+
+ &.e-horizontal {
+ .e-timeline-items {
+ display: inline-flex;
+ flex-direction: row;
+ }
+
+ .e-timeline-item {
+ height: auto;
+ }
+
+ &.e-rtl .e-timeline-item.e-connector::after,
+ &.e-timeline-reverse .e-timeline-item.e-connector::after {
+ right: calc(50% - var(--connector-size));
+ left: auto;
+ }
+
+ .e-dot-item {
+ margin: calc((var(--dot-size) * 2) / 2) 0;
+ }
+
+ .e-timeline-item {
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .e-opposite-content,
+ .e-content {
+ display: flex;
+ }
+
+ &.e-align-alternate .e-timeline-item:nth-of-type(even) .e-content,
+ &.e-align-alternate .e-timeline-item:nth-of-type(odd) .e-opposite-content,
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) .e-content,
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(even) .e-opposite-content,
+ &.e-align-before .e-content {
+ align-items: flex-end;
+ }
+
+ &.e-align-alternate .e-timeline-item:nth-of-type(odd) .e-content,
+ &.e-align-alternate .e-timeline-item:nth-of-type(even) .e-opposite-content,
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(even) .e-content,
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) .e-opposite-content,
+ &.e-align-before .e-opposite-content {
+ align-items: flex-start;
+ }
+
+ &.e-align-before .e-timeline-item,
+ &.e-align-alternate .e-timeline-item:nth-of-type(even),
+ &.e-align-alternatereverse .e-timeline-item:nth-of-type(odd) {
+ flex-direction: column-reverse;
+ }
+
+ &.e-timeline-reverse .e-timeline-items {
+ flex-direction: row-reverse;
+ }
+
+ .e-timeline-item::after {
+ width: 100%;
+ height: 0;
+ top: calc(50% - var(--connector-size));
+ }
+
+ .e-opposite-content {
+ display: flex;
+ align-items: flex-end;
+ text-align: left;
+ padding: 0;
+ }
+
+ .e-content {
+ padding: 0;
+ }
+
+ .e-timeline-item:last-child::after {
+ width: auto;
+ }
+ }
+ }
+
+ .e-bigger.e-timeline,
+ .e-bigger .e-timeline {
+ [class ^= 'e-dot ']::before {
+ min-width: $timeline-bigger-dot-icon-size;
+ min-height: $timeline-bigger-dot-icon-size;
+ font-size: $timeline-bigger-dot-font-size;
+ }
+
+ .e-dot-item {
+ flex: 0 1 calc(var(--dot-size) * 4);
+ }
+
+ .e-dot {
+ min-width: $timeline-bigger-dot-size;
+ min-height: $timeline-bigger-dot-size;
+ }
+
+ .e-opposite-content {
+ font-size: $timeline-bigger-opposite-content-font-size;
+ }
+
+ .e-content {
+ font-size: $timeline-bigger-content-font-size;
+ }
+ }
+}
diff --git a/controls/layouts/styles/timeline/_material-dark-definition.scss b/controls/layouts/styles/timeline/_material-dark-definition.scss
new file mode 100644
index 0000000000..ae1ee57388
--- /dev/null
+++ b/controls/layouts/styles/timeline/_material-dark-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $grey-400 !default;
+$timeline-dot-background-color: $grey-900 !default;
+$timeline-dot-border-color: $grey-700 !default;
+$timeline-content-font-color: $grey-white !default;
+$timeline-opposite-content-font-color: $grey-white !default;
+$timeline-item-disabled-color: 'rgba($white, .38)' !default;
diff --git a/controls/layouts/styles/timeline/_material-definition.scss b/controls/layouts/styles/timeline/_material-definition.scss
new file mode 100644
index 0000000000..6881b07cc1
--- /dev/null
+++ b/controls/layouts/styles/timeline/_material-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $base-font !default;
+$timeline-dot-background-color: $primary-300-font !default;
+$timeline-dot-border-color: $grey-200 !default;
+$timeline-content-font-color: $base-font !default;
+$timeline-opposite-content-font-color: $base-font !default;
+$timeline-item-disabled-color: 'rgba($black, .38)' !default;
diff --git a/controls/layouts/styles/timeline/_material3-dark-definition.scss b/controls/layouts/styles/timeline/_material3-dark-definition.scss
new file mode 100644
index 0000000000..356e259499
--- /dev/null
+++ b/controls/layouts/styles/timeline/_material3-dark-definition.scss
@@ -0,0 +1 @@
+@import './material3-definition.scss';
diff --git a/controls/layouts/styles/timeline/_material3-definition.scss b/controls/layouts/styles/timeline/_material3-definition.scss
new file mode 100644
index 0000000000..7ad84de233
--- /dev/null
+++ b/controls/layouts/styles/timeline/_material3-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: rgba($content-text-color) !default;
+$timeline-dot-background-color: rgba($content-bg-color) !default;
+$timeline-dot-border-color: rgba($border-light) !default;
+$timeline-content-font-color: $content-text-color !default;
+$timeline-opposite-content-font-color: $content-text-color-alt1 !default;
+$timeline-item-disabled-color: $content-text-color-disabled !default;
diff --git a/controls/layouts/styles/timeline/_tailwind-dark-definition.scss b/controls/layouts/styles/timeline/_tailwind-dark-definition.scss
new file mode 100644
index 0000000000..b0d3baea85
--- /dev/null
+++ b/controls/layouts/styles/timeline/_tailwind-dark-definition.scss
@@ -0,0 +1 @@
+@import './tailwind-definition.scss';
diff --git a/controls/layouts/styles/timeline/_tailwind-definition.scss b/controls/layouts/styles/timeline/_tailwind-definition.scss
new file mode 100644
index 0000000000..46b6db5fa5
--- /dev/null
+++ b/controls/layouts/styles/timeline/_tailwind-definition.scss
@@ -0,0 +1,18 @@
+$timeline-dot-size: 16px !default;
+$timeline-content-font-size: 14px !default;
+$timeline-dot-font-size: 16px !default;
+$timeline-opposite-content-font-size: 12px !default;
+$timeline-dot-icon-size: 32px !default;
+
+$timeline-bigger-dot-size: 20px !default;
+$timeline-bigger-content-font-size: 16px !default;
+$timeline-bigger-opposite-content-font-size: 14px !default;
+$timeline-bigger-dot-font-size: 18px !default;
+$timeline-bigger-dot-icon-size: 40px !default;
+
+$timeline-dot-color: $content-text-color-alt2 !default;
+$timeline-dot-background-color: $content-bg-color !default;
+$timeline-dot-border-color: $border-light !default;
+$timeline-content-font-color: $content-text-color !default;
+$timeline-opposite-content-font-color: $content-text-color !default;
+$timeline-item-disabled-color: $content-text-color-disabled !default;
diff --git a/controls/layouts/styles/timeline/_theme.scss b/controls/layouts/styles/timeline/_theme.scss
new file mode 100644
index 0000000000..25e31bfa2d
--- /dev/null
+++ b/controls/layouts/styles/timeline/_theme.scss
@@ -0,0 +1,31 @@
+@include export-module('timeline-theme') {
+ .e-timeline {
+ .e-dot {
+ background-color: $timeline-dot-border-color;
+ border-color: $timeline-dot-border-color;
+ color: $timeline-dot-color;
+ outline-color: $timeline-dot-background-color;
+ }
+
+ &.e-outline .e-dot {
+ background-color: $timeline-dot-background-color;
+ }
+
+ .e-timeline-item.e-connector::after {
+ border-color: $timeline-dot-border-color;
+ }
+
+ .e-content {
+ color: $timeline-content-font-color;
+ }
+
+ .e-opposite-content {
+ color: $timeline-opposite-content-font-color;
+ }
+
+ .e-item-disabled .e-content,
+ .e-item-disabled .e-opposite-content {
+ color: $timeline-item-disabled-color;
+ }
+ }
+}
diff --git a/controls/layouts/styles/timeline/bootstrap-dark.scss b/controls/layouts/styles/timeline/bootstrap-dark.scss
new file mode 100644
index 0000000000..acbfa5aad6
--- /dev/null
+++ b/controls/layouts/styles/timeline/bootstrap-dark.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/bootstrap-dark.scss';
+@import 'bootstrap-dark-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/bootstrap.scss b/controls/layouts/styles/timeline/bootstrap.scss
new file mode 100644
index 0000000000..7deba5ce06
--- /dev/null
+++ b/controls/layouts/styles/timeline/bootstrap.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/bootstrap.scss';
+@import 'bootstrap-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/bootstrap4.scss b/controls/layouts/styles/timeline/bootstrap4.scss
new file mode 100644
index 0000000000..500bf9a0e8
--- /dev/null
+++ b/controls/layouts/styles/timeline/bootstrap4.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/bootstrap4.scss';
+@import 'bootstrap4-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/bootstrap5-dark.scss b/controls/layouts/styles/timeline/bootstrap5-dark.scss
new file mode 100644
index 0000000000..6c2aaa3b0e
--- /dev/null
+++ b/controls/layouts/styles/timeline/bootstrap5-dark.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/bootstrap5-dark.scss';
+@import 'bootstrap5-dark-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/bootstrap5.scss b/controls/layouts/styles/timeline/bootstrap5.scss
new file mode 100644
index 0000000000..85ca966e24
--- /dev/null
+++ b/controls/layouts/styles/timeline/bootstrap5.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/bootstrap5.scss';
+@import 'bootstrap5-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/fabric-dark.scss b/controls/layouts/styles/timeline/fabric-dark.scss
new file mode 100644
index 0000000000..ae86756a76
--- /dev/null
+++ b/controls/layouts/styles/timeline/fabric-dark.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/fabric-dark.scss';
+@import 'fabric-dark-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/fabric.scss b/controls/layouts/styles/timeline/fabric.scss
new file mode 100644
index 0000000000..ae925e91a1
--- /dev/null
+++ b/controls/layouts/styles/timeline/fabric.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/fabric.scss';
+@import 'fabric-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/fluent-dark.scss b/controls/layouts/styles/timeline/fluent-dark.scss
new file mode 100644
index 0000000000..b75529aca4
--- /dev/null
+++ b/controls/layouts/styles/timeline/fluent-dark.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/fluent-dark.scss';
+@import 'fluent-dark-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/fluent.scss b/controls/layouts/styles/timeline/fluent.scss
new file mode 100644
index 0000000000..b852be2f68
--- /dev/null
+++ b/controls/layouts/styles/timeline/fluent.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/fluent.scss';
+@import 'fluent-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/highcontrast-light.scss b/controls/layouts/styles/timeline/highcontrast-light.scss
new file mode 100644
index 0000000000..a041dcb7f0
--- /dev/null
+++ b/controls/layouts/styles/timeline/highcontrast-light.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/highcontrast-light.scss';
+@import 'highcontrast-light-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/highcontrast.scss b/controls/layouts/styles/timeline/highcontrast.scss
new file mode 100644
index 0000000000..feb972b289
--- /dev/null
+++ b/controls/layouts/styles/timeline/highcontrast.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/highcontrast.scss';
+@import 'highcontrast-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/material-dark.scss b/controls/layouts/styles/timeline/material-dark.scss
new file mode 100644
index 0000000000..25d51ab76e
--- /dev/null
+++ b/controls/layouts/styles/timeline/material-dark.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/material-dark.scss';
+@import 'material-dark-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/material.scss b/controls/layouts/styles/timeline/material.scss
new file mode 100644
index 0000000000..e6ebcd96be
--- /dev/null
+++ b/controls/layouts/styles/timeline/material.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/material.scss';
+@import 'material-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/material3-dark.scss b/controls/layouts/styles/timeline/material3-dark.scss
new file mode 100644
index 0000000000..f83476b154
--- /dev/null
+++ b/controls/layouts/styles/timeline/material3-dark.scss
@@ -0,0 +1,4 @@
+@import 'ej2-base/styles/definition/material3-dark.scss';
+
+@import 'material3-dark-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/material3.scss b/controls/layouts/styles/timeline/material3.scss
new file mode 100644
index 0000000000..6e811b6c23
--- /dev/null
+++ b/controls/layouts/styles/timeline/material3.scss
@@ -0,0 +1,4 @@
+@import 'ej2-base/styles/definition/material3.scss';
+
+@import 'material3-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/tailwind-dark.scss b/controls/layouts/styles/timeline/tailwind-dark.scss
new file mode 100644
index 0000000000..4f446b0813
--- /dev/null
+++ b/controls/layouts/styles/timeline/tailwind-dark.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/tailwind-dark.scss';
+@import 'tailwind-dark-definition.scss';
+@import 'all.scss';
diff --git a/controls/layouts/styles/timeline/tailwind.scss b/controls/layouts/styles/timeline/tailwind.scss
new file mode 100644
index 0000000000..b19b9e1f09
--- /dev/null
+++ b/controls/layouts/styles/timeline/tailwind.scss
@@ -0,0 +1,3 @@
+@import 'ej2-base/styles/definition/tailwind.scss';
+@import 'tailwind-definition.scss';
+@import 'all.scss';
diff --git a/controls/lists/CHANGELOG.md b/controls/lists/CHANGELOG.md
index 0de26de626..6232a588b0 100644
--- a/controls/lists/CHANGELOG.md
+++ b/controls/lists/CHANGELOG.md
@@ -2,7 +2,7 @@
## [Unreleased]
-## 25.1.35 (2024-03-15)
+## 25.1.37 (2024-03-26)
### ListBox
diff --git a/controls/maps/CHANGELOG.md b/controls/maps/CHANGELOG.md
index c8f8445c4f..3be301794f 100644
--- a/controls/maps/CHANGELOG.md
+++ b/controls/maps/CHANGELOG.md
@@ -8,7 +8,7 @@
## [Unreleased]
-## 25.1.35 (2024-03-15)
+## 25.1.37 (2024-03-26)
### Maps
diff --git a/controls/navigations/CHANGELOG.md b/controls/navigations/CHANGELOG.md
index c127e9bf56..a1012c3979 100644
--- a/controls/navigations/CHANGELOG.md
+++ b/controls/navigations/CHANGELOG.md
@@ -2,6 +2,20 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### TreeView
+
+#### Bug Fixes
+
+- `#I570321` - The issue with the focus on first item in TreeView if it is disabled mode has been resolved.
+
+### Toolbar
+
+#### Bug Fixes
+
+- `#I553624` - An issue with expanded toolbar items not align properly when change the mouse and touch modes has been fixed.
+
## 25.1.35 (2024-03-15)
### ContextMenu
diff --git a/controls/navigations/package.json b/controls/navigations/package.json
index 8e27fe5dd7..cf24bd410c 100644
--- a/controls/navigations/package.json
+++ b/controls/navigations/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-navigations",
- "version": "22.42.3",
+ "version": "25.1.35",
"description": "A package of Essential JS 2 navigation components such as Tree-view, Tab, Toolbar, Context-menu, and Accordion which is used to navigate from one page to another",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/navigations/spec/toolbar.spec.ts b/controls/navigations/spec/toolbar.spec.ts
index edac015169..bab23ffbe9 100644
--- a/controls/navigations/spec/toolbar.spec.ts
+++ b/controls/navigations/spec/toolbar.spec.ts
@@ -13025,6 +13025,68 @@ describe('Hscroll module scrollStep change in beforeCreate', () => {
expect(document.activeElement).toBe(firstElement);
});
});
+
+ describe('Extended overflow mode in toolbar items ', () => {
+ let toolbar: any;
+ beforeEach((): void => {
+ toolbar = undefined;
+ const ele: HTMLElement = createElement('div', { id: 'ej2Toolbar' });
+ document.body.appendChild(ele);
+ });
+ afterEach((): void => {
+ if (toolbar) {
+ toolbar.destroy();
+ }
+ document.body.innerHTML = '';
+ });
+
+ it('Extended popup width testing', () => {
+ const element: HTMLElement = document.getElementById('ej2Toolbar');
+ toolbar = new Toolbar({
+ overflowMode: 'Extended',
+ width: '200px',
+ items: [
+ { prefixIcon: 'e-cut-icon', tooltipText: 'Cut' },
+ { prefixIcon: 'e-copy-icon', tooltipText: 'Copy' },
+ { prefixIcon: 'e-paste-icon', tooltipText: 'Paste' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-bold-icon', tooltipText: 'Bold' },
+ { prefixIcon: 'e-underline-icon', tooltipText: 'Underline' },
+ { prefixIcon: 'e-italic-icon', tooltipText: 'Italic' },
+ { prefixIcon: 'e-color-icon', tooltipText: 'Color-Picker' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-alignleft-icon', tooltipText: 'Align-Left' },
+ { prefixIcon: 'e-alignjustify-icon', tooltipText: 'Align-Justify' },
+ { prefixIcon: 'e-alignright-icon', tooltipText: 'Align-Right' },
+ { prefixIcon: 'e-aligncenter-icon', tooltipText: 'Align-Center' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-bullets-icon', tooltipText: 'Bullets' },
+ { prefixIcon: 'e-numbering-icon', tooltipText: 'Numbering' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-ascending-icon', tooltipText: 'Sort A - Z' },
+ { prefixIcon: 'e-descending-icon', tooltipText: 'Sort Z - A' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-upload-icon', tooltipText: 'Upload' },
+ { prefixIcon: 'e-download-icon', tooltipText: 'Download' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-indent-icon', tooltipText: 'Text Indent' },
+ { prefixIcon: 'e-outdent-icon', tooltipText: 'Text Outdent' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-clear-icon', tooltipText: 'Clear' },
+ { prefixIcon: 'e-reload-icon', tooltipText: 'Reload' },
+ { prefixIcon: 'e-export-icon', tooltipText: 'Export' },
+ { type: 'Separator' },
+ { prefixIcon: 'e-undo-icon', tooltipText: 'Undo', text: 'Undo' },
+ { prefixIcon: 'e-redo-icon', tooltipText: 'Redo', text: 'Redo' }
+ ]
+ });
+ toolbar.appendTo('#ej2Toolbar');
+ let toolbarWidth: number = element.offsetWidth;
+ let extendedToolbar: HTMLElement = element.querySelector('.e-toolbar-extended');
+ extendedToolbar.style.display = "block";
+ expect(extendedToolbar.offsetWidth).toEqual(toolbarWidth);
+ });
+ });
it('memory leak', () => {
profile.sample();
diff --git a/controls/navigations/src/toolbar/toolbar.ts b/controls/navigations/src/toolbar/toolbar.ts
index e954b9d401..09c75462e8 100644
--- a/controls/navigations/src/toolbar/toolbar.ts
+++ b/controls/navigations/src/toolbar/toolbar.ts
@@ -945,16 +945,23 @@ export class Toolbar extends Component implements INotifyPropertyCh
popObj.enableRtl = false;
popObj.position = { X: 'right', Y: 'top' };
}
- popObj.dataBind();
- popObj.refreshPosition();
- popObj.element.style.top = this.getElementOffsetY() + 'px';
if (this.overflowMode === 'Extended') {
popObj.element.style.minHeight = '0px';
+ popObj.width = this.getToolbarPopupWidth(this.element);
}
+ popObj.dataBind();
+ popObj.refreshPosition();
+ popObj.element.style.top = this.getElementOffsetY() + 'px';
popupNav.classList.add(CLS_TBARNAVACT);
popObj.show({ name: 'FadeIn', duration: 100 });
}
}
+
+ private getToolbarPopupWidth(ele: HTMLElement) {
+ var eleStyles = window.getComputedStyle(ele);
+ return parseFloat(eleStyles.width) + ((parseFloat(eleStyles.borderRightWidth)) * 2);
+ }
+
/**
* To Initialize the control rendering
*
@@ -1333,7 +1340,7 @@ export class Toolbar extends Component implements INotifyPropertyCh
position: this.enableRtl ? { X: 'left', Y: 'top' } : { X: 'right', Y: 'top' }
});
if (this.overflowMode === 'Extended') {
- popup.width = parseFloat(eleStyles.width) + ((parseFloat(eleStyles.borderRightWidth)) * 2);
+ popup.width = this.getToolbarPopupWidth(this.element);
popup.offsetX = 0;
}
popup.appendTo(ele);
@@ -2309,8 +2316,7 @@ export class Toolbar extends Component implements INotifyPropertyCh
}
if (this.popObj) {
if (this.overflowMode === 'Extended') {
- const eleStyles: CSSStyleDeclaration = window.getComputedStyle(this.element);
- this.popObj.width = parseFloat(eleStyles.width) + ((parseFloat(eleStyles.borderRightWidth)) * 2);
+ this.popObj.width = this.getToolbarPopupWidth(this.element);
}
if (this.tbarAlign) {
this.removePositioning();
diff --git a/controls/navigations/src/treeview/treeview.ts b/controls/navigations/src/treeview/treeview.ts
index beeecf095d..4cfd5edc55 100644
--- a/controls/navigations/src/treeview/treeview.ts
+++ b/controls/navigations/src/treeview/treeview.ts
@@ -3620,11 +3620,16 @@ export class TreeView extends Component implements INotifyPropertyC
private focusIn(): void {
if(!this.mouseDownStatus){
let focusedElement: Element = this.getFocusedNode();
- focusedElement.setAttribute("tabindex","0");
- addClass([focusedElement], FOCUS);
- EventHandler.add(focusedElement, 'blur', this.focusOut, this);
+ if (focusedElement.classList.contains('e-disable')) {
+ focusedElement.setAttribute("tabindex", "-1");
+ this.navigateNode(true);
+ } else {
+ focusedElement.setAttribute("tabindex","0");
+ addClass([focusedElement], FOCUS);
+ EventHandler.add(focusedElement, 'blur', this.focusOut, this);
+ }
+ this.mouseDownStatus = false;
}
- this.mouseDownStatus = false;
}
private focusOut(event: Event): void {
diff --git a/controls/notifications/CHANGELOG.md b/controls/notifications/CHANGELOG.md
index 1bd9aedbe0..9749283fc4 100644
--- a/controls/notifications/CHANGELOG.md
+++ b/controls/notifications/CHANGELOG.md
@@ -2,7 +2,7 @@
## [Unreleased]
-## 25.1.35 (2024-03-15)
+## 25.1.37 (2024-03-26)
### Toast
diff --git a/controls/officechart/CHANGELOG.md b/controls/officechart/CHANGELOG.md
index 62e3cc5dd5..0183ca809f 100644
--- a/controls/officechart/CHANGELOG.md
+++ b/controls/officechart/CHANGELOG.md
@@ -2,7 +2,7 @@
## [Unreleased]
-## 24.1.41 (2023-12-18)
+## 25.1.35 (2024-03-15)
### Office Chart
diff --git a/controls/officechart/package.json b/controls/officechart/package.json
index c918d9006c..7f8b87effb 100644
--- a/controls/officechart/package.json
+++ b/controls/officechart/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-office-chart",
- "version": "24.2.3",
+ "version": "25.1.35",
"description": "Essential JS 2 Component",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/officechart/tsconfig.json b/controls/officechart/tsconfig.json
index 188c599658..33ba08d2af 100644
--- a/controls/officechart/tsconfig.json
+++ b/controls/officechart/tsconfig.json
@@ -18,7 +18,7 @@
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"suppressImplicitAnyIndexErrors": true,
- "lib": ["es5", "es2015", "es2015.promise", "dom"],
+ "lib": ["es5", "es2015", "es2015.promise", "dom"],
"types": ["jasmine","jasmine-ajax","requirejs","chai"]
},
"exclude": [
@@ -29,4 +29,4 @@
"test-report"
],
"compileOnSave": false
- }
+ }
\ No newline at end of file
diff --git a/controls/pdf/CHANGELOG.md b/controls/pdf/CHANGELOG.md
index bad1ceaea4..4fedd75979 100644
--- a/controls/pdf/CHANGELOG.md
+++ b/controls/pdf/CHANGELOG.md
@@ -2,6 +2,14 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### PDF Parser
+
+#### Bug Fixes
+
+- Resolved an exception encountered while removing all pages from PDF document.
+
## 25.1.35 (2024-03-15)
### PDF Parser
diff --git a/controls/pdf/package.json b/controls/pdf/package.json
index 107fd891ca..03cc5c4f8b 100644
--- a/controls/pdf/package.json
+++ b/controls/pdf/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-pdf",
- "version": "17.9.0",
+ "version": "25.1.35",
"description": "Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/pdf/src/pdf/core/pdf-document.ts b/controls/pdf/src/pdf/core/pdf-document.ts
index 9113a2b2ae..cf486670e1 100644
--- a/controls/pdf/src/pdf/core/pdf-document.ts
+++ b/controls/pdf/src/pdf/core/pdf-document.ts
@@ -558,30 +558,42 @@ export class PdfDocument {
pageDictionary.objId = pageReference.toString();
pageDictionary.update('Parent', sectionReference);
sectionDictionary.update('Kids', [pageReference]);
- const lastPage: PdfPage = this.getPage(pageIndex === this.pageCount ? (pageIndex - 1) : pageIndex);
- if (lastPage && lastPage._pageDictionary) {
- const parentReference: _PdfReference = lastPage._pageDictionary._get('Parent');
- const parentDictionary: _PdfDictionary = this._crossReference._fetch(parentReference);
- if (parentDictionary && parentDictionary.has('Kids')) {
- let kids: _PdfReference[] = parentDictionary.get('Kids');
- if (kids) {
- if (pageIndex === this.pageCount) {
- kids.push(sectionReference);
- } else {
- const newKids: _PdfReference[] = [];
- kids.forEach((entry: _PdfReference) => {
- if (entry === lastPage._ref) {
- newKids.push(sectionReference);
- }
- newKids.push(entry);
- });
- kids = newKids;
- this._updatePageCache(pageIndex);
+ if (this.pageCount === 0) {
+ let parentReference: _PdfReference = this._catalog._catalogDictionary._get('Pages');
+ if (parentReference && this._catalog._topPagesDictionary) {
+ this._catalog._topPagesDictionary.update('Kids', [sectionReference]);
+ sectionDictionary.update('Parent', parentReference);
+ } else {
+ this._catalog._catalogDictionary.update('Pages', sectionReference);
+ }
+ this._pages = new Map();
+ this._pageCount = 1;
+ } else {
+ const lastPage: PdfPage = this.getPage(pageIndex === this.pageCount ? (pageIndex - 1) : pageIndex);
+ if (lastPage && lastPage._pageDictionary) {
+ const parentReference: _PdfReference = lastPage._pageDictionary._get('Parent');
+ const parentDictionary: _PdfDictionary = this._crossReference._fetch(parentReference);
+ if (parentDictionary && parentDictionary.has('Kids')) {
+ let kids: _PdfReference[] = parentDictionary.get('Kids');
+ if (kids) {
+ if (pageIndex === this.pageCount) {
+ kids.push(sectionReference);
+ } else {
+ const newKids: _PdfReference[] = [];
+ kids.forEach((entry: _PdfReference) => {
+ if (entry === lastPage._ref) {
+ newKids.push(sectionReference);
+ }
+ newKids.push(entry);
+ });
+ kids = newKids;
+ this._updatePageCache(pageIndex);
+ }
+ parentDictionary.update('Kids', kids);
+ sectionDictionary.update('Parent', parentReference);
+ this._updatePageCount(parentDictionary, 1);
+ this._pageCount = this.pageCount + 1;
}
- parentDictionary.update('Kids', kids);
- sectionDictionary.update('Parent', parentReference);
- this._updatePageCount(parentDictionary, 1);
- this._pageCount = this.pageCount + 1;
}
}
}
@@ -713,16 +725,18 @@ export class PdfDocument {
}
}
_removeParent(referenceToRemove: _PdfReference, dictionary: _PdfDictionary): void {
- const parentReference: _PdfReference = dictionary._get('Parent');
- const parentDictionary: _PdfDictionary = this._crossReference._fetch(parentReference);
- if (parentDictionary && parentDictionary.has('Kids')) {
- let kids: _PdfReference[] = parentDictionary.get('Kids');
- if (kids.length === 1 && parentDictionary && parentDictionary.get('Type').name === 'Pages') {
- this._removeParent(parentReference, parentDictionary);
- } else {
- kids = kids.filter((item: _PdfReference) => item !== referenceToRemove);
- parentDictionary.update('Kids', kids);
- this._updatePageCount(parentDictionary, -1);
+ if (dictionary.has('Parent')) {
+ const parentReference: _PdfReference = dictionary._get('Parent');
+ const parentDictionary: _PdfDictionary = this._crossReference._fetch(parentReference);
+ if (parentDictionary && parentDictionary.has('Kids')) {
+ let kids: _PdfReference[] = parentDictionary.get('Kids');
+ if (kids.length === 1 && parentDictionary && parentDictionary.get('Type').name === 'Pages') {
+ this._removeParent(parentReference, parentDictionary);
+ } else {
+ kids = kids.filter((item: _PdfReference) => item !== referenceToRemove);
+ parentDictionary.update('Kids', kids);
+ this._updatePageCount(parentDictionary, -1);
+ }
}
}
}
diff --git a/controls/pdfexport/package.json b/controls/pdfexport/package.json
index bf43914750..6a12e5d1ec 100644
--- a/controls/pdfexport/package.json
+++ b/controls/pdfexport/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-pdf-export",
- "version": "0.38.8",
+ "version": "25.1.35",
"description": "Syncfusion TypeScript Component",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/pdfexport/spec/syncfusion-pdf-base/main.spec.ts b/controls/pdfexport/spec/syncfusion-pdf-base/main.spec.ts
index 43bd9d0dcd..88b39757ca 100644
--- a/controls/pdfexport/spec/syncfusion-pdf-base/main.spec.ts
+++ b/controls/pdfexport/spec/syncfusion-pdf-base/main.spec.ts
@@ -4975,4 +4975,110 @@ describe('Usability features', () => {
});
document.destroy();
});
+});
+describe('Grid issue', () => {
+ it('872266 - nested grid - issue', (done) => {
+ let pdfDocument: PdfDocument = new PdfDocument();
+ pdfDocument.pageSettings.size = { height: 842, width: 595 };
+ pdfDocument.pageSettings.orientation = 1;
+ let hfont = new PdfStandardFont(2, 13); // font style for headers
+ // create black brush
+ let brush = new PdfSolidBrush(new PdfColor(0, 0, 0));
+ let bounds = new RectangleF(0, 0, 515, 50);
+ let header = new PdfPageTemplateElement(bounds);
+ header.graphics.drawString('Header Text', hfont, null, brush, 0, 0, 100, 50, null);
+ //Add the header at the top.
+ let grid2: PdfGrid = new PdfGrid();
+ grid2.columns.add(6);
+ grid2.headers.add(2);
+ let grid2header_0: PdfGridRow = grid2.headers.getHeader(0);
+ grid2header_0.cells.getCell(0).value = 'RECEIPT DETAIL';
+ grid2header_0.cells.getCell(0).style.font = hfont;
+ grid2header_0.cells.getCell(0).columnSpan = 6;
+ let grid2header_1: PdfGridRow = grid2.headers.getHeader(1);
+ grid2header_1.cells.getCell(0).value = 'Receipt Date';
+ grid2header_1.cells.getCell(0).style.font = hfont;
+ grid2header_1.cells.getCell(1).value = 'Receipt No';
+ grid2header_1.cells.getCell(1).style.font = hfont;
+ grid2header_1.cells.getCell(2).value = 'Sale Bill No';
+ grid2header_1.cells.getCell(2).style.font = hfont;
+ grid2header_1.cells.getCell(3).value = 'Name';
+ grid2header_1.cells.getCell(3).style.font = hfont;
+ grid2header_1.cells.getCell(4).value = 'Payment Mode';
+ grid2header_1.cells.getCell(4).style.font = hfont;
+ grid2header_1.cells.getCell(5).value = 'Amount';
+ grid2header_1.cells.getCell(5).style.font = hfont;
+ for (let i: number = 0; i < 30; i++) {
+ let grid2row1: PdfGridRow = grid2.rows.addRow();
+ grid2row1.cells.getCell(0).value = '15/06/2021';
+ grid2row1.cells.getCell(1).value = '15-06-2021/RECP/' + i.toString();
+ grid2row1.cells.getCell(2).value = 'Sale-702';
+ grid2row1.cells.getCell(3).value = 'Akash Agarwal';
+ grid2row1.cells.getCell(4).value = 'IDBI BANK';
+ grid2row1.cells.getCell(5).value = '11080';
+ }
+ let aggregateRow2_0: PdfGridRow = grid2.rows.addRow();
+ aggregateRow2_0.cells.getCell(0).value = '';
+ aggregateRow2_0.cells.getCell(1).value = '';
+ aggregateRow2_0.cells.getCell(2).value = '';
+ aggregateRow2_0.cells.getCell(3).value = 'Total :';
+ aggregateRow2_0.cells.getCell(4).value = '';
+ aggregateRow2_0.cells.getCell(5).value = '89,080.00';
+ let format2: PdfGridLayoutFormat = new PdfGridLayoutFormat();
+ format2.layout = PdfLayoutType.Paginate;
+ format2.break = PdfLayoutBreakType.FitPage;
+ pdfDocument.template.top = header;
+ let page: PdfPage = pdfDocument.pages.add();
+ // create a PdfGrid
+ let grid: PdfGrid = new PdfGrid();
+ grid.columns.add(5);
+ grid.headers.add(1);
+ let header_1: PdfGridRow = grid.headers.getHeader(0);
+ header_1.cells.getCell(0).value = 'Bill Date';
+ header_1.cells.getCell(0).style.font = hfont;
+ header_1.cells.getCell(1).value = 'Bill No';
+ header_1.cells.getCell(1).style.font = hfont;
+ header_1.cells.getCell(2).value = 'Bill Amount';
+ header_1.cells.getCell(2).style.font = hfont;
+ header_1.cells.getCell(3).value = 'Cash';
+ header_1.cells.getCell(3).style.font = hfont;
+ header_1.cells.getCell(4).value = 'Card';
+ header_1.cells.getCell(4).style.font = hfont;
+ for (let i: number = 0; i < 50; i++) {
+ let row_0: PdfGridRow = grid.rows.addRow();
+
+ if (i == 1) {
+ row_0.cells.getCell(0).value = grid2;
+ row_0.cells.getCell(0).columnSpan = 5;
+ }
+ else {
+ row_0.cells.getCell(0).value = '15/06/2021';
+ row_0.cells.getCell(1).value = '1048' + i.toString();
+ row_0.cells.getCell(2).value = '3070';
+ row_0.cells.getCell(3).value = '3070';
+ row_0.cells.getCell(4).value = '0';
+ }
+ }
+ let aggregateRow_0: PdfGridRow = grid.rows.addRow();
+ aggregateRow_0.cells.getCell(0).value = '';
+ aggregateRow_0.cells.getCell(1).value = '';
+ aggregateRow_0.cells.getCell(2).value = '570,310.00';
+ aggregateRow_0.cells.getCell(3).value = '344,570.00';
+ aggregateRow_0.cells.getCell(4).value = '87,640.00';
+ let result: PdfLayoutResult = grid.draw(page, 0, 0);
+ pdfDocument.save().then((xlBlob: { blobData: Blob }) => {
+ if (Utils.isDownloadEnabled) {
+ Utils.download(xlBlob.blobData, '872266_nested_grid.pdf');
+ }
+ let reader: FileReader = new FileReader();
+ reader.readAsArrayBuffer(xlBlob.blobData);
+ reader.onload = (): void => {
+ if (reader.readyState == 2) {
+ expect((reader.result as ArrayBuffer).byteLength).toBeGreaterThanOrEqual(0);
+ done();
+ }
+ }
+ });
+ pdfDocument.destroy();
+ });
});
\ No newline at end of file
diff --git a/controls/pdfexport/src/implementation/structured-elements/grid/layout/grid-layouter.ts b/controls/pdfexport/src/implementation/structured-elements/grid/layout/grid-layouter.ts
index 9dad9712bc..1f0d084fdd 100644
--- a/controls/pdfexport/src/implementation/structured-elements/grid/layout/grid-layouter.ts
+++ b/controls/pdfexport/src/implementation/structured-elements/grid/layout/grid-layouter.ts
@@ -1590,14 +1590,16 @@ export class PdfGridLayouter extends ElementLayouter {
// }
}
for (let i : number = this.cellStartIndex; i <= this.cellEndIndex; i++) {
+ let gridColumnWidth: number = this.Grid.columns.getColumn(i).width;
let cancelSpans : boolean = ((row.cells.getCell(i).columnSpan + i > this.cellEndIndex + 1) &&
(row.cells.getCell(i).columnSpan > 1));
- // if (!cancelSpans) {
- // for (let k : number = 1; k < row.cells.getCell(i).columnSpan; k++) {
- // row.cells.getCell(i + k).isCellMergeContinue = true;
- // }
- //}
- let size : SizeF = new SizeF(this.Grid.columns.getColumn(i).width, this.gridHeight > 0.0 ? this.gridHeight :
+ if (!cancelSpans) {
+ for (let k : number = 1; k < row.cells.getCell(i).columnSpan; k++) {
+ row.cells.getCell(i + k).isCellMergeContinue = true;
+ gridColumnWidth += this.Grid.columns.getColumn(i + k).width;
+ }
+ }
+ let size : SizeF = new SizeF(gridColumnWidth, this.gridHeight > 0.0 ? this.gridHeight :
this.currentPageBounds.height);
// if (size.width === 0) {
// size = new SizeF(row.cells.getCell(i).width, size.height);
diff --git a/controls/pdfexport/src/implementation/structured-elements/grid/pdf-grid-cell.ts b/controls/pdfexport/src/implementation/structured-elements/grid/pdf-grid-cell.ts
index b337e8d0e3..42e3015240 100644
--- a/controls/pdfexport/src/implementation/structured-elements/grid/pdf-grid-cell.ts
+++ b/controls/pdfexport/src/implementation/structured-elements/grid/pdf-grid-cell.ts
@@ -638,7 +638,8 @@ export class PdfGridCell {
}
if (param.page != childGridResult.page) //&& (isWidthGreaterthanParent != true))
{
- childGridResult.bounds.height = this.row.rowBreakHeightValue;
+ if (this.row.rowBreakHeightValue !== null && typeof this.row.rowBreakHeightValue !== 'undefined')
+ childGridResult.bounds.height = this.row.rowBreakHeightValue;
if(this.row.rowBreakHeight == 0)
this.row.NestedGridLayoutResult = childGridResult;
else
diff --git a/controls/pdfviewer/CHANGELOG.md b/controls/pdfviewer/CHANGELOG.md
index 4730e802b2..86aade3ad2 100644
--- a/controls/pdfviewer/CHANGELOG.md
+++ b/controls/pdfviewer/CHANGELOG.md
@@ -2,6 +2,25 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### PDF Viewer
+
+#### Bug Fixes
+
+- `#I562878` - Now, the custom data is not missing from deleted annotation properties when initializing settings with custom data.
+- `#I565199` - Now, the annotation custom data is not missing in `AnnotationSelect` events.
+- `#I563333` - Now, the comments cannot be edited when the annotation is locked.
+- `#I874338` - Now, the locked annotations are preserved properly when importing the annotation.
+- `#I561320` - Now, the undo has restored the programmatically deleted annotations.
+- `#I566765` - Now, the create and clear buttons are not enabled if the text box is empty in the text signature tab.
+- `#I564309` - Now, the script error not occurred when dynamically updating toolbar items without annotation module.
+- `#I564643` - Now, the form fields are rendered properly after deleting it from the customer document.
+
+#### Features
+
+- `#I531005` - Now, provided the option to turn off the autocomplete option for comments in the comment panel.
+
## 25.1.35 (2024-03-15)
### PDF Viewer
diff --git a/controls/pdfviewer/package.json b/controls/pdfviewer/package.json
index a0ef082406..45cbeb90da 100644
--- a/controls/pdfviewer/package.json
+++ b/controls/pdfviewer/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-pdfviewer",
- "version": "22.16.57",
+ "version": "25.1.35",
"description": "Essential JS 2 PDF viewer Component",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/annotation.ts
index f232f2fae8..9599922950 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/annotation.ts
@@ -2808,7 +2808,10 @@ export class Annotation {
}
// eslint-disable-next-line
- private modifyInCollections(annotationBase: PdfAnnotationBaseModel, property: string): any {
+ /**
+ * @private
+ */
+ public modifyInCollections(annotationBase: PdfAnnotationBaseModel, property: string): any {
// eslint-disable-next-line
let returnObj: any;
if (annotationBase.measureType === '' || isNullOrUndefined(annotationBase.measureType)) {
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/free-text-annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/free-text-annotation.ts
index 381b7c2546..63b5bc9c4e 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/free-text-annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/free-text-annotation.ts
@@ -353,6 +353,9 @@ export class FreeTextAnnotation {
}
// eslint-disable-next-line max-len
annotation.AnnotationSettings = annotation.AnnotationSettings ? annotation.AnnotationSettings : this.pdfViewer.annotationModule.updateSettings(this.pdfViewer.freeTextSettings);
+ if (annotation.IsLocked) {
+ annotation.AnnotationSettings.isLock = annotation.IsLocked;
+ }
let annot: PdfAnnotationBaseModel;
let paddingValue: number = 0.5;
let annotationBoundsX: number = !isNullOrUndefined(annotation.Bounds.X) ? annotation.Bounds.X - paddingValue : annotation.Bounds.x;
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/ink-annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/ink-annotation.ts
index 4944071343..bfec727360 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/ink-annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/ink-annotation.ts
@@ -211,7 +211,7 @@ export class InkAnnotation {
let isLock: boolean = this.pdfViewer.inkAnnotationSettings.isLock ? this.pdfViewer.inkAnnotationSettings.isLock : this.pdfViewer.annotationSettings.isLock;
const author: string = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.inkAnnotationSettings.author ? this.pdfViewer.inkAnnotationSettings.author : 'Guest';
const subject: string = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.inkAnnotationSettings.subject ? this.pdfViewer.inkAnnotationSettings.subject : 'Ink';
- const customData: object = this.pdfViewer.inkAnnotationSettings.customData;
+ const customData: object = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ?this.pdfViewer.annotationSettings.customData : this.pdfViewer.inkAnnotationSettings.customData ? this.pdfViewer.inkAnnotationSettings.customData : null;
const isPrint: boolean = this.pdfViewer.inkAnnotationSettings.isPrint;
// eslint-disable-next-line
let allowedInteractions: any = this.pdfViewer.inkAnnotationSettings.allowedInteractions ? this.pdfViewer.inkAnnotationSettings.allowedInteractions : this.pdfViewer.annotationSettings.allowedInteractions;
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/measure-annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/measure-annotation.ts
index 2bd266d820..88cb609b9d 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/measure-annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/measure-annotation.ts
@@ -308,6 +308,9 @@ export class MeasureAnnotation {
}
// eslint-disable-next-line max-len
annotation.AnnotationSettings = annotation.AnnotationSettings ? annotation.AnnotationSettings : this.pdfViewer.annotationModule.updateAnnotationSettings(annotation);
+ if (annotation.IsLocked) {
+ annotation.AnnotationSettings.isLock = annotation.IsLocked;
+ }
// eslint-disable-next-line max-len
annotation.allowedInteractions = annotation.AllowedInteractions ? annotation.AllowedInteractions : this.pdfViewer.annotationModule.updateAnnotationAllowedInteractions(annotation);
let isPrint: boolean = annotation.IsPrint;
@@ -369,7 +372,7 @@ export class MeasureAnnotation {
fontColor: annotation.FontColor, labelBorderColor: annotation.LabelBorderColor, fontSize: annotation.FontSize,
labelBounds: annotation.LabelBounds, annotationSelectorSettings: annotation.AnnotationSelectorSettings,
annotationSettings: annotationObject.annotationSettings, annotationAddMode: annotation.annotationAddMode,
- isPrint: isPrint, isCommentLock: annotationObject.isCommentLock
+ isPrint: isPrint, isCommentLock: annotationObject.isCommentLock, customData: annotationObject.customData
};
this.pdfViewer.annotation.storeAnnotations(pageNumber, annotationObject, '_annotations_shape_measure');
if(this.isAddAnnotationProgramatically)
@@ -388,6 +391,10 @@ export class MeasureAnnotation {
const annotationObject: IMeasureShapeAnnotation = this.createAnnotationObject(shapeAnnotations);
this.pdfViewer.annotationModule.isFormFieldShape = false;
this.pdfViewer.annotationModule.storeAnnotations(pageNumber, annotationObject, '_annotations_shape_measure');
+ if(shapeAnnotations)
+ {
+ shapeAnnotations.customData = annotationObject.customData;
+ }
this.pdfViewer.annotationModule.triggerAnnotationAdd(shapeAnnotations);
}
}
@@ -414,6 +421,7 @@ export class MeasureAnnotation {
public setAnnotationType(type: AnnotType): void {
let author: string = 'Guest';
let subject: string = "";
+ let customData: object;
this.updateMeasureproperties();
this.pdfViewerBase.disableTextSelectionMode();
switch (type) {
@@ -423,13 +431,14 @@ export class MeasureAnnotation {
// eslint-disable-next-line max-len
author = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.distanceSettings.author ? this.pdfViewer.distanceSettings.author : 'Guest';
subject = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.distanceSettings.subject ? this.pdfViewer.distanceSettings.subject : 'Distance calculation';
+ customData = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ? this.pdfViewer.annotationSettings.customData : this.pdfViewer.distanceSettings.customData ? this.pdfViewer.distanceSettings.customData : null;
this.pdfViewer.drawingObject = {
sourceDecoraterShapes: this.pdfViewer.annotation.getArrowType(this.distanceStartHead),
taregetDecoraterShapes: this.pdfViewer.annotation.getArrowType(this.distanceEndHead), measureType: 'Distance',
fillColor: this.distanceFillColor, notes: '', strokeColor: this.distanceStrokeColor, leaderHeight: this.leaderLength,
opacity: this.distanceOpacity, thickness: this.distanceThickness, borderDashArray: this.distanceDashArray.toString(),
// eslint-disable-next-line max-len
- shapeAnnotationType: 'Distance', author: author, subject: subject, isCommentLock: false
+ shapeAnnotationType: 'Distance', author: author, subject: subject, isCommentLock: false, customData: customData
};
this.pdfViewer.tool = 'Distance';
break;
@@ -470,11 +479,12 @@ export class MeasureAnnotation {
// eslint-disable-next-line max-len
author = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.radiusSettings.author ? this.pdfViewer.radiusSettings.author : 'Guest';
subject = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.radiusSettings.subject ? this.pdfViewer.radiusSettings.subject : 'Radius calculation';
+ customData = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ? this.pdfViewer.annotationSettings.customData : this.pdfViewer.radiusSettings.customData ? this.pdfViewer.radiusSettings.customData : null;
this.pdfViewer.drawingObject = {
// eslint-disable-next-line max-len
shapeAnnotationType: 'Radius', fillColor: this.radiusFillColor, notes: '', strokeColor: this.radiusStrokeColor, opacity: this.radiusOpacity,
thickness: this.radiusThickness, measureType: 'Radius', modifiedDate: modifiedDateRad, borderStyle: '', borderDashArray: '0',
- author: author, subject: subject, isCommentLock: false
+ author: author, subject: subject, isCommentLock: false, customData: customData
};
this.pdfViewer.tool = 'DrawTool';
break;
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/shape-annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/shape-annotation.ts
index 3351a2c59c..99553ec6bb 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/shape-annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/shape-annotation.ts
@@ -245,6 +245,9 @@ export class ShapeAnnotation {
annotation.AnnotationSelectorSettings = annotation.AnnotationSelectorSettings ? annotation.AnnotationSelectorSettings : this.pdfViewer.annotationSelectorSettings;
// eslint-disable-next-line max-len
annotation.AnnotationSettings = annotation.AnnotationSettings ? annotation.AnnotationSettings : this.pdfViewer.annotationModule.updateAnnotationSettings(annotation);
+ if (annotation.IsLocked) {
+ annotation.AnnotationSettings.isLock = annotation.IsLocked;
+ }
// eslint-disable-next-line max-len
annotation.allowedInteractions = annotation.AllowedInteractions ? annotation.AllowedInteractions : this.pdfViewer.annotationModule.updateAnnotationAllowedInteractions(annotation);
let left: number = annotation.Bounds.X ? annotation.Bounds.X : annotation.Bounds.x;
@@ -311,6 +314,9 @@ export class ShapeAnnotation {
else
this.pdfViewer.annotationModule.isFormFieldShape = false;
this.pdfViewer.annotationModule.storeAnnotations(pageNumber, annotationObject, '_annotations_shape');
+ if (shapeAnnotations) {
+ shapeAnnotations.customData = annotationObject.customData;
+ }
this.pdfViewer.annotationModule.triggerAnnotationAdd(shapeAnnotations);
}
}
@@ -339,6 +345,7 @@ export class ShapeAnnotation {
this.pdfViewerBase.disableTextSelectionMode();
let author: string = 'Guest';
let subject: string = "";
+ let customData: object;
switch (type) {
case 'Line':
this.currentAnnotationMode = 'Line';
@@ -347,13 +354,14 @@ export class ShapeAnnotation {
// eslint-disable-next-line max-len
author = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.lineSettings.author ? this.pdfViewer.lineSettings.author : 'Guest';
subject = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.lineSettings.subject ? this.pdfViewer.lineSettings.subject : 'Line';
+ customData = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ? this.pdfViewer.annotationSettings.customData : this.pdfViewer.lineSettings.customData ? this.pdfViewer.lineSettings.customData : null;
this.pdfViewer.drawingObject = {
// eslint-disable-next-line max-len
shapeAnnotationType: this.setShapeType('Line'), fillColor: this.lineFillColor, notes: '', strokeColor: this.lineStrokeColor, opacity: this.lineOpacity,
thickness: this.lineThickness, modifiedDate: modifiedDateLine, borderDashArray: this.lineDashArray.toString(),
// eslint-disable-next-line max-len
sourceDecoraterShapes: this.pdfViewer.annotation.getArrowType(this.lineStartHead.toString()), taregetDecoraterShapes: this.pdfViewer.annotation.getArrowType(this.lineEndHead.toString()),
- author: author, subject: subject, lineHeadStart: this.lineStartHead, lineHeadEnd: this.lineEndHead, isCommentLock: false
+ author: author, subject: subject, lineHeadStart: this.lineStartHead, lineHeadEnd: this.lineEndHead, isCommentLock: false, customData: customData
};
this.pdfViewer.tool = 'Line';
break;
@@ -363,6 +371,7 @@ export class ShapeAnnotation {
const modifiedDateArrow: string = this.pdfViewer.annotation.stickyNotesAnnotationModule.getDateAndTime();
author = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.arrowSettings.author ? this.pdfViewer.arrowSettings.author : 'Guest';
subject = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.arrowSettings.subject ? this.pdfViewer.arrowSettings.subject : 'Arrow';
+ customData = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ? this.pdfViewer.annotationSettings.customData : this.pdfViewer.arrowSettings.customData ? this.pdfViewer.arrowSettings.customData : null;
this.pdfViewer.drawingObject = {
shapeAnnotationType: this.setShapeType('Arrow'), opacity: this.arrowOpacity,
// eslint-disable-next-line max-len
@@ -372,7 +381,7 @@ export class ShapeAnnotation {
fillColor: this.arrowFillColor, strokeColor: this.arrowStrokeColor, notes: '', thickness: this.arrowThickness,
borderDashArray: this.arrowDashArray.toString(), author: author, subject: subject,
// eslint-disable-next-line max-len
- modifiedDate: modifiedDateArrow, lineHeadStart: this.arrowStartHead, lineHeadEnd: this.arrowEndHead, isCommentLock: false
+ modifiedDate: modifiedDateArrow, lineHeadStart: this.arrowStartHead, lineHeadEnd: this.arrowEndHead, isCommentLock: false, customData: customData
};
this.pdfViewer.tool = 'Line';
break;
@@ -383,11 +392,12 @@ export class ShapeAnnotation {
// eslint-disable-next-line max-len
author = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.rectangleSettings.author ? this.pdfViewer.rectangleSettings.author : 'Guest';
subject = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.rectangleSettings.subject ? this.pdfViewer.rectangleSettings.subject : 'Rectangle';
+ customData = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ? this.pdfViewer.annotationSettings.customData : this.pdfViewer.rectangleSettings.customData ? this.pdfViewer.rectangleSettings.customData : null;
this.pdfViewer.drawingObject = {
shapeAnnotationType: this.setShapeType('Rectangle'), strokeColor: this.rectangleStrokeColor,
fillColor: this.rectangleFillColor, opacity: this.rectangleOpacity, notes: '',
thickness: this.rectangleThickness, borderDashArray: '0', modifiedDate: modifiedDateRect,
- author: author, subject: subject, isCommentLock: false
+ author: author, subject: subject, isCommentLock: false, customData: customData
};
this.pdfViewer.tool = 'DrawTool';
break;
@@ -398,11 +408,12 @@ export class ShapeAnnotation {
// eslint-disable-next-line max-len
author = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.circleSettings.author ? this.pdfViewer.circleSettings.author : 'Guest';
subject = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.circleSettings.subject ? this.pdfViewer.circleSettings.subject : 'Circle';
+ customData = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ? this.pdfViewer.annotationSettings.customData : this.pdfViewer.circleSettings.customData ? this.pdfViewer.circleSettings.customData : null;
this.pdfViewer.drawingObject = {
shapeAnnotationType: this.setShapeType('Circle'), strokeColor: this.circleStrokeColor,
fillColor: this.circleFillColor, opacity: this.circleOpacity, notes: '',
thickness: this.circleThickness, borderDashArray: '0', modifiedDate: modifiedDateCir,
- author: author, subject: subject, isCommentLock: false
+ author: author, subject: subject, isCommentLock: false, customData: customData
};
this.pdfViewer.tool = 'DrawTool';
break;
@@ -413,11 +424,12 @@ export class ShapeAnnotation {
// eslint-disable-next-line max-len
author = (this.pdfViewer.annotationSettings.author !== 'Guest') ? this.pdfViewer.annotationSettings.author : this.pdfViewer.polygonSettings.author ? this.pdfViewer.polygonSettings.author : 'Guest';
subject = (this.pdfViewer.annotationSettings.subject !== "" && !isNullOrUndefined(this.pdfViewer.annotationSettings.subject)) ? this.pdfViewer.annotationSettings.subject : this.pdfViewer.polygonSettings.subject ? this.pdfViewer.polygonSettings.subject : 'Polygon';
+ customData = !isNullOrUndefined(this.pdfViewer.annotationSettings.customData) ? this.pdfViewer.annotationSettings.customData : this.pdfViewer.polygonSettings.customData ? this.pdfViewer.polygonSettings.customData : null;
this.pdfViewer.drawingObject = {
strokeColor: this.polygonStrokeColor, fillColor: this.polygonFillColor,
opacity: this.polygonOpacity, thickness: this.polygonThickness, borderDashArray: '0',
notes: '', author: author, subject: subject,
- modifiedDate: modifiedDatePolygon, borderStyle: '', isCommentLock: false
+ modifiedDate: modifiedDatePolygon, borderStyle: '', isCommentLock: false, customData: customData
};
this.pdfViewer.tool = 'Polygon';
break;
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/stamp-annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/stamp-annotation.ts
index 3419a2a7e6..6e061b3f11 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/stamp-annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/stamp-annotation.ts
@@ -136,10 +136,12 @@ export class StampAnnotation {
// eslint-disable-next-line
public renderStampAnnotations(stampAnnotations: any, pageNumber: number, canvass?: any, isImport?: boolean, isAnnotOrderAction?: boolean): void {
let isStampAdded: boolean = false;
- for (let p: number = 0; p < this.stampPageNumber.length; p++) {
- if (this.stampPageNumber[p] === pageNumber && !isNullOrUndefined(isImport)){
- isStampAdded = true;
- break;
+ if (!isImport) {
+ for (let p: number = 0; p < this.stampPageNumber.length; p++) {
+ if (this.stampPageNumber[p] === pageNumber) {
+ isStampAdded = true;
+ break;
+ }
}
}
if (isImport) {
@@ -170,6 +172,9 @@ export class StampAnnotation {
let pageDiv: HTMLElement = document.getElementById(this.pdfViewer.element.id + '_pageDiv_' + pageIndex);
// eslint-disable-next-line
annotation.AnnotationSettings = annotation.AnnotationSettings ? annotation.AnnotationSettings : this.pdfViewer.annotationModule.updateSettings(this.pdfViewer.stampSettings);
+ if (annotation.IsLocked) {
+ annotation.AnnotationSettings.isLock = annotation.IsLocked;
+ }
// eslint-disable-next-line
let isImageStamp : boolean = this.stampImageData(annotation);
if (stampName && annotation['IconName'] && annotation['IconName'] !== 'Draft' && !isImageStamp && (isNullOrUndefined(annotation.template) || annotation.template === "")) {
@@ -1184,6 +1189,9 @@ export class StampAnnotation {
// eslint-disable-next-line
let storeObject: any = window.sessionStorage.getItem(this.pdfViewerBase.documentId + '_annotations_stamp');
let index: number = 0;
+ if (this.pdfViewerBase.isStorageExceed) {
+ storeObject = this.pdfViewerBase.annotationStorage[this.pdfViewerBase.documentId + '_annotations_stamp'];
+ }
if (!storeObject) {
this.pdfViewer.annotationModule.storeAnnotationCollections(annotation, pageNumber);
let shapeAnnotation: IPageAnnotations = { pageIndex: pageNumber, annotations: [] };
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/sticky-notes-annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/sticky-notes-annotation.ts
index acb8eeda3b..667e4817ef 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/sticky-notes-annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/sticky-notes-annotation.ts
@@ -914,10 +914,11 @@ export class StickyNotesAnnotation {
// eslint-disable-next-line max-len
const commentTextBox: HTMLElement = createElement('div', { id: this.pdfViewer.element.id + '_commenttextbox_'+ pageIndex + '_' + this.commentsCount, className: 'e-pv-comment-textbox', attrs: { 'role': 'textbox', 'aria-label': "comment textbox" } });
// eslint-disable-next-line
+ let enableAutoComplete: any = this.pdfViewer.enableAutoComplete ? 'on' : 'off';
let editObj: any = new InPlaceEditor({
mode: 'Inline',
type: 'Text',
- model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a comment') + '..' },
+ model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a comment') + '..' ,htmlAttributes: { autocomplete: enableAutoComplete}},
emptyText: '',
editableOn: 'EditIconClick',
saveButton: {
@@ -984,6 +985,13 @@ export class StickyNotesAnnotation {
this.createCommentDiv(this.commentsContainer);
}
}
+ //Task Id: 874405. If a comment is added programmatically, create a reply div container.
+ if (data.Note !== ' ' && data.Note !== '' && data.Note !== null) {
+ this.createCommentDiv(this.commentsContainer);
+ }
+ if (data.AnnotType === "Text Box" && data.Text !== ' ' && data.Text !== '' && data.Text !== null) {
+ this.createCommentDiv(this.commentsContainer);
+ }
}
this.isNewcommentAdded = true;
commentDiv.addEventListener('click', this.commentsDivClickEvent.bind(this));
@@ -1074,12 +1082,13 @@ export class StickyNotesAnnotation {
titleContainer = args.valueEle.parentElement.parentElement.previousSibling.childNodes[1];
}
// eslint-disable-next-line
+ let enableAutoComplete: any = this.pdfViewer.enableAutoComplete ? 'on' : 'off';
let commentObj: any = new InPlaceEditor({
mode: 'Inline',
type: 'Text',
value: '',
editableOn: 'Click',
- model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a reply') + '..' },
+ model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a reply') + '..' ,htmlAttributes: { autocomplete: enableAutoComplete}},
emptyText: this.pdfViewer.localeObj.getConstant('Add a reply'),
saveButton: {
content: this.pdfViewer.localeObj.getConstant('Post'),
@@ -1175,12 +1184,13 @@ export class StickyNotesAnnotation {
replyCommentDiv.style.borderColor = 'black';
replyCommentDiv.style.zIndex = 1002;
// eslint-disable-next-line
+ let enableAutoComplete: any = this.pdfViewer.enableAutoComplete ? 'on' : 'off';
let saveObj: any = new InPlaceEditor({
mode: 'Inline',
type: 'Text',
emptyText: '',
editableOn: 'EditIconClick',
- model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a reply') + '..' },
+ model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a reply') + '..' ,htmlAttributes: { autocomplete: enableAutoComplete}},
value: commentValue,
saveButton: {
content: this.pdfViewer.localeObj.getConstant('Post'),
@@ -1246,12 +1256,13 @@ export class StickyNotesAnnotation {
replyDiv.addEventListener('click', this.commentDivOnSelect.bind(this));
replyTextBox.addEventListener('dblclick', this.openEditorElement.bind(this));
// eslint-disable-next-line
+ let enableAutoComplete: any = this.pdfViewer.enableAutoComplete ? 'on' : 'off';
let saveObj: any = new InPlaceEditor({
mode: 'Inline',
type: 'Text',
emptyText: '',
editableOn: 'EditIconClick',
- model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a reply') + '..' },
+ model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a reply') + '..' ,htmlAttributes: { autocomplete: enableAutoComplete}},
value: '',
saveButton: {
content: this.pdfViewer.localeObj.getConstant('Post'),
@@ -1402,10 +1413,11 @@ export class StickyNotesAnnotation {
// eslint-disable-next-line max-len
const commentTextBox: HTMLElement = createElement('div', { id: this.pdfViewer.element.id + '_commenttextbox_' + pageIndex + '_' + this.commentsCount, className: 'e-pv-comment-textbox', attrs: { 'role': 'textbox', 'aria-label': "comment textbox" } });
// eslint-disable-next-line
+ let enableAutoComplete: any = this.pdfViewer.enableAutoComplete ? 'on' : 'off';
let editObj: any = new InPlaceEditor({
mode: 'Inline',
type: 'Text',
- model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a comment') + '..' },
+ model: { placeholder: this.pdfViewer.localeObj.getConstant('Add a comment') + '..' ,htmlAttributes: { autocomplete: enableAutoComplete}},
emptyText: '',
editableOn: 'EditIconClick',
saveButton: {
@@ -1858,7 +1870,7 @@ export class StickyNotesAnnotation {
if (isCommentLocked) {
event.currentTarget.nextSibling.ej2_instances[0].enableEditMode = false;
} else if (event.currentTarget && event.target) {
- let isLocked : boolean = this.checkAnnotationSettings(event.target.id);
+ let isLocked : boolean = this.checkAnnotationSettings(event.currentTarget.id);
if (!isLocked) {
event.currentTarget.nextSibling.ej2_instances[0].enableEditMode = true;
}
@@ -1885,7 +1897,7 @@ export class StickyNotesAnnotation {
for (let i: number = 0; i < annotCollection.length; i++) {
// eslint-disable-next-line max-len
annotCollection[i].annotationSettings = !isNullOrUndefined(annotCollection[i].annotationSettings) ? annotCollection[i].annotationSettings : {};
- const note: string = annotCollection[i].note ? annotCollection[i].note : annotCollection[i].notes;
+ const note: string = !isNullOrUndefined(annotCollection[i].note) ? annotCollection[i].note : annotCollection[i].notes;
if (annotCollection[i].annotationSettings.isLock && (commentEvent.textContent === note || annotCollection[i].dynamicText === commentEvent.textContent)) {
return true;
}
@@ -1912,7 +1924,7 @@ export class StickyNotesAnnotation {
if (isCommentLocked) {
event.currentTarget.ej2_instances[0].enableEditMode = false;
} else if (event.currentTarget && event.target) {
- let isLocked : boolean = this.checkAnnotationSettings(event.target.id);
+ let isLocked : boolean = this.checkAnnotationSettings(event.currentTarget.id);
if (!isLocked) {
if (!isNullOrUndefined(this.pdfViewer.selectedItems) && this.pdfViewer.selectedItems.annotations[0] && this.pdfViewer.selectedItems.annotations[0].isReadonly) {
event.currentTarget.ej2_instances[0].enableEditMode = false;
@@ -2040,7 +2052,7 @@ export class StickyNotesAnnotation {
event.currentTarget.childNodes[1].ej2_instances[0].enableEditMode = false;
}
} else if (event.currentTarget && event.target) {
- const isLocked : boolean = this.checkAnnotationSettings(event.target.id);
+ const isLocked : boolean = this.checkAnnotationSettings(event.currentTarget.id);
if (!isLocked) {
if (event.currentTarget.childElementCount === 2) {
event.currentTarget.lastChild.ej2_instances[0].enableEditMode = true;
@@ -2170,7 +2182,7 @@ export class StickyNotesAnnotation {
// eslint-disable-next-line
private commentsAnnotationSelect(event: any): void {
const element: HTMLElement = event.currentTarget;
- let isLocked: boolean = this.checkAnnotationSettings(event.target.id);
+ let isLocked: boolean = this.checkAnnotationSettings(element.id);
// When the isLock is set to true, it comes and checks whether the allowedInteractions is select and set the isLock to false, In that case if enters the condition and makes the comment panel to editable mode. So, have removed the condition in openEditorElement, commentsDivClickEvent, openTextEditor,commentAnnotationSelect methods. (Task id: 835410)
if (!isLocked) {
if (element.classList.contains('e-pv-comments-border')) {
@@ -2314,25 +2326,28 @@ export class StickyNotesAnnotation {
}
}
- private checkAnnotationSettings(id: string): boolean {
+ private checkAnnotationSettings(annotId: any): boolean {
// eslint-disable-next-line
let annotationCollection: any = this.pdfViewer.annotationCollection;
- let parentDivId : string = this.pdfViewer.element.id;
if (annotationCollection) {
- for (let i: number = 0; i < annotationCollection.length; i++) {
- if(id.includes(parentDivId+"_commenttextbox") || id.includes(parentDivId+"_commentTitle") || id.includes(parentDivId+"_commentdiv")) {
- if (annotationCollection[i].annotationSettings && annotationCollection[i].annotationSettings.isLock) {
- return true;
- } else {
- return false;
- }
+ let annot: any = annotationCollection.find((annotation: { annotationId: any; }) => annotation.annotationId === annotId);
+ if (annot && annot.annotationSettings && annot.annotationSettings.isLock) {
+ if (!annot.isCommentLock && annot.comments.length === 0 && (isNullOrUndefined(annot.note) || annot.note === '') && annot.shapeAnnotationType !== "FreeText")
+ return true;
+ else if ((!isNullOrUndefined(annot.comments) && annot.comments.length > 0 && annot.comments[0].isLock) || annot.isCommentLock) {
+ return true;
+ }
+ else {
+ return false;
}
+ } else {
+ return false;
}
- return false;
} else {
return false;
}
}
+
private updateCommentsContainerWidth(): void {
const accordionContainer: HTMLElement = document.getElementById(this.pdfViewer.element.id + '_accordionContentContainer');
const commentsContentContainer: HTMLElement = document.getElementById(this.pdfViewer.element.id + '_commentscontentcontainer');
@@ -3048,6 +3063,7 @@ export class StickyNotesAnnotation {
if (poppedItem) {
this.createCommentsContainer(poppedItem, pageNumber);
this.updateUndoRedoCollections(poppedItem, pageIndex, type);
+ this.pdfViewer.annotationModule.storeAnnotationCollections(poppedItem, pageNumber-1);
}
}
diff --git a/controls/pdfviewer/src/pdfviewer/annotation/text-markup-annotation.ts b/controls/pdfviewer/src/pdfviewer/annotation/text-markup-annotation.ts
index e377a0069d..e2038e1c4e 100644
--- a/controls/pdfviewer/src/pdfviewer/annotation/text-markup-annotation.ts
+++ b/controls/pdfviewer/src/pdfviewer/annotation/text-markup-annotation.ts
@@ -589,6 +589,9 @@ export class TextMarkupAnnotation {
annotation.allowedInteractions = annotation.AllowedInteractions ? annotation.AllowedInteractions : this.pdfViewer.annotationModule.updateAnnotationAllowedInteractions(annotation);
// eslint-disable-next-line max-len
annotation.AnnotationSettings = annotation.AnnotationSettings ? annotation.AnnotationSettings : this.pdfViewer.annotationModule.updateAnnotationSettings(annotation);
+ if (annotation.IsLocked) {
+ annotation.AnnotationSettings.isLock = annotation.IsLocked;
+ }
// eslint-disable-next-line max-len
annotationObject = {
textMarkupAnnotationType: annotation.TextMarkupAnnotationType, color: annotation.Color, allowedInteractions: annotation.allowedInteractions, opacity: annotation.Opacity, bounds: annotation.Bounds, author: annotation.Author, subject: annotation.Subject, modifiedDate: annotation.ModifiedDate, note: annotation.Note, rect: annotation.Rect,
@@ -1943,10 +1946,10 @@ export class TextMarkupAnnotation {
// eslint-disable-next-line
private getAnnotationBounds(bounds: any, pageIndex: number): any {
- let left: number = bounds.left ? bounds.left : bounds.Left;
- let top: number = bounds.top ? bounds.top : bounds.Top;
- const height: number = bounds.height ? bounds.height : bounds.Height;
- const width: number = bounds.width ? bounds.width : bounds.Width;
+ let left: number = !isNullOrUndefined(bounds.left) ? bounds.left : bounds.Left;
+ let top: number = !isNullOrUndefined(bounds.top) ? bounds.top : bounds.Top;
+ const height: number = !isNullOrUndefined(bounds.height) ? bounds.height : bounds.Height;
+ const width: number = !isNullOrUndefined(bounds.width) ? bounds.width : bounds.Width;
const pageDetails: ISize = this.pdfViewerBase.pageSize[pageIndex];
left = left ? left : bounds.x;
top = top ? top : bounds.y;
diff --git a/controls/pdfviewer/src/pdfviewer/base/pdfviewer-base.ts b/controls/pdfviewer/src/pdfviewer/base/pdfviewer-base.ts
index b5637e701e..a22655bbb7 100644
--- a/controls/pdfviewer/src/pdfviewer/base/pdfviewer-base.ts
+++ b/controls/pdfviewer/src/pdfviewer/base/pdfviewer-base.ts
@@ -2828,7 +2828,7 @@ export class PdfViewerBase {
private wireEvents(): void {
this.isDeviceiOS = ((['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'] as any).includes(navigator.platform) || (navigator.userAgent.includes("Mac") && "ontouchend" in document));
this.isMacSafari = navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1 && !this.isDeviceiOS;
- this.isWebkitMobile = /Chrome/.test(navigator.userAgent) || /Google Inc/.test(navigator.vendor) || (navigator.userAgent.indexOf('Safari') !== -1);
+ this.isWebkitMobile = /Chrome/.test(navigator.userAgent) || /Google Inc/.test(navigator.vendor) || (navigator.userAgent.indexOf('Safari') !== -1) || (navigator.userAgent.indexOf('WebKit') !== -1);
this.viewerContainer.addEventListener('scroll', this.viewerContainerOnScroll, true);
if (Browser.isDevice && !this.pdfViewer.enableDesktopMode) {
this.viewerContainer.addEventListener('touchmove', this.viewerContainerOnScroll, true);
@@ -5218,7 +5218,7 @@ export class PdfViewerBase {
topValue = this.pageGap;
}
// eslint-disable-next-line max-len
- const size: ISize = { width: parseFloat(pageSize[0]), height: parseFloat(pageSize[1]), top: topValue, rotation: !isNullOrUndefined(pageValues.pageRotation) && pageValues.pageRotation.length > 0 ? pageValues.pageRotation[parseInt(i.toString(), 10)] : 0 };
+ const size: ISize = { width: parseFloat(pageSize[0]), height: parseFloat(pageSize[1]), top: topValue, rotation: !isNullOrUndefined(pageValues.pageRotation) && ((!isNullOrUndefined(pageValues.pageRotation.length) && pageValues.pageRotation.length > 0) || (!isNullOrUndefined(Object.keys(pageValues.pageRotation).length) && Object.keys(pageValues.pageRotation).length > 0)) ? pageValues.pageRotation[parseInt(i.toString(), 10)] : 0 };
this.pageSize.push(size);
} else {
if (pageValues.pageSizes[i - 1] !== null && i !== 0) {
@@ -5229,7 +5229,7 @@ export class PdfViewerBase {
topValue = this.pageGap;
}
// eslint-disable-next-line max-len
- const size: ISize = { width: (pageValues.pageSizes[parseInt(i.toString(), 10)].width ? pageValues.pageSizes[parseInt(i.toString(), 10)].width : pageValues.pageSizes[parseInt(i.toString(), 10)].Width), height: (pageValues.pageSizes[parseInt(i.toString(), 10)].height ? pageValues.pageSizes[parseInt(i.toString(), 10)].height : pageValues.pageSizes[parseInt(i.toString(), 10)].Height), top: topValue, rotation: !isNullOrUndefined(pageValues.pageRotation) && pageValues.pageRotation.length > 0 ? pageValues.pageRotation[parseInt(i.toString(), 10)] : 0 };
+ const size: ISize = { width: (pageValues.pageSizes[parseInt(i.toString(), 10)].width ? pageValues.pageSizes[parseInt(i.toString(), 10)].width : pageValues.pageSizes[parseInt(i.toString(), 10)].Width), height: (pageValues.pageSizes[parseInt(i.toString(), 10)].height ? pageValues.pageSizes[parseInt(i.toString(), 10)].height : pageValues.pageSizes[parseInt(i.toString(), 10)].Height), top: topValue, rotation: !isNullOrUndefined(pageValues.pageRotation) && ((!isNullOrUndefined(pageValues.pageRotation.length) && pageValues.pageRotation.length > 0) || (!isNullOrUndefined(Object.keys(pageValues.pageRotation).length) && Object.keys(pageValues.pageRotation).length > 0)) ? pageValues.pageRotation[parseInt(i.toString(), 10)] : 0 };
this.pageSize.push(size);
}
if (this.pageSize[parseInt(i.toString(), 10)].height > this.pageSize[parseInt(i.toString(), 10)].width) {
@@ -5419,7 +5419,7 @@ export class PdfViewerBase {
topValue = proxy.pageGap + parseFloat(previousPageHeight) + topValue;
}
// eslint-disable-next-line max-len
- const size: ISize = { width: parseFloat(pageSize[0]), height: parseFloat(pageSize[1]), top: topValue, rotation: !isNullOrUndefined(pageValues.pageRotation) && pageValues.pageRotation.length > 0 ? pageValues.pageRotation[parseInt(i.toString(), 10)] : 0 };
+ const size: ISize = { width: parseFloat(pageSize[0]), height: parseFloat(pageSize[1]), top: topValue, rotation: !isNullOrUndefined(pageValues.pageRotation) && ((!isNullOrUndefined(pageValues.pageRotation.length) && pageValues.pageRotation.length > 0) || (!isNullOrUndefined(Object.keys(pageValues.pageRotation).length) && Object.keys(pageValues.pageRotation).length > 0)) ? pageValues.pageRotation[parseInt(i.toString(), 10)] : 0 };
proxy.pageSize.push(size);
} else {
if (proxy.pageSize[i - 1] !== null && i !== 0) {
@@ -5427,7 +5427,7 @@ export class PdfViewerBase {
topValue = proxy.pageGap + parseFloat(previousPageHeight) + topValue;
}
// eslint-disable-next-line max-len
- const size: ISize = { width: (parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].width) ? parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].width) : parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].Width)), height: (parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].height) ? parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].height) : parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].Height)), top: topValue, rotation: pageValues.pageRotation[parseInt(i.toString(), 10)] };
+ const size: ISize = { width: (parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].width) ? parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].width) : parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].Width)), height: (parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].height) ? parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].height) : parseFloat(pageValues.pageSizes[parseInt(i.toString(), 10)].Height)), top: topValue, rotation: !isNullOrUndefined(pageValues.pageRotation) && ((!isNullOrUndefined(pageValues.pageRotation.length) && pageValues.pageRotation.length > 0) || (!isNullOrUndefined(Object.keys(pageValues.pageRotation).length) && Object.keys(pageValues.pageRotation).length > 0)) ? pageValues.pageRotation[parseInt(i.toString(), 10)] : 0 };
proxy.pageSize.push(size);
}
}
@@ -7750,6 +7750,11 @@ export class PdfViewerBase {
case 'LoadedStamp':
proxy.pdfViewer.pdfRendererModule.renderer.initialPagesRendered(event.data);
break;
+ case 'textExtracted':
+ if (event.data.message === 'textExtracted') {
+ proxy.pdfViewer.pdfRendererModule.textExtractionOnmessage(event);
+ }
+ break;
}
}
}
@@ -10851,6 +10856,16 @@ export class PdfViewerBase {
return importAnnotations;
}
+ // eslint-disable-next-line
+ private setAnnotationSettings(annotation: any): void {
+ if(!isNullOrUndefined(annotation)) {
+ annotation.AnnotationSettings = annotation.AnnotationSettings ? annotation.AnnotationSettings : this.pdfViewer.annotationModule.updateAnnotationSettings(annotation);
+ if (annotation.IsLocked) {
+ annotation.AnnotationSettings.isLock = annotation.IsLocked;
+ }
+ }
+ }
+
// eslint-disable-next-line
private drawPageAnnotations(annotation: any, pageIndex: number, isNewlyAdded?: boolean): void {
@@ -10894,6 +10909,9 @@ export class PdfViewerBase {
annotationData = this.checkAnnotationCollections(annotObject, annotationData, pageIndex);
}
}
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
annotation.textMarkupAnnotation = this.checkAnnotationCommentsCollections(annotation.textMarkupAnnotation, pageIndex);
this.pdfViewer.annotationModule.renderAnnotations(pageIndex, null, null, annotationData, null, true);
break;
@@ -10907,6 +10925,9 @@ export class PdfViewerBase {
annotObject = JSON.parse(storeObject);
annotationData = this.checkAnnotationCollections(annotObject, annotationData, pageIndex);
}
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
annotation.shapeAnnotation = this.checkAnnotationCommentsCollections(annotation.shapeAnnotation, pageIndex);
this.pdfViewer.annotationModule.renderAnnotations(pageIndex, annotationData, null, null, null, true);
break;
@@ -10920,6 +10941,9 @@ export class PdfViewerBase {
annotObject = JSON.parse(storeObject);
annotationData = this.checkAnnotationCollections(annotObject, annotationData, pageIndex);
}
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
annotation.measureShapeAnnotation = this.checkAnnotationCommentsCollections(annotation.measureShapeAnnotation, pageIndex);
this.pdfViewer.annotationModule.renderAnnotations(pageIndex, null, annotationData, null, null, true);
break;
@@ -10932,6 +10956,9 @@ export class PdfViewerBase {
annotObject = JSON.parse(storeObject);
annotationData = this.checkAnnotationCollections(annotObject, annotationData, pageIndex);
}
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
annotation.stampAnnotations = this.checkAnnotationCommentsCollections(annotation.stampAnnotations, pageIndex);
this.pdfViewer.annotationModule.stampAnnotationModule.renderStampAnnotations(annotationData, pageIndex, null, true);
break;
@@ -10945,6 +10972,9 @@ export class PdfViewerBase {
annotObject = JSON.parse(storeObject);
annotationData = this.checkAnnotationCollections(annotObject, annotationData, pageIndex);
}
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
annotation.freeTextAnnotation = this.checkAnnotationCommentsCollections(annotation.freeTextAnnotation, pageIndex);
this.pdfViewer.annotationModule.freeTextAnnotationModule.renderFreeTextAnnotations(annotationData, pageIndex, true);
break;
@@ -10957,12 +10987,18 @@ export class PdfViewerBase {
annotObject = JSON.parse(storeObject);
annotationData = this.checkAnnotationCollections(annotObject, annotationData, pageIndex);
}
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
annotation.stickyNotesAnnotation = this.checkAnnotationCommentsCollections(annotation.stickyNotesAnnotation, pageIndex);
this.pdfViewer.annotationModule.stickyNotesAnnotationModule.renderStickyNotesAnnotations(annotationData, pageIndex);
break;
case 'signature':
storeObject = window.sessionStorage.getItem(this.documentId + '_annotations_sign');
annotObject = JSON.parse(storeObject);
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
if (annotObject) {
annotation.signatureAnnotation = this.checkSignatureCollections(annotObject, annotationData, pageIndex);
}
@@ -10978,6 +11014,9 @@ export class PdfViewerBase {
annotObject = JSON.parse(storeObject);
annotationData = this.checkAnnotationCollections(annotObject, annotationData, pageIndex);
}
+ if(annotationData) {
+ this.setAnnotationSettings(annotationData[0]);
+ }
annotation.signatureInkAnnotation = this.checkAnnotationCommentsCollections(annotation.signatureInkAnnotation, pageIndex);
this.pdfViewer.annotationModule.inkAnnotationModule.renderExistingInkSignature(annotationData, pageIndex, true);
break;
@@ -11599,6 +11638,7 @@ export class PdfViewerBase {
public deleteAnnotations(): void {
if (this.pdfViewer.annotationModule) {
+ this.updateAnnotationsUndoRedo();
this.pdfViewer.annotations = [];
this.pdfViewer.zIndexTable = [];
this.pdfViewer.annotationCollection = [];
@@ -11608,14 +11648,6 @@ export class PdfViewerBase {
this.annotationComments = annotationCollection;
this.documentAnnotationCollections = annotationCollection;
this.annotationRenderredList = [];
- window.sessionStorage.removeItem(this.documentId + '_annotations_shape');
- window.sessionStorage.removeItem(this.documentId + '_annotations_shape_measure');
- window.sessionStorage.removeItem(this.documentId + '_annotations_stamp');
- window.sessionStorage.removeItem(this.documentId + '_annotations_sticky');
- window.sessionStorage.removeItem(this.documentId + '_annotations_textMarkup');
- window.sessionStorage.removeItem(this.documentId + '_annotations_freetext');
- window.sessionStorage.removeItem(this.documentId + '_annotations_sign');
- window.sessionStorage.removeItem(this.documentId + '_annotations_ink');
for (let i: number = 0; i < this.pageCount; i++) {
this.pdfViewer.annotationModule.renderAnnotations(i, null, null, null);
this.pdfViewer.renderDrawing(undefined, i);
@@ -11650,6 +11682,44 @@ export class PdfViewerBase {
}
}
+ // eslint-disable-next-line
+ private updateAnnotationsUndoRedo(): void {
+ for (let j: number = 0; j < this.pdfViewer.annotationCollection.length; j++) {
+ let currentAnnotation: any = null;
+ let proxy: any = this;
+ if (proxy.pdfViewer.annotationCollection[j].shapeAnnotationType === "textMarkup") {
+ currentAnnotation = proxy.pdfViewer.annotationCollection[parseInt(j.toString(), 10)];
+ let pageAnnotations: any = proxy.pdfViewer.annotation.textMarkupAnnotationModule.getAnnotations(currentAnnotation.pageNumber, null);
+ if (pageAnnotations) {
+ for (let i: number = 0; i < pageAnnotations.length; i++) {
+ if (currentAnnotation.annotationId === pageAnnotations[parseInt(i.toString(), 10)].annotName) {
+ let deletedAnnotation: any = pageAnnotations.splice(parseInt(i.toString(), 10), 1)[0];
+ proxy.pdfViewer.annotation.addAction(currentAnnotation.pageNumber, parseInt(i.toString(), 10), deletedAnnotation, 'Text Markup Deleted', null);
+ proxy.pdfViewer.annotation.stickyNotesAnnotationModule.findPosition(deletedAnnotation, 'textMarkup');
+ let removeDiv: any = document.getElementById(deletedAnnotation.annotName);
+ if (removeDiv) {
+ if (removeDiv.parentElement.childElementCount === 1) {
+ proxy.pdfViewer.annotationModule.stickyNotesAnnotationModule.updateAccordionContainer(removeDiv);
+ }
+ else {
+ removeDiv.remove();
+ }
+ }
+ }
+ }
+ }
+ proxy.pdfViewer.annotation.textMarkupAnnotationModule.manageAnnotations(pageAnnotations, currentAnnotation.pageNumber);
+ }
+ else {
+ currentAnnotation = proxy.pdfViewer.annotations.filter(function (s: { annotName: any; }) { return s.annotName === proxy.pdfViewer.annotationCollection[parseInt(j.toString(), 10)].annotationId; })[0];
+ let undoElement: any = proxy.pdfViewer.annotation.modifyInCollections(currentAnnotation, 'delete');
+ proxy.pdfViewer.annotation.undoCommentsElement.push(undoElement);
+ proxy.pdfViewer.annotation.addAction(currentAnnotation.pageIndex, null, currentAnnotation, 'Delete', '', undoElement, currentAnnotation);
+ proxy.pdfViewer.annotation.textMarkupAnnotationModule.manageAnnotations(currentAnnotation, currentAnnotation.pageNumber);
+ }
+ }
+ }
+
/**
* @param pageNumber
* @param isObject
diff --git a/controls/pdfviewer/src/pdfviewer/base/signature.ts b/controls/pdfviewer/src/pdfviewer/base/signature.ts
index b5b046e20c..34e56b4332 100644
--- a/controls/pdfviewer/src/pdfviewer/base/signature.ts
+++ b/controls/pdfviewer/src/pdfviewer/base/signature.ts
@@ -1608,6 +1608,7 @@ export class Signature {
};
private renderSignatureText(): void {
let maximumWidth: number = 750;
+ let enableButtons: boolean;
// eslint-disable-next-line
let fontDiv: any = document.getElementById(this.pdfViewer.element.id + '_font_appearance');
// eslint-disable-next-line
@@ -1628,8 +1629,14 @@ export class Signature {
let clickSign: any = document.getElementById('_font_signature' + i + '');
clickSign.addEventListener('click', this.typeSignatureclick.bind(this));
}
- this.enableCreateButton(false);
- this.enableClearbutton(false);
+ if (textBox.value.trim() === "") {
+ enableButtons = true;
+ }
+ else {
+ enableButtons = false;
+ }
+ this.enableCreateButton(enableButtons);
+ this.enableClearbutton(enableButtons);
if (this.pdfViewer.element.offsetWidth < maximumWidth)
this.updateCanvasSize();
this.drawSignOnTabSwitch();
@@ -1637,21 +1644,23 @@ export class Signature {
private typeSignatureclick(): void {
const eventTarget: HTMLElement = event.target as HTMLElement;
// eslint-disable-next-line
- let createButton: any = document.getElementsByClassName('e-pv-createbtn')[0];
- createButton.disabled = false;
- for (let i: number = 0; i < 4; i++) {
- // eslint-disable-next-line
- let fontElement: any = document.getElementById('_font_signature' + i + '');
- if (fontElement) {
- fontElement.style.borderColor = '';
+ if (eventTarget.textContent.trim() !== "") {
+ let createButton: any = document.getElementsByClassName('e-pv-createbtn')[0];
+ createButton.disabled = false;
+ for (let i: number = 0; i < 4; i++) {
+ // eslint-disable-next-line
+ let fontElement: any = document.getElementById('_font_signature' + i + '');
+ if (fontElement) {
+ fontElement.style.borderColor = '';
+ }
+ }
+ eventTarget.style.borderColor = 'red';
+ this.outputString = eventTarget.textContent;
+ try {
+ this.fontName = JSON.parse(eventTarget.style.fontFamily);
+ } catch (e) {
+ this.fontName = eventTarget.style.fontFamily;
}
- }
- eventTarget.style.borderColor = 'red';
- this.outputString = eventTarget.textContent;
- try {
- this.fontName = JSON.parse(eventTarget.style.fontFamily);
- } catch (e) {
- this.fontName = eventTarget.style.fontFamily;
}
}
/**
diff --git a/controls/pdfviewer/src/pdfviewer/drawing/drawing.ts b/controls/pdfviewer/src/pdfviewer/drawing/drawing.ts
index a428f907f1..fad74d8250 100644
--- a/controls/pdfviewer/src/pdfviewer/drawing/drawing.ts
+++ b/controls/pdfviewer/src/pdfviewer/drawing/drawing.ts
@@ -843,7 +843,7 @@ export class Drawing {
options: (obj as any).options, isChecked: (obj as any).isChecked, isSelected: (obj as any).isSelected
};
this.pdfViewer.fireFormFieldRemoveEvent('formFieldRemove', field, obj.pageIndex);
- this.pdfViewer.formDesignerModule.removeFieldsFromAnnotationCollections(obj.id);
+ this.pdfViewer.formDesignerModule.removeFieldsFromAnnotationCollections(obj.id, field.name);
}
}
this.pdfViewer.enableServerDataBinding(allowServerDataBind, true);
diff --git a/controls/pdfviewer/src/pdfviewer/form-designer/form-designer.ts b/controls/pdfviewer/src/pdfviewer/form-designer/form-designer.ts
index 67c1433c85..affe5fb945 100644
--- a/controls/pdfviewer/src/pdfviewer/form-designer/form-designer.ts
+++ b/controls/pdfviewer/src/pdfviewer/form-designer/form-designer.ts
@@ -3410,9 +3410,11 @@ export class FormDesigner {
/**
* @private
*/
- public removeFieldsFromAnnotationCollections(annotationId: string): any {
+ public removeFieldsFromAnnotationCollections(annotationId: string, fieldName: string): any {
var data = this.pdfViewerBase.getItemFromSessionStorage('_formDesigner');
var formFieldsData = JSON.parse(data);
+ let sessiondata : string = this.pdfViewerBase.getItemFromSessionStorage('_formfields');
+ let sessionformFields: any = JSON.parse(sessiondata);
for (let i: number = 0; i < formFieldsData.length; i++) {
if (formFieldsData[i].Key.split("_")[0] === annotationId) {
formFieldsData.splice(i, 1);
@@ -3420,6 +3422,15 @@ export class FormDesigner {
break;
}
}
+ if (!isNullOrUndefined(sessionformFields)) {
+ for (let i: number = 0; i < sessionformFields.length; i++) {
+ if (sessionformFields[i].FieldName === fieldName) {
+ sessionformFields.splice(parseInt(i.toString(), 10), 1);
+ sessionStorage.setItem(this.pdfViewerBase.documentId + '_formfields', JSON.stringify(sessionformFields));
+ break;
+ }
+ }
+ }
this.pdfViewerBase.setItemInSessionStorage(this.pdfViewerBase.formFieldCollection, '_formDesigner');
let storeObject: string = window.sessionStorage.getItem(this.pdfViewerBase.documentId + '_annotations_shape');
if (storeObject) {
diff --git a/controls/pdfviewer/src/pdfviewer/pdf-base/annotation-renderer.ts b/controls/pdfviewer/src/pdfviewer/pdf-base/annotation-renderer.ts
index 39cb811410..1902e2788b 100644
--- a/controls/pdfviewer/src/pdfviewer/pdf-base/annotation-renderer.ts
+++ b/controls/pdfviewer/src/pdfviewer/pdf-base/annotation-renderer.ts
@@ -1075,7 +1075,7 @@ export class AnnotationRenderer {
let appearance: PdfTemplate = rubberStampAnnotation.appearance.normal;
const dictionary: _PdfDictionary = new _PdfDictionary(page._crossReference);
const state: PdfGraphicsState = graphics.save();
- let template: PdfTemplate = new PdfTemplate();
+ let template: PdfTemplate = new PdfTemplate(stampAnnotation.template, dictionary._crossReference);
template._isExported = true;
template._appearance = stampAnnotation.template;
template._crossReference = dictionary._crossReference;
diff --git a/controls/pdfviewer/src/pdfviewer/pdf-base/pdf-renderer.ts b/controls/pdfviewer/src/pdfviewer/pdf-base/pdf-renderer.ts
index b830bf3f51..33c81a9f10 100644
--- a/controls/pdfviewer/src/pdfviewer/pdf-base/pdf-renderer.ts
+++ b/controls/pdfviewer/src/pdfviewer/pdf-base/pdf-renderer.ts
@@ -174,7 +174,7 @@ export class PdfRenderer {
this.m_formFields.showDigitalSignatureAppearance = jsonObject["showDigitalSignatureAppearance"];
}
}
- if (!isNullOrUndefined(this.m_formFields) && this.pageCount <= 100) {
+ if (!isNullOrUndefined(this.m_formFields) && this.pageSizes && Object.keys(this.pageSizes).length <=100) {
this.m_formFields.GetFormFields();
pdfRenderedFormFields = this.m_formFields.PdfRenderedFormFields;
}
@@ -1139,42 +1139,9 @@ export class PdfRenderer {
// eslint-disable-next-line max-len
private textExtraction(pageIndex: number, isLayout: boolean, isRenderText?: boolean): Promise {
- let extractedText: string = '';
- let textDataCollection: TextData[] = [];
- let proxy: PdfRenderer = this;
return new Promise((resolve: Function, reject: Function) => {
if (!isNullOrUndefined(this.pdfViewerBase.pdfViewerRunner)) {
this.pdfViewerBase.pdfViewerRunner.postMessage({ pageIndex: pageIndex, message: 'extractText', zoomFactor: this.pdfViewer.magnificationModule.zoomFactor, isTextNeed: true });
- this.pdfViewerBase.pdfViewerRunner.onmessage = function (event: any) {
- if (event.data.message === 'textExtracted') {
- const characterDetails: any = event.data.characterBounds;
- for (let i: number = 0; i < characterDetails.length; i++) {
- if (!isLayout && (characterDetails[parseInt(i.toString(), 10)].Text as string).indexOf('\r') !== -1) {
- extractedText += '';
- }
- else {
- extractedText += characterDetails[parseInt(i.toString(), 10)].Text;
- }
- const cropBox: number[] = proxy.loadedDocument.getPage(pageIndex).cropBox;
- // eslint-disable-next-line max-len
- const bound: AnnotBounds = new AnnotBounds(proxy.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].X), proxy.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].Y + cropBox[1]), proxy.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].Width), proxy.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].Height));
- textDataCollection.push(new TextData(characterDetails[parseInt(i.toString(), 10)].Text, bound));
- }
- let result: any = {};
- if (isRenderText) {
- result.extractedTextDetails = { textDataCollection: textDataCollection, extractedText: extractedText };
- result.textBounds = event.data.textBounds;
- result.textContent = event.data.textContent;
- result.rotation = event.data.rotation;
- result.pageText = event.data.pageText;
- result.characterBounds = event.data.characterBounds;
- }
- else{
- result = { textDataCollection: textDataCollection, extractedText: extractedText };
- }
- resolve(result);
- }
- };
}
else {
resolve(null);
@@ -1182,6 +1149,44 @@ export class PdfRenderer {
});
}
+ /**
+ * @private
+ */
+ public textExtractionOnmessage(event: any) {
+ let extractedText: string = '';
+ let textDataCollection: TextData[] = [];
+ return new Promise((resolve: Function, reject: Function) => {
+ if (event.data.message === 'textExtracted') {
+ const characterDetails: any = event.data.characterBounds;
+ for (let i: number = 0; i < characterDetails.length; i++) {
+ if (!event.data.isLayout && (characterDetails[parseInt(i.toString(), 10)].Text as string).indexOf('\r') !== -1) {
+ extractedText += '';
+ }
+ else {
+ extractedText += characterDetails[parseInt(i.toString(), 10)].Text;
+ }
+ const cropBox: number[] = this.loadedDocument.getPage(event.data.pageIndex).cropBox;
+ // eslint-disable-next-line max-len
+ const bound: AnnotBounds = new AnnotBounds(this.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].X), this.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].Y + cropBox[1]), this.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].Width), this.convertPixelToPoint(characterDetails[parseInt(i.toString(), 10)].Height));
+ textDataCollection.push(new TextData(characterDetails[parseInt(i.toString(), 10)].Text, bound));
+ }
+ let result: any = {};
+ if (event.data.isRenderText) {
+ result.extractedTextDetails = { textDataCollection: textDataCollection, extractedText: extractedText };
+ result.textBounds = event.data.textBounds;
+ result.textContent = event.data.textContent;
+ result.rotation = event.data.rotation;
+ result.pageText = event.data.pageText;
+ result.characterBounds = event.data.characterBounds;
+ }
+ else{
+ result = { textDataCollection: textDataCollection, extractedText: extractedText };
+ }
+ resolve(result);
+ }
+ });
+ }
+
public extractTextWithPageSize(pageIndex: number): Promise<{[key: number]: PageTextData}>{
return new Promise((resolve: Function, reject: Function) => {
resolve(this.extractTextDetailsWithPageSize(pageIndex));
diff --git a/controls/pdfviewer/src/pdfviewer/pdfium/pdfium-runner.ts b/controls/pdfviewer/src/pdfviewer/pdfium/pdfium-runner.ts
index c9302fe896..4e2b6ebdc6 100644
--- a/controls/pdfviewer/src/pdfviewer/pdfium/pdfium-runner.ts
+++ b/controls/pdfviewer/src/pdfviewer/pdfium/pdfium-runner.ts
@@ -197,6 +197,8 @@ export function PdfiumRunner(): void {
let ImageData: any = event.data;
let data: object = firstPage.render(null, ImageData.zoomFactor, ImageData.isTextNeed, null, null, ImageData.textDetailsId);
(data as any).message = 'textExtracted';
+ (data as any).isLayout = event.data.isLayout;
+ (data as any).isRenderText = event.data.isRenderText;
ctx.postMessage(data);
}
else if (event.data.message === 'renderThumbnail') {
diff --git a/controls/pdfviewer/src/pdfviewer/pdfviewer.ts b/controls/pdfviewer/src/pdfviewer/pdfviewer.ts
index 4c2527daa5..5d194a0eec 100644
--- a/controls/pdfviewer/src/pdfviewer/pdfviewer.ts
+++ b/controls/pdfviewer/src/pdfviewer/pdfviewer.ts
@@ -7858,10 +7858,12 @@ export class PdfViewer extends Component implements INotifyProperty
case 'toolbarSettings':
if (!Browser.isDevice || this.enableDesktopMode) {
this.toolbar.applyToolbarSettings();
- if (!isNullOrUndefined(this.toolbar.annotationToolbarModule) && !isNullOrUndefined(this.toolbar.formDesignerToolbarModule)) {
- this.toolbar.annotationToolbarModule.applyAnnotationToolbarSettings();
- this.toolbar.formDesignerToolbarModule.applyFormDesignerToolbarSettings();
- }
+ if (!isNullOrUndefined(this.toolbar.annotationToolbarModule)) {
+ this.toolbar.annotationToolbarModule.applyAnnotationToolbarSettings();
+ }
+ if (!isNullOrUndefined(this.toolbar.formDesignerToolbarModule)) {
+ this.toolbar.formDesignerToolbarModule.applyFormDesignerToolbarSettings();
+ }
}
else {
this.toolbar.applyToolbarSettingsForMobile();
diff --git a/controls/pdfviewer/src/pdfviewer/text-selection/text-selection.ts b/controls/pdfviewer/src/pdfviewer/text-selection/text-selection.ts
index 180d2d0fce..3c2d9f38d2 100644
--- a/controls/pdfviewer/src/pdfviewer/text-selection/text-selection.ts
+++ b/controls/pdfviewer/src/pdfviewer/text-selection/text-selection.ts
@@ -1918,10 +1918,10 @@ export class TextSelection {
// eslint-disable-next-line max-len
const topPositionValue: string = topClientValue + pageTopValue * this.pdfViewerBase.getZoomFactor() + (dropElementRect.height / 2) * this.pdfViewerBase.getZoomFactor() + 'px';
this.dropDivElementLeft.style.top = topPositionValue;
- this.dropDivElementLeft.style.left = rangePosition.left - (viewerLeftPosition + (dropElementRect.width)) + 'px';
+ this.dropDivElementLeft.style.left = rangePosition.left - (viewerLeftPosition + (dropElementRect.width)) + this.pdfViewerBase.viewerContainer.scrollLeft + 'px';
this.dropDivElementRight.style.top = topPositionValue;
// eslint-disable-next-line max-len
- this.dropDivElementRight.style.left = rangePosition.left + rangePosition.width - viewerLeftPosition + 'px';
+ this.dropDivElementRight.style.left = rangePosition.left + rangePosition.width - viewerLeftPosition + this.pdfViewerBase.viewerContainer.scrollLeft + 'px';
const currentPageLeft: number = this.pdfViewerBase.getElement('_pageDiv_' + (this.pdfViewerBase.currentPageNumber - 1)).getBoundingClientRect().left;
const currentRangeLeft: number = rangePosition.left - currentPageLeft;
// eslint-disable-next-line max-len
@@ -2032,12 +2032,14 @@ export class TextSelection {
this.fireTextSelectEnd();
let top: any = event.changedTouches[0].clientY + event.currentTarget.clientHeight;
var spanBounds = this.getSpanBounds();
- if ((spanBounds.bottom + this.contextMenuHeight + this.pdfViewerBase.toolbarHeight) > window.innerHeight) {
- top = spanBounds.top - (this.contextMenuHeight + this.pdfViewerBase.toolbarHeight);
- } else {
- top = spanBounds.bottom + this.pdfViewerBase.toolbarHeight - topMargin;
+ if(spanBounds) {
+ if ((spanBounds.bottom + this.contextMenuHeight + this.pdfViewerBase.toolbarHeight) > window.innerHeight) {
+ top = spanBounds.top - (this.contextMenuHeight + this.pdfViewerBase.toolbarHeight);
+ } else {
+ top = spanBounds.bottom + this.pdfViewerBase.toolbarHeight - topMargin;
+ }
+ this.pdfViewerBase.contextMenuModule.open(top, (spanBounds.right - spanBounds.left) / 2, this.pdfViewerBase.viewerContainer);
}
- this.pdfViewerBase.contextMenuModule.open(top, (spanBounds.right - spanBounds.left) / 2, this.pdfViewerBase.viewerContainer);
}
}
@@ -2098,7 +2100,7 @@ export class TextSelection {
this.dropDivElementLeft.style.top = pageTopValue * this.pdfViewerBase.getZoomFactor() + topClientValue + 'px';
this.topStoreLeft = { pageTop: pageTopValue, topClientValue: this.getMagnifiedValue(topClientValue), pageNumber: this.pdfViewerBase.currentPageNumber - 1, left: this.getMagnifiedValue(currentRangeLeft), isHeightNeeded: false };
// eslint-disable-next-line max-len
- this.dropDivElementLeft.style.left = xTouch - this.pdfViewerBase.viewerContainer.getBoundingClientRect().left - (elementClientRect.width / 2) + 'px';
+ this.dropDivElementLeft.style.left = xTouch - this.pdfViewerBase.viewerContainer.getBoundingClientRect().left - (elementClientRect.width / 2) + this.pdfViewerBase.viewerContainer.scrollLeft + 'px';
this.previousScrollDifference = currentDifference;
}
}
@@ -2144,7 +2146,7 @@ export class TextSelection {
// eslint-disable-next-line max-len
this.topStoreRight = { pageTop: pageTopValue, topClientValue: this.getMagnifiedValue(topClientValue), pageNumber: this.pdfViewerBase.currentPageNumber - 1, left: this.getMagnifiedValue(currentRangeLeft), isHeightNeeded: false };
// eslint-disable-next-line max-len
- this.dropDivElementRight.style.left = touchX - this.pdfViewerBase.viewerContainer.getBoundingClientRect().left - (elementClientRect.width / 2) + 'px';
+ this.dropDivElementRight.style.left = touchX - this.pdfViewerBase.viewerContainer.getBoundingClientRect().left - (elementClientRect.width / 2) + this.pdfViewerBase.viewerContainer.scrollLeft + 'px';
this.previousScrollDifference = currentDifference;
}
}
diff --git a/controls/pdfviewer/src/pdfviewer/toolbar/annotation-toolbar.ts b/controls/pdfviewer/src/pdfviewer/toolbar/annotation-toolbar.ts
index ceeb99587b..585c946e80 100644
--- a/controls/pdfviewer/src/pdfviewer/toolbar/annotation-toolbar.ts
+++ b/controls/pdfviewer/src/pdfviewer/toolbar/annotation-toolbar.ts
@@ -394,22 +394,26 @@ export class AnnotationToolbar {
if (!isNullOrUndefined(this.pdfViewer.annotationModule.textMarkupAnnotationModule) && !this.pdfViewer.annotationModule.textMarkupAnnotationModule.currentTextMarkupAnnotation) {
id = this.pdfViewer.element.id + '_underlineIcon';
}
- else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'FreeText') {
- id = this.pdfViewer.element.id + '_annotation_freeTextEdit';
- // eslint-disable-next-line max-len
- } else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Stamp' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'StickyNotes' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Image') {
- id = this.pdfViewer.element.id + '_annotation_stamp';
- // eslint-disable-next-line max-len
- } else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'HandWrittenSignature' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'SignatureText') {
- id = this.pdfViewer.element.id + '_annotation_handwrittenSign';
- } else if(this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'SignatureImage'){
- id = this.pdfViewer.element.id + '_annotation_handwrittenImage';
- }else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Ink' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Path') {
- id = this.pdfViewer.element.id + '_annotation_inkIcon';
- } else if (shapeType === 'Highlight' || shapeType === 'Underline' || shapeType === 'Strikethrough') {
- id = this.pdfViewer.element.id + '_highlightIcon';
- } else {
- id = this.pdfViewer.element.id + '_annotation_shapesIcon';
+ else {
+ if (this.pdfViewer.selectedItems.annotations[0]) {
+ if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'FreeText') {
+ id = this.pdfViewer.element.id + '_annotation_freeTextEdit';
+ // eslint-disable-next-line max-len
+ } else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Stamp' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'StickyNotes' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Image') {
+ id = this.pdfViewer.element.id + '_annotation_stamp';
+ // eslint-disable-next-line max-len
+ } else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'HandWrittenSignature' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'SignatureText') {
+ id = this.pdfViewer.element.id + '_annotation_handwrittenSign';
+ } else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'SignatureImage') {
+ id = this.pdfViewer.element.id + '_annotation_handwrittenImage';
+ } else if (this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Ink' || this.pdfViewer.selectedItems.annotations[0].shapeAnnotationType === 'Path') {
+ id = this.pdfViewer.element.id + '_annotation_inkIcon';
+ } else if (shapeType === 'Highlight' || shapeType === 'Underline' || shapeType === 'Strikethrough') {
+ id = this.pdfViewer.element.id + '_highlightIcon';
+ } else {
+ id = this.pdfViewer.element.id + '_annotation_shapesIcon';
+ }
+ }
}
this.pdfViewer.toolbarModule.annotationToolbarModule.mobileColorpicker(id);
}
diff --git a/controls/pivotview/CHANGELOG.md b/controls/pivotview/CHANGELOG.md
index dfe0fc1d62..d475d99354 100644
--- a/controls/pivotview/CHANGELOG.md
+++ b/controls/pivotview/CHANGELOG.md
@@ -2,6 +2,15 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### PivotTable
+
+#### Bug fixes
+
+- `#I562279`,`#I565475`,`#I566747` - The pivot table will now be properly displayed after engine export.
+- `#I566095` - The filter text will now be properly displayed in the OLAP Pivot Table's filter field button.
+
## 25.1.35 (2024-03-15)
### PivotTable
diff --git a/controls/pivotview/package.json b/controls/pivotview/package.json
index 6fb95035e5..d425460625 100644
--- a/controls/pivotview/package.json
+++ b/controls/pivotview/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-pivotview",
- "version": "24.1.43",
+ "version": "25.1.35",
"description": "The pivot grid, or pivot table, is used to visualize large sets of relational data in a cross-tabular format, similar to an Excel pivot table.",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/pivotview/spec/field-list/defer-update.spec.ts b/controls/pivotview/spec/field-list/defer-update.spec.ts
index a9b12a6ba0..15cb82c611 100644
--- a/controls/pivotview/spec/field-list/defer-update.spec.ts
+++ b/controls/pivotview/spec/field-list/defer-update.spec.ts
@@ -32,6 +32,16 @@ describe('Pivot Field List Rendering - Defer Update', () => {
}
});
describe('Check pivot button drag and drop Actions', () => {
+ let down: MouseEvent = new MouseEvent('mousedown', {
+ 'view': window,
+ 'bubbles': true,
+ 'cancelable': true,
+ });
+ let up: MouseEvent = new MouseEvent('mouseup', {
+ 'view': window,
+ 'bubbles': true,
+ 'cancelable': true,
+ });
let fieldListObj: PivotFieldList;
let pivotGridObj: PivotView;
let pivotCommon: PivotCommon;
@@ -176,8 +186,9 @@ describe('Pivot Field List Rendering - Defer Update', () => {
let treeObj: TreeView = fieldListObj.treeViewModule.fieldTable;
let checkEle: Element[] = >treeObj.element.querySelectorAll('.e-checkbox-wrapper');
expect(checkEle.length).toBeGreaterThan(0);
- util.checkTreeNode(treeObj, closest(checkEle[0], 'li'));
- expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(7);
+ closest(checkEle[0], 'li').dispatchEvent(down);
+ closest(checkEle[0], 'li').dispatchEvent(up);
+ expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(6);
});
it('Cancel button', (done: Function) => {
document.getElementById('PivotFieldList_DeferUpdateButton2').click();
@@ -191,15 +202,16 @@ describe('Pivot Field List Rendering - Defer Update', () => {
let treeObj: TreeView = fieldListObj.treeViewModule.fieldTable;
let checkEle: Element[] = >treeObj.element.querySelectorAll('.e-checkbox-wrapper');
expect(checkEle.length).toBeGreaterThan(0);
- util.checkTreeNode(treeObj, closest(checkEle[0], 'li'));
- expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(7);
+ closest(checkEle[0], 'li').dispatchEvent(down);
+ closest(checkEle[0], 'li').dispatchEvent(up);
+ expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(6);
done();
});
});
it('Apply button', (done: Function) => {
setTimeout(() => {
document.getElementById('PivotFieldList_DeferUpdateButton1').click();
- expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(7);
+ expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(6);
done();
});
});
@@ -208,7 +220,8 @@ describe('Pivot Field List Rendering - Defer Update', () => {
let treeObj: TreeView = fieldListObj.treeViewModule.fieldTable;
let checkEle: Element[] = >treeObj.element.querySelectorAll('.e-checkbox-wrapper');
expect(checkEle.length).toBeGreaterThan(0);
- util.checkTreeNode(treeObj, closest(checkEle[0], 'li'));
+ closest(checkEle[0], 'li').dispatchEvent(down);
+ closest(checkEle[0], 'li').dispatchEvent(up);
expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(7);
done();
});
@@ -216,7 +229,7 @@ describe('Pivot Field List Rendering - Defer Update', () => {
it('Cancel button', (done: Function) => {
document.getElementById('PivotFieldList_DeferUpdateButton2').click();
setTimeout(() => {
- expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(7);
+ expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(6);
done();
});
});
@@ -224,7 +237,8 @@ describe('Pivot Field List Rendering - Defer Update', () => {
let treeObj: TreeView = fieldListObj.treeViewModule.fieldTable;
let checkEle: Element[] = >treeObj.element.querySelectorAll('.e-checkbox-wrapper');
expect(checkEle.length).toBeGreaterThan(0);
- util.checkTreeNode(treeObj, closest(checkEle[0], 'li'));
+ closest(checkEle[0], 'li').dispatchEvent(down);
+ closest(checkEle[0], 'li').dispatchEvent(up);
setTimeout(() => {
expect(pivotGridObj.element.querySelectorAll('.e-pivot-button').length).toBe(7);
done();
@@ -271,7 +285,8 @@ describe('Pivot Field List Rendering - Defer Update', () => {
let checkEle: Element[] = >memberTreeObj.element.querySelectorAll('.e-checkbox-wrapper');
expect(checkEle.length).toBeGreaterThan(0);
expect(allNode.classList.contains('e-small')).toBe(false);
- util.checkTreeNode(treeObj, closest(allNode, 'li'));
+ closest(allNode, 'li').dispatchEvent(down);
+ closest(allNode, 'li').dispatchEvent(up);
let checkedEle: Element[] = >memberTreeObj.element.querySelectorAll('.e-check');
expect(checkEle.length).toEqual(2);
(fieldListObj.pivotCommon.filterDialog.dialogPopUp.element.querySelector('.e-ok-btn') as HTMLElement).click();
@@ -309,7 +324,8 @@ describe('Pivot Field List Rendering - Defer Update', () => {
let checkEle: Element[] = >memberTreeObj.element.querySelectorAll('.e-checkbox-wrapper');
expect(checkEle.length).toBeGreaterThan(0);
expect(allNode.classList.contains('e-small')).toBe(false);
- util.checkTreeNode(treeObj, closest(allNode, 'li'));
+ closest(allNode, 'li').dispatchEvent(down);
+ closest(allNode, 'li').dispatchEvent(up);
let checkedEle: Element[] = >memberTreeObj.element.querySelectorAll('.e-check');
expect(checkEle.length).toEqual(2);
expect(fieldListObj.pivotCommon.filterDialog.dialogPopUp.element.querySelector('.e-ok-btn').getAttribute('disabled')).toBe(null);
diff --git a/controls/pivotview/spec/field-list/pivotfieldlist.spec.ts b/controls/pivotview/spec/field-list/pivotfieldlist.spec.ts
index 08bab8a86b..5916f7d48c 100644
--- a/controls/pivotview/spec/field-list/pivotfieldlist.spec.ts
+++ b/controls/pivotview/spec/field-list/pivotfieldlist.spec.ts
@@ -222,7 +222,6 @@ describe('PivotFieldList spec', () => {
describe('Pivot Field List Rendering', () => {
describe('Field List with Tree Node Action', () => {
let fieldListObj: PivotFieldList;
- let pivotCommon: PivotCommon;
let elem: HTMLElement = createElement('div', { id: 'PivotFieldList', styles: 'height:400px;width:60%' });
let down: MouseEvent = new MouseEvent('mousedown', {
'view': window,
@@ -286,10 +285,7 @@ describe('PivotFieldList spec', () => {
}
});
fieldListObj.appendTo('#PivotFieldList');
- pivotCommon = fieldListObj.pivotCommon;
});
-
- let persistdata: string;
it('check field list tree view', () => {
expect(!isNullOrUndefined(fieldListObj.element.querySelector('.e-pivotfieldlist-container')));
expect(fieldListObj.treeViewModule.fieldTable.element.classList.contains('e-field-list'));
@@ -355,6 +351,37 @@ describe('PivotFieldList spec', () => {
closest(checkEle[0], 'li').dispatchEvent(down);
closest(checkEle[0], 'li').dispatchEvent(up);
expect(checkEle.length).toBe(2);
+ (fieldListObj.element.getElementsByClassName('e-member-editor-dialog')[0].getElementsByClassName('e-ok-btn')[0] as HTMLElement).click();
+ done();
+ }, 2000);
+ });
+ it('Node selecting with space key - check', (done: Function) => {
+ let keyboardEventArgs: any = {
+ preventDefault: (): void => {},
+ action: null
+ };
+ let fileds: HTMLElement[] = [].slice.call(fieldListObj.element.querySelectorAll('.e-list-item'));
+ (fieldListObj.treeViewModule.fieldTable as any).focusIn();
+ keyboardEventArgs.action = 'space';
+ (fieldListObj.treeViewModule.fieldTable as any).keyActionHandler(keyboardEventArgs);
+ setTimeout(() => {
+ expect(fileds[0].getAttribute('aria-checked')).toBe('true');
+ expect(fileds[0].querySelectorAll('.e-check').length).toBe(1);
+ done();
+ });
+ });
+ it('Node selecting with space key - uncheck', (done: Function) => {
+ let keyboardEventArgs: any = {
+ preventDefault: (): void => {},
+ action: null
+ };
+ let fileds: HTMLElement[] = [].slice.call(fieldListObj.element.querySelectorAll('.e-list-item'));
+ (fieldListObj.treeViewModule.fieldTable as any).focusIn();
+ keyboardEventArgs.action = 'space';
+ (fieldListObj.treeViewModule.fieldTable as any).keyActionHandler(keyboardEventArgs);
+ setTimeout(() => {
+ expect(fileds[0].getAttribute('aria-checked')).toBe('false');
+ expect(fileds[0].querySelectorAll('.e-check').length).toBe(0);
done();
});
});
diff --git a/controls/pivotview/src/base/engine.ts b/controls/pivotview/src/base/engine.ts
index c861c74474..c30a0b3750 100644
--- a/controls/pivotview/src/base/engine.ts
+++ b/controls/pivotview/src/base/engine.ts
@@ -170,8 +170,8 @@ export class PivotEngine {
* @returns {void}
* @hidden
*/
- public clearProperties(): void {
- if (!this.isPagingOrVirtualizationEnabled) {
+ public clearProperties(isExport?: boolean): void {
+ if (!this.isPagingOrVirtualizationEnabled && !isExport) {
this.columnKeys = {};
this.headerCollection = { rowHeaders: [], columnHeaders: [], rowHeadersCount: 0, columnHeadersCount: 0 };
}
@@ -2108,7 +2108,7 @@ export class PivotEngine {
this.generateGridData(dataSource);
this.isEditing = false;
}
- public generateGridData(dataSource: IDataOptions, requireDatasourceUpdate: boolean = false, headerCollection?: HeaderCollection): void {
+ public generateGridData(dataSource: IDataOptions, requireDatasourceUpdate: boolean = false, isExport?: boolean, headerCollection?: HeaderCollection): void {
this.updateDataSourceSettings(dataSource, requireDatasourceUpdate);
const columns: IFieldOptions[] = dataSource.columns ? dataSource.columns : [];
const data: IDataSet[] = this.data as IDataSet[];
@@ -2251,7 +2251,7 @@ export class PivotEngine {
this.isEngineUpdated = true;
this.isEmptyDataAvail(this.rMembers, this.cMembers);
// console.log(st1 - st2);
- this.clearProperties();
+ this.clearProperties(isExport);
}
private updateHeaders(rowFlag?: boolean, columnFlag?: boolean): void {
/* removing the row grant-total members */
diff --git a/controls/pivotview/src/base/olap/engine.ts b/controls/pivotview/src/base/olap/engine.ts
index 2988ae7ae5..81447bd288 100644
--- a/controls/pivotview/src/base/olap/engine.ts
+++ b/controls/pivotview/src/base/olap/engine.ts
@@ -3491,11 +3491,16 @@ export class OlapEngine {
const currentItems: string[] = [];
for (const selectedElement of filter.items) {
// currentItems.push(selectedElement.replace(/\&/g, '&'));
+ let filterCaption: string;
+ if (!isMembersAvail && filter.items.length === 1) {
+ this.getMembers(this.dataSourceSettings, filter.name, undefined, undefined, undefined, filter.items[0]);
+ filterCaption = this.fieldList[filter.name].actualFilter[0];
+ }
currentItems.push(selectedElement);
if (isMembersAvail) {
this.fieldList[filter.name].filter.push(members[selectedElement as string].caption);
} else {
- this.fieldList[filter.name].filter.push(selectedElement);
+ this.fieldList[filter.name].filter.push(filterCaption ? filterCaption : selectedElement);
}
}
this.filterMembers[filter.name] = currentItems;
@@ -3684,16 +3689,19 @@ export class OlapEngine {
return filterQuery;
}
public getMembers(dataSourceSettings: IDataOptions, fieldName: string, isAllFilterData?: boolean,
- filterParentQuery?: string, loadLevelMember?: boolean): void {
+ filterParentQuery?: string, loadLevelMember?: boolean, filterItemName?: string): void {
// dimProp = "dimension properties CHILDREN_CARDINALITY, MEMBER_TYPE";
const dimProp: string = 'DIMENSION PROPERTIES PARENT_UNIQUE_NAME, HIERARCHY_UNIQUE_NAME, CHILDREN_CARDINALITY, MEMBER_TYPE, MEMBER_VALUE';
let mdxQuery: string;
const hasAllMember: boolean = this.fieldList[fieldName as string].hasAllMember;
const hierarchy: string = (hasAllMember ? fieldName : fieldName + '.LEVELS(0)').replace(/\&/g, '&').replace(/\>/g, '>').replace(/\ 0 && this.fieldList[customArgs.fieldName] && fields[fields.length - 1].getElementsByTagName('Caption')
+ && fields[fields.length - 1].getElementsByTagName('Caption')[0]) {
+ this.fieldList[customArgs.fieldName].actualFilter[0] = fields[fields.length - 1].getElementsByTagName('Caption')[0].textContent;
+ }
+ }
public getChildMembers(dataSourceSettings: IDataOptions, memberUQName: string, fieldName: string): void {
// dimProp = "dimension properties CHILDREN_CARDINALITY, MEMBER_TYPE";
const dimProp: string = 'DIMENSION PROPERTIES PARENT_UNIQUE_NAME, HIERARCHY_UNIQUE_NAME, CHILDREN_CARDINALITY, MEMBER_TYPE, MEMBER_VALUE';
diff --git a/controls/pivotview/src/common/base/css-constant.ts b/controls/pivotview/src/common/base/css-constant.ts
index 6bd3be2676..8b51087065 100644
--- a/controls/pivotview/src/common/base/css-constant.ts
+++ b/controls/pivotview/src/common/base/css-constant.ts
@@ -832,3 +832,7 @@ export const FREEZED_CELL: string = 'e-leftfreeze';
export const PIVOT_CONTENT_LOADER: string = 'e-pivot-content-loader';
/** @hidden */
export const PIVOT_HIDE_LOADER: string = 'e-hide-loader';
+/** @hidden */
+export const COLLAPSIBLE: string = 'e-icon-collapsible';
+/** @hidden */
+export const EXPANDABLE: string = 'e-icon-expandable';
\ No newline at end of file
diff --git a/controls/pivotview/src/pivotfieldlist/renderer/tree-renderer.ts b/controls/pivotview/src/pivotfieldlist/renderer/tree-renderer.ts
index e0cfbb70e1..3212fa3910 100644
--- a/controls/pivotview/src/pivotfieldlist/renderer/tree-renderer.ts
+++ b/controls/pivotview/src/pivotfieldlist/renderer/tree-renderer.ts
@@ -5,8 +5,8 @@ import * as cls from '../../common/base/css-constant';
import * as events from '../../common/base/constant';
import { IAction, FieldDropEventArgs, FieldRemoveEventArgs, FieldDragStartEventArgs } from '../../common/base/interface';
import {
- TreeView, NodeCheckEventArgs, DragAndDropEventArgs, DrawNodeEventArgs,
- NodeExpandEventArgs, NodeSelectEventArgs
+ TreeView, NodeClickEventArgs, DragAndDropEventArgs, DrawNodeEventArgs,
+ NodeExpandEventArgs, NodeSelectEventArgs, NodeCheckEventArgs
} from '@syncfusion/ej2-navigations';
import { IFieldOptions, IField, IDataOptions, FieldItemInfo } from '../../base/engine';
import { Dialog } from '@syncfusion/ej2-popups';
@@ -35,6 +35,7 @@ export class TreeViewRenderer implements IAction {
private nonSearchList: HTMLElement[];
private isSearching: boolean = false;
private parentIDs: string[] = [];
+ private isSpaceKey: boolean = true;
/** Constructor for render module
*
@@ -143,6 +144,7 @@ export class TreeViewRenderer implements IAction {
private renderTreeView(): void {
this.fieldTable = new TreeView({
fields: { dataSource: this.getTreeData(), id: 'id', text: 'caption', isChecked: 'isSelected', parentID: 'pid', iconCss: 'spriteCssClass' },
+ nodeChecked: this.nodeChecked.bind(this),
nodeClicked: this.nodeStateChange.bind(this),
keyPress: this.nodeStateChange.bind(this),
cssClass: cls.FIELD_LIST_TREE_CLASS + (this.parent.cssClass ? (' ' + this.parent.cssClass) : ''),
@@ -384,6 +386,7 @@ export class TreeViewRenderer implements IAction {
locale: this.parent.locale,
enableHtmlSanitizer: this.parent.enableHtmlSanitizer,
cssClass: this.parent.cssClass,
+ nodeChecked: this.nodeChecked.bind(this),
nodeClicked: this.addNode.bind(this),
keyPress: this.addNode.bind(this),
drawNode: this.updateTreeNode.bind(this),
@@ -574,31 +577,57 @@ export class TreeViewRenderer implements IAction {
}
return buttonElement;
}
- private nodeStateChange(args: NodeCheckEventArgs): void {
- const id: string = args.node.getAttribute('data-uid');
+ private nodeChecked(args: NodeCheckEventArgs): void {
+ if (this.isSpaceKey) {
+ const node: HTMLElement = closest(args.node, '.' + cls.TEXT_CONTENT_CLASS) as HTMLElement;
+ if (!isNullOrUndefined(node)) {
+ const li: HTMLElement = closest(node, 'li') as HTMLElement;
+ const id: string = li.getAttribute('data-uid');
+ if (this.parent.isAdaptive) {
+ this.addNode(undefined, id, args.action === 'check', node);
+ } else {
+ this.nodeStateChange(undefined, id, args.action === 'check', node);
+ }
+ }
+ }
+ this.isSpaceKey = false;
+ }
+ private nodeStateChange(args: NodeClickEventArgs, id: string, isChecked: boolean, node: HTMLElement): void {
+ node = isNullOrUndefined(node) ? args.node : node;
+ id = isNullOrUndefined(id) ? node.getAttribute('data-uid') : id;
if (this.parent.pivotCommon.filterDialog.dialogPopUp) {
this.parent.pivotCommon.filterDialog.dialogPopUp.close();
}
const list: { [key: string]: Object } = this.parent.pivotFieldList;
- const selectedNode: { [key: string]: Object } = list[id as string] as { [key: string]: Object };
- const fieldInfo: FieldItemInfo = PivotUtil.getFieldInfo(id, this.parent);
- const control: PivotView | PivotFieldList = this.parent.isPopupView ? this.parent.pivotGridModule : this.parent;
- const parentNode: Element = args.node.closest('.' + cls.FIELD_TREE_PARENT);
- let isChecked: boolean = false; /* eslint-disable @typescript-eslint/no-explicit-any */
- const getNodeDetails: any = this.fieldTable.getNode(args.node);
- if ((args as any).event && (args as any).event.target &&
- !(args as any).event.target.classList.contains(cls.CHECK_BOX_FRAME_CLASS)) {
- /* eslint-enable @typescript-eslint/no-explicit-any */
- if (getNodeDetails.isChecked === 'true') {
- this.fieldTable.uncheckAll([args.node]);
- isChecked = false;
+ const selectedNode: { [key: string]: Object; } = list[id as string] as { [key: string]: Object };
+ if (!isNullOrUndefined(args)) {
+ /* eslint-disable @typescript-eslint/no-explicit-any */
+ this.isSpaceKey = (args.event as any).action && (args.event as any).action === 'space';
+ if (isNullOrUndefined(selectedNode) || node.classList.contains(cls.ICON_DISABLE) || (args.event.target &&
+ ((args.event.target as HTMLElement).classList.contains(cls.COLLAPSIBLE) ||
+ (args.event.target as HTMLElement).classList.contains(cls.EXPANDABLE))) ||
+ ((args.event as any).action && (args.event as any).action !== 'enter')) {
+ return;
+ }
+ isChecked = false;
+ const getNodeDetails: any = this.fieldTable.getNode(node);
+ if ((args as any).event && (args as any).event.target &&
+ !(args as any).event.target.classList.contains(cls.CHECK_BOX_FRAME_CLASS)) {
+ /* eslint-enable @typescript-eslint/no-explicit-any */
+ if (getNodeDetails.isChecked === 'true') {
+ this.fieldTable.uncheckAll([node]);
+ isChecked = false;
+ } else {
+ this.fieldTable.checkAll([node]);
+ isChecked = true;
+ }
} else {
- this.fieldTable.checkAll([args.node]);
- isChecked = true;
+ isChecked = getNodeDetails.isChecked === 'true';
}
- } else {
- isChecked = getNodeDetails.isChecked === 'true';
}
+ const control: PivotView | PivotFieldList = this.parent.isPopupView ? this.parent.pivotGridModule : this.parent;
+ const fieldInfo: FieldItemInfo = PivotUtil.getFieldInfo(id, this.parent);
+ const parentNode: Element = node.closest('.' + cls.FIELD_TREE_PARENT);
if (isChecked) {
const eventdrop: FieldDropEventArgs = {
fieldName: id, dropField: fieldInfo.fieldItem,
@@ -610,11 +639,11 @@ export class TreeViewRenderer implements IAction {
};
control.trigger(events.fieldDrop, eventdrop, (observedArgs: FieldDropEventArgs) => {
if (!observedArgs.cancel) {
- addClass([args.node.querySelector('.' + cls.LIST_TEXT_CLASS)], cls.LIST_SELECT_CLASS);
+ addClass([node.querySelector('.' + cls.LIST_TEXT_CLASS)], cls.LIST_SELECT_CLASS);
if (parentNode) {
addClass([parentNode.querySelector('.' + cls.LIST_TEXT_CLASS)], cls.LIST_SELECT_CLASS);
}
- this.updateSelectedNodes(args.node, 'check');
+ this.updateSelectedNodes(node, 'check');
const addNode: IFieldOptions = this.parent.pivotCommon.dataSourceUpdate.getNewField(id, fieldInfo.fieldItem);
this.updateReportSettings(addNode, observedArgs);
this.updateNodeStateChange(id, selectedNode, isChecked);
@@ -630,11 +659,11 @@ export class TreeViewRenderer implements IAction {
};
control.trigger(events.fieldRemove, removeFieldArgs, (observedArgs: FieldRemoveEventArgs) => {
if (!observedArgs.cancel) {
- removeClass([args.node.querySelector('.' + cls.LIST_TEXT_CLASS)], cls.LIST_SELECT_CLASS);
+ removeClass([node.querySelector('.' + cls.LIST_TEXT_CLASS)], cls.LIST_SELECT_CLASS);
if (parentNode && isNullOrUndefined(parentNode.querySelector('.' + cls.FIELD_TREE_CHILD + ' .' + cls.NODE_CHECK_CLASS))) {
removeClass([parentNode.querySelector('.' + cls.LIST_TEXT_CLASS)], cls.LIST_SELECT_CLASS);
}
- this.updateSelectedNodes(args.node, 'uncheck');
+ this.updateSelectedNodes(node, 'uncheck');
this.parent.pivotCommon.dataSourceUpdate.removeFieldFromReport(id);
if (this.parent.dataType === 'pivot' && this.parent.showValuesButton && this.parent.dataSourceSettings.values.length > 1 &&
fieldInfo && fieldInfo.position < this.parent.dataSourceSettings.valueIndex &&
@@ -774,27 +803,38 @@ export class TreeViewRenderer implements IAction {
}
}
- private addNode(args: NodeCheckEventArgs): void {
- const id: string = args.node.getAttribute('data-uid');
+ private addNode(args: NodeClickEventArgs, id: string, isChecked: boolean, node: HTMLElement): void {
+ node = isNullOrUndefined(node) ? args.node : node;
+ id = isNullOrUndefined(id) ? node.getAttribute('data-uid') : id;
const list: { [key: string]: Object } = this.parent.pivotFieldList;
- const selectedNode: { [key: string]: Object } = list[id as string] as { [key: string]: Object };
- const fieldInfo: FieldItemInfo = PivotUtil.getFieldInfo(selectedNode.id.toString(), this.parent);
- const control: PivotView | PivotFieldList = this.parent.isPopupView ? this.parent.pivotGridModule : this.parent;
- let isChecked: boolean = false; /* eslint-disable @typescript-eslint/no-explicit-any */
- const getNodeDetails: any = this.fieldTable.getNode(args.node);
- if ((args as any).event && (args as any).event.target &&
- !(args as any).event.target.classList.contains(cls.CHECK_BOX_FRAME_CLASS)) {
- /* eslint-enable @typescript-eslint/no-explicit-any */
- if (getNodeDetails.isChecked === 'true') {
- this.fieldTable.uncheckAll([args.node]);
- isChecked = false;
+ const selectedNode: { [key: string]: Object; } = list[id as string] as { [key: string]: Object };
+ if (!isNullOrUndefined(args)) {
+ /* eslint-disable @typescript-eslint/no-explicit-any */
+ this.isSpaceKey = (args.event as any).key && (args.event as any).key === ' ';
+ if (isNullOrUndefined(selectedNode) || args.node.classList.contains(cls.ICON_DISABLE) || (args.event.target &&
+ ((args.event.target as HTMLElement).classList.contains(cls.COLLAPSIBLE) ||
+ (args.event.target as HTMLElement).classList.contains(cls.EXPANDABLE))) ||
+ ((args.event as any).key && (args.event as any).key !== 'Enter')) {
+ return;
+ }
+ isChecked = false;
+ const getNodeDetails: any = this.fieldTable.getNode(args.node);
+ if ((args as any).event && (args as any).event.target &&
+ !(args as any).event.target.classList.contains(cls.CHECK_BOX_FRAME_CLASS)) {
+ /* eslint-enable @typescript-eslint/no-explicit-any */
+ if (getNodeDetails.isChecked === 'true') {
+ this.fieldTable.uncheckAll([args.node]);
+ isChecked = false;
+ } else {
+ this.fieldTable.checkAll([args.node]);
+ isChecked = true;
+ }
} else {
- this.fieldTable.checkAll([args.node]);
- isChecked = true;
+ isChecked = getNodeDetails.isChecked === 'true';
}
- } else {
- isChecked = getNodeDetails.isChecked === 'true';
}
+ const fieldInfo: FieldItemInfo = PivotUtil.getFieldInfo(selectedNode.id.toString(), this.parent);
+ const control: PivotView | PivotFieldList = this.parent.isPopupView ? this.parent.pivotGridModule : this.parent;
if (isChecked) {
const axis: string[] = ['filters', 'columns', 'rows', 'values'];
const eventdrop: FieldDropEventArgs = {
diff --git a/controls/pivotview/src/pivotview/actions/excel-export.ts b/controls/pivotview/src/pivotview/actions/excel-export.ts
index aa504a26a9..4367eeb32d 100644
--- a/controls/pivotview/src/pivotview/actions/excel-export.ts
+++ b/controls/pivotview/src/pivotview/actions/excel-export.ts
@@ -104,7 +104,7 @@ export class ExcelExport {
} else {
this.engine.pageSettings = null;
}
- (this.engine as PivotEngine).generateGridData(this.parent.dataSourceSettings, true);
+ (this.engine as PivotEngine).generateGridData(this.parent.dataSourceSettings, true, true);
this.parent.applyFormatting(this.engine.pivotValues);
clonedValues = PivotExportUtil.getClonedPivotValues(this.engine.pivotValues) as IAxisSet[][];
this.engine.pivotValues = currentPivotValues;
diff --git a/controls/pivotview/src/pivotview/actions/pdf-export.ts b/controls/pivotview/src/pivotview/actions/pdf-export.ts
index 4e812d1f9f..b05d2f24fb 100644
--- a/controls/pivotview/src/pivotview/actions/pdf-export.ts
+++ b/controls/pivotview/src/pivotview/actions/pdf-export.ts
@@ -530,7 +530,7 @@ export class PDFExport {
} else {
this.engine.pageSettings = null;
}
- (this.engine as PivotEngine).generateGridData(this.parent.dataSourceSettings as IDataOptions, true);
+ (this.engine as PivotEngine).generateGridData(this.parent.dataSourceSettings as IDataOptions, true, true);
this.parent.applyFormatting(this.engine.pivotValues);
clonedValues = PivotExportUtil.getClonedPivotValues(this.engine.pivotValues) as IAxisSet[][];
this.engine.pivotValues = currentPivotValues;
diff --git a/controls/pivotview/src/pivotview/actions/virtualscroll.ts b/controls/pivotview/src/pivotview/actions/virtualscroll.ts
index b88f93d0bf..a6bd8a13c1 100644
--- a/controls/pivotview/src/pivotview/actions/virtualscroll.ts
+++ b/controls/pivotview/src/pivotview/actions/virtualscroll.ts
@@ -206,7 +206,7 @@ export class VirtualScroll {
this.parent.getEngine('onScroll', null, null, null, null, null, null);
} else {
this.parent.engineModule.generateGridData(
- this.parent.dataSourceSettings, true, this.parent.engineModule.headerCollection);
+ this.parent.dataSourceSettings, true, false, this.parent.engineModule.headerCollection);
rowStartPos = this.parent.engineModule.rowStartPos;
}
} else {
@@ -251,7 +251,7 @@ export class VirtualScroll {
if (this.parent.dataSourceSettings.mode === 'Server') {
this.parent.getEngine('onScroll', null, null, null, null, null, null);
} else {
- pivot.engineModule.generateGridData(pivot.dataSourceSettings, true, pivot.engineModule.headerCollection);
+ pivot.engineModule.generateGridData(pivot.dataSourceSettings, true, false, pivot.engineModule.headerCollection);
colStartPos = pivot.engineModule.colStartPos;
}
} else {
diff --git a/controls/pivotview/src/pivotview/base/pivotview.ts b/controls/pivotview/src/pivotview/base/pivotview.ts
index 7682dfb43a..566677f941 100644
--- a/controls/pivotview/src/pivotview/base/pivotview.ts
+++ b/controls/pivotview/src/pivotview/base/pivotview.ts
@@ -4123,7 +4123,7 @@ export class PivotView extends Component implements INotifyProperty
this.getEngine('onPageChange', null, null, null, null, null, null);
} else {
this.engineModule.generateGridData(
- this.dataSourceSettings, true, this.engineModule.headerCollection);
+ this.dataSourceSettings, true, false, this.engineModule.headerCollection);
}
this.setProperties({ pivotValues: this.engineModule.pivotValues }, true);
this.enginePopulatedEventMethod('updateDataSource');
@@ -6061,7 +6061,7 @@ export class PivotView extends Component implements INotifyProperty
}
} else if ((this.dataSourceSettings.url !== '' && this.dataType === 'olap') ||
(pivot.dataSourceSettings.dataSource && (pivot.dataSourceSettings.dataSource as IDataSet[]).length > 0
- || this.engineModule.data.length > 0)) {
+ || (this.engineModule.data && this.engineModule.data.length > 0))) {
if (pivot.dataType === 'pivot') {
this.hideWaitingPopup();
pivot.engineModule.data = pivot.dataSourceSettings.dataSource;
diff --git a/controls/pivotview/src/pivotview/renderer/render.ts b/controls/pivotview/src/pivotview/renderer/render.ts
index b04c328357..eecd9d6386 100644
--- a/controls/pivotview/src/pivotview/renderer/render.ts
+++ b/controls/pivotview/src/pivotview/renderer/render.ts
@@ -1675,8 +1675,9 @@ export class Render {
this.parent.resizedValue = (this.parent.showGroupingBar && this.parent.resizedValue < 250) ? 250 : this.parent.resizedValue;
}
this.resColWidth = !isNullOrUndefined(this.parent.resizedValue) ? this.parent.resizedValue : this.resColWidth;
- const offsetWidth: number = this.parent.element.offsetWidth ? this.parent.element.offsetWidth :
- this.parent.element.getBoundingClientRect().width;
+ const offsetWidth: number = this.parent.grid ? this.parent.grid.element.offsetWidth ? this.parent.grid.element.offsetWidth :
+ this.parent.grid.element.getBoundingClientRect().width : this.parent.element.offsetWidth ?
+ this.parent.element.offsetWidth : this.parent.element.getBoundingClientRect().width;
let parWidth: number = isNaN(this.parent.width as number) ? (this.parent.width.toString().indexOf('%') > -1 ?
((parseFloat(this.parent.width.toString()) / 100) * offsetWidth) : offsetWidth) :
Number(this.parent.width);
diff --git a/controls/pivotview/styles/pivotfieldlist/_theme.scss b/controls/pivotview/styles/pivotfieldlist/_theme.scss
index f6ebbedbc3..269f4059fb 100644
--- a/controls/pivotview/styles/pivotfieldlist/_theme.scss
+++ b/controls/pivotview/styles/pivotfieldlist/_theme.scss
@@ -828,6 +828,9 @@
.e-field-list-container {
height: 369px;
+ @if ($skin-name == 'FluentUI') {
+ height: 394px;
+ }
/* stylelint-disable */
.e-field-table {
diff --git a/controls/popups/CHANGELOG.md b/controls/popups/CHANGELOG.md
index b3c0374487..d9854d2c25 100644
--- a/controls/popups/CHANGELOG.md
+++ b/controls/popups/CHANGELOG.md
@@ -2,7 +2,7 @@
## [Unreleased]
-## 25.1.35 (2024-03-15)
+## 25.1.37 (2024-03-26)
### Dialog
diff --git a/controls/querybuilder/CHANGELOG.md b/controls/querybuilder/CHANGELOG.md
index 87ddcfe9f6..22f88e4870 100644
--- a/controls/querybuilder/CHANGELOG.md
+++ b/controls/querybuilder/CHANGELOG.md
@@ -2,6 +2,14 @@
## [Unreleased]
+## 25.1.37 (2024-03-26)
+
+### QueryBuilder
+
+#### Bug Fixes
+
+- `#I568017` - Issue with QueryBuilder 'In' or 'Not in' Operator results in value field as empty list when using fieldMode as default mode has been fixed.
+
## 25.1.35 (2024-03-15)
### QueryBuilder
diff --git a/controls/querybuilder/package.json b/controls/querybuilder/package.json
index 7abb065075..97f60bc1f2 100644
--- a/controls/querybuilder/package.json
+++ b/controls/querybuilder/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-querybuilder",
- "version": "18.24.1",
+ "version": "25.1.35",
"description": "Essential JS 2 QueryBuilder",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/querybuilder/src/query-builder/query-builder.ts b/controls/querybuilder/src/query-builder/query-builder.ts
index 79718860eb..48ea5feed5 100644
--- a/controls/querybuilder/src/query-builder/query-builder.ts
+++ b/controls/querybuilder/src/query-builder/query-builder.ts
@@ -2449,17 +2449,11 @@ export class QueryBuilder extends Component implements INotifyPr
if (!this.dataColl.length && values.length) {
isValues = true;
}
- let fieldValue: string = this.selectedRule.field;
- const isNested: number = this.selectedRule.field.indexOf(this.separator);
- if (isNested !== 0 && this.fieldMode !== 'DropdownTree') {
- const nest: string[] = this.selectedRule.field.split(this.separator);
- fieldValue = nest[nest.length - 1];
- }
let multiSelectValue: MultiSelectModel;
multiSelectValue = {
dataSource: isValues ? values : (isFetched ? ds as { [key: string]: object }[] : this.dataManager),
query: new Query([rule.field]),
- fields: { text: fieldValue, value: fieldValue },
+ fields: { text: this.selectedRule.field, value: this.selectedRule.field },
placeholder: this.l10n.getConstant('SelectValue'),
value: selectedValue,
mode: 'CheckBox',
@@ -5139,6 +5133,7 @@ export class QueryBuilder extends Component implements INotifyPr
*/
public cloneRule(ruleID: string, groupID: string, index: number): void {
const getRule: RuleModel = this.getRule(ruleID.replace(this.element.id + '_', ''));
+ let isCloneRule: boolean = this.showButtons.cloneRule;
groupID = groupID.replace(this.element.id + '_', '');
this.ruleIndex = index;
this.cloneRuleBtnClick = true;
@@ -5149,7 +5144,8 @@ export class QueryBuilder extends Component implements INotifyPr
}], groupID);
this.ruleIndex = -1;
this.cloneRuleBtnClick = false;
- this.showButtons.cloneRule = false;
+ this.showButtons.cloneRule = isCloneRule;
+ isCloneRule = false;
}
/**
@@ -5163,6 +5159,7 @@ export class QueryBuilder extends Component implements INotifyPr
public cloneGroup(groupID: string, parentGroupID: string, index: number): void {
parentGroupID = parentGroupID.replace(this.element.id + '_', '');
const group: RuleModel = this.getGroup(parentGroupID);
+ let isCloneGroup: boolean = this.showButtons.cloneGroup;
groupID = groupID.replace(this.element.id + '_', '');
this.groupIndex = index;
this.cloneGrpBtnClick = true;
@@ -5170,7 +5167,8 @@ export class QueryBuilder extends Component implements INotifyPr
this.addGroups([{ 'condition': group.condition, 'not': group.not, 'rules': group.rules }], groupID);
this.groupIndex = -1;
this.cloneGrpBtnClick = false;
- this.showButtons.cloneGroup = false;
+ this.showButtons.cloneGroup = isCloneGroup;
+ isCloneGroup = false;
}
/**
@@ -5180,6 +5178,9 @@ export class QueryBuilder extends Component implements INotifyPr
* @returns {void}
*/
public lockRule(ruleID: string): void {
+ if (ruleID.indexOf(this.element.id) < 0) {
+ ruleID = this.element.id + '_' + ruleID;
+ }
const target: Element = document.getElementById(ruleID).querySelectorAll('.e-lock-rule-btn')[0];
this.ruleLock(target);
}
@@ -5191,6 +5192,9 @@ export class QueryBuilder extends Component implements INotifyPr
* @returns {void}
*/
public lockGroup(groupID: string): void {
+ if (groupID.indexOf(this.element.id) < 0) {
+ groupID = this.element.id + '_' + groupID;
+ }
const target: Element = document.getElementById(groupID).querySelectorAll('.e-lock-grp-btn')[0];
this.groupLock(target);
}
diff --git a/controls/querybuilder/styles/query-builder/_theme.scss b/controls/querybuilder/styles/query-builder/_theme.scss
index 3e5e8c9e4f..7b165568ed 100644
--- a/controls/querybuilder/styles/query-builder/_theme.scss
+++ b/controls/querybuilder/styles/query-builder/_theme.scss
@@ -8,7 +8,9 @@
}
& .e-group-header .e-dropdown-btn.e-add-btn,
- .e-deletegroup {
+ .e-deletegroup,
+ .e-clone-grp-btn,
+ .e-lock-grp-btn {
@if $skin-name == 'bootstrap5' {
background: $qrybldr-btngroup-bgcolor;
box-shadow: none;
diff --git a/controls/ribbon/package.json b/controls/ribbon/package.json
index d2100dcde2..f8bd5e2137 100644
--- a/controls/ribbon/package.json
+++ b/controls/ribbon/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-ribbon",
- "version": "21.29.0",
+ "version": "25.1.35",
"description": "Essential JS 2 Component",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/ribbon/styles/ribbon/_fabric-dark-definition.scss b/controls/ribbon/styles/ribbon/_fabric-dark-definition.scss
index 7c25a1e65e..28953272a8 100644
--- a/controls/ribbon/styles/ribbon/_fabric-dark-definition.scss
+++ b/controls/ribbon/styles/ribbon/_fabric-dark-definition.scss
@@ -255,7 +255,7 @@ $ribbon-bigger-rtl-button-icon-padding: 11px 16px 11px 12px !default;
$ribbon-bigger-caret-icon-padding: 0 12px !default;
$ribbon-bigger-rtl-caret-icon-padding: 0 12px !default;
-$ribbon-header-bg-color: $neutral-light-font !default;
+$ribbon-header-bg-color: $neutral-lighter !default;
$ribbon-border-color: unset !default;
$ribbon-group-seperator-color: $neutral-quintenary !default;
$ribbon-group-border-color: $neutral-quintenary !default;
diff --git a/controls/ribbon/styles/ribbon/_layout.scss b/controls/ribbon/styles/ribbon/_layout.scss
index 5f858f7673..c2f3d75be5 100644
--- a/controls/ribbon/styles/ribbon/_layout.scss
+++ b/controls/ribbon/styles/ribbon/_layout.scss
@@ -890,7 +890,7 @@
}
.e-ribbon-group-overflow-ddb {
- &.e-dropdown-popup {
+ &.e-dropdown-popup:has(.e-ribbon-overflow-target) {
min-width: 190px;
}
.e-ribbon-of-tab:not(.e-ribbon-active) {
diff --git a/controls/ribbon/styles/ribbon/_material3-definition.scss b/controls/ribbon/styles/ribbon/_material3-definition.scss
index 188c7effaf..17e6faffe4 100644
--- a/controls/ribbon/styles/ribbon/_material3-definition.scss
+++ b/controls/ribbon/styles/ribbon/_material3-definition.scss
@@ -339,8 +339,8 @@ $ribbon-popup-common-box-shadow: $shadow-md !default;
$ribbon-filemenu-popup-border-radius: 4px !default;
$ribbon-contextual-tab-color: $ribbon-active-tab-indicator-color !default;
$ribbon-contextual-tab-background: rgba($content-bg-color-selected) !default;
-$ribbon-keytip-background-color: rgba($black) !default;
-$ribbon-keytip-color: rgba($content-text-color-inverse) !default;
+$ribbon-keytip-background-color: rgba($tooltip-bg-color) !default;
+$ribbon-keytip-color: rgba($tooltip-text-color) !default;
$ribbon-gallery-popup-background-color: rgba($content-bg-color) !default;
$ribbon-gallery-item-background-color: $transparent !default;
$ribbon-gallery-item-selected-color: rgba($content-bg-color-selected) !default;
diff --git a/controls/richtexteditor/package.json b/controls/richtexteditor/package.json
index 18ef68f2fb..8d418bc950 100644
--- a/controls/richtexteditor/package.json
+++ b/controls/richtexteditor/package.json
@@ -1,6 +1,6 @@
{
"name": "@syncfusion/ej2-richtexteditor",
- "version": "23.1.54",
+ "version": "25.1.35",
"description": "Essential JS 2 RichTextEditor component",
"author": "Syncfusion Inc.",
"license": "SEE LICENSE IN license",
diff --git a/controls/richtexteditor/spec/cr-issues/rich-text-editor.spec.ts b/controls/richtexteditor/spec/cr-issues/rich-text-editor.spec.ts
index a9f4f7a8ec..72658b5186 100644
--- a/controls/richtexteditor/spec/cr-issues/rich-text-editor.spec.ts
+++ b/controls/richtexteditor/spec/cr-issues/rich-text-editor.spec.ts
@@ -1712,9 +1712,7 @@ describe('RTE CR issues', () => {
const tileItems: NodeList = ( row[0] as HTMLElement ).querySelectorAll('.e-tile');
( tileItems[9] as HTMLElement ).click();
// Background color
- (document.querySelectorAll('.e-control.e-colorpicker')[1] as any).ej2_instances[0].inline = true;
- (document.querySelectorAll('.e-control.e-colorpicker')[1] as any).ej2_instances[0].dataBind();
- ( document.body.querySelector('.e-apply') as HTMLElement).click();
+ (rteObject.element.querySelector('.e-background-color') as HTMLElement).click();
( dropButton[1] as HTMLElement ).click(); // Font Size
const fontDropItems : NodeList= document.body.querySelectorAll('.e-item');
( fontDropItems[6] as HTMLElement ).click(); // Apply Font size
diff --git a/controls/richtexteditor/spec/editor-manager/plugin/msword-cleanup.spec.ts b/controls/richtexteditor/spec/editor-manager/plugin/msword-cleanup.spec.ts
index d50aa6f8fc..55e14a2a02 100644
--- a/controls/richtexteditor/spec/editor-manager/plugin/msword-cleanup.spec.ts
+++ b/controls/richtexteditor/spec/editor-manager/plugin/msword-cleanup.spec.ts
@@ -1370,7 +1370,7 @@ ul
Filterauswahl |
5 |
42 |
- 0 |
+ 0 |