diff --git a/controls/documenteditor/package.json b/controls/documenteditor/package.json index c9be1a5b33..506d8dcf9e 100644 --- a/controls/documenteditor/package.json +++ b/controls/documenteditor/package.json @@ -1,6 +1,6 @@ { "name": "@syncfusion/ej2-documenteditor", - "version": "21.2.3", + "version": "22.1.39", "description": "Feature-rich document editor control with built-in support for context menu, options pane and dialogs.", "keywords": [ "ej2", diff --git a/controls/documenteditor/src/document-editor-container/document-editor-container-model.d.ts b/controls/documenteditor/src/document-editor-container/document-editor-container-model.d.ts index 0d384a05cb..19bd4d9808 100644 --- a/controls/documenteditor/src/document-editor-container/document-editor-container-model.d.ts +++ b/controls/documenteditor/src/document-editor-container/document-editor-container-model.d.ts @@ -1,4 +1,4 @@ -import { Component, Property, INotifyPropertyChanged, NotifyPropertyChanges, ModuleDeclaration, L10n, Complex, isNullOrUndefined, formatUnit } from '@syncfusion/ej2-base';import { Event, EmitType } from '@syncfusion/ej2-base';import { Toolbar } from './tool-bar/tool-bar';import { DocumentEditor, DocumentEditorSettings, DocumentSettings } from '../document-editor/document-editor';import { TextProperties } from './properties-pane/text-properties-pane';import { HeaderFooterProperties } from './properties-pane/header-footer-pane';import { ImageProperties } from './properties-pane/image-properties-pane';import { TocProperties } from './properties-pane/table-of-content-pane';import { TableProperties } from './properties-pane/table-properties-pane';import { StatusBar } from './properties-pane/status-bar';import { ViewChangeEventArgs, RequestNavigateEventArgs, ContainerContentChangeEventArgs, ContainerSelectionChangeEventArgs, ContainerDocumentChangeEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, BeforePaneSwitchEventArgs, LayoutType, CommentDeleteEventArgs, ServiceFailureArgs, CommentActionEventArgs, XmlHttpRequestEventArgs, RevisionActionEventArgs } from '../document-editor/base';import { createSpinner } from '@syncfusion/ej2-popups';import { ContainerServerActionSettingsModel, DocumentEditorSettingsModel, DocumentSettingsModel, FormFieldSettingsModel } from '../document-editor/document-editor-model';import { CharacterFormatProperties, ParagraphFormatProperties, SectionFormatProperties } from '../document-editor/implementation';import { ToolbarItem } from '../document-editor/base/types';import { CustomToolbarItemModel, TrackChangeEventArgs, FormFieldFillEventArgs, AutoResizeEventArgs } from '../document-editor/base/events-helper';import { ClickEventArgs } from '@syncfusion/ej2-navigations';import { beforeAutoResize, internalAutoResize, internalZoomFactorChange, beforeCommentActionEvent, commentDeleteEvent, contentChangeEvent, trackChangeEvent, beforePaneSwitchEvent, serviceFailureEvent, documentChangeEvent, selectionChangeEvent, customContextMenuSelectEvent, customContextMenuBeforeOpenEvent, internalviewChangeEvent, beforeXmlHttpRequestSend, protectionTypeChangeEvent, internalDocumentEditorSettingsChange, internalStyleCollectionChange, revisionActionEvent } from '../document-editor/base/constants';import { HelperMethods } from '../index';import { SanitizeHtmlHelper } from '@syncfusion/ej2-base'; +import { Component, Property, INotifyPropertyChanged, NotifyPropertyChanges, ModuleDeclaration, L10n, Complex, isNullOrUndefined, formatUnit } from '@syncfusion/ej2-base';import { Event, EmitType } from '@syncfusion/ej2-base';import { Toolbar } from './tool-bar/tool-bar';import { DocumentEditor, DocumentEditorSettings, DocumentSettings } from '../document-editor/document-editor';import { TextProperties } from './properties-pane/text-properties-pane';import { HeaderFooterProperties } from './properties-pane/header-footer-pane';import { ImageProperties } from './properties-pane/image-properties-pane';import { TocProperties } from './properties-pane/table-of-content-pane';import { TableProperties } from './properties-pane/table-properties-pane';import { StatusBar } from './properties-pane/status-bar';import { ViewChangeEventArgs, RequestNavigateEventArgs, ContainerContentChangeEventArgs, ContainerSelectionChangeEventArgs, ContainerDocumentChangeEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, BeforePaneSwitchEventArgs, LayoutType, CommentDeleteEventArgs, RevisionActionEventArgs, ServiceFailureArgs, CommentActionEventArgs, XmlHttpRequestEventArgs } from '../document-editor/base';import { createSpinner } from '@syncfusion/ej2-popups';import { ContainerServerActionSettingsModel, DocumentEditorSettingsModel, DocumentSettingsModel, FormFieldSettingsModel } from '../document-editor/document-editor-model';import { CharacterFormatProperties, ParagraphFormatProperties, SectionFormatProperties } from '../document-editor/implementation';import { ToolbarItem } from '../document-editor/base/types';import { CustomToolbarItemModel, TrackChangeEventArgs, FormFieldFillEventArgs, AutoResizeEventArgs } from '../document-editor/base/events-helper';import { ClickEventArgs } from '@syncfusion/ej2-navigations';import { beforeAutoResize, internalAutoResize, internalZoomFactorChange, beforeCommentActionEvent, commentDeleteEvent, contentChangeEvent, trackChangeEvent, beforePaneSwitchEvent, serviceFailureEvent, documentChangeEvent, selectionChangeEvent, customContextMenuSelectEvent, customContextMenuBeforeOpenEvent, internalviewChangeEvent, beforeXmlHttpRequestSend, protectionTypeChangeEvent, internalDocumentEditorSettingsChange, internalStyleCollectionChange, revisionActionEvent } from '../document-editor/base/constants';import { HelperMethods } from '../index';import { SanitizeHtmlHelper } from '@syncfusion/ej2-base';import { DialogUtility } from '@syncfusion/ej2-popups'; import {ComponentModel} from '@syncfusion/ej2-base'; /** diff --git a/controls/documenteditor/src/document-editor-container/document-editor-container.ts b/controls/documenteditor/src/document-editor-container/document-editor-container.ts index 35ef6274f0..c91aae9fd3 100644 --- a/controls/documenteditor/src/document-editor-container/document-editor-container.ts +++ b/controls/documenteditor/src/document-editor-container/document-editor-container.ts @@ -9,7 +9,7 @@ import { ImageProperties } from './properties-pane/image-properties-pane'; import { TocProperties } from './properties-pane/table-of-content-pane'; import { TableProperties } from './properties-pane/table-properties-pane'; import { StatusBar } from './properties-pane/status-bar'; -import { ViewChangeEventArgs, RequestNavigateEventArgs, ContainerContentChangeEventArgs, ContainerSelectionChangeEventArgs, ContainerDocumentChangeEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, BeforePaneSwitchEventArgs, LayoutType, CommentDeleteEventArgs, ServiceFailureArgs, CommentActionEventArgs, XmlHttpRequestEventArgs, RevisionActionEventArgs } from '../document-editor/base'; +import { ViewChangeEventArgs, RequestNavigateEventArgs, ContainerContentChangeEventArgs, ContainerSelectionChangeEventArgs, ContainerDocumentChangeEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, BeforePaneSwitchEventArgs, LayoutType, CommentDeleteEventArgs, RevisionActionEventArgs, ServiceFailureArgs, CommentActionEventArgs, XmlHttpRequestEventArgs } from '../document-editor/base'; import { createSpinner } from '@syncfusion/ej2-popups'; import { ContainerServerActionSettingsModel, DocumentEditorSettingsModel, DocumentSettingsModel, FormFieldSettingsModel } from '../document-editor/document-editor-model'; import { CharacterFormatProperties, ParagraphFormatProperties, SectionFormatProperties } from '../document-editor/implementation'; @@ -19,7 +19,7 @@ import { ClickEventArgs } from '@syncfusion/ej2-navigations'; import { beforeAutoResize, internalAutoResize, internalZoomFactorChange, beforeCommentActionEvent, commentDeleteEvent, contentChangeEvent, trackChangeEvent, beforePaneSwitchEvent, serviceFailureEvent, documentChangeEvent, selectionChangeEvent, customContextMenuSelectEvent, customContextMenuBeforeOpenEvent, internalviewChangeEvent, beforeXmlHttpRequestSend, protectionTypeChangeEvent, internalDocumentEditorSettingsChange, internalStyleCollectionChange, revisionActionEvent } from '../document-editor/base/constants'; import { HelperMethods } from '../index'; import { SanitizeHtmlHelper } from '@syncfusion/ej2-base'; - +import { DialogUtility } from '@syncfusion/ej2-popups'; /** * Document Editor container component. */ @@ -605,7 +605,13 @@ export class DocumentEditorContainer extends Component implements I 'Columns': 'Columns', 'Column': 'Column', 'Page Breaks': 'Page Breaks', - 'Section Breaks': 'Section Breaks' + 'Section Breaks': 'Section Breaks', + 'Link to Previous': 'Link to Previous', + 'Link to PreviousTooltip': 'Link this section with previous section header or footer', + 'Alternate Text': 'Alternate Text', + 'The address of this site is not valid. Check the address and try again.' : 'The address of this site is not valid. Check the address and try again.', + 'OK':'OK', + 'Information':'Information' }; /* eslint-enable @typescript-eslint/naming-convention */ /** @@ -881,12 +887,19 @@ export class DocumentEditorContainer extends Component implements I if(!isNullOrUndefined(this.documentEditorSettings.maximumRows)) { this.documentEditor.documentEditorSettings.maximumRows = this.documentEditorSettings.maximumRows; } + if(!isNullOrUndefined(this.documentEditorSettings.maximumColumns)) { + this.documentEditor.documentEditorSettings.maximumColumns = this.documentEditorSettings.maximumColumns; + } if(!isNullOrUndefined(this.documentEditorSettings.showHiddenMarks)) { this.documentEditor.documentEditorSettings.showHiddenMarks = this.documentEditorSettings.showHiddenMarks; } if (!isNullOrUndefined(this.documentEditorSettings.showBookmarks)) { this.documentEditor.documentEditorSettings.showBookmarks = this.documentEditorSettings.showBookmarks; } + if(!isNullOrUndefined(this.documentEditorSettings.highlightEditableRanges)){ + this.documentEditor.documentEditorSettings.highlightEditableRanges = this.documentEditorSettings.highlightEditableRanges; + } + if (!isNullOrUndefined(this.documentEditorSettings.allowDragAndDrop)) { this.documentEditor.documentEditorSettings.allowDragAndDrop = this.documentEditorSettings.allowDragAndDrop; } @@ -988,6 +1001,7 @@ export class DocumentEditorContainer extends Component implements I width: '100%', enableTrackChanges: this.enableTrackChanges, showRevisions: true, + showComments: true, enableLockAndEdit: this.enableLockAndEdit, enableAutoFocus: this.enableAutoFocus }); @@ -1165,8 +1179,9 @@ export class DocumentEditorContainer extends Component implements I public onSelectionChange(): void { setTimeout(() => { this.showPropertiesPaneOnSelection(); - let eventArgs: ContainerSelectionChangeEventArgs = { source: this }; + let eventArgs: ContainerSelectionChangeEventArgs = { source: this , isCompleted: this.documentEditor.documentHelper.isSelectionCompleted}; this.trigger(selectionChangeEvent, eventArgs); + this.documentEditor.documentHelper.isSelectionCompleted = true; }); } /** @@ -1186,11 +1201,26 @@ export class DocumentEditorContainer extends Component implements I */ private onRequestNavigate(args: RequestNavigateEventArgs): void { if (args.linkType !== 'Bookmark') { - let link: string = SanitizeHtmlHelper.sanitize(args.navigationLink); + const navLink = args.navigationLink; + let link: string = SanitizeHtmlHelper.sanitize(navLink); if (args.localReference.length > 0) { link += '#' + args.localReference; } - window.open(link); + if (navLink.substring(0, 8) === 'file:///' + || (navLink.substring(0, 7) === 'http://' && navLink.length > 7) + || (navLink.substring(0, 8) === 'https://' && navLink.length > 8) + || (navLink.substring(0, 4) === 'www.' && navLink.length > 4) + || (navLink.substring(0, 7) === 'mailto:' && navLink.length > 7)) { + window.open(link); + } + else { + DialogUtility.alert({ + title: this.localObj.getConstant("Information"), + content: this.localObj.getConstant("The address of this site is not valid. Check the address and try again."), + okButton: { text: this.localObj.getConstant("OK") }, + closeOnEscape: true, + }); + } args.isHandled = true; } } @@ -1320,19 +1350,17 @@ export class DocumentEditorContainer extends Component implements I public destroy(): void { super.destroy(); if (this.element) { + if (!this.refreshing) { + this.element.classList.remove('e-documenteditorcontainer'); + } this.element.innerHTML = ''; } if (!this.refreshing) { - this.element.classList.remove('e-documenteditorcontainer'); this.element = undefined; this.paragraphFormat = undefined; this.sectionFormat = undefined; this.characterFormat = undefined; } - if (this.toolbarModule) { - this.toolbarModule.destroy(); - this.toolbarModule = undefined; - } if (this.toolbarContainer && this.toolbarContainer.parentElement) { this.toolbarContainer.innerHTML = ''; this.toolbarContainer.parentElement.removeChild(this.toolbarContainer); @@ -1385,4 +1413,4 @@ export class DocumentEditorContainer extends Component implements I this.statusBar = undefined; this.previousContext = undefined; } -} \ No newline at end of file +} diff --git a/controls/documenteditor/src/document-editor-container/properties-pane/header-footer-pane.ts b/controls/documenteditor/src/document-editor-container/properties-pane/header-footer-pane.ts index 22c2bc22e3..e738a633fd 100644 --- a/controls/documenteditor/src/document-editor-container/properties-pane/header-footer-pane.ts +++ b/controls/documenteditor/src/document-editor-container/properties-pane/header-footer-pane.ts @@ -8,6 +8,7 @@ import { NumericTextBox } from '@syncfusion/ej2-inputs'; import { Toolbar } from '../tool-bar/tool-bar'; import { DocumentEditorContainer } from '../document-editor-container'; import { DocumentEditor } from '../../document-editor/document-editor'; +import { HeaderFooterWidget } from '../../document-editor/implementation/viewer'; /** * @private */ @@ -16,6 +17,7 @@ export class HeaderFooterProperties { private container: DocumentEditorContainer; private firstPage: CheckBox; private oddOrEven: CheckBox; + private linkToPrevious: CheckBox; private pageNumber: CheckBox; private pageCount: CheckBox; private headerFromTop: NumericTextBox; @@ -111,11 +113,18 @@ export class HeaderFooterProperties { this.firstPage.appendTo(firstPage); firstPageDiv.children[0].setAttribute('title', localObj.getConstant('Different header and footer for first page')); const oddOrEvenDiv: HTMLElement = this.createDivTemplate(elementId + '_oddOrEvenDiv', optionsDiv); + classList(oddOrEvenDiv, ['e-de-hdr-ftr-frst-div'], []); const oddOrEven: HTMLInputElement = createElement('input', { id: 'oddOrEven', className: 'e-de-sub-prop-label' }) as HTMLInputElement; oddOrEvenDiv.appendChild(oddOrEven); this.oddOrEven = new CheckBox({ label: localObj.getConstant('Different Odd And Even Pages'), change: this.changeoddOrEvenOptions.bind(this), cssClass: 'e-de-prop-sub-label', enableRtl: this.isRtl }); this.oddOrEven.appendTo(oddOrEven); oddOrEvenDiv.children[0].setAttribute('title', localObj.getConstant('Different header and footer for odd and even pages')); + const linkToPreviousDiv: HTMLElement = this.createDivTemplate(elementId + '_linkToPreviousDiv', optionsDiv); + const linkToPrevious: HTMLInputElement = createElement('input', { id: 'linkToPrevious', className: 'e-de-sub-prop-label' }) as HTMLInputElement; + linkToPreviousDiv.appendChild(linkToPrevious); + this.linkToPrevious = new CheckBox({ label: localObj.getConstant('Link to Previous'), change: this.changeLinkToPreviousOptions.bind(this) ,cssClass: 'e-de-prop-sub-label', enableRtl: this.isRtl, checked: true }); + this.linkToPrevious.appendTo(linkToPrevious); + linkToPreviousDiv.children[0].setAttribute('title', localObj.getConstant('Link to the previous Title')); // let autoFieldLabelDiv: HTMLElement = this.createDivTemplate(element + '_autoFieldLabelDiv', div, 'padding-top:10px;padding-left: 10px;'); // let autoFieldLabel: HTMLElement = createElement('label', { className: 'e-de-header-prop-label', styles: 'height:20px;' }); // autoFieldLabel.innerHTML = 'Insert Autofield'; @@ -222,6 +231,36 @@ export class HeaderFooterProperties { }, 10); } } + private changeLinkToPreviousOptions(): void { + if (!this.documentEditor.isReadOnly) { + let headerFooterType: any = ((this.documentEditor.selection.start.paragraph.containerWidget) as HeaderFooterWidget).headerFooterType; + let value: boolean = this.linkToPrevious.checked; + switch (headerFooterType) { + case 'OddHeader': + this.documentEditor.selection.sectionFormat.oddPageHeader.linkToPrevious = value; + break; + case 'OddFooter': + this.documentEditor.selection.sectionFormat.oddPageFooter.linkToPrevious = value; + break; + case 'EvenHeader': + this.documentEditor.selection.sectionFormat.evenPageHeader.linkToPrevious = value; + break; + case 'EvenFooter': + this.documentEditor.selection.sectionFormat.evenPageFooter.linkToPrevious = value; + break; + case 'FirstPageHeader': + this.documentEditor.selection.sectionFormat.firstPageHeader.linkToPrevious = value; + break; + case 'FirstPageFooter': + this.documentEditor.selection.sectionFormat.firstPageFooter.linkToPrevious = value; + break; + + } + setTimeout((): void => { + this.documentEditor.focusIn(); + }, 10); + } + } private changeHeaderValue(): void { if (!this.isHeaderTopApply) { return; @@ -273,6 +312,32 @@ export class HeaderFooterProperties { } else { this.oddOrEven.checked = false; } + if (this.documentEditor.selection.start.paragraph.bodyWidget.sectionIndex == 0) { + this.linkToPrevious.disabled = true; + } else { + this.linkToPrevious.disabled = false; + let headerFooterType: any = ((this.documentEditor.selection.start.paragraph.containerWidget) as HeaderFooterWidget).headerFooterType; + switch (headerFooterType) { + case 'OddHeader': + this.linkToPrevious.checked = this.documentEditor.selection.sectionFormat.oddPageHeader.linkToPrevious; + break; + case 'OddFooter': + this.linkToPrevious.checked = this.documentEditor.selection.sectionFormat.oddPageFooter.linkToPrevious; + break; + case 'EvenHeader': + this.linkToPrevious.checked = this.documentEditor.selection.sectionFormat.evenPageHeader.linkToPrevious; + break; + case 'EvenFooter': + this.linkToPrevious.checked = this.documentEditor.selection.sectionFormat.evenPageFooter.linkToPrevious; + break; + case 'FirstPageHeader': + this.linkToPrevious.checked = this.documentEditor.selection.sectionFormat.firstPageHeader.linkToPrevious; + break; + case 'FirstPageFooter': + this.linkToPrevious.checked = this.documentEditor.selection.sectionFormat.firstPageFooter.linkToPrevious; + break; + } + } } public destroy(): void { if (this.element) { @@ -290,6 +355,10 @@ export class HeaderFooterProperties { this.oddOrEven.destroy(); } this.oddOrEven = undefined; + if (this.linkToPrevious) { + this.linkToPrevious.destroy(); + } + this.linkToPrevious = undefined; if (this.headerFromTop) { this.headerFromTop.destroy(); this.headerFromTop = undefined; diff --git a/controls/documenteditor/src/document-editor-container/properties-pane/image-properties-pane.ts b/controls/documenteditor/src/document-editor-container/properties-pane/image-properties-pane.ts index 7e5cb8039c..58e2d1cdf6 100644 --- a/controls/documenteditor/src/document-editor-container/properties-pane/image-properties-pane.ts +++ b/controls/documenteditor/src/document-editor-container/properties-pane/image-properties-pane.ts @@ -1,8 +1,11 @@ import { createElement, KeyboardEventArgs, L10n, classList } from '@syncfusion/ej2-base'; import { NumericTextBox } from '@syncfusion/ej2-inputs'; import { CheckBox } from '@syncfusion/ej2-buttons'; +import { TextBox } from '@syncfusion/ej2-inputs'; import { DocumentEditorContainer } from '../document-editor-container'; import { DocumentEditor } from '../../document-editor/document-editor'; +import { SanitizeHtmlHelper } from '@syncfusion/ej2-base'; +import { isNullOrUndefined } from '@syncfusion/ej2-base'; /** * Image Property pane * @@ -21,6 +24,8 @@ export class ImageProperties { private isWidthApply: boolean = false; private isHeightApply: boolean = false; private isRtl: boolean; + private textArea: HTMLElement; + private textareaObj: TextBox; private get documentEditor(): DocumentEditor { return this.container.documentEditor; @@ -50,12 +55,13 @@ export class ImageProperties { this.element.style.display = 'none'; this.container.propertiesPaneContainer.appendChild(this.element); this.initImageProp(); + this.initImageAltProp(); this.wireEvents(); } private initImageProp(): void { const localObj: L10n = new L10n('documenteditorcontainer', this.container.defaultLocale, this.container.locale); - const imageDiv: HTMLElement = createElement('div', { id: this.elementId + '_imageDiv', className: 'e-de-cntr-pane-padding', styles: 'border:0px' }); + const imageDiv: HTMLElement = createElement('div', { id: this.elementId + '_imageDiv', className: 'e-de-cntr-pane-padding e-de-prop-separator-line'}); this.element.appendChild(imageDiv); const label: HTMLElement = createElement('label', { className: 'e-de-ctnr-prop-label' }); label.textContent = localObj.getConstant('Image'); @@ -75,6 +81,20 @@ export class ImageProperties { aspectRatioDiv.appendChild(aspectRatio); this.aspectRatioBtn = new CheckBox({ label: localObj.getConstant('Aspect ratio'), enableRtl: this.isRtl }, aspectRatio); } + private initImageAltProp(): void { + const localObj: L10n = new L10n('documenteditorcontainer', this.container.defaultLocale, this.container.locale); + const AltDiv: HTMLElement = createElement('div', { id: this.elementId + '_altDiv', className: 'e-de-cntr-pane-padding e-de-prop-separator-line' }); + this.element.appendChild(AltDiv); + const label: HTMLElement = createElement('label', { className: 'e-de-ctnr-prop-label' }); + label.textContent = localObj.getConstant('Alternate Text'); + AltDiv.appendChild(label); + this.textArea = createElement('textarea', { id: this.elementId + '_textarea',className: 'e-de-ctnr-prop-label '}); + AltDiv.appendChild(this.textArea); + let textareaObj = new TextBox({ + floatLabelType: 'Never' + }); + textareaObj.appendTo(this.textArea); + }; /* eslint-disable-next-line max-len */ private createImagePropertiesDiv(id: string, outerDiv: HTMLElement, inputId: string, spanContent: string, tooltip: string): HTMLElement { const divElement: HTMLElement = createElement('div', { id: this.elementId + id, styles: 'position: relative;width: 100%;', className: 'e-de-ctnr-segment' }); @@ -103,6 +123,18 @@ export class ImageProperties { this.heightNumericBox.element.addEventListener('blur', (): void => { this.applyImageHeight(); this.isHeightApply = false; }); + this.textArea.addEventListener('blur', (): void => { + if (this.documentEditor.selection.imageFormat.alternateText != (this.textArea as HTMLInputElement).value) { + this.applyImageAlternativeText(); + } + }); + } + private applyImageAlternativeText(): void{ + let altText: string = SanitizeHtmlHelper.sanitize((this.textArea as HTMLInputElement).value); + if(!isNullOrUndefined(altText)) + { + this.documentEditor.selection.imageFormat.applyImageAlternativeText(altText); + } } private onImageWidth(e: KeyboardEventArgs): void { if (e.keyCode === 13) { @@ -181,6 +213,14 @@ export class ImageProperties { public updateImageProperties(): void { this.widthNumericBox.value = this.documentEditor.selection.imageFormat.width; this.heightNumericBox.value = this.documentEditor.selection.imageFormat.height; + if(isNullOrUndefined(this.documentEditor.selection.imageFormat.alternateText)) + { + (this.textArea as HTMLInputElement).value = ""; + } + else + { + (this.textArea as HTMLInputElement).value = this.documentEditor.selection.imageFormat.alternateText; + } } public destroy(): void { this.container = undefined; @@ -192,7 +232,7 @@ export class ImageProperties { this.heightNumericBox.destroy(); } this.heightNumericBox = undefined; - if (this.aspectRatioBtn) { + if (this.aspectRatioBtn) { this.aspectRatioBtn.destroy(); } this.aspectRatioBtn = undefined; diff --git a/controls/documenteditor/src/document-editor-container/properties-pane/paragraph-properties.ts b/controls/documenteditor/src/document-editor-container/properties-pane/paragraph-properties.ts index 32a27d04c7..fba7b4506a 100644 --- a/controls/documenteditor/src/document-editor-container/properties-pane/paragraph-properties.ts +++ b/controls/documenteditor/src/document-editor-container/properties-pane/paragraph-properties.ts @@ -462,18 +462,22 @@ export class Paragraph { } private createStyleDropDownList(selectElement: HTMLElement): void { this.style = new ComboBox({ - dataSource: [{ StyleName: 'Normal', Class: 'e-icons e-edit-font' }], + dataSource: [{ StyleName: 'Normal', IconClass: 'e-de-e-paragraph-mark e-icons' }], cssClass: 'e-de-prop-dropdown', popupHeight: '240px', enableRtl: this.isRtl, - query: new Query().select(['StyleName', 'Style']), + query: new Query().select(['StyleName', 'Style', 'IconClass']), fields: { text: 'StyleName', value: 'StyleName' }, showClearButton: false, change: this.selectStyleValue.bind(this) }); if (!this.container.enableCsp) { this.style.open = this.updateOptions.bind(this); - this.style.itemTemplate = '${StyleName}'; + if (this.isRtl) { + this.style.itemTemplate = '${StyleName}'; + } else { + this.style.itemTemplate = '${StyleName}'; + } this.style.footerTemplate = '' + this.localObj.getConstant('Manage Styles') + '...' + ''; this.style.isStringTemplate = true; @@ -491,8 +495,12 @@ export class Paragraph { } public updateStyleNames(): void { this.styleName = !isNullOrUndefined((this.style as any).itemData) ? (this.style as any).itemData.StyleName : undefined; - this.style.dataSource = this.constructStyleDropItems(this.documentEditor.getStyles('Paragraph')); - this.style.dataBind(); + let paraStyles: Object[] = this.documentEditor.getStyles('Paragraph').filter(obj => (obj as any).type == "Paragraph"); + let linkedStyles: Object[] = this.documentEditor.getStyles('Paragraph').filter(obj => (obj as any).type == "Linked"); + let charStyles: Object[] = this.documentEditor.getStyles('Character').filter(obj => (obj as any).type == "Character"); + let styleData: Object[] = paraStyles.concat(linkedStyles, charStyles); + this.style.dataSource = this.constructStyleDropItems(styleData); + // this.style.dataBind(); this.onSelectionChange(); } private createStyle(): void { @@ -503,11 +511,21 @@ export class Paragraph { } private constructStyleDropItems(styles: unknown[]): any { const collection: any = []; + const paraIcon: string = 'e-list-icon e-de-listview-icon e-de-e-paragraph-style-mark e-icons'; + const charIcon: string = 'e-list-icon e-de-listview-icon e-de-e-character-style-mark e-icons'; + const linkedIcon: string = 'e-list-icon e-de-listview-icon e-de-e-linked-style-mark e-icons'; for (const styleObj of styles) { const obj: any = {}; const styleName: string = this.localObj.getConstant((styleObj as any).name); obj.StyleName = styleName === '' ? (styleObj as any).name : styleName; obj.Style = this.parseStyle((styleObj as any).style as string); + if (((styleObj as any).type as string) == "Paragraph") { + obj.IconClass = paraIcon; + } else if (((styleObj as any).type as string) == "Character") { + obj.IconClass = charIcon; + } else { + obj.IconClass = linkedIcon; + } collection.push(obj); } return collection; @@ -869,7 +887,10 @@ export class Paragraph { this.isRetrieving = true; if (this.documentEditor.editor) { //#region paragraph format - const style: string = this.documentEditor.selection.paragraphFormat.styleName; + let style: string = this.documentEditor.selection.characterFormat.styleName; + if (this.documentEditor.selection.characterFormat.styleName === "Default Paragraph Font") { + style = this.documentEditor.selection.paragraphFormat.styleName; + } if (style) { let localeValue: string = this.localObj.getConstant(style); this.style.value = (isNullOrUndefined(localeValue) || localeValue == '') ? style : localeValue; diff --git a/controls/documenteditor/src/document-editor-container/properties-pane/table-properties-pane.ts b/controls/documenteditor/src/document-editor-container/properties-pane/table-properties-pane.ts index 50ee202635..fa43d203db 100644 --- a/controls/documenteditor/src/document-editor-container/properties-pane/table-properties-pane.ts +++ b/controls/documenteditor/src/document-editor-container/properties-pane/table-properties-pane.ts @@ -109,7 +109,7 @@ export class TableProperties { private addTablePropertyTab(): void { const tableHeader: HTMLElement = createElement('div', { innerHTML: this.localObj.getConstant('Table') }); const textHeader: HTMLElement = createElement('div', { innerHTML: this.localObj.getConstant('Text') }); - this.parentElement = createElement('div', { styles: 'height:100%;overflow:auto;display:none', className: 'e-de-prop-pane' }); + this.parentElement = createElement('div', { styles: 'height:100%;overflow:auto;display:none', className: 'e-de-prop-pane e-de-scrollbar-hide' }); this.element = createElement('div', { id: this.elementId + '_propertyTabDiv', className: 'e-de-property-tab' }); /* eslint-disable-next-line max-len */ const items: TabItemModel[] = [{ header: { text: textHeader }, content: this.tableTextProperties.element }, { header: { text: tableHeader }, content: this.tableProperties }] as TabItemModel[]; diff --git a/controls/documenteditor/src/document-editor-container/properties-pane/text-properties.ts b/controls/documenteditor/src/document-editor-container/properties-pane/text-properties.ts index 0d83b99687..c9c8c67ece 100644 --- a/controls/documenteditor/src/document-editor-container/properties-pane/text-properties.ts +++ b/controls/documenteditor/src/document-editor-container/properties-pane/text-properties.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -import { createElement, L10n, classList, isNullOrUndefined } from '@syncfusion/ej2-base'; +import { createElement, L10n, classList, isNullOrUndefined, initializeCSPTemplate } from '@syncfusion/ej2-base'; import { DocumentEditor, HighlightColor } from '../../document-editor/index'; import { ComboBox } from '@syncfusion/ej2-dropdowns'; import { Button } from '@syncfusion/ej2-buttons'; @@ -435,9 +435,11 @@ export class Text { /* eslint-disable */ let fontStyle: { [key: string]: any }[]; let isStringTemplate: boolean = false; - let itemTemplate: string = ''; + let itemTemplate: string | Function = ''; if (!this.container.enableCsp) { - itemTemplate = '${FontName}'; + itemTemplate = initializeCSPTemplate( + function (data: any): string { return `${data.FontName}`; } + ); isStringTemplate = true; } this.fontFamily = new ComboBox({ diff --git a/controls/documenteditor/src/document-editor-container/tool-bar/tool-bar.ts b/controls/documenteditor/src/document-editor-container/tool-bar/tool-bar.ts index 2b417426e1..6a23e14629 100644 --- a/controls/documenteditor/src/document-editor-container/tool-bar/tool-bar.ts +++ b/controls/documenteditor/src/document-editor-container/tool-bar/tool-bar.ts @@ -850,7 +850,7 @@ export class Toolbar { const image: HTMLImageElement = document.createElement('img'); const container: DocumentEditorContainer = this.container; image.addEventListener('load', function (): void { - container.documentEditor.editor.insertImageInternal(data, true, this.width, this.height); + container.documentEditor.editor.insertImageInternal(data, true, this.width, this.height,this.alt); }); image.src = data; } @@ -948,6 +948,9 @@ export class Toolbar { if (this.containsItem(id + FOOTNOTE_ID)) { this.toolbar.enableItems(document.getElementById(id + FOOTNOTE_ID).parentElement, false); } + if (this.containsItem(id+BREAK_ID)) { + this.toolbar.enableItems(document.getElementById(id +BREAK_ID).parentElement, false); + } } if (!isProtectedContent || this.container.showPropertiesPane) { if (isProtectedContent) { diff --git a/controls/documenteditor/src/document-editor/base/events-helper.ts b/controls/documenteditor/src/document-editor/base/events-helper.ts index d94477cbd6..9b95c66afd 100644 --- a/controls/documenteditor/src/document-editor/base/events-helper.ts +++ b/controls/documenteditor/src/document-editor/base/events-helper.ts @@ -111,6 +111,10 @@ export interface SelectionChangeEventArgs { * @deprecated */ source: DocumentEditor + /** + * Indicates whether the selection has been completed or not. + */ + isCompleted: boolean } /** * This event arguments provides the necessary information about requestNavigate event. @@ -306,6 +310,10 @@ export interface ContainerSelectionChangeEventArgs { * @deprecated */ source: DocumentEditorContainer + /** + * Indicates whether the selection has been completed or not. + */ + isCompleted: boolean } /** * This event arguments provides the necessary information about DocumentEditorContainer's documentChange event. diff --git a/controls/documenteditor/src/document-editor/base/keywords.ts b/controls/documenteditor/src/document-editor/base/keywords.ts index 1ab341b887..27d9ebfefc 100644 --- a/controls/documenteditor/src/document-editor/base/keywords.ts +++ b/controls/documenteditor/src/document-editor/base/keywords.ts @@ -49,6 +49,7 @@ export const fontFamilyProperty: string[] = ['fontFamily','ff']; export const styleNameProperty: string[] = ['styleName','stn']; export const bidiProperty: string[] = ['bidi','bi']; export const bdoProperty: string[] = ['bdo','bdo']; +export const breakClearTypeProperty: string[] = ['breakClearType','bct']; export const fontSizeBidiProperty: string[] = ['fontSizeBidi','fszbi']; export const fontFamilyBidiProperty: string[] = ['fontFamilyBidi','ffbi']; export const boldBidiProperty: string[] = ['boldBidi','bbi']; @@ -60,6 +61,8 @@ export const fontFamilyFarEastProperty: string[] = ['fontFamilyFarEast','fffe']; export const fontFamilyNonFarEastProperty: string[] = ['fontFamilyNonFarEast','ffnfe']; export const revisionIdsProperty: string[] = ['revisionIds','rids']; export const listIdProperty: string[] = ['listId','lid']; +export const characterSpacingProperty: string[] = ['characterSpacing','csp']; +export const scalingProperty: string[] = ['scaling','sc']; export const listLevelNumberProperty: string[] = ['listLevelNumber','lilno']; export const leftIndentProperty: string[] = ['leftIndent','lin']; export const rightIndentProperty: string[] = ['rightIndent','rin']; @@ -205,6 +208,8 @@ export const textWrappingStyleProperty: string[] = ['textWrappingStyle','tws']; export const textWrappingTypeProperty: string[] = ['textWrappingType','twt']; export const verticalRelativePercentProperty: string[] = ['verticalRelativePercent','vrp']; export const horizontalRelativePercentProperty: string[] = ['horizontalRelativePercent','hrp']; +export const heightRelativePercentProperty: string[] = ['heightRelativePercent','hrp']; +export const widthRelativePercentProperty: string[] = ['widthRelativePercent','wrp']; export const zOrderPositionProperty: string[] = ['zOrderPosition','z']; export const layoutInCellProperty: string[] = ['layoutInCell','lc']; export const lockAnchorProperty: string[] = ['lockAnchor','la']; diff --git a/controls/documenteditor/src/document-editor/base/types.ts b/controls/documenteditor/src/document-editor/base/types.ts index 8c4f7e7b70..91c8661ce1 100644 --- a/controls/documenteditor/src/document-editor/base/types.ts +++ b/controls/documenteditor/src/document-editor/base/types.ts @@ -1222,7 +1222,7 @@ export type Action = 'Insert' | 'Delete' | 'BackSpace' | 'Selection' | 'MultiSel |'BottomBorder' |'HorizontalBorder' |'VerticalBorder'|'ColumnBreak' -|'DragAndDropContent'; +|'DragAndDropContent'|'LinkToPrevious'; /** * Enum for direction */ @@ -2626,4 +2626,24 @@ export enum SectionBreakType { * Section break with the new section beginning on the next odd-numbered page. */ OddPage = 'OddPage' -} \ No newline at end of file +} +/** +* Specifies the clear type of the Text Wrapping break. +*/ +export type BreakClearType = + /** + * Specifies the text to start on next line ragrdless of any floating objects.. + */ + 'None' | + /** + * Specifies the text to start on next text region left to right. + */ + 'Left' | + /** + * Specifies the text to start on next text region right to left. + */ + 'Right' | + /** + * Specifies the text to start on next full line. + */ + 'All'; \ No newline at end of file diff --git a/controls/documenteditor/src/document-editor/base/unique-format.ts b/controls/documenteditor/src/document-editor/base/unique-format.ts index d6a37bd538..55b06112f6 100644 --- a/controls/documenteditor/src/document-editor/base/unique-format.ts +++ b/controls/documenteditor/src/document-editor/base/unique-format.ts @@ -373,6 +373,12 @@ export class WUniqueFormat { if (property === 'localeIdFarEast') { return 23; } + if (property === 'characterSpacing') { + return 24; + } + if (property === 'scaling') { + return 25; + } return 0; } private static getParaFormatPropertyType(property: string): number { @@ -613,6 +619,12 @@ export class WUniqueFormat { if (this.isNotEqual('fontFamilyNonFarEast', source, modifiedProperty, modifiedValue, 2)) { return false; } + if (this.isNotEqual('characterSpacing', source, modifiedProperty, modifiedValue, 2)) { + return false; + } + if (this.isNotEqual('scaling', source, modifiedProperty, modifiedValue, 2)) { + return false; + } return true; } diff --git a/controls/documenteditor/src/document-editor/document-editor-model.d.ts b/controls/documenteditor/src/document-editor/document-editor-model.d.ts index ba28cb086c..c8a4d135bc 100644 --- a/controls/documenteditor/src/document-editor/document-editor-model.d.ts +++ b/controls/documenteditor/src/document-editor/document-editor-model.d.ts @@ -1,4 +1,4 @@ -import { Component, Property, INotifyPropertyChanged, NotifyPropertyChanges, Event, ModuleDeclaration, ChildProperty, classList, Complex, formatUnit } from '@syncfusion/ej2-base';import { isNullOrUndefined, L10n, EmitType, Browser } from '@syncfusion/ej2-base';import { Save } from '@syncfusion/ej2-file-utils';import { DocumentChangeEventArgs, ViewChangeEventArgs, ZoomFactorChangeEventArgs, StyleType, WStyle, BeforePaneSwitchEventArgs, LayoutType, FormFieldFillEventArgs, FormFieldData } from './index';import { SelectionChangeEventArgs, RequestNavigateEventArgs, ContentChangeEventArgs, DocumentEditorKeyDownEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, CommentDeleteEventArgs, BeforeFileOpenArgs, CommentActionEventArgs, XmlHttpRequestEventArgs, RevisionActionEventArgs } from './index';import { LayoutViewer, PageLayoutViewer, WebLayoutViewer, BulletsAndNumberingDialog } from './index';import { Print, SearchResultsChangeEventArgs } from './index';import { Page, BodyWidget, ParagraphWidget } from './index';import { WSectionFormat, WParagraphFormat, WCharacterFormat } from './index';import { SfdtReader } from './index';import { Selection } from './index';import { TextPosition } from './index';import { Editor, EditorHistory } from './index';import { WStyles } from './index';import { HeaderFooters } from './index';import { Search } from './index';import { OptionsPane } from './index';import { WordExport } from './index';import { TextExport } from './index';import { FormatType, PageFitType, DialogType, FormattingExceptions, CompatibilityMode } from './index';import { ContextMenu } from './index';import { ImageResizer } from './index';import { SfdtExport } from './index';import { HyperlinkDialog, TableDialog, BookmarkDialog, StylesDialog, TableOfContentsDialog } from './index';import { PageSetupDialog, ParagraphDialog, ListDialog, StyleDialog, FontDialog } from './index';import { TablePropertiesDialog, BordersAndShadingDialog, CellOptionsDialog, TableOptionsDialog } from './index';import { SpellChecker } from './implementation/spell-check/spell-checker';import { SpellCheckDialog } from './implementation/dialogs/spellCheck-dialog';import { CharacterFormatProperties, ParagraphFormatProperties, SectionFormatProperties, DocumentHelper } from './index';import { PasteOptions } from './index';import { CommentReviewPane, CheckBoxFormFieldDialog, DropDownFormField, TextFormField, CheckBoxFormField, FieldElementBox, TextFormFieldInfo, CheckBoxFormFieldInfo, DropDownFormFieldInfo, ContextElementInfo, CollaborativeEditing, CollaborativeEditingEventArgs } from './implementation/index';import { TextFormFieldDialog } from './implementation/dialogs/form-field-text-dialog';import { DropDownFormFieldDialog } from './implementation/dialogs/form-field-drop-down-dialog';import { FormFillingMode, TrackChangeEventArgs, ServiceFailureArgs, ImageFormat } from './base';import { TrackChangesPane } from './implementation/track-changes/track-changes-pane';import { RevisionCollection } from './implementation/track-changes/track-changes';import { NotesDialog } from './implementation/dialogs/notes-dialog';import { FootNoteWidget } from './implementation/viewer/page';import { internalZoomFactorChange, contentChangeEvent, documentChangeEvent, selectionChangeEvent, zoomFactorChangeEvent, beforeFieldFillEvent, afterFieldFillEvent, serviceFailureEvent, viewChangeEvent, customContextMenuSelectEvent, customContextMenuBeforeOpenEvent, internalviewChangeEvent, internalDocumentEditorSettingsChange } from './base/constants';import { Optimized, Regular, HelperMethods } from './index';import { ColumnsDialog } from './implementation/dialogs/columns-dialog';import { DocumentCanvasElement } from './implementation/viewer/document-canvas';import { ZipArchiveItem, ZipArchive } from '@syncfusion/ej2-compression'; +import { Component, Property, INotifyPropertyChanged, NotifyPropertyChanges, Event, ModuleDeclaration, ChildProperty, classList, Complex, formatUnit } from '@syncfusion/ej2-base';import { isNullOrUndefined, L10n, EmitType, Browser } from '@syncfusion/ej2-base';import { Save } from '@syncfusion/ej2-file-utils';import { DocumentChangeEventArgs, ViewChangeEventArgs, ZoomFactorChangeEventArgs, StyleType, WStyle, BeforePaneSwitchEventArgs, LayoutType, FormFieldFillEventArgs, FormFieldData } from './index';import { SelectionChangeEventArgs, RequestNavigateEventArgs, ContentChangeEventArgs, DocumentEditorKeyDownEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, CommentDeleteEventArgs, RevisionActionEventArgs, BeforeFileOpenArgs, CommentActionEventArgs, XmlHttpRequestEventArgs } from './index';import { LayoutViewer, PageLayoutViewer, WebLayoutViewer, BulletsAndNumberingDialog } from './index';import { Print, SearchResultsChangeEventArgs } from './index';import { Page, BodyWidget, ParagraphWidget } from './index';import { WSectionFormat, WParagraphFormat, WCharacterFormat } from './index';import { SfdtReader } from './index';import { Selection } from './index';import { TextPosition } from './index';import { Editor, EditorHistory } from './index';import { WStyles } from './index';import { HeaderFooters } from './index';import { Search } from './index';import { OptionsPane } from './index';import { WordExport } from './index';import { TextExport } from './index';import { FormatType, PageFitType, DialogType, FormattingExceptions, CompatibilityMode } from './index';import { ContextMenu } from './index';import { ImageResizer } from './index';import { SfdtExport } from './index';import { HyperlinkDialog, TableDialog, BookmarkDialog, StylesDialog, TableOfContentsDialog } from './index';import { PageSetupDialog, ParagraphDialog, ListDialog, StyleDialog, FontDialog } from './index';import { TablePropertiesDialog, BordersAndShadingDialog, CellOptionsDialog, TableOptionsDialog } from './index';import { SpellChecker } from './implementation/spell-check/spell-checker';import { SpellCheckDialog } from './implementation/dialogs/spellCheck-dialog';import { CharacterFormatProperties, ParagraphFormatProperties, SectionFormatProperties, DocumentHelper } from './index';import { PasteOptions } from './index';import { CommentReviewPane, CheckBoxFormFieldDialog, DropDownFormField, TextFormField, CheckBoxFormField, FieldElementBox, TextFormFieldInfo, CheckBoxFormFieldInfo, DropDownFormFieldInfo, ContextElementInfo, CollaborativeEditing, CollaborativeEditingEventArgs } from './implementation/index';import { TextFormFieldDialog } from './implementation/dialogs/form-field-text-dialog';import { DropDownFormFieldDialog } from './implementation/dialogs/form-field-drop-down-dialog';import { FormFillingMode, TrackChangeEventArgs, ServiceFailureArgs, ImageFormat } from './base';import { TrackChangesPane } from './implementation/track-changes/track-changes-pane';import { RevisionCollection } from './implementation/track-changes/track-changes';import { NotesDialog } from './implementation/dialogs/notes-dialog';import { FootNoteWidget } from './implementation/viewer/page';import { internalZoomFactorChange, contentChangeEvent, documentChangeEvent, selectionChangeEvent, zoomFactorChangeEvent, beforeFieldFillEvent, afterFieldFillEvent, serviceFailureEvent, viewChangeEvent, customContextMenuSelectEvent, customContextMenuBeforeOpenEvent, internalviewChangeEvent, internalDocumentEditorSettingsChange } from './base/constants';import { Optimized, Regular, HelperMethods } from './index';import { ColumnsDialog } from './implementation/dialogs/columns-dialog';import { DocumentCanvasElement } from './implementation/viewer/document-canvas';import { ZipArchiveItem, ZipArchive } from '@syncfusion/ej2-compression'; import {ComponentModel} from '@syncfusion/ej2-base'; /** @@ -66,6 +66,14 @@ export interface DocumentEditorSettingsModel { */ maximumRows?: number; + /** + * Gets or sets the maximum number of columns allowed while inserting a table in Document editor component. + * > The maximum value is 63, as per Microsoft Word application and you can set any value less than 63 to this property. If you set any value greater than 63, then Syncfusion Document editor will automatically reset as 63. + * @default 63 + * @returns {number} + */ + maximumColumns?: number; + /** * Gets or sets a value indicating whether to show the hidden characters like spaces, tab, paragraph marks, and breaks. * @@ -84,6 +92,15 @@ export interface DocumentEditorSettingsModel { */ showBookmarks?: boolean; + /** + * Gets or sets a value indicating whether to highlight the editable ranges in the document where the current user can edit. + * + * @default true + * @aspType bool + * @returns {boolean} Returns `true` if editable ranges in the document is highlighted. Otherwise `false`. + */ + highlightEditableRanges?: boolean; + /** * Describes whether to reduce the resultant SFDT file size by minifying the file content * diff --git a/controls/documenteditor/src/document-editor/document-editor.ts b/controls/documenteditor/src/document-editor/document-editor.ts index f6c29f1608..46ec94b7f1 100644 --- a/controls/documenteditor/src/document-editor/document-editor.ts +++ b/controls/documenteditor/src/document-editor/document-editor.ts @@ -2,7 +2,7 @@ import { Component, Property, INotifyPropertyChanged, NotifyPropertyChanges, Eve import { isNullOrUndefined, L10n, EmitType, Browser } from '@syncfusion/ej2-base'; import { Save } from '@syncfusion/ej2-file-utils'; import { DocumentChangeEventArgs, ViewChangeEventArgs, ZoomFactorChangeEventArgs, StyleType, WStyle, BeforePaneSwitchEventArgs, LayoutType, FormFieldFillEventArgs, FormFieldData } from './index'; -import { SelectionChangeEventArgs, RequestNavigateEventArgs, ContentChangeEventArgs, DocumentEditorKeyDownEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, CommentDeleteEventArgs, BeforeFileOpenArgs, CommentActionEventArgs, XmlHttpRequestEventArgs, RevisionActionEventArgs } from './index'; +import { SelectionChangeEventArgs, RequestNavigateEventArgs, ContentChangeEventArgs, DocumentEditorKeyDownEventArgs, CustomContentMenuEventArgs, BeforeOpenCloseCustomContentMenuEventArgs, CommentDeleteEventArgs, RevisionActionEventArgs, BeforeFileOpenArgs, CommentActionEventArgs, XmlHttpRequestEventArgs } from './index'; import { LayoutViewer, PageLayoutViewer, WebLayoutViewer, BulletsAndNumberingDialog } from './index'; import { Print, SearchResultsChangeEventArgs } from './index'; import { Page, BodyWidget, ParagraphWidget } from './index'; @@ -116,6 +116,15 @@ export class DocumentEditorSettings extends ChildProperty The maximum value is 63, as per Microsoft Word application and you can set any value less than 63 to this property. If you set any value greater than 63, then Syncfusion Document editor will automatically reset as 63. + * @default 63 + * @returns {number} + */ + @Property(63) + public maximumColumns: number; + /** * Gets or sets a value indicating whether to show the hidden characters like spaces, tab, paragraph marks, and breaks. * @@ -136,6 +145,16 @@ export class DocumentEditorSettings extends ChildProperty implements INotifyPro if (!isNullOrUndefined(model.documentEditorSettings.showHiddenMarks) && (model.documentEditorSettings.showHiddenMarks !== oldProp.documentEditorSettings.showHiddenMarks)) { this.viewer.updateScrollBars(); } - if (!isNullOrUndefined(model.documentEditorSettings.showBookmarks) && (model.documentEditorSettings.showBookmarks !== oldProp.documentEditorSettings.showBookmarks)) { - this.viewer.updateScrollBars(); + if(!isNullOrUndefined(model.documentEditorSettings.highlightEditableRanges)){ + if (this.documentHelper && this.documentHelper.restrictEditingPane) { + this.documentHelper.restrictEditingPane.highlightCheckBox.checked = model.documentEditorSettings.highlightEditableRanges; + } } break; case 'height': @@ -1534,9 +1555,11 @@ export class DocumentEditor extends Component implements INotifyPro if (!this.documentHelper.isCompositionStart && Browser.isDevice && this.editorModule) { this.editorModule.predictText(); } - const eventArgs: SelectionChangeEventArgs = { source: this }; + const eventArgs: SelectionChangeEventArgs = { source: this , isCompleted:this.documentHelper.isCompleted}; // if (this.createdTriggered) { this.trigger(selectionChangeEvent, eventArgs); + this.documentHelper.isSelectionCompleted = this.documentHelper.isCompleted; + this.documentHelper.isCompleted = true; // } } /** @@ -2027,6 +2050,8 @@ export class DocumentEditor extends Component implements INotifyPro 'Even Page Footer': 'Even Page Footer', 'Odd Page Header': 'Odd Page Header', 'Odd Page Footer': 'Odd Page Footer', + 'Same as Previous': 'Same as Previous', + 'Section': 'Section', 'Margin': 'Margins', 'Paper': 'Paper', 'Layout': 'Layout', @@ -2379,8 +2404,9 @@ export class DocumentEditor extends Component implements INotifyPro 'Emboss3D':'Emboss3D', 'ThinThickLargeGap':'ThinThickLargeGap', 'ThinThickMediumGap':'ThinThickMediumGap', - 'Number of rows must be between 1 and 32767.': 'Number of rows must be between 1 and 32767.', - 'Number of columns must be between 1 and 63.':'Number of columns must be between 1 and 63.', + 'Number of rows must be between': 'Number of rows must be between', + 'Number of columns must be between':'Number of columns must be between', + 'and' : 'and', 'Unlimited' : 'Unlimited', 'Regular text': 'Regular text', 'Date': 'Date', @@ -2416,9 +2442,9 @@ export class DocumentEditor extends Component implements INotifyPro 'Paste Content CheckBox' : 'Don’t show again', 'BookMarkList':'List of bookmarks in the document', 'Discard':'Discard', - "The top/bottom margins are too large for the page height in some sections.":"The top/bottom margins are too large for the page height in some sections.", - "Column width cannot be less than 36 pt.": "Column width cannot be less than 36 pt.", - "Left and right margins.": "Settings you chose for the left and right margins, column spacing, or pargraph indents are too large for the page width in same secitions." + 'The top/bottom margins are too large for the page height in some sections.':'The top/bottom margins are too large for the page height in some sections.', + 'Column width cannot be less than 36 pt.': 'Column width cannot be less than 36 pt.', + 'Left and right margins.': 'Settings you chose for the left and right margins, column spacing, or pargraph indents are too large for the page width in same secitions.' }; /* eslint-enable */ // Public Implementation Starts @@ -2430,7 +2456,6 @@ export class DocumentEditor extends Component implements INotifyPro */ public open(sfdtText: string): void { if (!isNullOrUndefined(this.viewer)) { - this.showComments = false; this.clearPreservedCollectionsInViewer(); this.documentHelper.userCollection.push('Everyone'); this.documentHelper.lists = []; @@ -2880,7 +2905,6 @@ export class DocumentEditor extends Component implements INotifyPro this.clearSpellCheck(); this.documentHelper.setDefaultDocumentFormat(); this.documentHelper.headersFooters.push(hfs); - this.documentHelper.onDocumentChanged(sections); if (this.editorModule) { this.editorModule.intializeDefaultStyles(); const style: WStyle = this.documentHelper.styles.findByName('Normal') as WStyle; @@ -2890,6 +2914,7 @@ export class DocumentEditor extends Component implements INotifyPro paragraph.paragraphFormat.listFormat.baseStyle = style; } } + this.documentHelper.onDocumentChanged(sections); } } /** diff --git a/controls/documenteditor/src/document-editor/implementation/comments/comment.ts b/controls/documenteditor/src/document-editor/implementation/comments/comment.ts index 9bb2821910..eb6702a3cb 100644 --- a/controls/documenteditor/src/document-editor/implementation/comments/comment.ts +++ b/controls/documenteditor/src/document-editor/implementation/comments/comment.ts @@ -101,6 +101,11 @@ export class CommentReviewPane { this.owner.notify('reviewPane', { comment: this.isCommentTabVisible, changes: this.owner.trackChangesPane.isChangesTabVisible }); this.reviewTab.hideTab(1, true); } + if (!this.owner.showComments) { + this.isCommentTabVisible = false; + this.owner.notify('reviewPane', { comment: this.isCommentTabVisible, changes: this.owner.trackChangesPane.isChangesTabVisible }); + this.reviewTab.hideTab(0, true); + } } if (show) { this.enableDisableItems(); @@ -169,7 +174,7 @@ export class CommentReviewPane { public initReviewPane(localValue: L10n): void { const reviewContainer: HTMLElement = this.owner.documentHelper.optionsPaneContainer; - reviewContainer.style.display = 'inline-flex'; + reviewContainer.style.display = 'flex'; this.initPaneHeader(localValue); reviewContainer.appendChild(this.addReviewTab(localValue)); this.initCommentPane(); @@ -737,7 +742,7 @@ export class CommentPane { this.parentPane.isCommentTabVisible = false; this.owner.notify('reviewPane', { comment: false, changes: this.owner.trackChangesPane.isChangesTabVisible}); this.parentPane.reviewTab.hideTab(0); - } else { + } else if (this.owner.showComments) { this.parentPane.isCommentTabVisible = true; this.noCommentIndicator.style.display = 'none'; this.owner.notify('reviewPane', { comment: true, changes: this.owner.trackChangesPane.isChangesTabVisible}); diff --git a/controls/documenteditor/src/document-editor/implementation/context-menu.ts b/controls/documenteditor/src/document-editor/implementation/context-menu.ts index 2b204f34fe..37221528fc 100644 --- a/controls/documenteditor/src/document-editor/implementation/context-menu.ts +++ b/controls/documenteditor/src/document-editor/implementation/context-menu.ts @@ -6,7 +6,7 @@ import { Selection, ContextElementInfo } from './index'; import { TextPosition } from './selection/selection-helper'; import { FieldElementBox, ElementBox, TextFormField, CheckBoxFormField, DropDownFormField } from './viewer/page'; import { SpellChecker } from './spell-check/spell-checker'; -import { HelperMethods, Point } from './editor/editor-helper'; +import { Point } from './editor/editor-helper'; import { CheckBox } from '@syncfusion/ej2-buttons'; import { DialogUtility } from '@syncfusion/ej2-popups'; import { createElement } from '@syncfusion/ej2-base'; @@ -644,7 +644,7 @@ export class ContextMenu { let splittedSuggestion: string[]; /* eslint-disable @typescript-eslint/no-explicit-any */ let allSuggestions: any; - let exactData: string = HelperMethods.manageSpecialCharacters(this.currentContextInfo.text, undefined, true); + let exactData: string = this.spellChecker.manageSpecialCharacters(this.currentContextInfo.text, undefined, true); if (!isNullOrUndefined(exactData) && this.spellChecker.errorWordCollection.containsKey(exactData)) { this.spellChecker.currentContextInfo = this.currentContextInfo; if (this.spellChecker.errorSuggestions.containsKey(exactData)) { diff --git a/controls/documenteditor/src/document-editor/implementation/dialogs/borders-and-shading-dialog.ts b/controls/documenteditor/src/document-editor/implementation/dialogs/borders-and-shading-dialog.ts index dfdd05fa51..81264b95f2 100644 --- a/controls/documenteditor/src/document-editor/implementation/dialogs/borders-and-shading-dialog.ts +++ b/controls/documenteditor/src/document-editor/implementation/dialogs/borders-and-shading-dialog.ts @@ -480,7 +480,7 @@ export class BordersAndShadingDialog { // handling dropdown change this.borderWidth = new NumericTextBox({ - value: 0, min: 0, max: 6, decimals: 2, + value: 0.5, min: 0.25, max: 6, decimals: 2, step: 0.25, floatLabelType: 'Always', placeholder: localeValue.getConstant('Width'), enablePersistence: false }); @@ -617,7 +617,7 @@ export class BordersAndShadingDialog { if (this.ulelementShading.value === 'Cell') { editorModule.onCellFormat(this.cellFormat); } else if (this.ulelementShading.value === 'Table') { - editorModule.onTableFormat(this.tableFormat, this.isShadingChanged); + editorModule.onTableFormat(this.tableFormat, true); } if (!isNullOrUndefined(this.documentHelper.owner.editorHistory.currentHistoryInfo)) { this.documentHelper.owner.editorHistory.updateComplexHistory(); diff --git a/controls/documenteditor/src/document-editor/implementation/dialogs/form-field-popup.ts b/controls/documenteditor/src/document-editor/implementation/dialogs/form-field-popup.ts index 4d0ce88863..c46b551703 100644 --- a/controls/documenteditor/src/document-editor/implementation/dialogs/form-field-popup.ts +++ b/controls/documenteditor/src/document-editor/implementation/dialogs/form-field-popup.ts @@ -234,11 +234,12 @@ export class FormFieldPopUp { } else if (formFieldData instanceof DropDownFormField) { classList(this.target, ['e-de-ddl-form'], []); + this.ddlInstance.refresh(); this.ddlInstance.dataSource = formFieldData.dropdownItems; this.ddlInstance.index = formFieldData.selectedIndex; setTimeout(() => { this.ddlInstance.showPopup(); - }); + }, 50); } const left: number = this.owner.selection.getLeftInternal(formField.line, formField, 0); const lineHeight: number = formField.line.height * this.owner.documentHelper.zoomFactor; diff --git a/controls/documenteditor/src/document-editor/implementation/dialogs/paragraph-dialog.ts b/controls/documenteditor/src/document-editor/implementation/dialogs/paragraph-dialog.ts index cda6c2aadf..3bffd94580 100644 --- a/controls/documenteditor/src/document-editor/implementation/dialogs/paragraph-dialog.ts +++ b/controls/documenteditor/src/document-editor/implementation/dialogs/paragraph-dialog.ts @@ -803,6 +803,7 @@ export class ParagraphDialog { paraFormat.firstLineIndent = Math.abs(this.firstLineIndent); if (this.special.index === 2) { paraFormat.firstLineIndent = -paraFormat.firstLineIndent; + paraFormat.leftIndent = this.leftIndentIn.value + this.byIn.value; } } if (!isNullOrUndefined(this.bidi)) { diff --git a/controls/documenteditor/src/document-editor/implementation/dialogs/spellCheck-dialog.ts b/controls/documenteditor/src/document-editor/implementation/dialogs/spellCheck-dialog.ts index ce40e342cd..50613fa25e 100644 --- a/controls/documenteditor/src/document-editor/implementation/dialogs/spellCheck-dialog.ts +++ b/controls/documenteditor/src/document-editor/implementation/dialogs/spellCheck-dialog.ts @@ -5,7 +5,7 @@ import { Button } from '@syncfusion/ej2-buttons'; import { ListView, SelectEventArgs } from '@syncfusion/ej2-lists'; import { ElementBox, TextElementBox, ErrorTextElementBox } from '../viewer/page'; import { DocumentEditor } from '../../document-editor'; -import { HelperMethods, MatchResults } from '../editor/editor-helper'; +import { MatchResults } from '../editor/editor-helper'; import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups'; import { DocumentHelper } from '../viewer'; /** @@ -196,7 +196,7 @@ export class SpellCheckDialog { this.handleRetrievedSuggestion(error, suggestions); }); } else { - error = HelperMethods.manageSpecialCharacters(error, undefined, true); + error = this.parent.spellChecker.manageSpecialCharacters(error, undefined, true); suggestions = this.parent.spellChecker.errorSuggestions.containsKey(error) ? this.parent.spellChecker.errorSuggestions.get(error) : []; this.handleRetrievedSuggestion(error, suggestions); @@ -205,7 +205,7 @@ export class SpellCheckDialog { private handleRetrievedSuggestion(error: string, suggestions: string[]): void { - error = HelperMethods.manageSpecialCharacters(error, undefined, true); + error = this.parent.spellChecker.manageSpecialCharacters(error, undefined, true); this.initSpellCheckDialog(this.localValue, error, suggestions); if (this.documentHelper.selection.caret.style.display !== 'none') { this.documentHelper.selection.caret.style.display = 'none'; diff --git a/controls/documenteditor/src/document-editor/implementation/dialogs/style-dialog.ts b/controls/documenteditor/src/document-editor/implementation/dialogs/style-dialog.ts index ec92976895..abbb0dd9a0 100644 --- a/controls/documenteditor/src/document-editor/implementation/dialogs/style-dialog.ts +++ b/controls/documenteditor/src/document-editor/implementation/dialogs/style-dialog.ts @@ -1,4 +1,4 @@ -import { createElement, isNullOrUndefined, L10n } from '@syncfusion/ej2-base'; +import { createElement, isNullOrUndefined, L10n, initializeCSPTemplate } from '@syncfusion/ej2-base'; import { DropDownList, ComboBox, SelectEventArgs, ChangeEventArgs } from '@syncfusion/ej2-dropdowns'; import { RadioButton, Button } from '@syncfusion/ej2-buttons'; import { WStyle, WCharacterStyle, WParagraphStyle } from '../../implementation/format/style'; @@ -205,19 +205,19 @@ export class StyleDialog { items: items, cssClass: 'e-de-style-format-dropdwn', enableRtl: isRtl, beforeItemRender: (args: MenuEventArgs) => { if (this.styleType.value === localValue.getConstant('Character')) { - if (args.item.text === localValue.getConstant('Paragraph')) { + if (args.item.id === "style_paragraph") { args.element.classList.add('e-disabled'); } - if (args.item.text === 'Numbering') { + if (args.item.id === 'style_numbering') { args.element.classList.add('e-disabled'); } } else { - if (args.item.text === localValue.getConstant('Paragraph')) { + if (args.item.id === "style_paragraph") { args.element.classList.remove('e-disabled'); } - if (args.item.text === 'Numbering') { + if (args.item.id === 'style_numbering') { args.element.classList.remove('e-disabled'); } } @@ -249,8 +249,10 @@ export class StyleDialog { id: this.target.id + '_fontName', }); let fontStyle: { [key: string]: Object; }[]; - let isStringTemplate: boolean = true; - let itemTemplate: string = '${FontName}'; + let isStringTemplate: boolean = true; + let itemTemplate: string | Function = initializeCSPTemplate( + function (data: any): string { return `${data.FontName}`; } + ); parentDiv.appendChild(fontFamilyElement); this.fontFamily = new ComboBox({ dataSource: fontStyle, query: new Query().select(['FontName']), fields: { text: 'FontName', value: 'value' }, @@ -539,7 +541,7 @@ export class StyleDialog { this.styleParagraph.dataSource = styles; this.styleParagraph.index = null; this.styleParagraph.index = styles.indexOf(typedName); - this.styleParagraph.dataBind(); + // this.styleParagraph.dataBind(); } } /** @@ -695,6 +697,9 @@ export class StyleDialog { } else { let tmpStyle: any = this.getTypeValue() === 'Paragraph' ? new WParagraphStyle() : new WCharacterStyle; tmpStyle.copyStyle(this.style); + if (this.getTypeValue() === 'Character') { + (tmpStyle as WCharacterStyle).characterFormat.copyFormat(this.characterFormat); + } let basedOn: any = this.documentHelper.styles.findByName(this.documentHelper.owner.stylesDialogModule.getStyleName(this.styleBasedOn.value as string)) as WStyle; if (this.styleType.value === 'Paragraph' || this.styleType.value === 'Linked Style') { if (styleName === this.documentHelper.owner.stylesDialogModule.getStyleName(this.styleParagraph.value as string)) { @@ -810,6 +815,9 @@ export class StyleDialog { if (!isNullOrUndefined(paragraphFOrmat)) { this.paragraphFormat = paragraphFOrmat; } + if (isNullOrUndefined(this.paragraphFormat)) { + return; + } if (this.paragraphFormat.textAlignment === 'Left') { if (!this.leftAlign.classList.contains('e-active')) { this.leftAlign.classList.add('e-active'); @@ -959,8 +967,8 @@ export class StyleDialog { } else { this.styleType.enabled = true; } - this.styleBasedOn.dataBind(); - this.styleParagraph.dataBind(); + // this.styleBasedOn.dataBind(); + // this.styleParagraph.dataBind(); } private getStyle(styleName: string): WStyle { diff --git a/controls/documenteditor/src/document-editor/implementation/dialogs/styles-dialog.ts b/controls/documenteditor/src/document-editor/implementation/dialogs/styles-dialog.ts index d301bf0168..e75d560eac 100644 --- a/controls/documenteditor/src/document-editor/implementation/dialogs/styles-dialog.ts +++ b/controls/documenteditor/src/document-editor/implementation/dialogs/styles-dialog.ts @@ -2,6 +2,7 @@ import { ListView, SelectEventArgs } from '@syncfusion/ej2-lists'; import { Button } from '@syncfusion/ej2-buttons'; import { createElement, L10n } from '@syncfusion/ej2-base'; import { DocumentHelper } from '../viewer'; +import { StyleType } from '../../base'; /** * The Styles dialog is used to create or modify styles. @@ -33,7 +34,7 @@ export class StylesDialog { * @param {boolean} isRtl - Specifies the is rtl. * @returns {void} */ - public initStylesDialog(localValue: L10n, styles: string[], isRtl?: boolean): void { + public initStylesDialog(localValue: L10n, styles: {[key: string]: string}[], isRtl?: boolean): void { const id: string = this.documentHelper.owner.containerId + '_insert_styles'; this.target = createElement('div', { id: id, className: 'e-de-styles' }); const headerValue: string = localValue.getConstant('Styles'); @@ -54,7 +55,9 @@ export class StylesDialog { this.listviewInstance = new ListView({ dataSource: styles, - cssClass: 'e-styles-listview' + cssClass: 'e-styles-listview', + fields: { text: 'StyleName', iconCss: 'IconClass' }, + showIcon: true }); this.listviewInstance.appendTo(listviewDiv); @@ -92,7 +95,10 @@ export class StylesDialog { public show(): void { const localValue: L10n = new L10n('documenteditor', this.documentHelper.owner.defaultLocale); localValue.setLocale(this.documentHelper.owner.locale); - const styles: string[] = this.updateStyleNames(); + let paraStyles: {[key: string]: string}[] = this.updateStyleNames('Paragraph').filter(obj => (obj as any).Type == "Paragraph"); + let linkedStyles: {[key: string]: string}[] = this.updateStyleNames('Paragraph').filter(obj => (obj as any).Type == "Linked"); + let charStyles: {[key: string]: string}[] = this.updateStyleNames('Character').filter(obj => (obj as any).Type == "Character"); + let styles: {[key: string]: string}[] = paraStyles.concat(linkedStyles, charStyles); this.localValue = localValue; this.initStylesDialog(localValue, styles, this.documentHelper.owner.enableRtl); this.documentHelper.dialog.content = this.target; @@ -108,20 +114,26 @@ export class StylesDialog { this.documentHelper.dialog.dataBind(); this.documentHelper.dialog.show(); } - private updateStyleNames(): string[] { + private updateStyleNames(type: StyleType): {[key: string]: string}[] { const localValue: L10n = new L10n('documenteditor', this.documentHelper.owner.defaultLocale); localValue.setLocale(this.documentHelper.owner.locale); - const collection: string[] = this.documentHelper.owner.documentHelper.styles.getStyleNames('Paragraph'); - const styleNames: string[] = ['Normal', 'Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6']; - const defaultStyleNames: string[] = this.defaultStyleName(styleNames); - const filteredList: string[] = collection.concat(defaultStyleNames).filter((v: string, i: number, a: string[]) => a.indexOf(v) === i); - let finalList: string[] = []; - for (let i: number = 0; i < filteredList.length; i++) { - let styleName : string = localValue.getConstant(filteredList[parseInt(i.toString(), 10)]); + const collection: object[] = this.documentHelper.owner.documentHelper.styles.getStyles(type); + const paraIcon: string = 'e-de-listview-icon e-de-e-paragraph-style-mark e-icons'; + const charIcon: string = 'e-de-listview-icon e-de-e-character-style-mark e-icons'; + const linkedIcon: string = 'e-de-listview-icon e-de-e-linked-style-mark e-icons'; + let finalList: {[key: string]: string}[] = []; + for (let i: number = 0; i < collection.length; i++) { + let styleName : string = localValue.getConstant((collection[parseInt(i.toString(), 10)] as any).name); if(styleName === '') { - styleName = filteredList[parseInt(i.toString(), 10)]; + styleName = (collection[parseInt(i.toString(), 10)] as any).name; + } + if ((collection[parseInt(i.toString(), 10)] as any).type == 'Paragraph') { + finalList.push({ StyleName: styleName, IconClass: paraIcon, Type: (collection[parseInt(i.toString(), 10)] as any).type }); + } else if ((collection[parseInt(i.toString(), 10)] as any).type == 'Character'){ + finalList.push({ StyleName: styleName, IconClass: charIcon, Type: (collection[parseInt(i.toString(), 10)] as any).type }); + } else { + finalList.push({ StyleName: styleName, IconClass: linkedIcon, Type: (collection[parseInt(i.toString(), 10)] as any).type }); } - finalList.push(styleName); } return finalList; } diff --git a/controls/documenteditor/src/document-editor/implementation/dialogs/table-dialog.ts b/controls/documenteditor/src/document-editor/implementation/dialogs/table-dialog.ts index 3656871bf0..58b05b32af 100644 --- a/controls/documenteditor/src/document-editor/implementation/dialogs/table-dialog.ts +++ b/controls/documenteditor/src/document-editor/implementation/dialogs/table-dialog.ts @@ -125,19 +125,17 @@ export class TableDialog { * @returns {void} */ public onInsertTableClick = (): void => { - if (this.columnValueTexBox.value < 1 || this.columnValueTexBox.value > 63) { - DialogUtility.alert(this.localeValue.getConstant('Number of columns must be between 1 and 63.')); + if (this.columnValueTexBox.value < 1 || this.columnValueTexBox.value > this.documentHelper.owner.documentEditorSettings.maximumColumns) { + let columnAlertPopup: string = this.localeValue.getConstant('Number of columns must be between') + ' 1 ' + this.localeValue.getConstant('and') + ' ' + this.documentHelper.owner.documentEditorSettings.maximumColumns.toString(); + DialogUtility.alert(columnAlertPopup).enableRtl = this.documentHelper.owner.enableRtl; return; } if (this.rowValueTextBox.value < 1 || this.rowValueTextBox.value > this.documentHelper.owner.documentEditorSettings.maximumRows) { - if(this.documentHelper.owner.locale == 'en-US') { - DialogUtility.alert('Number of rows must be between 1 and ' + this.documentHelper.owner.documentEditorSettings.maximumRows + '.'); - } else { - DialogUtility.alert(this.localeValue.getConstant('Number of rows must be between 1 and 32767.')); - } + let rowAlertPopup: string = this.localeValue.getConstant('Number of rows must be between') + ' 1 ' + this.localeValue.getConstant('and') + ' ' + this.documentHelper.owner.documentEditorSettings.maximumColumns.toString(); + DialogUtility.alert(rowAlertPopup).enableRtl = this.documentHelper.owner.enableRtl; return; } - if (this.rowValueTextBox.value <= this.documentHelper.owner.documentEditorSettings.maximumRows && this.columnValueTexBox.value <= 63) { + if (this.rowValueTextBox.value <= this.documentHelper.owner.documentEditorSettings.maximumRows && this.columnValueTexBox.value <= this.documentHelper.owner.documentEditorSettings.maximumColumns) { const rowCount: number = this.rowValueTextBox.value; const columnCount: number = this.columnValueTexBox.value; if (!(isNullOrUndefined(rowCount) && isNullOrUndefined(columnCount))) { 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 a183003811..e80077ed4d 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 @@ -334,7 +334,7 @@ export class BaseHistoryInfo { isRemoveContent = this.lastElementRevision ? false : isRemoveContent; this.revertModifiedNodes(deletedNodes, isRedoAction, isForwardSelection ? start : end, start === end); if (isRemoveContent) { - this.removeContent(insertTextPosition, endTextPosition); + this.removeContent(insertTextPosition, endTextPosition, true); } //this.owner.editorModule.reLayout(this.documentHelper.selection); } @@ -386,7 +386,7 @@ export class BaseHistoryInfo { } } } - private removeContent(insertTextPosition: TextPosition, endTextPosition: TextPosition): void { + private removeContent(insertTextPosition: TextPosition, endTextPosition: TextPosition, skipDeletecell?: boolean): void { //If the base parent of the insert text position and end text position is null //then the paragraphs already removed. //Example scenario: In table editing that is delete cells operation @@ -415,7 +415,7 @@ export class BaseHistoryInfo { if (this.action === 'BackSpace' || this.action === 'Uppercase' || this.action === 'RemoveRowTrack') { isDelete = true; } - this.owner.editorModule.deleteSelectedContents(this.owner.selection, isDelete); + this.owner.editorModule.deleteSelectedContents(this.owner.selection, isDelete, skipDeletecell); } } public updateEndRevisionInfo(): void { @@ -690,7 +690,7 @@ export class BaseHistoryInfo { this.owner.documentHelper.headersFooters.splice(node.sectionIndex, 0, node.removedHeaderFooters[0]); node.removedHeaderFooters = undefined; } - this.owner.editorModule.insertSection(this.owner.selection, false, true, undefined, node.sectionFormat); + this.owner.editorModule.insertSection(this.owner.selection, false, true, undefined, undefined, node.sectionFormat); } else if (typeof (node) === 'string' && this.action === 'AcceptTOC') { let insertIndex: string = this.selectionStart; let widget: BlockWidget = this.owner.editorModule.getBlock({ index: insertIndex }).node as BlockWidget; @@ -710,6 +710,7 @@ export class BaseHistoryInfo { item.revisions.splice(revisionIndex, 1); let rangeIndex: number = currentRevision.range.indexOf(item); currentRevision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } if (currentRevision.range.length === 0) { this.owner.revisions.remove(currentRevision); @@ -751,6 +752,7 @@ export class BaseHistoryInfo { item.revisions.splice(revisionIndex, 1); let rangeIndex: number = currentRevision.range.indexOf(item); currentRevision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } if (currentRevision.range.length === 0) { this.owner.revisions.remove(currentRevision); @@ -1034,6 +1036,9 @@ export class BaseHistoryInfo { } this.owner.editor.setPreviousBlockToLayout(); this.owner.editorModule.updateSelectionParagraphFormatting(property, undefined, false); + } else if (this.action === 'LinkToPrevious' && this.modifiedProperties[0] instanceof WSectionFormat) { + let sectionIndex: number = parseInt(this.selectionStart.split(';')[0]); + this.owner.editorModule.updateHeaderFooters(property, undefined, sectionIndex, (this.modifiedProperties[0] as WSectionFormat).removedHeaderFooters[0]); } else if (this.modifiedProperties[0] instanceof WSectionFormat) { this.owner.editorModule.updateSectionFormat(property, undefined); } else if (this.action === 'RestartNumbering') { @@ -1209,6 +1214,8 @@ export class BaseHistoryInfo { return 'bidi'; case 'ContextualSpacing': return 'contextualSpacing'; + case 'LinkToPrevious': + return 'linkToPrevious'; case 'LeftBorder': case 'TopBorder': case 'RightBorder': diff --git a/controls/documenteditor/src/document-editor/implementation/editor/editor-helper.ts b/controls/documenteditor/src/document-editor/implementation/editor/editor-helper.ts index ae7319035a..6620f98797 100644 --- a/controls/documenteditor/src/document-editor/implementation/editor/editor-helper.ts +++ b/controls/documenteditor/src/document-editor/implementation/editor/editor-helper.ts @@ -2,16 +2,22 @@ import { isNullOrUndefined, NumberFormatOptions, Internationalization, DateForma import { ZipArchive, ZipArchiveItem } from '@syncfusion/ej2-compression'; import { LineWidget, ElementBox, BodyWidget, ParagraphWidget, TextElementBox, BlockWidget } from '../viewer/page'; import { WCharacterFormat, WCellFormat, TextPosition, TextSearchResults } from '../index'; -import { HighlightColor, TextFormFieldType, CheckBoxSizeType, RevisionType, CollaborativeEditingAction, CompatibilityMode, BaselineAlignment, Underline, Strikethrough, BiDirectionalOverride } from '../../base/types'; +import { HighlightColor, TextFormFieldType, CheckBoxSizeType, RevisionType, CollaborativeEditingAction, CompatibilityMode, BaselineAlignment, Underline, Strikethrough, BiDirectionalOverride, BreakClearType, LineStyle, TextAlignment, LineSpacingType, OutlineLevel } from '../../base/types'; import { Widget, FieldElementBox, CommentCharacterElementBox } from '../viewer/page'; import { Dictionary } from '../..'; -import { WBorder } from '../format'; +import { WBorder, WBorders, WParagraphFormat } from '../format'; import { boldProperty, italicProperty, fontSizeProperty, fontFamilyProperty, underlineProperty, strikethroughProperty, baselineAlignmentProperty, highlightColorProperty, fontColorProperty, styleNameProperty, bidiProperty, bdoProperty, boldBidiProperty, italicBidiProperty, fontSizeBidiProperty, fontFamilyBidiProperty, allCapsProperty, localeIdBidiProperty, complexScriptProperty, fontFamilyAsciiProperty, - fontFamilyFarEastProperty, fontFamilyNonFarEastProperty + characterSpacingProperty, scalingProperty, fontFamilyFarEastProperty, fontFamilyNonFarEastProperty, bordersProperty, leftIndentProperty, + rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, beforeSpacingProperty, + afterSpacingProperty, spaceBeforeAutoProperty, spaceAfterAutoProperty, lineSpacingProperty, + lineSpacingTypeProperty, outlineLevelProperty, listFormatProperty, tabsProperty, + keepLinesTogetherProperty, keepWithNextProperty, contextualSpacingProperty, widowControlProperty, + topProperty, leftProperty, rightProperty, bottomProperty, horizontalProperty, verticalProperty, + colorProperty, hasNoneStyleProperty, lineStyleProperty, lineWidthProperty, shadowProperty, spaceProperty } from '../../index'; /** @@ -59,52 +65,6 @@ export class HelperMethods { text = text.replace("[#@!~\\$%^&\\*\\(\\)\\-_\\+\\.=\\{\\}\\[\\]:;,<>\\?'\\\\\"\\“\\”\\//0123456789]+$", ''); return text; } - /** - * Method to append/remove special characters - * - * @private - */ - /* eslint-disable */ - public static manageSpecialCharacters(exactText: string, replaceText: string, isRemove?: boolean): string { - if (!isNullOrUndefined(exactText)) { - if (isNullOrUndefined(replaceText)) { - replaceText = exactText; - } - - const pattern: RegExp = new RegExp('^[#\\@\\!\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\\”\'\\,\\<\\.\\>\\/\\?\\`\\s\\’]+', 'g'); - let matches: RegExpExecArray[] = []; - let matchInfo: RegExpExecArray; - // eslint-disable no-cond-assign - while (!isNullOrUndefined(matchInfo = pattern.exec(exactText))) { - matches.push(matchInfo); - } - - if (matches.length > 0) { - for (let i: number = 0; i < matches.length; i++) { - /* eslint-disable @typescript-eslint/no-explicit-any */ - const match: any[] = matches[i]; - replaceText = (!isRemove) ? match[0] + replaceText : replaceText.replace(match[0], ''); - } - } - - const endPattern: RegExp = new RegExp('[#\\@\\!\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\\”\'\\,\\<\\.\\>\\/\\?\\s\\`\\’]+$', 'g'); - matches = []; - // eslint-disable no-cond-assign - while (!isNullOrUndefined(matchInfo = endPattern.exec(replaceText))) { - matches.push(matchInfo); - } - - if (matches.length > 0) { - for (let i: number = 0; i < matches.length; i++) { - const match: any = matches[i]; - replaceText = (!isRemove) ? replaceText + match[0] : replaceText.slice(0, match.index); - } - } - } - - return replaceText; - } - /* eslint-enable */ /** * @private * @param text @@ -122,7 +82,7 @@ export class HelperMethods { let spellColl: any = []; for (const str of stringarr) { let spellInfo: any = {}; - spellInfo.Text = this.manageSpecialCharacters(str, undefined, true); + spellInfo.Text = this.replaceSpecialChars(str); spellInfo.HasSpellError = false; spellColl.push(spellInfo); } @@ -141,44 +101,11 @@ export class HelperMethods { zipArchive.open(JSON.stringify(json.sfdt)); let zipItem: ZipArchiveItem = zipArchive.items[0] as ZipArchiveItem; let value: Uint8Array = new Uint8Array(zipItem.data as ArrayBuffer); - let str: string = HelperMethods.utf8ArrayToString(value); + let str: string = new TextDecoder("utf-8").decode(value); json = JSON.parse(str); } return json; } - /* eslint-disable */ - /** - * @private - * Convert the Uint8Array to string. - * @param array - * @returns - */ - public static utf8ArrayToString(array: Uint8Array): string { - let out: string = ''; - let i: number = 0; - let c: number = 0; - let c1: number = 0; - let c2: number = 0; - let c3: number = 0; - while (i < array.length) { - /*eslint-disable*/ - c = array[i]; - if (c < 128) { - out += String.fromCharCode(c); - i++; - } else if (c > 191 && c < 224) { - c2 = array[i + 1]; - out += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); - i += 2; - } else { - c2 = array[i + 1]; - c3 = array[i + 2]; - out += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - i += 3; - } - } - return out; - } /* eslint-enable */ /** * Removes text from specified index in string. @@ -327,6 +254,7 @@ export class HelperMethods { } public static convertPointToPixel(point: number): number { + point = HelperMethods.round(point, 5); const pixel: number = HelperMethods.round((point * 96 / 72), 5); return pixel; } @@ -553,6 +481,185 @@ export class HelperMethods { } } + public static getBreakClearType(breakClearType: BreakClearType): number { + switch (breakClearType) { + case 'None': + return 0; + case 'Left': + return 1; + case 'Right': + return 2; + case 'All': + return 3; + } + } + + /* eslint-disable */ + public static getOutlineLevelEnumValue(outlineLevel: OutlineLevel): number { + switch (outlineLevel) { + case 'BodyText': + return 0; + case 'Level1': + return 1; + case 'Level2': + return 2; + case 'Level3': + return 3; + case 'Level4': + return 4; + case 'Level5': + return 5; + case 'Level6': + return 6; + case 'Level7': + return 7; + case 'Level8': + return 8; + case 'Level9': + return 9; + } + } + + /* eslint-disable */ + public static getTextAlignmentEnumValue(textAlignment: TextAlignment): number { + switch (textAlignment) { + case 'Left': + return 0; + case 'Center': + return 1; + case 'Right': + return 2; + case 'Justify': + return 3; + } + } + + /* eslint-disable */ + public static getLineStyleEnumValue(lineStyle: LineStyle): number { + switch (lineStyle) { + case 'Single': + return 0; + case 'None': + return 1; + case 'Dot': + return 2; + case 'DashSmallGap': + return 3; + case 'DashLargeGap': + return 4; + case 'DashDot': + return 5; + case 'DashDotDot': + return 6; + case 'Double': + return 7; + case 'Triple': + return 8; + case 'ThinThickSmallGap': + return 9; + case 'ThickThinSmallGap': + return 10; + case 'ThinThickThinSmallGap': + return 11; + case 'ThinThickMediumGap': + return 12; + case 'ThickThinMediumGap': + return 13; + case 'ThinThickThinMediumGap': + return 14; + case 'ThinThickLargeGap': + return 15; + case 'ThickThinLargeGap': + return 16; + case 'ThinThickThinLargeGap': + return 17; + case 'SingleWavy': + return 18; + case 'DoubleWavy': + return 19; + case 'DashDotStroked': + return 20; + case 'Emboss3D': + return 21; + case 'Engrave3D': + return 22; + case 'Outset': + return 23; + case 'Inset': + return 24; + case 'Thick': + return 25; + case 'Cleared': + return 26; + } + } + + /* eslint-disable */ + public static getLineSpacingTypeEnumValue(lineSpacing: LineSpacingType): number { + switch (lineSpacing) { + case 'Multiple': + return 0; + case 'AtLeast': + return 1; + case 'Exactly': + return 2; + } + } + + /* eslint-disable */ + public static writeBorder(wBorder: WBorder, keywordIndex: number): any { + let border: any = {}; + border[colorProperty[keywordIndex]] = wBorder.hasValue('color') ? wBorder.color : undefined; + border[hasNoneStyleProperty[keywordIndex]] = wBorder.hasValue('hasNoneStyle') ? HelperMethods.getBoolInfo(wBorder.hasNoneStyle, keywordIndex) : undefined; + border[lineStyleProperty[keywordIndex]] = wBorder.hasValue('lineStyle') ? + keywordIndex == 1 ? this.getLineStyleEnumValue(wBorder.lineStyle) : wBorder.lineStyle : undefined; + border[lineWidthProperty[keywordIndex]] = wBorder.hasValue('lineWidth') ? wBorder.lineWidth : undefined; + border[shadowProperty[keywordIndex]] = wBorder.hasValue('shadow') ? HelperMethods.getBoolInfo(wBorder.shadow, keywordIndex) : undefined; + border[spaceProperty[keywordIndex]] = wBorder.hasValue('space') ? wBorder.space : undefined; + return border; + } + + /* eslint-disable */ + public static writeParagraphBorders(wBorders: WBorders, keywordIndex: number): any { + let borders: any = {}; + borders[topProperty[keywordIndex]] = this.writeBorder(wBorders.getBorder('top'), keywordIndex); + borders[leftProperty[keywordIndex]] = this.writeBorder(wBorders.getBorder('left'), keywordIndex); + borders[rightProperty[keywordIndex]] = this.writeBorder(wBorders.getBorder('right'), keywordIndex); + borders[bottomProperty[keywordIndex]] = this.writeBorder(wBorders.getBorder('bottom'), keywordIndex); + borders[horizontalProperty[keywordIndex]] = this.writeBorder(wBorders.getBorder('horizontal'), keywordIndex); + borders[verticalProperty[keywordIndex]] = this.writeBorder(wBorders.getBorder('vertical'), keywordIndex); + return borders; + } + + /* eslint-disable */ + public static writeParagraphFormat(paragraphFormat: WParagraphFormat, isInline: boolean, format: WParagraphFormat, keywordIndex?: number): void { + keywordIndex = isNullOrUndefined(keywordIndex) ? 0 : keywordIndex; + paragraphFormat[bordersProperty[keywordIndex]] = this.writeParagraphBorders(format.borders, keywordIndex); + paragraphFormat[leftIndentProperty[keywordIndex]] = isInline ? format.leftIndent : format.getValue('leftIndent'); + paragraphFormat[rightIndentProperty[keywordIndex]] = isInline ? format.rightIndent : format.getValue('rightIndent'); + paragraphFormat[firstLineIndentProperty[keywordIndex]] = isInline ? format.firstLineIndent : format.getValue('firstLineIndent'); + paragraphFormat[textAlignmentProperty[keywordIndex]] = isInline ? + keywordIndex == 1 ? this.getTextAlignmentEnumValue(format.textAlignment): format.textAlignment : + keywordIndex == 1 ? this.getTextAlignmentEnumValue(format.getValue('textAlignment') as TextAlignment) : format.getValue('textAlignment') as TextAlignment; + paragraphFormat[beforeSpacingProperty[keywordIndex]] = isInline ? format.beforeSpacing : format.getValue('beforeSpacing'); + paragraphFormat[afterSpacingProperty[keywordIndex]] = isInline ? format.afterSpacing : format.getValue('afterSpacing'); + paragraphFormat[spaceBeforeAutoProperty[keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.spaceBeforeAuto, keywordIndex) : format.getValue('spaceBeforeAuto'); + paragraphFormat[spaceAfterAutoProperty[keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.spaceAfterAuto, keywordIndex) : format.getValue('spaceAfterAuto'); + paragraphFormat[lineSpacingProperty[keywordIndex]] = isInline ? format.lineSpacing : format.getValue('lineSpacing'); + paragraphFormat[lineSpacingTypeProperty[keywordIndex]] = isInline ? + keywordIndex == 1 ? this.getLineSpacingTypeEnumValue(format.lineSpacingType): format.lineSpacingType : + keywordIndex == 1 ? this.getLineSpacingTypeEnumValue(format.getValue('lineSpacingType') as LineSpacingType): format.getValue('lineSpacingType') as LineSpacingType; + paragraphFormat[styleNameProperty[keywordIndex]] = !isNullOrUndefined(format.baseStyle) ? format.baseStyle.name : undefined; + paragraphFormat[outlineLevelProperty[keywordIndex]] = isInline ? + keywordIndex == 1 ? this.getOutlineLevelEnumValue(format.outlineLevel):format.outlineLevel : + keywordIndex == 1 ? this.getOutlineLevelEnumValue(format.getValue('outlineLevel') as OutlineLevel) : format.getValue('outlineLevel') as OutlineLevel; + paragraphFormat[bidiProperty[keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.bidi, keywordIndex) : format.getValue('bidi'); + paragraphFormat[keepLinesTogetherProperty[keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.keepLinesTogether, keywordIndex) : format.getValue('keepLinesTogether'); + paragraphFormat[keepWithNextProperty[keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.keepWithNext, keywordIndex) : format.getValue('keepWithNext'); + paragraphFormat[contextualSpacingProperty[keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.contextualSpacing, keywordIndex) : format.getValue('contextualSpacing'); + paragraphFormat[widowControlProperty[keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.widowControl, keywordIndex) : format.getValue('widowControl'); + } + /* eslint-disable */ public static writeCharacterFormat(characterFormat: any, isInline: boolean, format: WCharacterFormat, keywordIndex?: number): void { keywordIndex = isNullOrUndefined(keywordIndex) ? 0 : keywordIndex; @@ -588,6 +695,8 @@ export class HelperMethods { characterFormat[fontFamilyAsciiProperty[keywordIndex]] = isInline ? this.toWriteInline(format, 'fontFamilyAscii') : format.getValue('fontFamilyAscii'); characterFormat[fontFamilyNonFarEastProperty[keywordIndex]] = isInline ? this.toWriteInline(format, 'fontFamilyNonFarEast') : format.getValue('fontFamilyNonFarEast'); characterFormat[fontFamilyFarEastProperty[keywordIndex]] = isInline ? this.toWriteInline(format, 'fontFamilyFarEast') : format.getValue('fontFamilyFarEast'); + characterFormat[characterSpacingProperty[keywordIndex]] = isInline ? this.toWriteInline(format, 'characterSpacing') : format.getValue('characterSpacing'); + characterFormat[scalingProperty[keywordIndex]] = isInline ? this.toWriteInline(format, 'scaling') : format.getValue('scaling'); if (format.hasValue('fontFamily')) { if (isNullOrUndefined(characterFormat[fontFamilyAsciiProperty[keywordIndex]])) { characterFormat[fontFamilyAsciiProperty[keywordIndex]] = format.fontFamily; diff --git a/controls/documenteditor/src/document-editor/implementation/editor/editor.ts b/controls/documenteditor/src/document-editor/implementation/editor/editor.ts index e545a094a6..5d489a0ba2 100644 --- a/controls/documenteditor/src/document-editor/implementation/editor/editor.ts +++ b/controls/documenteditor/src/document-editor/implementation/editor/editor.ts @@ -29,7 +29,7 @@ import { FieldElementBox } from '../viewer/page'; import { HighlightColor, BaselineAlignment, Strikethrough, Underline, LineSpacingType, TextAlignment, ListLevelPattern, RowPlacement, ColumnPlacement, - FollowCharacterType, HeaderFooterType, TrackChangeEventArgs, protectionTypeChangeEvent, imagesProperty + FollowCharacterType, HeaderFooterType, TrackChangeEventArgs, protectionTypeChangeEvent, imagesProperty, abstractListIdProperty } from '../../base/index'; import { SelectionCharacterFormat } from '../index'; import { Action } from '../../index'; @@ -54,8 +54,9 @@ import { XmlHttpRequestHandler } from '../../base/ajax-helper'; import { CommentActionEventArgs, beforeCommentActionEvent, trackChangeEvent, XmlHttpRequestEventArgs, beforeXmlHttpRequestSend, internalStyleCollectionChange } from '../../base/index'; import { CommentView } from '../comments'; import { SectionBreakType } from '../../base/types'; -import { sectionsProperty, commentsProperty, bidiProperty, revisionsProperty, lastParagraphMarkCopiedProperty, sectionFormatProperty, revisionIdProperty, contextualSpacingProperty, keepWithNextProperty, keepLinesTogetherProperty, widowControlProperty, outlineLevelProperty, numberFormatProperty, startAtProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, cellsProperty, rowsProperty, blocksProperty, listLevelPatternProperty, levelsProperty } from '../../index'; +import { sectionsProperty, commentsProperty, bidiProperty, revisionsProperty, lastParagraphMarkCopiedProperty, sectionFormatProperty, revisionIdProperty, contextualSpacingProperty, keepWithNextProperty, keepLinesTogetherProperty, widowControlProperty, outlineLevelProperty, numberFormatProperty, startAtProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, cellsProperty, rowsProperty, blocksProperty, listLevelPatternProperty, levelsProperty, stylesProperty, nameProperty } from '../../index'; import { SanitizeHtmlHelper } from '@syncfusion/ej2-base'; +import { ChangesSingleView } from '../track-changes/track-changes-pane'; /** * Editor module @@ -82,6 +83,18 @@ export class Editor { private previousBlockToLayout: BlockWidget; private isInsertText: boolean = false; private keywordIndex: number = 0; + /** + * @private + */ + public isFootnoteElementRemoved: boolean = false; + /** + * @private + */ + public isEndnoteElementRemoved: boolean = false; + /** + * @private + */ + public handledEnter: boolean = false; /** * @private */ @@ -271,6 +284,10 @@ export class Editor { * @private */ public isBordersAndShadingDialog: boolean = false; + /** + * @private + */ + public pasteImageIndex: Dictionary = undefined; private get selection(): Selection { if (this.documentHelper) { return this.documentHelper.selection; @@ -1233,6 +1250,7 @@ export class Editor { * @returns {void} */ public fireContentChange(): void { + this.owner.documentHelper.render.commentMarkDictionary.clear(); if (this.selection.isHighlightEditRegion) { if (this.owner.enableLockAndEdit) { this.owner.collaborativeEditingModule.updateLockRegion(); @@ -2376,6 +2394,7 @@ export class Editor { let currentRevision: Revision = revisions[i]; let rangeIndex: number = currentRevision.range.indexOf(revisionElement); currentRevision.range.splice(isEnd ? rangeIndex + 1 : rangeIndex, 0, elementToInclude); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } } /** @@ -2487,6 +2506,7 @@ export class Editor { elementToCombine.revisions.splice(j, 1); prevRevision.range.push(elementToCombine); elementToCombine.revisions.splice(j, 0, prevRevision); + this.owner.trackChangesPane.updateCurrentTrackChanges(prevRevision); } } @@ -2515,6 +2535,7 @@ export class Editor { let rangeIndex: number = currentRevision.range.indexOf(elementToCopy); elementToInclude.revisions.splice(0, 0, currentRevision); currentRevision.range.splice(rangeIndex + ((isSplitElementMerged) ? 2 : 1), 0, elementToInclude); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } } } @@ -2530,6 +2551,7 @@ export class Editor { } let rangeIndex: number = currentRevision.range.indexOf(revisionElement); currentRevision.range.splice((isBegin) ? rangeIndex : rangeIndex + 1, 0, elementToInclude); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } } } @@ -2584,7 +2606,14 @@ export class Editor { // Update selection end let endPosition: TextPosition = new TextPosition(this.owner); endPosition.setPositionForLineWidget(start.currentWidget, start.offset + text.length); - this.selection.selectPosition(isUpdate ? start : endPosition, endPosition); + if (this.owner.enableTrackChanges) { + if (!isUpdate) { + this.selection.start.setPositionInternal(this.selection.end); + } + this.selection.end.updatePhysicalPosition(true); + } else { + this.selection.selectPosition(isUpdate ? start : endPosition, endPosition); + } } /** * Inserts the section break at cursor position with specified section break type. @@ -2614,7 +2643,7 @@ export class Editor { if (sectionBreakType === SectionBreakType.Continuous) { this.insertSection(selection, true, undefined, true); } else { - this.insertSection(selection, true); + this.insertSection(selection, true, undefined, undefined, true); } this.updateEndPosition(); this.reLayout(selection, true); @@ -2790,6 +2819,7 @@ export class Editor { for (let j: number = startIndex; startIndex < revision.range.length; startIndex++) { (revision.range[j] as ElementBox).revisions.splice(i, 1); revision.range.splice(j, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); } } } @@ -2811,6 +2841,7 @@ export class Editor { let currentElement: ElementBox = revision.range[i] as ElementBox; currentElement.revisions.splice(currentElement.revisions.length - 1, 1); revision.range.splice(i, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); } } } @@ -2882,6 +2913,7 @@ export class Editor { currentElement.revisions.splice(currentElement.revisions.length - 1, 1); currentElement.revisions.push(revision); revision.range.splice(index + i, 0, currentElement); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); } } } @@ -2890,6 +2922,7 @@ export class Editor { let range: object[] = revision.range; let index: number = range.indexOf(item); revision.range = range.splice(0, index + 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); return range; } return undefined; @@ -2932,7 +2965,7 @@ export class Editor { let currentRevision: Revision = element.revisions[i]; for (let j: number = 0; j < compare.revisions.length; j++) { - if (currentRevision.author === compare.revisions[i].author && currentRevision.revisionType === compare.revisions[i].revisionType) { + if (currentRevision.author === compare.revisions[j].author && currentRevision.revisionType === compare.revisions[j].revisionType) { return true; } } @@ -3023,7 +3056,7 @@ export class Editor { for (let i: number = 0; i < currentElementRevisions.length; i++) { for (let j: number = 0; j < elementToCombine.length; j++) { let currentRevision: Revision = currentElementRevisions[i]; - let revisionToCombine: Revision = elementToCombine[i]; + let revisionToCombine: Revision = elementToCombine[j]; if (currentRevision.author === revisionToCombine.author && currentRevision.revisionType === revisionToCombine.revisionType) { let rangeLength: number = revisionToCombine.range.length; @@ -3031,7 +3064,9 @@ export class Editor { let item: any = revisionToCombine.range[0]; item.revisions.splice(item.revisions.indexOf(revisionToCombine), 1); revisionToCombine.range.splice(0, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revisionToCombine); currentRevision.range.push(item); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); item.revisions.push(currentRevision); } if (revisionToCombine.range.length === 0) { @@ -3138,6 +3173,7 @@ export class Editor { widget.characterFormat.revisions.push(revision); revision.range.push(widget.characterFormat); } + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); if (!isNullOrUndefined(revision)) { this.updateRevisionCollection(revision); } @@ -3183,6 +3219,13 @@ export class Editor { if (currentStart.isExistBefore(paraIndex)) { isInserted = true; this.owner.revisions.changes.splice(i, 0, revision); + if (!(revision.range[0] instanceof WRowFormat)) { + let currentChangeView: ChangesSingleView = new ChangesSingleView(this.owner, this.owner.trackChangesPane); + this.owner.trackChangesPane.changesInfoDiv.insertBefore(currentChangeView.createSingleChangesDiv(revision), this.owner.trackChangesPane.changesInfoDiv.children[i + 1]); + this.owner.trackChangesPane.revisions.splice(i, 0, revision); + this.owner.trackChangesPane.changes.add(revision, currentChangeView); + this.owner.trackChangesPane.renderedChanges.add(revision, currentChangeView); + } break; } } @@ -3190,6 +3233,13 @@ export class Editor { } if (!isInserted) { this.owner.revisions.changes.push(revision); + if (!(revision.range[0] instanceof WRowFormat)) { + 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(); } @@ -3198,7 +3248,7 @@ export class Editor { * @private * @returns {BodyWidget} */ - public insertSection(selection: Selection, selectFirstBlock: boolean, isUndoing?: boolean, sectionBreakContinuous?: boolean, sectionFormat?: WSectionFormat): BlockWidget { + public insertSection(selection: Selection, selectFirstBlock: boolean, isUndoing?: boolean, sectionBreakContinuous?: boolean, sectionBreakNewPage?:boolean, sectionFormat?: WSectionFormat): BlockWidget { let newSectionFormat: WSectionFormat; if (!isNullOrUndefined(sectionFormat)) { newSectionFormat = sectionFormat; @@ -3250,7 +3300,7 @@ export class Editor { } } //Split body widget - firstBlock = this.splitBodyWidget(lastBlock.bodyWidget, newSectionFormat, lastBlock, sectionBreakContinuous).firstChild as BlockWidget; + firstBlock = this.splitBodyWidget(lastBlock.bodyWidget, newSectionFormat, lastBlock, sectionBreakContinuous, sectionBreakNewPage).firstChild as BlockWidget; if (isUndoing) { this.layoutWholeDocument(true); } @@ -3269,7 +3319,7 @@ export class Editor { /** * @private */ - public splitBodyWidget(bodyWidget: BodyWidget, sectionFormat: WSectionFormat, startBlock: BlockWidget, sectionBreakContinuous?: boolean): BodyWidget { + public splitBodyWidget(bodyWidget: BodyWidget, sectionFormat: WSectionFormat, startBlock: BlockWidget, sectionBreakContinuous?: boolean, sectionBreakNewPage?: boolean): BodyWidget { //let sectionIndex: number; //Move blocks after the start block to next body widget let newBodyWidget: BodyWidget = this.documentHelper.layout.moveBlocksToNextPage(startBlock, true, undefined, sectionBreakContinuous); @@ -3305,6 +3355,11 @@ export class Editor { this.viewer.owner.parser.parseSectionFormat(0, bodyWidget.sectionFormat, newBodyWidget.sectionFormat); newBodyWidget.sectionFormat.breakCode = 'NoBreak'; } + if (sectionBreakNewPage) { + newBodyWidget.sectionFormat = new WSectionFormat(newBodyWidget); + this.viewer.owner.parser.parseSectionFormat(0, bodyWidget.sectionFormat, newBodyWidget.sectionFormat); + newBodyWidget.sectionFormat.breakCode = 'NewPage'; + } this.updateSectionIndex(newBodyWidget.sectionFormat, newBodyWidget, true); if (newBodyWidget.sectionFormat.numberOfColumns > 1) { this.updateColumnIndex(newBodyWidget, false); @@ -3443,6 +3498,9 @@ export class Editor { } } + if (convertList && listLevelPattern === 'Bullet' && inline.text === '- ' && (!isNullOrUndefined(inline.paragraph.previousWidget) && !(((inline.paragraph.previousWidget as ParagraphWidget).firstChild as LineWidget).children[0] instanceof ListTextElementBox))) { + convertList = false; + } if (convertList) { this.initComplexHistory('AutoList'); let paragraph: ParagraphWidget = inline.paragraph as ParagraphWidget; @@ -3659,6 +3717,10 @@ export class Editor { public insertTextInline(element: ElementBox, selection: Selection, text: string, index: number, skipReLayout?: boolean): void { if (element instanceof TextElementBox) { element.text = HelperMethods.insert(element.text, index, text); + if (this.owner.enableTrackChanges) { + let revision = element.revisions[0]; + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); + } let paragraph: ParagraphWidget = (element.line as LineWidget).paragraph; let lineIndex: number = paragraph.childWidgets.indexOf(element.line); let elementIndex: number = element.line.children.indexOf(element); @@ -3906,6 +3968,7 @@ export class Editor { private createHyperlinkElement(url: string, startPosition: TextPosition, endPosition: TextPosition, format: WCharacterFormat): FieldElementBox { let selection: Selection = this.selection; this.documentHelper.layout.allowLayout = false; + this.documentHelper.layout.isReplaceAll = true; this.appylingHyperlinkFormat(selection); //this.documentHelper.layout.allowLayout = true; // Adds the field end at the URL text end position. @@ -3924,6 +3987,7 @@ export class Editor { let lineIndex: number = selection.start.paragraph.childWidgets.indexOf(begin.line); let index: number = begin.line.children.indexOf(begin); fieldEnd.linkFieldCharacter(this.documentHelper); + this.documentHelper.layout.isReplaceAll = false; this.documentHelper.layout.allowLayout = true; this.documentHelper.layout.reLayoutParagraph(selection.start.paragraph, lineIndex, index); return fieldEnd; @@ -3959,6 +4023,7 @@ export class Editor { let rangeIndex: number = currentRevision.range.indexOf(inline); if (rangeIndex >= 0) { currentRevision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } if (currentRevision.range.length === 0 && removeCollection) { this.owner.revisions.remove(currentRevision); @@ -3979,6 +4044,7 @@ export class Editor { let rangeLength: number = currentRevision.range.length; for (let rangeIndex: number = 0; rangeIndex < rangeLength; rangeIndex++) { currentRevision.range.splice(0, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } if (currentRevision.range.length === 0) { this.owner.revisions.remove(currentRevision); @@ -4515,7 +4581,7 @@ export class Editor { let image: HTMLImageElement = document.createElement('img'); let editor: Editor = this; image.addEventListener('load', function (): void { - editor.insertImage(data, this.width, this.height); + editor.insertImage(data, this.width, this.height,this.alt); }); image.src = data; } @@ -4616,10 +4682,10 @@ export class Editor { return 0; } private checkSameLevelFormat(lstLevelNo: number, abstractList: any, list: WList): boolean { - return abstractList[levelsProperty[this.keywordIndex]][lstLevelNo][listLevelPatternProperty[this.keywordIndex]] === list[abstractListsProperty[this.keywordIndex]][levelsProperty[this.keywordIndex]][lstLevelNo][listLevelPatternProperty[this.keywordIndex]] - && abstractList[levelsProperty[this.keywordIndex]][lstLevelNo][numberFormatProperty[this.keywordIndex]] === list[abstractListsProperty[this.keywordIndex]][levelsProperty[this.keywordIndex]][lstLevelNo][numberFormatProperty[this.keywordIndex]] + return abstractList[levelsProperty[this.keywordIndex]][lstLevelNo][listLevelPatternProperty[this.keywordIndex]] === list.abstractList.levels[lstLevelNo].listLevelPattern + && abstractList[levelsProperty[this.keywordIndex]][lstLevelNo][numberFormatProperty[this.keywordIndex]] === list.abstractList.levels[lstLevelNo].numberFormat && (abstractList[levelsProperty[this.keywordIndex]][lstLevelNo][listLevelPatternProperty[this.keywordIndex]] === (this.keywordIndex == 1 ? 10 : 'Bullet') - || abstractList[levelsProperty[this.keywordIndex]][lstLevelNo][startAtProperty[this.keywordIndex]] === list[abstractListsProperty[this.keywordIndex]][levelsProperty[this.keywordIndex]][lstLevelNo][startAtProperty[this.keywordIndex]]); + || abstractList[levelsProperty[this.keywordIndex]][lstLevelNo][startAtProperty[this.keywordIndex]] === list.abstractList.levels[lstLevelNo].startAt); } private listLevelPatternInCollection(lstLevelNo: number, listLevel: any): WList { return this.documentHelper.lists.filter((list: WList) => { @@ -4749,35 +4815,35 @@ export class Editor { private updatePasteContent(pasteContent: any, sectionId: number): void { let uniqueListId: number = this.getUniqueListOrAbstractListId(true); - if (pasteContent[listsProperty[this.keywordIndex]].filter((obj: any): any => { return obj.listId === uniqueListId; }).length > 0) { - let sortedPasteList: any[] = pasteContent.lists.slice().sort((a: any, b: any) => { - return a.listId - b.listId; + if (pasteContent[listsProperty[this.keywordIndex]].filter((obj: any): any => { return obj[listIdProperty[this.keywordIndex]] === uniqueListId; }).length > 0) { + let sortedPasteList: any[] = pasteContent[listsProperty[this.keywordIndex]].slice().sort((a: any, b: any) => { + return a[listIdProperty[this.keywordIndex]] - b[listIdProperty[this.keywordIndex]]; }); - uniqueListId = sortedPasteList[sortedPasteList.length - 1].listId + 1; + uniqueListId = sortedPasteList[sortedPasteList.length - 1][listIdProperty[this.keywordIndex]] + 1; } let uniqueAbsLstId: number = this.getUniqueListOrAbstractListId(false); if (pasteContent[abstractListsProperty[this.keywordIndex]].filter((obj: any): any => { - return obj.abstractListId === uniqueAbsLstId; + return obj[abstractListIdProperty[this.keywordIndex]] === uniqueAbsLstId; }).length > 0) { let sortedPasteAbsList: any[] = pasteContent[abstractListsProperty[this.keywordIndex]].slice().sort((a: any, b: any) => { - return a.abstractListId - b.abstractListId; + return a[abstractListIdProperty[this.keywordIndex]] - b[abstractListIdProperty[this.keywordIndex]]; }); - uniqueAbsLstId = sortedPasteAbsList[sortedPasteAbsList.length - 1].abstractListId + 1; + uniqueAbsLstId = sortedPasteAbsList[sortedPasteAbsList.length - 1][abstractListIdProperty[this.keywordIndex]] + 1; } for (let k: number = 0; k < pasteContent[listsProperty[this.keywordIndex]].length; k++) { let list: WList = pasteContent[listsProperty[this.keywordIndex]][k]; - let abstractList: any = pasteContent[abstractListsProperty[this.keywordIndex]].filter((obj: WAbstractList) => { - return obj.abstractListId === list.abstractListId; + let abstractList: any = pasteContent[abstractListsProperty[this.keywordIndex]].filter((obj: any) => { + return obj[abstractListIdProperty[this.keywordIndex]] === list[abstractListIdProperty[this.keywordIndex]]; })[0]; - let lstDup: WList[] = this.documentHelper.lists.filter((obj: any) => { - return obj.listId === list.listId; + let lstDup: WList[] = this.documentHelper.lists.filter((obj: WList) => { + return obj.listId === list[listIdProperty[this.keywordIndex]]; }); if (!isNullOrUndefined(abstractList)) { - let isUpdate: boolean = this.updateListIdForBlocks(pasteContent[sectionsProperty[this.keywordIndex]][sectionId][blocksProperty[this.keywordIndex]], abstractList, lstDup[0], list.listId, uniqueListId); + let isUpdate: boolean = this.updateListIdForBlocks(pasteContent[sectionsProperty[this.keywordIndex]][sectionId][blocksProperty[this.keywordIndex]], abstractList, lstDup[0], list[listIdProperty[this.keywordIndex]], uniqueListId); if (isUpdate) { - abstractList.abstractListId = uniqueAbsLstId; - list.listId = uniqueListId; - list.abstractListId = uniqueAbsLstId; + abstractList[abstractListIdProperty[this.keywordIndex]] = uniqueAbsLstId; + list[listIdProperty[this.keywordIndex]] = uniqueListId; + list[abstractListIdProperty[this.keywordIndex]] = uniqueAbsLstId; uniqueListId++; uniqueAbsLstId++; } else { @@ -4934,7 +5000,16 @@ export class Editor { } else { widgets.push(bodyWidget); } - parser.parseBody(pasteContent[sectionsProperty[this.keywordIndex]][i][blocksProperty[this.keywordIndex]], bodyWidget.childWidgets as BlockWidget[]); + if (isPaste && !isNullOrUndefined(pasteContent[stylesProperty[this.keywordIndex]])) { + for (var j = 0; j < pasteContent[stylesProperty[this.keywordIndex]].length; j++) { + let styleName: string = pasteContent[stylesProperty[this.keywordIndex]][j][nameProperty[this.keywordIndex]]; + let style: WStyle = this.documentHelper.styles.findByName(styleName) as WStyle; + if (isNullOrUndefined(style)) { + parser.parseStyle(pasteContent, pasteContent[stylesProperty[this.keywordIndex]][j], this.documentHelper.styles) + } + } + } + parser.parseBody(pasteContent[sectionsProperty[this.keywordIndex]][i][blocksProperty[this.keywordIndex]], bodyWidget.childWidgets as BlockWidget[], undefined, undefined, undefined, pasteContent[stylesProperty[this.keywordIndex]]); if (pasteContent[lastParagraphMarkCopiedProperty[this.keywordIndex]] && this.selection.start.paragraph.isEmpty() && this.documentHelper.pages.length == 1 && this.documentHelper.pages[0].bodyWidgets[0].childWidgets.length == 1) { parser.parseSectionFormat(this.keywordIndex, pasteContent[sectionsProperty[this.keywordIndex]][i][sectionFormatProperty[this.keywordIndex]], bodyWidget.sectionFormat); } @@ -5104,12 +5179,28 @@ export class Editor { } } if (!isNullOrUndefined(content[imagesProperty[this.keywordIndex]])) { - this.documentHelper.owner.parser.parseImages(content[imagesProperty[this.keywordIndex]]); + let images = content[imagesProperty[this.keywordIndex]]; + if(this.documentHelper.images.length > 0) { + this.pasteImageIndex = new Dictionary(); + let newImages = {}; + for(let img in images) { + let newIndex = this.documentHelper.images.length + parseInt(img); + newImages[newIndex] = images[img]; + this.pasteImageIndex.add(img, newIndex.toString()); + } + content[imagesProperty[this.keywordIndex]] = newImages; + images = newImages; + } + this.documentHelper.owner.parser.parseImages(images); } this.pasteContentsInternal(this.getBlocks(content, true), true, currentFormat); if (content[commentsProperty[this.keywordIndex]] && content[commentsProperty[this.keywordIndex]].length > 0) { this.documentHelper.layout.layoutComments(this.documentHelper.comments); } + if(!isNullOrUndefined(this.pasteImageIndex)) { + this.pasteImageIndex.destroy(); + } + this.pasteImageIndex = undefined; this.isInsertField = false; } private pasteContentsInternal(widgets: BodyWidget[], isPaste: boolean, currentFormat?: WParagraphFormat): void { @@ -5998,6 +6089,10 @@ export class Editor { indexInInline = inlineObj.index; this.insertElementInternal(curInline, element, indexInInline, revisionType, true); } + let revision = element.revisions[0]; + if (!isNullOrUndefined(revision)) { + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); + } this.setPositionParagraph(paragraphInfo.paragraph, paragraphInfo.offset + length, true); } private insertElement(element: ElementBox[], paragraphFormat?: WParagraphFormat): void { @@ -6069,7 +6164,7 @@ export class Editor { curInline = element[i]; insertIndex++; } - if (paragraphFormat && (isNullOrUndefined(paragraph.paragraphFormat.listFormat.list) || + if ((!this.isPaste) && paragraphFormat && (isNullOrUndefined(paragraph.paragraphFormat.listFormat.list) || (!isNullOrUndefined(paragraph.paragraphFormat.listFormat) && paragraph.paragraphFormat.listFormat.listId === -1))) { paragraph.paragraphFormat.copyFormat(paragraphFormat); } @@ -6278,6 +6373,7 @@ export class Editor { } else { revisionToInclude.range.splice((isEnd) ? revisionToInclude.range.length : 0, 0, insertElement); } + this.owner.trackChangesPane.updateCurrentTrackChanges(revisionToInclude); this.updateRevisionCollection(revisionToInclude); } } @@ -6384,21 +6480,23 @@ export class Editor { * @param {string} imageString Base64 string, web URL or file URL. * @param {number} width Specify the image width. * @param {number} height Specify the image height. + * @param {string} alternateText Specify the image alternateText. * @returns {void} */ - public insertImage(imageString: string, width?: number, height?: number): void { - this.insertImageInternal(imageString, false, width, height); + public insertImage(imageString: string, width?: number, height?: number,alternateText?: string): void { + this.insertImageInternal(imageString, false, width, height,alternateText); } /** - * Inserts the image with specified size at cursor position in the Document editor. + * Inserts an image with a specified size at the cursor position in the DocumentEditor component. * - * @param {string} imageString Base64 string, web URL or file URL. - * @param {number} width Specify the image width. - * @param {number} height Specify the image height. - * @returns {Promise} Returns a Promise which is resolved when image has been inserted, or rejected if for any reason image cannot be inserted. + * @param {string} imageString - The Base64 string, web URL, or file URL of the image to be inserted. + * @param {number} width - The width of the image. Optional parameter, if not specified, the original width of the image will be used. + * @param {number} height - The height of the image. Optional parameter, if not specified, the original height of the image will be used. + * @param {string} alternateText - The alternate text of the image. Optional parameter, if specified, this text will be displayed when the image is not available or when images are disabled in the document. + * @returns {Promise} - A Promise that is resolved when the image has been inserted successfully, or rejected if the image could not be inserted for any reason. */ - public async insertImageAsync(imageString: string, width?: number, height?: number): Promise { - await this.insertImageInternal(imageString, false, width, height); + public async insertImageAsync(imageString: string, width?: number, height?: number,alternateText?: string): Promise { + await this.insertImageInternal(imageString, false, width, height,alternateText); } /** * Inserts the image with specified size at cursor position in the document editor. @@ -6408,9 +6506,10 @@ export class Editor { * @param {boolean} isUiInteracted Is image instered from UI interaction. * @param {number} width? Image width * @param {number} height? Image height + * @param {string} alternateText? Image alternateText * @returns {void} */ - public async insertImageInternal(imageString: string, isUiInteracted: boolean, width?: number, height?: number): Promise { + public async insertImageInternal(imageString: string, isUiInteracted: boolean, width?: number, height?: number,alternateText?: string): Promise { return new Promise( (resolve: Function, reject: Function) => { let formField: FieldElementBox = this.selection.getCurrentFormField(); @@ -6423,13 +6522,13 @@ export class Editor { const image: HTMLImageElement = document.createElement('img'); let editor: Editor = this; image.addEventListener('load', function (): void { - editor.insertPicture(imageString, this.width, this.height, true); + editor.insertPicture(imageString, this.width, this.height,this.alt,true); resolve(); }); image.src = imageString; } else { - this.insertPicture(imageString, width, height, isUiInteracted); + this.insertPicture(imageString, width, height, alternateText, isUiInteracted); resolve(); } setTimeout((): void => { @@ -6457,16 +6556,15 @@ export class Editor { columns = columns || 1; const localeValue: L10n = new L10n('documenteditor', this.owner.defaultLocale); localeValue.setLocale(this.documentHelper.owner.locale); - if (columns < 1 || columns > 63) { - DialogUtility.alert(localeValue.getConstant('Number of columns must be between 1 and 63.')); + if (columns < 1 || columns > this.documentHelper.owner.documentEditorSettings.maximumColumns) { + let columnAlertPopup: string = localeValue.getConstant('Number of columns must be between') + ' 1 ' + localeValue.getConstant('and') + ' ' + this.documentHelper.owner.documentEditorSettings.maximumColumns.toString(); + DialogUtility.alert(columnAlertPopup).enableRtl = this.documentHelper.owner.enableRtl; return; } if (rows < 1 || rows > this.documentHelper.owner.documentEditorSettings.maximumRows) { - if (this.documentHelper.owner.locale == 'en-US') { - DialogUtility.alert('Number of rows must be between 1 and ' + this.documentHelper.owner.documentEditorSettings.maximumRows + '.'); - } else { - DialogUtility.alert(localeValue.getConstant('Number of rows must be between 1 and 32767.')); - } + let rowAlertPopup: string = localeValue.getConstant('Number of rows must be between') + ' 1 ' + localeValue.getConstant('and') + ' ' + this.documentHelper.owner.documentEditorSettings.maximumColumns.toString(); + localeValue.getConstant('Number of rows must be between 1 and 32767.').replace("32767", this.documentHelper.owner.documentEditorSettings.maximumRows.toString()); + DialogUtility.alert(rowAlertPopup).enableRtl = this.documentHelper.owner.enableRtl; return; } let table: TableWidget = this.createTable(rows, columns); @@ -7097,6 +7195,12 @@ export class Editor { row.childWidgets.splice(j, 1); cell.destroy(); j--; + for (var l = this.documentHelper.contentControlCollection.length - 1; l > -1; l--) { + var content = this.documentHelper.contentControlCollection[l]; + if (isNullOrUndefined(content.contentControlProperties)) { + this.documentHelper.contentControlCollection.splice(l); + } + } } } } @@ -7409,7 +7513,7 @@ export class Editor { this.documentHelper.layout.layoutBodyWidgetCollection(newParagraph.index, bodyWidget, newParagraph, false); } - private moveInlines(currentParagraph: ParagraphWidget, newParagraph: ParagraphWidget, insertIndex: number, startOffset: number, startLine: LineWidget, endOffset: number, endLine: LineWidget): void { + private moveInlines(currentParagraph: ParagraphWidget, newParagraph: ParagraphWidget, insertIndex: number, startOffset: number, startLine: LineWidget, endOffset: number, endLine: LineWidget, removeBlock?: boolean): void { if (newParagraph.childWidgets.length === 0) { let line: LineWidget = new LineWidget(newParagraph); newParagraph.childWidgets.push(line); @@ -7436,7 +7540,7 @@ export class Editor { } } this.removeEmptyLine(currentParagraph); - if (!currentParagraph.isInsideTable) { + if (!currentParagraph.isInsideTable && !removeBlock) { this.viewer.updateClientArea(currentParagraph.bodyWidget, currentParagraph.bodyWidget.page); this.documentHelper.layout.reLayoutParagraph(currentParagraph, 0, 0); } @@ -7508,6 +7612,7 @@ export class Editor { let rangeIndex: number = currentRevision.range.indexOf(inline); tempSpan.revisions.splice(0, 0, currentRevision); currentRevision.range.splice(rangeIndex, 0, tempSpan); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } } @@ -7585,7 +7690,8 @@ export class Editor { } } this.isHandledComplex = false; - if (this.editorHistory.currentHistoryInfo && this.editorHistory.currentHistoryInfo.action === 'ColumnBreak') { + if (this.editorHistory.currentHistoryInfo && (this.editorHistory.currentHistoryInfo.action === 'ColumnBreak' + || this.editorHistory.currentHistoryInfo.action === 'PageBreak')) { } else { return; } @@ -7605,7 +7711,7 @@ export class Editor { //this.documentHelper.layout.layoutfootNote(foot); }*/ this.owner.viewer.updateScrollBars(); - if (!selection.owner.isShiftingEnabled) { + if (!selection.owner.isShiftingEnabled || this.documentHelper.isRowOrCellResizing) { selection.fireSelectionChanged(true); this.startParagraph = undefined; this.endParagraph = undefined; @@ -7623,7 +7729,7 @@ export class Editor { let bodyWidget: BodyWidget = selection.start.paragraph.bodyWidget; let splittedSection: BodyWidget[] = bodyWidget.getSplitWidgets() as BodyWidget[]; bodyWidget = splittedSection[splittedSection.length - 1]; - if (((!isNullOrUndefined(bodyWidget.nextRenderedWidget) && (bodyWidget.nextRenderedWidget as BodyWidget).sectionFormat.breakCode === 'NoBreak') || (bodyWidget.sectionFormat.breakCode === 'NoBreak' && (bodyWidget.sectionIndex === bodyWidget.page.bodyWidgets[0].sectionIndex))) && !(bodyWidget instanceof HeaderFooterWidget) && !(!isNullOrUndefined(bodyWidget.containerWidget) && bodyWidget.containerWidget instanceof FootNoteWidget)) { + if (((!isNullOrUndefined(bodyWidget.nextRenderedWidget) && (bodyWidget.nextRenderedWidget as BodyWidget).sectionFormat.breakCode === 'NoBreak' && this.documentHelper.layout.isMultiColumnDoc) || (bodyWidget.sectionFormat.breakCode === 'NoBreak' && (bodyWidget.sectionIndex === bodyWidget.page.bodyWidgets[0].sectionIndex) && bodyWidget.sectionFormat.numberOfColumns > 1)) && !(bodyWidget instanceof HeaderFooterWidget) && !(!isNullOrUndefined(bodyWidget.containerWidget) && bodyWidget.containerWidget instanceof FootNoteWidget)) { let startPosition: TextPosition = this.documentHelper.selection.start; let endPosition: TextPosition = this.documentHelper.selection.end; let startInfo: ParagraphInfo = this.selection.getParagraphInfo(startPosition); @@ -7698,6 +7804,8 @@ export class Editor { this.owner.viewer.updateScrollBars(); } this.owner.documentHelper.layout.isRelayout = false; + this.isFootnoteElementRemoved = false; + this.isEndnoteElementRemoved = false; } /** * @private @@ -7720,8 +7828,8 @@ export class Editor { for (let i: number = 0; i < this.documentHelper.pages.length; i++) { let page: Page = this.documentHelper.pages[i]; if (page.bodyWidgets[0].sectionFormat.differentFirstPage && isFirstPage - && page.headerWidgetIn.headerFooterType == node.headerFooterType && page.sectionIndex == currentPage.sectionIndex) { - this.updateHeaderFooterWidgetToPageInternal(page, node, node.headerFooterType.indexOf('Header') !== -1); + && (page.headerWidgetIn.headerFooterType == node.headerFooterType || page.footerWidgetIn.headerFooterType == node.headerFooterType)) { + this.updateHeaderFooterWidgetToPageInternal(page, node, node.headerFooterType.indexOf('Header') !== -1); continue; } if (page.bodyWidgets[0].sectionFormat.differentFirstPage && @@ -7747,9 +7855,9 @@ export class Editor { private updateHeaderFooterWidgetToPageInternal(page: Page, widget: HeaderFooterWidget, isHeader: boolean): void { let update: boolean = false; if (isHeader) { - update = widget != page.headerWidgetIn; + update = widget != page.headerWidgetIn && widget.page.headerWidget == page.headerWidget; } else { - update = widget != page.footerWidgetIn; + update = widget != page.footerWidgetIn && widget.page.footerWidget == page.footerWidget; } if (update) { let hfWidget: HeaderFooterWidget = widget.clone(); @@ -7865,7 +7973,7 @@ export class Editor { if (isNotEmpty) { top = Math.max(headerDistance + section.page.headerWidget.height, top); } - if (firstBlock.y !== top) { + if (firstBlock.y !== top && section.sectionFormat.breakCode !== "NoBreak") { this.owner.viewer.updateClientArea(section, section.page); firstBlock = firstBlock.combineWidget(this.owner.viewer) as BlockWidget; let prevWidget: BlockWidget = firstBlock.previousRenderedWidget as BlockWidget; @@ -8397,7 +8505,7 @@ export class Editor { */ public intializeDefaultStyles(): void { let existingStyles: string[] = this.owner.getStyleNames('Paragraph'); - let defaultStyleNames: string[] = ['Normal', 'Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6']; + let defaultStyleNames: string[] = ['Normal', 'Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6', 'Header', 'Footer']; let styleNames: string[] = defaultStyleNames.filter((val: string) => { return existingStyles.indexOf(val) === -1; }); @@ -9372,6 +9480,7 @@ export class Editor { let rangeIndex: number = currentRevision.range.indexOf(inline) + indexCount; tempSpan.revisions.splice(0, 0, currentRevision); currentRevision.range.splice(rangeIndex, 0, tempSpan); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } } // Cell @@ -9548,6 +9657,7 @@ export class Editor { if (!this.isRevisionAlreadyIn(currentElement, currentRevision)) { currentElement.revisions.push(currentRevision); currentRevision.range.push(currentElement); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); } } else { @@ -9590,7 +9700,7 @@ export class Editor { * @private * @returns {void} */ - public onImageFormat(elementBox: ImageElementBox, width: number, height: number): void { + public onImageFormat(elementBox: ImageElementBox, width: number, height: number,alternateText: string): void { let modifiedFormat: ImageInfo = new ImageInfo(elementBox); if (this.editorHistory) { this.editorHistory.initializeHistory('ImageResizing'); @@ -9599,6 +9709,7 @@ export class Editor { this.setOffsetValue(this.selection); elementBox.width = width; elementBox.height = height; + elementBox.alternateText = alternateText; this.documentHelper.layout.reLayoutParagraph(elementBox.line.paragraph, elementBox.line.indexInOwner, 0); this.reLayout(this.selection, false); @@ -10568,6 +10679,67 @@ export class Editor { } this.updateSectionFormat(property, value); } + /** + * + * @private + * @returns {void} + */ + public removeInlineHeaderFooterWidget(sectionIndex: number, headerFooterType: HeaderFooterType, propertyName: string, value: Object ):void { + if (sectionIndex != 0) { + let headerFooters: HeaderFooters = this.documentHelper.headersFooters[sectionIndex]; + let index: number = (this.viewer as PageLayoutViewer).getHeaderFooter(headerFooterType); + let sectionFormat: WSectionFormat = (this.selection.start.paragraph.containerWidget as HeaderFooterWidget).sectionFormat.cloneFormat(); + if(!isNullOrUndefined(value)) { + if (!isNullOrUndefined(propertyName)) { + let action: Action = (propertyName[0].toUpperCase() + propertyName.slice(1)) as Action; + this.initHistory(action); + let blockInfo: ParagraphInfo = this.selection.getParagraphInfo(this.selection.start); + this.selection.editPosition = this.selection.getHierarchicalIndex(blockInfo.paragraph, blockInfo.offset.toString()); + if (this.checkInsertPosition(this.selection)) { + this.setPositionForHistory(this.selection.editPosition); + } + } + if (value) { + if (headerFooters && !isNullOrUndefined(headerFooters[index])) { + sectionFormat.removedHeaderFooters.push(headerFooters[index]); + this.editorHistory.currentBaseHistoryInfo.addModifiedPropertiesForSection(sectionFormat, propertyName, value); + delete headerFooters[index]; + } + } else { + let parentHeaderFooter: HeaderFooterWidget = (this.viewer as PageLayoutViewer).getCurrentHeaderFooter(headerFooterType, sectionIndex); + if (!isNullOrUndefined(parentHeaderFooter) && isNullOrUndefined(headerFooters[index])){ + let HeaderFooterWidget: HeaderFooterWidget = parentHeaderFooter.clone(); + headerFooters[index] = HeaderFooterWidget; + sectionFormat.removedHeaderFooters.push(HeaderFooterWidget); + this.editorHistory.currentBaseHistoryInfo.addModifiedPropertiesForSection(sectionFormat, propertyName, value); + } + } + this.selection.updateTextPositionForBlockContainer(this.selection.start.paragraph.containerWidget as BlockContainer); + this.layoutWholeDocument(); + this.fireContentChange(); + } + } + } + /** + * + * @private + * @returns {void} + */ + public updateHeaderFooters (propertyName: string, value: boolean, sectionIndex: number, widget: HeaderFooterWidget): void { + let headerFooters: HeaderFooters = this.documentHelper.headersFooters[sectionIndex]; + let index: number = (this.viewer as PageLayoutViewer).getHeaderFooter(widget.headerFooterType); + let headerFooter: HeaderFooterWidget = headerFooters[index]; + if (this.editorHistory.isUndoing || this.editorHistory.isRedoing) { + if (isNullOrUndefined(headerFooter)) { + this.documentHelper.headersFooters[sectionIndex][index] = widget; + } + else if (!isNullOrUndefined(headerFooter)) { + delete headerFooters[index]; + } + } + this.selection.updateTextPositionForBlockContainer(this.selection.start.paragraph.containerWidget as BlockContainer); + this.layoutWholeDocument(); + } /** * Update section format * @@ -11323,7 +11495,7 @@ export class Editor { return true; } - private deleteSelectedContent(paragraph: ParagraphWidget, selection: Selection, start: TextPosition, end: TextPosition, editAction: number): void { + private deleteSelectedContent(paragraph: ParagraphWidget, selection: Selection, start: TextPosition, end: TextPosition, editAction: number, skipDeletecell?: boolean): void { let indexInInline: number = 0; let inlineObj: ElementInfo = start.currentWidget.getInline(start.offset, indexInInline); let inline: ElementBox = inlineObj.element; @@ -11377,7 +11549,7 @@ export class Editor { // Selection start in cell. if (end.paragraph.isInsideTable && (!start.paragraph.isInsideTable || start.paragraph.associatedCell !== end.paragraph.associatedCell - || selection.isCellSelected(end.paragraph.associatedCell, start, end))) { + || (selection.isCellSelected(end.paragraph.associatedCell, start, end) && !skipDeletecell))) { end.paragraph.associatedCell.ownerTable.combineWidget(this.owner.viewer); this.deleteTableCell(end.paragraph.associatedCell, selection, start, end, editAction); } else { @@ -11540,6 +11712,7 @@ export class Editor { let row: TableRowWidget = table.childWidgets[i] as TableRowWidget; if (row.childWidgets.length === 1) { if (deleteCells.indexOf(row.childWidgets[0] as TableCellWidget) >= 0) { + this.removeFieldInWidget(row.childWidgets[0] as Widget, true); table.childWidgets.splice(table.childWidgets.indexOf(row), 1); row.destroy(); i--; @@ -11548,6 +11721,7 @@ export class Editor { for (let j: number = 0; j < row.childWidgets.length; j++) { let tableCell: TableCellWidget = row.childWidgets[j] as TableCellWidget; if (deleteCells.indexOf(tableCell) >= 0) { + this.removeFieldInWidget(tableCell as Widget, true); row.childWidgets.splice(j, 1); tableCell.destroy(); j--; @@ -11646,6 +11820,7 @@ export class Editor { if (this.owner.enableTrackChanges && this.checkIsNotRedoing()) { this.trackRowDeletion(tableRow, true, false); } else { + this.removeFieldInBlock(tableRow, true); table.childWidgets.splice(i, 1); tableRow.destroy(); i--; @@ -11754,6 +11929,7 @@ export class Editor { } table.destroy(); } else { + this.removeFieldInBlock(row, true); table.childWidgets.splice(table.childWidgets.indexOf(row), 1); row.destroy(); this.updateTable(table); @@ -11799,9 +11975,14 @@ export class Editor { let startLine: LineWidget = undefined; let endLineWidget: LineWidget = undefined; let isCombineLastBlock = this.combineLastBlock; + let tempStartOffset : number; if (paragraph === start.paragraph) { startOffset = start.offset; startLine = start.currentWidget; + tempStartOffset = startOffset; + if ((startOffset + 1 === this.documentHelper.selection.getLineLength(paragraph.lastChild as LineWidget))) { + startOffset++; + } if (end.paragraph.isInsideTable) { isCombineNextParagraph = this.isEndInAdjacentTable(paragraph, end.paragraph); } @@ -11826,14 +12007,17 @@ export class Editor { let block: BlockWidget = (!isNullOrUndefined(paragraph.previousRenderedWidget) && start.paragraph !== paragraph) ? paragraph.previousRenderedWidget.combineWidget(this.documentHelper.viewer) as BlockWidget : undefined; - if (startOffset > paragraphStart && (paragraph === end.paragraph && end.offset === startOffset + 1 || + if (startOffset > paragraphStart && start.currentWidget === paragraph.lastChild && + startOffset === lastLinelength && (paragraph === end.paragraph && end.offset === startOffset + 1 || paragraph.nextRenderedWidget === end.paragraph && end.offset === endParagraphStartOffset) || (this.editorHistory && this.editorHistory.isUndoing && this.editorHistory.currentHistoryInfo && this.editorHistory.currentHistoryInfo.action === 'PageBreak' && block && block.isPageBreak() && (startOffset === 0 && !start.currentWidget.isFirstLine || startOffset > 0)) || start.paragraph !== end.paragraph && editAction === 2 && start.paragraph === paragraph && start.paragraph.nextWidget === end.paragraph) { isCombineNextParagraph = true; - isCombineLastBlock = true; + } + if ((tempStartOffset + 1 === this.documentHelper.selection.getLineLength(paragraph.lastChild as LineWidget))) { + startOffset--; } let paraEnd: TextPosition = end.clone(); paraEnd.offset = paraEnd.offset - 1; @@ -12114,7 +12298,7 @@ export class Editor { paragraph.childWidgets.push(lineWidget); let blockIndex: number = paragraphAdv.index; let insertIndex: number = paragraphAdv.indexInOwner; - this.moveInlines(paragraphAdv, paragraph, 0, startOffset, startLine, endOffset, endLine); + this.moveInlines(paragraphAdv, paragraph, 0, startOffset, startLine, endOffset, endLine, removeBlock); if (paragraphAdv.containerWidget.childWidgets[insertIndex]) { let line: BlockWidget = ((paragraphAdv.containerWidget.childWidgets[insertIndex] as ParagraphWidget)); for (let i: number = 0; i < line.childWidgets.length; i++) { @@ -12261,6 +12445,7 @@ export class Editor { let isParaMark: boolean = lastRange instanceof WCharacterFormat; if (isParaMark) { revision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); if (nonEmptyEndPara.characterFormat && nonEmptyEndPara.characterFormat.revisions.indexOf(revision) > -1) { nonEmptyEndPara.characterFormat.revisions.splice(nonEmptyEndPara.characterFormat.revisions.indexOf(revision), 1); } @@ -12290,6 +12475,7 @@ export class Editor { } return false; } + /** * @private */ @@ -12306,6 +12492,7 @@ export class Editor { } footnoteWidget.bodyWidgets.splice(j, 1); j--; + this.isFootnoteElementRemoved = true; } } if (footnoteWidget.bodyWidgets.length === 0) { @@ -12313,22 +12500,27 @@ export class Editor { } } this.documentHelper.footnoteCollection.splice(this.documentHelper.footnoteCollection.indexOf(element), 1); + this.updateFootNoteIndex(); } private removeEndnote(element: FootnoteElementBox, paragraph?: ParagraphWidget): void { - if (element.paragraph.bodyWidget.page.endnoteWidget) { - let endnoteWidget: FootNoteWidget = element.paragraph.bodyWidget.page.endnoteWidget; + const lastpage = this.documentHelper.pages.length; + const bodyWidget = this.documentHelper.pages[lastpage - 1].bodyWidgets[0]; + if (bodyWidget.page.endnoteWidget) { + let endnoteWidget: FootNoteWidget = bodyWidget.page.endnoteWidget; for (let j: number = 0; j < endnoteWidget.bodyWidgets.length; j++) { if (element === (endnoteWidget.bodyWidgets[j]).footNoteReference) { endnoteWidget.height -= (endnoteWidget.bodyWidgets[j].childWidgets[0] as BlockWidget).height; endnoteWidget.bodyWidgets.splice(j, 1); + this.isEndnoteElementRemoved = true; j--; } } if (endnoteWidget.bodyWidgets.length === 0) { - element.paragraph.bodyWidget.page.endnoteWidget = undefined; + bodyWidget.page.endnoteWidget = undefined; } } this.documentHelper.endnoteCollection.splice(this.documentHelper.endnoteCollection.indexOf(element), 1); + this.updateEndNoteIndex(); } private removeAutoShape(inline: ShapeBase): void { let shapeIndex: number = inline.line.paragraph.floatingElements.indexOf(inline); @@ -12359,9 +12551,20 @@ export class Editor { for (let i: number = 0; i < collection.length; i++) { let element: FieldElementBox | BookmarkElementBox = isBookmark ? this.documentHelper.bookmarks.get(collection[i] as string) : collection[i] as FieldElementBox; - if (element.line.paragraph === block) { + if (element.line.paragraph === block || (element instanceof BookmarkElementBox && element.reference.line.paragraph === block)) { if (isBookmark) { this.documentHelper.bookmarks.remove(collection[i] as string); + element.line.children.splice(element.indexInOwner, 1); + if(!isNullOrUndefined(element.line.paragraph.associatedCell)) { + const cell = element.line.paragraph.associatedCell; + cell.isRenderBookmarkStart ? cell.isRenderBookmarkStart = false : cell.isRenderBookmarkEnd = false; + } + const endBookMarkElement = (element as BookmarkElementBox).reference; + endBookMarkElement.line.children.splice(endBookMarkElement.indexInOwner, 1); + if(!isNullOrUndefined(endBookMarkElement.line.paragraph.associatedCell)) { + const cell = endBookMarkElement.line.paragraph.associatedCell; + cell.isRenderBookmarkStart ? cell.isRenderBookmarkStart = false : cell.isRenderBookmarkEnd = false; + } } else if (isContentControl) { this.documentHelper.contentControlCollection.splice(i, 1); } else { @@ -12820,6 +13023,7 @@ export class Editor { item.revisions.splice(item.revisions.indexOf(revision), 1); let rangeIndex: number = revision.range.indexOf(item); revision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); } } } @@ -12928,7 +13132,13 @@ export class Editor { let previousBlock: ParagraphWidget = this.checkAndInsertBlock(table, start, end, editAction, block instanceof ParagraphWidget ? block : undefined); if (selection.containsRow((table.firstChild as TableRowWidget), start.paragraph.associatedCell)) { - this.deleteContent(table, selection, editAction); + if (this.owner.enableTrackChanges) { + for (let i: number = 0; i < table.childWidgets.length; i++) { + this.trackRowDeletion(table.childWidgets[i] as TableRowWidget); + } + } else { + this.deleteContent(table, selection, editAction); + } } else { if (this.owner.enableTrackChanges) { if (isNullOrUndefined(end.paragraph.associatedCell) && !end.paragraph.isInsideTable) { @@ -13243,6 +13453,9 @@ export class Editor { this.removedEditRangeEndElements.push(inline); } lineWidget.children.splice(i, 1); + if (!isNullOrUndefined(lineWidget.layoutedElements) && lineWidget.layoutedElements.length > 0) { + lineWidget.layoutedElements.splice(i, 1); + } } } else if (inline instanceof TextElementBox) { let span: ElementBox = this.handleDeleteTracking(inline, startIndex, endIndex); @@ -13501,7 +13714,9 @@ export class Editor { } else { this.updateSelectionParagraphFormatting('listFormat', format, false); } - this.reLayout(selection); + this.documentHelper.owner.isShiftingEnabled = true; + this.layoutWholeDocument(); + this.documentHelper.owner.isShiftingEnabled = false; } /** * Applies bullets or numbering list @@ -13731,10 +13946,12 @@ export class Editor { * @returns {void} */ public onEnter(breakType?: string): void { + this.handledEnter = true; let selection: Selection = this.documentHelper.selection; var format: SelectionCharacterFormat; if (isNullOrUndefined(selection.start.paragraph.paragraphFormat.baseStyle) || - selection.start.paragraph.paragraphFormat.baseStyle.name === 'Normal') { + selection.start.paragraph.paragraphFormat.baseStyle.name === 'Normal' || + selection.start.paragraph.paragraphFormat.baseStyle.name === 'Normal (Web)') { format = new SelectionCharacterFormat(undefined) format.cloneFormat(this.selection.characterFormat); let eleme: ElementBox = (selection.start.paragraph.lastChild as LineWidget).children[(selection.start.paragraph.lastChild as LineWidget).children.length - 1]; @@ -13796,6 +14013,7 @@ export class Editor { let currentRevision: Revision = this.retrieveRevisionInOder(currentParagraph.characterFormat); currentRevision.range.push(breakParagraph.characterFormat); breakParagraph.characterFormat.revisions.push(currentRevision); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); breakParagraph.characterFormat.removedIds = []; } this.insertParagraph(breakParagraph, true); @@ -13841,6 +14059,7 @@ export class Editor { } this.documentHelper.layout.islayoutFootnote = false; this.updateHistoryForComments(commentStartToInsert); + this.handledEnter = false; } private splitParagraphInternal(selection: Selection, paragraphAdv: ParagraphWidget, currentLine: LineWidget, offset: number): void { let insertIndex: number = 0; @@ -14458,8 +14677,8 @@ export class Editor { * @param {boolean} isBackSpace - Specifies is backspace. * @returns {boolean} */ - public deleteSelectedContents(selection: Selection, isBackSpace: boolean): boolean { - let skipBackSpace: boolean = this.deleteSelectedContentInternal(selection, isBackSpace, selection.start, selection.end); + public deleteSelectedContents(selection: Selection, isBackSpace: boolean, skipDeletecell?: boolean): boolean { + let skipBackSpace: boolean = this.deleteSelectedContentInternal(selection, isBackSpace, selection.start, selection.end, skipDeletecell); let textPosition: TextPosition = selection.getTextPosBasedOnLogicalIndex(selection.editPosition); selection.selectContent(textPosition, true); return skipBackSpace; @@ -14631,38 +14850,6 @@ export class Editor { } } } - if (inline && (inline instanceof BookmarkElementBox || inline.previousNode instanceof BookmarkElementBox)) { - if (inline instanceof BookmarkElementBox && inline.bookmarkType === 1) { - if (inline.previousNode) { - inline = inline.previousNode; - paragraph = inline.line.paragraph; - offset = inline.line.getOffset(inline, inline.length); - } else { - // remove paragraph mark and move bookmark to previous paragraph - if (paragraph.previousRenderedWidget instanceof ParagraphWidget) { - let prevParagraph: ParagraphWidget = paragraph.previousRenderedWidget; - let line: LineWidget = prevParagraph.lastChild as LineWidget; - selection.start.setPositionParagraph(inline.line, inline.line.getOffset(inline, 0)); - selection.end.setPositionParagraph(line, line.getEndOffset()); - this.removeWholeElement(selection); - return; - } - } - // Remove bookmark if selection is in between bookmark start and end element. - } else if (inline.nextNode instanceof BookmarkElementBox && inline instanceof BookmarkElementBox && - inline.bookmarkType === 0 && inline.reference === inline.nextNode) { - this.deleteBookmark(inline.name); - return; - } - if (inline.length === 1 && inline.nextNode instanceof BookmarkElementBox && inline.previousNode instanceof BookmarkElementBox) { - let begin: BookmarkElementBox = inline.previousNode; - let end: BookmarkElementBox = inline.nextNode; - selection.start.setPositionParagraph(begin.line, begin.line.getOffset(begin, 0)); - selection.end.setPositionParagraph(end.line, end.line.getOffset(end, 0) + 1); - this.removeWholeElement(selection); - return; - } - } // if (inline instanceof CommentCharacterElementBox && inline.commentType === 1) { // let comment: CommentElementBox = inline.comment; // if (comment.isReply) { @@ -14707,11 +14894,13 @@ export class Editor { return; } if (inline instanceof EditRangeEndElementBox) { - if (!isNullOrUndefined(inline.previousNode)) { - inline = inline.previousNode; - paragraph = inline.line.paragraph; - offset = inline.line.getOffset(inline, inline.length); - } + do { + if (!isNullOrUndefined(inline.previousNode)) { + inline = inline.previousNode; + paragraph = inline.line.paragraph; + offset = inline.line.getOffset(inline, inline.length); + } else { break; } + } while(inline instanceof EditRangeEndElementBox); } if (inline.length === 1 && inline.nextNode instanceof EditRangeEndElementBox && inline.previousNode instanceof EditRangeStartElementBox) { @@ -14723,6 +14912,38 @@ export class Editor { return; } } + if (inline && (inline instanceof BookmarkElementBox || inline.previousNode instanceof BookmarkElementBox)) { + if (inline instanceof BookmarkElementBox && inline.bookmarkType === 1) { + if (inline.previousNode) { + inline = inline.previousNode; + paragraph = inline.line.paragraph; + offset = inline.line.getOffset(inline, inline.length); + } else { + // remove paragraph mark and move bookmark to previous paragraph + if (paragraph.previousRenderedWidget instanceof ParagraphWidget) { + let prevParagraph: ParagraphWidget = paragraph.previousRenderedWidget; + let line: LineWidget = prevParagraph.lastChild as LineWidget; + selection.start.setPositionParagraph(inline.line, inline.line.getOffset(inline, 0)); + selection.end.setPositionParagraph(line, line.getEndOffset()); + this.removeWholeElement(selection); + return; + } + } + // Remove bookmark if selection is in between bookmark start and end element. + } else if (inline.nextNode instanceof BookmarkElementBox && inline instanceof BookmarkElementBox && + inline.bookmarkType === 0 && inline.reference === inline.nextNode) { + this.deleteBookmark(inline.name); + return; + } + if (inline.length === 1 && inline.nextNode instanceof BookmarkElementBox && inline.previousNode instanceof BookmarkElementBox) { + let begin: BookmarkElementBox = inline.previousNode; + let end: BookmarkElementBox = inline.nextNode; + selection.start.setPositionParagraph(begin.line, begin.line.getOffset(begin, 0)); + selection.end.setPositionParagraph(end.line, end.line.getOffset(end, 0) + 1); + this.removeWholeElement(selection); + return; + } + } if (!isRedoing) { this.initHistory('BackSpace'); } @@ -14910,6 +15131,9 @@ export class Editor { inline.line = (inline.line.paragraph.nextRenderedWidget.firstChild as LineWidget); } lineWidget.children.splice(i, 1); + if (!isNullOrUndefined(lineWidget.layoutedElements) && lineWidget.layoutedElements.length > 0) { + lineWidget.layoutedElements.splice(i, 1); + } return true; } if (offset < count + inline.length) { @@ -14940,6 +15164,9 @@ export class Editor { } } lineWidget.children.splice(i, 1); + if (!isNullOrUndefined(lineWidget.layoutedElements) && lineWidget.layoutedElements.length > 0) { + lineWidget.layoutedElements.splice(i, 1); + } } this.documentHelper.layout.reLayoutParagraph(lineWidget.paragraph, lineIndex, i, undefined, isRearrange); } else { @@ -15020,9 +15247,14 @@ export class Editor { // inserted revision same author as delete revision so we can delete if (isNullOrUndefined(elementIndex)) { removedNode = this.removeCharacterInLine(elementBox, indexInInline, endOffset); + let revision = elementBox.revisions[0]; + if (!isNullOrUndefined(revision)) { + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); + } } else { let index: number = revision.range.indexOf(elementBox); revision.range.splice(index, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); if (revision.range.length === 0) { this.owner.revisionsInternal.remove(revision); } @@ -15041,6 +15273,10 @@ export class Editor { //Insert revision and delete revision (which is to be included) haven't matched if (isNullOrUndefined(elementIndex)) { let text: TextElementBox = this.removeCharacterInLine(elementBox, indexInInline, endOffset); + let revision = elementBox.revisions[0]; + if (!isNullOrUndefined(revision)) { + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); + } if (indexInInline === 0) { let prevElement: ElementBox = elementBox.previousElement; this.handleDeletionForInsertRevision(prevElement, elementBox, text, endOffset, indexInInline, true); @@ -15057,6 +15293,7 @@ export class Editor { text.revisions.splice(0, 0, revision); text.line = elementBox.line; revision.range.splice(index + 1, 0, text); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); (elementBox as TextElementBox).text = (elementBox as TextElementBox).text.substr(0, indexInInline); let indexInOwner: number = elementBox.indexInOwner; elementBox.line.children.splice(indexInOwner + 1, 0, newElement); @@ -15088,14 +15325,15 @@ export class Editor { } } } else if (revision.revisionType === 'Deletion') { - if (index !== -1 && revision.author !== this.owner.currentUser) { + if (index !== -1 && revision.author !== this.owner.currentUser && revision.range.length > 0) { let range: Object[] = revision.range; - let startOff: number = (range[0] as ElementBox).line.getOffset(range[0] as ElementBox, 0); - let lastEle: ElementBox = range[range.length - 1] as ElementBox; + let startOff: number = range[0] instanceof WCharacterFormat ? 0 : (range[0] as ElementBox).line.getOffset(range[0] as ElementBox, 0); + let lastEle: any = range[range.length - 1] instanceof WCharacterFormat ? range[range.length - 2] : range[range.length - 1]; let endOff: number = lastEle.line.getOffset(lastEle, lastEle.length); let isRevisionInserted : boolean = false; if (startOff === indexInInline && endOff === endOffset) { range.splice(range.indexOf(elementBox), 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); elementBox.revisions.splice(elementBox.revisions.indexOf(revision), 1); if (!this.checkToCombineRevisionsInSides(elementBox as ElementBox, 'Deletion')) { this.insertRevision(elementBox, 'Deletion'); @@ -15128,11 +15366,13 @@ export class Editor { revision.range[(rangeIndex + 1)] as TextElementBox); revision.range.splice(revision.range.indexOf(elementBox), 1); this.toCombineOrInsertRevision(elementBox, 'Deletion'); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); } else if (revision.range.length === 1 || indexInInline === 0) { this.handleDeleteBySplitting(elementBox, indexInInline, endOffset); - if (rangeIndex !== -1 && revision.range.length !== 1) { + if (rangeIndex > 0 && revision.range.length !== 1) { this.updateRevisionForSpittedTextElement(revision.range[(rangeIndex - 1)] as TextElementBox, revision.range[rangeIndex] as TextElementBox); + revision = this.retrieveRevisionInOder(elementBox); revision.range.splice(revision.range.indexOf(elementBox), 1); } } else { @@ -15158,6 +15398,10 @@ export class Editor { } } else { removedNode = this.removeCharacterInLine(elementBox, indexInInline, endOffset); + let revision = elementBox.revisions[0]; + if (!isNullOrUndefined(revision)) { + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); + } } return removedNode; @@ -15215,6 +15459,7 @@ export class Editor { let revision: Revision = currentElement.revisions[currentElement.revisions.length - 1]; let index: number = revision.range.indexOf(currentElement); revision.range.splice((isBegin) ? index : index + 1, 0, spittedSpan); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); spittedSpan.revisions.splice(0, 0, revision); let isDelete: boolean = false; if (this.owner.editorHistory) { @@ -15256,6 +15501,10 @@ export class Editor { } let spittedElement: TextElementBox = this.removeCharacterInLine(elementBox, indexInInline, endOffset); + let revision = elementBox.revisions[0]; + if (!isNullOrUndefined(revision)) { + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); + } this.addRemovedNodes(spittedElement.clone()); this.insertTextInternal(spittedElement.text, false, 'Deletion'); } @@ -15779,6 +16028,7 @@ export class Editor { let currentRevision: Revision = currentPara.characterFormat.revisions[i]; let rangeIndex: number = currentRevision.range.indexOf(currentPara.characterFormat); currentRevision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); if (currentRevision.range.length === 0) { this.owner.revisions.remove(currentRevision); } @@ -15793,6 +16043,7 @@ export class Editor { let revisionIndex: number = currentPara.characterFormat.revisions.indexOf(deleteRevision); currentPara.characterFormat.revisions.splice(revisionIndex, 1); deleteRevision.range.splice(deleteRevision.range.indexOf(currentPara.characterFormat), 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(deleteRevision); if (deleteRevision.range.length === 0) { this.owner.revisions.remove(deleteRevision); } @@ -15802,6 +16053,7 @@ export class Editor { if (!isNullOrUndefined(insertRevision) && this.isRevisionMatched(currentPara.characterFormat, 'Insertion')) { let rangeIndex: number = insertRevision.range.indexOf(currentPara.characterFormat); insertRevision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(insertRevision); if (insertRevision.range.length === 0) { this.owner.revisions.remove(insertRevision); } @@ -15876,7 +16128,7 @@ export class Editor { * deleteSelectedContentInternal * @private */ - public deleteSelectedContentInternal(selection: Selection, isBackSpace: boolean, startPosition: TextPosition, endPosition: TextPosition): boolean { + public deleteSelectedContentInternal(selection: Selection, isBackSpace: boolean, startPosition: TextPosition, endPosition: TextPosition, skipDeletecell?: boolean): boolean { let startPos: TextPosition = startPosition; let endPos: TextPosition = endPosition; if (!startPosition.isExistBefore(endPosition)) { @@ -15904,7 +16156,7 @@ export class Editor { this.editorHistory.currentBaseHistoryInfo.insertPosition = selection.editPosition; } const editAction: number = (isBackSpace ? 1 : 0); - this.deleteSelectedContent(endPos.paragraph, selection, startPos, endPos, editAction); + this.deleteSelectedContent(endPos.paragraph, selection, startPos, endPos, editAction, skipDeletecell); } return skipBackSpace; } @@ -15941,9 +16193,10 @@ export class Editor { * @param {string} base64String Base64 string, web URL or file URL. * @param {number} width Image width * @param {number} height Image height + * @param {string} alternateText Image alternateText * @returns {void} */ - public insertPicture(base64String: string, width: number, height: number, isUiInteracted: boolean): void { + public insertPicture(base64String: string, width: number, height: number, alternateText:string, isUiInteracted: boolean): void { const imageElementBox: ImageElementBox = new ImageElementBox(true); if (HelperMethods.formatClippedString(base64String).extension === '.svg') { imageElementBox.metaFileImageString = base64String; @@ -15955,6 +16208,10 @@ export class Editor { } imageElementBox.width = width; imageElementBox.height = height; + if(!isNullOrUndefined(alternateText) || alternateText!="") + { + imageElementBox.alternateText = alternateText; + } imageElementBox.textWrappingStyle = 'Inline'; this.documentHelper.addBase64StringInCollection(imageElementBox); imageElementBox.element.src = this.documentHelper.getImageString(imageElementBox); @@ -17383,20 +17640,12 @@ export class Editor { const table: TableWidget = this.selection.start.paragraph.associatedCell.ownerTable.combineWidget(this.owner.viewer) as TableWidget; if (isShading) { - for (let i: number = 0; i < table.childWidgets.length; i++) { - const rowWidget: TableRowWidget = table.childWidgets[i] as TableRowWidget; - for (let j: number = 0; j < rowWidget.childWidgets.length; j++) { - const cellWidget: TableCellWidget = rowWidget.childWidgets[j] as TableCellWidget; - cellWidget.cellFormat.shading.copyFormat(format.shading); - } - } - } - if (!isNullOrUndefined(isShading)) { for (let i: number = 0; i < table.childWidgets.length; i++) { const rowWidget: TableRowWidget = table.childWidgets[i] as TableRowWidget; rowWidget.rowFormat.borders.copyFormat(format.borders); for (let j: number = 0; j < rowWidget.childWidgets.length; j++) { const cellWidget: TableCellWidget = rowWidget.childWidgets[j] as TableCellWidget; + cellWidget.cellFormat.shading.copyFormat(format.shading); cellWidget.cellFormat.borders.copyFormat(format.borders); } } @@ -18008,6 +18257,7 @@ export class Editor { if (fieldBegin.revisions.length > 0) { const currentRevision: Revision = fieldBegin.revisions[fieldBegin.revisions.length - 1]; currentRevision.range.push(fieldEnd); + this.owner.trackChangesPane.updateCurrentTrackChanges(currentRevision); fieldEnd.revisions.push(currentRevision); } lineWidget.children.push(fieldEnd); @@ -18675,6 +18925,35 @@ export class Editor { if (this.documentHelper.editRanges.get(user).length === 0) { this.documentHelper.editRanges.remove(user); } + if(editStart.columnFirst!=-1 && editStart.columnLast !=-1){ + let row = editStart.paragraph.associatedCell.ownerRow; + if (row.editRangeID.containsKey(editStart.editRangeId)) { + let cell = row.getCellUsingColumnIndex(row.rowIndex, editStart.columnFirst); + if (!isNullOrUndefined(cell)) { + if (cell.isRenderEditRangeStart && cell.isRenderEditRangeEnd ) { + cell.isRenderEditRangeEnd = false; + cell.isRenderEditRangeStart = false; + row.editRangeID.remove(editStart.editRangeId); + } + } + } else { + let table = editStart.paragraph.associatedCell.ownerTable; + for (let i = row.rowIndex - 1; i >= 0; i--) { + let previousRow: TableRowWidget = table.childWidgets[i] as TableRowWidget; + if (previousRow.editRangeID.containsKey(editStart.editRangeId)) { + let previousCell = previousRow.getCellUsingColumnIndex(previousRow.rowIndex, editStart.columnFirst); + if (!isNullOrUndefined(previousCell)) { + if (previousCell.isRenderEditRangeStart && previousCell.isRenderEditRangeEnd) { + previousCell.isRenderEditRangeEnd = false; + previousCell.isRenderEditRangeStart = false; + previousRow.editRangeID.remove(editStart.editRangeId); + break; + } + } + } + } + } + } editStart.removeEditRangeMark(); editStart.editRangeEnd.line.children.splice(editStart.editRangeEnd.indexInOwner, 1); editStart.line.children.splice(editStart.indexInOwner, 1); @@ -18926,7 +19205,7 @@ export class Editor { } this.documentHelper.layout.isInsertFormField = true; this.insertElement(element); - this.documentHelper.layout.isInsertFormField = false; + this.documentHelper.layout.isInsertFormField = false; const paragraph: ParagraphWidget = this.selection.start.paragraph; fieldEnd.linkFieldCharacter(this.documentHelper); if (this.documentHelper.fields.indexOf(fieldBegin) === -1) { @@ -19210,6 +19489,7 @@ export class Editor { const paragraph: ParagraphWidget = new ParagraphWidget(); const lineWidget: LineWidget = new LineWidget(paragraph); const text: TextElementBox = new TextElementBox(); + paragraph.paragraphFormat.afterSpacing = 0; text.characterFormat.baselineAlignment = 'Superscript'; text.line = lineWidget; text.text = '?'; @@ -19287,6 +19567,7 @@ export class Editor { const paragraph: ParagraphWidget = new ParagraphWidget(); const lineWidget: LineWidget = new LineWidget(paragraph); const footText: TextElementBox = new TextElementBox(); + paragraph.paragraphFormat.afterSpacing = 0; footText.characterFormat.baselineAlignment = 'Superscript'; footText.line = lineWidget; footText.text = '?'; diff --git a/controls/documenteditor/src/document-editor/implementation/format/border.ts b/controls/documenteditor/src/document-editor/implementation/format/border.ts index 0fbe3bf12c..aaddbb66b9 100644 --- a/controls/documenteditor/src/document-editor/implementation/format/border.ts +++ b/controls/documenteditor/src/document-editor/implementation/format/border.ts @@ -164,7 +164,7 @@ export class WBorder { case 'DashDot': case 'DashDotDot': case 'Thick': - return this.lineWidth; + return (this.lineWidth >= 0.5 ? this.lineWidth : 0.5); case 'SingleWavy': return (this.lineWidth === 1.5 ? 3 : 2.5); //Double wave border only draw with the fixed width case 'DoubleWavy': @@ -172,9 +172,9 @@ export class WBorder { case 'DashDotStroked': case 'Outset': - return this.lineWidth; + return (this.lineWidth >= 0.5 ? this.lineWidth : 0.5); } - return this.lineWidth; + return (this.lineWidth >= 0.5 ? this.lineWidth : 0.5); /* eslint-enable */ } private getBorderLineWidthArray(lineStyle: LineStyle, lineWidth: number): number[] { diff --git a/controls/documenteditor/src/document-editor/implementation/format/character-format.ts b/controls/documenteditor/src/document-editor/implementation/format/character-format.ts index 45cdbb5185..c3370808ad 100644 --- a/controls/documenteditor/src/document-editor/implementation/format/character-format.ts +++ b/controls/documenteditor/src/document-editor/implementation/format/character-format.ts @@ -42,6 +42,18 @@ export class WCharacterFormat { public set fontSize(value: number) { this.setPropertyValue('fontSize', value); } + public get characterSpacing(): number { + return this.getPropertyValue('characterSpacing') as number; + } + public set characterSpacing(value: number) { + this.setPropertyValue('characterSpacing', value); + } + public get scaling(): number { + return this.getPropertyValue('scaling') as number; + } + public set scaling(value: number) { + this.setPropertyValue('scaling', value); + } public get fontFamily(): string { return this.getPropertyValue('fontFamily') as string; } @@ -319,6 +331,8 @@ export class WCharacterFormat { this.addUniqueCharacterFormat('fontFamilyAscii', property, propValue, uniqueCharFormatTemp); this.addUniqueCharacterFormat('fontFamilyNonFarEast', property, propValue, uniqueCharFormatTemp); this.addUniqueCharacterFormat('complexScript', property, propValue, uniqueCharFormatTemp); + this.addUniqueCharacterFormat('characterSpacing', property, propValue, uniqueCharFormatTemp); + this.addUniqueCharacterFormat('scaling', property, propValue, uniqueCharFormatTemp); this.uniqueCharacterFormat = WCharacterFormat.uniqueCharacterFormats.addUniqueFormat(uniqueCharFormatTemp, WCharacterFormat.uniqueFormatType); } @@ -395,6 +409,12 @@ export class WCharacterFormat { case 'fontFamilyNonFarEast': value = undefined; break; + case 'characterSpacing': + value = 0; + break; + case 'scaling': + value = 100; + break; } return value; } @@ -417,6 +437,8 @@ export class WCharacterFormat { && this.fontFamilyAscii === format.fontFamilyAscii && this.fontFamilyBidi === format.fontFamilyBidi && this.fontFamilyFarEast === format.fontFamilyFarEast + && this.characterSpacing === format.characterSpacing + && this.scaling === format.scaling && this.fontFamilyNonFarEast === format.fontFamilyNonFarEast); } public isSameFormat(format: WCharacterFormat): boolean { @@ -507,8 +529,24 @@ export class WCharacterFormat { if (isNullOrUndefined(this.getValue('fontSize'))) { this.fontSize = format.getValue('fontSize') as number; } + if (isNullOrUndefined(this.getValue('characterSpacing'))) { + this.characterSpacing = format.getValue('characterSpacing') as number; + } + if (isNullOrUndefined(this.getValue('scaling'))) { + this.scaling = format.getValue('scaling') as number; + } if (isNullOrUndefined(this.getValue('fontFamily'))) { this.fontFamily = format.getValue('fontFamily') as string; + } else { + if (isNullOrUndefined(this.getValue('fontFamilyAscii'))) { + this.fontFamilyAscii = format.getValue('fontFamily') as string; + } + if (isNullOrUndefined(this.getValue('fontFamilyFarEast'))) { + this.fontFamilyFarEast = format.getValue('fontFamily') as string; + } + if (isNullOrUndefined(this.getValue('fontFamilyNonFarEast'))) { + this.fontFamilyNonFarEast = format.getValue('fontFamily') as string; + } } if (isNullOrUndefined(this.getValue('underline'))) { this.underline = format.getValue('underline') as Underline; diff --git a/controls/documenteditor/src/document-editor/implementation/format/paragraph-format.ts b/controls/documenteditor/src/document-editor/implementation/format/paragraph-format.ts index f711874a09..34fdad1ca3 100644 --- a/controls/documenteditor/src/document-editor/implementation/format/paragraph-format.ts +++ b/controls/documenteditor/src/document-editor/implementation/format/paragraph-format.ts @@ -91,9 +91,9 @@ export class WParagraphFormat { inTabs.push(tabStops.get(key)); } } - inTabs = inTabs.concat(this.tabs.filter((a: WTabStop) => (a.position !== 0 && a.deletePosition === 0))); - inTabs = inTabs.sort((a: WTabStop, b: WTabStop) => a.position - b.position); } + inTabs = inTabs.concat(this.tabs.filter((a: WTabStop) => (a.position !== 0 && a.deletePosition === 0))); + inTabs = inTabs.sort((a: WTabStop, b: WTabStop) => a.position - b.position); return inTabs; } private getTabStopsFromListFormat(): WTabStop[] { diff --git a/controls/documenteditor/src/document-editor/implementation/format/section-format.ts b/controls/documenteditor/src/document-editor/implementation/format/section-format.ts index 43416deda5..e9e9ac6ba0 100644 --- a/controls/documenteditor/src/document-editor/implementation/format/section-format.ts +++ b/controls/documenteditor/src/document-editor/implementation/format/section-format.ts @@ -4,6 +4,8 @@ import { WUniqueFormat } from '../../base/unique-format'; import { WUniqueFormats } from '../../base/unique-formats'; import { EditorHistory } from '../editor-history/editor-history'; import { FootEndNoteNumberFormat, FootnoteRestartIndex } from '../../base/types'; +import { SelectionHeaderFooter } from '../selection'; +import { HeaderFooterWidget } from '../viewer/page'; /* eslint-disable */ /** * @private @@ -14,6 +16,7 @@ export class WSectionFormat { private static uniqueFormatType: number = 10; public ownerBase: Object; public columns: WColumnFormat[] = []; + public removedHeaderFooters: HeaderFooterWidget[]; public get headerDistance(): number { return this.getPropertyValue('headerDistance') as number; @@ -159,10 +162,58 @@ export class WSectionFormat { public set breakCode(value: string) { this.setPropertyValue('breakCode', value); } + public set firstPageHeader(value: SelectionHeaderFooter) { + this.setPropertyValue('firstPageHeader', value); + } + + public get firstPageHeader(): SelectionHeaderFooter { + return this.getPropertyValue('firstPageHeader') as SelectionHeaderFooter; + } + + public set firstPageFooter(value: SelectionHeaderFooter) { + this.setPropertyValue('firstPageFooter', value); + } + + public get firstPageFooter(): SelectionHeaderFooter { + return this.getPropertyValue('firstPageFooter') as SelectionHeaderFooter; + } + + public set oddPageHeader(value: SelectionHeaderFooter) { + this.setPropertyValue('oddPageHeader', value); + } + + public get oddPageHeader(): SelectionHeaderFooter { + return this.getPropertyValue('oddPageHeader') as SelectionHeaderFooter; + } + + public set oddPageFooter(value: SelectionHeaderFooter) { + this.setPropertyValue('oddPageFooter', value); + } + + public get oddPageFooter(): SelectionHeaderFooter { + return this.getPropertyValue('oddPageFooter') as SelectionHeaderFooter; + } + + public set evenPageHeader(value: SelectionHeaderFooter) { + this.setPropertyValue('evenPageHeader', value); + } + + public get evenPageHeader(): SelectionHeaderFooter { + return this.getPropertyValue('evenPageHeader') as SelectionHeaderFooter; + } + + public set evenPageFooter(value: SelectionHeaderFooter) { + this.setPropertyValue('evenPageFooter', value); + } + + public get evenPageFooter(): SelectionHeaderFooter { + return this.getPropertyValue('evenPageFooter') as SelectionHeaderFooter; + } public constructor(node?: Object) { this.ownerBase = node; this.columns = []; + this.removedHeaderFooters = []; } public destroy(): void { if (!isNullOrUndefined(this.uniqueSectionFormat)) { @@ -171,6 +222,7 @@ export class WSectionFormat { this.uniqueSectionFormat = undefined; this.ownerBase = undefined; this.columns = undefined; + this.removedHeaderFooters = undefined; } private hasValue(property: string): boolean { if (!isNullOrUndefined(this.uniqueSectionFormat)) { @@ -261,6 +313,24 @@ export class WSectionFormat { case 'breakCode': value = 'NewPage'; break; + case 'firstPageHeader': + value = undefined; + break; + case 'firstPageFooter': + value = undefined; + break; + case 'oddPageHeader': + value = undefined; + break; + case 'oddPageFooter': + value = undefined; + break; + case 'evenPageHeader': + value = undefined; + break; + case 'evenPageFooter': + value = undefined; + break; } return value; @@ -334,8 +404,10 @@ export class WSectionFormat { if (history && (history.isUndoing || history.isRedoing)) { this.uniqueSectionFormat = format.uniqueSectionFormat; this.columns = format.columns; + this.removedHeaderFooters = format.removedHeaderFooters; } else { if (!isNullOrUndefined(format)) { + this.removedHeaderFooters = format.removedHeaderFooters; if (!isNullOrUndefined(format.uniqueSectionFormat) && format.uniqueSectionFormat.propertiesHash) { this.updateUniqueSectionFormat(format); this.columns = format.columns; diff --git a/controls/documenteditor/src/document-editor/implementation/format/style.ts b/controls/documenteditor/src/document-editor/implementation/format/style.ts index f018bc5509..7d3ad7ac59 100644 --- a/controls/documenteditor/src/document-editor/implementation/format/style.ts +++ b/controls/documenteditor/src/document-editor/implementation/format/style.ts @@ -195,10 +195,20 @@ export class WStyles { for (const style of styles) { const returnStyle: any = {}; const returnStyleObject: any = {}; + 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); returnStyle.name = style.name; returnStyle.style = JSON.stringify(returnStyleObject); + if (!isNullOrUndefined(type)) { + returnStyle.type = type; + if (returnStyle.type == "Paragraph" && !isNullOrUndefined(style.link)){ + returnStyle.type = "Linked"; + } + } styleObjects.push(returnStyle); } return styleObjects; diff --git a/controls/documenteditor/src/document-editor/implementation/print.ts b/controls/documenteditor/src/document-editor/implementation/print.ts index 4e1aae2391..786d7571f3 100644 --- a/controls/documenteditor/src/document-editor/implementation/print.ts +++ b/controls/documenteditor/src/document-editor/implementation/print.ts @@ -10,6 +10,7 @@ export class Print { private getModuleName(): string { return 'Print'; } + private windowPrint: Window = undefined; /** * Prints the current viewer @@ -44,6 +45,7 @@ export class Print { if (isNullOrUndefined(printWindow)) { printWindow = window.open('', 'print', 'height=452,width=1024,tabbar=no'); } + this.windowPrint = printWindow; let pageSize: string = width.toString() + 'px ' + height.toString() + 'px'; if (width > height) { pageSize = 'landscape'; @@ -51,20 +53,21 @@ export class Print { if (browserUserAgent.indexOf('Chrome') !== -1) { // Chrome printWindow.document.write(''); - printWindow.document.write('
'); + printWindow.document.write('' + documentHelper.owner.documentName + '
'); } else if (browserUserAgent.indexOf('Firefox') !== -1) { // Firefox printWindow.document.write(''); - printWindow.document.write('
'); + printWindow.document.write('' + documentHelper.owner.documentName + '
'); } else { // Internet Explorer and Edge - printWindow.document.write('
'); + printWindow.document.write('' + documentHelper.owner.documentName + '
'); } printWindow.document.write(printElement.innerHTML + '
'); printElement = undefined; printWindow.document.close(); printWindow.focus(); + window.addEventListener('beforeunload', this.closePrintWindow); const interval: number = setInterval( () => { // eslint-disable-next-line @@ -76,7 +79,11 @@ export class Print { }, 500); } - + private closePrintWindow = (): void => { + if (this.windowPrint && !this.windowPrint.closed) { + this.windowPrint.close(); + } + } /** * Generate Document Image. * @@ -165,6 +172,8 @@ export class Print { * @returns {void} */ public destroy(): void { + window.removeEventListener('beforeunload', this.closePrintWindow); + this.windowPrint = undefined; return; } } diff --git a/controls/documenteditor/src/document-editor/implementation/restrict-editing/restrict-editing-pane.ts b/controls/documenteditor/src/document-editor/implementation/restrict-editing/restrict-editing-pane.ts index 06807f14b5..e9a08faf51 100644 --- a/controls/documenteditor/src/document-editor/implementation/restrict-editing/restrict-editing-pane.ts +++ b/controls/documenteditor/src/document-editor/implementation/restrict-editing/restrict-editing-pane.ts @@ -234,8 +234,7 @@ export class RestrictEditing { let highlightRegionInput: HTMLInputElement = createElement('input', { attrs: { type: 'checkbox' }, className: 'e-btn e-de-rp-nav-btn' }); highlightRegion.appendChild(highlightRegionInput); this.stopReadOnlyOptions.appendChild(highlightRegion); - - this.highlightCheckBox = new CheckBox({ label: localObj.getConstant('Highlight the regions I can edit') ,enableRtl:this.documentHelper.owner.enableRtl }, highlightRegionInput); + this.highlightCheckBox = new CheckBox({ label: localObj.getConstant('Highlight the regions I can edit') ,change: this.changeHighlightOptions.bind(this),enableRtl:this.documentHelper.owner.enableRtl }, highlightRegionInput,); let lastButtonDiv: HTMLElement = createElement('div', { className: 'e-de-rp-enforce' }); this.stopProtection = createElement('button', { innerHTML: localObj.getConstant('Stop Protection'), @@ -282,6 +281,12 @@ export class RestrictEditing { this.protectionTypeDrop.addEventListener('change', this.protectionTypeDropChanges.bind(this)); this.highlightCheckBox.addEventListener('change', this.highlightClicked.bind(this)); } + private changeHighlightOptions (): void { + this.documentHelper.owner.documentEditorSettings.highlightEditableRanges = this.highlightCheckBox.checked; + setTimeout((): void => { + this.documentHelper.owner.focusIn(); + }, 10); + } /* eslint-disable @typescript-eslint/no-explicit-any */ private enableFormatting(args: any): void { this.documentHelper.restrictFormatting = !args.checked; @@ -407,7 +412,7 @@ export class RestrictEditing { this.protectionTypeDrop.value = 'Tracked changes'; break; } - this.highlightCheckBox.checked = true; + this.highlightCheckBox.checked = this.documentHelper.owner.documentEditorSettings.highlightEditableRanges; this.addedUser.enablePersistence = true; this.addedUser.dataSource = this.usersCollection.slice(); this.addedUser.dataBind(); diff --git a/controls/documenteditor/src/document-editor/implementation/selection/selection-format.ts b/controls/documenteditor/src/document-editor/implementation/selection/selection-format.ts index efc45279e6..445f1150c9 100644 --- a/controls/documenteditor/src/document-editor/implementation/selection/selection-format.ts +++ b/controls/documenteditor/src/document-editor/implementation/selection/selection-format.ts @@ -3,14 +3,15 @@ import { TextAlignment, Underline, HighlightColor, BaselineAlignment, WidthType, Strikethrough, LineSpacingType, CellVerticalAlignment, HeightType, TableAlignment, BiDirectionalOverride, FootEndNoteNumberFormat, FootnoteRestartIndex, - FontScriptType + FontScriptType, + HeaderFooterType } from '../../base/types'; import { WSectionFormat, WCharacterFormat, WParagraphFormat, WTableFormat, WRowFormat, WCellFormat, WShading, WColumnFormat } from '../format/index'; -import { DocumentHelper, HelperMethods } from '../index'; +import { DocumentHelper, HelperMethods, PageLayoutViewer } from '../index'; import { isNullOrUndefined } from '@syncfusion/ej2-base'; -import { TableWidget, ImageElementBox, ListTextElementBox } from '../viewer/page'; +import { TableWidget, ImageElementBox, ListTextElementBox, HeaderFooterWidget, HeaderFooters } from '../viewer/page'; import { Editor } from '../index'; import { EditorHistory } from '../editor-history/index'; import { ModifiedLevel } from '../editor-history/history-helper'; @@ -1682,6 +1683,59 @@ export class SelectionParagraphFormat { } } } +export class SelectionHeaderFooter { + + private linkToPreviousIn: boolean = true; + private selection: Selection; + /** + * Gets or sets a value indicating whether this header footer is linked to the previous section header footer in the document. + * + * @default true + * @aspType bool + * @returns {boolean} Returns `true` if the header footer is linked to the previous section header footer; Otherwise `false`. + */ + public set linkToPrevious (value: boolean) { + this.linkToPreviousIn = value; + this.notifyPropertyChanged('linkToPrevious'); + } + + public get linkToPrevious (): boolean { + return this.linkToPreviousIn; + } + + + constructor(selection?: Selection) { + this.selection = selection; + } + + private notifyPropertyChanged(propertyName: string): void { + const selection: Selection = this.selection; + if (!isNullOrUndefined(selection) && (selection.isCleared || selection.owner.isPastingContent + || selection.owner.isReadOnlyMode || !selection.owner.isDocumentLoaded) + && !selection.isRetrieveFormatting) { + return; + } + if (!isNullOrUndefined(selection) && !isNullOrUndefined(selection.start) && !selection.isRetrieveFormatting) { + const value: Object = this.getPropertyvalue(propertyName); + if (!isNullOrUndefined(value)) { + const headerFooterWidget: HeaderFooterWidget = selection.start.paragraph.containerWidget as HeaderFooterWidget; + let sectionIndex: number = headerFooterWidget.sectionIndex; + let headerFooterType: HeaderFooterType = headerFooterWidget.headerFooterType; + selection.owner.editorModule.removeInlineHeaderFooterWidget(sectionIndex, headerFooterType, propertyName, value); + } + } + } + + + private getPropertyvalue(propertyName: string): Object { + if (propertyName == "linkToPrevious") { + if (!isNullOrUndefined(this.linkToPrevious)) { + return this.linkToPrevious; + } + } + return undefined; + } +} /** * Selection section format implementation */ @@ -1709,6 +1763,12 @@ export class SelectionSectionFormat { private lineBetweenColumnsIn: boolean; private columnsIn: SelectionColumnFormat[]; private breakCodeIn: string; + private firstPageHeaderIn: SelectionHeaderFooter; + private firstPageFooterIn: SelectionHeaderFooter; + private oddPageHeaderIn: SelectionHeaderFooter; + private oddPageFooterIn: SelectionHeaderFooter; + private evenPageHeaderIn: SelectionHeaderFooter; + private evenPageFooterIn: SelectionHeaderFooter; /** * private @@ -1833,6 +1893,75 @@ export class SelectionSectionFormat { this.headerDistanceIn = value; this.notifyPropertyChanged('headerDistance'); } + /** + * Gets the first page header of the section. + * + * @aspType SelectionHeaderFooter + */ + + public set firstPageHeader(value: SelectionHeaderFooter) { + this.firstPageHeaderIn = value; + } + + public get firstPageHeader():SelectionHeaderFooter { + return this.firstPageHeaderIn; + } + /** + * Gets the first page footer of the section. + * + * @aspType SelectionHeaderFooter + */ + + public set firstPageFooter(value: SelectionHeaderFooter) { + this.firstPageFooterIn = value; + } + public get firstPageFooter():SelectionHeaderFooter { + return this.firstPageFooterIn; + } + /** + * Gets the odd page header of the section. + * + * @aspType SelectionHeaderFooter + */ + public set oddPageHeader(value: SelectionHeaderFooter) { + this.oddPageHeaderIn = value; + } + public get oddPageHeader():SelectionHeaderFooter { + return this.oddPageHeaderIn; + } + /** + * Gets the odd page footer of the section. + * + * @aspType SelectionHeaderFooter + */ + public set oddPageFooter(value: SelectionHeaderFooter) { + this.oddPageFooterIn = value; + } + public get oddPageFooter():SelectionHeaderFooter { + return this.oddPageFooterIn; + } + /** + * Gets the even page header of the section. + * + * @aspType SelectionHeaderFooter + */ + public set evenPageHeader(value: SelectionHeaderFooter) { + this.evenPageHeaderIn = value; + } + public get evenPageHeader():SelectionHeaderFooter { + return this.evenPageHeaderIn; + } + /** + * Gets the even page footer of the section. + * + * @aspType SelectionHeaderFooter + */ + public set evenPageFooter(value: SelectionHeaderFooter) { + this.evenPageFooterIn = value; + } + public get evenPageFooter():SelectionHeaderFooter { + return this.evenPageFooterIn; + } /** * Gets or sets the starting page number. * @@ -2074,6 +2203,12 @@ export class SelectionSectionFormat { */ constructor(selection: Selection) { this.selection = selection; + this.firstPageHeaderIn = new SelectionHeaderFooter(selection); + this.firstPageFooterIn = new SelectionHeaderFooter(selection); + this.oddPageHeaderIn = new SelectionHeaderFooter(selection); + this.oddPageFooterIn = new SelectionHeaderFooter(selection); + this.evenPageHeaderIn = new SelectionHeaderFooter(selection); + this.evenPageFooterIn = new SelectionHeaderFooter(selection); } /** * Copies the format. @@ -2112,6 +2247,74 @@ export class SelectionSectionFormat { this.columns.push(selectCol); } this.breakCode = format.breakCode; + if (this.selection.owner.enableHeaderAndFooter) { + let headerFootersColletion: HeaderFooters[] = this.selection.documentHelper.headersFooters; + const headerFooterWidget: HeaderFooterWidget = this.selection.start.paragraph.containerWidget as HeaderFooterWidget; + let sectionIndex: number = headerFooterWidget.sectionIndex; + let headerFooterType: HeaderFooterType = headerFooterWidget.headerFooterType; + let isLinkedToPrevious: boolean = false; + if (sectionIndex == 0) { + this.oddPageHeader.linkToPrevious = false; + this.oddPageFooter.linkToPrevious = false; + this.evenPageHeader.linkToPrevious = false; + this.evenPageFooter.linkToPrevious = false; + this.firstPageHeader.linkToPrevious = false; + this.firstPageFooter.linkToPrevious = false; + } + else if (headerFootersColletion[sectionIndex]) { + let index: number = (this.selection.viewer as PageLayoutViewer).getHeaderFooter(headerFooterType); + let headerFooterWidget: HeaderFooterWidget = headerFootersColletion[sectionIndex][index]; + if (isNullOrUndefined(headerFooterWidget)) { + isLinkedToPrevious = true; + } + if (!isNullOrUndefined(headerFooterWidget) || isLinkedToPrevious) { + switch (headerFooterType) { + case "OddHeader": + if (isLinkedToPrevious) { + this.oddPageHeader.linkToPrevious = true; + } else { + this.oddPageHeader.linkToPrevious = false; + } + break; + case "OddFooter": + if (isLinkedToPrevious) { + this.oddPageFooter.linkToPrevious = true; + } else { + this.oddPageFooter.linkToPrevious = false; + } + break; + case "EvenHeader": + if (isLinkedToPrevious) { + this.evenPageHeader.linkToPrevious = true; + } else { + this.evenPageHeader.linkToPrevious = false; + } + break; + case "EvenFooter": + if (isLinkedToPrevious) { + this.evenPageFooter.linkToPrevious = true; + } else { + this.evenPageFooter.linkToPrevious = false; + } + break; + case "FirstPageHeader": + if (isLinkedToPrevious) { + this.firstPageHeader.linkToPrevious = true; + } else { + this.firstPageHeader.linkToPrevious = false; + } + break; + case "FirstPageFooter": + if (isLinkedToPrevious) { + this.firstPageFooter.linkToPrevious = true; + } else { + this.firstPageFooter.linkToPrevious = false; + } + break; + } + } + } + } } private applyColumnFormat(): void { @@ -2329,6 +2532,12 @@ export class SelectionSectionFormat { this.restartIndexForEndnotesIn = undefined; this.initialEndNoteNumber = undefined; this.initialFootNoteNumber = undefined; + this.firstPageHeaderIn = undefined; + this.firstPageFooterIn = undefined; + this.oddPageHeaderIn = undefined; + this.oddPageFooterIn = undefined; + this.evenPageHeaderIn = undefined; + this.evenPageFooterIn = undefined; } } /** @@ -3263,6 +3472,30 @@ export class SelectionImageFormat { } return 0; } + /** + * Gets the alternateText of the image. + * + * @aspType string + * @returns {string} - Returns image alternateText + */ + public get alternateText(): string { + if (this.image) { + return this.image.alternateText; + } + return null; + } + /** + * Sets the alternateText of the image. + * + * @aspType string + * @returns {string} - Returns image alternateText + */ + public set alternateText(value: string) { + if (value === this.alternateText) { + return; + } + this.image.alternateText = value; + } /** * @param {Selection} selection - Specifies selecion module * @private @@ -3279,20 +3512,31 @@ export class SelectionImageFormat { * @returns {void} */ public resize(width: number, height: number): void { - this.updateImageFormat(width, height); + this.updateImageFormat(width, height,this.alternateText); + } + /** + * update the image based on given alternateText. + * + * @param {string} alternateText - Specified the image alternateText + * @private + * @returns {void} + */ + public applyImageAlternativeText(alternateText: string): void { + this.updateImageFormat(this.width,this.height,alternateText); } /** * Update image width and height * * @param {number} width - Specified the image width * @param {number} height - Specifies the image height + * @param {string} alternateText - Specofies the image alternateText * @private * @returns {void} */ - public updateImageFormat(width: number, height: number): void { + public updateImageFormat(width: number, height: number,alternateText: string): void { if (this.image) { if (this.selection.owner.editorModule) { - this.selection.owner.editorModule.onImageFormat(this.image, width, height); + this.selection.owner.editorModule.onImageFormat(this.image, width, height,alternateText); } } } 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 9d2a17d9de..7037022db0 100644 --- a/controls/documenteditor/src/document-editor/implementation/selection/selection-helper.ts +++ b/controls/documenteditor/src/document-editor/implementation/selection/selection-helper.ts @@ -2327,6 +2327,10 @@ export class ImageInfo { * @private */ public height: number = 0; + /** + * @private + */ + public alternatetext: string; /** * Constructor for image format class * @@ -2335,6 +2339,7 @@ export class ImageInfo { constructor(imageContainer: ImageElementBox) { this.width = imageContainer.width; this.height = imageContainer.height; + this.alternatetext = imageContainer.alternateText; } /** * Dispose the internal objects which are maintained. @@ -2344,5 +2349,6 @@ export class ImageInfo { public destroy(): void { this.width = undefined; this.height = undefined; + this.alternatetext = undefined; } } diff --git a/controls/documenteditor/src/document-editor/implementation/selection/selection.ts b/controls/documenteditor/src/document-editor/implementation/selection/selection.ts index c3cae4a0f7..7900f3eaaf 100644 --- a/controls/documenteditor/src/document-editor/implementation/selection/selection.ts +++ b/controls/documenteditor/src/document-editor/implementation/selection/selection.ts @@ -22,7 +22,7 @@ import { Dictionary } from '../../base/dictionary'; import { LineSpacingType, BaselineAlignment, HighlightColor, Strikethrough, Underline, TextAlignment, FormFieldType, FormFieldFillEventArgs, contentControlEvent, - beforeFormFieldFillEvent, afterFormFieldFillEvent, requestNavigateEvent, CharacterRangeType + beforeFormFieldFillEvent, afterFormFieldFillEvent, requestNavigateEvent, CharacterRangeType, HeaderFooterType } from '../../base/index'; import { TextPositionInfo, PositionInfo, ParagraphInfo } from '../editor/editor-helper'; import { WCharacterFormat, WParagraphFormat, WStyle, WParagraphStyle, WSectionFormat } from '../index'; @@ -54,7 +54,10 @@ export class Selection { * @private */ public isImageSelected: boolean = false; - private documentHelper: DocumentHelper; + /** + * @private + */ + public documentHelper: DocumentHelper; private contextTypeInternal: ContextType = undefined; /** * @private @@ -573,7 +576,11 @@ export class Selection { } return bookmarkCln; } - private get viewer(): LayoutViewer { + /** + * + * @private + */ + public get viewer(): LayoutViewer { return this.owner.viewer; } @@ -2670,7 +2677,7 @@ export class Selection { this.owner.editor.applyFormTextFormat(previousField); if(!isNullOrUndefined(this.previousSelectedFormField)){ previousField = this.previousSelectedFormField; - } + } } previousFieldData = { 'fieldName': previousField.formFieldData.name, 'value': this.owner.editorModule.getFieldResultText(previousField) }; @@ -3165,7 +3172,7 @@ export class Selection { } } else { if (inline instanceof ElementBox && inline.nextNode instanceof ElementBox) { - text = text + this.getTextInline(inline.nextNode as ElementBox, endPosition.paragraph, undefined, 0, includeObject); + text = text + this.getTextInline(inline.nextNode as ElementBox, endPosition.paragraph, endInline, endIndex, includeObject); } else { let nextParagraphWidget: ParagraphWidget = this.documentHelper.selection.getNextParagraphBlock(startPosition.paragraph) as ParagraphWidget; @@ -5810,7 +5817,7 @@ export class Selection { const margin: Margin = element.margin; let top: number = 0; let left: number = 0; - if (element instanceof TextElementBox && (element as TextElementBox).text === '\v' && isNullOrUndefined(inline.nextNode)) { + if (element instanceof TextElementBox && (element as TextElementBox).text === '\v' && isNullOrUndefined(inline.nextNode) && !this.owner.editor.handledEnter) { lineWidget = this.getNextLineWidget(element.line.paragraph, element); index = 0; } else { @@ -6716,6 +6723,14 @@ export class Selection { let element: ElementBox = undefined; let index: number = 0; let isImageSelected: boolean = false; + if (this.owner.enableHeaderAndFooter) { + let headerFooterWidget: HeaderFooterWidget = this.start.paragraph.bodyWidget as HeaderFooterWidget; + if (headerFooterWidget.headerFooterType.indexOf('Header') != -1){ + this.comparePageWidthAndMargins(headerFooterWidget.page.headerWidget, headerFooterWidget.page); + } else { + this.comparePageWidthAndMargins(headerFooterWidget.page.footerWidget, headerFooterWidget.page); + } + } const isImageSelectedObj: TextPositionInfo = this.updateTextPositionIn(widget, element, index, point, false); if (!isNullOrUndefined(isImageSelectedObj)) { element = isImageSelectedObj.element; @@ -9472,10 +9487,13 @@ export class Selection { if (inline instanceof ImageElementBox || inline instanceof ShapeElementBox) { let width: number = inline.width; let height: number = inline.height; + let alternateText: string = inline.alternateText; inline.width = imageFormat.width; inline.height = imageFormat.height; + inline.alternateText = imageFormat.alternatetext; imageFormat.width = width; imageFormat.height = height; + imageFormat.alternatetext = alternateText; if (paragraph !== null && paragraph.containerWidget !== null && this.owner.editorModule) { let lineIndex: number = paragraph.childWidgets.indexOf(inline.line); let elementIndex: number = inline.line.children.indexOf(inline); @@ -9968,6 +9986,7 @@ export class Selection { break; } } else if (shift && !ctrl && !alt) { + this.documentHelper.isCompleted = false; switch (key) { case 33: event.preventDefault(); @@ -10208,12 +10227,50 @@ export class Selection { if (this.viewer instanceof PageLayoutViewer) { this.owner.enableHeaderAndFooter = true; widget.page = page; + this.comparePageWidthAndMargins(widget, page); this.updateTextPositionForBlockContainer(widget); this.shiftBlockOnHeaderFooterEnableDisable(); return true; } return false; } + /** + * /* Here is the explanation for the code below: + 1. When there are multiple sections in a document, the first section is the parent section of the other sections. + 2. If you change the page width or header distance of the parent section, the child section will inherit the page width or header distance of the parent section. + 3. So when you change the page width or header distance of the parent section, the child section should be relayouted. + * @private + */ + private comparePageWidthAndMargins(parentHFWidget: HeaderFooterWidget, page: Page):void { + let headerFooterType: HeaderFooterType = parentHFWidget.headerFooterType; + let currentHFWidget: HeaderFooterWidget; + let isHeader: boolean = headerFooterType.indexOf('Header') != -1; + let isRelayout: boolean = false; + if (isHeader) { + currentHFWidget = page.headerWidgetIn; + } else { + currentHFWidget = page.footerWidgetIn; + } + if(!isNullOrUndefined(currentHFWidget)) { + const parentSectionFormat: WSectionFormat = parentHFWidget.sectionFormat; + const currentSectionFormat: WSectionFormat = currentHFWidget.sectionFormat; + if (!isNullOrUndefined(parentSectionFormat) && !isNullOrUndefined(currentSectionFormat)) { + if (isHeader) { + if (parentHFWidget.width != currentHFWidget.width || parentSectionFormat.headerDistance != currentSectionFormat.headerDistance) { + isRelayout = true; + } + } else { + if (parentHFWidget.width != currentHFWidget.width || parentSectionFormat.footerDistance != currentSectionFormat.footerDistance) { + isRelayout = true; + } + } + } + if (isRelayout) { + (this.owner.viewer as PageLayoutViewer).updateHFClientArea(parentHFWidget.sectionFormat, isHeader); + parentHFWidget = this.documentHelper.layout.layoutHeaderFooterItems(this.owner.viewer, parentHFWidget); + } + } + } /** * @private */ @@ -10263,6 +10320,9 @@ export class Selection { this.editRegionHighlighters.clear(); } this.editRangeCollection = []; + if (this.selectedWidgets) { + this.selectedWidgets.clear(); + } } /** diff --git a/controls/documenteditor/src/document-editor/implementation/spell-check/spell-checker.ts b/controls/documenteditor/src/document-editor/implementation/spell-check/spell-checker.ts index 93a7cadd4a..93cdb27057 100644 --- a/controls/documenteditor/src/document-editor/implementation/spell-check/spell-checker.ts +++ b/controls/documenteditor/src/document-editor/implementation/spell-check/spell-checker.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -import { LayoutViewer, ContextElementInfo, TextPosition, ElementInfo, ErrorInfo, WCharacterFormat, SpecialCharacterInfo, SpaceCharacterInfo, TextSearchResults, TextInLineInfo, TextSearchResult, MatchResults, SfdtExport, TextExport, WordSpellInfo, HelperMethods } from '../index'; +import { LayoutViewer, ContextElementInfo, TextPosition, ElementInfo, ErrorInfo, WCharacterFormat, SpecialCharacterInfo, SpaceCharacterInfo, TextSearchResults, TextInLineInfo, TextSearchResult, MatchResults, SfdtExport, TextExport, WordSpellInfo } from '../index'; import { XmlHttpRequestEventArgs, beforeXmlHttpRequestSend } from './../../index'; import { Dictionary } from '../../base/dictionary'; import { ElementBox, TextElementBox, ErrorTextElementBox, LineWidget, TableCellWidget, Page, FieldElementBox } from '../viewer/page'; @@ -57,7 +57,7 @@ export class SpellChecker { */ public errorSuggestions: Dictionary; - private performOptimizedCheck: boolean = false; + private performOptimizedCheck: boolean = true; private textSearchResults: TextSearchResults; @@ -198,7 +198,7 @@ export class SpellChecker { this.documentHelper.selection.start = (dialogElement as ErrorTextElementBox).start.clone(); this.documentHelper.selection.end = (dialogElement as ErrorTextElementBox).end.clone(); if (content !== 'Ignore Once') { - content = HelperMethods.manageSpecialCharacters(exactText, content); + content = this.manageSpecialCharacters(exactText, content); this.documentHelper.owner.editor.insertTextInternal(content, true); this.documentHelper.selection.start.setPositionInternal(this.documentHelper.selection.end); this.documentHelper.clearSelectionHighlight(); @@ -313,7 +313,7 @@ export class SpellChecker { } else { exactText = textElement.text; } - exactText = HelperMethods.manageSpecialCharacters(exactText, undefined, true); + exactText = this.manageSpecialCharacters(exactText, undefined, true); if (textElement.ignoreOnceItems.indexOf(exactText) === -1) { textElement.ignoreOnceItems.push(exactText); } @@ -327,7 +327,7 @@ export class SpellChecker { */ public handleIgnoreAllItems(contextElement?: ContextElementInfo): void { const contextItem: ContextElementInfo = (!isNullOrUndefined(contextElement)) ? contextElement : this.retriveText(); - const retrievedText: string = HelperMethods.manageSpecialCharacters(contextItem.text, undefined, true); + const retrievedText: string = this.manageSpecialCharacters(contextItem.text, undefined, true); if (this.ignoreAllItems.indexOf(retrievedText) === -1) { this.ignoreAllItems.push(retrievedText); this.removeErrorsFromCollection(contextItem); @@ -345,7 +345,7 @@ export class SpellChecker { */ public handleAddToDictionary(contextElement?: ContextElementInfo): void { const contextItem: ContextElementInfo = (!isNullOrUndefined(contextElement)) ? contextElement : this.retriveText(); - const retrievedText: string = HelperMethods.manageSpecialCharacters(contextItem.text, undefined, true); + const retrievedText: string = this.manageSpecialCharacters(contextItem.text, undefined, true); /* eslint-disable @typescript-eslint/no-explicit-any */ this.callSpellChecker(this.languageID, retrievedText, false, false, true).then((data: any) => { @@ -356,7 +356,52 @@ export class SpellChecker { this.documentHelper.triggerSpellCheck = false; }); } + /** + * Method to append/remove special characters + * + * @private + */ + + public manageSpecialCharacters(exactText: string, replaceText: string, isRemove?: boolean): string { + if (!isNullOrUndefined(exactText)) { + if (isNullOrUndefined(replaceText)) { + replaceText = exactText; + } + const pattern: RegExp = new RegExp('^[#\\@\\!\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\\”\'\\,\\<\\.\\>\\/\\?\\`\\s\\’]+', 'g'); + let matches: RegExpExecArray[] = []; + let matchInfo: RegExpExecArray; + // eslint-disable no-cond-assign + while (!isNullOrUndefined(matchInfo = pattern.exec(exactText))) { + matches.push(matchInfo); + } + + if (matches.length > 0) { + for (let i: number = 0; i < matches.length; i++) { + /* eslint-disable @typescript-eslint/no-explicit-any */ + const match: any[] = matches[i]; + replaceText = (!isRemove) ? match[0] + replaceText : replaceText.replace(match[0], ''); + } + } + + const endPattern: RegExp = new RegExp('[#\\@\\!\\$\\%\\^\\&\\*\\(\\)\\-\\_\\+\\=\\{\\}\\[\\]\\:\\;\\"\\”\'\\,\\<\\.\\>\\/\\?\\s\\`\\’]+$', 'g'); + matches = []; + // eslint-disable no-cond-assign + while (!isNullOrUndefined(matchInfo = endPattern.exec(replaceText))) { + matches.push(matchInfo); + } + + if (matches.length > 0) { + for (let i: number = 0; i < matches.length; i++) { + /* eslint-disable @typescript-eslint/no-explicit-any */ + const match: any = matches[i]; + replaceText = (!isRemove) ? replaceText + match[0] : replaceText.slice(0, match.index); + } + } + } + + return replaceText; + } /** * Method to remove errors * @@ -465,7 +510,7 @@ export class SpellChecker { private updateStatusForGlobalErrors(erroElements: ErrorTextElementBox[], parentElement: ElementBox): void { if (erroElements.length > 0) { for (let i: number = 0; i < erroElements.length; i++) { - const exactText: string = HelperMethods.manageSpecialCharacters(erroElements[i].text, undefined, true); + const exactText: string = this.manageSpecialCharacters(erroElements[i].text, undefined, true); if (this.errorWordCollection.containsKey(exactText)) { const elements: ElementBox[] = this.errorWordCollection.get(exactText); for (let j: number = 0; j < elements.length; j++) { @@ -490,7 +535,7 @@ export class SpellChecker { */ public handleErrorCollection(errorInElement: TextElementBox): boolean { const errors: Dictionary = this.errorWordCollection; - const exactText: string = HelperMethods.manageSpecialCharacters(errorInElement.text, undefined, true); + const exactText: string = this.manageSpecialCharacters(errorInElement.text, undefined, true); if (errors.containsKey(exactText) && errorInElement.length > 1) { const ignoreAllIndex: number = this.ignoreAllItems.indexOf(exactText); if (ignoreAllIndex > -1) { @@ -551,7 +596,7 @@ export class SpellChecker { return { 'text': text, 'element': element }; } private addErrorCollection(text: string, elementToCompare: ElementBox, suggestions: string[]): void { - text = HelperMethods.manageSpecialCharacters(text, undefined, true); + text = this.manageSpecialCharacters(text, undefined, true); if (this.errorWordCollection.containsKey(text)) { const errorElements: ElementBox[] = this.errorWordCollection.get(text); if (elementToCompare instanceof ErrorTextElementBox) { @@ -574,7 +619,7 @@ export class SpellChecker { } } private addCorrectWordCollection(text: string): void { - text = HelperMethods.manageSpecialCharacters(text, undefined, true); + text = this.manageSpecialCharacters(text, undefined, true); if (!this.uniqueWordsCollection.containsKey(text)) { this.uniqueWordsCollection.add(text, false); } @@ -584,22 +629,7 @@ export class SpellChecker { */ public isInUniqueWords(text: string): boolean { text = text.replace(/[\s]+/g, ''); - text = text.replace('\r\n', ' '); - text = text.replace('\n', ' '); - text = text.replace('\r', ' '); - text = text.replace('\v', ' '); - text = text.replace('\t', ' '); - text = text.replace('/', ' '); - - let stringarr: string[] = text.split(' '); - let test: boolean = true; - for (let i: number = 0; i < stringarr.length; i++) { - if(!this.uniqueWordsCollection.containsKey(stringarr[i])){ - test = false; - break; - } - } - return test; + return this.uniqueWordsCollection.containsKey(text); } /** * @private @@ -626,7 +656,7 @@ export class SpellChecker { for (let i: number = 0; i < length; i++) { if (copyElement[i] instanceof ErrorTextElementBox) { if (copyElement[i].ischangeDetected) { - const exactText: string = HelperMethods.manageSpecialCharacters((copyElement[i] as TextElementBox).text, undefined, true); + const exactText: string = this.manageSpecialCharacters((copyElement[i] as TextElementBox).text, undefined, true); isChanged = true; this.removeErrorsFromCollection({ 'element': copyElement[i], 'text': exactText }); @@ -642,7 +672,7 @@ export class SpellChecker { if (isChanged) { - this.errorWordCollection.add(HelperMethods.manageSpecialCharacters(errorElement.text, undefined, true), [errorElement]); + this.errorWordCollection.add(this.manageSpecialCharacters(errorElement.text, undefined, true), [errorElement]); } return false; @@ -827,12 +857,12 @@ export class SpellChecker { if (splittedText.length > 1) { for (let i: number = 0; i < splittedText.length; i++) { let currentText: string = splittedText[i]; - currentText = HelperMethods.manageSpecialCharacters(currentText, undefined, true); + currentText = this.manageSpecialCharacters(currentText, undefined, true); this.documentHelper.render.handleUnorderedElements(currentText, elementBox, underlineY, i, 0, i === splittedText.length - 1, beforeIndex); } } else { - currentText = HelperMethods.manageSpecialCharacters(currentText, undefined, true); + currentText = this.manageSpecialCharacters(currentText, undefined, true); this.documentHelper.render.handleUnorderedElements(currentText, elementBox, underlineY, 0, 0, true, beforeIndex); } } @@ -1127,7 +1157,7 @@ export class SpellChecker { } private checkCombinedElementsBeIgnored(elements: TextElementBox[], exactText: string): boolean { - exactText = HelperMethods.manageSpecialCharacters(exactText, undefined, true); + exactText = this.manageSpecialCharacters(exactText, undefined, true); for (let i: number = 0; i < elements.length; i++) { if (elements[i].ignoreOnceItems.indexOf(exactText) !== -1) { return true; @@ -1204,9 +1234,6 @@ export class SpellChecker { this.uniqueSpelledWords = {}; } private checkForUniqueWords(spellData: any): void { - if (!this.uniqueWordsCollection.containsKey(spellData.Text)){ - this.uniqueWordsCollection.add(spellData.Text, spellData.HasSpellError); - } const identityMatched: boolean = this.uniqueSpelledWords[spellData.Text]; if (!identityMatched) { this.uniqueSpelledWords[spellData.Text] = spellData.HasSpellError; @@ -1240,29 +1267,16 @@ export class SpellChecker { * @returns {WordSpellInfo} - Retruns WordSpellInfo */ public checkSpellingInPageInfo(wordToCheck: string): WordSpellInfo { - // const hasError: boolean = false; - // const elementPresent: boolean = false; + const hasError: boolean = false; + const elementPresent: boolean = false; /* eslint-disable @typescript-eslint/no-explicit-any */ const uniqueWords: any = JSON.parse(localStorage.getItem(this.uniqueKey)); - let wordInfo: any = { hasSpellError: false, isElementPresent: true }; if (!isNullOrUndefined(uniqueWords)) { - wordToCheck = wordToCheck.replace(/[\s]+/g, ''); - wordToCheck = wordToCheck.replace('\r\n', ' '); - wordToCheck = wordToCheck.replace('\n', ' '); - wordToCheck = wordToCheck.replace('\r', ' '); - wordToCheck = wordToCheck.replace('\v', ' '); - wordToCheck = wordToCheck.replace('\t', ' '); - wordToCheck = wordToCheck.replace('/', ' '); - - let stringarr: string[] = wordToCheck.split(' '); - for (let i: number = 0; i < stringarr.length; i++) { - if(!this.uniqueWordsCollection.containsKey(stringarr[i])){ - wordInfo.hasSpellError = true; - break; - } + if (!isNullOrUndefined(uniqueWords[wordToCheck])) { + return { hasSpellError: uniqueWords[wordToCheck], isElementPresent: true }; } } - return wordInfo; + return { hasSpellError: hasError, isElementPresent: elementPresent }; } /** * @private diff --git a/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes-pane.ts b/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes-pane.ts index aa05974806..c82b6b95dd 100644 --- a/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes-pane.ts +++ b/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes-pane.ts @@ -141,7 +141,7 @@ export class TrackChangesPane { enableRtl: this.owner.enableRtl, items: [ { - template: this.locale.getConstant('User') + ':', cssClass: 'e-de-track-toolbar-overlay', disabled: true + text: this.locale.getConstant('User') + ':', cssClass: 'e-de-track-toolbar-overlay', disabled: true }, { template: createElement('div', { id: 'e-de-user-list' }) @@ -150,7 +150,7 @@ export class TrackChangesPane { type: 'Separator' }, { - template: this.locale.getConstant('View') + ':', cssClass: 'e-de-track-toolbar-overlay', disabled: true + text: this.locale.getConstant('View') + ':', cssClass: 'e-de-track-toolbar-overlay', disabled: true }, { template: createElement('div', { id: 'e-de-revision-list' }) @@ -374,11 +374,41 @@ export class TrackChangesPane { } return isUpdate; } + public updateCurrentTrackChanges(revision: Revision): void { + let currentChangeView: ChangesSingleView; + if (!isNullOrUndefined(revision)) { + currentChangeView = this.owner.trackChangesPane.changes.get(revision); + } + if (!isNullOrUndefined(currentChangeView) && revision.range.length > 0) { + let changesDiv = currentChangeView.singleInnerDiv.querySelector("#textDiv") as HTMLDivElement; + while (changesDiv.firstChild) { + changesDiv.removeChild(changesDiv.firstChild); + } + currentChangeView.layoutElementText(revision.range, changesDiv); + } + } public updateTrackChanges(show?: boolean): void { if (show || isNullOrUndefined(show)) { - this.tableRevisions.clear(); - this.renderedChanges.clear(); - this.removeAllChanges(); + if (this.owner.documentHelper.layout.isInitialLoad) { + this.tableRevisions.clear(); + this.renderedChanges.clear(); + this.removeAllChanges(); + } else { + for (let i: number = 0; i < this.tableRevisions.keys.length; i++) { + let revision: Revision = this.tableRevisions.keys[i]; + let index: number = this.revisions.indexOf(revision); + let removeChild: boolean = (this.tableRevisions.get(revision))[(this.tableRevisions.get(revision)).length -1] === revision; + if (!isNullOrUndefined(this.changesInfoDiv.childNodes[index + 1]) && removeChild) { + this.changesInfoDiv.removeChild(this.changesInfoDiv.childNodes[index + 1]); + } + if (this.renderedChanges.containsKey(revision)) { + this.renderedChanges.remove(revision); + } + this.changes.remove(revision); + this.revisions.splice(index, 1); + } + this.tableRevisions.clear(); + } if (!this.enableButtons && !this.menuoptionEle.classList.contains('e-de-overlay')) { this.menuoptionEle.classList.add('e-de-overlay'); } else if (this.menuoptionEle.classList.contains('e-de-overlay') && !this.owner.documentHelper.isDocumentProtected && !this.owner.isReadOnly) { @@ -386,39 +416,85 @@ export class TrackChangesPane { } this.isChangesTabVisible = true; this.owner.notify('reviewPane', { comment: this.commentReviewPane.isCommentTabVisible, changes: this.isChangesTabVisible}); - for (let i: number = 0; i < this.owner.revisions.changes.length; i++) { - let revision: Revision = this.owner.revisions.changes[i]; - let ranges: object = this.owner.revisions.changes[i].range[0]; - if(this.changes.containsKey(revision)) { - continue; - } - if (ranges instanceof WRowFormat) { - let groupedRevision: Revision[] = this.groupTableRevisions(this.owner.revisions.changes, i); - if (groupedRevision.length > 1) { - let changeView: ChangesSingleView; - for (let j: number = 0; j < groupedRevision.length; j++) { - let nextRevision: Revision = groupedRevision[j]; - if (j === 0) { - this.addChanges(nextRevision); - changeView = this.changes.get(revision); - } else { - let nextRowFormat: WRowFormat = nextRevision.range[0] as WRowFormat; - changeView.appendRowToTable(nextRowFormat, j); - this.revisions.push(nextRevision); - this.changes.add(nextRevision, changeView); + if (this.owner.documentHelper.layout.isInitialLoad) { + for (let i: number = 0; i < this.owner.revisions.changes.length; i++) { + let revision: Revision = this.owner.revisions.changes[i]; + let ranges: object = this.owner.revisions.changes[i].range[0]; + if (this.changes.containsKey(revision)) { + continue; + } + if (ranges instanceof WRowFormat) { + let groupedRevision: Revision[] = this.groupTableRevisions(this.owner.revisions.changes, i); + if (groupedRevision.length > 1) { + let changeView: ChangesSingleView; + for (let j: number = 0; j < groupedRevision.length; j++) { + let nextRevision: Revision = groupedRevision[j]; + if (j === 0) { + this.addChanges(nextRevision); + changeView = this.changes.get(revision); + } else { + let nextRowFormat: WRowFormat = nextRevision.range[0] as WRowFormat; + changeView.appendRowToTable(nextRowFormat, j); + this.revisions.push(nextRevision); + this.changes.add(nextRevision, changeView); + } + this.tableRevisions.add(nextRevision, groupedRevision); } - this.tableRevisions.add(nextRevision, groupedRevision); + } else { + this.addChanges(revision); } } else { this.addChanges(revision); } - } else { - this.addChanges(revision); + } + for (let i = 0; i < this.renderedChanges.keys.length; i++) { + let changeView: ChangesSingleView = this.renderedChanges.get(this.renderedChanges.keys[i]); + changeView.updateRevisionIndexAndCount(i + 1, this.renderedChanges.keys.length); } } - for (let i = 0; i < this.renderedChanges.keys.length; i++) { - let changeView: ChangesSingleView = this.renderedChanges.get(this.renderedChanges.keys[i]); - changeView.updateRevisionIndexAndCount(i + 1, this.renderedChanges.keys.length); + else { + for (let i: number = 0; i < this.owner.revisions.changes.length; i++) { + let revision: Revision = this.owner.revisions.changes[i]; + let ranges: object = this.owner.revisions.changes[i].range[0]; + if (this.changes.containsKey(revision)) { + continue; + } + if (ranges instanceof WRowFormat) { + let groupedRevision: Revision[] = this.groupTableRevisions(this.owner.revisions.changes, i); + if (groupedRevision.length > 1) { + let changeView: ChangesSingleView; + for (let j: number = 0; j < groupedRevision.length; j++) { + let nextRevision: Revision = groupedRevision[j]; + if (j === 0) { + let currentChangeView: ChangesSingleView = new ChangesSingleView(this.owner, this); + this.changesInfoDiv.insertBefore(currentChangeView.createSingleChangesDiv(nextRevision), this.changesInfoDiv.children[i + 1]); + this.revisions.splice(i, 0, nextRevision); + this.changes.add(nextRevision, currentChangeView); + this.renderedChanges.add(nextRevision, currentChangeView); + changeView = this.changes.get(revision); + } else { + let nextRowFormat: WRowFormat = nextRevision.range[0] as WRowFormat; + changeView.appendRowToTable(nextRowFormat, j); + this.revisions.splice(i, 0, nextRevision); + this.changes.add(nextRevision, changeView); + } + this.tableRevisions.add(nextRevision, groupedRevision); + } + } else { + let currentChangeView: ChangesSingleView = new ChangesSingleView(this.owner, this); + this.changesInfoDiv.insertBefore(currentChangeView.createSingleChangesDiv(revision), this.changesInfoDiv.children[i + 1]); + this.revisions.splice(i, 0, revision); + this.changes.add(revision, currentChangeView); + this.renderedChanges.add(revision, currentChangeView); + } + } + } + let totalCount = document.getElementsByClassName('e-de-track-chngs-count').length; + for (let i: number = 0; i < totalCount; i++) { + let div = document.getElementsByClassName('e-de-track-chngs-count')[i]; + div.innerHTML = this.locale.getConstant('Changes') + ' ' + (i + 1).toString() + + ' ' + this.locale.getConstant('of') + ' ' + totalCount.toString(); + } } this.sortCollectionToDisplay(); this.updateUsers(); @@ -742,7 +818,7 @@ export class ChangesSingleView { }); this.singleInnerDiv.appendChild(dateView); - let changesTextDiv: HTMLElement = createElement('div', { + let changesTextDiv: HTMLElement = createElement('div', { id:'textDiv', className: 'e-de-track-chngs-text' }); this.layoutElementText(revision.range, changesTextDiv); @@ -812,7 +888,7 @@ export class ChangesSingleView { } } - private layoutElementText(range: object[], changesText: HTMLElement): void { + public layoutElementText(range: object[], changesText: HTMLElement): void { changesText.style.width = '100%'; let text: string = ''; let toSkip: boolean = false; @@ -912,8 +988,12 @@ export class ChangesSingleView { } private removeFromParentCollec(): void { - this.trackChangesPane.changes.remove(this.revision); - this.trackChangesPane.revisions.splice(this.trackChangesPane.revisions.indexOf(this.revision), 1); + if (this.trackChangesPane.changes.containsKey(this.revision)) { + this.trackChangesPane.changes.remove(this.revision); + } + if (this.trackChangesPane.revisions.indexOf(this.revision) !== -1) { + this.trackChangesPane.revisions.splice(this.trackChangesPane.revisions.indexOf(this.revision), 1); + } if (this.trackChangesPane.changes.length === 0) { this.trackChangesPane.setNoChangesVisibility = true; } diff --git a/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes.ts b/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes.ts index f0d797475c..dabac1ed71 100644 --- a/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes.ts +++ b/controls/documenteditor/src/document-editor/implementation/track-changes/track-changes.ts @@ -9,6 +9,8 @@ import { Selection, TextPosition } from '../selection'; import { ParagraphInfo } from '../editor/editor-helper'; import { BaseHistoryInfo, EditorHistory } from '../editor-history'; import { RevisionActionEventArgs, revisionActionEvent } from '../../base/index'; +import { ChangesSingleView } from '../track-changes/track-changes-pane'; + /** * The revision class which holds the information related to changes made in the document */ @@ -54,6 +56,9 @@ export class Revision { private skipUnLinkElement: boolean = false; public constructor(documentHelper: DocumentEditor, author: string, date: string) { this.author = author; + if(isNullOrUndefined(this.author)) { + this.author = "Unknown"; + } this.date = date; this.owner = documentHelper; } @@ -268,6 +273,7 @@ export class Revision { this.owner.editor.deleteSelectedContents(this.owner.selection, true); let rangeIndex: number = revision.range.indexOf(item); revision.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(revision); while (this.range.length > 0) { this.removeRangeRevisionForItem(this.range[0]); } @@ -322,6 +328,7 @@ export class Revision { if (this.revisionID !== currentRevision.revisionID) { let rangeIndex: number = currentRevision.range.indexOf(item); item.revisions[revisionIndex].range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(item.revisions[revisionIndex]); } if (currentRevision.range.length === 0) { this.owner.revisions.remove(currentRevision); @@ -343,6 +350,7 @@ export class Revision { item.revisions.splice(revisionIndex, 1); let rangeIndex: number = this.range.indexOf(item); this.range.splice(rangeIndex, 1); + this.owner.trackChangesPane.updateCurrentTrackChanges(this); } } /** @@ -476,6 +484,21 @@ export class RevisionCollection { return; } this.changes.splice(this.changes.indexOf(revision), 1); + if (this.owner.trackChangesPane.revisions.indexOf(revision) !== -1) { + let index: number = this.owner.trackChangesPane.revisions.indexOf(revision); + let removeChild: boolean = !(this.owner.trackChangesPane.tableRevisions.containsKey(revision) && (this.owner.trackChangesPane.tableRevisions.get(revision))[(this.owner.trackChangesPane.tableRevisions.get(revision)).length -1] !== revision); + if (!isNullOrUndefined(this.owner.trackChangesPane.changesInfoDiv.childNodes[index + 1]) && removeChild) { + this.owner.trackChangesPane.changesInfoDiv.removeChild(this.owner.trackChangesPane.changesInfoDiv.childNodes[index + 1]); + } + this.owner.trackChangesPane.revisions.splice(index, 1); + this.owner.trackChangesPane.changes.remove(revision); + if (this.owner.trackChangesPane.renderedChanges.containsKey(revision)) { + this.owner.trackChangesPane.renderedChanges.remove(revision); + } + if (this.owner.trackChangesPane.tableRevisions.containsKey(revision)) { + this.owner.trackChangesPane.tableRevisions.remove(revision); + } + } } /** @@ -543,8 +566,7 @@ export class RevisionCollection { this.owner.editorHistory.updateComplexHistory(); if(isNullOrUndefined(selection.editPosition)) { this.owner.editorHistory.undoStack.pop(); - } - + } } this.owner.editor.reLayout(this.owner.selection, false); this.skipGroupAcceptReject = false; diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts b/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts index 349ff5ceae..23d6b31579 100644 --- a/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts +++ b/controls/documenteditor/src/document-editor/implementation/viewer/layout.ts @@ -40,6 +40,10 @@ export class Layout { * @private */ public islayoutFootnote: boolean = false; + /** + * @private + */ + public isMultiColumnDoc: boolean = false; /** * @private */ @@ -290,6 +294,7 @@ export class Layout { this.maxTextBaseline = undefined; this.isFieldCode = undefined; this.footnoteHeight = undefined; + this.isMultiColumnDoc = undefined; } public layoutItems(sections: BodyWidget[], isReLayout: boolean, isContinuousSection?: boolean): void { @@ -298,6 +303,9 @@ export class Layout { let width: number = 0; for (let i: number = 0; i < sections.length; i++) { const section: BodyWidget = sections[i] as BodyWidget; + if(section.sectionFormat.numberOfColumns > 1) { + this.isMultiColumnDoc = true; + } const nextSection: BodyWidget = sections[i + 1] as BodyWidget; this.viewer.columnLayoutArea.setColumns(section.sectionFormat); let lastpage: Page = this.documentHelper.pages[this.documentHelper.pages.length - 1]; @@ -827,7 +835,7 @@ export class Layout { page.headerWidget = this.layoutHeaderFooterItems(viewer, header); //this.updateHeaderFooterToParent(header); //When the vertical position is related to margin, then it should be adjusted based on the layouted header height. Not default header height. - if (section.sectionFormat.topMargin < page.boundingRectangle.bottom && page.headerWidget.floatingElements.length > 0) + if (section.sectionFormat.topMargin < page.boundingRectangle.bottom && page.headerWidget.floatingElements.length > 0 && (page.headerWidget.floatingElements[0] as ImageElementBox).textWrappingStyle !== "Behind") { page.headerWidget = this.shiftItemsForVerticalAlignment(page.headerWidget); } @@ -1122,7 +1130,7 @@ export class Layout { return nextBlock.nextRenderedWidget as BlockWidget; } private updateTableYPositionBasedonTextWrap(table: TableWidget): void { - if (!isNullOrUndefined(table.bodyWidget)) { + if (!isNullOrUndefined(table.bodyWidget) && !(table.containerWidget instanceof TextFrame)) { const tableY: number = table.y; const tableRect: Rect = new Rect(table.x, table.y, table.width, table.height); table.bodyWidget.floatingElements.forEach((shape: ShapeElementBox | TableWidget) => { @@ -1686,6 +1694,9 @@ export class Layout { } /* eslint-disable */ private layoutElement(element: ElementBox, paragraph: ParagraphWidget, isEmptyField?: boolean): void { + if(element.isPageBreak && paragraph.isInHeaderFooter) { + return; + } let line: LineWidget = element.line; let text: string = ''; let index: number = element.indexInOwner; @@ -1744,7 +1755,9 @@ export class Layout { } } else if (element.bookmarkType === 1 && this.documentHelper.bookmarks.containsKey(element.name)) { let bookmrkElement: BookmarkElementBox = this.documentHelper.bookmarks.get(element.name); - if (isNullOrUndefined(bookmrkElement.reference) || isNullOrUndefined(bookmrkElement.reference.paragraph.bodyWidget)) { + if (isNullOrUndefined(bookmrkElement.reference) + || isNullOrUndefined(bookmrkElement.reference.paragraph) + || isNullOrUndefined(bookmrkElement.reference.paragraph.bodyWidget)) { bookmrkElement.reference = element; element.reference = bookmrkElement; } @@ -1793,6 +1806,44 @@ export class Layout { } } } + if (element instanceof EditRangeStartElementBox || element instanceof EditRangeEndElementBox) { + if (element instanceof EditRangeStartElementBox && (this.documentHelper.owner.currentUser === element.user || (element.group === "Everyone" && element.user === ""))) { + if (element.columnFirst != -1 && element.columnLast != -1) { + let row = element.paragraph.associatedCell.ownerRow; + let cell = row.getCellUsingColumnIndex(row.rowIndex, element.columnFirst); + if (!isNullOrUndefined(cell)) { + cell.isRenderEditRangeStart = true; + row.editRangeID.add(element.editRangeId, element); + } + } + } else if (element instanceof EditRangeEndElementBox && (this.documentHelper.owner.currentUser === element.editRangeStart.user || (element.editRangeStart.group === "Everyone" && element.editRangeStart.user === ""))) { + if (element.editRangeStart.columnFirst != -1 && element.editRangeStart.columnLast != -1) { + let row = element.paragraph.associatedCell.ownerRow; + if (row.editRangeID.containsKey(element.editRangeStart.editRangeId)) { + let cell = row.getCellUsingColumnIndex(row.rowIndex, element.editRangeStart.columnFirst); + if (!isNullOrUndefined(cell)) { + if (cell.isRenderEditRangeStart) { + cell.isRenderEditRangeEnd = true; + } + } + } else { + let table = element.paragraph.associatedCell.ownerTable; + for (let i = row.rowIndex - 1; i >= 0; i--) { + let previousRow: TableRowWidget = table.childWidgets[i] as TableRowWidget; + if (previousRow.editRangeID.containsKey(element.editRangeStart.editRangeId)) { + let previousCell = previousRow.getCellUsingColumnIndex(previousRow.rowIndex, element.editRangeStart.columnFirst); + if (!isNullOrUndefined(previousCell)) { + if (previousCell.isRenderEditRangeStart) { + previousCell.isRenderEditRangeEnd = true; + break; + } + } + } + } + } + } + } + } if (element instanceof ShapeBase && element.textWrappingStyle !== 'Inline' && paragraph.floatingElements.indexOf(element) == -1) { if (element instanceof ShapeElementBox) { if (paragraph.floatingElements.indexOf(element) === -1) { @@ -1851,6 +1902,14 @@ export class Layout { (element as FootnoteElementBox).text = text; } } else if (element instanceof TextElementBox) { + // skip when cliked enter in first footnote element + if (!isNullOrUndefined((element.paragraph.containerWidget as BodyWidget).footNoteReference) + && element.line.isFirstLine() + && element.paragraph.index === 0 + && element.indexInOwner === 0 + && !this.documentHelper.owner.editor.handleEnterKey) { + element.text = (element.paragraph.containerWidget as BodyWidget).footNoteReference.text; + } this.checkAndSplitTabOrLineBreakCharacter(element.text, element); //TODO: Need to update revision // if (element.text.length > 1 && element.line.paragraph.bidi) { @@ -1878,7 +1937,8 @@ export class Layout { } } if (!isNullOrUndefined(paragraph.containerWidget) && paragraph.bodyWidget.floatingElements.length > 0 && - !(element instanceof ShapeElementBox) && !(paragraph.containerWidget instanceof TextFrame && !(element instanceof CommentCharacterElementBox))) { + !(element instanceof ShapeElementBox && element.textWrappingStyle == 'Inline') && !(paragraph.containerWidget instanceof TextFrame && !(element instanceof CommentCharacterElementBox)) && + !(paragraph.containerWidget instanceof TableCellWidget && paragraph.containerWidget.ownerTable.containerWidget instanceof TextFrame)) { this.adjustPosition(element, element.line.paragraph.bodyWidget); } if (this.viewer instanceof PageLayoutViewer && @@ -1934,6 +1994,13 @@ export class Layout { if (parseFloat(width.toFixed(4)) <= parseFloat(this.viewer.clientActiveArea.width.toFixed(4)) || !this.viewer.textWrap) { //Fits the text in current line. this.addElementToLine(paragraph, element); + if (isNullOrUndefined(element.nextElement) && !element.line.isLastLine()) { + let nextLine: LineWidget = element.line.nextLine; + let nextElement: ElementBox = nextLine.children[0]; + if (nextElement instanceof TextElementBox && nextElement.text.indexOf(" ") == 0) { + this.moveElementFromNextLine(line); + } + } if (isNullOrUndefined(element.nextElement) && this.viewer.clientActiveArea.width > 0 && !element.line.isLastLine()) { this.moveElementFromNextLine(line); } else if (!element.line.isLastLine() && isNullOrUndefined(element.nextElement) && this.viewer.clientActiveArea.width === 0) { @@ -1983,7 +2050,7 @@ export class Layout { this.splitTextForClientArea(line, element, element.text, element.width, element.characterFormat); } this.checkLineWidgetWithClientArea(line, element); - if (element instanceof FieldTextElementBox) { + if (element instanceof FieldTextElementBox && !this.isInitialLoad) { this.updateFieldText(element); } if (element.line !== line && !isNullOrUndefined(this.nextElementToLayout) && this.is2013Justification) { @@ -2011,6 +2078,29 @@ export class Layout { this.addSplittedLineWidget(line, elementIndex); } } + // We don't have a carriage return support, thus we have to manage it by creating a new paragraph if the break is a carriage return character. + // Todo: Remove this code once carriage return break support is implemented. + if (text === '\r') { + element.width = 0; + (element as TextElementBox).text = ''; + let newParagraph = new ParagraphWidget(); + let newline = new LineWidget(newParagraph); + newParagraph.childWidgets.push(newline); + do { + let lastElement: ElementBox = line.children[line.children.length - 1]; + if (lastElement === element) { + break; + } + line.children.splice(line.children.indexOf(lastElement), 1); + newline.children.splice(0, 0, lastElement); + lastElement.line = newline; + } while (true); + newParagraph.containerWidget = paragraph.containerWidget; + paragraph.containerWidget.childWidgets.splice(paragraph.indexInOwner + 1, 0, newParagraph); + newParagraph.paragraphFormat = paragraph.paragraphFormat; + newParagraph.characterFormat = paragraph.characterFormat; + newParagraph.index = paragraph.index + 1; + } if (element.line.isLastLine() && isNullOrUndefined(element.nextElement) || text === '\v' || text === '\f' || text === String.fromCharCode(14)) { if (this.isXPositionUpdated) { this.isXPositionUpdated = false; @@ -2675,6 +2765,12 @@ export class Layout { let textWrappingType: string = floatingElement instanceof TableWidget ? 'Both' : floatingElement.textWrappingType; let minimumWidthRequired: number = 24; let tableHeight: number = table.childWidgets.length > 0 ? (table.childWidgets[0] as TableRowWidget).rowFormat.height : 0; + let lastNestedTable: TableWidget = this.getNestedTable(table); + let characterFormat: WCharacterFormat = (((lastNestedTable.firstChild as TableRowWidget).firstChild as TableCellWidget).firstChild as ParagraphWidget).characterFormat; + let size: TextSizeInfo = this.documentHelper.textHelper.measureText(" ", characterFormat); + if (tableHeight < size.Height) { + tableHeight = size.Height; + } if (!(clientLayoutArea.x > (wrappingBounds.right + minimumWidthRequired) || clientLayoutArea.right < wrappingBounds.x - minimumWidthRequired)) { if (this.isNeedToWrapForSquareTightAndThroughForTable(bodyWidget, table, -1, -1, textWrappingStyle, wrappingBounds, allowOverlap, 1, floatingElement, false, rect, tableWidth, tableHeight)) { // Skip to update when the wrap type as left @@ -2745,6 +2841,13 @@ export class Layout { } return rect; } + private getNestedTable(tableWidget: TableWidget): TableWidget { + let table: TableWidget = tableWidget as TableWidget; + while (((table.firstChild as TableRowWidget).firstChild as TableCellWidget).firstChild instanceof TableWidget) { + table = ((table.firstChild as TableRowWidget).firstChild as TableCellWidget).firstChild as TableWidget; + } + return table; + } private startAt(element: FootnoteElementBox, text: string): string { if (element.footnoteType === 'Footnote') { @@ -3125,7 +3228,7 @@ export class Layout { lineWidget = isEmptyLine ? this.addLineWidget(paragraph) : line; } if (!isNullOrUndefined(paragraph.containerWidget) && paragraph.bodyWidget.floatingElements.length > 0 && - !(paragraph.containerWidget instanceof TextFrame)) { + !(paragraph.containerWidget instanceof TextFrame) && !(paragraph.containerWidget instanceof TableCellWidget && paragraph.containerWidget.ownerTable.containerWidget instanceof TextFrame)) { let elementBox = new TextElementBox(); elementBox.line = lineWidget; lineWidget.children.push(elementBox); @@ -3389,6 +3492,9 @@ export class Layout { } if (movedElementBox.length > 0) { lineWidget.children.splice(index + 1, lineWidget.children.length - 1); + if (!isNullOrUndefined(lineWidget.layoutedElements) && lineWidget.layoutedElements.length > 0) { + lineWidget.layoutedElements.splice(index + 1, lineWidget.layoutedElements.length - 1); + } newLineWidget.children = movedElementBox.concat(newLineWidget.children); } if (paragraph.childWidgets.indexOf(newLineWidget) === -1) { @@ -3445,7 +3551,7 @@ export class Layout { splittedElementBox.characterRange = elementBox.characterRange; //splittedElementBox.revisions = splittedElementBox.revisions; elementBox.text = elementBox.text.substr(0, index); - elementBox.width -= splittedElementBox.width; + elementBox.width = this.documentHelper.textHelper.getWidth(elementBox.text, elementBox.characterFormat, elementBox.scriptType); elementBox.trimEndWidth = elementBox.width; if (elementBox.revisions.length > 0) { this.updateRevisionForSplittedElement(elementBox, splittedElementBox, true); @@ -3489,6 +3595,10 @@ export class Layout { private splitByCharacter(lineWidget: LineWidget, textElement: TextElementBox, text: string, width: number, characterFormat: WCharacterFormat): void { const paragraph: ParagraphWidget = lineWidget.paragraph; const index: number = this.getTextSplitIndexByCharacter(this.viewer.clientArea.width, this.viewer.clientActiveArea.width, text, width, characterFormat, textElement.scriptType); + // if the index is zero, no need to split text by character. so, we can avoid the empty text element creation. + if (index === 0 && textElement.previousNode instanceof ImageElementBox && textElement.previousNode.textWrappingType === "Right") { + return; + } let splitWidth: number = 0; if (index < textElement.length) { splitWidth = this.documentHelper.textHelper.measureTextExcludingSpaceAtEnd(text.substring(0, index), characterFormat, textElement.scriptType); @@ -3509,7 +3619,7 @@ export class Layout { splittedElement.width = this.documentHelper.textHelper.getWidth(splittedElement.text, characterFormat, splittedElement.scriptType); splittedElement.trimEndWidth = splittedElement.width; splittedElement.characterRange = textElement.characterRange; - textElement.width -= splittedElement.width; + textElement.width = this.documentHelper.textHelper.getWidth(textElement.text, characterFormat, textElement.scriptType); textElement.trimEndWidth = textElement.width; splittedElement.height = textElement.height; splittedElement.baselineOffset = textElement.baselineOffset; @@ -3546,7 +3656,8 @@ export class Layout { } } } else { - currentRevision.range.splice(currentRevision.range.length - 1, 1); + let rangeIndex: number = currentRevision.range.indexOf(item); + currentRevision.range.splice(rangeIndex, 1); currentRevision.range.push(splittedElement); splittedElement.revisions.push(currentRevision); } @@ -3595,7 +3706,7 @@ export class Layout { splittedElement.isMarkedForRevision = textElement.isMarkedForRevision; } textElement.text = text; - textElement.width -= splittedElement.width; + textElement.width = this.documentHelper.textHelper.getWidth(textElement.text, textElement.characterFormat, textElement.scriptType); textElement.trimEndWidth = textElement.width; if (textElement.width === 0 && lineWidget.children.indexOf(textElement) !== -1) { lineWidget.children.splice(lineWidget.children.indexOf(textElement), 1); @@ -3636,7 +3747,7 @@ export class Layout { } if (this.viewer.clientActiveArea.width < textWidth) { //Check and split the previous text elements to next line. - isSplitByWord = this.checkPreviousElement(lineWidget, lineWidget.children.indexOf(element), characterFormat); + isSplitByWord = this.checkPreviousElement(lineWidget, lineWidget.children.indexOf(element)); if (isSplitByWord) { //lineWidget = paragraph.childWidgets[paragraph.childWidgets.indexOf(lineWidget) + 1] as LineWidget; //isSplitByWord = textWidth <= this.viewer.clientActiveArea.width; @@ -3772,8 +3883,12 @@ export class Layout { this.viewer.clientActiveArea.x -= widthForAdjustment; this.viewer.clientActiveArea.width += widthForAdjustment; this.is2013Justification = true; - this.moveElementFromNextLine(line); - this.nextElementToLayout = line.children[line.children.length - 1]; + if (isMultiColumnSplit) { + this.splitParagraphForMultiColumn(line, index); + } else { + this.moveElementFromNextLine(line); + this.nextElementToLayout = line.children[line.children.length - 1]; + } return; } else { if (this.is2013Justification && isParagraphEnd) { @@ -3877,6 +3992,12 @@ export class Layout { maxElementBottomMargin = elementBox.margin.bottom; maxElementTopMargin = elementBox.margin.top; } + if (i !== 0 && elementBox instanceof ShapeElementBox && elementBox.textWrappingStyle === "Inline") { + elementBox.x += children[0].margin.left; + for (let i: number = 0; i < elementBox.textFrame.childWidgets.length; i++) { + (elementBox.textFrame.childWidgets[i] as Widget).x += children[0].margin.left; + } + } } line.margin = new Margin(0, maxElementTopMargin, 0, maxElementBottomMargin); this.adjustPositionBasedOnTopAndBottom(line); @@ -3892,19 +4013,7 @@ export class Layout { this.updateClientAreaForNextBlock(line, line.paragraph); } } else if (isMultiColumnSplit) { - this.splitParagraph(line.paragraph, index, undefined); - if (isNullOrUndefined(line.paragraph.previousRenderedWidget) && index == 0) { - this.moveBlocksToNextPage(line.paragraph as BlockWidget); - } else { - this.moveBlocksToNextPage(line.paragraph.previousRenderedWidget as BlockWidget); - } - this.viewer.updateClientArea(line.paragraph.bodyWidget, line.paragraph.bodyWidget.page); - this.viewer.clientActiveArea.y = line.paragraph.bodyWidget.y; - if (line.paragraph.bodyWidget.sectionFormat.equalWidth) { - let parawidget: ParagraphWidget = line.paragraph; - this.documentHelper.blockToShift = parawidget; - this.shiftLayoutedItems(false); - } + this.splitParagraphForMultiColumn(line, index); } if (!isMultiColumnSplit) { this.viewer.cutFromTop(this.viewer.clientActiveArea.y + line.height); @@ -3926,6 +4035,22 @@ export class Layout { } } return section; } + + private splitParagraphForMultiColumn(line: LineWidget, index: number): void { + this.splitParagraph(line.paragraph, index, undefined); + if (isNullOrUndefined(line.paragraph.previousRenderedWidget) && index == 0) { + this.moveBlocksToNextPage(line.paragraph as BlockWidget); + } else { + this.moveBlocksToNextPage(line.paragraph.previousRenderedWidget as BlockWidget); + } + this.viewer.updateClientArea(line.paragraph.bodyWidget, line.paragraph.bodyWidget.page); + this.viewer.clientActiveArea.y = line.paragraph.bodyWidget.y; + if (line.paragraph.bodyWidget.sectionFormat.equalWidth) { + let parawidget: ParagraphWidget = line.paragraph; + this.documentHelper.blockToShift = parawidget; + this.shiftLayoutedItems(false); + } + } //Checks Inbetween Overlap & Updates Line marginTop private checkInbetweenShapeOverlap(line: LineWidget, floatingElements?: (ShapeBase | TableWidget)[]): void { if (!(line.paragraph.containerWidget instanceof TextFrame) && line.paragraph.bodyWidget) { @@ -4637,7 +4762,7 @@ export class Layout { } } - private checkPreviousElement(line: LineWidget, index: number, characterFormat: WCharacterFormat): boolean { + private checkPreviousElement(line: LineWidget, index: number): boolean { let paragraph: ParagraphWidget = line.paragraph; let isSplitByWord: boolean = false; let lastTextElement: number = 0; @@ -4668,19 +4793,26 @@ export class Layout { splittedElement.isMarkedForRevision = textElement.isMarkedForRevision; } textElement.text = text.substr(0, index); - this.documentHelper.textHelper.getTextSize(splittedElement, characterFormat); + this.documentHelper.textHelper.getTextSize(splittedElement, textElement.characterFormat); textElement.width -= splittedElement.width; + textElement.trimEndWidth = textElement.width; textElement.height = splittedElement.height; if (textElement.width === 0) { line.children.splice(i, 1); + if (!isNullOrUndefined(line.layoutedElements) && line.layoutedElements.length > 0) { + line.layoutedElements.splice(i, 1); + } } //Adds the text element to the line line.children.splice(i + 1, 0, splittedElement); + if (!isNullOrUndefined(line.layoutedElements)) { + line.layoutedElements.splice(i + 1, 0, splittedElement); + } break; } } else if (!(textElement instanceof ListTextElementBox || textElement instanceof FieldElementBox // to skip field code - || textElement instanceof TextElementBox && textElement.width === 0 || textElement instanceof CommentCharacterElementBox)) { + || textElement instanceof TextElementBox && textElement.width === 0 || textElement instanceof CommentCharacterElementBox || textElement instanceof ContentControl)) { //Handled for inline images/UIelements. lastTextElement = i; isSplitByWord = true; @@ -5391,6 +5523,9 @@ export class Layout { if (i === 0 && splitWidth > totalClientWidth) { //Handle for cell/section having client width less than a character's width. return (length > 1 && text[1] === ' ') ? this.getTextIndexAfterSpace(text, 1) : 1; + } else if (text[i] === ' ') { + // If the character is space, then split the text from next character. + return this.getTextIndexAfterSpace(text, i); } return i; } @@ -5703,7 +5838,7 @@ export class Layout { if (nextIndex === 0 || nextIndex === length) { return nextIndex; } - while (text[nextIndex] === ' ' || text[nextIndex] === '-') { + while (text[nextIndex] === ' ') { nextIndex++; if (nextIndex === length) { break; @@ -6036,9 +6171,9 @@ export class Layout { return colIndex < row.ownerTable.tableHolder.columns.length; } - private splitWidgets(tableRowWidget: TableRowWidget, viewer: LayoutViewer, tableCollection: TableWidget[], rowCollection: TableRowWidget[], splittedWidget: TableRowWidget, isLastRow: boolean, footNoteCollection: FootnoteElementBox[], lineIndexInCell?: number, cellIndex?: number, isMultiColumnSplit?: boolean): TableRowWidget { + private splitWidgets(tableRowWidget: TableRowWidget, viewer: LayoutViewer, tableCollection: TableWidget[], rowCollection: TableRowWidget[], splittedWidget: TableRowWidget, isLastRow: boolean, footNoteCollection: FootnoteElementBox[], lineIndexInCell?: number, cellIndex?: number, isMultiColumnSplit?: boolean, isRowSpan?: boolean): TableRowWidget { if (!(isMultiColumnSplit && lineIndexInCell === 0) && (this.isFirstLineFitForRow(viewer.clientArea.bottom, tableRowWidget) && tableRowWidget.childWidgets.length > 0)) { - splittedWidget = this.getSplittedWidgetForRow(viewer.clientArea.bottom, tableCollection, rowCollection, tableRowWidget, footNoteCollection, lineIndexInCell, isMultiColumnSplit); + splittedWidget = this.getSplittedWidgetForRow(viewer.clientArea.bottom, tableCollection, rowCollection, tableRowWidget, footNoteCollection, lineIndexInCell, isMultiColumnSplit, undefined, isRowSpan); if (this.documentHelper.splittedCellWidgets.length > 0 || splittedWidget !== tableRowWidget) { if (isLastRow) { for (let i: number = 0; i < splittedWidget.childWidgets.length; i++) { @@ -6059,7 +6194,7 @@ export class Layout { return splittedWidget; } - private getSplittedWidgetForRow(bottom: number, tableCollection: TableWidget[], rowCollection: TableRowWidget[], tableRowWidget: TableRowWidget, footNoteCollection: FootnoteElementBox[], lineIndexInCell?: number, isMultiColumnSplit?: boolean, count?: number): TableRowWidget { + private getSplittedWidgetForRow(bottom: number, tableCollection: TableWidget[], rowCollection: TableRowWidget[], tableRowWidget: TableRowWidget, footNoteCollection: FootnoteElementBox[], lineIndexInCell?: number, isMultiColumnSplit?: boolean, count?: number, isRowSpan?: boolean): TableRowWidget { let splittedWidget: TableRowWidget = undefined; let rowIndex: number = tableRowWidget.index; this.isRelayoutneed = false; @@ -6074,6 +6209,10 @@ export class Layout { cellHeight = cellWidget.height; } footNoteCollection = []; + if (isNullOrUndefined(splittedCell) && cellWidget === tableRowWidget.childWidgets[tableRowWidget.childWidgets.length - 1] && this.isVerticalMergedCellContinue(tableRowWidget) && this.isRowSpanEnd(tableRowWidget, this.viewer) && this.documentHelper.splittedCellWidgets.length > 0 && isRowSpan) { + splittedWidget = this.getSplittedWidgetForSpannedRow(bottom, tableRowWidget, tableCollection, rowCollection, footNoteCollection); + splittedCell = undefined; + } if (!isNullOrUndefined(splittedCell)) { if (splittedCell === cellWidget) { //Returns if the whole content of the row does not fit in current page. @@ -6135,6 +6274,36 @@ export class Layout { } return splittedWidget; } + private getSplittedWidgetForSpannedRow(bottom: number, tableRowWidget: TableRowWidget, tableCollection: TableWidget[], rowCollection: TableRowWidget[], footNoteCollection: FootnoteElementBox[]): TableRowWidget { + let splittedWidget: TableRowWidget = undefined; + let splittedCell: TableCellWidget = undefined; + let issplit: boolean = false; + for (let i: number = 0; i < this.documentHelper.splittedCellWidgets.length; i++) { + splittedCell = this.documentHelper.splittedCellWidgets[i]; + if (isNullOrUndefined(splittedWidget)) { + splittedWidget = new TableRowWidget(); + splittedWidget.containerWidget = tableRowWidget.containerWidget; + splittedWidget.index = tableRowWidget.index; + splittedWidget.rowFormat = tableRowWidget.rowFormat; + splittedWidget.isRenderBookmarkEnd = tableRowWidget.isRenderBookmarkEnd; + this.updateWidgetLocation(tableRowWidget, splittedWidget); + rowCollection.push(splittedWidget); + } + splittedWidget.childWidgets.push(splittedCell); + splittedCell.containerWidget = splittedWidget; + this.isRelayoutneed = true; + let count: number = (this.documentHelper.splittedCellWidgets[i] as TableCellWidget).index; + while (count > 0 && !issplit) { + let cellWidget: TableCellWidget = tableRowWidget.childWidgets[count - 1] as TableCellWidget; + splittedCell = this.getSplittedWidget(bottom, true, tableCollection, rowCollection, cellWidget, footNoteCollection); + splittedWidget.childWidgets.splice(0, 0, splittedCell); + splittedCell.containerWidget = splittedWidget; + count--; + } + issplit = true; + } + return splittedWidget; + } private getFootNoteHeightInLine(line: LineWidget): number { let height: number = 0; for (let i: number = 0; i < line.children.length; i++) { @@ -6272,7 +6441,7 @@ export class Layout { if (isInsertSplittedWidgets) { this.insertSplittedCellWidgets(viewer, tableWidgets, splittedWidget, tableRowWidget.indexInOwner - 1); } else { - splittedWidget = this.splitWidgets(tableRowWidget, viewer, tableWidgets, rowWidgets, splittedWidget, isLastRow, footnoteElements); + splittedWidget = this.splitWidgets(tableRowWidget, viewer, tableWidgets, rowWidgets, splittedWidget, isLastRow, footnoteElements, undefined, undefined, undefined, true); if (isNullOrUndefined(splittedWidget)) { isInsertSplittedWidgets = (tableRowWidget.y === viewer.clientArea.y || tableRowWidget.y === this.viewer.clientArea.y + tableRowWidget.ownerTable.headerHeight); @@ -6285,6 +6454,12 @@ export class Layout { } } else if (isLastRow && !isAllowBreakAcrossPages) { splittedWidget = this.splitWidgets(tableRowWidget, viewer, tableWidgets, rowWidgets, splittedWidget, isLastRow, footnoteElements); + } else if (this.isRowSpanEnd(row, viewer) && !isAllowBreakAcrossPages) { + if (heightType === 'AtLeast' && row.ownerTable.spannedRowCollection.keys.length > 0) + splittedWidget = this.splitWidgets(tableRowWidget, viewer, tableWidgets, rowWidgets, splittedWidget, isLastRow, footnoteElements, lineIndexInCell, cellIndex, isMultiColumnSplit, true); + if (isNullOrUndefined(splittedWidget)) { + this.addWidgetToTable(viewer, tableWidgets, rowWidgets, tableRowWidget, footnoteElements); + } } } //Create New table for splitted widget @@ -6321,6 +6496,10 @@ export class Layout { //Creates new table widget for splitted rows. this.addTableWidget(viewer.clientActiveArea, tableWidgets, true); } + } else if (heightType === 'Exactly' && rowHeight + tableRowWidget.y + this.footHeight < viewer.clientArea.bottom && tableRowWidget.y === viewer.clientArea.y) { + this.addWidgetToTable(viewer, tableWidgets, rowWidgets, tableRowWidget, footnoteElements); + count++; + continue; } moveRowToNextTable = true; count--; @@ -6411,7 +6590,7 @@ export class Layout { if (insertHeaderRow && rowToMove.ownerTable.header && tableRowWidget.height < viewer.clientArea.bottom && !keepNext) { if (viewer instanceof PageLayoutViewer) { - (viewer as PageLayoutViewer).documentHelper.currentRenderingPage.repeatHeaderRowTableWidget = true; + tableRowWidget.bodyWidget.page.repeatHeaderRowTableWidget = true; } //Updates table widgets location. viewer.updateClientAreaForBlock(rowToMove.ownerTable, true, tableWidgets); @@ -6453,7 +6632,7 @@ export class Layout { splittedWidget.y = tableWidget.y; // let cellspace: number = viewer instanceof PageLayoutViewer ? cellspacing / 2 : cellspacing; let cellspace: number = cellSpacing / 2; - this.updateChildLocationForRow(tableWidget.y - cellspace, splittedWidget,tableWidget.containerWidget as BodyWidget); + this.updateChildLocationForRow(tableWidget.y - cellspace, splittedWidget,tableWidget.containerWidget as BodyWidget, true); } if (removeTable && this.shiftedFloatingItemsFromTable.length > 0) { for (let i: number = 0; i < this.shiftedFloatingItemsFromTable.length; i++) { @@ -7211,7 +7390,7 @@ export class Layout { } } - public updateChildLocationForRow(top: number, rowWidget: TableRowWidget, bodyWidget?:BodyWidget): void { + public updateChildLocationForRow(top: number, rowWidget: TableRowWidget, bodyWidget?: BodyWidget, updatePosition?: boolean): void { let spacing: number = 0; if (rowWidget.ownerTable.tableFormat.cellSpacing > 0) { spacing = HelperMethods.convertPointToPixel(rowWidget.ownerTable.tableFormat.cellSpacing); @@ -7221,11 +7400,11 @@ export class Layout { //cellWidget.x = cellWidget.x; cellWidget.index = cellWidget.cellIndex; cellWidget.y = top + cellWidget.margin.top + spacing; - this.updateChildLocationForCellOrShape(cellWidget.y, cellWidget, bodyWidget); + this.updateChildLocationForCellOrShape(cellWidget.y, cellWidget, bodyWidget, updatePosition); } } - private updateChildLocationForCellOrShape(top: number, widget: TableCellWidget | ShapeElementBox, bodyWidget?:BodyWidget): void { + private updateChildLocationForCellOrShape(top: number, widget: TableCellWidget | ShapeElementBox, bodyWidget?:BodyWidget, updatePosition?: boolean): void { let container: Widget = widget as Widget; if (widget instanceof ShapeElementBox) { container = widget.textFrame; @@ -7237,6 +7416,9 @@ export class Layout { && (container.childWidgets[i + 1] as Widget).y < ((container.childWidgets[i] as Widget).y + (container.childWidgets[i] as Widget).height)) { skipHeight = true; } + if (!isNullOrUndefined((container.childWidgets[i] as ParagraphWidget).floatingElements) && (container.childWidgets[i] as ParagraphWidget).floatingElements.length > 0 && updatePosition) { + this.viewer.cutFromTop(top); + } (container.childWidgets[i] as Widget).x = (container.childWidgets[i] as Widget).x; (container.childWidgets[i] as Widget).y = top; if (!isNullOrUndefined(bodyWidget) && widget instanceof TableCellWidget && container.childWidgets[i] instanceof ParagraphWidget) { @@ -7499,7 +7681,7 @@ export class Layout { /* eslint-disable-next-line max-len */ if (this.documentHelper.fieldStacks.length === 0 && !isNullOrUndefined(nextWidget) && currentWidget.containerWidget === nextWidget.containerWidget && (HelperMethods.round(nextWidget.y, 2) === HelperMethods.round(currentWidget.y + currentWidget.height, 2))) { - if (!isNullOrUndefined(this.documentHelper.blockToShift)) { + if (!isNullOrUndefined(this.documentHelper.blockToShift) || this.documentHelper.owner.editor.isFootnoteElementRemoved) { this.documentHelper.blockToShift = block; } else if ((nextWidget as BlockWidget).bodyWidget) { const floatingElementLength = (nextWidget as BlockWidget).bodyWidget.floatingElements.length; @@ -7899,7 +8081,10 @@ export class Layout { } if (blockIndex > 0 || (curretBlock.bodyWidget.sectionFormat.breakCode === 'NoBreak' && curretBlock.bodyWidget.index !== 0 && curretBlock === bodyWidget.firstChild)) { - const prevWidget: Widget = curretBlock.getSplitWidgets()[0].previousRenderedWidget as Widget; + let prevWidget: Widget = curretBlock.getSplitWidgets()[0].previousRenderedWidget as Widget; + if (!isNullOrUndefined(prevWidget) && (prevWidget as TableWidget).wrapTextAround && !isNullOrUndefined(prevWidget.getSplitWidgets()[0].previousRenderedWidget) && prevWidget.y < (prevWidget.getSplitWidgets()[0].previousRenderedWidget as BlockWidget).y) { + prevWidget = prevWidget.getSplitWidgets()[0].previousRenderedWidget as Widget; + } if (!(isNullOrUndefined(prevWidget) || prevWidget instanceof ParagraphWidget) || (prevWidget instanceof ParagraphWidget) && !prevWidget.isEndsWithPageBreak && !prevWidget.isEndsWithColumnBreak) { if (isNullOrUndefined(isSkipShifting) && curretBlock.containerWidget !== prevWidget.containerWidget) { @@ -8039,7 +8224,7 @@ export class Layout { clientActiveAreaForTableWrap = this.viewer.clientActiveArea.clone(); clientAreaForTableWrap = this.viewer.clientArea.clone(); this.updateClientAreaForWrapTable(tableView, table, true, clientActiveAreaForTableWrap, clientAreaForTableWrap); - } else { + } else if (!(table.containerWidget instanceof TextFrame)) { this.adjustClientAreaBasedOnTextWrapForTable(table, this.viewer.clientActiveArea); if (this.isWrapText) { wrapDiff = this.viewer.clientActiveArea.x - this.viewer.clientArea.x; @@ -8067,7 +8252,8 @@ export class Layout { if (wrapDiff > 0) { this.viewer.clientArea.x = this.viewer.clientArea.x - wrapDiff; } - if (table.wrapTextAround && table.bodyWidget) { + let tableWidget: TableWidget[] = table.getSplitWidgets() as TableWidget[]; + if (table.wrapTextAround && table.bodyWidget && table.bodyWidget.lastChild !== tableWidget[tableWidget.length - 1]) { this.updateClientAreaForWrapTable(tableView, table, false, clientActiveAreaForTableWrap, clientAreaForTableWrap); } tableView[tableView.length - 1].isLayouted = true; @@ -8625,7 +8811,7 @@ export class Layout { nextWidget = blocks[0] as TableWidget; } } - if (currentWidget.containerWidget === nextWidget.containerWidget + if (!this.documentHelper.owner.editor.isFootnoteElementRemoved && currentWidget.containerWidget === nextWidget.containerWidget && (HelperMethods.round(nextWidget.y, 2) === HelperMethods.round(this.viewer.clientActiveArea.y, 2)) && isNullOrUndefined(nextWidget.nextWidget)) { break; @@ -8653,12 +8839,33 @@ export class Layout { } this.documentHelper.blockToShift = undefined; const viewer: LayoutViewer = this.viewer; + if(viewer.owner.editor.isFootnoteElementRemoved) { + const lastPage = this.documentHelper.pages[this.documentHelper.pages.length - 1]; + const lastChild = lastPage.bodyWidgets[lastPage.bodyWidgets.length - 1]; + const endNote = lastPage.endnoteWidget; + if(!isNullOrUndefined(endNote)) { + const clientArea: Rect = this.viewer.clientArea.clone(); + const clientActiveArea: Rect = this.viewer.clientActiveArea.clone(); + const lastPageLastPara = lastChild.childWidgets[lastChild.childWidgets.length - 1] as Widget; + const y = lastPageLastPara.y + lastPageLastPara.height; + this.viewer.clientActiveArea.height = this.viewer.clientActiveArea.bottom - y; + this.viewer.clientActiveArea.x = this.viewer.clientArea.x; + this.viewer.clientActiveArea.width = this.viewer.clientArea.width; + this.viewer.clientActiveArea.y = y; + this.layoutfootNote(endNote); + this.viewer.clientArea = clientArea; + this.viewer.clientActiveArea = clientActiveArea; + } + } // if (viewer instanceof PageLayoutViewer) { this.documentHelper.removeEmptyPages(); this.updateFieldElements(); if ((!this.documentHelper.owner.enableLockAndEdit || !reLayout) && !this.isMultiColumnSplit) { viewer.updateScrollBars(); } + if (!(block.bodyWidget instanceof FootNoteWidget) && !this.isRelayoutFootnote && block.bodyWidget.page.endnoteWidget) { + this.layoutfootNote(block.bodyWidget.page.endnoteWidget); + } // } } private checkAndShiftEndnote(): void { @@ -8744,10 +8951,6 @@ export class Layout { if (!this.isRelayoutFootnote && block.bodyWidget.page.footnoteWidget) { this.layoutfootNote(block.bodyWidget.page.footnoteWidget); } - if (!(block.bodyWidget instanceof FootNoteWidget) && !this.isRelayoutFootnote - && block.bodyWidget.page.endnoteWidget) { - this.layoutfootNote(block.bodyWidget.page.endnoteWidget); - } // } } private isNeedToRelayout(bodyWidget: BlockContainer): boolean { @@ -8825,7 +9028,7 @@ export class Layout { if (shape instanceof ShapeElementBox && shape.textWrappingStyle === 'Inline') { let lineIndex: number = shape.line.indexInOwner; let lineHeight: number = 0; - topMargin = shape.textFrame.marginTop as number; + topMargin = HelperMethods.convertPointToPixel(shape.textFrame.marginTop as number); for (let k: number = 0; k < lineIndex; k++) { lineHeight += (widget.childWidgets[k] as LineWidget).height as number; } @@ -8870,7 +9073,7 @@ export class Layout { isSkip = false; i--; } - if ((widget.isEndsWithPageBreak || widget.isEndsWithColumnBreak) && this.viewer instanceof PageLayoutViewer) { + if (((widget.isEndsWithPageBreak && !this.isPageBreakInsideField(widget)) || widget.isEndsWithColumnBreak) && this.viewer instanceof PageLayoutViewer) { let nextBodyWidget: BodyWidget = this.createOrGetNextBodyWidget(prevBodyWidget, this.viewer); nextBodyWidget = this.moveBlocksToNextPage(widget, true); viewer.updateClientArea(nextBodyWidget, nextBodyWidget.page); @@ -8906,6 +9109,36 @@ export class Layout { } this.skipUpdateContainerWidget = false; } + + private isPageBreakInsideField(widget: ParagraphWidget): boolean { + let isPageBreakInsideField: boolean = false; + let isFieldElement: boolean = false; + let height: number = 0; + for (let i: number = 0; i < widget.childWidgets.length; i++) { + let line: LineWidget = widget.childWidgets[i] as LineWidget; + height += line.height; + for (let j: number = 0; j < line.children.length; j++) { + let element: ElementBox = line.children[j] as ElementBox; + if (element instanceof FieldElementBox) { + if (element.fieldType === 0) { + isFieldElement = true; + } else if (element.fieldType === 2 || element.fieldType === 1) { + isFieldElement = false; + } + } + if (!isFieldElement && (element as TextElementBox).text === '\f') { + isPageBreakInsideField = false; + } else { + isPageBreakInsideField = true; + } + } + } + if (isPageBreakInsideField && widget.height === 0) { + this.viewer.cutFromTop(this.viewer.clientActiveArea.y + height); + } + return isPageBreakInsideField; + } + /** * @private * Get the footnote of the block widget. @@ -9132,6 +9365,28 @@ export class Layout { public shiftParagraphWidget(paragraph: ParagraphWidget): void { this.addParagraphWidget(this.viewer.clientActiveArea, paragraph); + if (paragraph.floatingElements.length > 0) { + for (let k: number = 0; k < paragraph.floatingElements.length; k++) { + let shape: ShapeBase = paragraph.floatingElements[k]; + let topMargin: number = 0; + if (shape instanceof ShapeElementBox && shape.textWrappingStyle === 'Inline') { + let lineIndex: number = shape.line.indexInOwner; + let lineHeight: number = 0; + topMargin = HelperMethods.convertPointToPixel(shape.textFrame.marginTop as number); + for (let k: number = 0; k < lineIndex; k++) { + lineHeight += (paragraph.childWidgets[k] as LineWidget).height as number; + } + shape.y = paragraph.y + lineHeight; + } else { + let position: Point = this.getFloatingItemPoints(shape); + shape.y = position.y; + shape.x = position.x; + } + if (shape instanceof ShapeElementBox) { + this.updateChildLocationForCellOrShape(shape.y + topMargin, shape as ShapeElementBox); + } + } + } this.viewer.cutFromTop(this.viewer.clientActiveArea.y + paragraph.height); let footnoteCollection: BodyWidget[] = this.getFootNoteWidgetsOf(paragraph as BlockWidget, true); for (let i: number = 0; i < footnoteCollection.length; i++) { @@ -9791,7 +10046,9 @@ export class Layout { /* eslint-disable */ public reLayoutLine(paragraph: ParagraphWidget, lineIndex: number, isBidi: boolean, isSkip?: boolean): void { - this.isFootnoteContentChanged = false; + if (!this.documentHelper.owner.editor.isFootnoteElementRemoved) { + this.isFootnoteContentChanged = false; + } if (this.viewer.owner.isDocumentLoaded && this.viewer.owner.editorModule) { this.viewer.owner.editorModule.updateWholeListItems(paragraph); } @@ -9801,7 +10058,10 @@ export class Layout { } else { lineWidget = paragraph.childWidgets[lineIndex] as LineWidget; } - let lineToLayout: LineWidget = lineWidget.previousLine; + let lineToLayout: LineWidget; + if (paragraph.containerWidget instanceof BodyWidget && paragraph.containerWidget.sectionFormat.equalWidth) { + lineToLayout = lineWidget.previousLine; + } if (isNullOrUndefined(lineToLayout)) { lineToLayout = lineWidget; } @@ -9872,21 +10132,33 @@ export class Layout { let lastPage: Page = this.documentHelper.pages[page - 1]; let foot: FootNoteWidget; let newBodyWidget: BlockContainer = lastPage.bodyWidgets[lastPage.bodyWidgets.length - 1]; - if (this.isFootnoteContentChanged && !isNullOrUndefined(paragraph.bodyWidget.page.footnoteWidget)) { + if ((this.documentHelper.owner.editor.isFootnoteElementRemoved || this.isFootnoteContentChanged) + && !isNullOrUndefined(paragraph.bodyWidget.page.footnoteWidget)) { foot = paragraph.bodyWidget.page.footnoteWidget; this.layoutfootNote(foot); } - if (this.isEndnoteContentChanged && !isNullOrUndefined(newBodyWidget.page.endnoteWidget)) { + if (this.viewer.owner.editorHistory.isRedoing && !isNullOrUndefined(newBodyWidget.page.endnoteWidget)) { + this.isEndnoteContentChanged = true; + } + if ((this.documentHelper.owner.editor.isEndnoteElementRemoved || this.isEndnoteContentChanged) + && !isNullOrUndefined(newBodyWidget.page.endnoteWidget)) { foot = newBodyWidget.page.endnoteWidget; - let clientArea: Rect = this.viewer.clientArea.clone(); - let clientActiveArea: Rect = this.viewer.clientActiveArea.clone(); - this.viewer.cutFromTop((newBodyWidget.childWidgets[newBodyWidget.childWidgets.length - 1] as Widget).y - + (newBodyWidget.childWidgets[newBodyWidget.childWidgets.length - 1] as Widget).height); + const clientArea: Rect = this.viewer.clientArea.clone(); + const clientActiveArea: Rect = this.viewer.clientActiveArea.clone(); + const lastPageLastPara = newBodyWidget.childWidgets[newBodyWidget.childWidgets.length - 1] as Widget; + const y = lastPageLastPara.y + lastPageLastPara.height; + this.viewer.clientActiveArea.height = this.viewer.clientActiveArea.bottom - y; + this.viewer.clientActiveArea.x = this.viewer.clientArea.x; + this.viewer.clientActiveArea.width = this.viewer.clientArea.width; + this.viewer.clientActiveArea.y = y; this.layoutfootNote(foot); this.viewer.clientArea = clientArea; this.viewer.clientActiveArea = clientActiveArea; //this.viewer.updateClientAreaForBlock(foot.block, false); } + if (this.viewer.owner.editorHistory.isRedoing) { + this.isEndnoteContentChanged = false; + } } //#endregion //RTL Feature layout start @@ -10508,6 +10780,8 @@ export class Layout { let vertPosition: number = floatElement.verticalPosition; let horzPosition: number = floatElement.horizontalPosition; let layoutInCell: boolean = floatElement.layoutInCell; + let heightPercent: number = floatElement.heightRelativePercent; + let widthPercent:number = floatElement.widthRelativePercent; let autoShape: any; if (floatElement instanceof ShapeElementBox) { autoShape = floatElement.autoShapeType; @@ -10559,7 +10833,12 @@ export class Layout { if (vertOrigin === 'TopMargin') { indentY = (topMargin - shapeHeight) / 2; } else { - indentY = (pageHeight - shapeHeight) / 2; + if (heightPercent > 0 && widthPercent > 0) { + indentY = (pageHeight - (pageHeight) * (heightPercent / 100)) / 2; + floatElement.height = (pageHeight) * (heightPercent / 100); + } else { + indentY = (pageHeight - shapeHeight) / 2; + } } break; case 'Outside': @@ -10782,7 +11061,12 @@ export class Layout { if (isLayoutInCell) { indentX = (paragraph.associatedCell.cellFormat.cellWidth - shapeWidth) / 2; } else { - indentX = (pageWidth - shapeWidth) / 2; + if (heightPercent > 0 && widthPercent > 0) { + indentX = (pageWidth - (pageWidth) * (widthPercent / 100)) / 2; + floatElement.width = (pageWidth) * (widthPercent / 100); + } else { + indentX = (pageWidth - shapeWidth) / 2; + } } break; case 'Left': diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/page.ts b/controls/documenteditor/src/document-editor/implementation/viewer/page.ts index 2f9054a760..e219cc71c0 100644 --- a/controls/documenteditor/src/document-editor/implementation/viewer/page.ts +++ b/controls/documenteditor/src/document-editor/implementation/viewer/page.ts @@ -3,11 +3,11 @@ import { WTableFormat, WRowFormat, WCellFormat, WColumnFormat } from '../format/ import { WidthType, WColor, AutoFitType, TextFormFieldType, CheckBoxSizeType, VerticalOrigin, VerticalAlignment, HorizontalOrigin, HorizontalAlignment, LineFormatType, LineDashing, AutoShapeType, ContentControlType, ContentControlWidgetType, - TextWrappingStyle, TextWrappingType, CharacterRangeType, FontScriptType + TextWrappingStyle, TextWrappingType, CharacterRangeType, FontScriptType, BreakClearType } from '../../base/types'; import { WListLevel } from '../list/list-level'; import { WParagraphFormat, WCharacterFormat, WSectionFormat, WBorder, WBorders } from '../format/index'; -import { isNullOrUndefined, createElement, L10n } from '@syncfusion/ej2-base'; +import { isNullOrUndefined, createElement, L10n, classList } from '@syncfusion/ej2-base'; import { Dictionary } from '../../base/dictionary'; import { ElementInfo, HelperMethods, Point, WidthInfo, TextFormFieldInfo, CheckBoxFormFieldInfo, DropDownFormFieldInfo, BorderInfo, LtrRtlTextInfo } from '../editor/editor-helper'; import { HeaderFooterType, TabLeader, FootnoteType } from '../../base/types'; @@ -1398,11 +1398,13 @@ export class ParagraphWidget extends BlockWidget { let text: string = ''; let prevCharacterType: FontScriptType = FontScriptType.English; let currCharacterType: FontScriptType = FontScriptType.English; + // Regex for finding a string is unicode or not. + const surrogateRegex = /[\uD800-\uDFFF]/; for (let i: number = 0; i < inputText.length; i++) { // Gets a FontScriptType for the current character. // As per the Microsoft application behavior, we need to consider a space (\u0020) as previous character type. // So, that we can avoid a text splitting based on space character. - if (inputText[i] != String.fromCharCode(32)) { + if (inputText[i] != String.fromCharCode(32) && !surrogateRegex.test(inputText[i])) { // && !(char.IsHighSurrogate(inputText.charAt(i)) || char.IsLowSurrogate(inputText.charAt(i)))) { //Skip the setting of script type for surrogate character. currCharacterType = this.getFontScriptType(inputText[i]); } @@ -1485,6 +1487,9 @@ export class ParagraphWidget extends BlockWidget { lineWidget.children.splice(i + j, 0, clonedtextElement); clonedtextElement.line = lineWidget; iIncrementer++; + if (textElement.revisions.length > 0) { + this.updateTextElementInRevisionRange(textElement, clonedtextElement); + } } else { //Replace the source text range with splitted text. @@ -1607,7 +1612,7 @@ export class ParagraphWidget extends BlockWidget { let currentTxtRange: TextElementBox = elementBox; let nextTxtRange: TextElementBox = lineWidget.children[i + 1] as TextElementBox; - if (currentTxtRange.characterFormat.complexScript && currentTxtRange.scriptType == nextTxtRange.scriptType && + if ((currentTxtRange.characterFormat.complexScript || currentTxtRange.characterFormat.bidi) && currentTxtRange.scriptType == nextTxtRange.scriptType && currentTxtRange.text.length > 0 && nextTxtRange.text.length > 0 && !textHelper.isWordSplitChar(currentTxtRange.text[currentTxtRange.text.length - 1]) && !textHelper.isWordSplitChar(nextTxtRange.text[0]) && currentTxtRange.characterFormat.isEqualFormat(nextTxtRange.characterFormat)) { @@ -2800,6 +2805,10 @@ export class TableRowWidget extends BlockWidget { * @private */ public isRenderBookmarkEnd: boolean = false; + /** + * @private + */ + public editRangeID: Dictionary; /** * @private */ @@ -2833,6 +2842,7 @@ export class TableRowWidget extends BlockWidget { this.topBorderWidth = 0; this.bottomBorderWidth = 0; this.rowFormat = new WRowFormat(this); + this.editRangeID = new Dictionary(); } /** * @private @@ -3297,6 +3307,14 @@ export class TableCellWidget extends BlockWidget { * @private */ public isRenderBookmarkEnd: boolean = false; + /** + * @private + */ + public isRenderEditRangeStart: boolean = false; + /** + * @private + */ + public isRenderEditRangeEnd: boolean = false; /** * @private */ @@ -6277,7 +6295,7 @@ export class ShapeCommon extends ElementBox { /** * @private */ - public alternativeText: string = ''; + public alternateText: string = ''; /** * @private */ @@ -6351,6 +6369,14 @@ export class ShapeBase extends ShapeCommon { * @private */ public horizontalPosition: number = 0; + /** + * @private + */ + public heightRelativePercent: number; + /** + * @private + */ + public widthRelativePercent: number; /** * @private */ @@ -6416,6 +6442,10 @@ export class ShapeElementBox extends ShapeBase { * @private */ public textFrame: TextFrame; + /** + * @private + */ + public isZeroHeight: boolean; /** * @private */ @@ -6432,7 +6462,7 @@ export class ShapeElementBox extends ShapeBase { shape.height = this.height; shape.shapeId = this.shapeId; shape.name = this.name; - shape.alternativeText = this.alternativeText; + shape.alternateText = this.alternateText; shape.title = this.title; shape.widthScale = this.widthScale; shape.heightScale = this.heightScale; @@ -6445,6 +6475,8 @@ export class ShapeElementBox extends ShapeBase { shape.horizontalAlignment = this.horizontalAlignment; shape.horizontalOrigin = this.horizontalOrigin; shape.horizontalRelativePercent = this.horizontalRelativePercent; + shape.heightRelativePercent = this.heightRelativePercent; + shape.widthRelativePercent = this.widthRelativePercent; shape.zOrderPosition = this.zOrderPosition; shape.allowOverlap = this.allowOverlap; shape.textWrappingStyle = this.textWrappingStyle; @@ -6782,7 +6814,7 @@ export class ImageElementBox extends ShapeBase { } } image.name = this.name; - image.alternativeText = this.alternativeText; + image.alternateText = this.alternateText; image.title = this.title; image.visible = this.visible; image.widthScale = this.widthScale; @@ -8621,7 +8653,9 @@ export class CommentCharacterElementBox extends ElementBox { this.commentType = type; } - public renderCommentMark(): void { + public renderCommentMark(topPosition?: string, leftPosition?: string): void { + let documentHelper: DocumentHelper = this.line.paragraph.bodyWidget.page.documentHelper; + let commentMarkDictionary:Dictionary=documentHelper.render.commentMarkDictionary; if (this.commentType === 0 && isNullOrUndefined(this.commentMark)) { this.commentMark = document.createElement('div'); this.commentMark.style.display = 'none'; @@ -8632,17 +8666,109 @@ export class CommentCharacterElementBox extends ElementBox { this.commentMark.appendChild(span); } if (this.line && isNullOrUndefined(this.commentMark.parentElement)) { - let documentHelper: DocumentHelper = this.line.paragraph.bodyWidget.page.documentHelper; documentHelper.pageContainer.appendChild(this.commentMark); this.commentMark.addEventListener('click', this.selectComment.bind(this)); } + + let positionOverlap:boolean=false; + let overlapKey:HTMLElement; + for (let index = 0; index < commentMarkDictionary.length; index++) { + if(this.elementsOverlap(commentMarkDictionary.keys[index],topPosition,leftPosition)){ + positionOverlap=true; + overlapKey=commentMarkDictionary.keys[index]; + break; + } + } + if(positionOverlap){ + let ifNotPresent:boolean=true; + for (let index = 0; index < commentMarkDictionary.get(overlapKey).length; index++) { + if(commentMarkDictionary.get(overlapKey)[index]===this){ + ifNotPresent=false; + break; + } + } + if(ifNotPresent){ + commentMarkDictionary.get(overlapKey).push(this); + } + } + else{ + commentMarkDictionary.add(this.commentMark,[this]); + } + + for (let index = 0; index < commentMarkDictionary.length; index++){ + let element:HTMLElement=commentMarkDictionary.keys[index]; + if(commentMarkDictionary.get(element).length==1){ + if(commentMarkDictionary.get(element)[0].commentMark){ + if(commentMarkDictionary.get(element)[0].commentMark.firstElementChild.classList.contains('e-de-multi-cmt-mark')){ + classList(commentMarkDictionary.get(element)[0].commentMark.firstElementChild,['e-de-cmt-mark-icon'],['e-de-multi-cmt-mark']); + } + } + } + if(commentMarkDictionary.get(element).length>1){ + for (let z = 0; z < commentMarkDictionary.get(element).length; z++) { + if(commentMarkDictionary.get(element)[z].commentMark){ + if(commentMarkDictionary.get(element)[z].commentMark.firstElementChild.classList.contains('e-de-cmt-mark-icon')){ + classList(commentMarkDictionary.get(element)[z].commentMark.firstElementChild,['e-de-multi-cmt-mark'],['e-de-cmt-mark-icon']); + } + } + } + } + } + } + + private elementsOverlap(elementOne: HTMLElement, top: string, left: string) { + const width: number = elementOne.offsetWidth; + const height: number = elementOne.offsetHeight; + const elementOneTop: number = parseFloat(elementOne.style.top); + const elementOneLeft: number = parseFloat(elementOne.style.left); + const elementOneBottom: number = elementOneTop + height; + const elementOneRight: number = elementOneLeft + width; + const elementTwoTop: number = parseFloat(top); + const elementTwoLeft: number = parseFloat(left); + const elementTwoBottom: number = elementTwoTop + height; + const elementTwoRight: number = elementTwoLeft + width; + return !( + elementOneTop > elementTwoBottom || + elementOneRight < elementTwoLeft || + elementOneBottom < elementTwoTop || + elementOneLeft > elementTwoRight + ); } public selectComment(): void { let documentHelper: DocumentHelper = this.line.paragraph.bodyWidget.page.documentHelper; + let commentMarkDictionary:Dictionary=documentHelper.render.commentMarkDictionary; + let topPosition:string=this.commentMark.style.top; + let leftPosition:string=this.commentMark.style.left; + let currentIndex:number=0; + let navigationArray:CommentCharacterElementBox[]=[]; + for (let index = 0; index < commentMarkDictionary.keys.length; index++) { + if(this.elementsOverlap(commentMarkDictionary.keys[index],topPosition,leftPosition)){ + navigationArray=commentMarkDictionary.get(commentMarkDictionary.keys[index]); + break; + } + + } + if(!documentHelper.owner.documentHelper.currentSelectedComment){ + currentIndex=0; + } + else{ + for (let index = 0; index < navigationArray.length; index++) { + if(navigationArray[index].comment===documentHelper.owner.documentHelper.currentSelectedComment){ + currentIndex=index; + break; + } + } + if(currentIndex<(navigationArray.length-1)){ + currentIndex+=1; + } + else{ + currentIndex=0; + } + } if (documentHelper.owner) { if (!documentHelper.owner.commentReviewPane.commentPane.isEditMode) { - documentHelper.selectComment(this.comment); + documentHelper.selectComment(navigationArray[currentIndex].comment); } else { documentHelper.owner.showComments = true; } @@ -9449,4 +9575,38 @@ export class ColumnSizeInfo { * @private */ public hasMaximumWordWidth: boolean = false; +} +/** + * @private + */ +export class BreakElementBox extends TextElementBox { + /** + * @private + */ + public breakClearType: BreakClearType; + public constructor() { + super(); + } + /** + * @private + */ + public clone(): BreakElementBox { + let breakElement = super.clone() as BreakElementBox; + breakElement.breakClearType = this.breakClearType; + return breakElement; + } + /* + * @Private + */ + public destroy(): void { + this.breakClearType = undefined; + super.destroy(); + } + /* + * @Private + */ + public componentDestroy(): void { + this.breakClearType = undefined; + super.componentDestroy(); + } } \ No newline at end of file diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/render.ts b/controls/documenteditor/src/document-editor/implementation/viewer/render.ts index 12f677662f..516fe41417 100644 --- a/controls/documenteditor/src/document-editor/implementation/viewer/render.ts +++ b/controls/documenteditor/src/document-editor/implementation/viewer/render.ts @@ -9,7 +9,7 @@ import { TableRowWidget, TableWidget, TableCellWidget, FieldElementBox, TabElementBox, BlockWidget, ErrorTextElementBox, CommentCharacterElementBox, ShapeElementBox, EditRangeStartElementBox, FootNoteWidget, ShapeBase, FootnoteElementBox, TextFrame, BookmarkElementBox, EditRangeEndElementBox } from './page'; -import { BaselineAlignment, HighlightColor, Underline, Strikethrough, TabLeader, CollaborativeEditingSettingsModel, TextureStyle, Dictionary } from '../../index'; +import { BaselineAlignment, HighlightColor, Underline, Strikethrough, TabLeader, CollaborativeEditingSettingsModel, TextureStyle } from '../../index'; import { Layout } from './layout'; import { LayoutViewer, PageLayoutViewer, WebLayoutViewer, DocumentHelper } from './viewer'; import { HelperMethods, ErrorInfo, Point, SpecialCharacterInfo, SpaceCharacterInfo, WordSpellInfo, RevisionInfo, BorderInfo, BorderRenderInfo } from '../editor/editor-helper'; @@ -21,11 +21,16 @@ import { WColumnFormat, WSectionFormat } from '../format'; import { FontScriptType, TextWrappingStyle } from '../../index'; import { TextSizeInfo } from './text-helper'; import { DocumentCanvasElement, DocumentCanvasRenderingContext2D } from './document-canvas'; +import { Dictionary } from '../../base/dictionary'; /** * @private */ export class Renderer { + /** + * @private + */ + public commentMarkDictionary:Dictionary=new Dictionary(); public isPrinting: boolean = false; public isExporting: boolean = false; private pageLeft: number = 0; @@ -152,6 +157,9 @@ export class Renderer { this.pageContext.fillStyle = '#000000'; } private renderHFWidgets(page: Page, widget: HeaderFooterWidget, width: number, isHeader: boolean): void { + if (this.isFieldCode) { + this.isFieldCode = false; + } if (!this.isPrinting) { this.pageContext.globalAlpha = this.documentHelper.owner.enableHeaderAndFooter ? 1 : 0.65; } @@ -199,7 +207,7 @@ export class Renderer { this.pageContext.restore(); } if (!this.isPrinting) { - this.pageContext.globalAlpha = this.documentHelper.owner.enableHeaderAndFooter ? 0.65 : 1; + this.pageContext.globalAlpha = this.documentHelper.owner.enableHeaderAndFooter ? 0.50 : 1; } } private renderHeaderSeparator(page: Page, left: number, top: number, widget: HeaderFooterWidget): void { @@ -209,17 +217,36 @@ export class Renderer { const pageWidth: number = this.getScaledValue(page.boundingRectangle.width); const ctx: CanvasRenderingContext2D | DocumentCanvasRenderingContext2D = this.pageContext; ctx.save(); - ctx.globalAlpha = 0.65; + ctx.globalAlpha = 0.85; const headerFooterHeight: number = (this.getScaledValue(page.boundingRectangle.height) / 100) * 40; //Maximum header height limit y = Math.min(y, headerFooterHeight); //Dash line Separator this.renderDashLine(ctx, left, top + y, pageWidth, '#000000', false); let type: string = this.getHeaderFooterType(page, true); + let index: number = (this.viewer as PageLayoutViewer).getHeaderFooter(widget.headerFooterType); + let sectionIndex: number = page.sectionIndex; + let l10n: L10n = new L10n('documenteditor', this.documentHelper.owner.defaultLocale); + l10n.setLocale(this.documentHelper.owner.locale); + if (this.documentHelper.headersFooters.length > 1) { + let sectionMarkIndex: number = sectionIndex + 1; + type = type + " -" + l10n.getConstant('Section')+ " " +sectionMarkIndex+ "-"; + } ctx.font = '9pt Arial'; let width: number = ctx.measureText(type).width; this.renderHeaderFooterMark(ctx, left + 5, top + y, width + 10, 20); this.renderHeaderFooterMarkText(ctx, type, left + 10, y + top + 15); + let headerFooterWidget: HeaderFooterWidget; + if (this.documentHelper.headersFooters[parseInt(sectionIndex.toString(),10)]) { + headerFooterWidget = this.documentHelper.headersFooters[parseInt(sectionIndex.toString(),10)][parseInt(index.toString(),10)] as HeaderFooterWidget; + } + if (sectionIndex != 0 && !headerFooterWidget) { + let content: string = l10n.getConstant('Same as Previous'); + let width: number = ctx.measureText(content).width; + let right: number = this.viewer.containerWidth - width - 75 + left; + this.renderHeaderFooterMark(ctx, right, top + y, width + 10, 20); + this.renderHeaderFooterMarkText(ctx, content, right + 5, y + top + 15); + } if (page.footerWidget) { //Footer Widget const footerDistance: number = HelperMethods.convertPointToPixel(page.bodyWidgets[0].sectionFormat.footerDistance); @@ -230,10 +257,27 @@ export class Renderer { //Maximum footer height limit footerHeight = Math.max((this.getScaledValue(page.boundingRectangle.height) - headerFooterHeight), footerHeight); this.renderDashLine(ctx, left, top + footerHeight, pageWidth, '#000000', false); - type = this.getHeaderFooterType(page, false); + let type: string = this.getHeaderFooterType(page, false); + let sectionIndex: number = page.sectionIndex; + if (this.documentHelper.headersFooters.length > 1) { + let sectionMarkIndex: number = sectionIndex + 1; + type = type + " -" + l10n.getConstant('Section')+ " " +sectionMarkIndex+ "-"; + } width = ctx.measureText(type).width; this.renderHeaderFooterMark(ctx, left + 5, top + footerHeight - 20, width + 10, 20); this.renderHeaderFooterMarkText(ctx, type, left + 10, top + footerHeight - 5); + let index: number = (this.viewer as PageLayoutViewer).getHeaderFooter(page.footerWidget.headerFooterType); + let headerFooterWidget: HeaderFooterWidget; + if (this.documentHelper.headersFooters[parseInt(sectionIndex.toString(),10)]) { + headerFooterWidget = this.documentHelper.headersFooters[parseInt(sectionIndex.toString(),10)][parseInt(index.toString(),10)] as HeaderFooterWidget; + } + if (sectionIndex != 0 && !headerFooterWidget) { + let content: string = l10n.getConstant('Same as Previous'); + let width: number = ctx.measureText(content).width; + let right: number = this.viewer.containerWidth - width - 75 + left; + this.renderHeaderFooterMark(ctx, right, top + footerHeight - 20, width + 10, 20); + this.renderHeaderFooterMarkText(ctx, content, right + 5, top + footerHeight - 5); + } ctx.restore(); } } @@ -415,7 +459,7 @@ export class Renderer { (wrappingType !== "Behind" && shape.textWrappingStyle === "Behind")) { continue; } - if (!this.isOverLappedShapeWidget(shape)) { + if (!this.isOverLappedShapeWidget(shape) || (!isNullOrUndefined(floatingElements[i + 1]) && shape.paragraph !== (floatingElements[i + 1] as ShapeBase).paragraph)) { if (shape instanceof ImageElementBox) { this.renderImageElementBox(shape, shape.x, shape.y, 0); } else if (shape instanceof ShapeElementBox) { @@ -463,15 +507,21 @@ export class Renderer { let blocks: BlockWidget[] = shape.textFrame.childWidgets as BlockWidget[]; this.pageContext.beginPath(); - if (shape.fillFormat && shape.fillFormat.color && shape.fillFormat.fill) { + if (shape.fillFormat && shape.fillFormat.color && shape.fillFormat.fill && shapeType !== 'StraightConnector') { this.pageContext.fillStyle = shape.fillFormat.color; this.pageContext.fillRect(shapeLeft, shapeTop, this.getScaledValue(shape.width), this.getScaledValue(shape.height)); } if (!isNullOrUndefined(shapeType)) { - if ((shape.lineFormat.line && shape.lineFormat.lineFormatType !== 'None')) { + if (shape.lineFormat.line && shape.lineFormat.lineFormatType !== 'None') { this.pageContext.lineWidth = shape.lineFormat.weight; this.pageContext.strokeStyle = HelperMethods.getColor(shape.lineFormat.color); - this.pageContext.strokeRect(shapeLeft, shapeTop, this.getScaledValue(shape.width), this.getScaledValue(shape.height)); + if (shapeType !== 'StraightConnector') { + this.pageContext.strokeRect(shapeLeft, shapeTop, this.getScaledValue(shape.width), this.getScaledValue(shape.height)); + } else { + this.pageContext.moveTo(shapeLeft, shapeTop); + this.pageContext.lineTo(shapeLeft + this.getScaledValue(shape.width), shapeTop + this.getScaledValue(shape.height)); + this.pageContext.stroke(); + } } } this.pageContext.closePath(); @@ -588,7 +638,9 @@ export class Renderer { this.clipRect(paraWidget.x + paddingLeft, this.getScaledValue(page.boundingRectangle.y), this.getScaledValue(page.boundingRectangle.width), this.getScaledValue(page.boundingRectangle.height)); isClipped = true; } - this.renderParagraphBorder(page, paraWidget); + if (!(paraWidget.containerWidget instanceof HeaderFooterWidget && paraWidget.containerWidget.isEmpty && !isNullOrUndefined(this.documentHelper.selection) && !isNullOrUndefined(this.documentHelper.selection.start.paragraph) && !this.documentHelper.selection.start.paragraph.isInHeaderFooter)) { + this.renderParagraphBorder(page, paraWidget); + } if (isClipped) { this.pageContext.restore(); } @@ -612,7 +664,7 @@ export class Renderer { let firstLine: LineWidget = paragraphWidet.firstChild as LineWidget; let lastLine: LineWidget = paragraphWidet.lastChild as LineWidget; let canRenderParagraphBorders: BorderRenderInfo = this.documentHelper.canRenderBorder(paragraphWidet); - if (leftBorder.lineStyle !== 'None') { + if (!isNullOrUndefined(leftBorder) && leftBorder.lineStyle !== 'None') { startX = this.documentHelper.getParagraphLeftPosition(paragraphWidet) - HelperMethods.convertPointToPixel(leftBorder.space); endX = startX; endY = startY + paragraphWidet.height; @@ -630,7 +682,7 @@ export class Renderer { lineWidth = HelperMethods.convertPointToPixel(leftBorder.lineWidth); this.renderSingleBorder(leftBorder.color, startX, startY, endX, endY, lineWidth, leftBorder.lineStyle); } - if (topBorder.lineStyle !== 'None' && firstLine.isFirstLine() && !canRenderParagraphBorders.skipTopBorder) { + if (!isNullOrUndefined(topBorder) && topBorder.lineStyle !== 'None' && firstLine.isFirstLine() && !canRenderParagraphBorders.skipTopBorder) { startX = this.documentHelper.getParagraphLeftPosition(paragraphWidet); endX = startX + this.getContainerWidth(paragraphWidet, page); startY = paragraphWidet.y + this.getTopMargin(paragraphWidet) - (HelperMethods.convertPointToPixel(topBorder.lineWidth + topBorder.space)); @@ -644,7 +696,7 @@ export class Renderer { lineWidth = HelperMethods.convertPointToPixel(topBorder.lineWidth); this.renderSingleBorder(topBorder.color, startX, startY, endX, endY, lineWidth, topBorder.lineStyle); } - if (rightBorder.lineStyle !== 'None') { + if (!isNullOrUndefined(rightBorder) && rightBorder.lineStyle !== 'None') { startX = this.documentHelper.getParagraphLeftPosition(paragraphWidet) + this.getContainerWidth(paragraphWidet, page) + HelperMethods.convertPointToPixel(rightBorder.space); startY = endY; endX = startX; @@ -663,7 +715,7 @@ export class Renderer { lineWidth = HelperMethods.convertPointToPixel(rightBorder.lineWidth); this.renderSingleBorder(rightBorder.color, startX, startY, endX, endY, lineWidth, rightBorder.lineStyle); } - if (bottomBorder.lineStyle !== 'None' && lastLine.isLastLine() && !canRenderParagraphBorders.skipBottomBorder) { + if (!isNullOrUndefined(bottomBorder) && bottomBorder.lineStyle !== 'None' && lastLine.isLastLine() && !canRenderParagraphBorders.skipBottomBorder) { startX = this.documentHelper.getParagraphLeftPosition(paragraphWidet); endX = startX + this.getContainerWidth(paragraphWidet, page); startY = (paragraphWidet.y + paragraphWidet.height + HelperMethods.convertPointToPixel(bottomBorder.lineWidth + bottomBorder.space)) - (this.getBottomMargin(paragraphWidet)); @@ -758,7 +810,9 @@ export class Renderer { } if (j === 0 && !isNullOrUndefined(footNoteReference) && (widget.childWidgets[0] as LineWidget).children[0] instanceof TextElementBox && !this.documentHelper.owner.editor.isFootNoteInsert) { //if (j < 1 || (j > 0 && widget.footNoteReference !== (bodyWidget.childWidgets[j - 1] as BlockWidget).footNoteReference)) { - ((widget.childWidgets[0] as LineWidget).children[0] as TextElementBox).text = ((widget.childWidgets[0] as LineWidget).children[0] as TextElementBox).text.replace(((widget.childWidgets[0] as LineWidget).children[0] as TextElementBox).text, footNoteReference.text); + let footNoteElement: TextElementBox = (widget.childWidgets[0] as LineWidget).children[0] as TextElementBox; + footNoteElement.text = footNoteElement.text.replace(footNoteElement.text, footNoteReference.text); + footNoteElement.width = footNoteReference.width; //} } this.renderWidget(page, widget); @@ -829,6 +883,30 @@ export class Renderer { } this.renderWidget(page, widget); this.pageContext.restore(); + } + if (cellWidget.isRenderEditRangeStart) { + let firstPara: ParagraphWidget = this.documentHelper.selection.getFirstParagraph(cellWidget) as ParagraphWidget; + let firstLine: LineWidget = firstPara.firstChild as LineWidget; + let xLeft = firstLine.paragraph.x; + let ytop = firstLine.paragraph.y; + if(this.documentHelper.owner.documentEditorSettings.highlightEditableRanges){ + let highlighters = page.documentHelper.selection.editRegionHighlighters; + let widgetInfo : SelectionWidgetInfo[]= !isNullOrUndefined(highlighters)? highlighters.get(firstLine) : []; + let color : string = !isNullOrUndefined(widgetInfo) && !isNullOrUndefined(widgetInfo[0])? widgetInfo[0].color : "ffff00"; + this.renderBookmark(this.getScaledValue(xLeft, 1),this.getScaledValue(ytop, 2),this.getScaledValue(firstLine.height - firstLine.margin.bottom),0,color); + } + } + if (cellWidget.isRenderEditRangeEnd) { + let lastPara: ParagraphWidget = this.documentHelper.selection.getLastParagraph(cellWidget) as ParagraphWidget; + let lastLine: LineWidget = lastPara.lastChild as LineWidget; + let position: Point = this.documentHelper.selection.getEndPosition(lastPara); + let xLeft = this.documentHelper.textHelper.getWidth(String.fromCharCode(164), lastLine.paragraph.characterFormat) + position.x; + if(this.documentHelper.owner.documentEditorSettings.highlightEditableRanges){ + let highlighters = page.documentHelper.selection.editRegionHighlighters; + let widgetInfo : SelectionWidgetInfo[]= !isNullOrUndefined(highlighters)? highlighters.get(lastLine) : []; + let color : string = !isNullOrUndefined(widgetInfo) && !isNullOrUndefined(widgetInfo[0])? widgetInfo[0].color : "ffff00"; + this.renderBookmark(this.getScaledValue(xLeft, 1),this.getScaledValue(position.y, 2),this.getScaledValue(lastLine.height - lastLine.margin.bottom),0,color); + } } } private checkHeaderFooterLineWidget(widget: IWidget, keys: IWidget[]): IWidget { @@ -930,7 +1008,7 @@ export class Renderer { } } } - private renderLine(lineWidget: LineWidget, page: Page, left: number, top: number): void { + private renderLine(lineWidget: LineWidget, page: Page, left: number, top: number): void { this.renderSelectionHighlight(page, lineWidget, top); let paraFormat: WParagraphFormat = lineWidget.paragraph.paragraphFormat; let x: number = left; @@ -976,8 +1054,8 @@ export class Renderer { this.renderSearchHighlight(page, lineWidget, top); // EditRegion highlight this.renderEditRegionHighlight(page, lineWidget, top); - let isCommentMark: boolean = false; - + let commentIDList: string[]=[]; + let children: ElementBox[] = lineWidget.renderedElements; let underlineY: number = this.getUnderlineYPosition(lineWidget); let bookmarks: any = []; @@ -1000,7 +1078,16 @@ export class Renderer { let style: string = 'display:block;position:absolute;'; let topPosition: string = this.getScaledValue((top) + (page.boundingRectangle.y - (pageGap * (page.index + 1)))) + (pageGap * (page.index + 1)) + 'px;'; - if (elementBox instanceof EditRangeStartElementBox) { + if (elementBox instanceof EditRangeStartElementBox && (this.documentHelper.owner.currentUser === elementBox.user || (elementBox.group === "Everyone" && elementBox.user === ""))) { + if(this.documentHelper.owner.documentEditorSettings.highlightEditableRanges && elementBox.columnFirst==-1 ){ + var height = elementBox.line.height - elementBox.line.margin.bottom; + let xLeft = left; + let yTop = top; + let highlighters = page.documentHelper.selection.editRegionHighlighters; + let widgetInfo : SelectionWidgetInfo[]= !isNullOrUndefined(highlighters)? highlighters.get(lineWidget) : []; + let color : string = !isNullOrUndefined(widgetInfo) && !isNullOrUndefined(widgetInfo[0])? widgetInfo[0].color : "ffff00"; + this.renderBookmark(this.getScaledValue(xLeft, 1),this.getScaledValue(yTop, 2),this.getScaledValue(lineWidget.height - lineWidget.margin.bottom),0,color); + } if (this.documentHelper.owner.enableLockAndEdit) { let l10n: L10n = new L10n('documenteditor', this.documentHelper.owner.defaultLocale); l10n.setLocale(this.documentHelper.owner.locale); @@ -1023,9 +1110,7 @@ export class Renderer { } } else if (elementBox instanceof CommentCharacterElementBox && elementBox.commentType === 0 && this.documentHelper.owner.selectionModule) { - if (this.documentHelper.owner.enableComment && !isCommentMark) { - isCommentMark = true; - elementBox.renderCommentMark(); + if (this.documentHelper.owner.enableComment ) { let rightMargin: number = HelperMethods.convertPointToPixel(page.bodyWidgets[0].sectionFormat.rightMargin); let pageWidth: number = HelperMethods.convertPointToPixel(page.bodyWidgets[0].sectionFormat.pageWidth); @@ -1035,7 +1120,11 @@ export class Renderer { leftPosition = (page.boundingRectangle.width - (this.viewer.padding.right * 2) - (this.viewer.padding.left * 2)) + 'px;'; } style = style + 'left:' + leftPosition + 'top:' + topPosition; - elementBox.commentMark.setAttribute('style', style); + if (commentIDList.indexOf(elementBox.commentId) === -1 && !isNullOrUndefined(elementBox.comment) && !elementBox.comment.isReply) { + commentIDList.push(elementBox.commentId); + elementBox.renderCommentMark(topPosition, leftPosition); + elementBox.commentMark.setAttribute('style', style); + } } else { if (elementBox.commentMark) { elementBox.commentMark.setAttribute('style', 'display:none'); @@ -1044,6 +1133,17 @@ export class Renderer { } } + if (elementBox instanceof EditRangeEndElementBox && (this.documentHelper.owner.currentUser === elementBox.editRangeStart.user || (elementBox.editRangeStart.group === "Everyone" && elementBox.editRangeStart.user === ""))) { + if (elementBox.editRangeStart.columnFirst==-1 && this.documentHelper.owner.documentEditorSettings.highlightEditableRanges) { + var height = elementBox.line.height - elementBox.line.margin.bottom; + let xLeft = left; + let yTop = top; + let highlighters = page.documentHelper.selection.editRegionHighlighters; + let widgetInfo : SelectionWidgetInfo[]= !isNullOrUndefined(highlighters)? highlighters.get(lineWidget) : []; + let color : string = !isNullOrUndefined(widgetInfo) && !isNullOrUndefined(widgetInfo[0])? widgetInfo[0].color : "ffff00"; + this.renderBookmark(this.getScaledValue(xLeft, 1),this.getScaledValue(yTop, 2),this.getScaledValue(lineWidget.height - lineWidget.margin.bottom),1,color); + } + } if (elementBox instanceof BookmarkElementBox && this.documentHelper.owner.documentEditorSettings.showBookmarks) { var height = elementBox.line.height - elementBox.line.margin.bottom; let xLeft = left; @@ -1284,7 +1384,12 @@ export class Renderer { x -= this.documentHelper.textHelper.getWidth(text, currentCharFormat, FontScriptType.English); } this.pageContext.font = characterFont; - this.pageContext.fillText(text, this.getScaledValue(x, 1), this.getScaledValue(y, 2)); + let scaleFactor: number = currentCharFormat.scaling < 100 ? 1 : currentCharFormat.scaling / 100; + (this.pageContext as any).letterSpacing = currentCharFormat.characterSpacing * this.documentHelper.zoomFactor + 'pt'; + this.pageContext.save(); + this.pageContext.scale(scaleFactor, 1); + this.pageContext.fillText(text, this.getScaledValue(x, 1)/(scaleFactor), this.getScaledValue(y, 2)); + this.pageContext.restore(); } } } @@ -1321,7 +1426,22 @@ export class Renderer { } return false; } - private renderBookmark(x: number, y: number, height: number, type: number): void { + private combineHexColors(color1: string, color2: string):string{ + const hex1 = color1.replace("#", ""); + const hex2 = color2.replace("#", ""); + const r1 = parseInt(hex1.substring(0, 2), 16); + const g1 = parseInt(hex1.substring(2, 4), 16); + const b1 = parseInt(hex1.substring(4, 6), 16); + const r2 = parseInt(hex2.substring(0, 2), 16); + const g2 = parseInt(hex2.substring(2, 4), 16); + const b2 = parseInt(hex2.substring(4, 6), 16); + const r = Math.round((r1 * 0.35) + (r2 * 0.65)); + const g = Math.round((g1 * 0.35) + (g2 * 0.65)); + const b = Math.round((b1 * 0.35) + (b2 * 0.65)); + const mixedColor = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; + return mixedColor; + } + private renderBookmark(x: number, y: number, height: number, type: number,restrictColor?:string): void { if(this.isPrinting) { return; } @@ -1342,7 +1462,12 @@ export class Renderer { } this.pageContext.strokeStyle = "#7F7F7F"; this.pageContext.stroke(); - this.pageContext.closePath(); + this.pageContext.closePath(); + if(!isNullOrUndefined(restrictColor)){ + const combinedColor = this.combineHexColors(restrictColor,"#7F7F7F") + this.pageContext.fillStyle = combinedColor; + this.pageContext.fillRect(x, y, 1.5, height); + } } private retriveCharacterformat(character: WCharacterFormat, fontSizeFactor?: number): string { if(isNullOrUndefined(fontSizeFactor)){ @@ -1422,7 +1547,7 @@ export class Renderer { this.pageContext.fillStyle = HelperMethods.getColor(highlightColor); } - this.pageContext.fillRect(Math.floor(this.getScaledValue(left + leftMargin, 1) - 1), Math.floor(this.getScaledValue(top + topMargin, 2) - 1), Math.ceil(this.getScaledValue(elementBox.width) + 1), Math.ceil(this.getScaledValue(elementBox.height) + 1)); + this.pageContext.fillRect(Math.floor(this.getScaledValue(left + leftMargin, 1)), Math.floor(this.getScaledValue(top + topMargin, 2) - 1), Math.ceil(this.getScaledValue(elementBox.width) + 1), Math.ceil(this.getScaledValue(elementBox.height) + 1)); } this.pageContext.font = bold + ' ' + italic + ' ' + fontSize + 'pt' + ' ' + '"' + fontFamily + '"'; if (baselineAlignment === 'Subscript') { @@ -1443,13 +1568,22 @@ export class Renderer { } else { this.pageContext.fillStyle = HelperMethods.getColor(color); } + let scaleFactor: number = format.scaling < 100 ? 1 : format.scaling / 100; if (this.documentHelper.owner.documentEditorSettings.showHiddenMarks && !this.isPrinting) { if (elementBox instanceof ListTextElementBox && elementBox.text === "\t") { this.tabMark(elementBox, format, left, top, leftMargin, topMargin); } - this.pageContext.fillText(this.replaceSpace(text), this.getScaledValue(left + leftMargin, 1), this.getScaledValue(top + topMargin, 2), this.getScaledValue(elementBox.width)); + (this.pageContext as any).letterSpacing = format.characterSpacing * this.documentHelper.zoomFactor + 'pt'; + this.pageContext.save(); + this.pageContext.scale(scaleFactor, 1); + this.pageContext.fillText(this.replaceSpace(text), this.getScaledValue(left + leftMargin, 1)/scaleFactor, this.getScaledValue(top + topMargin, 2), this.getScaledValue(elementBox.width)); + this.pageContext.restore(); } else { - this.pageContext.fillText(text, this.getScaledValue(left + leftMargin, 1), this.getScaledValue(top + topMargin, 2), this.getScaledValue(elementBox.width)); + (this.pageContext as any).letterSpacing = format.characterSpacing * this.documentHelper.zoomFactor + 'pt'; + this.pageContext.save(); + this.pageContext.scale(scaleFactor, 1); + this.pageContext.fillText(text, this.getScaledValue(left + leftMargin, 1)/scaleFactor, this.getScaledValue(top + topMargin, 2), this.getScaledValue(elementBox.width)); + this.pageContext.restore(); } if (isParaBidi) { this.pageContext.direction = 'ltr'; @@ -1491,7 +1625,7 @@ export class Renderer { this.pageContext.fillStyle = HelperMethods.getColor(format.highlightColor); } - this.pageContext.fillRect(Math.floor(this.getScaledValue(left + leftMargin, 1) - 1), Math.floor(this.getScaledValue(top + topMargin, 2) - 1), Math.ceil(this.getScaledValue(elementBox.width) + 1), Math.ceil(this.getScaledValue(elementBox.height) + 1)); + this.pageContext.fillRect(Math.floor(this.getScaledValue(left + leftMargin, 1)), Math.floor(this.getScaledValue(top + topMargin, 2) - 1), Math.ceil(this.getScaledValue(elementBox.width) + 1), Math.ceil(this.getScaledValue(elementBox.height) + 1)); } let revisionInfo: RevisionInfo[] = this.checkRevisionType(elementBox); @@ -1543,13 +1677,22 @@ export class Renderer { ((characterRange & CharacterRangeType.RightToLeft) == CharacterRangeType.RightToLeft))) && format.bidi) { text = this.inverseCharacter(text); } + let scaleFactor: number = format.scaling < 100 ? 1 : format.scaling / 100; if (this.documentHelper.owner.documentEditorSettings.showHiddenMarks && !this.isPrinting) { if ((elementBox instanceof TabElementBox || elementBox instanceof TextElementBox) && elementBox.text === "\t") { this.tabMark(elementBox, format, left, top, leftMargin, topMargin); } - this.pageContext.fillText(this.replaceSpace(text), this.getScaledValue(left + leftMargin, 1), this.getScaledValue(top + topMargin, 2), scaledWidth); + (this.pageContext as any).letterSpacing = format.characterSpacing * this.documentHelper.zoomFactor + 'pt'; + this.pageContext.save(); + this.pageContext.scale(scaleFactor, 1); + this.pageContext.fillText(this.replaceSpace(text), this.getScaledValue(left + leftMargin, 1)/(scaleFactor), this.getScaledValue(top + topMargin, 2), scaledWidth); + this.pageContext.restore(); } else { - this.pageContext.fillText(text, this.getScaledValue(left + leftMargin, 1), this.getScaledValue(top + topMargin, 2), scaledWidth); + (this.pageContext as any).letterSpacing = format.characterSpacing * this.documentHelper.zoomFactor + 'pt'; + this.pageContext.save(); + this.pageContext.scale(scaleFactor, 1); + this.pageContext.fillText(text, this.getScaledValue(left + leftMargin, 1)/(scaleFactor), this.getScaledValue(top + topMargin, 2), scaledWidth); + this.pageContext.restore(); } if (this.documentHelper.owner.isSpellCheck) { if (((this.documentHelper.owner.isSpellCheck && !this.spellChecker.removeUnderline) && (this.documentHelper.triggerSpellCheck || elementBox.canTrigger) && elementBox.text !== ' ' && !this.documentHelper.isScrollHandler && (isNullOrUndefined(elementBox.previousNode) || !(elementBox.previousNode instanceof FieldElementBox)) @@ -1563,7 +1706,7 @@ export class Renderer { let backgroundColor: string = (containerWidget instanceof TableCellWidget) ? (containerWidget as TableCellWidget).cellFormat.shading.backgroundColor : this.documentHelper.backgroundColor; for (let i: number = 0; i < errorDetails.elements.length; i++) { let currentElement: ErrorTextElementBox = errorDetails.elements[i]; - if (elementBox.ignoreOnceItems.indexOf(HelperMethods.manageSpecialCharacters(currentElement.text, undefined, true)) === -1) { + if (elementBox.ignoreOnceItems.indexOf(this.spellChecker.manageSpecialCharacters(currentElement.text, undefined, true)) === -1) { this.renderWavyLine(currentElement, (isNullOrUndefined(currentElement.start)) ? left : currentElement.start.location.x, (isNullOrUndefined(currentElement.start)) ? top : currentElement.start.location.y - elementBox.margin.top, underlineY, color, 'Single', format.baselineAlignment, backgroundColor); } } @@ -1596,11 +1739,16 @@ export class Renderer { let availableSpaceWidth = elementBox.width / 2; let tabWidth = tabMarkWidth / 2; this.pageContext.font = this.retriveCharacterformat(elementBox.characterFormat); + (this.pageContext as any).letterSpacing = format.characterSpacing * this.documentHelper.zoomFactor + 'pt'; + this.pageContext.save(); + let scaleFactor: number = format.scaling < 100 ? 1 : format.scaling / 100; + this.pageContext.scale(scaleFactor, 1); if (availableSpaceWidth > tabMarkWidth) { - this.pageContext.fillText(tabMarkString, this.getScaledValue(((left + leftMargin + availableSpaceWidth) - (tabWidth)), 1), this.getScaledValue(top + topMargin, 2)); + this.pageContext.fillText(tabMarkString, this.getScaledValue(((left + leftMargin + availableSpaceWidth) - (tabWidth)), 1)/scaleFactor, this.getScaledValue(top + topMargin, 2)); } else { - this.pageContext.fillText(tabMarkString, this.getScaledValue(left + leftMargin, 1), this.getScaledValue(top + topMargin, 2), this.getScaledValue(elementBox.width)); + this.pageContext.fillText(tabMarkString, this.getScaledValue(left + leftMargin, 1)/scaleFactor, this.getScaledValue(top + topMargin, 2), this.getScaledValue(elementBox.width)); } + this.pageContext.restore(); } private replaceSpace(text: string) { text = text.replace(new RegExp(String.fromCharCode(32), 'g'), String.fromCharCode(183)); @@ -1691,7 +1839,7 @@ export class Renderer { if (splittedText.length > 1) { for (let i: number = 0; i < splittedText.length; i++) { let currentText: string = splittedText[i]; - let retrievedText: string = HelperMethods.manageSpecialCharacters(currentText, undefined, true); + let retrievedText: string = this.spellChecker.manageSpecialCharacters(currentText, undefined, true); if (this.spellChecker.ignoreAllItems.indexOf(retrievedText) === -1 && elementBox.ignoreOnceItems.indexOf(retrievedText) === -1) { this.handleUnorderedElements(retrievedText, elementBox, underlineY, i, markindex, i === splittedText.length - 1, beforeIndex); @@ -1699,7 +1847,7 @@ export class Renderer { } } } else { - let retrievedText: string = HelperMethods.manageSpecialCharacters(checkText, undefined, true); + let retrievedText: string = this.spellChecker.manageSpecialCharacters(checkText, undefined, true); if (checkText.length > 0) { if (this.spellChecker.ignoreAllItems.indexOf(retrievedText) === -1 && elementBox.ignoreOnceItems.indexOf(retrievedText) === -1) { @@ -1994,7 +2142,7 @@ export class Renderer { } catch (e) { elementBox.imageString = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAgVBMVEX///8AAADgAADY2Njl5eVcXFxjY2NZWVl/f3+wsLCmpqb4+PiioqKpqam7u7vV1dX2uLj2wsLhFRXzpKT3vb30sbHhCwv74+P40dH+9vbkIyO2trbBwcHLy8tsbGycnJz529v4zMzrbGzlLS3qZmblNzfrdXXoRkbvi4vvgYHlHh7CZsBOAAADpUlEQVR4nO3da1faQBSF4ekAUQlUEFs14AXxVv7/D6yaQiZx5mSEYXF2ut+PNKzyyK5diYDmR9czx34AB49C/CjE759w3jvvWr15Tdgz3atXE54f++EcIArxoxA/CvGjED8K8aMQPwrxoxA/CvGLEeZ9jPJdhfk4GyCUjb3ECGE/Q6m/q3DwfudjP0ERZYN9hKdn2hvd3+0jHJz5/kBVuTk96bbQUEjhYR9ckiikUH8UUqg/CinUH4UU6o9CCvVHIYX6o5BC/VFIof4opFB/FFKoPwop1B+FFOqPQgrjyxfjVC38Lxk9tnAxGqZqdKtSOE4GHA5/fuNJpDCtcNHbv4VqYYqPLjgfUViPQgrjozA2CptRSGF8/59w+Wrt+rr1btNna1cPzg0wwuXavncxabnX7PfHYYXzlYARvlobQZyUR9mXm+1NMEK7SSLONgcVV9vb8IQXv4J3KSeKKlxXxNCzONkeYp8AV3p9UT1+P3FWHVAsq5thhGZSEb1DrSZq7dS5HUdoLiuBZ6jORG3tCwAkNJfCUJ2Jrqe1P0ESCkMNTdSACYNDDU7UoAkDQw1P1MAJvUMVJmrwhJ6hShM1gMIvQxUnahCFjaHKEzWQQneoxR95ogZTWBuqPFEDKnSHKk/UoArdoYoTNbDC5lBDEzW4QjMpYiZqgIXG/S76JhwHK5zVVipcnkIVuv/RW/HyFKhwYhuFr6NiCmdNoDBUSGFjovJQEYXuRN9ahwoorJ8uSZenPsMTNk+X2q6jwgm/ntHL11HhhL4zenmoYEL/Gb04VCxh6KKTNFQoYfiikzBUJKF00Sk8VCChfF00OFQcYdt10dBQYYRT5xn0n9G7Q0X8GfCzNNEyZ6iPgD/HlydaVg11DfhajJaJlm2HugIUrlomWrYZKuJKHz6vHhbSM/hROdRnxNe1meuXYvW0DB6+aflYrB7dlzDiCM3N1dVN6GDhMCDhjlHYjEIK46MwNgqbUUhhfJ/vA07wO8N1vw94ONo/3e/lTpVOYfc/UyG//ZmqW52fi/FuTNW3/lZ+eguF+qOQQv1RSKH+KKRQfxRSqD8KKdQfhRTqj0IK9UchhfqjkEL9UUih/iikUH8UUqg/CmXh6Hsv3jlK+wnvD/vgkrSHMMuyu1P9ZdmuwnycDQYn+svG3n9KEUKT9zHyf6+IEWJHIX4U4kchfhTiRyF+FOJHIX4U4kchfnVhijeZa6sunCf4ZdPamteEHY5C/CjEr/vCv0ec0g+AtS1QAAAAAElFTkSuQmCC'; - + this.documentHelper.addBase64StringInCollection(elementBox); elementBox.element.src = this.documentHelper.getImageString(elementBox); this.pageContext.drawImage(elementBox.element, this.getScaledValue(left + leftMargin, 1), this.getScaledValue(top + topMargin, 2), this.getScaledValue(elementBox.width), this.getScaledValue(elementBox.height)); 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 cd3498030a..5d985b7c30 100644 --- a/controls/documenteditor/src/document-editor/implementation/viewer/sfdt-reader.ts +++ b/controls/documenteditor/src/document-editor/implementation/viewer/sfdt-reader.ts @@ -16,15 +16,16 @@ import { ChartSeriesFormat, ElementBox, CommentCharacterElementBox, CommentElementBox, FormField, TextFormField, CheckBoxFormField, DropDownFormField, ShapeElementBox, LineFormat, TextFrame, ContentControlProperties, ContentControlListItems, ContentControl, IWidget, CheckBoxState, XmlMapping, CustomXmlPart, Footnote, FootnoteElementBox, FillFormat, - TablePosition + TablePosition, + BreakElementBox } from './page'; import { HelperMethods } from '../editor/editor-helper'; import { Dictionary } from '../../base/dictionary'; import { ChartComponent } from '@syncfusion/ej2-office-chart'; import { Revision } from '../track-changes/track-changes'; -import { AutoShapeType, BaselineAlignment, BiDirectionalOverride, CellVerticalAlignment, CheckBoxSizeType, CompatibilityMode, ContentControlType, FollowCharacterType, FootEndNoteNumberFormat, FootnoteRestartIndex, FootnoteType, HeightType, HighlightColor, HorizontalAlignment, HorizontalOrigin, LineDashing, LineFormatType, LineSpacingType, LineStyle, ListLevelPattern, OutlineLevel, ProtectionType, RevisionType, Strikethrough, StyleType, TabJustification, TabLeader, TableAlignment, TextAlignment, TextFormFieldType, TextureStyle, TextWrappingStyle, TextWrappingType, Underline, VerticalAlignment, VerticalOrigin, WidthType } from '../../base/types'; +import { AutoShapeType, BaselineAlignment, BiDirectionalOverride, BreakClearType, CellVerticalAlignment, CheckBoxSizeType, CompatibilityMode, ContentControlType, FollowCharacterType, FootEndNoteNumberFormat, FootnoteRestartIndex, FootnoteType, HeightType, HighlightColor, HorizontalAlignment, HorizontalOrigin, LineDashing, LineFormatType, LineSpacingType, LineStyle, ListLevelPattern, OutlineLevel, ProtectionType, RevisionType, Strikethrough, StyleType, TabJustification, TabLeader, TableAlignment, TextAlignment, TextFormFieldType, TextureStyle, TextWrappingStyle, TextWrappingType, Underline, VerticalAlignment, VerticalOrigin, WidthType } from '../../base/types'; import { Themes, FontSchemeStruct, MajorMinorFontScheme } from '../index'; -import { sectionsProperty, imagesProperty, fontSubstitutionTableProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, backgroundProperty, stylesProperty, commentsProperty, revisionsProperty, customXmlProperty, defaultTabWidthProperty, formattingProperty, trackChangesProperty, protectionTypeProperty, enforcementProperty, hashValueProperty, saltValueProperty, cryptProviderTypeProperty, cryptAlgorithmClassProperty, cryptAlgorithmTypeProperty, cryptAlgorithmSidProperty, cryptSpinCountProperty, doNotUseHTMLParagraphAutoSpacingProperty, alignTablesRowByRowProperty, formFieldShadingProperty, lastParagraphMarkCopiedProperty, footnotesProperty, endnotesProperty, compatibilityModeProperty, themeFontLanguagesProperty, themesProperty, nameProperty, basedOnProperty, nextProperty, linkProperty, localeIdProperty, localeIdFarEastProperty, localeIdBidiProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, bidiProperty, bdoProperty, fontSizeBidiProperty, fontFamilyBidiProperty, boldBidiProperty, italicBidiProperty, allCapsProperty, complexScriptProperty, fontFamilyAsciiProperty, fontFamilyFarEastProperty, fontFamilyNonFarEastProperty, revisionIdsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, spaceAfterAutoProperty, spaceBeforeAutoProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, keepWithNextProperty, widowControlProperty, keepLinesTogetherProperty, outlineLevelProperty, contextualSpacingProperty, bordersProperty, tabsProperty, headerDistanceProperty, footerDistanceProperty, differentFirstPageProperty, differentOddAndEvenPagesProperty, pageWidthProperty, pageHeightProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, restartPageNumberingProperty, pageStartingNumberProperty, endnoteNumberFormatProperty, footNoteNumberFormatProperty, restartIndexForFootnotesProperty, restartIndexForEndnotesProperty, initialFootNoteNumberProperty, initialEndNoteNumberProperty, pageNumberStyleProperty, columnsProperty, numberOfColumnsProperty, equalWidthProperty, lineBetweenColumnsProperty, breakCodeProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, allowBreakAcrossPagesProperty, isHeaderProperty, heightTypeProperty, beforeWidthProperty, afterWidthProperty, gridBeforeProperty, gridBeforeWidthProperty, gridBeforeWidthTypeProperty, gridAfterProperty, gridAfterWidthProperty, gridAfterWidthTypeProperty, allowAutoFitProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, horizontalPositionAbsProperty, textureProperty, backgroundColorProperty, foregroundColorProperty, shadowProperty, hasNoneStyleProperty, verticalProperty, horizontalProperty, diagonalUpProperty, diagonalDownProperty, lineStyleProperty, lineWidthProperty, layoutProperty, dataFormatProperty, yValueProperty, chartDataProperty, categoryXNameProperty, lineProperty, foreColorProperty, patternProperty, layoutXProperty, layoutYProperty, directionProperty, endStyleProperty, numberValueProperty, markerStyleProperty, markerColorProperty, markerSizeProperty, forwardProperty, backwardProperty, interceptProperty, isDisplayRSquaredProperty, isDisplayEquationProperty, seriesNameProperty, dataLabelProperty, errorBarProperty, seriesFormatProperty, trendLinesProperty, dataPointsProperty, firstSliceAngleProperty, holeSizeProperty, isLegendKeyProperty, isBubbleSizeProperty, isCategoryNameProperty, isSeriesNameProperty, isValueProperty, isPercentageProperty, isLeaderLinesProperty, showSeriesKeysProperty, hasHorizontalBorderProperty, hasVerticalBorderProperty, hasBordersProperty, categoryTypeProperty, chartCategoryProperty, chartSeriesProperty, chartAreaProperty, chartTitleAreaProperty, plotAreaProperty, chartLegendProperty, chartPrimaryCategoryAxisProperty, chartPrimaryValueAxisProperty, chartTitleProperty, chartTypeProperty, gapWidthProperty, overlapProperty, chartDataTableProperty, textProperty, shapeIdProperty, alternativeTextProperty, visibleProperty, widthProperty, heightProperty, widthScaleProperty, heightScaleProperty, lineFormatProperty, fillFormatProperty, textWrappingStyleProperty, textWrappingTypeProperty, verticalRelativePercentProperty, horizontalRelativePercentProperty, zOrderPositionProperty, layoutInCellProperty, lockAnchorProperty, autoShapeTypeProperty, textFrameProperty, colorProperty, fillProperty, textVerticalAlignmentProperty, imageStringProperty, metaFileImageStringProperty, lengthProperty, isInlineImageProperty, isMetaFileProperty, topProperty, bottomProperty, rightProperty, leftProperty, getImageHeightProperty, getImageWidthProperty, hasFieldEndProperty, formFieldDataProperty, fieldTypeProperty, enabledProperty, helpTextProperty, statusTextProperty, textInputProperty, checkBoxProperty, dropDownListProperty, maxLengthProperty, defaultValueProperty, formatProperty, sizeTypeProperty, sizeProperty, checkedProperty, dropDownItemsProperty, selectedIndexProperty, commentIdProperty, commentCharacterTypeProperty, authorProperty, initialProperty, dateProperty, doneProperty, replyCommentsProperty, revisionTypeProperty, revisionIdProperty, itemIDProperty, xmlProperty, footnoteTypeProperty, symbolCodeProperty, symbolFontNameProperty, customMarkerProperty, inlinesProperty, contentControlPropertiesProperty, lockContentControlProperty, lockContentsProperty, tagProperty, titleProperty, hasPlaceHolderTextProperty, multiLineProperty, isTemporaryProperty, dateCalendarTypeProperty, dateStorageFormatProperty, dateDisplayLocaleProperty, dateDisplayFormatProperty, isCheckedProperty, uncheckedStateProperty, checkedStateProperty, contentControlListItemsProperty, xmlMappingProperty, fontProperty, valueProperty, displayTextProperty, isMappedProperty, isWordMlProperty, prefixMappingProperty, xPathProperty, storeItemIdProperty, customXmlPartProperty, idProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, descriptionProperty, wrapTextAroundProperty, positioningProperty, tableFormatProperty, allowOverlapProperty, distanceTopProperty, distanceRightProperty, distanceLeftProperty, distanceBottomProperty, verticalOriginProperty, verticalPositionProperty, horizontalOriginProperty, horizontalAlignmentProperty, horizontalPositionProperty, blocksProperty, headerProperty, footerProperty, evenHeaderProperty, evenFooterProperty, firstPageHeaderProperty, firstPageFooterProperty, headersFootersProperty, sectionFormatProperty, listLevelPatternProperty, followCharacterProperty, startAtProperty, restartLevelProperty, levelNumberProperty, numberFormatProperty, abstractListIdProperty, levelsProperty, overrideListLevelProperty, levelOverridesProperty, separatorProperty, continuationSeparatorProperty, continuationNoticeProperty, bookmarkTypeProperty, propertiesProperty, tabJustificationProperty, positionProperty, deletePositionProperty, leaderProperty, tabLeaderProperty, editRangeIdProperty, columnFirstProperty, columnLastProperty, userProperty, groupProperty, editableRangeStartProperty, spaceProperty, fontSchemeProperty, fontSchemeNameProperty, majorFontSchemeProperty, minorFontSchemeProperty, fontSchemeListProperty, fontTypefaceProperty, typefaceProperty, panoseProperty, typeProperty, majorUnitProperty, maximumValueProperty, minimumValueProperty, hasMajorGridLinesProperty, hasMinorGridLinesProperty, majorTickMarkProperty, minorTickMarkProperty, tickLabelPositionProperty, rgbProperty, appearanceProperty, lineFormatTypeProperty, allowSpaceOfSameStyleInTableProperty, weightProperty, inlineFormatProperty, fontNameProperty, isCompressedProperty, columnIndexProperty, isAfterParagraphMarkProperty, isAfterRowMarkProperty, isAfterCellMarkProperty , isAfterTableMarkProperty, belowTextProperty } from '../../index'; +import { sectionsProperty, imagesProperty, fontSubstitutionTableProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, backgroundProperty, stylesProperty, commentsProperty, revisionsProperty, customXmlProperty, defaultTabWidthProperty, formattingProperty, trackChangesProperty, protectionTypeProperty, enforcementProperty, hashValueProperty, saltValueProperty, cryptProviderTypeProperty, cryptAlgorithmClassProperty, cryptAlgorithmTypeProperty, cryptAlgorithmSidProperty, cryptSpinCountProperty, doNotUseHTMLParagraphAutoSpacingProperty, alignTablesRowByRowProperty, formFieldShadingProperty, lastParagraphMarkCopiedProperty, footnotesProperty, endnotesProperty, compatibilityModeProperty, themeFontLanguagesProperty, themesProperty, nameProperty, basedOnProperty, nextProperty, linkProperty, localeIdProperty, localeIdFarEastProperty, localeIdBidiProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, bidiProperty, bdoProperty, fontSizeBidiProperty, fontFamilyBidiProperty, boldBidiProperty, italicBidiProperty, allCapsProperty, complexScriptProperty, fontFamilyAsciiProperty, fontFamilyFarEastProperty, fontFamilyNonFarEastProperty, revisionIdsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, spaceAfterAutoProperty, spaceBeforeAutoProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, keepWithNextProperty, widowControlProperty, keepLinesTogetherProperty, outlineLevelProperty, contextualSpacingProperty, bordersProperty, tabsProperty, headerDistanceProperty, footerDistanceProperty, differentFirstPageProperty, differentOddAndEvenPagesProperty, pageWidthProperty, pageHeightProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, restartPageNumberingProperty, pageStartingNumberProperty, endnoteNumberFormatProperty, footNoteNumberFormatProperty, restartIndexForFootnotesProperty, restartIndexForEndnotesProperty, initialFootNoteNumberProperty, initialEndNoteNumberProperty, pageNumberStyleProperty, columnsProperty, numberOfColumnsProperty, equalWidthProperty, lineBetweenColumnsProperty, breakCodeProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, allowBreakAcrossPagesProperty, isHeaderProperty, heightTypeProperty, beforeWidthProperty, afterWidthProperty, gridBeforeProperty, gridBeforeWidthProperty, gridBeforeWidthTypeProperty, gridAfterProperty, gridAfterWidthProperty, gridAfterWidthTypeProperty, allowAutoFitProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, horizontalPositionAbsProperty, textureProperty, backgroundColorProperty, foregroundColorProperty, shadowProperty, hasNoneStyleProperty, verticalProperty, horizontalProperty, diagonalUpProperty, diagonalDownProperty, lineStyleProperty, lineWidthProperty, layoutProperty, dataFormatProperty, yValueProperty, chartDataProperty, categoryXNameProperty, lineProperty, foreColorProperty, patternProperty, layoutXProperty, layoutYProperty, directionProperty, endStyleProperty, numberValueProperty, markerStyleProperty, markerColorProperty, markerSizeProperty, forwardProperty, backwardProperty, interceptProperty, isDisplayRSquaredProperty, isDisplayEquationProperty, seriesNameProperty, dataLabelProperty, errorBarProperty, seriesFormatProperty, trendLinesProperty, dataPointsProperty, firstSliceAngleProperty, holeSizeProperty, isLegendKeyProperty, isBubbleSizeProperty, isCategoryNameProperty, isSeriesNameProperty, isValueProperty, isPercentageProperty, isLeaderLinesProperty, showSeriesKeysProperty, hasHorizontalBorderProperty, hasVerticalBorderProperty, hasBordersProperty, categoryTypeProperty, chartCategoryProperty, chartSeriesProperty, chartAreaProperty, chartTitleAreaProperty, plotAreaProperty, chartLegendProperty, chartPrimaryCategoryAxisProperty, chartPrimaryValueAxisProperty, chartTitleProperty, chartTypeProperty, gapWidthProperty, overlapProperty, chartDataTableProperty, textProperty, shapeIdProperty, alternativeTextProperty, visibleProperty, widthProperty, heightProperty, widthScaleProperty, heightScaleProperty, lineFormatProperty, fillFormatProperty, textWrappingStyleProperty, textWrappingTypeProperty, verticalRelativePercentProperty, horizontalRelativePercentProperty, heightRelativePercentProperty, widthRelativePercentProperty, zOrderPositionProperty, layoutInCellProperty, lockAnchorProperty, autoShapeTypeProperty, textFrameProperty, colorProperty, fillProperty, textVerticalAlignmentProperty, imageStringProperty, metaFileImageStringProperty, lengthProperty, isInlineImageProperty, isMetaFileProperty, topProperty, bottomProperty, rightProperty, leftProperty, getImageHeightProperty, getImageWidthProperty, hasFieldEndProperty, formFieldDataProperty, fieldTypeProperty, enabledProperty, helpTextProperty, statusTextProperty, textInputProperty, checkBoxProperty, dropDownListProperty, maxLengthProperty, defaultValueProperty, formatProperty, sizeTypeProperty, sizeProperty, checkedProperty, dropDownItemsProperty, selectedIndexProperty, commentIdProperty, commentCharacterTypeProperty, authorProperty, initialProperty, dateProperty, doneProperty, replyCommentsProperty, revisionTypeProperty, revisionIdProperty, itemIDProperty, xmlProperty, footnoteTypeProperty, symbolCodeProperty, symbolFontNameProperty, customMarkerProperty, inlinesProperty, contentControlPropertiesProperty, lockContentControlProperty, lockContentsProperty, tagProperty, titleProperty, hasPlaceHolderTextProperty, multiLineProperty, isTemporaryProperty, dateCalendarTypeProperty, dateStorageFormatProperty, dateDisplayLocaleProperty, dateDisplayFormatProperty, isCheckedProperty, uncheckedStateProperty, checkedStateProperty, contentControlListItemsProperty, xmlMappingProperty, fontProperty, valueProperty, displayTextProperty, isMappedProperty, isWordMlProperty, prefixMappingProperty, xPathProperty, storeItemIdProperty, customXmlPartProperty, idProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, descriptionProperty, wrapTextAroundProperty, positioningProperty, tableFormatProperty, allowOverlapProperty, distanceTopProperty, distanceRightProperty, distanceLeftProperty, distanceBottomProperty, verticalOriginProperty, verticalPositionProperty, horizontalOriginProperty, horizontalAlignmentProperty, horizontalPositionProperty, blocksProperty, headerProperty, footerProperty, evenHeaderProperty, evenFooterProperty, firstPageHeaderProperty, firstPageFooterProperty, headersFootersProperty, sectionFormatProperty, listLevelPatternProperty, followCharacterProperty, startAtProperty, restartLevelProperty, levelNumberProperty, numberFormatProperty, abstractListIdProperty, levelsProperty, overrideListLevelProperty, levelOverridesProperty, separatorProperty, continuationSeparatorProperty, continuationNoticeProperty, bookmarkTypeProperty, propertiesProperty, tabJustificationProperty, positionProperty, deletePositionProperty, leaderProperty, tabLeaderProperty, editRangeIdProperty, columnFirstProperty, columnLastProperty, userProperty, groupProperty, editableRangeStartProperty, spaceProperty, fontSchemeProperty, fontSchemeNameProperty, majorFontSchemeProperty, minorFontSchemeProperty, fontSchemeListProperty, fontTypefaceProperty, typefaceProperty, panoseProperty, typeProperty, majorUnitProperty, maximumValueProperty, minimumValueProperty, hasMajorGridLinesProperty, hasMinorGridLinesProperty, majorTickMarkProperty, minorTickMarkProperty, tickLabelPositionProperty, rgbProperty, appearanceProperty, lineFormatTypeProperty, allowSpaceOfSameStyleInTableProperty, weightProperty, inlineFormatProperty, fontNameProperty, isCompressedProperty, columnIndexProperty, isAfterParagraphMarkProperty, isAfterRowMarkProperty, isAfterCellMarkProperty , isAfterTableMarkProperty, belowTextProperty, breakClearTypeProperty, characterSpacingProperty, scalingProperty } from '../../index'; import { ZipArchive, ZipArchiveItem } from '@syncfusion/ej2-compression'; /** * @private @@ -200,7 +201,13 @@ export class SfdtReader { */ public parseImages(data: any): void { for (let img in data) { - this.documentHelper.images.add(parseInt(img), data[`${img}`]); + if (Array.isArray(data[`${img}`])) { + this.documentHelper.images.add(parseInt(img), data[`${img}`]); + } else { + let images: string[] = []; + images.push(data[`${img}`]); + this.documentHelper.images.add(parseInt(img), images); + } } } private parseEndtnotes(data: any, endnote: Footnote): void { @@ -589,7 +596,7 @@ export class SfdtReader { } } } - public parseBody(data: any, blocks: BlockWidget[], container?: Widget, isSectionBreak?: boolean, contentControlProperties?: ContentControlProperties): void { + public parseBody(data: any, blocks: BlockWidget[], container?: Widget, isSectionBreak?: boolean, contentControlProperties?: ContentControlProperties, styles?: any): void { if (!isNullOrUndefined(data)) { for (let i: number = 0; i < data.length; i++) { const block: any = data[i]; @@ -614,6 +621,19 @@ export class SfdtReader { } styleObj = this.documentHelper.styles.findByName(styleName, 'Paragraph'); if (!isNullOrUndefined(styleObj)) { + if (this.isPaste && styles) { + for (let j = 0; j < styles.length; j++) { + if (styles[j][nameProperty[this.keywordIndex]] === styleName) { + var fontColor = styles[j][characterFormatProperty[this.keywordIndex]]; + if (fontColor[fontColorProperty[this.keywordIndex]] !== (styleObj as WCharacterStyle).characterFormat.fontColor) { + const charFormat: WCharacterFormat = new WCharacterFormat(); + this.parseCharacterFormat(this.keywordIndex, styles[j][characterFormatProperty[this.keywordIndex]], charFormat); + (styleObj as WCharacterStyle).characterFormat.copyFormat(charFormat); + break; + } + } + } + } paragraph.paragraphFormat.applyStyle(styleObj as WStyle); } blocks.push(paragraph); @@ -726,6 +746,10 @@ export class SfdtReader { } cellStartContentControl.line = (cell.firstChild as ParagraphWidget).firstChild as LineWidget; ((cell.firstChild as ParagraphWidget).firstChild as LineWidget).children.splice(0, 0, cellStartContentControl); + if ((cell.lastChild as ParagraphWidget).childWidgets.length === 0) { + const lineWidget: LineWidget = new LineWidget(cell.lastChild as ParagraphWidget); + (cell.lastChild as ParagraphWidget).childWidgets.push(lineWidget); + } cellEndContentControl.line = (cell.lastChild as ParagraphWidget).lastChild as LineWidget; ((cell.lastChild as ParagraphWidget).lastChild as LineWidget).children.push(cellEndContentControl); } @@ -916,8 +940,8 @@ export class SfdtReader { let trackChange: boolean = this.viewer.owner.enableTrackChanges; for (let i: number = 0; i < data.length; i++) { let inline: any = data[i]; - if (inline.hasOwnProperty(textProperty[this.keywordIndex])) { - let textElement: FieldTextElementBox | TextElementBox | TabElementBox = undefined; + if (inline.hasOwnProperty(textProperty[this.keywordIndex]) || inline.hasOwnProperty(breakClearTypeProperty[this.keywordIndex])) { + let textElement: any = undefined; if (this.documentHelper.isPageField) { textElement = new FieldTextElementBox(); (textElement as FieldTextElementBox).fieldBegin = this.documentHelper.fieldStacks[this.documentHelper.fieldStacks.length - 1]; @@ -927,13 +951,18 @@ export class SfdtReader { } else if (inline[textProperty[this.keywordIndex]] === '\f' && this.isPageBreakInsideTable) { continue; } else { - textElement = new TextElementBox(); + if (inline.hasOwnProperty(breakClearTypeProperty[this.keywordIndex])) { + textElement = new BreakElementBox(); + textElement.breakClearType = this.getBreakClearType(inline[breakClearTypeProperty[this.keywordIndex]]); + } else { + textElement = new TextElementBox(); + } } textElement.characterFormat = new WCharacterFormat(textElement); this.parseCharacterFormat(this.keywordIndex, inline[characterFormatProperty[this.keywordIndex]], textElement.characterFormat, writeInlineFormat); this.applyCharacterStyle(inline, textElement); - textElement.text = inline[textProperty[this.keywordIndex]]; - if (this.isHtmlPaste && textElement instanceof TextElementBox) { + textElement.text = textElement instanceof BreakElementBox ? "\v" : inline[textProperty[this.keywordIndex]]; + if (this.isHtmlPaste && (textElement instanceof TextElementBox || textElement instanceof BreakElementBox)) { let previousElement: ElementBox; if (lineWidget.children.length > 0) { previousElement = lineWidget.children[lineWidget.children.length - 1]; @@ -1043,7 +1072,12 @@ export class SfdtReader { if (!isValidImage) { image.imageString = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAgVBMVEX///8AAADgAADY2Njl5eVcXFxjY2NZWVl/f3+wsLCmpqb4+PiioqKpqam7u7vV1dX2uLj2wsLhFRXzpKT3vb30sbHhCwv74+P40dH+9vbkIyO2trbBwcHLy8tsbGycnJz529v4zMzrbGzlLS3qZmblNzfrdXXoRkbvi4vvgYHlHh7CZsBOAAADpUlEQVR4nO3da1faQBSF4ekAUQlUEFs14AXxVv7/D6yaQiZx5mSEYXF2ut+PNKzyyK5diYDmR9czx34AB49C/CjE759w3jvvWr15Tdgz3atXE54f++EcIArxoxA/CvGjED8K8aMQPwrxoxA/CvGLEeZ9jPJdhfk4GyCUjb3ECGE/Q6m/q3DwfudjP0ERZYN9hKdn2hvd3+0jHJz5/kBVuTk96bbQUEjhYR9ckiikUH8UUqg/CinUH4UU6o9CCvVHIYX6o5BC/VFIof4opFB/FFKoPwop1B+FFOqPQgrjyxfjVC38Lxk9tnAxGqZqdKtSOE4GHA5/fuNJpDCtcNHbv4VqYYqPLjgfUViPQgrjozA2CptRSGF8/59w+Wrt+rr1btNna1cPzg0wwuXavncxabnX7PfHYYXzlYARvlobQZyUR9mXm+1NMEK7SSLONgcVV9vb8IQXv4J3KSeKKlxXxNCzONkeYp8AV3p9UT1+P3FWHVAsq5thhGZSEb1DrSZq7dS5HUdoLiuBZ6jORG3tCwAkNJfCUJ2Jrqe1P0ESCkMNTdSACYNDDU7UoAkDQw1P1MAJvUMVJmrwhJ6hShM1gMIvQxUnahCFjaHKEzWQQneoxR95ogZTWBuqPFEDKnSHKk/UoArdoYoTNbDC5lBDEzW4QjMpYiZqgIXG/S76JhwHK5zVVipcnkIVuv/RW/HyFKhwYhuFr6NiCmdNoDBUSGFjovJQEYXuRN9ahwoorJ8uSZenPsMTNk+X2q6jwgm/ntHL11HhhL4zenmoYEL/Gb04VCxh6KKTNFQoYfiikzBUJKF00Sk8VCChfF00OFQcYdt10dBQYYRT5xn0n9G7Q0X8GfCzNNEyZ6iPgD/HlydaVg11DfhajJaJlm2HugIUrlomWrYZKuJKHz6vHhbSM/hROdRnxNe1meuXYvW0DB6+aflYrB7dlzDiCM3N1dVN6GDhMCDhjlHYjEIK46MwNgqbUUhhfJ/vA07wO8N1vw94ONo/3e/lTpVOYfc/UyG//ZmqW52fi/FuTNW3/lZ+eguF+qOQQv1RSKH+KKRQfxRSqD8KKdQfhRTqj0IK9UchhfqjkEL9UUih/iikUH8UUqg/CmXh6Hsv3jlK+wnvD/vgkrSHMMuyu1P9ZdmuwnycDQYn+svG3n9KEUKT9zHyf6+IEWJHIX4U4kchfhTiRyF+FOJHIX4U4kchfnVhijeZa6sunCf4ZdPamteEHY5C/CjEr/vCv0ec0g+AtS1QAAAAAElFTkSuQmCC'; } else { - image.imageString = inline[imageStringProperty[this.keywordIndex]]; + if(this.isPaste && !isNullOrUndefined(this.documentHelper.owner.editor.pasteImageIndex)) { + image.imageString = this.documentHelper.owner.editor.pasteImageIndex.get(inline[imageStringProperty[this.keywordIndex]]); + } + else { + image.imageString = inline[imageStringProperty[this.keywordIndex]]; + } } // Before 21.1 duplicate images are preserved as inline images with direct base64 string in the image string property. TO provide backward compatibility we are checking both the index based retrieval from images collections and inline image string. let imgStrValue: number = parseInt(inline[imageStringProperty[this.keywordIndex]]); @@ -1060,7 +1094,7 @@ export class SfdtReader { image.cropHeightScale = inline[getImageHeightProperty[this.keywordIndex]]; image.cropWidthScale = inline[getImageWidthProperty[this.keywordIndex]]; image.name = inline[nameProperty[this.keywordIndex]]; - image.alternativeText = inline[alternativeTextProperty[this.keywordIndex]]; + image.alternateText = inline[alternativeTextProperty[this.keywordIndex]]; image.title = inline[titleProperty[this.keywordIndex]]; image.visible = HelperMethods.parseBoolValue(inline[visibleProperty[this.keywordIndex]]); image.widthScale = inline[widthScaleProperty[this.keywordIndex]]; @@ -1072,8 +1106,12 @@ export class SfdtReader { image.horizontalOrigin = this.getHorizontalOrigin(inline[horizontalOriginProperty[this.keywordIndex]]); image.horizontalAlignment = this.getShapeHorizontalAlignment(inline[horizontalAlignmentProperty[this.keywordIndex]]); image.allowOverlap = HelperMethods.parseBoolValue(inline[allowOverlapProperty[this.keywordIndex]]); - image.textWrappingStyle = this.getTextWrappingStyle(inline[textWrappingStyleProperty[this.keywordIndex]]); - image.textWrappingType = this.getTextWrappingType(inline[textWrappingTypeProperty[this.keywordIndex]]); + if(!isNullOrUndefined(inline[textWrappingStyleProperty[this.keywordIndex]])) { + image.textWrappingStyle = this.getTextWrappingStyle(inline[textWrappingStyleProperty[this.keywordIndex]]); + } + if(!isNullOrUndefined(inline[textWrappingTypeProperty[this.keywordIndex]])) { + image.textWrappingType = this.getTextWrappingType(inline[textWrappingTypeProperty[this.keywordIndex]]); + } image.isBelowText = HelperMethods.parseBoolValue(inline[belowTextProperty[this.keywordIndex]]); if(!isNullOrUndefined(inline[distanceBottomProperty[this.keywordIndex]])) { image.distanceBottom = HelperMethods.convertPointToPixel(inline[distanceBottomProperty[this.keywordIndex]]); @@ -1241,6 +1279,9 @@ export class SfdtReader { let start: EditRangeStartElementBox = this.editableRanges.get(inline[editRangeIdProperty[this.keywordIndex]]); permEnd.editRangeStart = start; start.editRangeEnd = permEnd; + if (!isNullOrUndefined(inline[editRangeIdProperty[this.keywordIndex]])) { + permEnd.editRangeId = inline[editRangeIdProperty[this.keywordIndex]] + } this.editableRanges.remove(inline[editRangeIdProperty[this.keywordIndex]]); } lineWidget.children.push(permEnd); @@ -1306,11 +1347,14 @@ export class SfdtReader { let shape: ShapeElementBox = new ShapeElementBox(); shape.shapeId = inline[shapeIdProperty[this.keywordIndex]]; shape.name = inline[nameProperty[this.keywordIndex]]; - shape.alternativeText = inline[alternativeTextProperty[this.keywordIndex]]; + shape.alternateText = inline[alternativeTextProperty[this.keywordIndex]]; shape.title = inline[titleProperty[this.keywordIndex]]; shape.visible = HelperMethods.parseBoolValue(inline[visibleProperty[this.keywordIndex]]); shape.width = HelperMethods.convertPointToPixel(inline[widthProperty[this.keywordIndex]]); shape.height = HelperMethods.convertPointToPixel(inline[heightProperty[this.keywordIndex]]); + if (shape.height === 0) { + shape.isZeroHeight = true; + } shape.widthScale = inline[widthScaleProperty[this.keywordIndex]]; shape.heightScale = inline[heightScaleProperty[this.keywordIndex]]; shape.verticalPosition = HelperMethods.convertPointToPixel(inline[verticalPositionProperty[this.keywordIndex]]); @@ -1321,6 +1365,8 @@ export class SfdtReader { shape.horizontalOrigin = this.getHorizontalOrigin(inline[horizontalOriginProperty[this.keywordIndex]]); shape.horizontalAlignment = this.getShapeHorizontalAlignment(inline[horizontalAlignmentProperty[this.keywordIndex]]); shape.horizontalRelativePercent = inline[horizontalRelativePercentProperty[this.keywordIndex]]; + shape.heightRelativePercent = inline[heightRelativePercentProperty[this.keywordIndex]]; + shape.widthRelativePercent = inline[widthRelativePercentProperty[this.keywordIndex]]; shape.zOrderPosition = inline[zOrderPositionProperty[this.keywordIndex]]; shape.allowOverlap = HelperMethods.parseBoolValue(inline[allowOverlapProperty[this.keywordIndex]]); shape.textWrappingStyle = this.getTextWrappingStyle(inline[textWrappingStyleProperty[this.keywordIndex]]); @@ -1412,6 +1458,9 @@ export class SfdtReader { if (!isNullOrUndefined(data[columnLastProperty[this.keywordIndex]])) { permStart.columnLast = data[columnLastProperty[this.keywordIndex]]; } + if (!isNullOrUndefined(data[editRangeIdProperty[this.keywordIndex]])) { + permStart.editRangeId = data[editRangeIdProperty[this.keywordIndex]] + } if (!isNullOrUndefined(data[userProperty[this.keywordIndex]])) { permStart.user = data[userProperty[this.keywordIndex]]; if (this.documentHelper.userCollection.indexOf(permStart.user) === -1) { @@ -1796,6 +1845,15 @@ export class SfdtReader { sourceFormat[fontFamilyProperty[keyIndex]] = sourceFormat[fontFamilyProperty[keyIndex]].replace('"', ''); } characterFormat.fontFamily = sourceFormat[fontFamilyProperty[keyIndex]]; + if (isNullOrUndefined(sourceFormat[fontFamilyFarEastProperty[keyIndex]])) { + characterFormat.fontFamilyFarEast = sourceFormat[fontFamilyProperty[keyIndex]]; + } + if (isNullOrUndefined(sourceFormat[fontFamilyAsciiProperty[keyIndex]])) { + characterFormat.fontFamilyAscii = sourceFormat[fontFamilyProperty[keyIndex]]; + } + if (isNullOrUndefined(sourceFormat[fontFamilyNonFarEastProperty[keyIndex]])) { + characterFormat.fontFamilyNonFarEast = sourceFormat[fontFamilyProperty[keyIndex]]; + } } if (!isNullOrUndefined(sourceFormat[boldProperty[keyIndex]])) { characterFormat.bold = HelperMethods.parseBoolValue(sourceFormat[boldProperty[keyIndex]]); @@ -1866,6 +1924,12 @@ export class SfdtReader { } characterFormat.fontFamilyNonFarEast = sourceFormat[fontFamilyNonFarEastProperty[keyIndex]]; } + if (!isNullOrUndefined(sourceFormat[characterSpacingProperty[keyIndex]])) { + characterFormat.characterSpacing = sourceFormat[characterSpacingProperty[keyIndex]]; + } + if (!isNullOrUndefined(sourceFormat[scalingProperty[keyIndex]])) { + characterFormat.scaling = sourceFormat[scalingProperty[keyIndex]]; + } } } private getColor(color: string): string { @@ -2630,6 +2694,20 @@ export class SfdtReader { return biDirectionalOverride as BiDirectionalOverride; } } + private getBreakClearType(breakClearType: number | BreakClearType): BreakClearType { + switch (breakClearType) { + case 0: + return 'None'; + case 1: + return 'Left'; + case 2: + return 'Right'; + case 3: + return 'All'; + default: + return breakClearType as BreakClearType; + } + } private getTextVerticalAlignment(textVerticalAlignment: number | VerticalAlignment): VerticalAlignment { switch (textVerticalAlignment) { case 0: diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/text-helper.ts b/controls/documenteditor/src/document-editor/implementation/viewer/text-helper.ts index 300d279dc9..2ff8007605 100644 --- a/controls/documenteditor/src/document-editor/implementation/viewer/text-helper.ts +++ b/controls/documenteditor/src/document-editor/implementation/viewer/text-helper.ts @@ -145,10 +145,12 @@ export class TextHelper { fontFamily = this.getFontNameToRender(scriptType, characterFormat); fontSize = fontSize === 0 ? 0.5 : fontSize / (characterFormat.baselineAlignment === 'Normal' ? 1 : 1.5); this.context.font = bold + ' ' + italic + ' ' + fontSize + 'pt' + ' ' + '"' + fontFamily + '"'; + (this.context as any).letterSpacing = characterFormat.characterSpacing + 'pt'; + let scaleFactor: number = (characterFormat.scaling/100); if (characterFormat.allCaps) { text = text.toUpperCase(); } - return this.context.measureText(text).width; + return Math.abs(this.context.measureText(text).width * scaleFactor); } public setText(textToRender: string, isBidi: boolean, bdo: BiDirectionalOverride, isRender?: boolean): string { @@ -611,7 +613,7 @@ export class TextHelper { if (charFormat.bidi || charFormat.complexScript) { return this.getFontNameBidiToRender(scriptType, charFormat); } else { - if (this.isEastAsiaScript(scriptType)) + if (this.isEastAsiaScript(scriptType) && !isNullOrUndefined(charFormat.fontFamilyFarEast)) return this.getFontNameEAToRender(scriptType, charFormat); else @@ -754,6 +756,9 @@ export class TextHelper { // fontNameFromTheme = fontName; // } } + else if (isNullOrUndefined(fontNameFromTheme) && this.documentHelper.themeFontLanguage != null && (fontName === "minorBidi" || fontName === "majorBidi")) { + return fontName = this.getFontNameWithFontScript(majorMinorFontScheme, this.documentHelper.themeFontLanguage.localeIdBidi, hintType); + } } if (isNullOrUndefined(fontNameFromTheme)) @@ -766,62 +771,61 @@ export class TextHelper { // /// // /// Gets the font name from a theme part for the specified font script. // /// - // private getFontNameWithFontScript(majorMinorFontScheme: MajorMinorFontScheme, localeID: number, hintType: FontHintType): string - // { - // let fontName: string = null; - // //To-Do: Should extend this behavior deponds on the localeID. - // let lang: string = LocaleIDs[localeID]; - // let fontTypeFaces: Dictionary = majorMinorFontScheme.fontTypeface; - // //Gujarati - // //If lang script is "gu-IN" or "gu", we should retrive the "Gujr" font from a theme part. - // if ((lang == 'gu_IN' || localeID == 71) && fontTypeFaces.containsKey("Gujr")) - // fontName = fontTypeFaces.get("Arab"); - // //Hindi - // //If lang script is "hi-IN" or "hi", we should retrive the "Deva" font from a theme part. - // //Marathi - // //If lang script is "mr-IN" or "mr", we should retrive the "Deva" font from a theme part. - // else if ((lang == 'hi_IN' || lang == 'mr_IN' || localeID == 57 || localeID == 78) - // && fontTypeFaces.containsKey("Deva")) - // fontName = fontTypeFaces.get("Arab"); - // //Korean - // //If lang script is "ko-KR" or "ko", we should retrive the "Hang" font from a theme part. - // else if ((lang == 'ko_KR' || localeID == 18) && fontTypeFaces.containsKey("Hang")) - // fontName = fontTypeFaces.get("Arab"); - // //Chinese - Simplified - // //If lang script is "zh-CN", "zh-SG" or "zh", we should retrive the "Hans" font from a theme part. - // else if ((lang == 'zh_CN' || lang == 'zh_SG' || localeID == 4) && fontTypeFaces.containsKey("Hans")) - // fontName = fontTypeFaces.get("Arab"); - // //Chinese - Traditional - // //If lang script is "zh-TW", "zh-HK", or "zh-MO", we should retrive the "Hant" font from a theme part. - // else if ((lang == 'zh_TW' || lang == 'zh_HK' || lang == 'zh_MO') - // && fontTypeFaces.containsKey("Hant")) - // fontName = fontTypeFaces.get("Arab"); - // //Japanese - // //If lang script is "ja-JP" or "ja", we should retrive the "Jpan" font from a theme part. - // else if ((lang == 'ja_JP' || localeID == 17) && fontTypeFaces.containsKey("Jpan")) - // fontName = fontTypeFaces.get("Arab"); - // //Tamil - // //If lang script is "ta-IN" or "ta", we should retrive the "Taml" font from a theme part. - // else if ((lang == 'ta_IN' || localeID == 73) && fontTypeFaces.containsKey("Taml")) - // fontName = fontTypeFaces.get("Arab"); - // //Telugu - // //If lang script is "te-IN" or "te", we should retrive the "Telu" font from a theme part. - // else if ((lang == 'te_IN' || localeID == 74) && fontTypeFaces.containsKey("Telu")) - // fontName = fontTypeFaces.get("Arab"); - // //Hebrew - // //If lang script is "he-IL" or "he", we should retrive the "Hebr" font from a theme part. - // else if ((lang == 'he_IL' || lang == 'yi_Hebr' || localeID == 13) && fontTypeFaces.containsKey("Hebr")) - // fontName = fontTypeFaces.get("Arab"); - // //Thai - // //If lang script is "th_TH" or "th", we should retrive the "Thai" font from a theme part. - // else if ((lang == 'th_TH' || localeID == 30) && fontTypeFaces.containsKey("Thai")) - // fontName = fontTypeFaces.get("Thai"); - // //Arabic - // else if (hintType == FontHintType.CS && fontTypeFaces.containsKey("Arab")) - // fontName = fontTypeFaces.get("Arab"); - - // return fontName; - // } + private getFontNameWithFontScript(majorMinorFontScheme: MajorMinorFontScheme, localeID: number, hintType: FontHintType): string { + let fontName: string = null; + //To-Do: Should extend this behavior deponds on the localeID. + let lang: string = localeID.toString(); + let fontTypeFaces: Dictionary = majorMinorFontScheme.fontTypeface; + //Gujarati + //If lang script is "gu-IN" or "gu", we should retrive the "Gujr" font from a theme part. + if ((lang == 'gu_IN' || localeID == 1095) && fontTypeFaces.containsKey("Gujr")) + fontName = fontTypeFaces.get("Arab"); + //Hindi + //If lang script is "hi-IN" or "hi", we should retrive the "Deva" font from a theme part. + //Marathi + //If lang script is "mr-IN" or "mr", we should retrive the "Deva" font from a theme part. + else if ((lang == 'hi_IN' || lang == 'mr_IN' || localeID == 1081 || localeID == 1102) + && fontTypeFaces.containsKey("Deva")) + fontName = fontTypeFaces.get("Arab"); + //Korean + //If lang script is "ko-KR" or "ko", we should retrive the "Hang" font from a theme part. + else if ((lang == 'ko_KR' || localeID == 1042) && fontTypeFaces.containsKey("Hang")) + fontName = fontTypeFaces.get("Arab"); + //Chinese - Simplified + //If lang script is "zh-CN", "zh-SG" or "zh", we should retrive the "Hans" font from a theme part. + else if ((lang == 'zh_CN' || lang == 'zh_SG' || localeID == 2052) && fontTypeFaces.containsKey("Hans")) + fontName = fontTypeFaces.get("Arab"); + //Chinese - Traditional + //If lang script is "zh-TW", "zh-HK", or "zh-MO", we should retrive the "Hant" font from a theme part. + else if ((lang == 'zh_TW' || lang == 'zh_HK' || lang == 'zh_MO') + && fontTypeFaces.containsKey("Hant")) + fontName = fontTypeFaces.get("Arab"); + //Japanese + //If lang script is "ja-JP" or "ja", we should retrive the "Jpan" font from a theme part. + else if ((lang == 'ja_JP' || localeID == 1041) && fontTypeFaces.containsKey("Jpan")) + fontName = fontTypeFaces.get("Arab"); + //Tamil + //If lang script is "ta-IN" or "ta", we should retrive the "Taml" font from a theme part. + else if ((lang == 'ta_IN' || localeID == 1097) && fontTypeFaces.containsKey("Taml")) + fontName = fontTypeFaces.get("Arab"); + //Telugu + //If lang script is "te-IN" or "te", we should retrive the "Telu" font from a theme part. + else if ((lang == 'te_IN' || localeID == 1098) && fontTypeFaces.containsKey("Telu")) + fontName = fontTypeFaces.get("Arab"); + //Hebrew + //If lang script is "he-IL" or "he", we should retrive the "Hebr" font from a theme part. + else if ((lang == 'he_IL' || lang == 'yi_Hebr' || localeID == 1037) && fontTypeFaces.containsKey("Hebr")) + fontName = fontTypeFaces.get("Arab"); + //Thai + //If lang script is "th_TH" or "th", we should retrive the "Thai" font from a theme part. + else if ((lang == 'th_TH' || localeID == 1054) && fontTypeFaces.containsKey("Thai")) + fontName = fontTypeFaces.get("Thai"); + //Arabic + else if (hintType == FontHintType.CS && fontTypeFaces.containsKey("Arab")) + fontName = fontTypeFaces.get("Arab"); + + return fontName; + } public destroy(): void { this.documentHelper = undefined; diff --git a/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts b/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts index 1b3d207819..8444eab431 100644 --- a/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts +++ b/controls/documenteditor/src/document-editor/implementation/viewer/viewer.ts @@ -4,7 +4,7 @@ import { WList } from '../list/list'; import { WAbstractList } from '../list/abstract-list'; import { WListLevel } from '../list/list-level'; import { WLevelOverride } from '../list/level-override'; -import { WSectionFormat, WCharacterFormat, WParagraphFormat, WStyles, WColumnFormat } from '../format/index'; +import { WSectionFormat, WCharacterFormat, WParagraphFormat, WStyles, WStyle, WColumnFormat } from '../format/index'; import { Layout } from './layout'; import { Renderer } from './render'; import { createElement, Browser } from '@syncfusion/ej2-base'; @@ -47,6 +47,14 @@ import { beforeAutoResize, internalAutoResize } from '../../base/constants'; * @private */ export class DocumentHelper { + /** + * @private + */ + public isCompleted: boolean = true; + /** + * @private + */ + public isSelectionCompleted: boolean = true; /** * @private */ @@ -859,6 +867,8 @@ export class DocumentHelper { this.preDefinedStyles.add('TOC 7', '{"type":"Paragraph","name":"TOC 7","basedOn":"Normal","next":"Normal","paragraphFormat":{"leftIndent" :66.0,"afterSpacing":5.0}}'); this.preDefinedStyles.add('TOC 8', '{"type":"Paragraph","name":"TOC 8","basedOn":"Normal","next":"Normal","paragraphFormat":{"leftIndent" :77.0,"afterSpacing":5.0}}'); this.preDefinedStyles.add('TOC 9', '{"type":"Paragraph","name":"TOC 9","basedOn":"Normal","next":"Normal","paragraphFormat":{"leftIndent" :88.0,"afterSpacing":5.0}}'); + this.preDefinedStyles.add('Header', '{"type":"Paragraph","name":"Header","basedOn":"Normal","next":"Header","paragraphFormat":{"afterSpacing":0,"lineSpacing":1,"lineSpacingType":"Multiple"}}'); + this.preDefinedStyles.add('Footer', '{"type":"Paragraph","name":"Footer","basedOn":"Normal","next":"Footer","paragraphFormat":{"afterSpacing":0,"lineSpacing":1,"lineSpacingType":"Multiple"}}'); } /** * @private @@ -868,6 +878,9 @@ export class DocumentHelper { if (this.owner.editor) { this.owner.editor.clear(); } + if(this.owner.search) { + this.owner.search.clearSearchHighlight(); + } if (this.owner.selection) { this.owner.selection.clear(); } @@ -1683,6 +1696,7 @@ export class DocumentHelper { this.owner.isDocumentLoaded = false; this.viewer.columnLayoutArea.clear(); this.layout.isDocumentContainsRtl = false; + this.layout.isMultiColumnDoc = false; this.updateAuthorIdentity(); for (let i: number = 0; i < this.pages.length; i++) { for (let j: number = 0; j < this.pages[i].bodyWidgets.length; j++) { @@ -1996,6 +2010,7 @@ export class DocumentHelper { const touchPoint: Point = new Point(xPosition, touchY); if (!this.owner.enableImageResizerMode || !this.owner.imageResizerModule.isImageResizerVisible || this.owner.imageResizerModule.isShapeResize) { + this.isCompleted = false; this.owner.selection.moveTextPosition(touchPoint, textPosition); } this.isSelectionChangedOnMouseMoved = true; @@ -2200,8 +2215,8 @@ export class DocumentHelper { } } } - startPosition.setPositionParagraph((endnotes.childWidgets[i] as BlockWidget).childWidgets[0] as LineWidget, 0); - endPosition.setPositionParagraph((endnotes.childWidgets[i] as BlockWidget).childWidgets[0] as LineWidget, 0); + startPosition.setPositionParagraph((endnotes.bodyWidgets[i].childWidgets[0] as BlockWidget).childWidgets[0] as LineWidget, 0); + endPosition.setPositionParagraph((endnotes.bodyWidgets[i].childWidgets[0] as BlockWidget).childWidgets[0] as LineWidget, 0); this.selection.selectRange(startPosition, endPosition); } } else { @@ -2323,6 +2338,9 @@ export class DocumentHelper { this.selection.selectInternal(formField.line, formField, 0, point); } } + if(this.isSelectionChangedOnMouseMoved){ + this.selection.fireSelectionChanged(true); + } } if (!this.owner.isReadOnlyMode && this.isSelectionInListText(touchPoint)) { this.selection.selectListText(); @@ -2338,6 +2356,9 @@ export class DocumentHelper { if (this.isDragStarted) { this.moveSelectedContent(); } + if(this.isMouseDown) { + this.updateFocus(); + } this.isMouseDownInSelection = false; this.isMouseDown = false; this.isFootnoteWidget = false; @@ -2345,7 +2366,6 @@ export class DocumentHelper { this.isTouchInput = false; this.useTouchSelectionMark = true; this.isControlPressed = false; - this.updateFocus(); if (this.isListTextSelected) { this.selection.hideCaret(); } @@ -2635,6 +2655,7 @@ export class DocumentHelper { cursorPoint = this.getTouchOffsetValue(event); let touchPoint: Point = this.owner.viewer.findFocusedPage(cursorPoint, true); if (this.touchDownOnSelectionMark > 0 /*|| !this.useTouchSelectionMark*/) { + this.isCompleted = false; event.preventDefault(); let touchY: number = touchPoint.y; let textPosition: TextPosition = this.owner.selection.end; @@ -2706,6 +2727,9 @@ export class DocumentHelper { this.selection.navigateHyperLinkOnEvent(touchPoint, true); } } + if(this.isSelectionChangedOnMouseMoved){ + this.selection.fireSelectionChanged(true); + } this.isMouseDown = false; this.touchDownOnSelectionMark = 0; this.useTouchSelectionMark = true; @@ -3103,6 +3127,9 @@ export class DocumentHelper { this.viewerContainer.scrollLeft = x - (this.pageContainer.offsetWidth / 100) * 20; } else if (scrollLeft + this.visibleBounds.width < x + scrollBarWidth) { this.viewerContainer.scrollLeft = scrollLeft + (this.pageContainer.offsetWidth / 100) * 15 + scrollBarWidth; + while (x < this.owner.viewer.containerWidth && this.viewerContainer.scrollLeft + this.visibleBounds.width < x + scrollBarWidth) { + this.viewerContainer.scrollLeft = this.viewerContainer.scrollLeft + (this.pageContainer.offsetWidth / 100) * 15 + scrollBarWidth; + } } } public getLineWidget(cursorPoint: Point): LineWidget { @@ -4265,6 +4292,10 @@ export abstract class LayoutViewer { * @private */ public containerTop: number = 0; + /** + * @private + */ + public containerWidth: number = 0; /** * @private */ @@ -5044,6 +5075,7 @@ export abstract class LayoutViewer { } public updateScrollBarPosition(containerWidth: number, containerHeight: number, viewerWidth: number, viewerHeight: number, width: number, height: number): void { this.owner.viewer.containerTop = this.documentHelper.viewerContainer.scrollTop; + this.owner.viewer.containerWidth = containerWidth; this.documentHelper.containerCanvas.style.position = 'absolute'; this.documentHelper.containerCanvas.style.top = this.owner.viewer.containerTop.toString() + 'px'; this.documentHelper.selectionCanvas.style.position = 'absolute'; @@ -5183,7 +5215,7 @@ export class PageLayoutViewer extends LayoutViewer { let type: HeaderFooterType; type = isHeader ? 'OddHeader' : 'OddFooter'; let page: Page = section.page; - if (section.sectionFormat.differentFirstPage && (isNullOrUndefined(page.previousPage) || page.sectionIndex !== page.previousPage.sectionIndex)) { + if (section.sectionFormat.differentFirstPage && (isNullOrUndefined(page.previousPage) || (isNullOrUndefined(page.previousPage) && page.sectionIndex !== page.previousPage.sectionIndex && page.previousPage.bodyWidgets[page.previousPage.bodyWidgets.length - 1].sectionIndex !== page.bodyWidgets[0].sectionIndex))) { type = isHeader ? 'FirstPageHeader' : 'FirstPageFooter'; } else if (section.sectionFormat.differentOddAndEvenPages && this.documentHelper.pages.length % 2 === 0) { type = isHeader ? 'EvenHeader' : 'EvenFooter'; @@ -5204,7 +5236,9 @@ export class PageLayoutViewer extends LayoutViewer { headerFooter = this.createHeaderFooterWidget(type); headerFooter.isEmpty = true; } - this.documentHelper.headersFooters[sectionIndex][index] = headerFooter; + if (sectionIndex == 0) { + this.documentHelper.headersFooters[sectionIndex][index] = headerFooter; + } } return headerFooter; } else if (sectionIndex > 0) { @@ -5213,9 +5247,20 @@ export class PageLayoutViewer extends LayoutViewer { return undefined; } private createHeaderFooterWidget(type: HeaderFooterType): HeaderFooterWidget { - let headerFooter: HeaderFooterWidget = new HeaderFooterWidget(type); - let paragraph: ParagraphWidget = new ParagraphWidget(); + const headerFooter: HeaderFooterWidget = new HeaderFooterWidget(type); + const paragraph: ParagraphWidget = new ParagraphWidget(); paragraph.childWidgets.push(new LineWidget(paragraph)); + let style; + if(type.indexOf('Header') !== -1) { + style = this.documentHelper.styles.findByName('Header') as WStyle; + } + else { + style = this.documentHelper.styles.findByName('Footer') as WStyle; + } + paragraph.paragraphFormat.baseStyle = style; + paragraph.paragraphFormat.listFormat.baseStyle = style; + headerFooter.childWidgets.push(paragraph); + paragraph.containerWidget = headerFooter; return headerFooter; } public getHeaderFooter(type: HeaderFooterType): number { diff --git a/controls/documenteditor/src/document-editor/implementation/writer/html-export.ts b/controls/documenteditor/src/document-editor/implementation/writer/html-export.ts index f4d348bd32..97ad7d9bd8 100644 --- a/controls/documenteditor/src/document-editor/implementation/writer/html-export.ts +++ b/controls/documenteditor/src/document-editor/implementation/writer/html-export.ts @@ -4,7 +4,7 @@ import { CellVerticalAlignment, LineStyle } from '../../base/types'; import { WCharacterFormat } from '../format/character-format'; import { WParagraphFormat } from '../format/paragraph-format'; import { HelperMethods } from '../editor/editor-helper'; -import { sectionsProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, nameProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, allCapsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, bordersProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, isHeaderProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, backgroundColorProperty, hasNoneStyleProperty, lineStyleProperty, lineWidthProperty, textProperty, widthProperty, heightProperty, colorProperty, imageStringProperty, topProperty, bottomProperty, rightProperty, leftProperty, fieldTypeProperty, inlinesProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, tableFormatProperty, blocksProperty, listLevelPatternProperty, abstractListIdProperty, levelsProperty, bookmarkTypeProperty, inlineFormatProperty, startAtProperty} from '../../index'; +import { sectionsProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, nameProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, allCapsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, bordersProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, isHeaderProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, backgroundColorProperty, hasNoneStyleProperty, lineStyleProperty, lineWidthProperty, textProperty, widthProperty, heightProperty, colorProperty, imageStringProperty, topProperty, bottomProperty, rightProperty, leftProperty, fieldTypeProperty, inlinesProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, tableFormatProperty, blocksProperty, listLevelPatternProperty, abstractListIdProperty, levelsProperty, bookmarkTypeProperty, inlineFormatProperty, startAtProperty, characterSpacingProperty, scalingProperty, imagesProperty, Dictionary, isMetaFileProperty} from '../../index'; /** * @private @@ -16,6 +16,7 @@ export class HtmlExport { private prevListLevel: any = undefined; private isOrdered: boolean = undefined; private keywordIndex: number = undefined; + private images: Dictionary; /** * @private @@ -27,11 +28,26 @@ export class HtmlExport { this.keywordIndex = isOptimizeSfdt ? 1 : 0; this.document = document; let html: string = ''; + if (document.hasOwnProperty(imagesProperty[this.keywordIndex])) { + this.serializeImages(document[imagesProperty[this.keywordIndex]]); + } for (let i: number = 0; i < document[sectionsProperty[this.keywordIndex]].length; i++) { html += this.serializeSection(document[sectionsProperty[this.keywordIndex]][i]); } return html; } + private serializeImages(data: any): void { + this.images = new Dictionary(); + for (let img in data) { + if (Array.isArray(data[`${img}`])) { + this.images.add(parseInt(img), data[`${img}`]); + } else { + let images: string[] = []; + images.push(data[`${img}`]); + this.images.add(parseInt(img), images); + } + } + } private serializeSection(section: any): string { let string: string = ''; for (let i: number = 0; i < section[blocksProperty[this.keywordIndex]].length; i++) { @@ -345,7 +361,8 @@ export class HtmlExport { this.serializeInlineStyle(image[characterFormatProperty[this.keywordIndex]]); let imageSource: string = ''; if (!isNullOrUndefined(image[imageStringProperty[this.keywordIndex]])) { - imageSource = image[imageStringProperty[this.keywordIndex]]; + let base64ImageString: string[] = this.images.get(parseInt(image[imageStringProperty[this.keywordIndex]])); + imageSource = base64ImageString[HelperMethods.parseBoolValue(image[isMetaFileProperty[this.keywordIndex]]) ? 1 : 0]; } const width: number = HelperMethods.convertPointToPixel(image[widthProperty[this.keywordIndex]]); const height: number = HelperMethods.convertPointToPixel(image[heightProperty[this.keywordIndex]]); @@ -358,7 +375,7 @@ export class HtmlExport { } // Serialize Table Cell - public serializeCell(cell: any): string { + public serializeCell(cell: any, row: any): string { let blockStyle: string = ''; let tagAttributes: string[] = []; let cellHtml: string = ''; @@ -395,7 +412,7 @@ export class HtmlExport { cellHtml += ('padding-bottom:' + cell[cellFormatProperty[this.keywordIndex]][bottomMarginProperty[this.keywordIndex]].toString() + 'pt;'); } if (!isNullOrUndefined(cell[cellFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]])) { - cellHtml += this.serializeCellBordersStyle(cell[cellFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]]); + cellHtml += this.serializeCellBordersStyle(cell[cellFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]], row); } } if (cellHtml.length !== 0) { @@ -443,7 +460,7 @@ export class HtmlExport { let html: string = ''; html += this.createRowStartTag(row); for (let k: number = 0; k < row[cellsProperty[this.keywordIndex]].length; k++) { - html += this.serializeCell(row[cellsProperty[this.keywordIndex]][k]); + html += this.serializeCell(row[cellsProperty[this.keywordIndex]][k], row); } return html; } @@ -451,9 +468,11 @@ export class HtmlExport { // Serialize Styles private serializeParagraphStyle(paragraph: any, className: string, isList: boolean): string { let paragraphClass: string = ''; - if (paragraph[inlinesProperty[this.keywordIndex]].length > 0) { - paragraphClass += this.serializeCharacterFormat(paragraph[characterFormatProperty[this.keywordIndex]]); + let isEmptyLine: boolean = false; + if (paragraph[inlinesProperty[this.keywordIndex]].length == 0) { + isEmptyLine = true; } + paragraphClass += this.serializeCharacterFormat(paragraph[characterFormatProperty[this.keywordIndex]], isEmptyLine); paragraphClass += this.serializeParagraphFormat(paragraph[paragraphFormatProperty[this.keywordIndex]], isList); return paragraphClass; } @@ -502,7 +521,7 @@ export class HtmlExport { } return borderStyle; } - private serializeCellBordersStyle(borders: any): string { + private serializeCellBordersStyle(borders: any, row: any): string { let borderStyle: string = ''; //borderStyle = 'border:solid 1px;'; @@ -538,6 +557,13 @@ export class HtmlExport { borderStyle += this.serializeBorderStyle(border, 'left'); } else if (!isNullOrUndefined(border) && HelperMethods.parseBoolValue(border[hasNoneStyleProperty[this.keywordIndex]])) { borderStyle += ('border-left-style:none;'); + } else if (!isNullOrUndefined(row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][leftProperty[this.keywordIndex]])) { + border = row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][leftProperty[this.keywordIndex]]; + if (!isNullOrUndefined(border) && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 1 : 'None') && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 26 : 'Cleared')) { + border[colorProperty[this.keywordIndex]] = isNullOrUndefined(border[colorProperty[this.keywordIndex]]) ? "#000000" : border[colorProperty[this.keywordIndex]]; + border[lineWidthProperty[this.keywordIndex]] = isNullOrUndefined(border[lineWidthProperty[this.keywordIndex]]) ? 0.5 : border[lineWidthProperty[this.keywordIndex]]; + borderStyle += this.serializeBorderStyle(border, 'left'); + } } //TopBorder border = borders[topProperty[this.keywordIndex]]; @@ -547,6 +573,13 @@ export class HtmlExport { borderStyle += this.serializeBorderStyle(border, 'top'); } else if (!isNullOrUndefined(border) && HelperMethods.parseBoolValue(border[hasNoneStyleProperty[this.keywordIndex]])) { borderStyle += ('border-top-style:none;'); + } else if (!isNullOrUndefined(row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][topProperty[this.keywordIndex]])) { + border = row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][topProperty[this.keywordIndex]]; + if (!isNullOrUndefined(border) && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 1 : 'None') && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 26 : 'Cleared')) { + border[colorProperty[this.keywordIndex]] = isNullOrUndefined(border[colorProperty[this.keywordIndex]]) ? "#000000" : border[colorProperty[this.keywordIndex]]; + border[lineWidthProperty[this.keywordIndex]] = isNullOrUndefined(border[lineWidthProperty[this.keywordIndex]]) ? 0.5 : border[lineWidthProperty[this.keywordIndex]]; + borderStyle += this.serializeBorderStyle(border, 'top'); + } } //RightBorder border = borders[rightProperty[this.keywordIndex]]; @@ -556,6 +589,13 @@ export class HtmlExport { borderStyle += this.serializeBorderStyle(border, 'right'); } else if (!isNullOrUndefined(border) && HelperMethods.parseBoolValue(border[hasNoneStyleProperty[this.keywordIndex]])) { borderStyle += ('border-right-style:none;'); + } else if (!isNullOrUndefined(row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][rightProperty[this.keywordIndex]])) { + border = row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][rightProperty[this.keywordIndex]]; + if (!isNullOrUndefined(border) && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 1 : 'None') && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 26 : 'Cleared')) { + border[colorProperty[this.keywordIndex]] = isNullOrUndefined(border[colorProperty[this.keywordIndex]]) ? "#000000" : border[colorProperty[this.keywordIndex]]; + border[lineWidthProperty[this.keywordIndex]] = isNullOrUndefined(border[lineWidthProperty[this.keywordIndex]]) ? 0.5 : border[lineWidthProperty[this.keywordIndex]]; + borderStyle += this.serializeBorderStyle(border, 'right'); + } } //BottomBorder border = borders[bottomProperty[this.keywordIndex]]; @@ -565,6 +605,13 @@ export class HtmlExport { borderStyle += this.serializeBorderStyle(border, 'bottom'); } else if (!isNullOrUndefined(border) && HelperMethods.parseBoolValue(border[hasNoneStyleProperty[this.keywordIndex]])) { borderStyle += ('border-bottom-style:none;'); + } else if (!isNullOrUndefined(row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][bottomProperty[this.keywordIndex]])) { + border = row[rowFormatProperty[this.keywordIndex]][bordersProperty[this.keywordIndex]][bottomProperty[this.keywordIndex]]; + if (!isNullOrUndefined(border) && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 1 : 'None') && border[lineStyleProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 26 : 'Cleared')) { + border[colorProperty[this.keywordIndex]] = isNullOrUndefined(border[colorProperty[this.keywordIndex]]) ? "#000000" : border[colorProperty[this.keywordIndex]]; + border[lineWidthProperty[this.keywordIndex]] = isNullOrUndefined(border[lineWidthProperty[this.keywordIndex]]) ? 0.5 : border[lineWidthProperty[this.keywordIndex]]; + borderStyle += this.serializeBorderStyle(border, 'bottom'); + } } return borderStyle; } @@ -651,9 +698,9 @@ export class HtmlExport { } // Serialize Format - private serializeCharacterFormat(characterFormat: any): string { + private serializeCharacterFormat(characterFormat: any, isEmptyLine?: boolean): string { if (!isNullOrUndefined(characterFormat[inlineFormatProperty[this.keywordIndex]])) { - return this.serializeCharacterFormat(characterFormat[inlineFormatProperty[this.keywordIndex]]); + return this.serializeCharacterFormat(characterFormat[inlineFormatProperty[this.keywordIndex]], isEmptyLine); } let propertyValue: any; let charStyle: string = ''; @@ -679,7 +726,7 @@ export class HtmlExport { } //Text Foreground and Background Color - if (!isNullOrUndefined(characterFormat[highlightColorProperty[this.keywordIndex]]) && characterFormat[highlightColorProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'NoColor')) { + if (!isNullOrUndefined(characterFormat[highlightColorProperty[this.keywordIndex]]) && characterFormat[highlightColorProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'NoColor') && !isEmptyLine) { charStyle += 'background-color'; charStyle += ':'; charStyle += this.keywordIndex == 1 ? this.getHighlightColorCode(characterFormat[highlightColorProperty[this.keywordIndex]]) : HelperMethods.getHighlightColorCode(characterFormat.highlightColor.toString()); @@ -715,6 +762,21 @@ export class HtmlExport { charStyle += propertyValue.toString(); charStyle += ';'; } + propertyValue = characterFormat[characterSpacingProperty[this.keywordIndex]]; + if (!isNullOrUndefined(propertyValue)) { + charStyle += 'letter-spacing'; + charStyle += ':'; + charStyle += propertyValue.toString(); + charStyle += 'pt'; + charStyle += ';'; + } + propertyValue = characterFormat[scalingProperty[this.keywordIndex]]; + if (!isNullOrUndefined(propertyValue)) { + charStyle += 'transform:scaleX('; + charStyle += (propertyValue/100).toString(); + charStyle += ')'; + charStyle += ';'; + } return charStyle.toString(); } private serializeTextDecoration(characterFormat: any): string { 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 87ef18f686..41e94a2087 100644 --- a/controls/documenteditor/src/document-editor/implementation/writer/sfdt-export.ts +++ b/controls/documenteditor/src/document-editor/implementation/writer/sfdt-export.ts @@ -12,7 +12,7 @@ import { ListTextElementBox, BookmarkElementBox, EditRangeStartElementBox, EditRangeEndElementBox, ChartElementBox, ChartDataTable, ChartTitleArea, ChartDataFormat, ChartLayout, ChartArea, ChartLegend, ChartCategoryAxis, CommentElementBox, CommentCharacterElementBox, TextFormField, CheckBoxFormField, DropDownFormField, ShapeElementBox, - ContentControlProperties, FootnoteElementBox, ShapeBase + ContentControlProperties, FootnoteElementBox, ShapeBase, BreakElementBox } from '../viewer/page'; import { BlockWidget } from '../viewer/page'; import { isNullOrUndefined } from '@syncfusion/ej2-base'; @@ -27,7 +27,7 @@ import { Themes } from '../themes/themes'; import { MajorMinorFontScheme } from '../themes/major-minor-font-scheme'; import { ZipArchive, ZipArchiveItem } from '@syncfusion/ej2-compression'; import { AutoShapeType, CellVerticalAlignment, CheckBoxSizeType, CompatibilityMode, ContentControlType, FollowCharacterType, FootEndNoteNumberFormat, FootnoteRestartIndex, FootnoteType, HeightType, HorizontalAlignment, HorizontalOrigin, LineDashing, LineFormatType, LineSpacingType, LineStyle, ListLevelPattern, OutlineLevel, ProtectionType, RevisionType, StyleType, TabJustification, TabLeader, TableAlignment, TextAlignment, TextFormFieldType, TextureStyle, TextWrappingStyle, TextWrappingType, VerticalAlignment, VerticalOrigin, WidthType } from '../../base/types'; -import { sectionsProperty, imagesProperty, fontSubstitutionTableProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, backgroundProperty, stylesProperty, commentsProperty, revisionsProperty, customXmlProperty, defaultTabWidthProperty, formattingProperty, trackChangesProperty, protectionTypeProperty, enforcementProperty, hashValueProperty, saltValueProperty, cryptProviderTypeProperty, cryptAlgorithmClassProperty, cryptAlgorithmTypeProperty, cryptAlgorithmSidProperty, cryptSpinCountProperty, doNotUseHTMLParagraphAutoSpacingProperty, alignTablesRowByRowProperty, formFieldShadingProperty, lastParagraphMarkCopiedProperty, footnotesProperty, endnotesProperty, compatibilityModeProperty, themeFontLanguagesProperty, themesProperty, nameProperty, basedOnProperty, nextProperty, linkProperty, localeIdProperty, localeIdFarEastProperty, localeIdBidiProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, bidiProperty, bdoProperty, fontSizeBidiProperty, fontFamilyBidiProperty, boldBidiProperty, italicBidiProperty, allCapsProperty, complexScriptProperty, fontFamilyAsciiProperty, fontFamilyFarEastProperty, fontFamilyNonFarEastProperty, revisionIdsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, spaceAfterAutoProperty, spaceBeforeAutoProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, keepWithNextProperty, widowControlProperty, keepLinesTogetherProperty, outlineLevelProperty, contextualSpacingProperty, bordersProperty, tabsProperty, headerDistanceProperty, footerDistanceProperty, differentFirstPageProperty, differentOddAndEvenPagesProperty, pageWidthProperty, pageHeightProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, restartPageNumberingProperty, pageStartingNumberProperty, endnoteNumberFormatProperty, footNoteNumberFormatProperty, restartIndexForFootnotesProperty, restartIndexForEndnotesProperty, initialFootNoteNumberProperty, initialEndNoteNumberProperty, pageNumberStyleProperty, columnsProperty, numberOfColumnsProperty, equalWidthProperty, lineBetweenColumnsProperty, breakCodeProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, allowBreakAcrossPagesProperty, isHeaderProperty, heightTypeProperty, beforeWidthProperty, afterWidthProperty, gridBeforeProperty, gridBeforeWidthProperty, gridBeforeWidthTypeProperty, gridAfterProperty, gridAfterWidthProperty, gridAfterWidthTypeProperty, allowAutoFitProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, horizontalPositionAbsProperty, textureProperty, backgroundColorProperty, foregroundColorProperty, shadowProperty, hasNoneStyleProperty, verticalProperty, horizontalProperty, diagonalUpProperty, diagonalDownProperty, lineStyleProperty, lineWidthProperty, layoutProperty, dataFormatProperty, yValueProperty, chartDataProperty, categoryXNameProperty, lineProperty, foreColorProperty, patternProperty, layoutXProperty, layoutYProperty, directionProperty, endStyleProperty, numberValueProperty, markerStyleProperty, markerColorProperty, markerSizeProperty, forwardProperty, backwardProperty, interceptProperty, isDisplayRSquaredProperty, isDisplayEquationProperty, seriesNameProperty, dataLabelProperty, errorBarProperty, seriesFormatProperty, trendLinesProperty, dataPointsProperty, firstSliceAngleProperty, holeSizeProperty, isLegendKeyProperty, isBubbleSizeProperty, isCategoryNameProperty, isSeriesNameProperty, isValueProperty, isPercentageProperty, isLeaderLinesProperty, showSeriesKeysProperty, hasHorizontalBorderProperty, hasVerticalBorderProperty, hasBordersProperty, categoryTypeProperty, chartCategoryProperty, chartSeriesProperty, chartAreaProperty, chartTitleAreaProperty, plotAreaProperty, chartLegendProperty, chartPrimaryCategoryAxisProperty, chartPrimaryValueAxisProperty, chartTitleProperty, chartTypeProperty, gapWidthProperty, overlapProperty, chartDataTableProperty, textProperty, shapeIdProperty, alternativeTextProperty, visibleProperty, widthProperty, heightProperty, widthScaleProperty, heightScaleProperty, lineFormatProperty, fillFormatProperty, textWrappingStyleProperty, textWrappingTypeProperty, verticalRelativePercentProperty, horizontalRelativePercentProperty, zOrderPositionProperty, layoutInCellProperty, lockAnchorProperty, autoShapeTypeProperty, textFrameProperty, colorProperty, fillProperty, textVerticalAlignmentProperty, imageStringProperty, metaFileImageStringProperty, lengthProperty, isInlineImageProperty, isMetaFileProperty, topProperty, bottomProperty, rightProperty, leftProperty, getImageHeightProperty, getImageWidthProperty, hasFieldEndProperty, formFieldDataProperty, fieldTypeProperty, enabledProperty, helpTextProperty, statusTextProperty, textInputProperty, checkBoxProperty, dropDownListProperty, maxLengthProperty, defaultValueProperty, formatProperty, sizeTypeProperty, sizeProperty, checkedProperty, dropDownItemsProperty, selectedIndexProperty, commentIdProperty, commentCharacterTypeProperty, authorProperty, initialProperty, dateProperty, doneProperty, replyCommentsProperty, revisionTypeProperty, revisionIdProperty, itemIDProperty, xmlProperty, footnoteTypeProperty, symbolCodeProperty, symbolFontNameProperty, customMarkerProperty, inlinesProperty, contentControlPropertiesProperty, lockContentControlProperty, lockContentsProperty, tagProperty, titleProperty, hasPlaceHolderTextProperty, multiLineProperty, isTemporaryProperty, dateCalendarTypeProperty, dateStorageFormatProperty, dateDisplayLocaleProperty, dateDisplayFormatProperty, isCheckedProperty, uncheckedStateProperty, checkedStateProperty, contentControlListItemsProperty, xmlMappingProperty, fontProperty, valueProperty, displayTextProperty, isMappedProperty, isWordMlProperty, prefixMappingProperty, xPathProperty, storeItemIdProperty, customXmlPartProperty, idProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, descriptionProperty, wrapTextAroundProperty, positioningProperty, tableFormatProperty, allowOverlapProperty, distanceTopProperty, distanceRightProperty, distanceLeftProperty, distanceBottomProperty, verticalOriginProperty, verticalPositionProperty, horizontalOriginProperty, horizontalAlignmentProperty, horizontalPositionProperty, blocksProperty, headerProperty, footerProperty, evenHeaderProperty, evenFooterProperty, firstPageHeaderProperty, firstPageFooterProperty, headersFootersProperty, sectionFormatProperty, listLevelPatternProperty, followCharacterProperty, startAtProperty, restartLevelProperty, levelNumberProperty, numberFormatProperty, abstractListIdProperty, levelsProperty, overrideListLevelProperty, levelOverridesProperty, separatorProperty, continuationSeparatorProperty, continuationNoticeProperty, bookmarkTypeProperty, propertiesProperty, tabJustificationProperty, positionProperty, deletePositionProperty, leaderProperty, tabLeaderProperty, editRangeIdProperty, columnFirstProperty, columnLastProperty, userProperty, groupProperty, editableRangeStartProperty, spaceProperty, fontSchemeProperty, fontSchemeNameProperty, majorFontSchemeProperty, minorFontSchemeProperty, fontSchemeListProperty, fontTypefaceProperty, typefaceProperty, panoseProperty, typeProperty, majorUnitProperty, maximumValueProperty, minimumValueProperty, hasMajorGridLinesProperty, hasMinorGridLinesProperty, majorTickMarkProperty, minorTickMarkProperty, tickLabelPositionProperty, rgbProperty, appearanceProperty, lineFormatTypeProperty, allowSpaceOfSameStyleInTableProperty, weightProperty, inlineFormatProperty, fontNameProperty, isCompressedProperty, columnIndexProperty, columnCountProperty, gridProperty , isAfterParagraphMarkProperty, isAfterCellMarkProperty, isAfterRowMarkProperty, isAfterTableMarkProperty, belowTextProperty } from '../../index'; +import { sectionsProperty, imagesProperty, fontSubstitutionTableProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, backgroundProperty, stylesProperty, commentsProperty, revisionsProperty, customXmlProperty, defaultTabWidthProperty, formattingProperty, trackChangesProperty, protectionTypeProperty, enforcementProperty, hashValueProperty, saltValueProperty, cryptProviderTypeProperty, cryptAlgorithmClassProperty, cryptAlgorithmTypeProperty, cryptAlgorithmSidProperty, cryptSpinCountProperty, doNotUseHTMLParagraphAutoSpacingProperty, alignTablesRowByRowProperty, formFieldShadingProperty, lastParagraphMarkCopiedProperty, footnotesProperty, endnotesProperty, compatibilityModeProperty, themeFontLanguagesProperty, themesProperty, nameProperty, basedOnProperty, nextProperty, linkProperty, localeIdProperty, localeIdFarEastProperty, localeIdBidiProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, bidiProperty, bdoProperty, fontSizeBidiProperty, fontFamilyBidiProperty, boldBidiProperty, italicBidiProperty, allCapsProperty, complexScriptProperty, fontFamilyAsciiProperty, fontFamilyFarEastProperty, fontFamilyNonFarEastProperty, revisionIdsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, spaceAfterAutoProperty, spaceBeforeAutoProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, keepWithNextProperty, widowControlProperty, keepLinesTogetherProperty, outlineLevelProperty, contextualSpacingProperty, bordersProperty, tabsProperty, headerDistanceProperty, footerDistanceProperty, differentFirstPageProperty, differentOddAndEvenPagesProperty, pageWidthProperty, pageHeightProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, restartPageNumberingProperty, pageStartingNumberProperty, endnoteNumberFormatProperty, footNoteNumberFormatProperty, restartIndexForFootnotesProperty, restartIndexForEndnotesProperty, initialFootNoteNumberProperty, initialEndNoteNumberProperty, pageNumberStyleProperty, columnsProperty, numberOfColumnsProperty, equalWidthProperty, lineBetweenColumnsProperty, breakCodeProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, allowBreakAcrossPagesProperty, isHeaderProperty, heightTypeProperty, beforeWidthProperty, afterWidthProperty, gridBeforeProperty, gridBeforeWidthProperty, gridBeforeWidthTypeProperty, gridAfterProperty, gridAfterWidthProperty, gridAfterWidthTypeProperty, allowAutoFitProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, horizontalPositionAbsProperty, textureProperty, backgroundColorProperty, foregroundColorProperty, shadowProperty, hasNoneStyleProperty, verticalProperty, horizontalProperty, diagonalUpProperty, diagonalDownProperty, lineStyleProperty, lineWidthProperty, layoutProperty, dataFormatProperty, yValueProperty, chartDataProperty, categoryXNameProperty, lineProperty, foreColorProperty, patternProperty, layoutXProperty, layoutYProperty, directionProperty, endStyleProperty, numberValueProperty, markerStyleProperty, markerColorProperty, markerSizeProperty, forwardProperty, backwardProperty, interceptProperty, isDisplayRSquaredProperty, isDisplayEquationProperty, seriesNameProperty, dataLabelProperty, errorBarProperty, seriesFormatProperty, trendLinesProperty, dataPointsProperty, firstSliceAngleProperty, holeSizeProperty, isLegendKeyProperty, isBubbleSizeProperty, isCategoryNameProperty, isSeriesNameProperty, isValueProperty, isPercentageProperty, isLeaderLinesProperty, showSeriesKeysProperty, hasHorizontalBorderProperty, hasVerticalBorderProperty, hasBordersProperty, categoryTypeProperty, chartCategoryProperty, chartSeriesProperty, chartAreaProperty, chartTitleAreaProperty, plotAreaProperty, chartLegendProperty, chartPrimaryCategoryAxisProperty, chartPrimaryValueAxisProperty, chartTitleProperty, chartTypeProperty, gapWidthProperty, overlapProperty, chartDataTableProperty, textProperty, shapeIdProperty, alternativeTextProperty, visibleProperty, widthProperty, heightProperty, widthScaleProperty, heightScaleProperty, lineFormatProperty, fillFormatProperty, textWrappingStyleProperty, textWrappingTypeProperty, verticalRelativePercentProperty, horizontalRelativePercentProperty,heightRelativePercentProperty, widthRelativePercentProperty, zOrderPositionProperty, layoutInCellProperty, lockAnchorProperty, autoShapeTypeProperty, textFrameProperty, colorProperty, fillProperty, textVerticalAlignmentProperty, imageStringProperty, metaFileImageStringProperty, lengthProperty, isInlineImageProperty, isMetaFileProperty, topProperty, bottomProperty, rightProperty, leftProperty, getImageHeightProperty, getImageWidthProperty, hasFieldEndProperty, formFieldDataProperty, fieldTypeProperty, enabledProperty, helpTextProperty, statusTextProperty, textInputProperty, checkBoxProperty, dropDownListProperty, maxLengthProperty, defaultValueProperty, formatProperty, sizeTypeProperty, sizeProperty, checkedProperty, dropDownItemsProperty, selectedIndexProperty, commentIdProperty, commentCharacterTypeProperty, authorProperty, initialProperty, dateProperty, doneProperty, replyCommentsProperty, revisionTypeProperty, revisionIdProperty, itemIDProperty, xmlProperty, footnoteTypeProperty, symbolCodeProperty, symbolFontNameProperty, customMarkerProperty, inlinesProperty, contentControlPropertiesProperty, lockContentControlProperty, lockContentsProperty, tagProperty, titleProperty, hasPlaceHolderTextProperty, multiLineProperty, isTemporaryProperty, dateCalendarTypeProperty, dateStorageFormatProperty, dateDisplayLocaleProperty, dateDisplayFormatProperty, isCheckedProperty, uncheckedStateProperty, checkedStateProperty, contentControlListItemsProperty, xmlMappingProperty, fontProperty, valueProperty, displayTextProperty, isMappedProperty, isWordMlProperty, prefixMappingProperty, xPathProperty, storeItemIdProperty, customXmlPartProperty, idProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, descriptionProperty, wrapTextAroundProperty, positioningProperty, tableFormatProperty, allowOverlapProperty, distanceTopProperty, distanceRightProperty, distanceLeftProperty, distanceBottomProperty, verticalOriginProperty, verticalPositionProperty, horizontalOriginProperty, horizontalAlignmentProperty, horizontalPositionProperty, blocksProperty, headerProperty, footerProperty, evenHeaderProperty, evenFooterProperty, firstPageHeaderProperty, firstPageFooterProperty, headersFootersProperty, sectionFormatProperty, listLevelPatternProperty, followCharacterProperty, startAtProperty, restartLevelProperty, levelNumberProperty, numberFormatProperty, abstractListIdProperty, levelsProperty, overrideListLevelProperty, levelOverridesProperty, separatorProperty, continuationSeparatorProperty, continuationNoticeProperty, bookmarkTypeProperty, propertiesProperty, tabJustificationProperty, positionProperty, deletePositionProperty, leaderProperty, tabLeaderProperty, editRangeIdProperty, columnFirstProperty, columnLastProperty, userProperty, groupProperty, editableRangeStartProperty, spaceProperty, fontSchemeProperty, fontSchemeNameProperty, majorFontSchemeProperty, minorFontSchemeProperty, fontSchemeListProperty, fontTypefaceProperty, typefaceProperty, panoseProperty, typeProperty, majorUnitProperty, maximumValueProperty, minimumValueProperty, hasMajorGridLinesProperty, hasMinorGridLinesProperty, majorTickMarkProperty, minorTickMarkProperty, tickLabelPositionProperty, rgbProperty, appearanceProperty, lineFormatTypeProperty, allowSpaceOfSameStyleInTableProperty, weightProperty, inlineFormatProperty, fontNameProperty, isCompressedProperty, columnIndexProperty, columnCountProperty, gridProperty , isAfterParagraphMarkProperty, isAfterCellMarkProperty, isAfterRowMarkProperty, isAfterTableMarkProperty, belowTextProperty, breakClearTypeProperty } from '../../index'; /** * Exports the document to Sfdt format. */ @@ -367,18 +367,55 @@ export class SfdtExport { next = bodyWidget.page.nextPage.bodyWidgets[0]; } } while (next instanceof BodyWidget && next.index === bodyWidget.index); + // While importing, If the last paragraph is empty and the section break is present, then the empty paragraph is removed. So, added the empty paragraph at the end of the section while exporting. + if (!isNullOrUndefined(next) && next instanceof BodyWidget && bodyWidget.sectionIndex !== next.sectionIndex) { + var paragraph = {}; + paragraph[inlinesProperty[this.keywordIndex]] = []; + section[blocksProperty[this.keywordIndex]].push(paragraph); + } return next; } private writeHeaderFooters(hfs: HeaderFooters, section: any): void { if (isNullOrUndefined(hfs)) { return; } - section[headersFootersProperty[this.keywordIndex]][headerProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[0]); - section[headersFootersProperty[this.keywordIndex]][footerProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[1]); - section[headersFootersProperty[this.keywordIndex]][evenHeaderProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[2]); - section[headersFootersProperty[this.keywordIndex]][evenFooterProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[3]); - section[headersFootersProperty[this.keywordIndex]][firstPageHeaderProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[4]); - section[headersFootersProperty[this.keywordIndex]][firstPageFooterProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[5]); + let headersFooters: any = section[headersFootersProperty[this.keywordIndex]]; + if (!(isNullOrUndefined(hfs[0]) || hfs[0].isEmpty)) { + headersFooters[headerProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[0]); + if (JSON.stringify(headersFooters[headerProperty[this.keywordIndex]]) == "{}") { + delete headersFooters[headerProperty[this.keywordIndex]]; + } + } + if (!(isNullOrUndefined(hfs[1]) || hfs[1].isEmpty)) { + headersFooters[footerProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[1]); + if (JSON.stringify(headersFooters[footerProperty[this.keywordIndex]]) == "{}") { + delete headersFooters[footerProperty[this.keywordIndex]]; + } + } + if (!(isNullOrUndefined(hfs[2]) || hfs[2].isEmpty)) { + headersFooters[evenHeaderProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[2]); + if (JSON.stringify(headersFooters[evenHeaderProperty[this.keywordIndex]]) == "{}") { + delete headersFooters[evenHeaderProperty[this.keywordIndex]]; + } + } + if (!(isNullOrUndefined(hfs[3]) || hfs[3].isEmpty)) { + headersFooters[evenFooterProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[3]); + if (JSON.stringify(headersFooters[evenFooterProperty[this.keywordIndex]]) == "{}") { + delete headersFooters[evenFooterProperty[this.keywordIndex]]; + } + } + if (!(isNullOrUndefined(hfs[4]) || hfs[4].isEmpty)) { + headersFooters[firstPageHeaderProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[4]); + if (JSON.stringify(headersFooters[firstPageHeaderProperty[this.keywordIndex]]) == "{}") { + delete headersFooters[firstPageHeaderProperty[this.keywordIndex]]; + } + } + if (!(isNullOrUndefined(hfs[5]) || hfs[5].isEmpty)) { + headersFooters[firstPageFooterProperty[this.keywordIndex]] = this.writeHeaderFooter(hfs[5]); + if (JSON.stringify(headersFooters[firstPageFooterProperty[this.keywordIndex]]) == "{}") { + delete headersFooters[firstPageFooterProperty[this.keywordIndex]]; + } + } } private writeHeaderFooter(widget: HeaderFooterWidget): any { if (isNullOrUndefined(widget) || widget.isEmpty) { @@ -612,7 +649,9 @@ export class SfdtExport { } else { this.isBlockClosed = true; } - } + } else { + this.isBlockClosed = true; + } if (!isNullOrUndefined(block[blocksProperty[this.keywordIndex]])) { let child: LineWidget = widget.childWidgets[0] as LineWidget; let firstChild: ElementBox = child.children[0]; @@ -678,7 +717,7 @@ export class SfdtExport { next = paragraphWidget.nextSplitWidget as ParagraphWidget; } next = paragraphWidget.nextRenderedWidget as BlockWidget; - if (isNullOrUndefined(next) && paragraphWidget.containerWidget instanceof BodyWidget && + if (this.documentHelper.owner.layoutType !== 'Continuous' && isNullOrUndefined(next) && paragraphWidget.containerWidget instanceof BodyWidget && !isNullOrUndefined((paragraphWidget.containerWidget as BodyWidget).page.nextPage) && !isNullOrUndefined((paragraphWidget.containerWidget as BodyWidget).page.nextPage.bodyWidgets)) { next = (paragraphWidget.containerWidget as BodyWidget).page.nextPage.bodyWidgets[0].childWidgets[0] as BlockWidget; @@ -752,7 +791,7 @@ export class SfdtExport { } } if (nextElement instanceof ContentControl && nextElement.type === 1 && !this.nestedContent) { - if (this.multipleLineContent) { + if (this.multipleLineContent && !isNullOrUndefined(inlines)) { inlines[inlines.length - 1][contentControlPropertiesProperty[this.keywordIndex]] = this.contentControlProperty(nextElement.contentControlProperties); this.multipleLineContent = false; return; @@ -800,7 +839,7 @@ export class SfdtExport { if (element instanceof FieldElementBox) { inline[fieldTypeProperty[this.keywordIndex]] = element.fieldType; if (element.fieldType === 0) { - inline[hasFieldEndProperty[this.keywordIndex]] = true; + inline[hasFieldEndProperty[this.keywordIndex]] = element.hasFieldEnd; if (element.formFieldData) { inline[formFieldDataProperty[this.keywordIndex]] = {}; inline[formFieldDataProperty[this.keywordIndex]][nameProperty[this.keywordIndex]] = element.formFieldData.name; @@ -812,7 +851,7 @@ export class SfdtExport { inline[formFieldDataProperty[this.keywordIndex]][textInputProperty[this.keywordIndex]][typeProperty[this.keywordIndex]] = this.keywordIndex == 1 ? this.getTextFormFieldTypeEnumValue((element.formFieldData as TextFormField).type) : (element.formFieldData as TextFormField).type; inline[formFieldDataProperty[this.keywordIndex]][textInputProperty[this.keywordIndex]][maxLengthProperty[this.keywordIndex]] = (element.formFieldData as TextFormField).maxLength; inline[formFieldDataProperty[this.keywordIndex]][textInputProperty[this.keywordIndex]][defaultValueProperty[this.keywordIndex]] = (element.formFieldData as TextFormField).defaultValue; - inline[formFieldDataProperty[this.keywordIndex]][textInputProperty[this.keywordIndex]][formatProperty[this.keywordIndex]] = this.keywordIndex == 1 ? this.getTextFormFieldFormatEnumValue((element.formFieldData as TextFormField).format) : (element.formFieldData as TextFormField).format; + inline[formFieldDataProperty[this.keywordIndex]][textInputProperty[this.keywordIndex]][formatProperty[this.keywordIndex]] = this.keywordIndex == 1 && (element.formFieldData as TextFormField).type === 'Text' ? this.getTextFormFieldFormatEnumValue((element.formFieldData as TextFormField).format) : (element.formFieldData as TextFormField).format; } else if (element.formFieldData instanceof CheckBoxFormField) { inline[formFieldDataProperty[this.keywordIndex]][checkBoxProperty[this.keywordIndex]] = {}; this.checkboxOrDropdown = true; @@ -850,7 +889,7 @@ export class SfdtExport { inline[getImageHeightProperty[this.keywordIndex]] = element.cropHeightScale; } inline[nameProperty[this.keywordIndex]] = element.name; - inline[alternativeTextProperty[this.keywordIndex]] = element.alternativeText; + inline[alternativeTextProperty[this.keywordIndex]] = element.alternateText; inline[titleProperty[this.keywordIndex]] = element.title; inline[visibleProperty[this.keywordIndex]] = HelperMethods.getBoolInfo(element.visible, this.keywordIndex); inline[widthScaleProperty[this.keywordIndex]] = element.widthScale; @@ -904,6 +943,8 @@ export class SfdtExport { } inline[propertiesProperty[this.keywordIndex]] = properties; } + } else if (element instanceof BreakElementBox) { + inline[breakClearTypeProperty[this.keywordIndex]] = this.keywordIndex == 1? HelperMethods.getBreakClearType(element.breakClearType): element.breakClearType; } else if (element instanceof TextElementBox) { // replacing the no break hyphen character by '-' if (element.text.indexOf(String.fromCharCode(30)) !== -1) { @@ -979,11 +1020,16 @@ export class SfdtExport { private writeShape(element: ShapeElementBox, inline: any): void { inline[shapeIdProperty[this.keywordIndex]] = element.shapeId; inline[nameProperty[this.keywordIndex]] = element.name; - inline[alternativeTextProperty[this.keywordIndex]] = element.alternativeText; + inline[alternativeTextProperty[this.keywordIndex]] = element.alternateText; inline[titleProperty[this.keywordIndex]] = element.title; inline[visibleProperty[this.keywordIndex]] = HelperMethods.getBoolInfo(element.visible, this.keywordIndex); inline[widthProperty[this.keywordIndex]] = HelperMethods.convertPixelToPoint(element.width); inline[heightProperty[this.keywordIndex]] = HelperMethods.convertPixelToPoint(element.height); + if (element.isZeroHeight) { + inline[heightProperty[this.keywordIndex]] = 0; + } else { + inline[heightProperty[this.keywordIndex]] = HelperMethods.convertPixelToPoint(element.height); + } inline[widthScaleProperty[this.keywordIndex]] = element.widthScale; inline[heightScaleProperty[this.keywordIndex]] = element.heightScale; inline[verticalPositionProperty[this.keywordIndex]] = HelperMethods.convertPixelToPoint(element.verticalPosition); @@ -994,6 +1040,8 @@ export class SfdtExport { inline[horizontalOriginProperty[this.keywordIndex]] = this.keywordIndex == 1 ? this.getHorizontalOriginEnumValue(element.horizontalOrigin) : element.horizontalOrigin; inline[horizontalAlignmentProperty[this.keywordIndex]] = this.keywordIndex == 1 ? this.getShapeHorizontalAlignmentEnumValue(element.horizontalAlignment) : element.horizontalAlignment; inline[horizontalRelativePercentProperty[this.keywordIndex]] = element.horizontalRelativePercent; + inline[heightRelativePercentProperty[this.keywordIndex]] = element.heightRelativePercent; + inline[widthRelativePercentProperty[this.keywordIndex]] = element.widthRelativePercent; inline[zOrderPositionProperty[this.keywordIndex]] = element.zOrderPosition; inline[allowOverlapProperty[this.keywordIndex]] = HelperMethods.getBoolInfo(element.allowOverlap, this.keywordIndex); inline[textWrappingStyleProperty[this.keywordIndex]] = this.keywordIndex == 1 ? this.getTextWrappingStyleEnumValue(element.textWrappingStyle) : element.textWrappingStyle; @@ -1037,6 +1085,9 @@ export class SfdtExport { inline[textFrameProperty[this.keywordIndex]][blocksProperty[this.keywordIndex]] = []; for (let j: number = 0; j < element.textFrame.childWidgets.length; j++) { let textFrameBlock: BlockWidget = element.textFrame.childWidgets[j] as BlockWidget; + if (textFrameBlock.hasOwnProperty('contentControlProperties') && !isNullOrUndefined(element.paragraph) && (element.paragraph.hasOwnProperty('contentControlProperties'))) { + this.blocks = []; + } this.writeBlock(textFrameBlock, 0, inline[textFrameProperty[this.keywordIndex]][blocksProperty[this.keywordIndex]]); } } @@ -1085,7 +1136,7 @@ export class SfdtExport { chartDataFormat[fillProperty[this.keywordIndex]][foreColorProperty[this.keywordIndex]] = format.fill.color.substring(2); } else { - chartDataFormat[fillProperty[this.keywordIndex]][fontColorProperty[this.keywordIndex]] = format.fill.color; + chartDataFormat[fillProperty[this.keywordIndex]][foreColorProperty[this.keywordIndex]] = format.fill.color; } } chartDataFormat[fillProperty[this.keywordIndex]][rgbProperty[this.keywordIndex]] = format.fill.rgb; @@ -1451,32 +1502,9 @@ export class SfdtExport { } private writeParagraphFormat(format: WParagraphFormat, isInline?: boolean): any { let paragraphFormat: any = {}; - paragraphFormat[bordersProperty[this.keywordIndex]] = this.writeParagraphBorders(format.borders); - paragraphFormat[leftIndentProperty[this.keywordIndex]] = isInline ? format.leftIndent : format.getValue('leftIndent'); - paragraphFormat[rightIndentProperty[this.keywordIndex]] = isInline ? format.rightIndent : format.getValue('rightIndent'); - paragraphFormat[firstLineIndentProperty[this.keywordIndex]] = isInline ? format.firstLineIndent : format.getValue('firstLineIndent'); - paragraphFormat[textAlignmentProperty[this.keywordIndex]] = isInline ? - this.keywordIndex == 1 ? this.getTextAlignmentEnumValue(format.textAlignment): format.textAlignment : - this.keywordIndex == 1 ? this.getTextAlignmentEnumValue(format.getValue('textAlignment') as TextAlignment) : format.getValue('textAlignment') as TextAlignment; - paragraphFormat[beforeSpacingProperty[this.keywordIndex]] = isInline ? format.beforeSpacing : format.getValue('beforeSpacing'); - paragraphFormat[afterSpacingProperty[this.keywordIndex]] = isInline ? format.afterSpacing : format.getValue('afterSpacing'); - paragraphFormat[spaceBeforeAutoProperty[this.keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.spaceBeforeAuto, this.keywordIndex) : format.getValue('spaceBeforeAuto'); - paragraphFormat[spaceAfterAutoProperty[this.keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.spaceAfterAuto, this.keywordIndex) : format.getValue('spaceAfterAuto'); - paragraphFormat[lineSpacingProperty[this.keywordIndex]] = isInline ? format.lineSpacing : format.getValue('lineSpacing'); - paragraphFormat[lineSpacingTypeProperty[this.keywordIndex]] = isInline ? - this.keywordIndex == 1 ? this.getLineSpacingTypeEnumValue(format.lineSpacingType): format.lineSpacingType : - this.keywordIndex == 1 ? this.getLineSpacingTypeEnumValue(format.getValue('lineSpacingType') as LineSpacingType): format.getValue('lineSpacingType') as LineSpacingType; - paragraphFormat[styleNameProperty[this.keywordIndex]] = !isNullOrUndefined(format.baseStyle) ? format.baseStyle.name : undefined; - paragraphFormat[outlineLevelProperty[this.keywordIndex]] = isInline ? - this.keywordIndex == 1 ? this.getOutlineLevelEnumValue(format.outlineLevel):format.outlineLevel : - this.keywordIndex == 1 ? this.getOutlineLevelEnumValue(format.getValue('outlineLevel') as OutlineLevel) : format.getValue('outlineLevel') as OutlineLevel; + HelperMethods.writeParagraphFormat(paragraphFormat, isInline, format, this.keywordIndex); paragraphFormat[listFormatProperty[this.keywordIndex]] = this.writeListFormat(format.listFormat, isInline); paragraphFormat[tabsProperty[this.keywordIndex]] = this.writeTabs(format.tabs); - paragraphFormat[bidiProperty[this.keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.bidi, this.keywordIndex) : format.getValue('bidi'); - paragraphFormat[keepLinesTogetherProperty[this.keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.keepLinesTogether, this.keywordIndex) : format.getValue('keepLinesTogether'); - paragraphFormat[keepWithNextProperty[this.keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.keepWithNext, this.keywordIndex) : format.getValue('keepWithNext'); - paragraphFormat[contextualSpacingProperty[this.keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.contextualSpacing, this.keywordIndex) : format.getValue('contextualSpacing'); - paragraphFormat[widowControlProperty[this.keywordIndex]] = isInline ? HelperMethods.getBoolInfo(format.widowControl, this.keywordIndex) : format.getValue('widowControl'); if (this.writeInlineStyles && !isInline) { paragraphFormat[inlineFormatProperty[this.keywordIndex]] = this.writeParagraphFormat(format, true); } @@ -1689,39 +1717,17 @@ export class SfdtExport { this.keywordIndex == 1 ? this.getTextureStyleEnumValue(wShading.textureStyle) : wShading.textureStyle : undefined; return shading; } - private writeBorder(wBorder: WBorder): any { - let border: any = {}; - border[colorProperty[this.keywordIndex]] = wBorder.hasValue('color') ? wBorder.color : undefined; - border[hasNoneStyleProperty[this.keywordIndex]] = wBorder.hasValue('hasNoneStyle') ? HelperMethods.getBoolInfo(wBorder.hasNoneStyle, this.keywordIndex) : undefined; - border[lineStyleProperty[this.keywordIndex]] = wBorder.hasValue('lineStyle') ? - this.keywordIndex == 1 ? this.getLineStyleEnumValue(wBorder.lineStyle) : wBorder.lineStyle : undefined; - border[lineWidthProperty[this.keywordIndex]] = wBorder.hasValue('lineWidth') ? wBorder.lineWidth : undefined; - border[shadowProperty[this.keywordIndex]] = wBorder.hasValue('shadow') ? HelperMethods.getBoolInfo(wBorder.shadow, this.keywordIndex) : undefined; - border[spaceProperty[this.keywordIndex]] = wBorder.hasValue('space') ? wBorder.space : undefined; - return border; - } - - private writeParagraphBorders(wBorders: WBorders): any { - let borders: any = {}; - borders[topProperty[this.keywordIndex]] = this.writeBorder(wBorders.getBorder('top')); - borders[leftProperty[this.keywordIndex]] = this.writeBorder(wBorders.getBorder('left')); - borders[rightProperty[this.keywordIndex]] = this.writeBorder(wBorders.getBorder('right')); - borders[bottomProperty[this.keywordIndex]] = this.writeBorder(wBorders.getBorder('bottom')); - borders[horizontalProperty[this.keywordIndex]] = this.writeBorder(wBorders.getBorder('horizontal')); - borders[verticalProperty[this.keywordIndex]] = this.writeBorder(wBorders.getBorder('vertical')); - return borders; - } private writeBorders(wBorders: WBorders): any { let borders: any = {}; - borders[topProperty[this.keywordIndex]] = this.writeBorder(wBorders.top); - borders[leftProperty[this.keywordIndex]] = this.writeBorder(wBorders.left); - borders[rightProperty[this.keywordIndex]] = this.writeBorder(wBorders.right); - borders[bottomProperty[this.keywordIndex]] = this.writeBorder(wBorders.bottom); - borders[diagonalDownProperty[this.keywordIndex]] = this.writeBorder(wBorders.diagonalDown); - borders[diagonalUpProperty[this.keywordIndex]] = this.writeBorder(wBorders.diagonalUp); - borders[horizontalProperty[this.keywordIndex]] = this.writeBorder(wBorders.horizontal); - borders[verticalProperty[this.keywordIndex]] = this.writeBorder(wBorders.vertical); + borders[topProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.top, this.keywordIndex); + borders[leftProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.left, this.keywordIndex); + borders[rightProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.right, this.keywordIndex); + borders[bottomProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.bottom, this.keywordIndex); + borders[diagonalDownProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.diagonalDown, this.keywordIndex); + borders[diagonalUpProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.diagonalUp, this.keywordIndex); + borders[horizontalProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.horizontal, this.keywordIndex); + borders[verticalProperty[this.keywordIndex]] = HelperMethods.writeBorder(wBorders.vertical, this.keywordIndex); return borders; } private writeCellFormat(wCellFormat: WCellFormat): any { @@ -2013,52 +2019,7 @@ export class SfdtExport { } return cell; } - private getLineSpacingTypeEnumValue(lineSpacing: LineSpacingType): number { - switch (lineSpacing) { - case 'Multiple': - return 0; - case 'AtLeast': - return 1; - case 'Exactly': - return 2; - } - } - private getOutlineLevelEnumValue(outlineLevel: OutlineLevel): number { - switch (outlineLevel) { - case 'BodyText': - return 0; - case 'Level1': - return 1; - case 'Level2': - return 2; - case 'Level3': - return 3; - case 'Level4': - return 4; - case 'Level5': - return 5; - case 'Level6': - return 6; - case 'Level7': - return 7; - case 'Level8': - return 8; - case 'Level9': - return 9; - } - } - private getTextAlignmentEnumValue(textAlignment: TextAlignment): number { - switch (textAlignment) { - case 'Left': - return 0; - case 'Center': - return 1; - case 'Right': - return 2; - case 'Justify': - return 3; - } - } + private getWidthTypeEnumValue(widthType: WidthType): number { switch (widthType) { case 'Auto': @@ -2079,64 +2040,7 @@ export class SfdtExport { return 2; } } - private getLineStyleEnumValue(lineStyle: LineStyle): number { - switch (lineStyle) { - case 'Single': - return 0; - case 'None': - return 1; - case 'Dot': - return 2; - case 'DashSmallGap': - return 3; - case 'DashLargeGap': - return 4; - case 'DashDot': - return 5; - case 'DashDotDot': - return 6; - case 'Double': - return 7; - case 'Triple': - return 8; - case 'ThinThickSmallGap': - return 9; - case 'ThickThinSmallGap': - return 10; - case 'ThinThickThinSmallGap': - return 11; - case 'ThinThickMediumGap': - return 12; - case 'ThickThinMediumGap': - return 13; - case 'ThinThickThinMediumGap': - return 14; - case 'ThinThickLargeGap': - return 15; - case 'ThickThinLargeGap': - return 16; - case 'ThinThickThinLargeGap': - return 17; - case 'SingleWavy': - return 18; - case 'DoubleWavy': - return 19; - case 'DashDotStroked': - return 20; - case 'Emboss3D': - return 21; - case 'Engrave3D': - return 22; - case 'Outset': - return 23; - case 'Inset': - return 24; - case 'Thick': - return 25; - case 'Cleared': - return 26; - } - } + private getTextureStyleEnumValue(textureStyle: TextureStyle): number { switch (textureStyle) { case 'TextureNone': @@ -2587,9 +2491,9 @@ export class SfdtExport { case 'Number': return 1; case 'Date': - return 3; + return 2; case 'Calculation': - return 4; + return 3; } } private getTextFormFieldFormatEnumValue(textFormFieldFormat: string): number { 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 f0b17d2fcc..9a315cf748 100644 --- a/controls/documenteditor/src/document-editor/implementation/writer/word-export.ts +++ b/controls/documenteditor/src/document-editor/implementation/writer/word-export.ts @@ -4,10 +4,10 @@ import { isNullOrUndefined } from '@syncfusion/ej2-base'; import { ImageFormatInfo, ImageStringInfo, HelperMethods } from '../index'; import { Dictionary, TabJustification, TabLeader, WColumnFormat, LocaleId } from '../../index'; import { WTabStop } from '../index'; -import { ProtectionType, CompatibilityMode } from '../../base'; +import { ProtectionType, CompatibilityMode, BreakClearType } from '../../base'; import { DocumentHelper } from '../viewer'; import { Revision } from '../track-changes/track-changes'; -import { sectionsProperty, fontSubstitutionTableProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, backgroundProperty, stylesProperty, commentsProperty, revisionsProperty, customXmlProperty, defaultTabWidthProperty, formattingProperty, trackChangesProperty, protectionTypeProperty, enforcementProperty, hashValueProperty, saltValueProperty, cryptProviderTypeProperty, cryptAlgorithmClassProperty, cryptAlgorithmTypeProperty, cryptAlgorithmSidProperty, cryptSpinCountProperty, doNotUseHTMLParagraphAutoSpacingProperty, alignTablesRowByRowProperty, formFieldShadingProperty, lastParagraphMarkCopiedProperty, footnotesProperty, endnotesProperty, compatibilityModeProperty, themeFontLanguagesProperty, themesProperty, nameProperty, basedOnProperty, nextProperty, linkProperty, localeIdProperty, localeIdFarEastProperty, localeIdBidiProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, bidiProperty, bdoProperty, fontSizeBidiProperty, fontFamilyBidiProperty, boldBidiProperty, italicBidiProperty, allCapsProperty, complexScriptProperty, fontFamilyAsciiProperty, fontFamilyFarEastProperty, fontFamilyNonFarEastProperty, revisionIdsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, spaceAfterAutoProperty, spaceBeforeAutoProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, keepWithNextProperty, widowControlProperty, keepLinesTogetherProperty, outlineLevelProperty, contextualSpacingProperty, bordersProperty, tabsProperty, headerDistanceProperty, footerDistanceProperty, differentFirstPageProperty, differentOddAndEvenPagesProperty, pageWidthProperty, pageHeightProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, restartPageNumberingProperty, pageStartingNumberProperty, endnoteNumberFormatProperty, footNoteNumberFormatProperty, restartIndexForFootnotesProperty, restartIndexForEndnotesProperty, initialFootNoteNumberProperty, initialEndNoteNumberProperty, pageNumberStyleProperty, columnsProperty, numberOfColumnsProperty, equalWidthProperty, lineBetweenColumnsProperty, breakCodeProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, allowBreakAcrossPagesProperty, isHeaderProperty, heightTypeProperty, beforeWidthProperty, afterWidthProperty, gridBeforeProperty, gridBeforeWidthProperty, gridBeforeWidthTypeProperty, gridAfterProperty, gridAfterWidthProperty, gridAfterWidthTypeProperty, allowAutoFitProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, horizontalPositionAbsProperty, textureProperty, backgroundColorProperty, foregroundColorProperty, shadowProperty, hasNoneStyleProperty, verticalProperty, horizontalProperty, diagonalUpProperty, diagonalDownProperty, lineStyleProperty, lineWidthProperty, layoutProperty, dataFormatProperty, yValueProperty, chartDataProperty, categoryXNameProperty, lineProperty, foreColorProperty, patternProperty, layoutXProperty, layoutYProperty, directionProperty, endStyleProperty, numberValueProperty, markerStyleProperty, markerColorProperty, markerSizeProperty, forwardProperty, backwardProperty, interceptProperty, isDisplayRSquaredProperty, isDisplayEquationProperty, seriesNameProperty, dataLabelProperty, errorBarProperty, seriesFormatProperty, trendLinesProperty, dataPointsProperty, firstSliceAngleProperty, holeSizeProperty, isLegendKeyProperty, isBubbleSizeProperty, isCategoryNameProperty, isSeriesNameProperty, isValueProperty, isPercentageProperty, isLeaderLinesProperty, showSeriesKeysProperty, hasHorizontalBorderProperty, hasVerticalBorderProperty, hasBordersProperty, categoryTypeProperty, chartCategoryProperty, chartSeriesProperty, chartAreaProperty, chartTitleAreaProperty, plotAreaProperty, chartLegendProperty, chartPrimaryCategoryAxisProperty, chartPrimaryValueAxisProperty, chartTitleProperty, chartTypeProperty, gapWidthProperty, overlapProperty, chartDataTableProperty, textProperty, shapeIdProperty, alternativeTextProperty, visibleProperty, widthProperty, heightProperty, widthScaleProperty, heightScaleProperty, lineFormatProperty, fillFormatProperty, textWrappingStyleProperty, textWrappingTypeProperty, verticalRelativePercentProperty, horizontalRelativePercentProperty, zOrderPositionProperty, layoutInCellProperty, lockAnchorProperty, autoShapeTypeProperty, textFrameProperty, colorProperty, fillProperty, textVerticalAlignmentProperty, imageStringProperty, metaFileImageStringProperty, lengthProperty, isInlineImageProperty, isMetaFileProperty, topProperty, bottomProperty, rightProperty, leftProperty, getImageHeightProperty, getImageWidthProperty, hasFieldEndProperty, formFieldDataProperty, fieldTypeProperty, enabledProperty, helpTextProperty, statusTextProperty, textInputProperty, checkBoxProperty, dropDownListProperty, maxLengthProperty, defaultValueProperty, formatProperty, sizeTypeProperty, sizeProperty, checkedProperty, dropDownItemsProperty, selectedIndexProperty, commentIdProperty, commentCharacterTypeProperty, authorProperty, initialProperty, dateProperty, doneProperty, replyCommentsProperty, revisionTypeProperty, revisionIdProperty, itemIDProperty, xmlProperty, footnoteTypeProperty, symbolCodeProperty, symbolFontNameProperty, customMarkerProperty, inlinesProperty, contentControlPropertiesProperty, lockContentControlProperty, lockContentsProperty, tagProperty, titleProperty, hasPlaceHolderTextProperty, multiLineProperty, isTemporaryProperty, dateCalendarTypeProperty, dateStorageFormatProperty, dateDisplayLocaleProperty, dateDisplayFormatProperty, isCheckedProperty, uncheckedStateProperty, checkedStateProperty, contentControlListItemsProperty, xmlMappingProperty, fontProperty, valueProperty, displayTextProperty, isMappedProperty, isWordMlProperty, prefixMappingProperty, xPathProperty, storeItemIdProperty, customXmlPartProperty, idProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, descriptionProperty, wrapTextAroundProperty, positioningProperty, tableFormatProperty, allowOverlapProperty, distanceTopProperty, distanceRightProperty, distanceLeftProperty, distanceBottomProperty, verticalOriginProperty, verticalPositionProperty, horizontalOriginProperty, horizontalAlignmentProperty, horizontalPositionProperty, blocksProperty, headerProperty, footerProperty, evenHeaderProperty, evenFooterProperty, firstPageHeaderProperty, firstPageFooterProperty, headersFootersProperty, sectionFormatProperty, listLevelPatternProperty, followCharacterProperty, startAtProperty, restartLevelProperty, levelNumberProperty, numberFormatProperty, abstractListIdProperty, levelsProperty, overrideListLevelProperty, levelOverridesProperty, separatorProperty, continuationSeparatorProperty, continuationNoticeProperty, bookmarkTypeProperty, propertiesProperty, tabJustificationProperty, positionProperty, deletePositionProperty, leaderProperty, tabLeaderProperty, editRangeIdProperty, columnFirstProperty, columnLastProperty, userProperty, groupProperty, editableRangeStartProperty, spaceProperty, fontSchemeProperty, fontSchemeNameProperty, majorFontSchemeProperty, minorFontSchemeProperty, fontSchemeListProperty, fontTypefaceProperty, typefaceProperty, panoseProperty, typeProperty, majorUnitProperty, maximumValueProperty, minimumValueProperty, hasMajorGridLinesProperty, hasMinorGridLinesProperty, majorTickMarkProperty, minorTickMarkProperty, tickLabelPositionProperty, rgbProperty, appearanceProperty, lineFormatTypeProperty, allowSpaceOfSameStyleInTableProperty, weightProperty, inlineFormatProperty, fontNameProperty, isCompressedProperty, columnIndexProperty , isAfterRowMarkProperty, isAfterParagraphMarkProperty, columnCountProperty, gridProperty} from '../../index'; +import { sectionsProperty, fontSubstitutionTableProperty, breakClearTypeProperty, characterFormatProperty, paragraphFormatProperty, listsProperty, abstractListsProperty, backgroundProperty, stylesProperty, commentsProperty, revisionsProperty, customXmlProperty, defaultTabWidthProperty, formattingProperty, trackChangesProperty, protectionTypeProperty, enforcementProperty, hashValueProperty, saltValueProperty, cryptProviderTypeProperty, cryptAlgorithmClassProperty, cryptAlgorithmTypeProperty, cryptAlgorithmSidProperty, cryptSpinCountProperty, doNotUseHTMLParagraphAutoSpacingProperty, alignTablesRowByRowProperty, formFieldShadingProperty, lastParagraphMarkCopiedProperty, footnotesProperty, endnotesProperty, compatibilityModeProperty, themeFontLanguagesProperty, themesProperty, nameProperty, basedOnProperty, nextProperty, linkProperty, localeIdProperty, localeIdFarEastProperty, localeIdBidiProperty, boldProperty, italicProperty, underlineProperty, baselineAlignmentProperty, strikethroughProperty, highlightColorProperty, fontSizeProperty, fontColorProperty, fontFamilyProperty, styleNameProperty, bidiProperty, bdoProperty, fontSizeBidiProperty, fontFamilyBidiProperty, boldBidiProperty, italicBidiProperty, allCapsProperty, complexScriptProperty, fontFamilyAsciiProperty, fontFamilyFarEastProperty, fontFamilyNonFarEastProperty, revisionIdsProperty, listIdProperty, listLevelNumberProperty, leftIndentProperty, rightIndentProperty, firstLineIndentProperty, textAlignmentProperty, afterSpacingProperty, beforeSpacingProperty, spaceAfterAutoProperty, spaceBeforeAutoProperty, lineSpacingProperty, lineSpacingTypeProperty, listFormatProperty, keepWithNextProperty, widowControlProperty, keepLinesTogetherProperty, outlineLevelProperty, contextualSpacingProperty, bordersProperty, tabsProperty, headerDistanceProperty, footerDistanceProperty, differentFirstPageProperty, differentOddAndEvenPagesProperty, pageWidthProperty, pageHeightProperty, leftMarginProperty, rightMarginProperty, topMarginProperty, bottomMarginProperty, restartPageNumberingProperty, pageStartingNumberProperty, endnoteNumberFormatProperty, footNoteNumberFormatProperty, restartIndexForFootnotesProperty, restartIndexForEndnotesProperty, initialFootNoteNumberProperty, initialEndNoteNumberProperty, pageNumberStyleProperty, columnsProperty, numberOfColumnsProperty, equalWidthProperty, lineBetweenColumnsProperty, breakCodeProperty, cellWidthProperty, columnSpanProperty, rowSpanProperty, verticalAlignmentProperty, allowBreakAcrossPagesProperty, isHeaderProperty, heightTypeProperty, beforeWidthProperty, afterWidthProperty, gridBeforeProperty, gridBeforeWidthProperty, gridBeforeWidthTypeProperty, gridAfterProperty, gridAfterWidthProperty, gridAfterWidthTypeProperty, allowAutoFitProperty, cellSpacingProperty, shadingProperty, tableAlignmentProperty, preferredWidthProperty, preferredWidthTypeProperty, horizontalPositionAbsProperty, textureProperty, backgroundColorProperty, foregroundColorProperty, shadowProperty, hasNoneStyleProperty, verticalProperty, horizontalProperty, diagonalUpProperty, diagonalDownProperty, lineStyleProperty, lineWidthProperty, layoutProperty, dataFormatProperty, yValueProperty, chartDataProperty, categoryXNameProperty, lineProperty, foreColorProperty, patternProperty, layoutXProperty, layoutYProperty, directionProperty, endStyleProperty, numberValueProperty, markerStyleProperty, markerColorProperty, markerSizeProperty, forwardProperty, backwardProperty, interceptProperty, isDisplayRSquaredProperty, isDisplayEquationProperty, seriesNameProperty, dataLabelProperty, errorBarProperty, seriesFormatProperty, trendLinesProperty, dataPointsProperty, firstSliceAngleProperty, holeSizeProperty, isLegendKeyProperty, isBubbleSizeProperty, isCategoryNameProperty, isSeriesNameProperty, isValueProperty, isPercentageProperty, isLeaderLinesProperty, showSeriesKeysProperty, hasHorizontalBorderProperty, hasVerticalBorderProperty, hasBordersProperty, categoryTypeProperty, chartCategoryProperty, chartSeriesProperty, chartAreaProperty, chartTitleAreaProperty, plotAreaProperty, chartLegendProperty, chartPrimaryCategoryAxisProperty, chartPrimaryValueAxisProperty, chartTitleProperty, chartTypeProperty, gapWidthProperty, overlapProperty, chartDataTableProperty, textProperty, shapeIdProperty, alternativeTextProperty, visibleProperty, widthProperty, heightProperty, widthScaleProperty, heightScaleProperty, lineFormatProperty, fillFormatProperty, textWrappingStyleProperty, textWrappingTypeProperty, verticalRelativePercentProperty, horizontalRelativePercentProperty, zOrderPositionProperty, layoutInCellProperty, lockAnchorProperty, autoShapeTypeProperty, textFrameProperty, colorProperty, fillProperty, textVerticalAlignmentProperty, imageStringProperty, metaFileImageStringProperty, lengthProperty, isInlineImageProperty, isMetaFileProperty, topProperty, bottomProperty, rightProperty, leftProperty, getImageHeightProperty, getImageWidthProperty, hasFieldEndProperty, formFieldDataProperty, fieldTypeProperty, enabledProperty, helpTextProperty, statusTextProperty, textInputProperty, checkBoxProperty, dropDownListProperty, maxLengthProperty, defaultValueProperty, formatProperty, sizeTypeProperty, sizeProperty, checkedProperty, dropDownItemsProperty, selectedIndexProperty, commentIdProperty, commentCharacterTypeProperty, authorProperty, initialProperty, dateProperty, doneProperty, replyCommentsProperty, revisionTypeProperty, revisionIdProperty, itemIDProperty, xmlProperty, footnoteTypeProperty, symbolCodeProperty, symbolFontNameProperty, customMarkerProperty, inlinesProperty, contentControlPropertiesProperty, lockContentControlProperty, lockContentsProperty, tagProperty, titleProperty, hasPlaceHolderTextProperty, multiLineProperty, isTemporaryProperty, dateCalendarTypeProperty, dateStorageFormatProperty, dateDisplayLocaleProperty, dateDisplayFormatProperty, isCheckedProperty, uncheckedStateProperty, checkedStateProperty, contentControlListItemsProperty, xmlMappingProperty, fontProperty, valueProperty, displayTextProperty, isMappedProperty, isWordMlProperty, prefixMappingProperty, xPathProperty, storeItemIdProperty, customXmlPartProperty, idProperty, cellFormatProperty, rowFormatProperty, cellsProperty, rowsProperty, descriptionProperty, wrapTextAroundProperty, positioningProperty, tableFormatProperty, allowOverlapProperty, distanceTopProperty, distanceRightProperty, distanceLeftProperty, distanceBottomProperty, verticalOriginProperty, verticalPositionProperty, horizontalOriginProperty, horizontalAlignmentProperty, horizontalPositionProperty, blocksProperty, headerProperty, footerProperty, evenHeaderProperty, evenFooterProperty, firstPageHeaderProperty, firstPageFooterProperty, headersFootersProperty, sectionFormatProperty, listLevelPatternProperty, followCharacterProperty, startAtProperty, restartLevelProperty, levelNumberProperty, numberFormatProperty, abstractListIdProperty, levelsProperty, overrideListLevelProperty, levelOverridesProperty, separatorProperty, continuationSeparatorProperty, continuationNoticeProperty, bookmarkTypeProperty, propertiesProperty, tabJustificationProperty, positionProperty, deletePositionProperty, leaderProperty, tabLeaderProperty, editRangeIdProperty, columnFirstProperty, columnLastProperty, userProperty, groupProperty, editableRangeStartProperty, spaceProperty, fontSchemeProperty, fontSchemeNameProperty, majorFontSchemeProperty, minorFontSchemeProperty, fontSchemeListProperty, fontTypefaceProperty, typefaceProperty, panoseProperty, typeProperty, majorUnitProperty, maximumValueProperty, minimumValueProperty, hasMajorGridLinesProperty, hasMinorGridLinesProperty, majorTickMarkProperty, minorTickMarkProperty, tickLabelPositionProperty, rgbProperty, appearanceProperty, lineFormatTypeProperty, allowSpaceOfSameStyleInTableProperty, weightProperty, inlineFormatProperty, fontNameProperty, isCompressedProperty, columnIndexProperty , isAfterRowMarkProperty, isAfterParagraphMarkProperty, columnCountProperty, gridProperty, characterSpacingProperty, scalingProperty} from '../../index'; /** * Exports the document to Word format. @@ -345,6 +345,7 @@ export class WordExport { private isBookmarkAtRowEnd: Boolean = false; private keywordIndex: number = undefined; private isHeaderFooter: boolean = false; + private isSerializeFootEndNote: string = undefined; // Gets the bookmark name private get bookmarks(): string[] { if (isNullOrUndefined(this.mBookmarks)) { @@ -1606,7 +1607,9 @@ export class WordExport { private serializeTrackChanges(writer: XmlWriter, type: any, author: any, date: any): void { writer.writeStartElement('w', type, this.wNamespace); writer.writeAttributeString('w', 'id', this.wNamespace, (this.trackChangesId++).toString()); - writer.writeAttributeString('w', 'author', this.wNamespace, author); + if(author != "Unknown") { + writer.writeAttributeString('w', 'author', this.wNamespace, author); + } writer.writeAttributeString('w', 'date', this.wNamespace, date); } @@ -1669,7 +1672,19 @@ export class WordExport { } else if (item.hasOwnProperty(footnoteTypeProperty[this.keywordIndex])) { this.serializeEFReference(writer, item); } else { - this.serializeTextRange(writer, item, previousNode); + if(!isNullOrUndefined(this.isSerializeFootEndNote) && i == 0) { + writer.writeStartElement(undefined, 'r', this.wNamespace); + if(this.isSerializeFootEndNote === "Footnote") { + writer.writeStartElement(undefined, 'footnoteRef', this.wNamespace); + writer.writeEndElement(); + } else { + writer.writeStartElement(undefined, 'endnoteRef', this.wNamespace); + writer.writeEndElement(); + } + writer.writeEndElement(); + } else { + this.serializeTextRange(writer, item, previousNode); + } } //Serialize revision end this.serializeRevisionEnd(writer, item, previousNode); @@ -1741,18 +1756,21 @@ export class WordExport { } } private serializeInlineEndnotes(writer: XmlWriter, endNote: any, id: string): void { + this.isSerializeFootEndNote = "Endnote"; this.endNoteFootnote = endNote; const owner: any = this.blockOwner; this.blockOwner = endNote; writer.writeStartElement('w', 'endnote', this.wNamespace); writer.writeAttributeString(undefined, 'id', this.wNamespace, id); - this.serializeBodyItems(writer, endNote, true); + this.serializeBodyItems(writer, endNote, true); writer.writeEndElement(); this.blockOwner = owner; this.endNoteFootnote = undefined; + this.isSerializeFootEndNote = undefined; } private serializeInlineFootnotes(writer: XmlWriter, footNote: any, id: string): void { + this.isSerializeFootEndNote = "Footnote"; this.endNoteFootnote = footNote; const owner: any = this.blockOwner; this.blockOwner = footNote; @@ -1762,6 +1780,7 @@ export class WordExport { writer.writeEndElement(); this.blockOwner = owner; this.endNoteFootnote = undefined; + this.isSerializeFootEndNote = undefined; } // private footnoteXMLItem(fileIndex: number): any { // let writer = new XmlWriter; @@ -2441,7 +2460,7 @@ export class WordExport { const isString: RegExpMatchArray = categoryName.match(/[a-z]/i); if (isNullOrUndefined(isString) && format === 'm/d/yyyy') { type = 's'; - } else if ((!isString && !isNullOrUndefined(isString)) || isScatterType) { + } else if (!isString || isScatterType) { type = 'n'; } else { type = 's'; @@ -2466,7 +2485,7 @@ export class WordExport { writer.writeStartElement(undefined, 'v', undefined); if (row === 0 && column === 0 && !isScatterType) { writer.writeString(this.chartStringCount.toString()); - } else if (type === 's') { + } else if (type === 's' && count < this.chartStringCount) { writer.writeString(count.toString()); count++; } else if (row !== 0 && type !== 's' && column === 0 && column !== (bubbleLength)) { @@ -3351,7 +3370,7 @@ export class WordExport { writer.writeAttributeString(undefined, 'cap', undefined, 'rnd'); } if (chartType !== 'lineChart') { - this.serializeChartSolidFill(writer, data[fillProperty[this.keywordIndex]][foreColorProperty[this.keywordIndex]], true); + this.serializeChartSolidFill(writer, this.getColor(data[fillProperty[this.keywordIndex]][rgbProperty[this.keywordIndex]]), true); } else { this.serializeChartSolidFill(writer, data[lineProperty[this.keywordIndex]][colorProperty[this.keywordIndex]], true); } @@ -4635,18 +4654,19 @@ export class WordExport { let bottom: string = Math.round(table[positioningProperty[this.keywordIndex]][distanceBottomProperty[this.keywordIndex]] * this.twipsInOnePoint).toString(); writer.writeAttributeString('w', 'bottomFromText', this.wNamespace, bottom); } - if (table[positioningProperty[this.keywordIndex]][verticalOriginProperty[this.keywordIndex]]) { + if (!isNullOrUndefined(table[positioningProperty[this.keywordIndex]][verticalOriginProperty[this.keywordIndex]])) { let verticalOrigin: string = table[positioningProperty[this.keywordIndex]][verticalOriginProperty[this.keywordIndex]] === (this.keywordIndex == 1 ? 0 : 'Paragraph') ? 'text' : this.getTableVerticalRelation(table[positioningProperty[this.keywordIndex]][verticalOriginProperty[this.keywordIndex]]).toLowerCase(); writer.writeAttributeString('w', 'vertAnchor', this.wNamespace, verticalOrigin); } - if (table[positioningProperty[this.keywordIndex]][horizontalOriginProperty[this.keywordIndex]] && table[positioningProperty[this.keywordIndex]][horizontalOriginProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'Column')) { - writer.writeAttributeString('w', 'horzAnchor', this.wNamespace, this.getTableHorizontalRelation(table[positioningProperty[this.keywordIndex]][horizontalOriginProperty[this.keywordIndex]]).toLowerCase()); + if (!isNullOrUndefined(table[positioningProperty[this.keywordIndex]][horizontalOriginProperty[this.keywordIndex]]) && table[positioningProperty[this.keywordIndex]][horizontalOriginProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'Column')) { + let horizontalOrigin: string = this.keywordIndex == 1 ? this.getTableHorizontalRelation(table[positioningProperty[this.keywordIndex]][horizontalOriginProperty[this.keywordIndex]]).toLowerCase() : table[positioningProperty[this.keywordIndex]][horizontalOriginProperty[this.keywordIndex]].toLowerCase(); + writer.writeAttributeString('w', 'horzAnchor', this.wNamespace, horizontalOrigin); } - if (table[positioningProperty[this.keywordIndex]][horizontalAlignmentProperty[this.keywordIndex]] && table[positioningProperty[this.keywordIndex]][horizontalAlignmentProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'Left')) { + if (!isNullOrUndefined(table[positioningProperty[this.keywordIndex]][horizontalAlignmentProperty[this.keywordIndex]]) && table[positioningProperty[this.keywordIndex]][horizontalAlignmentProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'Left')) { let horizontalAlignment: string = this.keywordIndex == 1 ? this.getTableHorizontalAlignment(table[positioningProperty[this.keywordIndex]][horizontalAlignmentProperty[this.keywordIndex]]) : table[positioningProperty[this.keywordIndex]][horizontalAlignmentProperty[this.keywordIndex]].toLowerCase(); writer.writeAttributeString('w', 'tblpXSpec', this.wNamespace, horizontalAlignment); } - if (table[positioningProperty[this.keywordIndex]][verticalAlignmentProperty[this.keywordIndex]] && table[positioningProperty[this.keywordIndex]][verticalAlignmentProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'None')) { + if (!isNullOrUndefined(table[positioningProperty[this.keywordIndex]][verticalAlignmentProperty[this.keywordIndex]]) && table[positioningProperty[this.keywordIndex]][verticalAlignmentProperty[this.keywordIndex]] !== (this.keywordIndex == 1 ? 0 : 'None')) { let verticalAlignment: string = this.keywordIndex == 1 ? this.getTableVerticalAlignment(table[positioningProperty[this.keywordIndex]][verticalAlignmentProperty[this.keywordIndex]]) : table[positioningProperty[this.keywordIndex]][verticalAlignmentProperty[this.keywordIndex]].toLowerCase(); writer.writeAttributeString('w', 'tblpYSpec', this.wNamespace, verticalAlignment); } @@ -5147,7 +5167,7 @@ export class WordExport { writer.writeAttributeString(undefined, 'val', this.wNamespace, formFieldData[textInputProperty[this.keywordIndex]][defaultValueProperty[this.keywordIndex]]); writer.writeEndElement(); writer.writeStartElement(undefined, 'format', this.wNamespace); - writer.writeAttributeString(undefined, 'val', this.wNamespace, this.keywordIndex == 1 ? this.getTextFormFieldFormat(formFieldData[textInputProperty[this.keywordIndex]][formatProperty[this.keywordIndex]]) : formFieldData[textInputProperty[this.keywordIndex]][formatProperty[this.keywordIndex]]); + writer.writeAttributeString(undefined, 'val', this.wNamespace, this.keywordIndex == 1 && type === 'Text' ? this.getTextFormFieldFormat(formFieldData[textInputProperty[this.keywordIndex]][formatProperty[this.keywordIndex]]) : formFieldData[textInputProperty[this.keywordIndex]][formatProperty[this.keywordIndex]]); writer.writeEndElement(); writer.writeEndElement(); } else if (formFieldData.hasOwnProperty(checkBoxProperty[this.keywordIndex])) { @@ -5206,6 +5226,11 @@ export class WordExport { writer.writeElementString(undefined, 'tab', this.wNamespace, undefined); } else if (span[textProperty[this.keywordIndex]] === '\v') { writer.writeElementString(undefined, 'br', this.wNamespace, undefined); + } else if (!isNullOrUndefined(span[breakClearTypeProperty[this.keywordIndex]])) { + writer.writeStartElement(undefined, 'br', this.wNamespace); + writer.writeAttributeString('w', 'type', this.wNamespace, "textWrapping"); + writer.writeAttributeString('w', 'clear', this.wNamespace, this.getBreakClearType(span[breakClearTypeProperty[this.keywordIndex]]).toString().toLowerCase()); + writer.writeEndElement(); } else if (span[textProperty[this.keywordIndex]] === '\f') { writer.writeStartElement(undefined, 'br', this.wNamespace); writer.writeAttributeString('w', 'type', this.wNamespace, 'page'); @@ -5634,6 +5659,20 @@ export class WordExport { return 'None'; } } + private getBreakClearType(breakClearType: number | BreakClearType): BreakClearType { + switch (breakClearType) { + case 0: + return 'None'; + case 1: + return 'Left'; + case 2: + return 'Right'; + case 3: + return 'All'; + default: + return breakClearType as BreakClearType; + } + } // // Seraializes the pargraph list format // private serializeListParagraph(writer: XmlWriter, paragraph: any): void { // if (!isNullOrUndefined(paragraph.paragraphFormat.listFormat)) { @@ -5688,9 +5727,10 @@ export class WordExport { if (!isNullOrUndefined(lf[listIdProperty[this.keywordIndex]])) { writer.writeStartElement(undefined, 'numId', this.wNamespace); let listId = (lf[listIdProperty[this.keywordIndex]] + 1).toString() - if (lf[listIdProperty[this.keywordIndex]] === -1) { - listId = ''; - } + // When attempting to open the exported document in tika server, the empty listId value is having trouble.So commented this below lines + // if (lf[listIdProperty[this.keywordIndex]] === -1) { + // listId = ''; + // } writer.writeAttributeString('w', 'val', this.wNamespace, listId); writer.writeEndElement(); } @@ -6040,7 +6080,7 @@ export class WordExport { writer.writeStartElement(undefined, 'rFonts', this.wNamespace); if (!isNullOrUndefined(characterFormat[fontFamilyAsciiProperty[this.keywordIndex]])) { let key: string = HelperMethods.isThemeFont(characterFormat[fontFamilyAsciiProperty[this.keywordIndex]]) ? 'asciiTheme' : 'ascii'; - writer.writeAttributeString(undefined, key, this.wNamespace, characterFormat[fontFamilyProperty[this.keywordIndex]]); + writer.writeAttributeString(undefined, key, this.wNamespace, characterFormat[fontFamilyAsciiProperty[this.keywordIndex]]); } if (!isNullOrUndefined(characterFormat[fontFamilyFarEastProperty[this.keywordIndex]])) { let key: string = HelperMethods.isThemeFont(characterFormat[fontFamilyFarEastProperty[this.keywordIndex]]) ? 'eastAsiaTheme' : 'eastAsia'; @@ -6110,6 +6150,16 @@ export class WordExport { writer.writeAttributeString('w', 'val', this.wNamespace, this.roundToTwoDecimal(characterFormat[fontSizeProperty[this.keywordIndex]] * 2).toString()); writer.writeEndElement(); } + if (!isNullOrUndefined(characterFormat[characterSpacingProperty[this.keywordIndex]])) { + writer.writeStartElement(undefined, 'spacing', this.wNamespace); + writer.writeAttributeString('w', 'val', this.wNamespace, (characterFormat[characterSpacingProperty[this.keywordIndex]] * 20).toString()); + writer.writeEndElement(); + } + if (!isNullOrUndefined(characterFormat[scalingProperty[this.keywordIndex]])) { + writer.writeStartElement(undefined, 'w', this.wNamespace); + writer.writeAttributeString('w', 'val', this.wNamespace, (characterFormat[scalingProperty[this.keywordIndex]]).toString()); + writer.writeEndElement(); + } if (!isNullOrUndefined(characterFormat[fontSizeBidiProperty[this.keywordIndex]])) { writer.writeStartElement(undefined, 'szCs', this.wNamespace); writer.writeAttributeString('w', 'val', this.wNamespace, this.roundToTwoDecimal(characterFormat[fontSizeBidiProperty[this.keywordIndex]] * 2).toString()); @@ -6928,7 +6978,7 @@ export class WordExport { let mImage: any = images.get(keys[i]); let imageStringInfo: ImageStringInfo = this.getBase64ImageString(mImage); base64ImageString = imageStringInfo.imageString; - if (HelperMethods.parseBoolValue(mImage.isMetaFile)) { + if (HelperMethods.parseBoolValue(mImage[isMetaFileProperty[this.keywordIndex]])) { let format: string = HelperMethods.formatClippedString(imageStringInfo.metaFileImageString).extension; if (format !== '.svg' || isSvg) { base64ImageString = imageStringInfo.metaFileImageString; diff --git a/controls/documenteditor/styles/document-editor-container/_bootstrap-dark-definition.scss b/controls/documenteditor/styles/document-editor-container/_bootstrap-dark-definition.scss index 830f8c6c21..1185f5857d 100644 --- a/controls/documenteditor/styles/document-editor-container/_bootstrap-dark-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_bootstrap-dark-definition.scss @@ -125,6 +125,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $de-white-color: #fff !default; $de-black-color: #000 !default; $de-hlt-clr-height: 18px; diff --git a/controls/documenteditor/styles/document-editor-container/_bootstrap-definition.scss b/controls/documenteditor/styles/document-editor-container/_bootstrap-definition.scss index 908bde660f..dc57a5279e 100644 --- a/controls/documenteditor/styles/document-editor-container/_bootstrap-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_bootstrap-definition.scss @@ -125,6 +125,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $de-white-color: #fff !default; $de-black-color: #000 !default; $de-hlt-clr-height: 18px; diff --git a/controls/documenteditor/styles/document-editor-container/_bootstrap4-definition.scss b/controls/documenteditor/styles/document-editor-container/_bootstrap4-definition.scss index 0c99f4f703..82b8f1aca4 100644 --- a/controls/documenteditor/styles/document-editor-container/_bootstrap4-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_bootstrap4-definition.scss @@ -142,6 +142,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $de-white-color: #fff !default; $de-black-color: #000 !default; $de-hlt-clr-height: 18px; diff --git a/controls/documenteditor/styles/document-editor-container/_bootstrap5-definition.scss b/controls/documenteditor/styles/document-editor-container/_bootstrap5-definition.scss index b3e1128abb..1c95a4dac6 100644 --- a/controls/documenteditor/styles/document-editor-container/_bootstrap5-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_bootstrap5-definition.scss @@ -101,6 +101,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $text-base; $de-status-br-lbl-fnt-weight: $font-weight-medium; $de-status-br-left: 0 !default; $de-status-br-top: 6px !default; +$de-status-br-top-big: 6px !default; $e-de-btn-font-size: $text-sm; $e-de-btn-font-icon-size: 16px; $e-de-btn-font-size-big: $text-base; diff --git a/controls/documenteditor/styles/document-editor-container/_fabric-dark-definition.scss b/controls/documenteditor/styles/document-editor-container/_fabric-dark-definition.scss index a7518fe1ab..c8b826970b 100644 --- a/controls/documenteditor/styles/document-editor-container/_fabric-dark-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_fabric-dark-definition.scss @@ -130,6 +130,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $de-white-color: #fff !default; $de-black-color: #000 !default; $de-hlt-clr-height: 18px; diff --git a/controls/documenteditor/styles/document-editor-container/_fabric-definition.scss b/controls/documenteditor/styles/document-editor-container/_fabric-definition.scss index ef42a2a55d..838edb8079 100644 --- a/controls/documenteditor/styles/document-editor-container/_fabric-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_fabric-definition.scss @@ -127,6 +127,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $de-white-color: #fff !default; $de-black-color: #000 !default; $de-hlt-clr-height: 18px; diff --git a/controls/documenteditor/styles/document-editor-container/_fluent-definition.scss b/controls/documenteditor/styles/document-editor-container/_fluent-definition.scss index 62fa4693fc..a62a41ba91 100644 --- a/controls/documenteditor/styles/document-editor-container/_fluent-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_fluent-definition.scss @@ -102,6 +102,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $text-base; $de-status-br-lbl-fnt-weight: $font-weight-medium; $de-status-br-left: 0 !default; $de-status-br-top: 6px !default; +$de-status-br-top-big: 6px !default; $e-de-btn-font-size: $text-sm; $e-de-btn-font-icon-size: 16px; $e-de-btn-font-size-big: $text-base; diff --git a/controls/documenteditor/styles/document-editor-container/_fusionnew-definition.scss b/controls/documenteditor/styles/document-editor-container/_fusionnew-definition.scss index 0f5166396c..fbd122172b 100644 --- a/controls/documenteditor/styles/document-editor-container/_fusionnew-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_fusionnew-definition.scss @@ -101,6 +101,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $text-base; $de-status-br-lbl-fnt-weight: $font-weight-medium; $de-status-br-left: 0 !default; $de-status-br-top: 6px !default; +$de-status-br-top-big: 6px !default; $e-de-btn-font-size: $text-sm; $e-de-btn-font-icon-size: 16px; $e-de-btn-font-size-big: 16px; diff --git a/controls/documenteditor/styles/document-editor-container/_highcontrast-definition.scss b/controls/documenteditor/styles/document-editor-container/_highcontrast-definition.scss index 2bdb013975..ac5d784ae6 100644 --- a/controls/documenteditor/styles/document-editor-container/_highcontrast-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_highcontrast-definition.scss @@ -128,6 +128,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $de-white-color: #fff !default; $de-black-color: #000 !default; $de-hlt-clr-height: 18px; diff --git a/controls/documenteditor/styles/document-editor-container/_highcontrast-light-definition.scss b/controls/documenteditor/styles/document-editor-container/_highcontrast-light-definition.scss index d98cfa2454..e6f1f579a4 100644 --- a/controls/documenteditor/styles/document-editor-container/_highcontrast-light-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_highcontrast-light-definition.scss @@ -117,6 +117,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $e-de-bzr-btn-font-size: 16px; $e-de-bzr-btn-font-size-big: 16px; $de-white-color: #fff !default; diff --git a/controls/documenteditor/styles/document-editor-container/_material-dark-definition.scss b/controls/documenteditor/styles/document-editor-container/_material-dark-definition.scss index 48120a6313..92dead573a 100644 --- a/controls/documenteditor/styles/document-editor-container/_material-dark-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_material-dark-definition.scss @@ -4,7 +4,7 @@ $de-ctnr-bg-clr: $grey-dark !default; $de-ctnr-prop-bg-clr: $de-ctnr-bg-clr !default; $de-ctnr-height: calc(100%) !default; $de-ctnr-tlbr-height: 77px !default; -$de-ctnr-tlbt-height-big: 82px !default; +$de-ctnr-tlbt-height-big: 90px !default; $de-tlbr-margin-first: 12px !default; $de-tlbr-margin-first-big: 16px !default; $de-tlbr-margin-right: 6px !default; @@ -118,6 +118,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $e-de-bzr-btn-font-size: 14px; $e-de-bzr-btn-font-size-big: 16px; $de-white-color: #fff !default; diff --git a/controls/documenteditor/styles/document-editor-container/_material-definition.scss b/controls/documenteditor/styles/document-editor-container/_material-definition.scss index ad7bcb7ce2..9d6905549f 100644 --- a/controls/documenteditor/styles/document-editor-container/_material-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_material-definition.scss @@ -118,6 +118,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $de-ctnr-pg-no-spellout-fnt-size; $de-status-br-lbl-fnt-weight: normal; $de-status-br-left: 15.5 !default; $de-status-br-top: 10px !default; +$de-status-br-top-big: 10px !default; $de-white-color: #fff !default; $de-black-color: #000 !default; $de-hlt-clr-height: 18px; diff --git a/controls/documenteditor/styles/document-editor-container/_tailwind-definition.scss b/controls/documenteditor/styles/document-editor-container/_tailwind-definition.scss index 0682bfdabc..74e35055b6 100644 --- a/controls/documenteditor/styles/document-editor-container/_tailwind-definition.scss +++ b/controls/documenteditor/styles/document-editor-container/_tailwind-definition.scss @@ -107,6 +107,7 @@ $de-ctnr-pg-no-spellout-fnt-size-bg: $text-base; $de-status-br-lbl-fnt-weight: $font-weight-medium; $de-status-br-left: 0 !default; $de-status-br-top: 6px !default; +$de-status-br-top-big: 6px !default; $e-de-bzr-button-hover-border-radius: 4px; $e-de-bzr-button-hover-border: none; $de-clr-pckr-width: 43px; diff --git a/controls/documenteditor/styles/document-editor-container/_theme.scss b/controls/documenteditor/styles/document-editor-container/_theme.scss index 5e807d24b3..4f26dd8574 100644 --- a/controls/documenteditor/styles/document-editor-container/_theme.scss +++ b/controls/documenteditor/styles/document-editor-container/_theme.scss @@ -3,6 +3,115 @@ .e-de-toolbar { height: 100%; } + .e-de-prop-pane .e-de-ctnr-group-btn.e-btn-group:not(.e-outline){ + box-shadow: none; + height: $de-group-btn-hgt; + #{if(&, '&', '*')}:focus { + box-shadow: none; + } + #{if(&, '&', '*')}:active { + box-shadow: none; + } + #{if(&, '&', '*')}:hover { + box-shadow: none; + } + } + .e-de-ctnr-group-btn-middle button { + border-radius: 0px; + } + @if ($skin-name=='Material3') { + .e-de-review-pane button.e-de-close-icon { + background: transparent; + box-shadow: none; + } + .e-de-op-more-less > div:last-child label { + left: 35px; + } + .e-bigger .e-de-ctn .e-de-bzr-button { + line-height: 17px; + padding-top: 12px; + } + .e-de-ctn .e-de-bzr-button { + box-shadow: none !important; + } + .e-bigger .e-de-ctn .e-de-bzr-button { + box-shadow: none !important; + } + .e-de-char-fmt-btn-left button:not(:first-child) { + border: 1px solid transparent; + border-left: 1px solid rgba($border-light); + } + .e-de-ctnr-group-btn { + .e-de-prop-font-button { + position: relative; + border: 1px solid transparent rgba($border-light); + border-right-width: 1px; + } + .e-de-prop-font-last-button { + position: relative; + border: 1px solid transparent rgba($border-light); + border-left-width: 1px; + } + } + .e-de-ctnr-group-btn { + .e-de-prop-indent-button { + position: relative; + border: 1px solid transparent rgba($border-light); + border-right-width: 1px; + } + .e-de-prop-indent-last-button { + position: relative; + border: 1px solid transparent rgba($border-light); + border-left-width: 1px; + } + } + .e-de-grp-btn-ctnr { + .e-de-ctnr-group-btn-middle { + > * { + border-radius: 0px; + } + margin-bottom: -1px; + } + } + .e-bigger { + .e-de-grp-btn-ctnr { + .e-de-ctnr-group-btn-middle { + > * { + border-radius: 0px; + } + } + .e-de-ctnr-group-btn-top { + > * { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + } + } + .e-de-ctnr-group-btn-bottom { + > * { + border-top-left-radius: 0px; + border-top-right-radius: 0px; + } + } + } + } + } + .de-tbl-fill-clr .e-dropdown-btn.e-btn { + box-shadow: none; + } + .e-de-prop-pane .e-de-ctnr-group-btn button, + .e-de-ctn .e-de-status-bar button { + box-shadow: none; + height: $de-group-btn-hgt; + #{if(&, '&', '*')}:focus { + box-shadow: none; + } + #{if(&, '&', '*')}:active { + box-shadow: none; + } + #{if(&, '&', '*')}:hover { + box-shadow: none; + } + } .e-de-statusbar-pageweb { background: $de-ctnr-bg-clr; border: 0; @@ -25,6 +134,14 @@ box-shadow: none; } } + + .e-split-btn-wrapper.e-de-prop-splitbutton, + .e-split-btn-wrapper.e-de-btn-hghlclr, + .e-btn.de-split-button { + @if $skin-name=='Material3' { + box-shadow: none; + } + } .e-de-statusbar-pageweb .e-de-printlayout, .e-de-statusbar-pageweb .e-de-weblayout { font-size: $e-de-bzr-btn-font-size; @@ -56,7 +173,10 @@ margin-right: $e-de-ctnr-break-listview-margin-right; } .e-de-listview-icon { + height: auto; + width: auto; line-height: 22px; + margin-right: $e-de-ctnr-break-listview-margin-right; } .e-de-linespacing { margin-top: $e-de-ctnr-linespacing-tick-icon; @@ -79,6 +199,18 @@ } @if $skin-name=='Material3' { + .e-de-prop-pane .e-de-ctnr-group-btn.e-btn-group button { + background: $de-prop-btn-bg-color; + } + .e-de-font-clr-picker button, .e-de-prop-font-colorpicker button { + background: $de-prop-btn-bg-color !important; + } + .e-de-style-font-color-picker .e-de-style-icon-button-size button:first-child { + margin-right: 0px; + } + .e-de-ctnr-group-btn .e-btn-group button, + .e-documenteditorcontainer.e-lib .e-split-btn-wrapper button, + .e-documenteditorcontainer.e-lib .e-colorpicker-wrapper .e-split-btn-wrapper .e-split-colorpicker.e-split-btn, .e-de-ctnr-segment button, .e-de-char-fmt-btn-right button, .e-de-border-size-button, @@ -86,26 +218,55 @@ .e-de-insert-del-cell button, .e-de-align-text button { border-radius: 4px; - //background: $de-prop-btn-bg-color; + background: $de-prop-btn-bg-color; } .e-de-char-fmt-btn-right button:not(:first-child), - .e-de-char-fmt-btn-left button:not(:first-child), - .e-de-insert-del-cell button:not(:first-child), + .e-de-char-fmt-btn-left button:not(:first-child), .e-de-align-text button:not(:first-child) { - border-left: 1.7px solid $border-light; + border-left: 1.7px solid rgba($border-light); + background: $de-prop-btn-bg-color; + } + .e-de-insert-del-cell button:not(:first-child) { + &:not(.e-rtl) { + border-left: 1.7px solid rgba($border-light); + } + } + .e-de-ctnr-segment-rtl { + .e-de-char-fmt-btn-left, + .e-de-char-fmt-btn-right { + .e-de-prop-font-last-button, + .e-de-prop-indent-last-button { + border-left: 0; + } + } } - .e-rtl { .e-de-char-fmt-btn-right button:not(:last-child), .e-de-char-fmt-btn-left button:not(:last-child), .e-de-insert-del-cell button:not(:last-child), .e-de-align-text button:not(:last-child) { - border-right: 1.7px solid $border-light; + border-right: 1.7px solid rgba($border-light); + background: $de-prop-btn-bg-color; } } - .e-de-grp-btn-ctnr button { - //background: $de-prop-btn-bg-color; - border: 1px solid $border-light; + + .e-de-char-fmt-btn-right.e-rtl button:not(:first-child), + .e-de-char-fmt-btn-left.e-rtl button:not(:first-child), + .e-de-insert-del-cell .e-rtl button:not(:first-child), + .e-de-align-text .e-rtl button:not(:first-child) + { + border-right: 1px solid rgba($border-light) !important; + } + .e-de-grp-btn-ctnr { + .e-de-ctnr-group-btn { + .e-de-prop-font-button { + background: $de-prop-btn-bg-color; + border: 1px solid rgba($border-light) !important; + } + } + .e-de-ctnr-group-btn-top { + margin-bottom: -1px; + } } .e-de-font-clr-picker > *, .de-split-button>div:first-child { @@ -115,7 +276,12 @@ .e-de-pagenumber-input { background: $e-de-pagenumber-bg; - border: 1px solid $de-panel-border; + @if $skin-name =='Material3'{ + border: none !important; + } + @else { + border: 1px solid $de-panel-border; + } border-radius: $de-pagenumber-text-border-radius; color: $de-font-color; @if $skin-name=='bootstrap5' or $skin-name=='tailwind' or $skin-name =='FluentUI' { @@ -158,7 +324,7 @@ background-color: $de-title-bar-bg-clr; border-bottom: none !important; color: $de-title-bar-font-clr; - @if $skin-name=='tailwind' or $skin-name == 'bootstrap5' or $skin-name == 'FluentUI' { + @if $skin-name=='tailwind' or $skin-name == 'bootstrap5' or $skin-name =='FluentUI' or $skin-name =='Material3' { font-size: $e-de-btn-font-size !important; button { font-size: $e-de-btn-font-size !important; @@ -172,7 +338,7 @@ } } } - @if $skin-name=='tailwind' or $skin-name == 'bootstrap5' or $skin-name =='FluentUI' { + @if $skin-name=='tailwind' or $skin-name == 'bootstrap5' or $skin-name =='FluentUI' or $skin-name =='Material3' { .e-bigger { .e-de-ctn-title { font-size: $e-de-btn-font-size-big !important; @@ -203,13 +369,25 @@ .e-de-statusbar-separator { border-left: 1px solid $e-de-statusbar-separator-color; height: 16px; - margin-left: $de-status-br-left; + margin-left: $de-spellcheck-tlbr-margin-left; + margin-right: $de-spellcheck-tlbr-margin-left; margin-top: $de-status-br-top; } + .e-bigger .e-de-statusbar-separator { + border-left: 1px solid $e-de-statusbar-separator-color; + @if $skin-name == 'Material3' { + height: 20px; + } @else { + height: 16px; + } + margin-left: $de-spellcheck-tlbr-margin-left; + margin-right: $de-spellcheck-tlbr-margin-left; + margin-top: $de-status-br-top-big; + } .e-de-statusbar-spellcheck { border-radius: 2px; font-weight: 400; - margin-left: $de-spellcheck-tlbr-margin-left; + @if $skin-name == 'Material3' { background: $de-ctnr-bg-clr; } @@ -223,12 +401,14 @@ } .e-bigger .e-de-statusbar-spellcheck { border-radius: 2px; - margin-left: $de-spellcheck-tlbr-margin-left; } .e-de-ctnr-toolbar { display: flex; height: $de-ctnr-tlbr-height; width: 100%; + @if $skin-name == 'Material3' { + background: $de-toolbar-background-color; + } } .e-de-tlbr-wrapper .e-de-toolbar.e-toolbar, .e-de-tlbr-wrapper .e-de-ctnr-properties-pane-btn { @@ -236,9 +416,15 @@ } .e-de-pane { border-left: 1px solid $de-panel-border; + @if $skin-name == 'Material3' { + background: $de-pane-background-color; + } } .e-de-pane-rtl { border-right: 1px solid $de-panel-border; + @if $skin-name == 'Material3' { + background: $de-pane-background-color; + } } @if $skin-name=='material' { .e-de-pane>div button:not(.e-primary), @@ -709,6 +895,11 @@ .e-de-toolbar.e-toolbar .e-toolbar-items .e-toolbar-item:not(.e-separator) { padding: $de-ctrnr-tblr-item-padding; } + .e-de-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn-text .e-de-text-wrap { + @if $skin-name =='Material3' { + line-height: 0.8; + } + } .e-de-toolbar.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn-text { display: table; font-size: $de-toolbar-font-size; @@ -737,6 +928,7 @@ width: $de-text-pane-width; } .e-de-review-pane { + background: $de-ctnr-prop-bg-clr; border-left: 1px solid $de-op-border-clr; height: 100%; min-height: 200px; @@ -781,32 +973,6 @@ } } } - .e-de-ctnr-group-btn.e-btn-group:not(.e-outline) { - box-shadow: none; - height: $de-group-btn-hgt; - #{if(&, '&', '*')}:focus { - box-shadow: none; - } - #{if(&, '&', '*')}:active { - box-shadow: none; - } - #{if(&, '&', '*')}:hover { - box-shadow: none; - } - } - .e-de-ctnr-group-btn button { - box-shadow: none; - height: $de-group-btn-hgt; - #{if(&, '&', '*')}:focus { - box-shadow: none; - } - #{if(&, '&', '*')}:active { - box-shadow: none; - } - #{if(&, '&', '*')}:hover { - box-shadow: none; - } - } .e-de-property-div-padding { @if $skin-name=='Material3' { border-bottom: 1px solid $de-pane-separator; @@ -941,7 +1107,7 @@ font-size: 42px; } .e-de-list-header-presetmenu .e-de-list-line { - border-bottom: 1px solid $de-prop-btn-icon-clr; + border-bottom: 1px solid $de-prop-btn-icon-clr !important; margin-left: 5px; width: 100%; } @@ -1005,11 +1171,11 @@ @if $skin-name !='tailwind' { .e-de-list-container { @if $skin-name !='Material3' { - background: $de-ctnr-bg-clr; border: 1px solid #ccc; border-radius: 2px; box-shadow: 0 0 14px rgba(0, 0, 0, 0.2); } + background: $de-ctnr-bg-clr; box-sizing: border-box; display: inline-block; line-height: normal; @@ -1204,7 +1370,9 @@ background: $de-ctnr-bg-clr; //border-bottom: 1px solid $de-panel-border; display: flex; - padding-top: $e-de-status-bar-padding-top; + @if $skin-name !='Material3' { + padding-top: $e-de-status-bar-padding-top; + } width: 100%; } .e-de-ctnr-pg-no { @@ -1239,7 +1407,12 @@ width: $de-page-no-width-spellout-big; } .e-de-statusbar-zoom-spell { - background-color: $de-ctnr-bg-clr; + @if $skin-name =='Material3' { + background: $de-ctnr-bg-clr; + } + @else { + background-color: $de-ctnr-bg-clr; + } border: 0; color: $de-font-color; float: right; @@ -1247,7 +1420,12 @@ margin-left: $de-zoom-tlbr-margin-left; } .e-bigger .e-de-statusbar-zoom-spell { - background-color: $de-ctnr-bg-clr; + @if $skin-name =='Material3' { + background: $de-ctnr-bg-clr; + } + @else { + background-color: $de-ctnr-bg-clr; + } border: 0; color: $de-font-color; float: right; @@ -1359,7 +1537,7 @@ } .e-de-grp-btn-ctnr .e-de-ctnr-group-btn { - height: 38px !important; + height: 36px !important; } .e-bigger .e-de-grp-btn-ctnr .e-de-ctnr-group-btn { height: 42px !important; @@ -1391,6 +1569,11 @@ width: 70px; } } + .e-documenteditor-optionspane { + @if $skin-name=='Material3' { + background: $de-background-color; + } + } @if $skin-name=='tailwind' { .e-de-prop-fill-label { font-size: 16px; @@ -1410,7 +1593,10 @@ margin-left: $e-de-ctnr-break-listview-margin-left; } .e-de-listview-icon { + height: auto; + width: auto; line-height: 22px; + margin-left: $e-de-ctnr-break-listview-margin-left; } } .e-bigger { @@ -1583,7 +1769,6 @@ .e-de-toolbar.e-toolbar .e-toolbar-items { height: $de-ctnr-tlbt-height-big; .e-toolbar-item.e-de-separator { - height: 25px; margin: $de-ctrnr-tblr-separator-margin-big; } .e-toolbar-item.e-de-toolbar-btn-start { @@ -1710,6 +1895,9 @@ @if $skin-name=='material' { font-size: 13px; } + @if $skin-name=='material3' { + font-size: $text-base; + } @else if $skin-name=='tailwind' { font-size: 14px; line-height: 1.5; @@ -1747,6 +1935,24 @@ box-shadow: none; } } + .e-de-status-bar button + { + @if $skin-name=='Material3' { + height: $de-status-btn-hgt-big; + } @else { + height: $de-group-btn-hgt-big; + } + box-shadow: none; + #{if(&, '&', '*')}:focus { + box-shadow: none; + } + #{if(&, '&', '*')}:active { + box-shadow: none; + } + #{if(&, '&', '*')}:hover { + box-shadow: none; + } + } .e-de-ctnr-group-btn button { box-shadow: none; height: $de-group-btn-hgt-big; @@ -1894,22 +2100,25 @@ margin-left: 10px; } .e-de-status-bar { - background-color: $de-ctnr-bg-clr; + background: $de-ctnr-bg-clr; //border-bottom: 1px solid $de-panel-border; display: flex; - padding-top: $e-de-status-bar-big-padding-top; + @if $skin-name !='Material3' { + padding-top: $e-de-status-bar-big-padding-top; + } width: 100%; } .e-de-statusbar-zoom { - background-color: $de-ctnr-bg-clr; border: 0; color: $de-font-color; float: right; @if $skin-name =='Material3' { height: 40px; + background: $de-ctnr-bg-clr; } @else { height: 34px; + background-color: $de-ctnr-bg-clr; } } @if $skin-name !='tailwind' { @@ -1932,6 +2141,9 @@ @else { line-height: 0; } + @if $skin-name =='Material3' { + line-height: 0.8; + } } } .e-listview .e-list-icon { @@ -1940,7 +2152,10 @@ margin-right: $e-de-ctnr-break-listview-margin-right-big; } .e-de-listview-icon { + height: auto; + width: auto; line-height: 22px; + margin-right: $e-de-ctnr-break-listview-margin-right-big; } .e-rtl { .e-listview .e-list-icon { @@ -1949,7 +2164,10 @@ margin-left: $e-de-ctnr-break-listview-margin-left-big; } .e-de-listview-icon { + height: auto; + width: auto; line-height: 22px; + margin-left: $e-de-ctnr-break-listview-margin-left-big; } } } @@ -2059,7 +2277,8 @@ } @if $skin-name =='Material3' { height: calc(100% - 10px); - line-height: 23px; + line-height: 16px; + font-size: $de-toolbar-font-size !important; } @if $skin-name=='bootstrap4' or $skin-name=='bootstrap' { border: 1px solid $e-de-bzr-button-border-color; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap-dark.scss b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap-dark.scss index 330d2ae062..f9137e4f33 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap-dark.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap-dark.scss @@ -400,6 +400,21 @@ font-family: 'e-icons'; } + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e98e'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e992'; + font-family: 'e-icons'; + } + .e-de-ctnr-columns::before { content: '\e955'; font-family: 'e-icons'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap.scss b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap.scss index 330d2ae062..f9137e4f33 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap.scss @@ -400,6 +400,21 @@ font-family: 'e-icons'; } + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e98e'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e992'; + font-family: 'e-icons'; + } + .e-de-ctnr-columns::before { content: '\e955'; font-family: 'e-icons'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap4.scss b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap4.scss index 8384676ea7..d26761cc3b 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap4.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap4.scss @@ -399,6 +399,21 @@ content: '\e720'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e720'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e97b'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e97c'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e955'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap5.scss b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap5.scss index b99d475104..cf2c321304 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_bootstrap5.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_bootstrap5.scss @@ -425,6 +425,21 @@ content: '\e844'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e844'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e8bf'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e8c0'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e8b4'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_fabric-dark.scss b/controls/documenteditor/styles/document-editor-container/icons/_fabric-dark.scss index 57e22e8dd8..257da19ce0 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_fabric-dark.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_fabric-dark.scss @@ -399,6 +399,21 @@ content: '\e353'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e982'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e983'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e972'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_fabric.scss b/controls/documenteditor/styles/document-editor-container/icons/_fabric.scss index 70b91c0abd..49219cd0f3 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_fabric.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_fabric.scss @@ -399,6 +399,21 @@ content: '\e353'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e982'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e983'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e972'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_fluent.scss b/controls/documenteditor/styles/document-editor-container/icons/_fluent.scss index 2c34075afb..cbc21d35b5 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_fluent.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_fluent.scss @@ -425,6 +425,21 @@ content: '\e844'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e844'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e8bf'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e8c0'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e8b4'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_fusionnew.scss b/controls/documenteditor/styles/document-editor-container/icons/_fusionnew.scss index 6ed7d45f22..339c16c02a 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_fusionnew.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_fusionnew.scss @@ -425,6 +425,21 @@ content: '\e844'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e844'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e8bf'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e8c0'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e89d'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_highcontrast-light.scss b/controls/documenteditor/styles/document-editor-container/icons/_highcontrast-light.scss index 6805690114..8c5d9512a2 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_highcontrast-light.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_highcontrast-light.scss @@ -399,6 +399,21 @@ content: '\e353'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e980'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e981'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e968'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_highcontrast.scss b/controls/documenteditor/styles/document-editor-container/icons/_highcontrast.scss index 67f846f380..920363f0a6 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_highcontrast.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_highcontrast.scss @@ -399,6 +399,21 @@ content: '\e353'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e980'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e981'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e968'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_material-dark.scss b/controls/documenteditor/styles/document-editor-container/icons/_material-dark.scss index b45a60197c..18f257121c 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_material-dark.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_material-dark.scss @@ -401,6 +401,21 @@ content: '\e353'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e97d'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e97e'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e955'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_material.scss b/controls/documenteditor/styles/document-editor-container/icons/_material.scss index 9b9526b9af..a847f1c7e8 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_material.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_material.scss @@ -401,6 +401,21 @@ content: '\e353'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e353'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e97d'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e97e'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e955'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_material3.scss b/controls/documenteditor/styles/document-editor-container/icons/_material3.scss index e19d8bb487..7537e85934 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_material3.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_material3.scss @@ -1,6 +1,6 @@ @include export-module('document-editor-container-material3-icons') { .e-de-ctnr-close::before { - color: $icon-color; + color: rgba($icon-color); content: '\e7e7'; font-size: 16px; } @@ -157,7 +157,7 @@ } .e-de-ctnr-borders::before { - content: '\e93b'; + content: '\e893'; } .e-de-ctnr-decreaseindent::before { @@ -166,7 +166,6 @@ .e-de-ctnr-showhide::before { content: '\e71a'; - font-size: 16px; } .e-de-ctnr-print::before { @@ -422,22 +421,37 @@ } .e-de-e-paragraph-mark::before{ - content: '\e353'; + content: '\e844'; + font-family: 'e-icons'; + } + + .e-de-e-paragraph-style-mark::before{ + content: '\e844'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e8bf'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e8c0'; font-family: 'e-icons'; } .e-de-ctnr-columns::before { - content: '\e955'; + content: '\e8b4'; font-family: 'e-icons'; } .e-de-ctnr-page-size::before { - content: '\e952'; + content: '\e89a'; font-family: 'e-icons'; } .e-de-ctnr-page-break-column::before { - content: '\e970'; + content: '\e8b4'; font-family: 'e-icons'; } @@ -447,46 +461,46 @@ } .e-de-ctnr-section-break-continuous::before { - content: '\e971'; + content: '\e8b5'; font-family: 'e-icons'; } .e-de-ctnr-section-break-even-page::before { - content: '\e96e'; + content: '\e8b2'; font-family: 'e-icons'; } .e-de-ctnr-section-break-odd-page::before { - content: '\e96f'; + content: '\e8b3'; font-family: 'e-icons'; } .e-de-ctnr-columns-one::before { - content: '\e976'; + content: '\e8b9'; font-family: 'e-icons'; font-size: $de-column-presets-font-size; } .e-de-ctnr-columns-two::before { - content: '\e978'; + content: '\e8ba'; font-family: 'e-icons'; font-size: $de-column-presets-font-size; } .e-de-ctnr-columns-three::before { - content: '\e979'; + content: '\e8bb'; font-family: 'e-icons'; font-size: $de-column-presets-font-size; } .e-de-ctnr-columns-right::before { - content: '\e973'; + content: '\e8b7'; font-family: 'e-icons'; font-size: $de-column-presets-font-size; } .e-de-ctnr-columns-left::before { - content: '\e975'; + content: '\e8b8'; font-family: 'e-icons'; font-size: $de-column-presets-font-size; } diff --git a/controls/documenteditor/styles/document-editor-container/icons/_tailwind-dark.scss b/controls/documenteditor/styles/document-editor-container/icons/_tailwind-dark.scss index d00a9e64aa..a1ad21b3ce 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_tailwind-dark.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_tailwind-dark.scss @@ -425,6 +425,21 @@ content: '\e844'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e844'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e8bf'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e8c0'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e89d'; diff --git a/controls/documenteditor/styles/document-editor-container/icons/_tailwind.scss b/controls/documenteditor/styles/document-editor-container/icons/_tailwind.scss index 2825785bed..79a6a514cd 100644 --- a/controls/documenteditor/styles/document-editor-container/icons/_tailwind.scss +++ b/controls/documenteditor/styles/document-editor-container/icons/_tailwind.scss @@ -425,6 +425,21 @@ content: '\e844'; font-family: 'e-icons'; } + + .e-de-e-paragraph-style-mark::before{ + content: '\e844'; + font-family: 'e-icons'; + } + + .e-de-e-character-style-mark::before{ + content: '\e8bf'; + font-family: 'e-icons'; + } + + .e-de-e-linked-style-mark::before{ + content: '\e8c0'; + font-family: 'e-icons'; + } .e-de-ctnr-columns::before { content: '\e89d'; diff --git a/controls/documenteditor/styles/document-editor/_theme.scss b/controls/documenteditor/styles/document-editor/_theme.scss index 3483923655..086bbbc854 100644 --- a/controls/documenteditor/styles/document-editor/_theme.scss +++ b/controls/documenteditor/styles/document-editor/_theme.scss @@ -903,6 +903,12 @@ .e-de-bookmark { margin-top: 0 !important; } + .e-de-bookmark .e-bookmark-textbox-input { + box-sizing: border-box !important; + } + .e-de-cp-option { + background: transparent; + } .e-styles-common { padding-top: $de-style-list-top; @@ -1740,6 +1746,23 @@ .e-de-hyperlink { width: $de-hyper-link-width; } + @if $skin-name =='Material3'{ + .e-de-table-border-shading-dlg { + .e-de-dlg-row .e-de-dlg-row label { + margin-left: 10px; + } + } + .e-de-table-setting-heading { + line-height: 22px; + letter-spacing: 0.30000001192092896px; + } + .e-de-rp-btn-enforce { + border-radius: 4px !important; + } + .e-de-track-toolbar .e-de-track-pane-drop-btn, #e-de-menu-option { + background: none; + } + } .e-bigger { .e-de-hyperlink { @if $skin-name=='Material3' { @@ -2133,7 +2156,43 @@ } } + .e-bigger .e-dlg-container .e-de-dlg-target .e-de-style-dialog { + .e-de-style-font-group-button, + .e-style-paragraph { + button { + @if $skin-name =='Material3' { + height: 40px !important; + width: 44px !important; + } + } + } + .e-de-style-font-color-picker button { + height: 40px !important; + width: auto !important; + } + } + @if $skin-name =='Material3' { + .e-bigger { + .e-rtl { + .e-de-style-font-group-button, + .e-de-style-paragraph-indent-group-button, + .e-de-style-paragraph-group-button { + button { + height: 40px !important; + width: 44px !important; + } + } + } + .e-de-style-font-group-button, + .e-de-style-paragraph-indent-group-button, + .e-de-style-paragraph-group-button { + button { + height: 40px !important; + width: 44px !important; + } + } + } .e-de-style-font-group-button button, .e-de-style-paragraph-indent-group-button button, .e-de-style-paragraph-group-button button { @@ -2145,7 +2204,7 @@ } .e-de-style-bold-button-size { margin-left: $de-style-dialog-label-bottom-margin; - @if $skin-name !='tailwind' and $skin-name !='bootstrap5' and $skin-name != 'FluentUI' and $skin-name != 'Material3' { + @if $skin-name !='tailwind' and $skin-name !='bootstrap5' and $skin-name != 'FluentUI' { margin-right: 8px; height: 31px; } @@ -2978,7 +3037,7 @@ padding-left: 0px; padding-right: 0px; @if $skin-name =='Material3' { - padding-top: 10px; + padding-top: 10px !important; } @else { padding-top: 5px; @@ -2986,6 +3045,11 @@ font-size: 13px; font-weight: $de-header-font-weight; } + @if ($skin-name =='fabric' or $skin-name =='bootstrap') { + .e-de-track-toolbar .e-de-track-pane-drop-btn { + padding-top: 4px !important; + } + } } .e-toolbar-item.e-de-track-toolbar-overlay.e-template.e-overlay { opacity: 1; @@ -3079,6 +3143,7 @@ } .e-de-cp-option.e-btn.e-icon-btn span { margin-top: 0px; + background: $de-op-bg-color; } .e-de-cmt-view:hover { .e-de-cp-option { @@ -3413,7 +3478,7 @@ } .e-de-table-setting-labels-heading { margin-left: 0; - margin-right: $de-table-alignment-label-margin-left; + margin-right: 10px; } } .e-bigger { diff --git a/controls/documenteditor/styles/document-editor/icons/_bootstrap-dark.scss b/controls/documenteditor/styles/document-editor/icons/_bootstrap-dark.scss index 76bb2d5650..7b861fa9c9 100644 --- a/controls/documenteditor/styles/document-editor/icons/_bootstrap-dark.scss +++ b/controls/documenteditor/styles/document-editor/icons/_bootstrap-dark.scss @@ -58,6 +58,7 @@ .e-de-multi-cmt-mark::before { content: '\e98a'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_bootstrap.scss b/controls/documenteditor/styles/document-editor/icons/_bootstrap.scss index 01e4e6b7b1..58bed0550e 100644 --- a/controls/documenteditor/styles/document-editor/icons/_bootstrap.scss +++ b/controls/documenteditor/styles/document-editor/icons/_bootstrap.scss @@ -58,6 +58,7 @@ .e-de-multi-cmt-mark::before { content: '\e98a'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_bootstrap4.scss b/controls/documenteditor/styles/document-editor/icons/_bootstrap4.scss index e68aa9d159..dcae1facc0 100644 --- a/controls/documenteditor/styles/document-editor/icons/_bootstrap4.scss +++ b/controls/documenteditor/styles/document-editor/icons/_bootstrap4.scss @@ -58,6 +58,7 @@ .e-de-multi-cmt-mark::before { content: '\e978'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_bootstrap5.scss b/controls/documenteditor/styles/document-editor/icons/_bootstrap5.scss index 13de131f41..893dc59cf7 100644 --- a/controls/documenteditor/styles/document-editor/icons/_bootstrap5.scss +++ b/controls/documenteditor/styles/document-editor/icons/_bootstrap5.scss @@ -58,6 +58,7 @@ color: $icon-color; content: '\e8bc'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_fabric-dark.scss b/controls/documenteditor/styles/document-editor/icons/_fabric-dark.scss index fdf2b7e609..11b7991a42 100644 --- a/controls/documenteditor/styles/document-editor/icons/_fabric-dark.scss +++ b/controls/documenteditor/styles/document-editor/icons/_fabric-dark.scss @@ -58,6 +58,7 @@ .e-de-multi-cmt-mark::before { content: '\e97e'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_fabric.scss b/controls/documenteditor/styles/document-editor/icons/_fabric.scss index 5cfa94e64e..8e40941382 100644 --- a/controls/documenteditor/styles/document-editor/icons/_fabric.scss +++ b/controls/documenteditor/styles/document-editor/icons/_fabric.scss @@ -58,6 +58,7 @@ .e-de-multi-cmt-mark::before { content: '\e97e'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_fluent.scss b/controls/documenteditor/styles/document-editor/icons/_fluent.scss index 6e6875a36f..9912699f2b 100644 --- a/controls/documenteditor/styles/document-editor/icons/_fluent.scss +++ b/controls/documenteditor/styles/document-editor/icons/_fluent.scss @@ -56,6 +56,7 @@ .e-de-multi-cmt-mark::before { content: '\e8bc'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_fusionnew.scss b/controls/documenteditor/styles/document-editor/icons/_fusionnew.scss index 1b907bd7a7..daa1c3d7a6 100644 --- a/controls/documenteditor/styles/document-editor/icons/_fusionnew.scss +++ b/controls/documenteditor/styles/document-editor/icons/_fusionnew.scss @@ -58,6 +58,7 @@ color: $icon-color; content: '\e8bc'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_highcontrast-light.scss b/controls/documenteditor/styles/document-editor/icons/_highcontrast-light.scss index fca1096d8d..e29913e237 100644 --- a/controls/documenteditor/styles/document-editor/icons/_highcontrast-light.scss +++ b/controls/documenteditor/styles/document-editor/icons/_highcontrast-light.scss @@ -68,6 +68,7 @@ .e-de-multi-cmt-mark::before { content: '\e97a'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_highcontrast.scss b/controls/documenteditor/styles/document-editor/icons/_highcontrast.scss index c818481f8a..0b2cd41cbd 100644 --- a/controls/documenteditor/styles/document-editor/icons/_highcontrast.scss +++ b/controls/documenteditor/styles/document-editor/icons/_highcontrast.scss @@ -58,6 +58,7 @@ .e-de-multi-cmt-mark::before { content: '\e97a'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_material-dark.scss b/controls/documenteditor/styles/document-editor/icons/_material-dark.scss index b321f5ea30..49b93ffc2d 100644 --- a/controls/documenteditor/styles/document-editor/icons/_material-dark.scss +++ b/controls/documenteditor/styles/document-editor/icons/_material-dark.scss @@ -64,6 +64,7 @@ .e-de-multi-cmt-mark::before { content: '\e97a'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_material.scss b/controls/documenteditor/styles/document-editor/icons/_material.scss index c5f490953d..d4f03898f0 100644 --- a/controls/documenteditor/styles/document-editor/icons/_material.scss +++ b/controls/documenteditor/styles/document-editor/icons/_material.scss @@ -64,6 +64,7 @@ .e-de-multi-cmt-mark::before { content: '\e97a'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_material3.scss b/controls/documenteditor/styles/document-editor/icons/_material3.scss index dd0a817de6..213cdb2c67 100644 --- a/controls/documenteditor/styles/document-editor/icons/_material3.scss +++ b/controls/documenteditor/styles/document-editor/icons/_material3.scss @@ -58,6 +58,7 @@ color: $icon-color; content: '\e8bc'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { @@ -232,7 +233,7 @@ .e-de-table-border-none-setting::before { color: $icon-color; content: '\e7eb'; - font-size: $de-border-none-setting-font-size; + font-size: $de-border-setting-font-size; position: absolute; } @@ -266,14 +267,14 @@ .e-de-para-border-none-setting::before { color: $icon-color; - content: '\e93f'; - font-size: $de-border-none-setting-font-size; + content: '\e890'; + font-size: $de-border-setting-font-size; position: absolute; } .e-de-para-border-box-setting::before { color: $icon-color; - content: '\e940'; + content: '\e891'; font-size: $de-border-setting-font-size; left: 2px; position: absolute; @@ -282,7 +283,7 @@ .e-de-para-border-shadow-setting::before { color: $icon-color; - content: '\e942'; + content: '\e892'; font-size: $de-border-setting-font-size; left: 2px; position: absolute; @@ -291,7 +292,7 @@ .e-de-para-border-custom-setting::before { color: $icon-color; - content: '\e946'; + content: '\e88f'; font-size: $de-border-setting-font-size; left: 2px; position: absolute; diff --git a/controls/documenteditor/styles/document-editor/icons/_tailwind-dark.scss b/controls/documenteditor/styles/document-editor/icons/_tailwind-dark.scss index f976aec90c..fe8d0a2217 100644 --- a/controls/documenteditor/styles/document-editor/icons/_tailwind-dark.scss +++ b/controls/documenteditor/styles/document-editor/icons/_tailwind-dark.scss @@ -58,6 +58,7 @@ color: $icon-color; content: '\e8bc'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before { diff --git a/controls/documenteditor/styles/document-editor/icons/_tailwind.scss b/controls/documenteditor/styles/document-editor/icons/_tailwind.scss index d8ab53c9de..d2a02fb97b 100644 --- a/controls/documenteditor/styles/document-editor/icons/_tailwind.scss +++ b/controls/documenteditor/styles/document-editor/icons/_tailwind.scss @@ -58,6 +58,7 @@ color: $icon-color; content: '\e8bc'; font-family: 'e-icons'; + font-size: 14px; } .e-de-cmt-post::before {