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.