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
-
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.
-
-
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
-
Enqueueing the JavaScript:
enqueue_live_preview_script
Function:wp_enqueue_script
: Loads thelive-preview.js
script from your theme’sjs
directory. Ensure that this file exists; you’ll create it in the next step.wp_localize_script
: Passes theajax_url
and a securitynonce
to the JavaScript file, enabling secure AJAX requests.
-
Registering the AJAX Handler:
add_action('wp_ajax_create_new_page_or_post_from_preview', 'create_new_page_or_post_from_preview')
: Registers thecreate_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
andpost
).
- Title: Sanitized using
- 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
)
- Bootstrap classes for styling (
-
CSS
- Sets width, display, and margin for proper alignment.
-
-
Options
-
-
-
Default Option
- “Select Post Type” (disabled and selected by default).
-
Page Option
- Value
page
.
- Value
-
Post Option
- Value
post
.
- Value
-
-
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
)
- Bootstrap classes for styling (
-
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
orpost
), the button is enabled.
- If a post type is selected (
-
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 thelive-preview.js
file there.
- If not, create a
-
Add the PHP Code
-
-
Location
- Insert the PHP code into your theme’s
functions.php
file or within a custom plugin.
- Insert the PHP code into your theme’s
-
JavaScript File Path
- Ensure that the path in
wp_enqueue_script
correctly points to yourlive-preview.js
file. - Adjust it if your JS file is located elsewhere.
- Ensure that the path in
-
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>
- Ensure there’s an element with
-
Content Element
- Ensure there’s a
<div>
withid="preview-area"
where the content resides. - Example:
- <div id=”preview-area”>
<!– Your live preview content here –>
</div>
- Ensure there’s a
-
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.
- Before making changes to your
- 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.
- If you’re modifying a theme’s
- Plugin Alternative
- For better maintainability and portability, consider encapsulating this functionality within a custom plugin instead of placing it in
functions.php
.
- For better maintainability and portability, consider encapsulating this functionality within a custom plugin instead of placing it in
- 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
orPost
.
- Allows users to select between creating a
-
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.
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