JustPaste.it

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
}