Changes to repeater ui, and completed MVP for custom image sizes
This commit is contained in:
32
assets/js/custom-image-sizes.js
Normal file
32
assets/js/custom-image-sizes.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
function lcpUpdateImageSizes(imageSizes) {
|
||||||
|
// Validate the input to ensure it's an array
|
||||||
|
if (!Array.isArray(imageSizes)) {
|
||||||
|
console.error('Invalid image sizes data');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the form data to send to WordPress to update the theme settings
|
||||||
|
const updateData = new FormData();
|
||||||
|
updateData.append('action', 'update_lcp_theme_settings'); // WordPress action hook
|
||||||
|
updateData.append('image_sizes', JSON.stringify(imageSizes)); // Send image sizes as a JSON string
|
||||||
|
updateData.append('nonce', customImageSizeAjax.nonce); // Send the nonce
|
||||||
|
|
||||||
|
console.log('Sending data to AJAX:', updateData); // Log the data for debugging
|
||||||
|
|
||||||
|
// Send the AJAX request
|
||||||
|
fetch(customImageSizeAjax.ajax_url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: updateData, // Send form data directly
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
console.log('Theme settings updated successfully.');
|
||||||
|
} else {
|
||||||
|
console.error('Failed to update theme settings:', data.message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error updating theme settings:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -1,5 +1,4 @@
|
|||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
console.log("I Tried"); // This will log the button element to the console
|
|
||||||
|
|
||||||
// Check if the 'Import Demo Posts' button exists
|
// Check if the 'Import Demo Posts' button exists
|
||||||
const importButton = document.getElementById('import-demo-posts');
|
const importButton = document.getElementById('import-demo-posts');
|
||||||
@ -42,9 +41,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
console.warn('Import button not found.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the 'Delete Demo Posts' button exists
|
// Check if the 'Delete Demo Posts' button exists
|
||||||
const deleteButton = document.getElementById('delete-demo-posts');
|
const deleteButton = document.getElementById('delete-demo-posts');
|
||||||
|
|||||||
@ -94,3 +94,157 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* REPEATER */
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Function to initialize each repeater instance
|
||||||
|
function initRepeater(repeater) {
|
||||||
|
const firstRow = repeater.querySelector('.lcp-repeater-row');
|
||||||
|
|
||||||
|
// Function to check if all required fields are filled
|
||||||
|
function isRequiredFieldsFilled(row) {
|
||||||
|
const requiredFields = row.querySelectorAll('[data-lcp-required="true"], [data-lcp-required-for-new-row="true"]');
|
||||||
|
let valid = true;
|
||||||
|
|
||||||
|
requiredFields.forEach(input => {
|
||||||
|
// Check input type and value for validation
|
||||||
|
if (input.type === 'number' && (input.value === '' || isNaN(input.value))) {
|
||||||
|
valid = false;
|
||||||
|
} else if (input.type === 'checkbox' && !input.checked) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to create a new row by cloning the first row
|
||||||
|
function addRepeaterRow() {
|
||||||
|
const newRow = firstRow.cloneNode(true); // true means deep cloning (includes children)
|
||||||
|
|
||||||
|
const inputs = newRow.querySelectorAll('input');
|
||||||
|
inputs.forEach(input => input.value = ''); // Reset value for input fields
|
||||||
|
newRow.querySelector('input[type="checkbox"]').checked = false; // Uncheck the checkbox
|
||||||
|
|
||||||
|
repeater.insertBefore(newRow, repeater.querySelector('.lcp-repeater-add-row'));
|
||||||
|
|
||||||
|
toggleAddRowButton();
|
||||||
|
toggleSubmitButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to toggle the "Add Row" button based on the required field for new rows
|
||||||
|
function toggleAddRowButton() {
|
||||||
|
const addRowButton = repeater.querySelector('.lcp-repeater-add-row');
|
||||||
|
const rows = repeater.querySelectorAll('.lcp-repeater-row');
|
||||||
|
|
||||||
|
let validForNewRow = true;
|
||||||
|
|
||||||
|
rows.forEach(row => {
|
||||||
|
const requiredForNewRowFields = row.querySelectorAll('[data-lcp-required-for-new-row="true"]');
|
||||||
|
requiredForNewRowFields.forEach(input => {
|
||||||
|
if (input.value === '' || (input.type === 'checkbox' && !input.checked)) {
|
||||||
|
validForNewRow = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
addRowButton.disabled = !validForNewRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to toggle the "Submit" button based on the validation of all rows
|
||||||
|
function toggleSubmitButton() {
|
||||||
|
const submitButton = repeater.querySelector('.lcp-repeater-submit');
|
||||||
|
const rows = repeater.querySelectorAll('.lcp-repeater-row');
|
||||||
|
|
||||||
|
let allValid = true;
|
||||||
|
|
||||||
|
rows.forEach(row => {
|
||||||
|
if (!isRequiredFieldsFilled(row)) {
|
||||||
|
allValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
submitButton.disabled = !allValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to handle form submission, ensuring all required fields are filled
|
||||||
|
function handleSubmit(event) {
|
||||||
|
const submitButton = event.target;
|
||||||
|
const actionType = submitButton.getAttribute('data-lcp-action'); // This will be used to pass data to the handler
|
||||||
|
const rows = repeater.querySelectorAll('.lcp-repeater-row');
|
||||||
|
let allValid = true;
|
||||||
|
|
||||||
|
rows.forEach(row => {
|
||||||
|
if (!isRequiredFieldsFilled(row)) {
|
||||||
|
allValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allValid) {
|
||||||
|
const repeaterData = [];
|
||||||
|
|
||||||
|
rows.forEach(function(row) {
|
||||||
|
const rowData = {};
|
||||||
|
const inputs = row.querySelectorAll('input');
|
||||||
|
|
||||||
|
inputs.forEach(function(input) {
|
||||||
|
const key = input.getAttribute('data-lcp-repeater-key');
|
||||||
|
let value;
|
||||||
|
|
||||||
|
if (input.type === 'checkbox') {
|
||||||
|
value = input.checked; // Boolean value for checkbox
|
||||||
|
} else {
|
||||||
|
value = input.value; // Text or number inputs
|
||||||
|
}
|
||||||
|
|
||||||
|
rowData[key] = value; // Add key-value pair to rowData
|
||||||
|
});
|
||||||
|
|
||||||
|
repeaterData.push(rowData); // Add rowData to the repeaterData array
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now just pass the data off to the handler
|
||||||
|
if (typeof window[actionType] === 'function') {
|
||||||
|
window[actionType](repeaterData); // Calls the function (e.g., `lcpUpdateImageSizes`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("Please fill in all required fields.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listener for adding a new row when a user clicks the "Add Row" button
|
||||||
|
const addRowButtons = repeater.querySelectorAll('.lcp-repeater-add-row');
|
||||||
|
addRowButtons.forEach(button => {
|
||||||
|
button.addEventListener('click', function() {
|
||||||
|
if (isRequiredFieldsFilled(firstRow)) {
|
||||||
|
addRepeaterRow();
|
||||||
|
} else {
|
||||||
|
alert('Please fill in the required fields to add a new row.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event listener for submitting the repeater form
|
||||||
|
const submitButton = repeater.querySelector('.lcp-repeater-submit');
|
||||||
|
submitButton.addEventListener('click', handleSubmit);
|
||||||
|
|
||||||
|
// Initial validation for the add row button
|
||||||
|
toggleAddRowButton();
|
||||||
|
|
||||||
|
// Initial validation for the submit button
|
||||||
|
toggleSubmitButton();
|
||||||
|
|
||||||
|
// Added event listeners to handle any changes in input and trigger validation
|
||||||
|
repeater.addEventListener('input', function() {
|
||||||
|
toggleAddRowButton(); // Revalidate Add Row button
|
||||||
|
toggleSubmitButton(); // Revalidate Submit button
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize each repeater on the page
|
||||||
|
const repeaters = document.querySelectorAll('.lcp-repeater');
|
||||||
|
repeaters.forEach(repeater => {
|
||||||
|
initRepeater(repeater);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
117
functions.php
117
functions.php
@ -575,3 +575,120 @@ function lcp_delete_demo_posts_ajax_handler() {
|
|||||||
// Send a success response back to the browser
|
// Send a success response back to the browser
|
||||||
wp_send_json_success('Demo posts deleted successfully.');
|
wp_send_json_success('Demo posts deleted successfully.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Set a visited post cookies
|
||||||
|
// Hooked into send_headers via wp-hooks.php
|
||||||
|
|
||||||
|
function lcp_set_visited_posts_cookie() {
|
||||||
|
// Only track posts on single post pages
|
||||||
|
if (is_single()) {
|
||||||
|
// Get the current post's ID and post type
|
||||||
|
$current_post_id = get_the_ID();
|
||||||
|
$post_type = get_post_type();
|
||||||
|
$visit_time = time(); // Get the current time as a Unix timestamp
|
||||||
|
|
||||||
|
// Check if the cookie exists
|
||||||
|
if (isset($_COOKIE['lcp_visited_posts'])) {
|
||||||
|
// Decode the cookie's JSON value
|
||||||
|
$visited_posts = json_decode(stripslashes($_COOKIE['lcp_visited_posts']), true);
|
||||||
|
|
||||||
|
// Check if decoding was successful and if the format is correct
|
||||||
|
if (json_last_error() !== JSON_ERROR_NONE || !is_array($visited_posts)) {
|
||||||
|
// If the cookie is not valid, delete the cookie and start over
|
||||||
|
setcookie('lcp_visited_posts', '', time() - 3600, '/'); // Expire the cookie
|
||||||
|
$visited_posts = []; // Initialize an empty array
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Initialize an empty array if the cookie doesn't exist
|
||||||
|
$visited_posts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the post type is not already in the cookie, initialize it as an empty array
|
||||||
|
if (!isset($visited_posts[$post_type])) {
|
||||||
|
$visited_posts[$post_type] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the current post ID and the visit timestamp as an array entry
|
||||||
|
// Ensure that the post ID isn't already added for this post type
|
||||||
|
$found = false;
|
||||||
|
foreach ($visited_posts[$post_type] as &$post) {
|
||||||
|
if (array_key_exists($current_post_id, $post)) {
|
||||||
|
$post[$current_post_id] = $visit_time; // Update the timestamp if post already exists
|
||||||
|
$found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If post wasn't found, add it as a new entry
|
||||||
|
if (!$found) {
|
||||||
|
$visited_posts[$post_type][] = [$current_post_id => $visit_time];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode the updated visited posts array to JSON
|
||||||
|
$cookie_value = json_encode($visited_posts);
|
||||||
|
|
||||||
|
// Set the cookie with a 30-day expiration time (this must be done before any output)
|
||||||
|
setcookie('lcp_visited_posts', $cookie_value, time() + (30 * 24 * 60 * 60), '/'); // '/' makes the cookie available across the whole site
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CUSTOM IMAGE SIZES */
|
||||||
|
function lcp_update_image_sizes() {
|
||||||
|
// Verify nonce for security
|
||||||
|
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'custom_image_sizes_nonce')) {
|
||||||
|
wp_send_json_error(array('message' => 'Nonce validation failed.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if image_sizes data is provided
|
||||||
|
if (isset($_POST['image_sizes'])) {
|
||||||
|
$image_sizes = json_decode(stripslashes($_POST['image_sizes']), true); // Decode JSON data
|
||||||
|
|
||||||
|
// Make sure that the image_sizes data is valid
|
||||||
|
if (!is_array($image_sizes)) {
|
||||||
|
wp_send_json_error(array('message' => 'Invalid image sizes data.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the data (e.g., update options)
|
||||||
|
update_option('lcp_image_sizes', $image_sizes);
|
||||||
|
|
||||||
|
// Return success message
|
||||||
|
wp_send_json_success(array('message' => 'Image sizes updated successfully.'));
|
||||||
|
} else {
|
||||||
|
wp_send_json_error(array('message' => 'No image sizes data received.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action('wp_ajax_update_lcp_theme_settings', 'lcp_update_image_sizes');
|
||||||
|
add_action('wp_ajax_nopriv_update_lcp_theme_settings', 'lcp_update_image_sizes');
|
||||||
|
|
||||||
|
function lcp_register_custom_image_sizes() {
|
||||||
|
// Retrieve the 'lcp_image_sizes' option, which is already unserialized by WordPress
|
||||||
|
$custom_image_sizes = get_option('lcp_image_sizes');
|
||||||
|
|
||||||
|
// Check if the option exists and is an array (because WordPress auto-unserializes the data)
|
||||||
|
if ($custom_image_sizes && is_array($custom_image_sizes)) {
|
||||||
|
// Loop through the array and register each image size
|
||||||
|
foreach ($custom_image_sizes as $size) {
|
||||||
|
// Ensure the size has the correct keys and valid values
|
||||||
|
if (isset($size['name'], $size['width'], $size['height'], $size['crop']) && !empty($size['name'])) {
|
||||||
|
// Sanitize the name, but ensure it's not just a number like '1'
|
||||||
|
$name = sanitize_key($size['name']);
|
||||||
|
$width = (int) $size['width']; // Cast to integer
|
||||||
|
$height = (int) $size['height']; // Cast to integer
|
||||||
|
$crop = (bool) $size['crop']; // Convert to boolean
|
||||||
|
|
||||||
|
// Register the custom image size
|
||||||
|
add_image_size($name, $width, $height, $crop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Hook into WordPress to register custom sizes
|
||||||
|
add_action('after_setup_theme', 'lcp_register_custom_image_sizes');
|
||||||
|
|||||||
@ -47,7 +47,16 @@ function lcp_custom_svgs_field() {
|
|||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function custom_image_size_settings_page() {
|
||||||
|
add_options_page(
|
||||||
|
'Custom Image Sizes', // Page title
|
||||||
|
'Custom Image Sizes', // Menu title
|
||||||
|
'manage_options', // Capability
|
||||||
|
'custom-image-sizes', // Menu slug
|
||||||
|
'display_custom_image_size_form' // Callback function to display the form
|
||||||
|
);
|
||||||
|
}
|
||||||
|
add_action('admin_menu', 'custom_image_size_settings_page');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -247,6 +256,7 @@ function render_lcp_theme_settings_page() {
|
|||||||
<li class="tab-link active" data-tab="custom-meta">Custom Meta</li>
|
<li class="tab-link active" data-tab="custom-meta">Custom Meta</li>
|
||||||
<li class="tab-link" data-tab="icons">Icons</li>
|
<li class="tab-link" data-tab="icons">Icons</li>
|
||||||
<li class="tab-link" data-tab="custom-code">Custom Code</li>
|
<li class="tab-link" data-tab="custom-code">Custom Code</li>
|
||||||
|
<li class="tab-link" data-tab="images">Images</li>
|
||||||
<li class="tab-link" data-tab="misc">Miscellaneous</li>
|
<li class="tab-link" data-tab="misc">Miscellaneous</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -302,6 +312,24 @@ function render_lcp_theme_settings_page() {
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="images" class="tab-pane">
|
||||||
|
<h3> Image Sizes </h3>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="lcp-repeater">
|
||||||
|
<div class="lcp-repeater-row">
|
||||||
|
<input data-lcp-repeater-key="name" placeholder="Enter Name">
|
||||||
|
<input type="number" data-lcp-repeater-key="width" data-lcp-required="true" placeholder="Enter Width (pixels)">
|
||||||
|
<input type="number" data-lcp-repeater-key="height" data-lcp-required-for-new-row="true" placeholder="Enter Height (pixels)">
|
||||||
|
<label for="crop-toggle">Crop</label>
|
||||||
|
<input type="checkbox" data-lcp-repeater-key="crop">
|
||||||
|
</div>
|
||||||
|
<button class="lcp-button lcp-repeater-add-row" id="add-repeater-row">Add Row</button>
|
||||||
|
<button class="lcp-button lcp-repeater-submit" data-lcp-action="lcpUpdateImageSizes"id="submit-repeater">Submit Repeater</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Misc Settings Tab -->
|
||||||
<div id="misc" class="tab-pane">
|
<div id="misc" class="tab-pane">
|
||||||
<!-- Misc Settings -->
|
<!-- Misc Settings -->
|
||||||
<h2>Miscellaneous Settings</h2>
|
<h2>Miscellaneous Settings</h2>
|
||||||
|
|||||||
@ -55,6 +55,31 @@ function lcp_backend_enqueue() {
|
|||||||
'ajax_url' => admin_url('admin-ajax.php'), // This is the URL that we’ll send the AJAX request to
|
'ajax_url' => admin_url('admin-ajax.php'), // This is the URL that we’ll send the AJAX request to
|
||||||
'nonce' => wp_create_nonce('lcp_import_demo_posts_nonce') // Security nonce for validation
|
'nonce' => wp_create_nonce('lcp_import_demo_posts_nonce') // Security nonce for validation
|
||||||
));
|
));
|
||||||
|
|
||||||
|
/* --- Image Sizes --- */
|
||||||
|
// Enqueue the JavaScript file
|
||||||
|
wp_enqueue_script('custom-image-sizes', get_template_directory_uri() . '/assets/js/custom-image-sizes.js', array(), null, true);
|
||||||
|
|
||||||
|
// Localize script to pass the nonce and ajaxurl to JavaScript
|
||||||
|
wp_localize_script('custom-image-sizes', 'customImageSizeAjax', array(
|
||||||
|
'ajax_url' => admin_url('admin-ajax.php'), // The URL to send the request to
|
||||||
|
'nonce' => wp_create_nonce('custom_image_sizes_nonce') // Create the nonce and pass it
|
||||||
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_action('admin_enqueue_scripts', 'lcp_backend_enqueue');
|
add_action('admin_enqueue_scripts', 'lcp_backend_enqueue');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function lcp_send_headers_hooks(){
|
||||||
|
lcp_set_visited_posts_cookie();
|
||||||
|
}
|
||||||
|
add_action('send_headers','lcp_send_headers_hooks');
|
||||||
|
|
||||||
|
|
||||||
|
function lcp_after_setup_theme() {
|
||||||
|
lcp_register_custom_image_sizes();
|
||||||
|
|
||||||
|
}
|
||||||
|
add_action('after_setup_theme', 'lcp_after_setup_theme');
|
||||||
@ -322,7 +322,7 @@ Version: 0.0.1
|
|||||||
|
|
||||||
|
|
||||||
#lcp-sidecontent {
|
#lcp-sidecontent {
|
||||||
overflow: scroll;
|
|
||||||
scrollbar-color: red orange;
|
scrollbar-color: red orange;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
border-radius:5px
|
border-radius:5px
|
||||||
|
|||||||
Reference in New Issue
Block a user