function add_replace_words_meta_box() {
add_meta_box(
'replace_words_meta_box',
'Replace Words',
'replace_words_meta_box_callback',
'post',
'side',
'high'
);
}
add_action('add_meta_boxes', 'add_replace_words_meta_box');
function replace_words_meta_box_callback($post) {
?>
<label for="old_word">Old Word:</label>
<input type="text" id="old_word" style="width: 100%;" placeholder="Enter the old word">
<label for="new_word" style=" 10px; display: block;">New Word:</label>
<input type="text" id="new_word" style="width: 100%;" placeholder="Enter the new word">
<button type="button" id="replace_words_btn" style=" 10px; padding: 5px 10px; background: #0073aa; color: white; border: none; cursor: pointer;">
Replace Word
</button>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Function to update an element's value using the native setter so React detects the change.
function setNativeValue(element, value) {
if (!element) return;
if (element.tagName === "INPUT") {
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
nativeInputValueSetter.call(element, value);
} else if (element.tagName === "TEXTAREA") {
const nativeTextAreaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
nativeTextAreaValueSetter.call(element, value);
}
element.dispatchEvent(new Event('input', { bubbles: true }));
element.dispatchEvent(new Event('change', { bubbles: true }));
}
document.getElementById("replace_words_btn").addEventListener("click", function () {
// First, sync TinyMCE content if available.
if (typeof tinymce !== "undefined") {
tinymce.triggerSave();
}
let oldWord = document.getElementById("old_word").value.trim();
let newWord = document.getElementById("new_word").value.trim();
if (oldWord === "" || newWord === "") {
alert("Please enter both the old and new words.");
return;
}
let changesMade = false;
let regex = new RegExp(oldWord, "g");
// Replace in the post title (works with both editors)
let postTitle = document.getElementById("title");
if (postTitle && postTitle.value.includes(oldWord)) {
postTitle.value = postTitle.value.replace(regex, newWord);
changesMade = true;
}
// Replace in the classic editor content (usually with the ID "content")
let contentArea = document.getElementById("content");
if (contentArea && contentArea.value.includes(oldWord)) {
contentArea.value = contentArea.value.replace(regex, newWord);
changesMade = true;
// If TinyMCE is active, update its content as well.
if (typeof tinymce !== "undefined") {
let editor = tinymce.get("content");
if (editor) {
editor.setContent(contentArea.value);
}
}
}
// Replace in Gutenberg editor content.
if (typeof wp !== "undefined" && wp.data) {
let postContent = wp.data.select("core/editor").getEditedPostAttribute("content");
if (postContent && postContent.includes(oldWord)) {
let updatedContent = postContent.replace(regex, newWord);
wp.data.dispatch("core/editor").editPost({ content: updatedContent });
changesMade = true;
}
let postTitleGutenberg = wp.data.select("core/editor").getEditedPostAttribute("title");
if (postTitleGutenberg && postTitleGutenberg.includes(oldWord)) {
let updatedTitle = postTitleGutenberg.replace(regex, newWord);
wp.data.dispatch("core/editor").editPost({ title: updatedTitle });
changesMade = true;
}
}
// Replace in Yoast SEO Premium fields.
// We use multiple selectors and the setNativeValue function to update the value in a way React recognizes.
let yoastTitle = document.querySelector('input#yoast_wpseo_title, input[name="yoast_wpseo_title"]');
if (yoastTitle && yoastTitle.value.includes(oldWord)) {
let newVal = yoastTitle.value.replace(regex, newWord);
setNativeValue(yoastTitle, newVal);
changesMade = true;
}
let yoastDesc = document.querySelector('textarea#yoast_wpseo_metadesc, textarea[name="yoast_wpseo_metadesc"]');
if (yoastDesc && yoastDesc.value.includes(oldWord)) {
let newVal = yoastDesc.value.replace(regex, newWord);
setNativeValue(yoastDesc, newVal);
changesMade = true;
}
if (changesMade) {
alert("Successfully replaced all occurrences of '" + oldWord + "' with '" + newWord + "'.");
} else {
alert("No occurrences of '" + oldWord + "' were found in the post content, title, or Yoast SEO fields.");
}
});
});
</script>
<?php
}