| @@ -72,9 +72,12 @@ | ||
| 72 | 72 | } |
| 73 | 73 | $elMarkup .= '<div class="ff_el_checkable_photo_holders">'; |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | - $data['settings']['container_class'] .= ' ' . ArrayHelper::get($data, 'settings.layout_class'); | |
| 76 | + $data['settings']['container_class'] = trim( | |
| 77 | + ArrayHelper::get($data, 'settings.container_class', '') | |
| 78 | + . ' ' . ArrayHelper::get($data, 'settings.layout_class', '') | |
| 79 | + ); | |
| 77 | 80 | |
| 78 | 81 | if ('yes' == ArrayHelper::get($data, 'settings.randomize_options')) { |
| 79 | 82 | shuffle($formattedOptions); |
| 80 | 83 | } |
| @@ -155,11 +158,31 @@ | ||
| 155 | 158 | $fieldName = str_replace(['[', ']'], '', $data['attributes']['name']); |
| 156 | 159 | $otherInputName = $fieldName . '__ff_other_input__'; |
| 157 | 160 | $otherValue = ''; |
| 158 | 161 | |
| 162 | + // Defaulted like the sibling reads above: forms saved before this | |
| 163 | + // setting existed would otherwise fall through to the field's | |
| 164 | + // "This field is required", which is wrong on an optional field. | |
| 165 | + $otherRequiredMessage = trim((string) ArrayHelper::get( | |
| 166 | + $data, | |
| 167 | + 'settings.other_option_required_message', | |
| 168 | + __('Please specify a value for the selected "Other" option', 'fluentform') | |
| 169 | + )); | |
| 170 | + | |
| 171 | + // An "Other" that is already selected (configured or dynamic | |
| 172 | + // default) must render with its input visible and required — | |
| 173 | + // otherwise the field is mandatory but invisible and the form | |
| 174 | + // cannot be submitted at all. | |
| 175 | + $otherIsSelected = in_array($option['value'], $defaultValues); | |
| 176 | + $wrapperDisplay = $otherIsSelected ? '' : 'display: none; '; | |
| 177 | + $otherAriaRequired = $otherIsSelected ? " aria-required='true'" : ''; | |
| 178 | + | |
| 159 | 179 | $marginTop = $hasImageOption ? '20px' : '8px'; |
| 160 | - $otherInputHtml .= "<div class='ff-other-input-wrapper' style='display: none; margin-top: {$marginTop};' data-field='{$fieldName}'>"; | |
| 161 | - $otherInputHtml .= "<input type='text' name='" . esc_attr($otherInputName) . "' class='ff-el-form-control' placeholder='" . esc_attr($otherPlaceholder) . "' value='" . esc_attr($otherValue) . "'>"; | |
| 180 | + $otherInputHtml .= "<div class='ff-other-input-wrapper' style='{$wrapperDisplay}margin-top: {$marginTop};' data-field='" . esc_attr($fieldName) . "' data-required-message='" . esc_attr($otherRequiredMessage) . "'>"; | |
| 181 | + // The id is what the validator points aria-describedby at when the | |
| 182 | + // free text is required but empty. | |
| 183 | + $otherInputId = $this->getUniqueid('ff_other_' . $fieldName); | |
| 184 | + $otherInputHtml .= "<input type='text' id='" . esc_attr($otherInputId) . "' name='" . esc_attr($otherInputName) . "' class='ff-el-form-control'{$otherAriaRequired} placeholder='" . esc_attr($otherPlaceholder) . "' value='" . esc_attr($otherValue) . "'>"; | |
| 162 | 185 | $otherInputHtml .= "</div>"; |
| 163 | 186 | } |
| 164 | 187 | |
| 165 | 188 | $elMarkup .= '</div>'; |