Products Technologies Demo Docs Blog Support Company

Reuse Document Editor Instances by Dynamically Moving them in the DOM

Reusing the document editor by moving it in the DOM is a very fast and efficient way to edit documents or snippets in multiple places on a page. This technique and the logic behind it are explained in this article.

Reuse Document Editor Instances by Dynamically Moving them in the DOM

Reusing instances of the Document Editor reduces load and initialization time and significantly improves the user experience when editing smaller snippets of text on a page. Once loaded, the Document Editor can be easily reused by moving it in the DOM and dynamically loading the document.

The following screen capture shows three instances of the Document Editor that are being moved around in the DOM in order to edit different documents.

Reusing Document Editor Instances

HTML Containers

In the HTML there is a mainContainer, which contains the document editor that has been initialized. The other DIV elements with the editorContainer class name will contain these instances when they are enabled.

<div id="mainContainer">
    @Html.TXTextControl().TextControl(settings => {
        settings.Dock = DockStyle.Fill;
    }).Render()
</div>

<div class="row mb-3">
    <div class="col-12">
        <label for="container1" class="form-label">Document Editor 1</label>
        <div id="container1" class="editorContainer inactive">
            
        </div>
    </div>
</div>

<div class="row mb-3">
    <div class="col-12">
        <label for="container2" class="form-label">Document Editor 2</label>
        <div id="container2" class="editorContainer inactive">
           
        </div>
    </div>
</div>

<div class="row mb-3">
    <div class="col-12">
        <label for="container3" class="form-label">Document Editor 3</label>
        <div id="container3" class="editorContainer inactive">
        </div>
    </div>
</div>

JavaScript: ContainerManager

The ContainerManager class handles the DOM manipulation when a new container is activated. All DIV elements with the class name editorContainer will have click events added to them in the constructor.

class ContainerManager {

     constructor() {
         this.currentContainer = null;
         this.storedDocuments = {};
         this.attachEventListeners();
     }

     async enableContainer(container, show) {

         if (this.currentContainer !== null) {
             await this.saveContainer(this.currentContainer);
             this.currentContainer.classList.add("inactive");
         }

         container.classList.remove("inactive");
         container.innerHTML = "";
         container.appendChild(document.getElementById("mainContainer"));

         await this.replaceContainer(this.currentContainer);
         await this.loadContainer(container);

         this.currentContainer = container;

         if (show === true) {
             document.getElementById("mainContainer").style.display = "inline-block";
             document.getElementById("mainContainer").style.height = "100%";
             window.dispatchEvent(new Event('resize'));
         }
     }

     async replaceContainer(container) {
         return new Promise(resolve => {
             if (container === null) {
                 resolve(false);
             } else {
                 TXTextControl.pages.elementAt(0, page => {
                     page.getImage(TXTextControl.ImageFormat.Png, 100, 7, function (image) {
                         const img = document.createElement("img");
                         img.src = "data:image/png;base64," + image;
                         img.className = "img-thumbnail";
                         container.innerHTML = "";
                         container.appendChild(img);
                         resolve(true);
                     });
                 });
             }
         });
     }

     async saveContainer(container) {
         return new Promise(resolve => {
             if (container === null) {
                 resolve(false);
             } else {

                 var docs = this.storedDocuments;

                 TXTextControl.saveDocument(TXTextControl.StreamType.InternalUnicodeFormat, function (data) {
                     docs[container.id] = data;
                     resolve(true);
                 });
             }
         });
     }

     async loadContainer(container) {
         return new Promise(resolve => {
             if (container === null) {
                 resolve(false);
             } else {

                 console.log(this.storedDocuments[container.id]);

                 if (this.storedDocuments[container.id] !== undefined) {
                     TXTextControl.loadDocument(TXTextControl.StreamType.InternalUnicodeFormat, this.storedDocuments[container.id].data, function () {
                         resolve(true);
                     });
                 } else {
                     TXTextControl.resetContents();
                     resolve(false);
                 }
             }
         });
     }

     attachEventListeners() {
         const elements = document.getElementsByClassName("editorContainer");

         for (let i = 0; i < elements.length; i++) {
             elements[i].addEventListener("click", (elem) => {
                 if (elem.target !== this.currentContainer && elem.target.className.includes("editorContainer")) {
                     this.enableContainer(elem.target, true);
                 }
             });
         }
     }
 }

 const containerManager = new ContainerManager();

When a container is clicked, an image of the first page of the document is created using the getImage method. This image is used to replace the Document Editor in inactive mode. The current state of the document is stored in the internal TX Text Control format in a dictionary.

Finally, the stored document is loaded into the moved document editor to display the document of that container.

Stay in the loop!

Subscribe to the newsletter to receive the latest updates.

ASP.NET

Integrate document processing into your applications to create documents such as PDFs and MS Word documents, including client-side document editing, viewing, and electronic signatures.

ASP.NET Core
Angular
Blazor
JavaScript
React
  • Angular
  • Blazor
  • React
  • JavaScript
  • ASP.NET MVC, ASP.NET Core, and WebForms

Learn more Trial token Download trial

Related Posts

AngularASP.NETJavaScript

Reuse Angular Document Editor Instances in Bootstrap Tabs

The initialization time of document editor instances is time-consuming and requires resources on both the server side and the client side. To reuse instances, they can be moved within the DOM.…


ASP.NETJavaScriptASP.NET Core

Add JavaScript to PDFs with TX Text Control in C# .NET: Time-Based Alerts…

In this article, we explore how to enrich PDF documents with JavaScript using TX Text Control in C# .NET. Read on to learn how to create time-based alerts that trigger actions based on specific…


AngularASP.NETJavaScript

Using the Document Editor in SPA Applications using the removeFromDom Method

This article shows how to use the removeFromDom method to remove the Document Editor from the DOM when it is no longer needed. This is useful when the Document Editor is used in a Single Page…


AngularASP.NETJavaScript

Observe When the Reporting Preview Tab is Active Using MutationObserver

This article shows how to observe when the Reporting Preview tab is active using MutationObserver. The Reporting Preview tab is a feature of the TX Text Control Document Editor that allows you to…


ASP.NETJavaScriptDocument Editor

Removing Empty Pages in TX Text Control with JavaScript

TX Text Control offers a C# solution for removing empty pages already. However, implementing this in JavaScript provides more flexibility for web environments. By using JavaScript methods to…