From 39346372fa2c80945ed105164518cafbfa145881 Mon Sep 17 00:00:00 2001 From: rickyosser Date: Wed, 11 Sep 2024 15:55:02 +0200 Subject: [PATCH] Add reveal eye to password form control (#2219) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Voříšek --- demos/form-control/input2.php | 5 ++++ src/Behat/Context.php | 2 +- src/Form/Control/Input.php | 2 +- src/Form/Control/Password.php | 50 +++++++++++++++++++++++++++++++++++ tests-behat/input.feature | 13 +++++++++ 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 tests-behat/input.feature diff --git a/demos/form-control/input2.php b/demos/form-control/input2.php index 25af84c1ac..e4b9ad0936 100644 --- a/demos/form-control/input2.php +++ b/demos/form-control/input2.php @@ -26,6 +26,11 @@ $group->addControl('line_read', ['readOnly' => true])->set('read only'); $group->addControl('line_disb', ['disabled' => true])->set('disabled'); +$group = $form->addGroup('Password'); +$group->addControl('password_norm', [Form\Control\Password::class], ['type' => 'text'])->set('editable'); +$group->addControl('password_read', [Form\Control\Password::class, 'readOnly' => true])->set('read only'); +$group->addControl('password_disb', [Form\Control\Password::class, 'disabled' => true])->set('disabled'); + $group = $form->addGroup('Textarea'); $group->addControl('text_norm', [Form\Control\Textarea::class], ['type' => 'text'])->set("editable\nline2"); $group->addControl('text_read', [Form\Control\Textarea::class, 'readOnly' => true], ['type' => 'text'])->set("read only\nline2"); diff --git a/src/Behat/Context.php b/src/Behat/Context.php index 312ad89a52..4f60b2bcad 100644 --- a/src/Behat/Context.php +++ b/src/Behat/Context.php @@ -247,7 +247,7 @@ static function ($matches) { } /** - * @return array + * @return list */ protected function findElements(?NodeElement $context, string $selector): array { diff --git a/src/Form/Control/Input.php b/src/Form/Control/Input.php index 1271820a29..b938444223 100644 --- a/src/Form/Control/Input.php +++ b/src/Form/Control/Input.php @@ -163,7 +163,7 @@ protected function prepareRenderButton($button, $spot) $button->on('click', $executor); } } - if (!$button->isInitialized()) { + if (!$button->isInitialized()) { // TODO if should be replaced with new method like View::addOrAssertRegion() which will add the element and otherwise assert the owner and region $this->add($button, $spot); } diff --git a/src/Form/Control/Password.php b/src/Form/Control/Password.php index db37697645..20c7fc8224 100644 --- a/src/Form/Control/Password.php +++ b/src/Form/Control/Password.php @@ -4,7 +4,57 @@ namespace Atk4\Ui\Form\Control; +use Atk4\Ui\Js\JsExpression; + class Password extends Line { public string $inputType = 'password'; + + /** Enable reveal button */ + public bool $revealEye = true; + + #[\Override] + protected function init(): void + { + parent::init(); + + if ($this->revealEye) { + $this->icon = 'eye link slash'; + if ($this->disabled) { + $this->icon .= ' grey disabled'; + } + } + } + + #[\Override] + protected function recursiveRender(): void + { + if ($this->revealEye && !$this->disabled) { + $this->icon->on( + 'mousedown', // do not use 'click' to keep focus/selection + new JsExpression( + <<<'EOF' + let inputElem = document.getElementById([]); + let iconElem = document.getElementById([]); + + if (inputElem.getAttribute('type') === 'password') { + inputElem.setAttribute('type', 'text'); + iconElem.classList.remove('slash'); + } else { + inputElem.setAttribute('type', 'password'); + iconElem.classList.add('slash'); + } + + if (document.activeElement !== inputElem) { + inputElem.setSelectionRange(-1, -1); + inputElem.focus(); + } + EOF, + [$this->name . '_input', $this->icon->name] + ) + ); + } + + parent::recursiveRender(); + } } diff --git a/tests-behat/input.feature b/tests-behat/input.feature new file mode 100644 index 0000000000..b66d2d1fec --- /dev/null +++ b/tests-behat/input.feature @@ -0,0 +1,13 @@ +Feature: Input control + + Scenario: Password reveal + Given I am on "form-control/input2.php" + When I fill in "password_norm" with "Foo secret" + Then Element "//input[@name='password_norm']" attribute "type" should contain text "password" + Then Element "//input[@name='password_norm']/../i[contains(@class, 'eye')]" attribute "class" should contain text "eye link slash icon" + When I click using selector "//input[@name='password_norm']/../i[contains(@class, 'eye')]" + Then Element "//input[@name='password_norm']" attribute "type" should contain text "text" + Then Element "//input[@name='password_norm']/../i[contains(@class, 'eye')]" attribute "class" should contain text "eye link icon" + When I click using selector "//input[@name='password_norm']/../i[contains(@class, 'eye')]" + Then Element "//input[@name='password_norm']" attribute "type" should contain text "password" + Then Element "//input[@name='password_norm']/../i[contains(@class, 'eye')]" attribute "class" should contain text "eye link icon slash"