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 preview the generated documents. Getting notified when the tab is active can be useful to trigger certain actions in your application.

Consider the following situation: You have an external Save button in your application that saves the current document in the Document Editor. This button should only be enabled to allow users to save content when the document is in Edit mode, not Preview mode. Preview mode is a mode that populates inserted merge fields with data to preview the document as you design a template.
When the document is in Preview mode, the Save button should be disabled, as shown in the following screenshot:
MutationObserver
One way to achieve this is by using the MutationObserver API. The MutationObserver interface provides the ability to watch for changes being made to the DOM tree. When a change is detected, the observer will call a specified callback function. This is useful for detecting changes to the DOM that are made by JavaScript, such as when the document mode changes from Preview to Edit.
In the ribbonTabsLoaded event handler, you can create a new MutationObserver instance and observe changes to the ribbonGroupMailMergePreview element. When the ribbonGroupMailMergePreview element is visible (i.e., the document is in Preview mode), you can disable the Save button. When the ribbonGroupMailMergePreview element is not visible (i.e., the document is in Edit mode), you can enable the Save button.
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
TXTextControl.addEventListener("ribbonTabsLoaded", function () {
targetNode = document.getElementById('ribbonGroupMailMergePreview');
// Start observing the target node for configured mutations
if (targetNode) {
observer.observe(targetNode, config);
// Initial check
console.log(`Initial visibility of #ribbonGroupMailMergePreview: ${checkVisibility(targetNode)}`);
} else {
console.error('Element #ribbonGroupMailMergePreview not found');
}
});
The callback function will be called whenever a change is detected in the ribbonGroupMailMergePreview element. The function will check if the ribbonGroupMailMergePreview element is visible and enable or disable the Save button accordingly.
// Function to check visibility
function checkVisibility(element) {
const style = window.getComputedStyle(element);
return style && style.display !== 'none' && style.visibility !== 'hidden';
}
// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'attributes' || mutation.type === 'childList') {
// Check visibility whenever an attribute or child list changes
const isVisible = checkVisibility(targetNode);
if (isVisible) {
document.getElementById('saveBtn').disabled = true;
} else {
document.getElementById('saveBtn').disabled = false;
}
}
}
};
The full kbd for this example is here:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>TX Text Control Document Editor from JS</title>
<script
src="https://backend.textcontrol.com/api/TXWebSocket/GetResource?name=tx-document-editor.min.js">
</script>
<style>
body {
font-family: Verdana, Geneva, Tahoma, sans-serif;
}
button {
margin-top: 20px;
}
#txDocumentEditor {
height: 600px;
width: 800px;
}
</style>
</head>
<body>
<div id="txDocumentEditor"></div>
<button id="saveBtn" onclick="save()">Save Document</button>
<script>
var targetNode = null;
TXTextControl.init({
containerID: "txDocumentEditor",
webSocketURL: "wss://backend.textcontrol.com/api/TXWebSocket?access-token="
});
var customerJson = [{
"name": "John Doe",
"address": "1234 Elm Street",
"city": "Austin",
"state": "TX",
"zip": "78701"
}];
TXTextControl.addEventListener("ribbonTabsLoaded", function () {
targetNode = document.getElementById('ribbonGroupMailMergePreview');
// Start observing the target node for configured mutations
if (targetNode) {
observer.observe(targetNode, config);
// Initial check
console.log(`Initial visibility of #ribbonGroupMailMergePreview: ${checkVisibility(targetNode)}`);
} else {
console.error('Element #ribbonGroupMailMergePreview not found');
}
});
TXTextControl.addEventListener("textControlLoaded", function () {
TXTextControl.loadJsonData(JSON.stringify(customerJson));
});
function save() {
TXTextControl.saveDocument(TXTextControl.StreamType.HTMLFormat, function (data) {
console.log(data);
});
}
// Function to check visibility
function checkVisibility(element) {
const style = window.getComputedStyle(element);
return style && style.display !== 'none' && style.visibility !== 'hidden';
}
// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
for (let mutation of mutationsList) {
if (mutation.type === 'attributes' || mutation.type === 'childList') {
// Check visibility whenever an attribute or child list changes
const isVisible = checkVisibility(targetNode);
if (isVisible) {
document.getElementById('saveBtn').disabled = true;
} else {
document.getElementById('saveBtn').disabled = false;
}
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: true, subtree: true };
</script>
</body>
</html>
Conclusion
The MutationObserver API is a powerful tool for detecting changes to the DOM tree. In this example, we used a MutationObserver to enable or disable a Save button based on the visibility of a specific element. This technique can be applied to a wide range of scenarios where you need to respond to changes in the DOM.
Related Posts
Building an ASP.NET Core Backend Application to Host the Document Editor and…
This article explains how to create an ASP.NET Core backend application to host the Document Editor and Document Viewer. This backend application is required to provide the required functionality…
Building an ASP.NET Core Backend (Linux and Windows) for the Document Editor…
This article shows how to create a backend for the Document Editor and Viewer using ASP.NET Core. The backend can be hosted on Windows and Linux and can be used in Blazor, Angular, JavaScript, and…
JavaScript: Avoid Flickering and Visual Updates by Grouping Undo Steps
The JavaScript API can be used to group several steps into one undo action that can be undone with a single undo call. Additionally, those groups are visually updated at once to avoid screen…
JavaScript Functions for Typical Form Field Tasks
The new JavaScript API not only enables programmatic access to all elements of a document, but also provides events for user interaction.
ASP.NETASP.NET CoreDocument Editor
Getting Started Video Tutorial: Document Editor in ASP.NET Core C# on Linux
This video tutorial shows how to use the Document Editor in an ASP.NET Core application using C# and deploy on Linux using Docker. This tutorial is part of the TX Text Control Getting Started…