Loading gutenberg editor in front end— But Not loading

admin2025-05-31  0

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 —

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748634102a313675.html

最新回复(0)