$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>Loading gutenberg editor in front end— But Not loading|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

Loading gutenberg editor in front end— But Not loading

matteradmin8PV0评论
gutenberg-post-submitter/
├── gutenberg-post-submitter.php       # Main plugin file
├── assets/
│   ├── css/
│   │   └── submitter-style.css        # CSS for the form
│   └── js/
│       └── submitter-script.js        # JavaScript for Gutenberg integration

gutenberg-post-submitter.php:

<?php
/**
 * Plugin Name: Gutenberg Post Submitter
 * Description: Creates a shortcode to display a post submission form with Gutenberg editor for admin users only.
 * Version: 1.0.0
 * Author: Your Name
 * Text Domain: gutenberg-post-submitter
 */

// If this file is called directly, abort.
if (!defined('WPINC')) {
    die;
}

// Define plugin constants
define('GUT_POST_SUBMITTER_VERSION', '1.0.0');
define('GUT_POST_SUBMITTER_PLUGIN_DIR', plugin_dir_path(__FILE__));

/**
 * The core plugin class
 */
class Gutenberg_Post_Submitter {

    /**
     * Initialize the plugin
     */
    public function __construct() {
        // Register shortcode
        add_shortcode('gut_post_form', array($this, 'render_post_form'));
        
        // Register scripts and styles
        add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
        
        // Register REST API endpoints
        add_action('rest_api_init', array($this, 'register_rest_routes'));
    }

    /**
     * Enqueue scripts and styles for the frontend
     */
    public function enqueue_scripts() {
        global $post;
        
        // Only enqueue if the shortcode is present
        if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'gut_post_form')) {
            
            // Only enqueue Gutenberg resources for admin users
            if (current_user_can('manage_options')) {
                // Register and enqueue WordPress packages for Gutenberg
                // Core scripts
                wp_enqueue_script('wp-element');
                wp_enqueue_script('wp-polyfill');
                wp_enqueue_script('wp-blocks');
                wp_enqueue_script('wp-dom');
                wp_enqueue_script('wp-dom-ready');
                wp_enqueue_script('wp-components');
                wp_enqueue_script('wp-i18n');
                wp_enqueue_script('wp-data');  // CRITICAL for editor to function
                wp_enqueue_script('wp-compose');
                wp_enqueue_script('wp-block-editor');
                wp_enqueue_script('wp-format-library');
                
                // Core styles
                wp_enqueue_style('wp-edit-blocks');
                wp_enqueue_style('wp-components');
                wp_enqueue_style('wp-editor');
                wp_enqueue_style('wp-block-editor');
                wp_enqueue_style('wp-edit-post');
                wp_enqueue_style('wp-format-library');
                
                // Add editor styles to match your theme
                wp_add_inline_style('wp-edit-blocks', '
                    .editor-styles-wrapper { 
                        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
                        padding: 20px;
                    }
                    .wp-block {
                        max-width: 100%;
                    }
                    /* Fix contenteditable issues */
                    .block-list-appender {
                        position: relative !important;
                        display: flex !important;
                        pointer-events: all !important;
                        cursor: text !important;
                    }
                    
                    .block-editor-writing-flow {
                        display: block !important;
                        pointer-events: auto !important;
                    }
                    
                    [contenteditable="false"] {
                        user-select: auto !important;
                        -webkit-user-select: auto !important;
                    }
                    
                    .block-editor-block-list__layout .block-editor-block-list__block {
                        pointer-events: all !important;
                    }
                ');
                
                // Add debugging message to console
                wp_add_inline_script('wp-element', '
                    console.log("Gutenberg editor scripts loaded");
                    console.log("wp object available:", typeof wp !== "undefined");
                    if (typeof wp !== "undefined") {
                        console.log("  wp.element available:", typeof wp.element !== "undefined");
                        console.log("  wp.blocks available:", typeof wp.blocks !== "undefined");
                        console.log("  wp.blockEditor available:", typeof wp.blockEditor !== "undefined");
                        console.log("  wp.data available:", typeof wp.data !== "undefined");
                    }
                ');
                
                // Custom script
                wp_enqueue_script(
                    'gut-post-submitter-script',
                    plugins_url('assets/js/submitter-script.js', __FILE__),
                    array(
                        'wp-element',
                        'wp-blocks',
                        'wp-block-editor',
                        'wp-data',
                        'wp-components',
                        'jquery'
                    ),
                    GUT_POST_SUBMITTER_VERSION,
                    true  // Load in footer
                );
                
                // Add inline script to fix contenteditable issues
                wp_add_inline_script('gut-post-submitter-script', '
                // Fix contenteditable issues on load
                document.addEventListener("DOMContentLoaded", function() {
                    // Wait a moment for the editor to initialize
                    setTimeout(function() {
                        // Force all contenteditable=false elements to be editable
                        const nonEditables = document.querySelectorAll("[contenteditable=\'false\']");
                        for(let i = 0; i < nonEditables.length; i++) {
                            nonEditables[i].removeAttribute("contenteditable");
                            nonEditables[i].style.pointerEvents = "auto";
                        }
                        console.log("Fixed " + nonEditables.length + " contenteditable elements");
                    }, 1000);
                });
                ');
                
                // Custom style
                wp_enqueue_style(
                    'gut-post-submitter-style',
                    plugins_url('assets/css/submitter-style.css', __FILE__),
                    array('wp-edit-blocks', 'wp-components', 'wp-editor'),
                    GUT_POST_SUBMITTER_VERSION
                );
                
                // Localize script with REST API info
                wp_localize_script(
                    'gut-post-submitter-script',
                    'gutPostSubmitter',
                    array(
                        'restUrl' => esc_url_raw(rest_url('gut-post-submitter/v1/submit')),
                        'nonce' => wp_create_nonce('wp_rest'),
                        'currentUser' => get_current_user_id(),
                        'debugMode' => defined('WP_DEBUG') && WP_DEBUG,
                        'allowedBlocks' => true,  
                        'hasFixedToolbar' => true,
                        'hasUploadPermissions' => current_user_can('upload_files'),
                        'editorSettings' => array(
                            '__experimentalSetIsInserterOpened' => true,
                            'isRTL' => is_rtl(),
                            'disableCustomColors' => false,
                            'disableCustomFontSizes' => false,
                        ),
                    )
                );
            }
        }
    }
    
    /**
     * Register REST API routes
     */
    public function register_rest_routes() {
        register_rest_route('gut-post-submitter/v1', '/submit', array(
            'methods' => 'POST',
            'callback' => array($this, 'handle_post_submission'),
            'permission_callback' => array($this, 'check_permission')
        ));
    }
    
    /**
     * Check if user has permission to submit posts
     */
    public function check_permission() {
        return current_user_can('manage_options');
    }

    /**
     * Render the post submission form
     */
    public function render_post_form() {
        // Check if user is admin
        if (!current_user_can('manage_options')) {
            return '<p>' . esc_html__('You must be an administrator to access this form.', 'gutenberg-post-submitter') . '</p>';
        }
        
        ob_start();
        ?>
        <div class="gut-post-form-container">
            <form id="gut-post-form">
                <div class="form-group">
                    <label for="gut-post-title"><?php esc_html_e('Post Title', 'gutenberg-post-submitter'); ?></label>
                    <input type="text" id="gut-post-title" name="post_title" required>
                </div>
                
                <div class="form-group">
                    <label for="gut-post-content"><?php esc_html_e('Post Content', 'gutenberg-post-submitter'); ?></label>
                    <div id="gut-editor-container"></div>
                </div>
                
                <div class="form-group">
                    <button type="submit" class="gut-submit-button"><?php esc_html_e('Submit Post', 'gutenberg-post-submitter'); ?></button>
                </div>
                
                <div id="gut-form-messages"></div>
            </form>
        </div>
        <?php
        return ob_get_clean();
    }

    /**
     * Handle the post submission via REST API
     * 
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_REST_Response
     */
    public function handle_post_submission($request) {
        // Get request parameters
        $params = $request->get_json_params();
        
        // Validate input
        if (empty($params['title']) || empty($params['content'])) {
            return new WP_REST_Response(array(
                'success' => false,
                'message' => 'Title and content are required.'
            ), 400);
        }
        
        // Sanitize input
        $title = sanitize_text_field($params['title']);
        $content = wp_kses_post($params['content']);
        
        // Create post
        $post_data = array(
            'post_title'    => $title,
            'post_content'  => $content,
            'post_status'   => 'draft',
            'post_author'   => get_current_user_id(),
            'post_type'     => 'post'
        );
        
        $post_id = wp_insert_post($post_data);
        
        if ($post_id) {
            return new WP_REST_Response(array(
                'success' => true,
                'message' => 'Post created successfully!',
                'post_id' => $post_id,
                'edit_url' => get_edit_post_link($post_id, 'raw')
            ), 201);
        } else {
            return new WP_REST_Response(array(
                'success' => false,
                'message' => 'Error creating post.'
            ), 500);
        }
    }
}

// Initialize the plugin
$gutenberg_post_submitter = new Gutenberg_Post_Submitter();

submitter-script.js —

/**
 * Gutenberg Post Submitter Script
 * Integrates the Gutenberg editor into the frontend submission form
 */

;(function ($) {
    "use strict"

    // Wait for DOM to be fully loaded
    $(document).ready(function () {
        // Check if we're on the right page with the editor container
        const editorContainer = document.getElementById("gut-editor-container")
        if (!editorContainer) {
            console.error("Editor container not found - cannot initialize Gutenberg")
            return
        }

        // Check if all required WordPress packages are available
        if (typeof wp === "undefined" || !wp.element || !wp.blockEditor || !wp.blocks || !wp.data) {
            console.error("Required WordPress packages not loaded. Make sure all required scripts are enqueued.")
            console.log("Available wp object:", wp)
            return
        }

        console.log("Starting Gutenberg editor initialization...")

        // Initialize variables
        let editorData

        // Initialize Gutenberg editor
        initGutenbergEditor()

        // Handle form submission
        $("#gut-post-form").on("submit", function (e) {
            e.preventDefault()
            submitPost()
        })

        /**
         * Fix contenteditable issues
         */
        function fixContentEditableIssues() {
            // Force the block-list-appender to be editable
            const appenders = document.querySelectorAll(".block-list-appender")
            if (appenders.length) {
                appenders.forEach(appender => {
                    // Remove contenteditable="false" from appenders
                    appender.removeAttribute("contenteditable")
                    appender.style.pointerEvents = "auto"
                    appender.style.cursor = "pointer"
                })
                console.log("Fixed contenteditable issues on block appenders")
            }

            // Also fix any other non-editable blocks
            const nonEditableBlocks = document.querySelectorAll('[contenteditable="false"]')
            if (nonEditableBlocks.length) {
                nonEditableBlocks.forEach(block => {
                    block.removeAttribute("contenteditable")
                    block.style.pointerEvents = "auto"
                })
                console.log("Fixed " + nonEditableBlocks.length + " contenteditable elements")
            }
        }

        /**
         * Force editor interaction by programmatically inserting blocks
         */
        function forceEditorInteraction() {
            // Simulate a click on the block appender to make it interactive
            const appender = document.querySelector(".block-list-appender")
            if (appender) {
                // Force it to be a proper block
                appender.style.border = "1px dashed #ccc"
                appender.style.padding = "8px"
                appender.style.marginBottom = "20px"
                appender.style.minHeight = "40px"

                // Try to create a paragraph block programmatically
                try {
                    // Insert a default block through the WordPress data system
                    const { dispatch } = wp.data
                    dispatch("core/block-editor").insertBlocks(
                        wp.blocks.createBlock("core/paragraph", {
                            content: "Click here to start editing..."
                        })
                    )
                    console.log("Inserted default paragraph block")
                } catch (error) {
                    console.error("Could not insert default block:", error)
                }
            }
        }

        /**
         * Initialize the Gutenberg editor
         */
        function initGutenbergEditor() {
            // Get WordPress editor components
            const { createElement, Fragment } = wp.element
            const { BlockEditorProvider, BlockList, WritingFlow, ObserveTyping } = wp.blockEditor
            const { Popover, SlotFillProvider } = wpponents

            // Change this line in the initGutenbergEditor function:
            const initialBlocks = wp.blocks.parse("<!-- wp:paragraph --><p>Start typing here...</p><!-- /wp:paragraph -->")

            // Create editor component using React function component for simplicity
            function Editor() {
                // Use state hook for blocks
                const [blocks, setBlocks] = wp.element.useState(initialBlocks)

                // Update our reference to blocks for form submission
                editorData = blocks

                // Use effect hook to fix contenteditable issues after render
                wp.element.useEffect(() => {
                    // Fix contenteditable issues after editor is rendered
                    setTimeout(fixContentEditableIssues, 100)

                    // Also set up a mutation observer to fix issues as DOM changes
                    const observer = new MutationObserver(mutations => {
                        fixContentEditableIssues()
                    })

                    // Start observing the editor container
                    observer.observe(editorContainer, {
                        childList: true,
                        subtree: true,
                        attributes: true,
                        attributeFilter: ["contenteditable"]
                    })

                    // Cleanup function to disconnect observer when unmounting
                    return () => observer.disconnect()
                }, [])

                return createElement(
                    Fragment,
                    null,
                    createElement(
                        SlotFillProvider,
                        null,
                        createElement(
                            BlockEditorProvider,
                            {
                                value: blocks,
                                onInput: setBlocks,
                                onChange: setBlocks
                            },
                            createElement("div", { className: "editor-styles-wrapper" }, createElement(WritingFlow, null, createElement(ObserveTyping, null, createElement(BlockList, null)))),
                            createElement(Popover.Slot, null)
                        )
                    )
                )
            }

            // Render the editor
            try {
                wp.element.render(createElement(Editor, null), editorContainer)
                console.log("Gutenberg editor rendered successfully")

                // Fix contenteditable issues after a moment
                setTimeout(fixContentEditableIssues, 500)

                // Force editor interaction after editor is fully loaded
                setTimeout(forceEditorInteraction, 800)
            } catch (error) {
                console.error("Failed to render Gutenberg editor:", error)
            }
        }

        /**
         * Submit the post to WordPress using REST API
         */
        function submitPost() {
            // Get post title
            const title = $("#gut-post-title").val()

            // Validate title
            if (!title) {
                showMessage("Please enter a post title", "error")
                return
            }

            // Get Gutenberg content
            const content = editorData ? wp.blocks.serialize(editorData) : ""

            // Validate content
            if (!content || content.trim() === "") {
                showMessage("Please add some content to your post", "error")
                return
            }

            // Show loading state
            showMessage("Submitting post...", "info")

            // Debug log
            if (gutPostSubmitter.debugMode) {
                console.log("Submitting post data:", { title, content })
                console.log("REST URL:", gutPostSubmitter.restUrl)
            }

            // Send data to REST API
            fetch(gutPostSubmitter.restUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "X-WP-Nonce": gutPostSubmitter.nonce
                },
                body: JSON.stringify({
                    title: title,
                    content: content
                })
            })
                .then(function (response) {
                    if (!response.ok) {
                        if (gutPostSubmitter.debugMode) {
                            console.error("Response not OK:", response)
                        }
                        throw new Error("Network response was not ok: " + response.status)
                    }
                    return response.json()
                })
                .then(function (responseData) {
                    if (gutPostSubmitter.debugMode) {
                        console.log("Response data:", responseData)
                    }

                    if (responseData.success) {
                        // Show success message
                        showMessage(responseData.message, "success")

                        // Clear form
                        $("#gut-post-title").val("")

                        // Reset editor - reinitialize with empty content
                        initGutenbergEditor()

                        // Add edit link
                        if (responseData.edit_url) {
                            $("#gut-form-messages").append('<p><a href="' + responseData.edit_url + '" target="_blank">Edit this post in admin</a></p>')
                        }
                    } else {
                        showMessage(responseData.message || "Error submitting post", "error")
                    }
                })
                .catch(function (error) {
                    console.error("Error:", error)
                    showMessage("An error occurred while submitting the post: " + error.message, "error")
                })
        }

        /**
         * Display a message to the user
         */
        function showMessage(message, type) {
            const messageContainer = $("#gut-form-messages")

            // Clear previous messages
            messageContainer.html("")

            // Add new message
            messageContainer.append('<div class="gut-message gut-message-' + type + '">' + message + "</div>")

            // Scroll to message
            $("html, body").animate(
                {
                    scrollTop: messageContainer.offset().top - 100
                },
                200
            )
        }
    })
})(jQuery)

The DOM output is this:

<div class="form-group">
                    <label for="gut-post-content">Post Content</label>
                    <div id="gut-editor-container"><div class="editor-styles-wrapper"><div tabindex="0"></div><div class="block-editor-writing-flow" tabindex="0" data-has-multi-selection="false"><div><div class="is-root-container block-editor-block-list__layout" data-is-drop-zone="true"><div tabindex="-1" class="block-list-appender wp-block" data-block="true" style="pointer-events: auto; cursor: pointer; border: 1px dashed rgb(204, 204, 204); padding: 8px; margin-bottom: 20px; min-height: 40px;"></div></div></div></div><div tabindex="0"></div></div><div class="popover-slot css-0 e19lxcc00"></div></div>
                </div>

Still Can't type anything in that FRONT end editor. In front end it looks like this —

Post a comment

comment list (0)

  1. No comments so far