| @@ -1,111 +1,83 @@ | ||
| 1 | 1 | <?php |
| 2 | -/** | |
| 3 | - * Color Picker Field | |
| 4 | - * | |
| 5 | - * Frontend: Uses HTML5 native color input for WCAG 2.2 AA compliance: | |
| 6 | - * | |
| 7 | - * @phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- PFBC framework extension, HTML output is controlled | |
| 8 | - * - Full keyboard navigation (Tab, Enter, Arrow keys) | |
| 9 | - * - Screen reader compatible with native browser support | |
| 10 | - * - European Accessibility Act compliant | |
| 11 | - * - No external dependencies | |
| 12 | - * - Mobile and touch optimized (native OS color picker) | |
| 13 | - * - Works in all modern browsers | |
| 14 | - * | |
| 15 | - * Output format: #rrggbb (backward compatible with jqColorPicker) | |
| 16 | - * | |
| 17 | - * Admin: Uses WordPress wp-color-picker (Iris) for consistency with WP admin UI | |
| 18 | - */ | |
| 19 | 2 | class AccuaForm_Element_ColorPicker extends Element { |
| 3 | + /** | |
| 4 | + * Status that changes to 1 if WordPress is ready to load javascripts, and changes to 2 when color picker scripts are loaded | |
| 5 | + * | |
| 6 | + * @var int | |
| 7 | + */ | |
| 8 | + protected static $_cp_loaded_scripts = 0; | |
| 9 | + /** | |
| 10 | + * Status that changes to 1 if WordPress is ready to load styles, and changes to 2 when color picker styles are loaded | |
| 11 | + * | |
| 12 | + * @var int | |
| 13 | + */ | |
| 14 | + protected static $_cp_loaded_styles = 0; | |
| 15 | + /** | |
| 16 | + * Status that changes to TRUE when a color picker field is rendered, meaning that scripts and styles are needed | |
| 17 | + * | |
| 18 | + * @var bool | |
| 19 | + */ | |
| 20 | + protected static $_cp_required_script_styles = FALSE; | |
| 20 | 21 | |
| 21 | - public function __construct($label, $name, ?array $properties = null) { | |
| 22 | + public function __construct($label, $name, array $properties = null) { | |
| 22 | 23 | parent::__construct($label,$name,$properties); |
| 23 | 24 | $this->setValidation(new AccuaForm_Validation_Color()); |
| 24 | 25 | } |
| 26 | + | |
| 27 | + public function jQueryDocumentReady() { | |
| 28 | + parent::jQueryDocumentReady(); | |
| 29 | + echo 'jQuery("#', $this->attributes["id"], '").colorPicker({opacity: false, renderCallback: function($elm, toggled){ | |
| 30 | + if ($elm.val() != "") { | |
| 31 | + $elm.val("#"+this.color.colors.HEX); | |
| 32 | + } | |
| 33 | + }});'; | |
| 34 | + } | |
| 25 | 35 | |
| 26 | 36 | /** |
| 27 | - * Whether to render the frontend flavor (native HTML5 color input). | |
| 37 | + * Loads scripts and styles for color picker only once, if needed, when WordPress is ready | |
| 28 | 38 | * |
| 29 | - * True on the frontend; admin previews that must mirror the frontend | |
| 30 | - * (the Fields page live preview runs through admin-ajax, where | |
| 31 | - * is_admin() is true) force it via the filter. | |
| 32 | - * | |
| 33 | - * @return bool | |
| 39 | + * @return void | |
| 34 | 40 | */ |
| 35 | - protected function isFrontendRender() { | |
| 36 | - /** | |
| 37 | - * Filter to force the frontend rendering of elements inside an | |
| 38 | - * admin-context preview. | |
| 39 | - * | |
| 40 | - * @param bool $force False by default. | |
| 41 | - */ | |
| 42 | - return !is_admin() || apply_filters('accua_forms_preview_render_as_frontend', false); | |
| 43 | - } | |
| 44 | - | |
| 45 | - public function jQueryDocumentReady() { | |
| 46 | - parent::jQueryDocumentReady(); | |
| 47 | - | |
| 48 | - // Only initialize wpColorPicker in admin context where it's available | |
| 49 | - // On frontend, we use HTML5 native color input which doesn't need JS initialization | |
| 50 | - if (!$this->isFrontendRender()) { | |
| 51 | - echo 'if (typeof jQuery.fn.wpColorPicker !== "undefined") { | |
| 52 | - jQuery("#', $this->attributes["id"], '").wpColorPicker({ | |
| 53 | - change: function(event, ui) { | |
| 54 | - var element = jQuery(event.target); | |
| 55 | - var color = ui.color.toString(); | |
| 56 | - if (color && color !== "") { | |
| 57 | - element.val(color); | |
| 58 | - } | |
| 59 | - }, | |
| 60 | - clear: function(event) { | |
| 61 | - jQuery(event.target).val(""); | |
| 62 | - } | |
| 63 | - }); | |
| 64 | - }'; | |
| 65 | - } else { | |
| 66 | - // Frontend: Update hex display when color changes | |
| 67 | - $id = $this->attributes["id"]; | |
| 68 | - echo 'jQuery("#', $id, '").on("input change", function() { | |
| 69 | - var hex = jQuery(this).val().toUpperCase(); | |
| 70 | - jQuery(this).siblings(".pfbc-color-hex").text(hex); | |
| 71 | - });'; | |
| 72 | - } | |
| 73 | - } | |
| 74 | - | |
| 75 | - public function render() { | |
| 76 | - // On frontend, change input type to 'color' for native browser color picker | |
| 77 | - // This provides excellent accessibility without any JS dependencies | |
| 78 | - if ($this->isFrontendRender()) { | |
| 79 | - $this->attributes['type'] = 'color'; | |
| 80 | - // Set a default value if empty (HTML5 color inputs require a valid color) | |
| 81 | - if (empty($this->attributes['value'])) { | |
| 82 | - $this->attributes['value'] = '#000000'; | |
| 41 | + protected static function maybe_load_colorPicker_scripts_styles() { | |
| 42 | + if (self::$_cp_required_script_styles) { // scripts and styles are needed | |
| 43 | + if (self::$_cp_loaded_scripts == 1) { // WordPress is ready to load scripts | |
| 44 | + self::$_cp_loaded_scripts = 2; // Change status to load them just once | |
| 45 | + wp_enqueue_script('accua-jqColorPicker', plugins_url('/js/jqColorPicker.min.js', ACCUA_FORMS_FILE ), array( 'jquery' ), ACCUA_FORMS_JS_VERSION); | |
| 83 | 46 | } |
| 84 | - // Add class for styling | |
| 85 | - $this->setClass('pfbc-color-input'); | |
| 86 | - | |
| 87 | - // Output wrapper with color input and hex display | |
| 88 | - $value = esc_attr($this->attributes['value']); | |
| 89 | - echo '<div class="pfbc-color-wrapper">'; | |
| 90 | - parent::render(); | |
| 91 | - echo '<span class="pfbc-color-hex">' . strtoupper($value) . '</span>'; | |
| 92 | - echo '</div>'; | |
| 93 | - return; // Don't call parent::render() again | |
| 47 | + if (self::$_cp_loaded_styles == 1) { // WordPress is ready to load styles | |
| 48 | + self::$_cp_loaded_styles = 2; // Change status to load them just once | |
| 49 | + // wp_enqueue_style(...) here if needed | |
| 50 | + } | |
| 94 | 51 | } |
| 95 | - parent::render(); | |
| 96 | 52 | } |
| 97 | 53 | |
| 98 | 54 | /** |
| 99 | - * @deprecated No longer needed - scripts are handled in accua-form-api.php | |
| 55 | + * Function called during action wp_print_scripts to change status of self::$_cp_loaded_scripts and load scripts if needed | |
| 56 | + * | |
| 57 | + * @return void | |
| 100 | 58 | */ |
| 101 | 59 | public static function maybe_load_colorPicker_scripts(){ |
| 102 | - // Backward compatibility - no longer used | |
| 60 | + if (self::$_cp_loaded_scripts == 0) { // First time | |
| 61 | + self::$_cp_loaded_scripts = 1; // When we are in this status, WordPress is ready to load scripts | |
| 62 | + self::maybe_load_colorPicker_scripts_styles(); // Load scripts if they were previously set as needed | |
| 63 | + } | |
| 103 | 64 | } |
| 104 | 65 | |
| 105 | 66 | /** |
| 106 | - * @deprecated No longer needed - styles are handled in accua-form-api.php | |
| 67 | + * Function called during action wp_print_styles to change status of self::$_cp_loaded_styles and load styles if needed | |
| 68 | + * | |
| 69 | + * @return void | |
| 107 | 70 | */ |
| 108 | 71 | public static function maybe_load_colorPicker_styles(){ |
| 109 | - // Backward compatibility - no longer used | |
| 72 | + if (self::$_cp_loaded_styles == 0) { // First time | |
| 73 | + self::$_cp_loaded_styles = 1; // When we are in this status, WordPress is ready to load styles | |
| 74 | + self::maybe_load_colorPicker_scripts_styles(); // Load styles if they were previously set as needed | |
| 75 | + } | |
| 76 | + } | |
| 77 | + | |
| 78 | + public function render() { | |
| 79 | + self::$_cp_required_script_styles = TRUE; // Changing status meaning that script and styles are needed | |
| 80 | + self::maybe_load_colorPicker_scripts_styles(); // Load script and styles once if WordPress is ready | |
| 81 | + parent::render(); | |
| 110 | 82 | } |
| 111 | 83 | } |