diff --git a/doc/accessibility/required-form-elements.html b/doc/accessibility/required-form-elements.html new file mode 100644 index 000000000..86fc9374e --- /dev/null +++ b/doc/accessibility/required-form-elements.html @@ -0,0 +1,19 @@ + + + + + + Accessibility: Required form elements + + + + +
+ + +
+ + \ No newline at end of file diff --git a/library/Icinga/Web/Form.php b/library/Icinga/Web/Form.php index 1a75cb852..606a74f98 100644 --- a/library/Icinga/Web/Form.php +++ b/library/Icinga/Web/Form.php @@ -6,6 +6,7 @@ namespace Icinga\Web; use LogicException; use Zend_Config; use Zend_Form; +use Zend_Form_Element; use Zend_View_Interface; use Icinga\Application\Icinga; use Icinga\Authentication\Manager; @@ -550,7 +551,24 @@ class Form extends Zend_Form unset($el->autosubmit); } - return $el; + return $this->ensureElementAccessibility($el); + } + + /** + * Add accessibility related attributes + * + * @param Zend_Form_Element $element + * + * @return Zend_Form_Element + */ + public function ensureElementAccessibility(Zend_Form_Element $element) + { + if ($element->isRequired() && strpos(strtolower($element->getType()), 'checkbox') === false) { + $element->setAttrib('aria-required', 'true'); // ARIA + $element->setAttrib('required', ''); // HTML5 + } + + return $element; } /** diff --git a/modules/setup/application/forms/AdminAccountPage.php b/modules/setup/application/forms/AdminAccountPage.php index e9334c650..de8650439 100644 --- a/modules/setup/application/forms/AdminAccountPage.php +++ b/modules/setup/application/forms/AdminAccountPage.php @@ -78,7 +78,7 @@ class AdminAccountPage extends Form 'text', 'by_name', array( - 'required' => isset($formData['user_type']) && $formData['user_type'] === 'by_name', + 'required' => !isset($formData['user_type']) || $formData['user_type'] === 'by_name', 'value' => $this->getUsername(), 'label' => $this->translate('Username'), 'description' => $this->translate( @@ -87,6 +87,12 @@ class AdminAccountPage extends Form ) ) ); + if (! $this->request->isXmlHttpRequest()) { + // In case JS is disabled we must not provide client side validation as + // the user is required to input data even he has changed his mind + $this->getElement('by_name')->setAttrib('required', null); + $this->getElement('by_name')->setAttrib('aria-required', null); + } } if ($this->backendConfig['backend'] === 'db' || $this->backendConfig['backend'] === 'ldap') { @@ -111,6 +117,12 @@ class AdminAccountPage extends Form 'multiOptions' => array_combine($users, $users) ) ); + if (! $this->request->isXmlHttpRequest()) { + // In case JS is disabled we must not provide client side validation as + // the user is required to input data even he has changed his mind + $this->getElement('existing_user')->setAttrib('required', null); + $this->getElement('existing_user')->setAttrib('aria-required', null); + } } } @@ -149,6 +161,14 @@ class AdminAccountPage extends Form ) ) ); + if (! $this->request->isXmlHttpRequest()) { + // In case JS is disabled we must not provide client side validation as + // the user is required to input data even he has changed his mind + foreach (array('new_user', 'new_user_password', 'new_user_2ndpass') as $elementName) { + $this->getElement($elementName)->setAttrib('aria-required', null); + $this->getElement($elementName)->setAttrib('required', null); + } + } } if (count($choices) > 1) { @@ -157,6 +177,8 @@ class AdminAccountPage extends Form 'user_type', array( 'required' => true, + 'autosubmit' => true, + 'value' => key($choices), 'multiOptions' => $choices ) ); @@ -218,6 +240,26 @@ class AdminAccountPage extends Form return true; } + /** + * Return whether the given values (possibly incomplete) are valid + * + * Unsets all empty text-inputs so that they are not being validated when auto-submitting the form. + * + * @param array $formData + * + * @return type + */ + public function isValidPartial(array $formData) + { + foreach (array('by_name', 'new_user', 'new_user_password', 'new_user_2ndpass') as $elementName) { + if (isset($formData[$elementName]) && $formData[$elementName] === '') { + unset($formData[$elementName]); + } + } + + return parent::isValidPartial($formData); + } + /** * Return the name of the externally authenticated user * diff --git a/modules/setup/application/views/scripts/form/setup-admin-account.phtml b/modules/setup/application/views/scripts/form/setup-admin-account.phtml index ac060526a..b069bb371 100644 --- a/modules/setup/application/views/scripts/form/setup-admin-account.phtml +++ b/modules/setup/application/views/scripts/form/setup-admin-account.phtml @@ -17,7 +17,7 @@ $showRadioBoxes = strpos(strtolower(get_class($radioElem)), 'radio') !== false;
@@ -32,7 +32,7 @@ $showRadioBoxes = strpos(strtolower(get_class($radioElem)), 'radio') !== false;
@@ -49,7 +49,7 @@ $showRadioBoxes = strpos(strtolower(get_class($radioElem)), 'radio') !== false;
diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 7bcbc8e3b..16b6fb0f5 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -118,8 +118,6 @@ // Select a table row $(document).on('click', 'table.multiselect tr[href]', { self: this }, this.rowSelected); - $(document).on('click', 'button', { self: this }, this.submitForm); - // We catch all form submit events $(document).on('submit', 'form', { self: this }, this.submitForm);