Live Content Generator Visual Toolbox Button

  • Save the Generated Data as New WordPress Page or Post on the Live Content Generator Visual Toolbox SEO Book Pro Tools Page
  • Enhance the “Save as New Page” button by adding a dropdown menu that allows users to select the post type (Page or Post)

The button Save as New Page/Post will

  • Include a dropdown for selecting the post type
  • Enable the button only when a post type is selected
  • Change the button text based on the selected post type
  • Send the selected post type along with the title and content via AJAX to create the new page or post
  • Ensure security and proper handling in the PHP backend

Overview of the Implementation

  1. JavaScript (live-preview.js)

    • Create and Insert the Dropdown and Button

      • Adds a dropdown for selecting the post type and a “Save as New Page/Post” button to the specified toolbar container.
    • Handle Dropdown Change

      • Enables/disables the button and updates the button text based on the selected post type.
    • Handle Button Click

      • Captures the title, content, and selected post type, then sends them via AJAX to the server.
    • Handle Server Response

      • Opens the new page/post in a new tab upon successful creation.
  2. PHP (functions.php or Custom Plugin)

Enqueue JavaScript

Loads the custom JavaScript file and localizes necessary data (AJAX URL and nonce).

Register AJAX Handlers

Defines functions to handle AJAX requests for creating new pages or posts.

Create New Page/Post

Processes the AJAX request by validating permissions and creating a new WordPress page or post with the provided title, content, and post type.


PHP Code

Add the Following PHP Code to Your Theme’s functions.php File or a Custom Plugin

This PHP code enqueues the custom JavaScript file and sets up the AJAX handler to process the creation of a new WordPress page or post based on the selected post type.


// functions.php or your custom plugin file

// 1. Enqueue the custom JavaScript and localize necessary data
function enqueue_live_preview_script() {
    // Enqueue the script
    wp_enqueue_script(
        'live-preview-script', // Handle
        get_template_directory_uri() . '/js/live-preview.js', // Path to the JS file
        array('jquery'), // Dependencies
        '1.1', // Version
        true // Load in footer
    );

    // Localize script with AJAX URL and nonce for security
    wp_localize_script(
        'live-preview-script',
        'livePreviewData',
        array(
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce'    => wp_create_nonce('live_preview_nonce')
        )
    );
}
add_action('wp_enqueue_scripts', 'enqueue_live_preview_script');

// 2. Register AJAX handler for logged-in users
add_action('wp_ajax_create_new_page_or_post_from_preview', 'create_new_page_or_post_from_preview');

function create_new_page_or_post_from_preview() {
    // Verify the nonce for security
    if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'live_preview_nonce')) {
        wp_send_json_error('Invalid nonce.');
        wp_die();
    }

    // Check if the user has permission to create pages/posts
    if (!current_user_can('edit_posts')) {
        wp_send_json_error('Insufficient permissions.');
        wp_die();
    }

    // Sanitize and retrieve the title, content, and post type
    $title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
    $content = isset($_POST['content']) ? wp_kses_post($_POST['content']) : '';
    $post_type = isset($_POST['post_type']) ? sanitize_text_field($_POST['post_type']) : 'page';

    // Validate post type
    $allowed_post_types = array('page', 'post');
    if (!in_array($post_type, $allowed_post_types)) {
        wp_send_json_error('Invalid post type.');
        wp_die();
    }

    if (empty($title) || empty($content)) {
        wp_send_json_error('Title or content is missing.');
        wp_die();
    }

    // Prepare the new page/post data
    $new_post = array(
        'post_title'    => $title,
        'post_content'  => $content,
        'post_status'   => 'draft', // Change to 'publish' if you prefer immediate publishing
        'post_author'   => get_current_user_id(),
        'post_type'     => $post_type,
    );

    // Insert the new page/post into the database
    $post_id = wp_insert_post($new_post);

    if (is_wp_error($post_id)) {
        wp_send_json_error('Failed to create the ' . $post_type . '.');
    } else {
        wp_send_json_success(array(
            'message'  => ucfirst($post_type) . ' created successfully!',
            'post_url' => get_permalink($post_id)
        ));
    }

    wp_die(); // Always terminate AJAX handlers with wp_die()
}

Explanation of the PHP Code

  1. Enqueueing the JavaScript:

    • enqueue_live_preview_script Function:
      • wp_enqueue_script: Loads the live-preview.js script from your theme’s js directory. Ensure that this file exists; you’ll create it in the next step.
      • wp_localize_script: Passes the ajax_url and a security nonce to the JavaScript file, enabling secure AJAX requests.
  2. Registering the AJAX Handler:

    • add_action('wp_ajax_create_new_page_or_post_from_preview', 'create_new_page_or_post_from_preview'): Registers the create_new_page_or_post_from_preview function to handle AJAX requests from logged-in users.
    • create_new_page_or_post_from_preview Function:
      • Nonce Verification: Ensures that the request is legitimate.
      • Permission Check: Verifies that the user has the capability to edit posts (typically admins or editors).
      • Sanitization and Validation:
        • Title: Sanitized using sanitize_text_field.
        • Content: Sanitized using wp_kses_post to allow only safe HTML tags.
        • Post Type: Sanitized and validated against allowed post types (page and post).
      • Page/Post Creation: Uses wp_insert_post to create a new WordPress page or post with the provided title, content, and post type.
      • Response: Sends a JSON response back to the JavaScript indicating success or failure, along with the URL of the newly created page/post if successful.

JavaScript Code

Create and Add the Following JavaScript Code to live-preview.js

This JavaScript code handles the creation of the dropdown menu and the “Save as New Page/Post” button, manages their interactions, captures the title and content, sends them via AJAX, and opens the newly created page/post in a new browser tab upon successful creation.


// live-preview.js

jQuery(document).ready(function($) {
    // 1. Create the dropdown for selecting post type
    const postTypeDropdown = $('<select>', {
        id: 'postTypeDropdown',
        class: 'form-select mb-2',
        css: {
            width: '200px',
            display: 'inline-block',
            marginRight: '10px'
        }
    }).append(
        $('<option>', { value: '', text: 'Select Post Type', disabled: true, selected: true }),
        $('<option>', { value: 'page', text: 'Page' }),
        $('<option>', { value: 'post', text: 'Post' })
    );

    // 2. Create the "Save as New Page/Post" button
    const saveButton = $('<button>', {
        text: 'Save as New Page',
        id: 'saveAsNewPagePostButton',
        class: 'btn btn-primary mb-3',
        disabled: true, // Initially disabled
        css: {
            // Adjust the styling as needed
            display: 'inline-block'
        }
    });

    // 3. Append the dropdown and button to the live preview audit toolbar container
    $('#livePreviewAuditToolbarContainer').append(postTypeDropdown, saveButton);

    // 4. Handle dropdown change to enable/disable the button and update button text
    $('#postTypeDropdown').on('change', function() {
        const selectedType = $(this).val();
        if (selectedType) {
            saveButton.prop('disabled', false);
            if (selectedType === 'page') {
                saveButton.text('Save as New Page');
            } else if (selectedType === 'post') {
                saveButton.text('Save as New Post');
            }
        } else {
            saveButton.prop('disabled', true).text('Save as New Page');
        }
    });

    // 5. Handle button click
    $('#saveAsNewPagePostButton').on('click', function(e) {
        e.preventDefault();

        // Retrieve the selected post type, title, and content
        const postType = $('#postTypeDropdown').val();
        const title = $('#previewTitle').text().trim();
        const content = $('#preview-area').html().trim();

        if (!postType) {
            alert('Please select a post type.');
            return;
        }

        if (title === '' || content === '') {
            alert('Both the title and content must be filled out before saving.');
            return;
        }

        // Optional: Confirm the action
        if (!confirm(`Are you sure you want to create a new ${postType} with the current content?`)) {
            return;
        }

        // 6. Send AJAX request to the server
        $.ajax({
            type: 'POST',
            url: livePreviewData.ajax_url, // Provided by wp_localize_script
            data: {
                action: 'create_new_page_or_post_from_preview',
                nonce: livePreviewData.nonce,
                title: title,
                content: content,
                post_type: postType
            },
            beforeSend: function() {
                // Disable the dropdown and button to prevent multiple clicks
                $('#postTypeDropdown').prop('disabled', true);
                $('#saveAsNewPagePostButton').prop('disabled', true).text('Saving...');
            },
            success: function(response) {
                if (response.success) {
                    // Open the new page/post in a new tab
                    window.open(response.data.post_url, '_blank');
                } else {
                    alert('Error: ' + response.data);
                }
            },
            error: function(xhr, status, error) {
                alert('An unexpected error occurred: ' + error);
            },
            complete: function() {
                // Re-enable the dropdown and button
                $('#postTypeDropdown').prop('disabled', false);
                $('#saveAsNewPagePostButton').prop('disabled', false).text(function() {
                    const selectedType = $('#postTypeDropdown').val();
                    return selectedType === 'page' ? 'Save as New Page' :
                           selectedType === 'post' ? 'Save as New Post' : 'Save as New Page';
                });
            }
        });
    });
});


Explanation of the JavaScript Code


Creating the Dropdown Menu

      • $('<select>', {...})

        • Dynamically creates a <select> element with:
      • ID

        • postTypeDropdown
      • Classes

        • Bootstrap classes for styling (form-select mb-2)
      • CSS

        • Sets width, display, and margin for proper alignment.

Options

      • Default Option

        • “Select Post Type” (disabled and selected by default).
      • Page Option

        • Value page.
      • Post Option

        • Value post.

Creating the Button

      • $('<button>', {...})

        • Dynamically creates a button element with:
      • Text

        • “Save as New Page” (default)

      • ID:

        • saveAsNewPagePostButton
      • Classes:

        • Bootstrap classes for styling (btn btn-primary mb-3)
      • Disabled:

        • Initially disabled until a post type is selected.
      • CSS:

        • Sets display to inline-block for alignment.

Appending Elements

$('#livePreviewAuditToolbarContainer').append(postTypeDropdown, saveButton)

Inserts the dropdown and button into the specified toolbar container.

Handling Dropdown Changes

    • Event Listener

      • Listens for changes in the dropdown selection.
    • Functionality

      • Enable Button

        • If a post type is selected (page or post), the button is enabled.
      • Update Button Text

        • Changes the button text to “Save as New Page” or “Save as New Post” based on selection.
      • Disable Button

        • If no post type is selected, the button remains disabled.

Handling Button Click

        • Event Listener

          • Listens for clicks on the “Save as New Page/Post” button.
        • Functionality

          • Retrieve Data

            • Gets the selected post type, title, and content.
          • Validation

            • Ensures that a post type is selected and that both title and content are not empty.
          • Confirmation

            • Optionally prompts the user to confirm the action.
          • AJAX Request

            • Sends the data to the server to create the new page or post.
          • Before Send

            • Disables the dropdown and button to prevent multiple submissions and updates the button text to “Saving…”.
          • Success Handler

            • If Successful
              • Opens the newly created page/post in a new browser tab.
            • If Failed
              • Displays an alert with the error message.
          • Error Handler

            • Alerts the user of any unexpected errors.
          • Complete Handler

            • Re-enables the dropdown and button, resetting the button text based on the selected post type.

Integration Steps

To implement this enhanced functionality, follow these steps


Create the JavaScript File

    • Path

      • your-theme/js/live-preview.js
    • Content

      • Paste the JavaScript code provided above into this file.
    • Ensure the js Directory Exists

      • If not, create a js directory within your theme folder and add the live-preview.js file there.

Add the PHP Code

    • Location

      • Insert the PHP code into your theme’s functions.php file or within a custom plugin.
    • JavaScript File Path

      • Ensure that the path in wp_enqueue_script correctly points to your live-preview.js file.
      • Adjust it if your JS file is located elsewhere.

Verify HTML Structure

    • Title Element

      • Ensure there’s an element with id="previewTitle", typically an <h1> tag.
      • Example
      • <h1 id=”previewTitle”>Your Page Title Here</h1>
    • Content Element

      • Ensure there’s a <div> with id="preview-area" where the content resides.
      • Example:
      • <div id=”preview-area”>
        <!– Your live preview content here –>
        </div>
    • Live Preview Audit Toolbar Container

      • Ensure the container exists where you want to place the dropdown and button.
      • Example
      • <div id=”livePreviewAuditToolbarContainer” class=”row preview-toolbar”>
        <!– Other toolbar elements –>
        </div>

Additional Considerations

Security Enhancements:

  • Nonce Verification

    • The PHP function verifies the nonce to ensure that the AJAX request is legitimate, preventing Cross-Site Request Forgery (CSRF) attacks.
  • Capability Checks

    • The PHP function checks if the user has the necessary permissions (edit_posts) to create a new page or post.
  • Sanitization

    • Title

      • Sanitized using sanitize_text_field to remove unwanted characters.
    • Content

      • Sanitized using wp_kses_post to allow only safe HTML tags.
    • Post Type

      • Sanitized and validated against allowed post types (page and post).

User Feedback

  • Success Message

    • Alerts the user with a success message and opens the newly created page/post in a new browser tab.
  • Error Messages

    • Provides feedback if something goes wrong during the page/post creation process.

Handling Pop-Up Blockers

  • window.open Usage

    • Some browsers might block pop-ups initiated by JavaScript. Ensure that users are aware they need to allow pop-ups from your site for this functionality to work seamlessly.

Post Status

  • Saving as Draft vs. Publishing Immediately

    • The PHP code sets ‘post_status’ => ‘draft’, which saves the page/post as a draft. If you prefer to publish immediately, change this to ‘post_status’ => ‘publish’.

e. Accessibility

  • ARIA Labels

    • Enhance accessibility by adding aria-label attributes to the dropdown and button.
  • Keyboard Navigation

    • Ensure that all interactive elements (dropdown and button) are accessible via keyboard.

Final Notes

  • Backup Your Site
    • Before making changes to your functions.php or adding new plugins, ensure you have a recent backup of your website to prevent any accidental issues.
  • Child Theme Usage
    • If you’re modifying a theme’s functions.php, consider using a child theme to ensure that your changes aren’t lost during theme updates.
  • Plugin Alternative
    • For better maintainability and portability, consider encapsulating this functionality within a custom plugin instead of placing it in functions.php.
  • Testing
    • After implementing, thoroughly test the functionality across different browsers and user roles to ensure consistent behavior.
  • Styling Consistency
    • Ensure that any styling associated with the dropdown and button aligns with your application’s overall design for a seamless user experience.

Summary

By following the steps above, you’ve successfully:

  • Added a Dropdown Menu

    • Allows users to select between creating a Page or Post.
  • Enhanced the Button Functionality:

    • Enabled Only When a Post Type is Selected.
    • Changed Text Based on Selection: “Save as New Page” or “Save as New Post”.
  • Handled AJAX Requests Securely

    • Ensures that only authorized users can create pages or posts.
  • Opened the New Page/Post in a New Tab

    • Keeps the current editor page open for continued work.
  • Ensured Accessibility and Security

    • By using ARIA labels, sanitization, and nonce verification.

This implementation enhances the usability of your Online Content Generator by providing users with flexibility in creating either pages or posts directly from the live preview area.

Ad Section After Last Paragraph

If you encounter any issues or need further customization, feel free to ask about Enhance the “Save as New Page” at the Live Content Generator Visual Toolbox