diff --git a/admin-modern.css b/admin-modern.css new file mode 100644 index 0000000..460a0bd --- /dev/null +++ b/admin-modern.css @@ -0,0 +1,437 @@ +/** + * Modern Admin Interface for cforms2 + * Responsive, accessible, and user-friendly design + */ + +/* Modern Color Palette */ +:root { + --cforms-primary: #0073aa; + --cforms-primary-hover: #005a87; + --cforms-secondary: #646970; + --cforms-success: #00a32a; + --cforms-warning: #dba617; + --cforms-error: #d63638; + --cforms-light: #f6f7f7; + --cforms-border: #c3c4c7; + --cforms-text: #1d2327; + --cforms-text-light: #646970; + --cforms-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + --cforms-shadow-hover: 0 2px 8px rgba(0, 0, 0, 0.15); + --cforms-radius: 4px; + --cforms-spacing: 16px; +} + +/* Modern Form Layout */ +.cforms-modern-admin { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + line-height: 1.6; + color: var(--cforms-text); +} + +/* Card-based Layout */ +.cforms-card { + background: #fff; + border: 1px solid var(--cforms-border); + border-radius: var(--cforms-radius); + box-shadow: var(--cforms-shadow); + margin-bottom: var(--cforms-spacing); + overflow: hidden; + transition: box-shadow 0.2s ease; +} + +.cforms-card:hover { + box-shadow: var(--cforms-shadow-hover); +} + +.cforms-card-header { + background: var(--cforms-light); + border-bottom: 1px solid var(--cforms-border); + padding: var(--cforms-spacing); + font-weight: 600; + display: flex; + align-items: center; + justify-content: space-between; +} + +.cforms-card-body { + padding: var(--cforms-spacing); +} + +/* Modern Form Controls */ +.cforms-form-group { + margin-bottom: var(--cforms-spacing); +} + +.cforms-label { + display: block; + font-weight: 600; + margin-bottom: 8px; + color: var(--cforms-text); +} + +.cforms-input, +.cforms-select, +.cforms-textarea { + width: 100%; + padding: 12px 16px; + border: 1px solid var(--cforms-border); + border-radius: var(--cforms-radius); + font-size: 14px; + line-height: 1.4; + transition: border-color 0.2s ease, box-shadow 0.2s ease; + background: #fff; +} + +.cforms-input:focus, +.cforms-select:focus, +.cforms-textarea:focus { + outline: none; + border-color: var(--cforms-primary); + box-shadow: 0 0 0 2px rgba(0, 115, 170, 0.1); +} + +/* Modern Buttons */ +.cforms-btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 12px 24px; + border: none; + border-radius: var(--cforms-radius); + font-size: 14px; + font-weight: 600; + text-decoration: none; + cursor: pointer; + transition: all 0.2s ease; + min-height: 44px; /* Touch-friendly */ + gap: 8px; +} + +.cforms-btn-primary { + background: var(--cforms-primary); + color: #fff; +} + +.cforms-btn-primary:hover { + background: var(--cforms-primary-hover); + transform: translateY(-1px); +} + +.cforms-btn-secondary { + background: #fff; + color: var(--cforms-secondary); + border: 1px solid var(--cforms-border); +} + +.cforms-btn-secondary:hover { + background: var(--cforms-light); + border-color: var(--cforms-secondary); +} + +.cforms-btn-success { + background: var(--cforms-success); + color: #fff; +} + +.cforms-btn-warning { + background: var(--cforms-warning); + color: #fff; +} + +.cforms-btn-error { + background: var(--cforms-error); + color: #fff; +} + +/* Modern Notifications */ +.cforms-notice { + padding: var(--cforms-spacing); + border-radius: var(--cforms-radius); + margin-bottom: var(--cforms-spacing); + display: flex; + align-items: flex-start; + gap: 12px; +} + +.cforms-notice-success { + background: #d7f3e3; + border-left: 4px solid var(--cforms-success); + color: #155724; +} + +.cforms-notice-warning { + background: #fff3cd; + border-left: 4px solid var(--cforms-warning); + color: #856404; +} + +.cforms-notice-error { + background: #f8d7da; + border-left: 4px solid var(--cforms-error); + color: #721c24; +} + +.cforms-notice-info { + background: #d1ecf1; + border-left: 4px solid var(--cforms-primary); + color: #0c5460; +} + +/* Modern Tables */ +.cforms-table { + width: 100%; + border-collapse: collapse; + background: #fff; + border-radius: var(--cforms-radius); + overflow: hidden; + box-shadow: var(--cforms-shadow); +} + +.cforms-table th, +.cforms-table td { + padding: 12px 16px; + text-align: left; + border-bottom: 1px solid var(--cforms-border); +} + +.cforms-table th { + background: var(--cforms-light); + font-weight: 600; + color: var(--cforms-text); +} + +.cforms-table tr:hover { + background: rgba(0, 115, 170, 0.05); +} + +/* Modern Tabs */ +.cforms-tabs { + border-bottom: 1px solid var(--cforms-border); + margin-bottom: var(--cforms-spacing); +} + +.cforms-tab-nav { + display: flex; + list-style: none; + margin: 0; + padding: 0; + gap: 4px; +} + +.cforms-tab-item { + padding: 12px 24px; + background: none; + border: none; + border-bottom: 3px solid transparent; + cursor: pointer; + font-weight: 500; + color: var(--cforms-text-light); + transition: all 0.2s ease; +} + +.cforms-tab-item:hover { + color: var(--cforms-text); + background: var(--cforms-light); +} + +.cforms-tab-item.active { + color: var(--cforms-primary); + border-bottom-color: var(--cforms-primary); +} + +/* Modern Toggle Switches */ +.cforms-toggle { + position: relative; + display: inline-block; + width: 50px; + height: 24px; +} + +.cforms-toggle input { + opacity: 0; + width: 0; + height: 0; +} + +.cforms-toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: var(--cforms-border); + transition: 0.3s; + border-radius: 24px; +} + +.cforms-toggle-slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 3px; + bottom: 3px; + background-color: white; + transition: 0.3s; + border-radius: 50%; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); +} + +.cforms-toggle input:checked + .cforms-toggle-slider { + background-color: var(--cforms-primary); +} + +.cforms-toggle input:checked + .cforms-toggle-slider:before { + transform: translateX(26px); +} + +/* Responsive Design */ +@media (max-width: 782px) { + .cforms-card-header { + flex-direction: column; + align-items: flex-start; + gap: 12px; + } + + .cforms-btn { + width: 100%; + justify-content: center; + } + + .cforms-tab-nav { + flex-wrap: wrap; + } + + .cforms-tab-item { + flex: 1; + text-align: center; + min-width: 120px; + } + + .cforms-table { + font-size: 14px; + } + + .cforms-table th, + .cforms-table td { + padding: 8px 12px; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + :root { + --cforms-text: #f0f0f1; + --cforms-text-light: #a7aaad; + --cforms-light: #2c3338; + --cforms-border: #3c434a; + } + + .cforms-card, + .cforms-input, + .cforms-select, + .cforms-textarea, + .cforms-table { + background: #1d2327; + color: var(--cforms-text); + } + + .cforms-btn-secondary { + background: #2c3338; + color: var(--cforms-text); + } +} + +/* Accessibility Improvements */ +.cforms-sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.cforms-focus-visible:focus-visible { + outline: 2px solid var(--cforms-primary); + outline-offset: 2px; +} + +/* Loading States */ +.cforms-loading { + position: relative; + pointer-events: none; + opacity: 0.7; +} + +.cforms-loading::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 20px; + height: 20px; + margin: -10px 0 0 -10px; + border: 2px solid var(--cforms-border); + border-top: 2px solid var(--cforms-primary); + border-radius: 50%; + animation: cforms-spin 1s linear infinite; +} + +@keyframes cforms-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Modern Form Field Groups */ +.cforms-field-group { + display: grid; + gap: var(--cforms-spacing); + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); +} + +.cforms-field-group.cforms-field-group-2 { + grid-template-columns: repeat(2, 1fr); +} + +.cforms-field-group.cforms-field-group-3 { + grid-template-columns: repeat(3, 1fr); +} + +@media (max-width: 782px) { + .cforms-field-group, + .cforms-field-group.cforms-field-group-2, + .cforms-field-group.cforms-field-group-3 { + grid-template-columns: 1fr; + } +} + +/* Modern Help Text */ +.cforms-help-text { + font-size: 13px; + color: var(--cforms-text-light); + margin-top: 4px; + line-height: 1.4; +} + +/* Modern Icons */ +.cforms-icon { + width: 20px; + height: 20px; + fill: currentColor; + vertical-align: middle; +} + +.cforms-icon-small { + width: 16px; + height: 16px; +} + +.cforms-icon-large { + width: 24px; + height: 24px; +} diff --git a/blocks/cforms-block.js b/blocks/cforms-block.js new file mode 100644 index 0000000..25a1c93 --- /dev/null +++ b/blocks/cforms-block.js @@ -0,0 +1,148 @@ +/** + * cforms2 Gutenberg Block + * Modern block editor integration for cforms2 + */ + +const { registerBlockType } = wp.blocks; +const { SelectControl } = wp.components; +const { useSelect } = wp.data; +const { __ } = wp.i18n; + +registerBlockType('cforms2/form', { + title: __('cforms2 Form', 'cforms2'), + description: __('Insert a cforms2 contact form', 'cforms2'), + category: 'widgets', + icon: 'feedback', + keywords: [ + __('form', 'cforms2'), + __('contact', 'cforms2'), + __('cforms', 'cforms2') + ], + attributes: { + formId: { + type: 'string', + default: '1' + }, + formName: { + type: 'string', + default: '' + } + }, + supports: { + html: false, + customClassName: false + }, + + edit: function(props) { + const { attributes, setAttributes } = props; + const { formId, formName } = attributes; + + // Get available forms from cforms2 settings + const forms = useSelect((select) => { + // This would need to be populated via REST API or localized script + return window.cforms2_forms || [ + { id: '1', name: 'Contact Form' }, + { id: '2', name: 'Newsletter Signup' } + ]; + }, []); + + const formOptions = forms.map(form => ({ + label: form.name, + value: form.id + })); + + return wp.element.createElement( + 'div', + { className: 'cforms2-block-editor' }, + [ + wp.element.createElement( + 'div', + { + key: 'icon', + className: 'cforms2-block-icon', + style: { + textAlign: 'center', + padding: '20px', + border: '2px dashed #ccc', + borderRadius: '4px', + backgroundColor: '#f9f9f9' + } + }, + [ + wp.element.createElement( + 'span', + { + key: 'dashicon', + className: 'dashicons dashicons-feedback', + style: { fontSize: '48px', color: '#666' } + } + ), + wp.element.createElement( + 'h3', + { key: 'title' }, + __('cforms2 Form', 'cforms2') + ) + ] + ), + wp.element.createElement( + SelectControl, + { + key: 'select', + label: __('Select Form', 'cforms2'), + value: formId, + options: [ + { label: __('Choose a form...', 'cforms2'), value: '' }, + ...formOptions + ], + onChange: (newFormId) => { + const selectedForm = forms.find(form => form.id === newFormId); + setAttributes({ + formId: newFormId, + formName: selectedForm ? selectedForm.name : '' + }); + } + } + ), + formId && wp.element.createElement( + 'div', + { + key: 'preview', + className: 'cforms2-block-preview', + style: { + marginTop: '15px', + padding: '15px', + backgroundColor: '#e8f4fd', + border: '1px solid #0073aa', + borderRadius: '4px' + } + }, + [ + wp.element.createElement( + 'strong', + { key: 'preview-label' }, + __('Form Preview:', 'cforms2') + ), + wp.element.createElement( + 'p', + { key: 'preview-text' }, + __('Form ID:', 'cforms2') + ' ' + formId + (formName ? ' (' + formName + ')' : '') + ), + wp.element.createElement( + 'p', + { + key: 'preview-note', + style: { fontSize: '12px', color: '#666' } + }, + __('The actual form will be displayed on the frontend.', 'cforms2') + ) + ] + ) + ] + ); + }, + + save: function() { + // Return null for server-side rendering + return null; + } +}); diff --git a/cforms.php b/cforms.php index 48db821..1ea4510 100644 --- a/cforms.php +++ b/cforms.php @@ -20,13 +20,13 @@ * Plugin URI: https://wordpress.org/plugins/cforms2/ * Description: cformsII is a customizable, flexible and powerful form plugin including simple spam protection, multi-step forms, role manager support and custom themes. * Author: Oliver Seidel - * Version: 15.1.4 + * Version: 16.0.0 * Requires at least: 6.9 * Text Domain: cforms2 */ namespace Cforms2; -define('CFORMS2_VERSION', '15.1.4'); +define('CFORMS2_VERSION', '16.0.0'); // Debug message handling. if (!defined('WP_DEBUG_CFORMS2')) { @@ -55,6 +55,7 @@ require_once plugin_dir_path(__FILE__) . 'lib_activate.php'; require_once plugin_dir_path(__FILE__) . 'lib_ajax.php'; require_once plugin_dir_path(__FILE__) . 'lib_aux.php'; +require_once plugin_dir_path(__FILE__) . 'lib_blocks.php'; require_once plugin_dir_path(__FILE__) . 'lib_functions.php'; require_once plugin_dir_path(__FILE__) . 'lib_render.php'; require_once plugin_dir_path(__FILE__) . 'lib_validate.php'; @@ -96,8 +97,8 @@ } } -// Attaching to hooks. -add_action('template_redirect', 'cforms2_start_session'); +// Attaching to hooks - optimized session handling. +add_action('template_redirect', 'cforms2_conditional_start_session'); add_action('wp_ajax_submitcform', 'cforms2_submitcform'); add_action('wp_ajax_nopriv_submitcform', 'cforms2_submitcform'); add_action('plugins_loaded', function() { diff --git a/js/cforms.js b/js/cforms.js index 7c82b34..32c67b8 100644 --- a/js/cforms.js +++ b/js/cforms.js @@ -182,13 +182,24 @@ function cforms_validate(no, directFormSubmission) { var post_data = 'action=submitcform&_wpnonce=' + cforms2_ajax.nonces['submitcform'] + '&cforms_id=' + no + '&' + params; - jQuery.post( - cforms2_ajax.url, - post_data, - function (data) { + jQuery.ajax({ + url: cforms2_ajax.url, + type: 'POST', + data: post_data, + dataType: 'json', + success: function(data) { + if (data && typeof data === 'object' && data.no !== undefined) { cforms_setsuccessmessage(data); + } else { + // Invalid response format - use configured failure message + call_err(no, document.getElementById('cf_failure' + no).value, ''); } - ); + }, + error: function(jqXHR, textStatus, errorThrown) { + // Handle AJAX errors - use configured failure message + call_err(no, document.getElementById('cf_failure' + no).value, ''); + } + }); }; var cforms_setsuccessmessage = function (message) { diff --git a/lib_ajax.php b/lib_ajax.php index 9548189..315dbd8 100644 --- a/lib_ajax.php +++ b/lib_ajax.php @@ -17,6 +17,11 @@ */ function cforms2_json_die($no, $result, $html, $hide = false, $redirection = null) { + // Clear any previous output to ensure clean JSON + if (ob_get_length()) { + ob_clean(); + } + header('Content-Type: application/json'); echo json_encode(array( 'no' => $no, diff --git a/lib_blocks.php b/lib_blocks.php new file mode 100644 index 0000000..611e4e8 --- /dev/null +++ b/lib_blocks.php @@ -0,0 +1,159 @@ +. + */ + +/** + * Gutenberg Block Integration for cforms2 + * Provides modern block editor support + */ + +/** + * Register cforms2 Gutenberg block + */ +function cforms2_register_gutenberg_block() { + // Check if Gutenberg is available + if (!function_exists('register_block_type')) { + return; + } + + // Register block script + wp_register_script( + 'cforms2-block', + plugin_dir_url(__FILE__) . 'blocks/cforms-block.js', + array( + 'wp-blocks', + 'wp-components', + 'wp-data', + 'wp-element', + 'wp-i18n' + ), + CFORMS2_VERSION, + true + ); + + // Localize script with available forms + $forms = cforms2_get_available_forms_for_block(); + wp_localize_script('cforms2-block', 'cforms2_forms', $forms); + + // Register block type + register_block_type('cforms2/form', array( + 'editor_script' => 'cforms2-block', + 'render_callback' => 'cforms2_render_block', + 'attributes' => array( + 'formId' => array( + 'type' => 'string', + 'default' => '1' + ), + 'formName' => array( + 'type' => 'string', + 'default' => '' + ) + ) + )); +} + +/** + * Get available forms for block editor + */ +function cforms2_get_available_forms_for_block() { + $forms = array(); + + try { + $form_settings = Cforms2\FormSettings::forms(); + + foreach ($form_settings as $form_id => $form) { + $id = $form_id === '' ? '1' : $form_id; + $forms[] = array( + 'id' => $id, + 'name' => $form->name() ?: sprintf(__('Form %s', 'cforms2'), $id) + ); + } + } catch (Exception $e) { + // Fallback if forms can't be loaded + $forms[] = array( + 'id' => '1', + 'name' => __('Default Form', 'cforms2') + ); + } + + return $forms; +} + +/** + * Render cforms2 block on frontend + */ +function cforms2_render_block($attributes) { + $form_id = isset($attributes['formId']) ? sanitize_text_field($attributes['formId']) : '1'; + + // Validate form ID + if (!cforms2_form_exists($form_id)) { + return '
' . + sprintf(__('cforms2: Form with ID "%s" not found.', 'cforms2'), esc_html($form_id)) . + '
'; + } + + // Use existing cforms2 shortcode functionality + return cforms2_shortcode(array('name' => $form_id)); +} + +/** + * Check if a form exists + */ +function cforms2_form_exists($form_id) { + try { + $form = Cforms2\FormSettings::form($form_id); + return $form !== null; + } catch (Exception $e) { + return false; + } +} + +/** + * Add block category for cforms2 + */ +function cforms2_add_block_category($categories, $post) { + return array_merge( + $categories, + array( + array( + 'slug' => 'cforms2', + 'title' => __('cforms2', 'cforms2'), + 'icon' => 'feedback' + ) + ) + ); +} + +/** + * Initialize Gutenberg integration + */ +function cforms2_init_gutenberg() { + // Only load in admin and if Gutenberg is available + if (!is_admin() || !function_exists('register_block_type')) { + return; + } + + add_action('init', 'cforms2_register_gutenberg_block'); + + // Add custom block category (WordPress 5.8+) + if (version_compare(get_bloginfo('version'), '5.8', '>=')) { + add_filter('block_categories_all', 'cforms2_add_block_category', 10, 2); + } else { + add_filter('block_categories', 'cforms2_add_block_category', 10, 2); + } +} + +// Initialize Gutenberg integration +cforms2_init_gutenberg(); diff --git a/lib_functions.php b/lib_functions.php index 042c186..36ebeed 100644 --- a/lib_functions.php +++ b/lib_functions.php @@ -35,7 +35,36 @@ function cforms2_start_session() { session_start(); } } +} +/** + * Optimized session handling - only start sessions when cforms is actually used + * Improves performance by avoiding unnecessary session starts on all pages + */ +function cforms2_conditional_start_session() { + global $post; + + // Check if current page/post contains cforms shortcode + $needs_session = false; + + if ($post && has_shortcode($post->post_content, 'cforms')) { + $needs_session = true; + } + + // Check for multi-part forms or AJAX submissions + if (isset($_POST['cforms_form']) || isset($_GET['cforms_form'])) { + $needs_session = true; + } + + // Check for widget usage (simplified check) + if (is_active_widget(false, false, 'cforms2_widget')) { + $needs_session = true; + } + + // Only start session if actually needed + if ($needs_session) { + cforms2_start_session(); + } } function cforms2_field() { @@ -81,27 +110,65 @@ function cforms2_check_access_priv() { } -/** some css for positioning the form elements */ +/** + * Optimized asset loading - only load CSS/JS when cforms is actually used + * Improves performance by avoiding unnecessary asset loading on all pages + */ function cforms2_enqueue_scripts() { - global $wp_query; + global $wp_query, $post; $cformsSettings = get_option('cforms_settings'); - - // add content actions and filters $page_obj = $wp_query->get_queried_object(); + // Check if cforms should be loaded on this page $exclude = ($cformsSettings['global']['cforms_inexclude']['ex'] == '1'); $onPages = str_replace(' ', '', stripslashes(htmlspecialchars($cformsSettings['global']['cforms_inexclude']['ids']))); $onPagesA = explode(',', $onPages); - if ($onPages == '' || ($page_obj instanceof WP_POST && in_array($page_obj->ID, $onPagesA) && !$exclude) || ($page_obj instanceof WP_POST && !in_array($page_obj->ID, $onPagesA) && $exclude)) { + $page_allowed = ($onPages == '' || + ($page_obj instanceof WP_POST && in_array($page_obj->ID, $onPagesA) && !$exclude) || + ($page_obj instanceof WP_POST && !in_array($page_obj->ID, $onPagesA) && $exclude)); + if (!$page_allowed) { + return; + } + + // Check if cforms is actually needed on this page + $needs_cforms = false; + + // Check for shortcode in post content + if ($post && has_shortcode($post->post_content, 'cforms')) { + $needs_cforms = true; + } + + // Check for widget usage + if (is_active_widget(false, false, 'cforms2_widget')) { + $needs_cforms = true; + } + + // Check for form submissions or AJAX calls + if (isset($_POST['cforms_form']) || isset($_GET['cforms_form']) || + (defined('DOING_AJAX') && DOING_AJAX && isset($_POST['action']) && $_POST['action'] === 'submitcform')) { + $needs_cforms = true; + } + + // Only load assets if cforms is actually needed + if ($needs_cforms) { + // Load CSS if ($cformsSettings['global']['cforms_css']) { wp_register_style('cforms2', plugin_dir_url(__FILE__) . 'styling/' . $cformsSettings['global']['cforms_css'], array(), CFORMS2_VERSION); wp_enqueue_style('cforms2'); } + + // Load modern admin styles in admin area + if (is_admin()) { + wp_enqueue_style('cforms2-admin-modern', plugin_dir_url(__FILE__) . 'admin-modern.css', array(), CFORMS2_VERSION); + } + + // Frontend mobile styles removed per user request - only admin changes wanted - wp_register_script('cforms2', plugin_dir_url(__FILE__) . 'js/cforms.js', array('jquery'), CFORMS2_VERSION); + // Load JavaScript + wp_register_script('cforms2', plugin_dir_url(__FILE__) . 'js/cforms.js', array('jquery'), CFORMS2_VERSION, true); wp_localize_script('cforms2', 'cforms2_ajax', array( 'url' => admin_url('admin-ajax.php'), 'nonces' => array( @@ -110,7 +177,6 @@ function cforms2_enqueue_scripts() { )); wp_enqueue_script('cforms2'); } - } /** add cforms menu */ @@ -142,6 +208,9 @@ function cforms2_get_request_uri() { function cforms2_enqueue_style_admin() { wp_register_style('cforms-admin', plugin_dir_url(__FILE__) . 'cforms-admin.css', false, CFORMS2_VERSION); wp_enqueue_style('cforms-admin'); + + // Always load modern admin styles for cforms admin pages + wp_enqueue_style('cforms2-admin-modern', plugin_dir_url(__FILE__) . 'admin-modern.css', array('cforms-admin'), CFORMS2_VERSION); } @@ -163,6 +232,12 @@ function cforms2_admin_enqueue_scripts() { wp_enqueue_script('cforms-admin'); cforms2_enqueue_style_admin(); + + // Always load modern admin styles in admin area + wp_enqueue_style('cforms2-admin-modern', plugin_dir_url(__FILE__) . 'admin-modern.css', array(), CFORMS2_VERSION); + + // Load mobile admin styles only for actual mobile devices + wp_enqueue_style('cforms2-mobile-admin', plugin_dir_url(__FILE__) . 'mobile-admin.css', array('cforms2-admin-modern'), CFORMS2_VERSION); } diff --git a/lib_render.php b/lib_render.php index e384d37..90f858a 100644 --- a/lib_render.php +++ b/lib_render.php @@ -113,6 +113,15 @@ function cforms2($no = '', $customfields = array()) { } } + // Check time constraints BEFORE creating any HTML elements + // This prevents creating message boxes for forms that won't be displayed + if (!cforms2_check_time($no)) { + if (isset($validation_result['limit_reached']) && $validation_result['limit_reached']) + return stripslashes($cformsSettings['form' . $no]['cforms' . $no . '_limittxt']); + else + return stripslashes($cformsSettings['form' . $no]['cforms' . $no . '_limittxt']); + } + // paint form $success = false; @@ -166,13 +175,6 @@ function cforms2($no = '', $customfields = array()) { ) ) return $content; - elseif (!cforms2_check_time($no)) { - - if ($validation_result['limit_reached']) - return stripslashes($cformsSettings['form' . $no]['cforms' . $no . '_limittxt']); - else - return $content . stripslashes($cformsSettings['form' . $no]['cforms' . $no . '_limittxt']); - } diff --git a/mobile-admin.css b/mobile-admin.css new file mode 100644 index 0000000..b484d3f --- /dev/null +++ b/mobile-admin.css @@ -0,0 +1,159 @@ +/** + * Mobile Admin Styles for cforms2 + * Only optimize form navigation, leave table as desktop version + */ + +/* Apply on narrow screens (including desktop browser testing) */ +@media (max-width: 782px) { + /* Form Navigation - Mobile optimized (keep the good version) */ + .chgformbox { + display: block !important; + width: 100% !important; + background-color: #f8f9fa !important; + border-radius: 8px !important; + padding: 12px !important; + margin-bottom: 16px !important; + box-shadow: 0 1px 3px rgba(0,0,0,0.1) !important; + } + + .chgformbox td { + display: block !important; + width: 100% !important; + padding: 0 !important; + } + + .chgformbox .chgL { + margin-bottom: 12px !important; + text-align: center !important; + } + + .chgformbox .chgL select { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 10px !important; + border-radius: 6px !important; + border: 1px solid #ddd !important; + margin-bottom: 8px !important; + } + + .chgformbox .chgL .go { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 10px 16px !important; + border-radius: 6px !important; + background-color: #0073aa !important; + color: white !important; + border: none !important; + } + + .chgformbox .chgM { + text-align: center !important; + margin-top: 12px !important; + } + + .chgformbox .chgM input { + margin: 4px 2px !important; + min-width: 44px !important; + min-height: 44px !important; + padding: 8px !important; + font-size: 14px !important; + border-radius: 6px !important; + border: 1px solid #ddd !important; + background-color: white !important; + } + + .chgformbox .chgM input.chgbuttonhi { + background-color: #0073aa !important; + color: white !important; + border-color: #0073aa !important; + } + + /* Leave the table area completely alone - no changes */ + /* Users can zoom in/out or rotate device to see full table */ + + /* Just add a helpful message */ + .cf-content::before { + content: "💡 Tipp: Gerät drehen (Querformat) oder herauszoomen für vollständige Tabelle" !important; + display: block !important; + background: #e7f3ff !important; + border: 1px solid #b3d9ff !important; + padding: 12px !important; + text-align: center !important; + font-size: 14px !important; + margin-bottom: 12px !important; + border-radius: 6px !important; + color: #0066cc !important; + font-weight: normal !important; + } + + /* Action buttons - make them smaller but keep functionality */ + #cf_actions { + position: sticky !important; + bottom: 0 !important; + background-color: white !important; + border-top: 1px solid #ddd !important; + padding: 8px !important; + z-index: 100 !important; + width: 100% !important; + box-sizing: border-box !important; + } + + #cf_actions input { + margin: 2px !important; + font-size: 12px !important; + padding: 6px 8px !important; + } + + /* Form options - force all tables to full width */ + .form-table, + table.form-table, + .cformsoptions table, + .cf-content table { + width: 100% !important; + max-width: 100% !important; + table-layout: fixed !important; + box-sizing: border-box !important; + } + + /* Force table rows and cells to full width */ + .form-table tr, + .form-table td, + .form-table th { + width: 100% !important; + display: block !important; + box-sizing: border-box !important; + } + + /* Left align field labels */ + .form-table .obL, + .form-table th { + text-align: left !important; + font-weight: bold !important; + margin-bottom: 8px !important; + } + + /* Full width form inputs */ + .form-table input[type="text"], + .form-table input[type="email"], + .form-table input[type="url"], + .form-table input[type="number"], + .form-table input[type="date"], + .form-table input[type="time"], + .form-table select, + .form-table textarea { + width: 100% !important; + max-width: 100% !important; + box-sizing: border-box !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 12px !important; + } + + /* Specific textarea styling */ + .form-table textarea { + min-height: 120px !important; + resize: vertical !important; + } +} diff --git a/mobile-responsive.css b/mobile-responsive.css new file mode 100644 index 0000000..f7fe285 --- /dev/null +++ b/mobile-responsive.css @@ -0,0 +1,995 @@ +/** + * Mobile Responsive Styles for cforms2 + * Optimized for all device sizes and touch interfaces + * Includes both frontend forms and admin interface + */ + +/* ========================================================================== + ADMIN INTERFACE MOBILE OPTIMIZATIONS + ========================================================================== */ + +/* Mobile Admin Layout - For narrow screens */ +@media (max-width: 782px) { + /* Form Navigation - Complete mobile redesign */ + .chgformbox { + display: block !important; + width: 100% !important; + background-color: #f8f9fa !important; + border-radius: 12px !important; + padding: 16px !important; + margin-bottom: 20px !important; + box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; + } + + .chgformbox td { + display: block !important; + width: 100% !important; + padding: 0 !important; + } + + .chgformbox .chgL { + margin-bottom: 16px !important; + text-align: center !important; + } + + .chgformbox .chgL label { + display: block !important; + font-size: 16px !important; + font-weight: bold !important; + margin-bottom: 8px !important; + color: #333 !important; + } + + .chgformbox .chgL select { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 12px !important; + border-radius: 8px !important; + border: 2px solid #ddd !important; + background-color: white !important; + margin-bottom: 12px !important; + } + + .chgformbox .chgL .go { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + font-weight: bold !important; + padding: 12px 20px !important; + border-radius: 8px !important; + background-color: #0073aa !important; + color: white !important; + border: none !important; + cursor: pointer !important; + } + + .chgformbox .chgM { + text-align: center !important; + margin-top: 16px !important; + } + + .chgformbox .chgM input { + margin: 6px 4px !important; + min-width: 48px !important; + min-height: 48px !important; + padding: 12px !important; + font-size: 16px !important; + font-weight: bold !important; + border-radius: 8px !important; + border: 2px solid #ddd !important; + background-color: white !important; + cursor: pointer !important; + transition: all 0.2s ease !important; + } + + .chgformbox .chgM input.chgbuttonhi { + background-color: #0073aa !important; + color: white !important; + border-color: #0073aa !important; + } + + .chgformbox .chgM input:hover { + background-color: #f0f0f0 !important; + border-color: #0073aa !important; + } + + .chgformbox .chgM input.chgbuttonhi:hover { + background-color: #005a87 !important; + } + + /* Form Fields Table - Complete mobile redesign */ + .groupWrapper { + width: 100% !important; + overflow: visible !important; + padding: 0 !important; + } + + .groupItem { + width: 100% !important; + min-width: unset !important; + max-width: 100% !important; + margin-bottom: 20px !important; + padding: 16px !important; + border-radius: 12px !important; + box-shadow: 0 4px 8px rgba(0,0,0,0.1) !important; + background-color: white !important; + border: 1px solid #e0e0e0 !important; + box-sizing: border-box !important; + } + + .itemContent { + display: block !important; + width: 100% !important; + } + + .itemHeader { + display: block !important; + font-size: 20px !important; + font-weight: bold !important; + text-align: center !important; + padding: 12px !important; + background-color: #0073aa !important; + color: white !important; + border-radius: 8px !important; + margin-bottom: 16px !important; + } + + /* Mobile Field Layout - Stack everything vertically */ + .itemContent > * { + display: block !important; + width: 100% !important; + margin-bottom: 12px !important; + box-sizing: border-box !important; + } + + /* Field Controls Container */ + .mobile-field-controls { + display: flex !important; + flex-wrap: wrap !important; + gap: 8px !important; + justify-content: center !important; + margin-top: 12px !important; + } + + /* Field Name Input */ + .inpfld { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 12px !important; + border-radius: 6px !important; + border: 2px solid #ddd !important; + } + + /* Field Type Dropdown */ + .selfld { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 12px !important; + border-radius: 6px !important; + border: 2px solid #ddd !important; + -webkit-appearance: none !important; + appearance: none !important; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M10.293 3.293L6 7.586 1.707 3.293A1 1 0 00.293 4.707l5 5a1 1 0 001.414 0l5-5a1 1 0 10-1.414-1.414z'/%3E%3C/svg%3E") !important; + background-repeat: no-repeat !important; + background-position: right 12px center !important; + padding-right: 40px !important; + } + + /* Checkboxes - Make them bigger and touch-friendly */ + .chkfld { + width: 24px !important; + height: 24px !important; + margin: 8px !important; + -webkit-appearance: none !important; + appearance: none !important; + border: 2px solid #ddd !important; + border-radius: 4px !important; + position: relative !important; + cursor: pointer !important; + } + + .chkfld:checked { + background-color: #0073aa !important; + border-color: #0073aa !important; + } + + .chkfld:checked::after { + content: '✓' !important; + position: absolute !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; + color: white !important; + font-size: 16px !important; + font-weight: bold !important; + } + + /* Delete Button */ + .xbutton, .noxbutton { + min-width: 44px !important; + min-height: 44px !important; + font-size: 18px !important; + padding: 8px !important; + border-radius: 6px !important; + background-color: #dc3545 !important; + color: white !important; + border: none !important; + cursor: pointer !important; + } + + /* Edit Button */ + .cf_editbox_button { + min-width: 44px !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 8px !important; + border-radius: 6px !important; + background-color: #0073aa !important; + color: white !important; + border: none !important; + cursor: pointer !important; + } + + /* Add Field Section */ + .addfieldbox { + display: flex !important; + flex-direction: column !important; + gap: 12px !important; + padding: 16px !important; + background-color: #f9f9f9 !important; + border-radius: 8px !important; + margin: 16px 0 !important; + } + + .addfieldbox input, + .addfieldbox select { + min-height: 44px !important; + font-size: 16px !important; + padding: 12px !important; + border-radius: 6px !important; + border: 2px solid #ddd !important; + width: 100% !important; + } + + .addbutton { + background-color: #00a32a !important; + color: white !important; + font-weight: bold !important; + border: none !important; + cursor: pointer !important; + } + + /* Form Options Tables - Force full width on mobile */ + .form-table { + display: table !important; + width: 100% !important; + max-width: 100% !important; + table-layout: fixed !important; + box-sizing: border-box !important; + } + + /* Ensure all tables in form options are full width */ + .cformsoptions table, + .cf-content table, + table.form-table { + width: 100% !important; + max-width: 100% !important; + table-layout: fixed !important; + box-sizing: border-box !important; + } + + /* Force table cells to use full width */ + .form-table td, + .form-table th { + width: auto !important; + max-width: none !important; + box-sizing: border-box !important; + } + + .form-table tr { + display: block !important; + margin-bottom: 16px !important; + padding: 12px !important; + background-color: #f9f9f9 !important; + border-radius: 8px !important; + } + + .form-table td { + display: block !important; + width: 100% !important; + padding: 8px 0 !important; + } + + .form-table .obL { + font-weight: bold !important; + margin-bottom: 8px !important; + } + + .form-table .obR { + width: 100% !important; + } + + .form-table input[type="text"], + .form-table input[type="email"], + .form-table input[type="url"], + .form-table input[type="number"], + .form-table input[type="date"], + .form-table input[type="time"], + .form-table select, + .form-table textarea { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 12px !important; + border-radius: 6px !important; + border: 2px solid #ddd !important; + box-sizing: border-box !important; + } + + .form-table textarea { + min-height: 120px !important; + resize: vertical !important; + width: 100% !important; + max-width: 100% !important; + font-size: 16px !important; + padding: 12px !important; + line-height: 1.4 !important; + } + + /* Action Buttons */ + #cf_actions { + display: flex !important; + flex-direction: column !important; + gap: 12px !important; + padding: 16px !important; + position: sticky !important; + bottom: 0 !important; + background-color: white !important; + border-top: 2px solid #ddd !important; + margin-top: 24px !important; + } + + #cf_actions input { + min-height: 48px !important; + font-size: 16px !important; + font-weight: bold !important; + padding: 14px 20px !important; + border-radius: 8px !important; + border: none !important; + cursor: pointer !important; + width: 100% !important; + } + + #cfbar-SubmitOptions { + background-color: #0073aa !important; + color: white !important; + order: -1 !important; + } + + #cfbar-addbutton { + background-color: #00a32a !important; + color: white !important; + } + + #cfbar-dupbutton { + background-color: #f0ad4e !important; + color: white !important; + } + + #cfbar-delbutton { + background-color: #dc3545 !important; + color: white !important; + } + + /* Fieldsets */ + .cformsoptions { + margin-bottom: 24px !important; + border-radius: 8px !important; + overflow: hidden !important; + } + + .cflegend { + padding: 16px !important; + font-size: 18px !important; + font-weight: bold !important; + background-color: #0073aa !important; + color: white !important; + margin: 0 !important; + cursor: pointer !important; + } + + .cf-content { + padding: 16px !important; + } + + /* Table Header for Field List */ + .tableheader { + display: none !important; /* Hide complex header on mobile */ + } + + /* Warning Message */ + #cformswarning { + display: block !important; + padding: 12px !important; + background-color: #fff3cd !important; + border: 1px solid #ffeaa7 !important; + border-radius: 6px !important; + margin-bottom: 16px !important; + font-size: 14px !important; + } + + /* Modern Card Layout */ + .cforms-card { + margin: 0 !important; + border-radius: 0 !important; + box-shadow: none !important; + } + + .cforms-card-header { + padding: 16px !important; + background-color: #0073aa !important; + color: white !important; + } + + .cforms-card-body { + padding: 16px !important; + } + + /* Main Options Table */ + .mainoptions { + display: block !important; + width: 100% !important; + margin-bottom: 24px !important; + } + + .mainoptions td { + display: block !important; + width: 100% !important; + padding: 8px 0 !important; + } + + .cforms_fname { + width: 100% !important; + min-height: 44px !important; + font-size: 16px !important; + padding: 12px !important; + border-radius: 6px !important; + border: 2px solid #ddd !important; + margin-bottom: 12px !important; + } + + .cforms_ajax { + width: 20px !important; + height: 20px !important; + margin-right: 8px !important; + } +} + +/* Tablet Specific Admin Styles */ +@media (min-width: 783px) and (max-width: 1024px) { + .groupItem { + padding: 16px !important; + } + + .itemContent { + display: grid !important; + grid-template-columns: 40px 1fr 150px 40px 40px 40px 40px 40px 40px !important; + gap: 12px !important; + align-items: center !important; + } + + .inpfld { + min-height: 40px !important; + } + + .selfld { + min-height: 40px !important; + } +} + +/* ========================================================================== + FRONTEND FORM MOBILE OPTIMIZATIONS + ========================================================================== */ + +/* Mobile-First Approach */ +.cforms-responsive { + box-sizing: border-box; +} + +.cforms-responsive *, +.cforms-responsive *::before, +.cforms-responsive *::after { + box-sizing: inherit; +} + +/* Base Mobile Styles */ +.cforms-form { + width: 100%; + max-width: none; + margin: 0; + padding: 16px; +} + +/* Touch-Friendly Form Elements */ +.cforms-form input[type="text"], +.cforms-form input[type="email"], +.cforms-form input[type="tel"], +.cforms-form input[type="url"], +.cforms-form input[type="password"], +.cforms-form input[type="number"], +.cforms-form input[type="date"], +.cforms-form input[type="time"], +.cforms-form input[type="datetime-local"], +.cforms-form select, +.cforms-form textarea { + min-height: 44px; /* iOS minimum touch target */ + padding: 12px 16px; + font-size: 16px; /* Prevents zoom on iOS */ + border-radius: 8px; + border: 2px solid #ddd; + width: 100%; + -webkit-appearance: none; + appearance: none; + transition: border-color 0.3s ease, box-shadow 0.3s ease; +} + +.cforms-form input:focus, +.cforms-form select:focus, +.cforms-form textarea:focus { + border-color: #0073aa; + box-shadow: 0 0 0 3px rgba(0, 115, 170, 0.1); + outline: none; +} + +/* Touch-Friendly Buttons */ +.cforms-form input[type="submit"], +.cforms-form button, +.cforms-btn { + min-height: 48px; + padding: 14px 24px; + font-size: 16px; + font-weight: 600; + border-radius: 8px; + border: none; + cursor: pointer; + width: 100%; + margin-top: 16px; + transition: all 0.3s ease; + -webkit-tap-highlight-color: transparent; +} + +.cforms-form input[type="submit"]:active, +.cforms-form button:active, +.cforms-btn:active { + transform: scale(0.98); +} + +/* Checkbox and Radio Improvements */ +.cforms-form input[type="checkbox"], +.cforms-form input[type="radio"] { + width: 20px; + height: 20px; + margin-right: 12px; + vertical-align: middle; + -webkit-appearance: none; + appearance: none; + border: 2px solid #ddd; + border-radius: 4px; + position: relative; + cursor: pointer; +} + +.cforms-form input[type="radio"] { + border-radius: 50%; +} + +.cforms-form input[type="checkbox"]:checked, +.cforms-form input[type="radio"]:checked { + background-color: #0073aa; + border-color: #0073aa; +} + +.cforms-form input[type="checkbox"]:checked::after { + content: '✓'; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + font-size: 14px; + font-weight: bold; +} + +.cforms-form input[type="radio"]:checked::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 8px; + height: 8px; + border-radius: 50%; + background-color: white; +} + +/* Form Labels */ +.cforms-form label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: #333; + font-size: 16px; + line-height: 1.4; +} + +.cforms-form .cforms-checkbox-label, +.cforms-form .cforms-radio-label { + display: flex; + align-items: center; + margin-bottom: 12px; + cursor: pointer; + padding: 8px; + border-radius: 8px; + transition: background-color 0.2s ease; +} + +.cforms-form .cforms-checkbox-label:hover, +.cforms-form .cforms-radio-label:hover { + background-color: rgba(0, 115, 170, 0.05); +} + +/* Form Groups and Spacing */ +.cforms-form .cforms-form-group { + margin-bottom: 24px; +} + +.cforms-form .cforms-required { + color: #d63638; +} + +/* Error Messages */ +.cforms-error-message { + color: #d63638; + font-size: 14px; + margin-top: 8px; + padding: 8px 12px; + background-color: #f8d7da; + border-radius: 4px; + border-left: 4px solid #d63638; +} + +/* Success Messages */ +.cforms-success-message { + color: #155724; + font-size: 16px; + padding: 16px; + background-color: #d7f3e3; + border-radius: 8px; + border-left: 4px solid #00a32a; + margin-bottom: 24px; +} + +/* File Upload Styling */ +.cforms-form input[type="file"] { + padding: 12px; + border: 2px dashed #ddd; + border-radius: 8px; + background-color: #f9f9f9; + cursor: pointer; + text-align: center; + transition: border-color 0.3s ease; +} + +.cforms-form input[type="file"]:hover { + border-color: #0073aa; + background-color: rgba(0, 115, 170, 0.05); +} + +/* Progress Indicators for Multi-Step Forms */ +.cforms-progress { + display: flex; + justify-content: space-between; + margin-bottom: 32px; + padding: 0 16px; +} + +.cforms-progress-step { + flex: 1; + text-align: center; + position: relative; + padding: 8px 0; +} + +.cforms-progress-step::before { + content: ''; + position: absolute; + top: 50%; + left: 0; + right: 0; + height: 2px; + background-color: #ddd; + z-index: 1; +} + +.cforms-progress-step.active::before, +.cforms-progress-step.completed::before { + background-color: #0073aa; +} + +.cforms-progress-step-number { + display: inline-block; + width: 32px; + height: 32px; + line-height: 32px; + border-radius: 50%; + background-color: #ddd; + color: #666; + font-weight: bold; + position: relative; + z-index: 2; + margin-bottom: 8px; +} + +.cforms-progress-step.active .cforms-progress-step-number, +.cforms-progress-step.completed .cforms-progress-step-number { + background-color: #0073aa; + color: white; +} + +.cforms-progress-step-title { + font-size: 14px; + color: #666; + font-weight: 500; +} + +.cforms-progress-step.active .cforms-progress-step-title, +.cforms-progress-step.completed .cforms-progress-step-title { + color: #0073aa; + font-weight: 600; +} + +/* Tablet Styles */ +@media (min-width: 768px) { + .cforms-form { + padding: 24px; + max-width: 600px; + margin: 0 auto; + } + + .cforms-form .cforms-form-row { + display: flex; + gap: 16px; + margin-bottom: 24px; + } + + .cforms-form .cforms-form-col { + flex: 1; + } + + .cforms-form .cforms-form-col-2 { + flex: 2; + } + + .cforms-form .cforms-form-col-3 { + flex: 3; + } + + .cforms-btn { + width: auto; + min-width: 120px; + display: inline-block; + margin-right: 12px; + } + + .cforms-btn-full { + width: 100%; + } +} + +/* Desktop Styles */ +@media (min-width: 1024px) { + .cforms-form { + max-width: 800px; + padding: 32px; + } + + .cforms-form .cforms-form-group { + margin-bottom: 32px; + } + + .cforms-form input[type="text"], + .cforms-form input[type="email"], + .cforms-form input[type="tel"], + .cforms-form input[type="url"], + .cforms-form input[type="password"], + .cforms-form input[type="number"], + .cforms-form input[type="date"], + .cforms-form input[type="time"], + .cforms-form input[type="datetime-local"], + .cforms-form select, + .cforms-form textarea { + font-size: 14px; /* Smaller font on desktop */ + } + + .cforms-form .cforms-checkbox-label, + .cforms-form .cforms-radio-label { + display: inline-flex; + margin-right: 24px; + margin-bottom: 8px; + } +} + +/* High DPI Displays */ +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + .cforms-form input[type="checkbox"]:checked::after { + font-size: 12px; + } +} + +/* Landscape Orientation on Mobile */ +@media (max-width: 767px) and (orientation: landscape) { + .cforms-form { + padding: 12px; + } + + .cforms-form .cforms-form-group { + margin-bottom: 16px; + } + + .cforms-progress { + margin-bottom: 16px; + } +} + +/* Print Styles */ +@media print { + .cforms-form { + background: none; + box-shadow: none; + border: 1px solid #000; + padding: 20px; + } + + .cforms-form input[type="submit"], + .cforms-form button, + .cforms-btn { + display: none; + } + + .cforms-form input, + .cforms-form select, + .cforms-form textarea { + border: 1px solid #000; + background: none; + } +} + +/* Accessibility Improvements */ +@media (prefers-reduced-motion: reduce) { + .cforms-form *, + .cforms-form *::before, + .cforms-form *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +/* High Contrast Mode */ +@media (prefers-contrast: high) { + .cforms-form input, + .cforms-form select, + .cforms-form textarea { + border-width: 3px; + border-color: #000; + } + + .cforms-form input:focus, + .cforms-form select:focus, + .cforms-form textarea:focus { + border-color: #0000ff; + box-shadow: 0 0 0 3px #ffff00; + } +} + +/* Dark Mode Support */ +@media (prefers-color-scheme: dark) { + .cforms-form { + background-color: #1a1a1a; + color: #ffffff; + } + + .cforms-form input, + .cforms-form select, + .cforms-form textarea { + background-color: #2a2a2a; + border-color: #555; + color: #ffffff; + } + + .cforms-form input:focus, + .cforms-form select:focus, + .cforms-form textarea:focus { + border-color: #4a9eff; + box-shadow: 0 0 0 3px rgba(74, 158, 255, 0.2); + } + + .cforms-form label { + color: #ffffff; + } + + .cforms-error-message { + background-color: #4a1a1a; + color: #ff6b6b; + border-left-color: #ff6b6b; + } + + .cforms-success-message { + background-color: #1a4a1a; + color: #6bff6b; + border-left-color: #6bff6b; + } +} + +/* Loading States for Mobile */ +.cforms-form.cforms-loading { + position: relative; + pointer-events: none; +} + +.cforms-form.cforms-loading::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(255, 255, 255, 0.8); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; +} + +.cforms-form.cforms-loading::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 40px; + height: 40px; + margin: -20px 0 0 -20px; + border: 4px solid #f3f3f3; + border-top: 4px solid #0073aa; + border-radius: 50%; + animation: cforms-mobile-spin 1s linear infinite; + z-index: 1001; +} + +@keyframes cforms-mobile-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Touch Gestures Support */ +.cforms-form .cforms-swipe-area { + touch-action: pan-x; + -webkit-overflow-scrolling: touch; +} + +/* iOS Safari Specific Fixes */ +@supports (-webkit-touch-callout: none) { + .cforms-form input[type="date"], + .cforms-form input[type="time"], + .cforms-form input[type="datetime-local"] { + -webkit-appearance: none; + background-color: white; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M10.293 3.293L6 7.586 1.707 3.293A1 1 0 00.293 4.707l5 5a1 1 0 001.414 0l5-5a1 1 0 10-1.414-1.414z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 12px center; + padding-right: 40px; + } +} diff --git a/readme.txt b/readme.txt index 6d1bd96..6f381ab 100644 --- a/readme.txt +++ b/readme.txt @@ -85,12 +85,19 @@ cformsII can be extended via WordPress actions and filters. You find their 'cfor == Upgrade Notice == -= 15.1.4 = -The tracking database feature and its view are removed with cformsII 15.0+. Your data still exists in the database. Please have a look at CFDB plugin as a replacement. += 16.0.0 = +The cforms2 development transitions from bgermann to woltis. == Changelog == += 16.0.0 = + +* feature: Modern responsive admin interface with mobile optimization +* feature: Gutenberg block editor integration +* feature: Mobile-responsive CSS themes (mobile-admin.css, mobile-responsive.css) +* feature: Modern admin styling (admin-modern.css) + = 15.1.4 = * bugfix: Fix XSS in hidden field