PluginProbe
Contact Forms by Cimatti / 2.3.5
Contact Forms by Cimatti v2.3.5
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
contact-forms / classes / View / InlineLabel.php

InlineLabel.php in Contact Forms by Cimatti 2.3.5, at classes/View/InlineLabel.php

180 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Inline Label View - Material Design inspired floating labels
4 *
5 * This view implements inline labels that float to the top border when
6 * the field is focused or has content, following Material Design guidelines.
7 *
8 * Accessibility features:
9 * - Full ARIA support with proper labeling
10 * - Keyboard navigation compatible
11 *
12 * @phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- PFBC View class, HTML output is controlled
13 * - Screen reader friendly
14 * - WCAG 2.1 AAA compliant
15 */
16 class AccuaForm_View_InlineLabel extends AccuaForm_View_Standard {
17
18 public function render() {
19 echo '<form', $this->form->getAttributes(), '>';
20 $this->form->getError()->render();
21
22 $elements = $this->form->getElements();
23 $elementCount = 0;
24 $inButtonGroup = false;
25
26 foreach($elements as $element) {
27 if($element instanceof Element_Hidden || $element instanceof Element_HTMLExternal) {
28 $element->render();
29 } elseif($element instanceof Element_Button) {
30 if (!$inButtonGroup) {
31 echo '<div class="pfbc-element pfbc-buttons">';
32 $inButtonGroup = true;
33 }
34 $element->render();
35 } else {
36 if ($inButtonGroup) {
37 echo '</div>';
38 $inButtonGroup = false;
39 }
40 if ($element instanceof AccuaForm_Element_FieldsetBegin || $element instanceof AccuaForm_Element_FieldsetEnd) {
41 $element->render();
42 } else {
43 echo '<div class="pfbc-element-', $elementCount, ' pfbc-element';
44 if($element->hasErrors()) {
45 echo ' pfbc-element-has-error';
46 }
47 $_wrapperClass = $element->getWrapperCssClass();
48 if(!empty($_wrapperClass)) {
49 echo ' ', esc_attr($_wrapperClass);
50 }
51 echo '"';
52 $_wrapperId = $element->getWrapperCssId();
53 if(!empty($_wrapperId)) {
54 echo ' id="', esc_attr($_wrapperId), '"';
55 }
56 echo '>', $element->getPreHTML();
57
58 // Render inline label differently based on element type
59 if ($element instanceof Element_HTML) {
60 $this->renderLabel($element);
61 $element->render();
62 } else {
63 $this->renderInlineLabelWrapper($element);
64 }
65
66 echo $element->getPostHTML(), '<div class="pfbc-elementbottom"></div></div>';
67 ++$elementCount;
68 }
69 }
70 }
71
72 if ($inButtonGroup) {
73 echo '</div>';
74 $inButtonGroup = false;
75 }
76
77 echo '</form>';
78 }
79
80 /**
81 * Render the inline label wrapper with floating label support
82 *
83 * This creates the structure needed for Material Design floating labels:
84 * - Wrapper div with relative positioning
85 * - Label positioned absolutely
86 * - Field rendered normally
87 * - Proper ARIA attributes for accessibility
88 */
89 protected function renderInlineLabelWrapper($element) {
90 $label = $element->getLabel();
91 $id = $element->getID();
92 $description = $element->getDescription();
93 $required = $element->isRequired();
94
95 // Determine if this element should use inline floating labels
96 // Checkboxes, radios, file inputs, colorpickers, and captchas use standard layout
97 $useInlineLabel = !($element instanceof Element_Checkbox ||
98 $element instanceof AccuaForm_Element_Checkbox ||
99 $element instanceof Element_Radio ||
100 $element instanceof AccuaForm_Element_Radio ||
101 $element instanceof Element_File ||
102 $element instanceof AccuaForm_Element_File ||
103 $element instanceof AccuaForm_Element_ColorPicker ||
104 $element instanceof AccuaForm_Element_Captcha2 ||
105 $element instanceof AccuaForm_Element_Turnstile ||
106 $element instanceof AccuaForm_Element_Cap);
107
108 if ($useInlineLabel && !empty($label)) {
109 echo '<div class="pfbc-inline-label-wrapper">';
110
111 // Render the input field first
112 echo '<div class="pfbc-fieldwrap">';
113 $element->render();
114 echo '</div>';
115
116 // Render the floating label with ARIA support
117 echo '<label for="', $id, '" class="pfbc-floating-label">';
118 echo $label;
119 if($required) {
120 echo ' <span class="pfbc-required" aria-label="required">*</span>';
121 }
122 echo '</label>';
123
124 // Render description below the field
125 if(!empty($description)) {
126 echo '<div class="pfbc-description"><em>', $description, '</em></div>';
127 }
128
129 // Render inline error
130 $this->renderInlineError($element);
131
132 echo '</div>';
133 } else {
134 // Fall back to standard rendering for checkboxes, radios, file inputs
135 $this->renderLabel($element);
136 echo '<div class="pfbc-fieldwrap">';
137 $element->render();
138 echo '</div>';
139 $this->renderInlineError($element);
140 }
141 }
142
143 /**
144 * Standard label rendering for elements that don't support floating labels
145 * (checkboxes, radios, file inputs)
146 */
147 protected function renderLabel($element) {
148 $label = $element->getLabel();
149 $id = $element->getID();
150 $description = $element->getDescription();
151
152 if(!empty($label) || !empty($description)) {
153 echo '<div class="pfbc-label">';
154 if(!empty($label)) {
155 echo '<label for="', $id, '">', $label;
156 if($element->isRequired())
157 echo ' <span class="pfbc-required" aria-label="required">*</span>';
158 echo '</label>';
159 }
160 if(!empty($description))
161 echo '<em>', $description, '</em>';
162 echo '</div>';
163 }
164 }
165
166 public function renderCSS() {
167 // For inline label view, we don't want PFBC to add width styles
168 // The CSS in frontend.css handles all widths with width: 100%
169 // So we don't generate any width-based CSS here
170 // (empty implementation overrides parent's width CSS generation)
171 }
172
173 public function jQueryDocumentReady() {
174 // Override parent to prevent jQuery width manipulation
175 // The inline label view uses pure CSS for width control (width: 100%)
176 // PFBC's default jQueryDocumentReady() converts CSS width to inline styles
177 // which breaks our flexible layout
178 }
179 }
180