From 2ea9b07acf188880fe3849dd1994d75660cf21e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:49:45 +0000 Subject: [PATCH 1/9] Bump intl-tel-input from 19.5.7 to 21.2.7 Bumps [intl-tel-input](https://github.com/jackocnr/intl-tel-input) from 19.5.7 to 21.2.7. - [Release notes](https://github.com/jackocnr/intl-tel-input/releases) - [Changelog](https://github.com/jackocnr/intl-tel-input/blob/master/CHANGELOG.md) - [Commits](https://github.com/jackocnr/intl-tel-input/compare/v19.5.7...v21.2.7) --- updated-dependencies: - dependency-name: intl-tel-input dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c177628..abba942 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "bootstrap-icons": "^1.11.3", "chart.js": "^4.4.1", "flatpickr": "^4.6.13", - "intl-tel-input": "^19.5.3" + "intl-tel-input": "^21.2.7" }, "devDependencies": { "@bsi-cx/design-build": "^1.13.3", From 30b870fb7f93ab0f28484db6733b119b08c1d35f Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Mon, 29 Apr 2024 17:25:55 +0200 Subject: [PATCH 2/9] add pin element plus container --- configs/styles/pin-label.js | 15 ++ .../advanced/form-container-pin/index.js | 29 ++++ .../advanced/form-container-pin/styles.scss | 156 ++++++++++++++++++ .../advanced/form-container-pin/template.twig | 33 ++++ .../advanced/form-pin/form-pin.js | 99 +++++++++++ content-elements/advanced/form-pin/index.js | 19 +++ .../advanced/form-pin/styles.scss | 59 +++++++ .../advanced/form-pin/template.twig | 27 +++ content-elements/advanced/index.js | 3 +- core/main/index.js | 1 + 10 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 configs/styles/pin-label.js create mode 100644 content-elements/advanced/form-container-pin/index.js create mode 100644 content-elements/advanced/form-container-pin/styles.scss create mode 100644 content-elements/advanced/form-container-pin/template.twig create mode 100644 content-elements/advanced/form-pin/form-pin.js create mode 100644 content-elements/advanced/form-pin/index.js create mode 100644 content-elements/advanced/form-pin/styles.scss create mode 100644 content-elements/advanced/form-pin/template.twig diff --git a/configs/styles/pin-label.js b/configs/styles/pin-label.js new file mode 100644 index 0000000..aeb3980 --- /dev/null +++ b/configs/styles/pin-label.js @@ -0,0 +1,15 @@ +const {cx} = require('@bsi-cx/design-build'); + +module.exports = cx.style + .withIdentifier('pin-label-numbering-ba3c80c7') + /*.withLabel('Footer gradient')*/ + .withLabel('Nummerierung') + .withCssClasses( + cx.cssClass + /*.withLabel('No gradient')*/ + .withLabel('Mit Nummerierung') + .withCssClass('default'), + cx.cssClass + /*.withLabel('Show gradient')*/ + .withLabel('Ohne Nummerierung') + .withCssClass('pin-label-invisible')); \ No newline at end of file diff --git a/content-elements/advanced/form-container-pin/index.js b/content-elements/advanced/form-container-pin/index.js new file mode 100644 index 0000000..08c8191 --- /dev/null +++ b/content-elements/advanced/form-container-pin/index.js @@ -0,0 +1,29 @@ +require('./styles.scss'); +const {cx, Icon} = require('@bsi-cx/design-build'); + +const element = cx.contentElement; + +/** + * @returns {ContentElement} + */ +module.exports = element; +element.withFile(require('./template.twig')) + .withElementId('form-container-pin-384aa4d6') + /*.withLabel('Form')*/ + .withLabel('Pin-Element') + .withIcon(Icon.ONE_COLUMN) + .withStyleConfigs( + require('../../../configs/styles/form-width'), + require('../../../configs/styles/form-layout'), + require('../../../configs/styles/form-color'), + require('../../../configs/styles/form-info-text')) + .withParts( + cx.part.form + .withId('form-container-pin-30c44d0d') + /*.withLabel('Form'))*/ + .withLabel('Pin-Element')) + .withDropzones( + cx.dropzone + .withDropzone('form-container-dropzone-6b6f360e') + .withAllowedElements( + require('../form-pin'))); \ No newline at end of file diff --git a/content-elements/advanced/form-container-pin/styles.scss b/content-elements/advanced/form-container-pin/styles.scss new file mode 100644 index 0000000..e00a208 --- /dev/null +++ b/content-elements/advanced/form-container-pin/styles.scss @@ -0,0 +1,156 @@ +@import "../../../styles/properties"; + +.bsi-element-form-container-692qIu { + padding-right: 0px; + padding-left: 0px; + + .form-text { + margin-top: 0 !important; + } + input, select, textarea, input.bsi-form-tel-input-element, .bsi-poll-radio-group, .form-radio { + margin-top: 0.5rem !important; + } + label { + margin-bottom: 0; + } + + .card, input, select, textarea { + border: 1px solid rgba(56, 62, 66, .3); + } + + &.bsi-form-slim { + max-width: 540px; + } + + &.bsi-form-card-visible .card-body { + padding-right: 32px; + padding-left: 32px; + } + + &.bsi-form-card-hide { + .card { + box-shadow: none !important; + border: none; + } + + .card-body { + padding-right: 0; + padding-left: 0; + } + } + + &.bsi-corner-sharp { + input { + border-radius: 0; + } + } + + $colors: ("primary": $primary, "secondary": $secondary); + @each $name, $color in $colors { + input:focus, select:focus, textarea:focus { + border-color: rgba($color, .25); + box-shadow: 0 0 0 .25rem rgba($color, .25); + } + + &.bsi-form-btn-outline .btn-submit { + color: $color; + background-color: transparent; + border-color: $color; + + &:hover { + color: $light; + background-color: $color; + border-color: $color; + } + } + + &.bsi-form-btn-filled .btn-submit { + color: $light; + background-color: $color; + border-color: $color; + + &:hover { + color: $color; + background-color: transparent; + border-color: $color; + } + } + + input[type=range]::-webkit-slider-thumb { + background: $color; + } + + input[type=range]::-moz-range-thumb { + background: $color; + } /* Firefox */ + + input[type=range]::-ms-thumb { + background: $color; + } /* IE */ + + input[type=range]:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 .25rem rgba($color, .25); + } + + input[type=range]:focus::-moz-range-thumb { + box-shadow: 0 0 0 .25rem rgba($color, .25); + } /* Firefox */ + + input[type=range]:focus::-ms-thumb { + box-shadow: 0 0 0 .25rem rgba($color, .25); + } /* IE */ + + i.bi-info-circle { + color: $color; + } + } + + + &.bsi-form-btn-filled .btn-outline-info { + color: $light; + background-color: $dark; + border-color: $dark; + + &:hover { + color: $dark; + background-color: transparent; + border-color: $dark; + } + } + + input[type=submit], input[type=reset], .bsi-btn-element { + margin: 0 0.25rem 0.25rem 0 !important; + } + + input[type=reset][disabled] { + display: none; + } + + .text-danger { + list-style-type: none; + } + + .form-label-and-info-text { + &.contains-tooltip { + display: flex; + gap: 0.5rem; + + .form-text { + display: none; + } + } + + i.bi-info-circle { + display: none; + + &.tooltip-visible { + display: block; + } + } + } +} + +.bsi-tooltip { + --bs-tooltip-bg: var(--bs-gray-dark); + --bs-tooltip-color: var(--bs-light); +} \ No newline at end of file diff --git a/content-elements/advanced/form-container-pin/template.twig b/content-elements/advanced/form-container-pin/template.twig new file mode 100644 index 0000000..f6f1296 --- /dev/null +++ b/content-elements/advanced/form-container-pin/template.twig @@ -0,0 +1,33 @@ +{% apply spaceless %} + {% set formWidth = (formWidth ?: properties.formWidth) ?: 'bsi-form-wide' %} + {% set formLayout = (formLayout ?: properties.formLayout) ?: 'bsi-form-card-visible' %} + {% set formBorderRadius = (formBorderRadius ?: properties.formBorderRadius) ?: 'bsi-corner-rounded' %} + {% set formLabelPosition = (formLabelPosition ?: properties.formLabelPosition) ?: 'bsi-form-label-top' %} + {% set formColor = (formColor ?: properties.formColor) ?: 'bsi-form-color-primary' %} + {% set formButtonLayout = (formButtonLayout ?: properties.formButtonLayout) ?: 'bsi-form-btn-outline' %} + +
+
+
+
+
+ {% block form_container_dropzone %} + {% include '../form-pin/template.twig' %} + {% endblock %} +
+
+
    +
  • +
+
+
+
+ + +
+
+
+
+
+
+{% endapply %} \ No newline at end of file diff --git a/content-elements/advanced/form-pin/form-pin.js b/content-elements/advanced/form-pin/form-pin.js new file mode 100644 index 0000000..996ac5a --- /dev/null +++ b/content-elements/advanced/form-pin/form-pin.js @@ -0,0 +1,99 @@ +import Alpine from '@alpinejs/csp'; + +Alpine.data('formPin', () => ({ + rootEl: null, + maxlength: null, + + initFormFieldInput() { + this.rootEl = this.$root.querySelector('.bsi-form-field-input'); + var containerDiv = this.$root.querySelector('.bsi-form-pin-element'); + + if (this.rootEl.getAttribute('maxlength') == null) { + this.maxlength = 6; + } else { + this.maxlength = this.rootEl.getAttribute('maxlength'); + } + + for (var i = 0; i < this.maxlength; i++) { + var inputWrapper = document.createElement('div'); + inputWrapper.classList = 'input-wrapper'; + containerDiv.appendChild(inputWrapper); + + var label = document.createElement('label'); + label.classList = 'form-label'; + label.innerHTML = i + 1 + "."; + inputWrapper.appendChild(label); + + var pinBox = document.createElement('input'); + pinBox.setAttribute('x-init', 'initFormPinInput'); + pinBox.setAttribute('required', 'true'); + pinBox.classList = 'bsi-form-field-input form-control bsi-form-field-input pin'; + inputWrapper.appendChild(pinBox); + } + }, + + initFormPinInput() { + var inputPin = this.$el; + inputPin.setAttribute('inputmode', 'numeric'); + inputPin.setAttribute('pattern', "[0-9]"); + inputPin.addEventListener('focusin', (e) => { + inputPin.setAttribute('old', inputPin.value); + }); + inputPin.addEventListener('input', (e) => { + this._isCompletelyFilledIn(); + this._autoFocusNextPinInput(); + }); + }, + + _isCompletelyFilledIn() { + let form = this.$root.closest('form'); + const inputPinList = this.$root.querySelectorAll('input.pin'); + this._cleanUp(); + this.rootEl.value = Array.from(inputPinList).reduce((result, input) => { + return result + input.value; + }, ""); + if (form && this.rootEl.value.length == this.maxlength) { + form.submit(); + } + }, + + _autoFocusNextPinInput() { + var inputPin = this.$el; + var inputWrapper = inputPin.parentNode.nextElementSibling; + if (inputPin.value && this._LastPinElement()!=null) { + var nextPinInput = inputWrapper.children[1]; + while (nextPinInput) { + var pinInput = nextPinInput; + pinInput.focus(); + break; + } + } + }, + + _cleanUp() { + var inputPin = this.$el; + if (inputPin.value) { + if (this._LastPinElement() == null){ + inputPin.value = inputPin.value.slice(-1); + } + if (inputPin.value.length > 1) { + var old = inputPin.getAttribute('old'); + var value = inputPin.value; + if (!/^[0-9]+$/.test(inputPin.value)) { + inputPin.value = old; + } else { + var newVal = value.replace(old, ''); + inputPin.value = newVal; + var old = newVal; + } + } else if (!/^[0-9]+$/.test(inputPin.value)) { + inputPin.value = null; + } + } + }, + + _LastPinElement() { + var inputPin = this.$el; + return inputPin.parentNode.nextElementSibling; + }, +})); diff --git a/content-elements/advanced/form-pin/index.js b/content-elements/advanced/form-pin/index.js new file mode 100644 index 0000000..25a441c --- /dev/null +++ b/content-elements/advanced/form-pin/index.js @@ -0,0 +1,19 @@ +require('./styles.scss'); + +const {cx, Icon} = require('@bsi-cx/design-build'); + +module.exports = cx.contentElement + .withFile(require('./template.twig')) + .withElementId('form-pin-dafa5a0e') + .withLabel('PIN') + .withDescription('') + .withIcon(Icon.FORMFIELD) + .withStyleConfigs( + require('../../../configs/styles/pin-label')) + .withParts( + cx.part.formField + .withId('form-field-part-eefc3ac5') + .withLabel('Formularfeld'), + cx.part.plainText + .withId('form-field-part-text-cc1a1c62') + .withLabel('Formularfeld')); \ No newline at end of file diff --git a/content-elements/advanced/form-pin/styles.scss b/content-elements/advanced/form-pin/styles.scss new file mode 100644 index 0000000..7a7f224 --- /dev/null +++ b/content-elements/advanced/form-pin/styles.scss @@ -0,0 +1,59 @@ +@use '../../form/form-field/prototype/styles.scss' as element; + +@include element.styles('form-pin-dafa5a0e'); + +.hide { display: none; } +.bsi-ce-edit-mode .show-if-edit { display: block; } + +.bsi-element-form-pin-dafa5a0e { + + .bsi-form-input-element { + display: flex; + justify-content: center; + text-align: center; + column-gap: 2%; + + input { + height: 64px; + padding: 10px 10px; + text-align: center; + font-size: 25px; + font-weight: 400; + color: rgb(0, 0, 0, 0.60); + font-style: normal; + align-items: center; + align-self: stretch; + } + } + + &.pin-label-invisible .bsi-form-pin-element label.form-label { + display: none; + } + + /* Chrome, Safari, Edge, Opera */ + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + /* Firefox */ + input[type=number] { + -moz-appearance: textfield; + } +} + +.was-validated .form-control:valid, +.form-control.is-valid { + padding: 10px 10px; + background-image: none !important; + background-color:#ffff !important; +} + +.was-validated .form-control:invalid, +.form-control.is-invalid { + padding: 10px 10px; + background-image: none !important; + background-color: rgb(217, 19, 41, 0.05) !important; + border: 1px solid #d91329 !important; +} \ No newline at end of file diff --git a/content-elements/advanced/form-pin/template.twig b/content-elements/advanced/form-pin/template.twig new file mode 100644 index 0000000..4851e53 --- /dev/null +++ b/content-elements/advanced/form-pin/template.twig @@ -0,0 +1,27 @@ +{% apply spaceless %} + {% set formFieldElementId = elementId ?: 'form-pin-dafa5a0e' %} + {% set formFieldElementPartId = elementPartId ?: 'form-field-part-eefc3ac5' %} + {% set formFieldTextPartId = formTextPartId ?: 'form-field-part-text-cc1a1c62' %} + {% set formFieldLabelText = (labelText ?: properties.formFieldLabelText) ?: bsi_cx_lorem(3) %} + {% set formFieldInfoText = (infoText ?: properties.formFieldInfoText) ?: "" %} + +
+
+ {# generated Inputs #} +
+
+ + {# Preview Pin Inputs #} + + + + + +
+
+ +
{{ formFieldInfoText }}
+ +
+
+{% endapply %} \ No newline at end of file diff --git a/content-elements/advanced/index.js b/content-elements/advanced/index.js index dc5cfff..49bcb17 100644 --- a/content-elements/advanced/index.js +++ b/content-elements/advanced/index.js @@ -1,5 +1,6 @@ const advancedElements = [ - require('./webcam-image-upload') + require('./webcam-image-upload'), + require('./form-container-pin') ]; module.exports.advancedElements = advancedElements; \ No newline at end of file diff --git a/core/main/index.js b/core/main/index.js index f801cfa..269b2ff 100644 --- a/core/main/index.js +++ b/core/main/index.js @@ -5,6 +5,7 @@ import 'bootstrap-icons/font/bootstrap-icons.css'; // add module specific scripts in ALPHABETICAL order import '../../content-elements/advanced/webcam-image-upload/prototype/webcam-image-upload'; +import '../../content-elements/advanced/form-pin/form-pin'; import '../../content-elements/base/accordion/prototype/accordion'; import '../../content-elements/base/button/prototype/button'; import '../../content-elements/base/chart/prototype/chart'; From 9ab255dfaab612dfc78f99df7d591252594a10bb Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Mon, 29 Apr 2024 17:25:55 +0200 Subject: [PATCH 3/9] wip --- content-elements/advanced/form-pin/form-pin.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/content-elements/advanced/form-pin/form-pin.js b/content-elements/advanced/form-pin/form-pin.js index 996ac5a..7587f7f 100644 --- a/content-elements/advanced/form-pin/form-pin.js +++ b/content-elements/advanced/form-pin/form-pin.js @@ -60,7 +60,7 @@ Alpine.data('formPin', () => ({ _autoFocusNextPinInput() { var inputPin = this.$el; var inputWrapper = inputPin.parentNode.nextElementSibling; - if (inputPin.value && this._LastPinElement()!=null) { + if (inputPin.value && !this._LastPinElement()) { var nextPinInput = inputWrapper.children[1]; while (nextPinInput) { var pinInput = nextPinInput; @@ -73,7 +73,7 @@ Alpine.data('formPin', () => ({ _cleanUp() { var inputPin = this.$el; if (inputPin.value) { - if (this._LastPinElement() == null){ + if (this._LastPinElement()){ inputPin.value = inputPin.value.slice(-1); } if (inputPin.value.length > 1) { @@ -94,6 +94,10 @@ Alpine.data('formPin', () => ({ _LastPinElement() { var inputPin = this.$el; - return inputPin.parentNode.nextElementSibling; + if(inputPin.parentNode.nextElementSibling == null){ + return true; + } else { + return false; + } ; }, })); From 8c1d7aad309253e330c069e1d93f53c1fad2d067 Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Mon, 29 Apr 2024 17:25:55 +0200 Subject: [PATCH 4/9] style configs auto submit --- configs/styles/pin-auto-submit.js | 15 ++++++++++ content-elements/advanced/index.js | 1 - .../form-container-pin/index.js | 0 .../form-container-pin/styles.scss | 0 .../form-container-pin/template.twig | 1 - .../{advanced => form}/form-pin/form-pin.js | 30 ++++++++++++++++--- .../{advanced => form}/form-pin/index.js | 3 +- .../{advanced => form}/form-pin/styles.scss | 11 ++++++- .../{advanced => form}/form-pin/template.twig | 2 +- content-elements/layout/col-one/index.js | 3 +- core/main/index.js | 2 +- 11 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 configs/styles/pin-auto-submit.js rename content-elements/{advanced => form}/form-container-pin/index.js (100%) rename content-elements/{advanced => form}/form-container-pin/styles.scss (100%) rename content-elements/{advanced => form}/form-container-pin/template.twig (95%) rename content-elements/{advanced => form}/form-pin/form-pin.js (78%) rename content-elements/{advanced => form}/form-pin/index.js (82%) rename content-elements/{advanced => form}/form-pin/styles.scss (89%) rename content-elements/{advanced => form}/form-pin/template.twig (91%) diff --git a/configs/styles/pin-auto-submit.js b/configs/styles/pin-auto-submit.js new file mode 100644 index 0000000..29015cb --- /dev/null +++ b/configs/styles/pin-auto-submit.js @@ -0,0 +1,15 @@ +const {cx} = require('@bsi-cx/design-build'); + +module.exports = cx.style + .withIdentifier('pin-auto-submit-ae00c3ca') + /*.withLabel('Footer gradient')*/ + .withLabel('automatisch versenden ') + .withCssClasses( + cx.cssClass + /*.withLabel('No gradient')*/ + .withLabel('nein') + .withCssClass('default'), + cx.cssClass + /*.withLabel('Show gradient')*/ + .withLabel('ja') + .withCssClass('auto-submit')); \ No newline at end of file diff --git a/content-elements/advanced/index.js b/content-elements/advanced/index.js index 49bcb17..d942ebf 100644 --- a/content-elements/advanced/index.js +++ b/content-elements/advanced/index.js @@ -1,6 +1,5 @@ const advancedElements = [ require('./webcam-image-upload'), - require('./form-container-pin') ]; module.exports.advancedElements = advancedElements; \ No newline at end of file diff --git a/content-elements/advanced/form-container-pin/index.js b/content-elements/form/form-container-pin/index.js similarity index 100% rename from content-elements/advanced/form-container-pin/index.js rename to content-elements/form/form-container-pin/index.js diff --git a/content-elements/advanced/form-container-pin/styles.scss b/content-elements/form/form-container-pin/styles.scss similarity index 100% rename from content-elements/advanced/form-container-pin/styles.scss rename to content-elements/form/form-container-pin/styles.scss diff --git a/content-elements/advanced/form-container-pin/template.twig b/content-elements/form/form-container-pin/template.twig similarity index 95% rename from content-elements/advanced/form-container-pin/template.twig rename to content-elements/form/form-container-pin/template.twig index f6f1296..5d0919b 100644 --- a/content-elements/advanced/form-container-pin/template.twig +++ b/content-elements/form/form-container-pin/template.twig @@ -23,7 +23,6 @@
-
diff --git a/content-elements/advanced/form-pin/form-pin.js b/content-elements/form/form-pin/form-pin.js similarity index 78% rename from content-elements/advanced/form-pin/form-pin.js rename to content-elements/form/form-pin/form-pin.js index 7587f7f..c021721 100644 --- a/content-elements/advanced/form-pin/form-pin.js +++ b/content-elements/form/form-pin/form-pin.js @@ -39,13 +39,22 @@ Alpine.data('formPin', () => ({ inputPin.addEventListener('focusin', (e) => { inputPin.setAttribute('old', inputPin.value); }); + inputPin.addEventListener('keydown', (e) => { + if (e.key==='Backspace' && !inputPin.value) { + this._autoFocusPreviousPinInput(); + } + }) inputPin.addEventListener('input', (e) => { - this._isCompletelyFilledIn(); + if (this.$root.classList.contains('auto-submit')) { + this._autoSubmitIfFilledIn(); + } else { + this._cleanUp(); + } this._autoFocusNextPinInput(); }); }, - _isCompletelyFilledIn() { + _autoSubmitIfFilledIn() { let form = this.$root.closest('form'); const inputPinList = this.$root.querySelectorAll('input.pin'); this._cleanUp(); @@ -59,9 +68,9 @@ Alpine.data('formPin', () => ({ _autoFocusNextPinInput() { var inputPin = this.$el; - var inputWrapper = inputPin.parentNode.nextElementSibling; + var nextWrapper = inputPin.parentNode.nextElementSibling; if (inputPin.value && !this._LastPinElement()) { - var nextPinInput = inputWrapper.children[1]; + var nextPinInput = nextWrapper.children[1]; while (nextPinInput) { var pinInput = nextPinInput; pinInput.focus(); @@ -70,6 +79,19 @@ Alpine.data('formPin', () => ({ } }, + _autoFocusPreviousPinInput() { + var inputPin = this.$el; + var previousWrapper = inputPin.parentNode.previousSibling; + if (previousWrapper != null) { + var previousPinInput = previousWrapper.children[1]; + while (previousPinInput) { + var pinInput = previousPinInput; + pinInput.focus(); + break; + } + } + }, + _cleanUp() { var inputPin = this.$el; if (inputPin.value) { diff --git a/content-elements/advanced/form-pin/index.js b/content-elements/form/form-pin/index.js similarity index 82% rename from content-elements/advanced/form-pin/index.js rename to content-elements/form/form-pin/index.js index 25a441c..fb5f9da 100644 --- a/content-elements/advanced/form-pin/index.js +++ b/content-elements/form/form-pin/index.js @@ -9,7 +9,8 @@ module.exports = cx.contentElement .withDescription('') .withIcon(Icon.FORMFIELD) .withStyleConfigs( - require('../../../configs/styles/pin-label')) + require('../../../configs/styles/pin-label'), + require('../../../configs/styles/pin-auto-submit')) .withParts( cx.part.formField .withId('form-field-part-eefc3ac5') diff --git a/content-elements/advanced/form-pin/styles.scss b/content-elements/form/form-pin/styles.scss similarity index 89% rename from content-elements/advanced/form-pin/styles.scss rename to content-elements/form/form-pin/styles.scss index 7a7f224..5d64113 100644 --- a/content-elements/advanced/form-pin/styles.scss +++ b/content-elements/form/form-pin/styles.scss @@ -13,7 +13,7 @@ text-align: center; column-gap: 2%; - input { + input{ height: 64px; padding: 10px 10px; text-align: center; @@ -25,6 +25,15 @@ align-self: stretch; } } + + .bsi-form-pin-element { + flex-wrap: wrap; + + .input-wrapper{ + min-width: 40px; + max-width: 7%; + } + } &.pin-label-invisible .bsi-form-pin-element label.form-label { display: none; diff --git a/content-elements/advanced/form-pin/template.twig b/content-elements/form/form-pin/template.twig similarity index 91% rename from content-elements/advanced/form-pin/template.twig rename to content-elements/form/form-pin/template.twig index 4851e53..2aa004c 100644 --- a/content-elements/advanced/form-pin/template.twig +++ b/content-elements/form/form-pin/template.twig @@ -5,7 +5,7 @@ {% set formFieldLabelText = (labelText ?: properties.formFieldLabelText) ?: bsi_cx_lorem(3) %} {% set formFieldInfoText = (infoText ?: properties.formFieldInfoText) ?: "" %} -
+
{# generated Inputs #}
diff --git a/content-elements/layout/col-one/index.js b/content-elements/layout/col-one/index.js index 4c5f6d2..c1db87b 100644 --- a/content-elements/layout/col-one/index.js +++ b/content-elements/layout/col-one/index.js @@ -33,4 +33,5 @@ element.withElementId('col-one-l2ZclN') require('../../base/banner'), ...contentElements, ...advancedElements, - require('../../form/form-container'))); \ No newline at end of file + require('../../form/form-container'), + require('../../form/form-container-pin'))); \ No newline at end of file diff --git a/core/main/index.js b/core/main/index.js index 269b2ff..a31f4c8 100644 --- a/core/main/index.js +++ b/core/main/index.js @@ -5,7 +5,6 @@ import 'bootstrap-icons/font/bootstrap-icons.css'; // add module specific scripts in ALPHABETICAL order import '../../content-elements/advanced/webcam-image-upload/prototype/webcam-image-upload'; -import '../../content-elements/advanced/form-pin/form-pin'; import '../../content-elements/base/accordion/prototype/accordion'; import '../../content-elements/base/button/prototype/button'; import '../../content-elements/base/chart/prototype/chart'; @@ -15,6 +14,7 @@ import '../../content-elements/base/table/prototype/table'; import '../../content-elements/form/form-container/form'; import '../../content-elements/form/form-field-tel/prototype/form-tel-input'; import '../../content-elements/form/form-field/prototype/form-field'; +import '../../content-elements/form/form-pin/form-pin'; import '../../content-elements/form/poll/prototype/poll'; import '../../content-elements/form/radio/prototype/radio'; import '../../content-elements/form/checkbox/prototype/checkbox'; From b834019e4a0f945f511d0213ca6cb11e8cc9af24 Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Mon, 29 Apr 2024 17:25:55 +0200 Subject: [PATCH 5/9] validation, testing --- .../form/form-container-pin/template.twig | 2 +- content-elements/form/form-pin/form-pin.js | 152 ++++++++++-------- content-elements/form/form-pin/index.js | 5 +- content-elements/form/form-pin/styles.scss | 16 +- content-elements/form/form-pin/template.twig | 38 +++-- 5 files changed, 119 insertions(+), 94 deletions(-) diff --git a/content-elements/form/form-container-pin/template.twig b/content-elements/form/form-container-pin/template.twig index 5d0919b..4cc85e6 100644 --- a/content-elements/form/form-container-pin/template.twig +++ b/content-elements/form/form-container-pin/template.twig @@ -22,7 +22,7 @@
- +
diff --git a/content-elements/form/form-pin/form-pin.js b/content-elements/form/form-pin/form-pin.js index c021721..abbdb31 100644 --- a/content-elements/form/form-pin/form-pin.js +++ b/content-elements/form/form-pin/form-pin.js @@ -1,125 +1,141 @@ import Alpine from '@alpinejs/csp'; Alpine.data('formPin', () => ({ - rootEl: null, + bsiInputElement: null, // Input field required for CX story / value flow maxlength: null, + requiredErrorElement: null, - initFormFieldInput() { - this.rootEl = this.$root.querySelector('.bsi-form-field-input'); - var containerDiv = this.$root.querySelector('.bsi-form-pin-element'); + initPinNumberFields() { + this.bsiInputElement = this.$root.querySelector('.bsi-form-field-input-original'); + let containerDiv = this.$root.querySelector('.generated-inputs'); - if (this.rootEl.getAttribute('maxlength') == null) { + const maxLength = this.bsiInputElement.getAttribute('maxlength'); + if (maxLength == null) { this.maxlength = 6; } else { - this.maxlength = this.rootEl.getAttribute('maxlength'); + this.maxlength = this.bsiInputElement.getAttribute('maxlength'); } - for (var i = 0; i < this.maxlength; i++) { - var inputWrapper = document.createElement('div'); - inputWrapper.classList = 'input-wrapper'; - containerDiv.appendChild(inputWrapper); - - var label = document.createElement('label'); - label.classList = 'form-label'; - label.innerHTML = i + 1 + "."; - inputWrapper.appendChild(label); - - var pinBox = document.createElement('input'); - pinBox.setAttribute('x-init', 'initFormPinInput'); - pinBox.setAttribute('required', 'true'); - pinBox.classList = 'bsi-form-field-input form-control bsi-form-field-input pin'; - inputWrapper.appendChild(pinBox); + for (let i = 0; i < this.maxlength; i++) { + this._initPinNumberField(containerDiv, i); } }, + _initPinNumberField(containerDiv, i) { + let inputWrapper = document.createElement('div'); + inputWrapper.classList = 'input-wrapper'; + containerDiv.appendChild(inputWrapper); + + let label = document.createElement('label'); + label.classList = 'form-label'; + label.innerHTML = (i + 1) + "."; + inputWrapper.appendChild(label); + + let pinBox = document.createElement('input'); + pinBox.setAttribute('x-init', 'initFormPinInput'); + pinBox.setAttribute('required', 'true'); + pinBox.classList = 'bsi-form-field-input form-control bsi-form-field-input pin'; + inputWrapper.appendChild(pinBox); + }, + initFormPinInput() { - var inputPin = this.$el; + let inputPin = this.$el; inputPin.setAttribute('inputmode', 'numeric'); inputPin.setAttribute('pattern', "[0-9]"); + inputPin.addEventListener('focusin', (e) => { inputPin.setAttribute('old', inputPin.value); }); + inputPin.addEventListener('keydown', (e) => { - if (e.key==='Backspace' && !inputPin.value) { + if (e.key ==='Backspace' && !inputPin.value) { this._autoFocusPreviousPinInput(); } - }) + }); + inputPin.addEventListener('input', (e) => { + const inputPinList = this.$root.querySelectorAll('input.pin'); + this._cleanUp(); + this.bsiInputElement.value = Array.from(inputPinList).reduce((result, input) => { + return result + input.value; + }, ""); if (this.$root.classList.contains('auto-submit')) { this._autoSubmitIfFilledIn(); - } else { - this._cleanUp(); } this._autoFocusNextPinInput(); }); }, - _autoSubmitIfFilledIn() { - let form = this.$root.closest('form'); - const inputPinList = this.$root.querySelectorAll('input.pin'); - this._cleanUp(); - this.rootEl.value = Array.from(inputPinList).reduce((result, input) => { - return result + input.value; - }, ""); - if (form && this.rootEl.value.length == this.maxlength) { - form.submit(); + initRequiredError() { + this.requiredErrorElement = this.$el; + }, + + validateInput() { + if (this.bsiInputElement.value.length != this.maxlength) { + this.requiredErrorElement.style.display = "block"; + } else { + this.requiredErrorElement.style.display = "none"; } }, _autoFocusNextPinInput() { - var inputPin = this.$el; - var nextWrapper = inputPin.parentNode.nextElementSibling; - if (inputPin.value && !this._LastPinElement()) { - var nextPinInput = nextWrapper.children[1]; - while (nextPinInput) { - var pinInput = nextPinInput; - pinInput.focus(); - break; - } + let inputPin = this.$el; + let nextWrapper = inputPin.parentNode.nextElementSibling; + if (inputPin.value && !this._isLastPinElement()) { + this._autoFocus(nextWrapper); } }, _autoFocusPreviousPinInput() { - var inputPin = this.$el; - var previousWrapper = inputPin.parentNode.previousSibling; + let inputPin = this.$el; + let previousWrapper = inputPin.parentNode.previousSibling; if (previousWrapper != null) { - var previousPinInput = previousWrapper.children[1]; - while (previousPinInput) { - var pinInput = previousPinInput; - pinInput.focus(); - break; + this._autoFocus(previousWrapper); + } + }, + + _autoFocus(wrapper){ + var nextPinInput = wrapper.querySelector('input.pin'); + if (nextPinInput) { + nextPinInput.focus(); } + }, + + _autoSubmitIfFilledIn() { + let form = this.$root.closest('form'); + if (form && this.bsiInputElement.value.length == this.maxlength) { + form.submit(); } }, _cleanUp() { - var inputPin = this.$el; + // TODO: auch im DOM lösbar? + let inputPin = this.$el; if (inputPin.value) { - if (this._LastPinElement()){ + if (this._isLastPinElement()){ inputPin.value = inputPin.value.slice(-1); } + + const numberPattern = /^[0-9]+$/; if (inputPin.value.length > 1) { - var old = inputPin.getAttribute('old'); - var value = inputPin.value; - if (!/^[0-9]+$/.test(inputPin.value)) { - inputPin.value = old; + var oldValue = inputPin.getAttribute('old'); + var currentValue = inputPin.value; + + if (!numberPattern.test(inputPin.value)) { + inputPin.value = oldValue; } else { - var newVal = value.replace(old, ''); - inputPin.value = newVal; - var old = newVal; + var newValue = currentValue.replace(oldValue, ''); + inputPin.value = newValue; + oldValue = newValue; } - } else if (!/^[0-9]+$/.test(inputPin.value)) { + + } else if (!numberPattern.test(inputPin.value)) { inputPin.value = null; } } }, - _LastPinElement() { - var inputPin = this.$el; - if(inputPin.parentNode.nextElementSibling == null){ - return true; - } else { - return false; - } ; + _isLastPinElement() { + return this.$el.parentNode.nextElementSibling == null; }, })); diff --git a/content-elements/form/form-pin/index.js b/content-elements/form/form-pin/index.js index fb5f9da..45ba82f 100644 --- a/content-elements/form/form-pin/index.js +++ b/content-elements/form/form-pin/index.js @@ -17,4 +17,7 @@ module.exports = cx.contentElement .withLabel('Formularfeld'), cx.part.plainText .withId('form-field-part-text-cc1a1c62') - .withLabel('Formularfeld')); \ No newline at end of file + .withLabel('Info Text'), + cx.part.plainText + .withId('form-field-part-error-required-f3cf3728') + .withLabel('Fehlermeldung bei leerem Pflichtfeld')); \ No newline at end of file diff --git a/content-elements/form/form-pin/styles.scss b/content-elements/form/form-pin/styles.scss index 5d64113..0bad183 100644 --- a/content-elements/form/form-pin/styles.scss +++ b/content-elements/form/form-pin/styles.scss @@ -2,14 +2,12 @@ @include element.styles('form-pin-dafa5a0e'); -.hide { display: none; } -.bsi-ce-edit-mode .show-if-edit { display: block; } - .bsi-element-form-pin-dafa5a0e { - .bsi-form-input-element { + .hide { display: none; } + + .bsi-form-pin-element { display: flex; - justify-content: center; text-align: center; column-gap: 2%; @@ -24,16 +22,16 @@ align-items: center; align-self: stretch; } - } - - .bsi-form-pin-element { - flex-wrap: wrap; .input-wrapper{ min-width: 40px; max-width: 7%; } } + + .generated-inputs{ + flex-wrap: wrap; + } &.pin-label-invisible .bsi-form-pin-element label.form-label { display: none; diff --git a/content-elements/form/form-pin/template.twig b/content-elements/form/form-pin/template.twig index 2aa004c..9969404 100644 --- a/content-elements/form/form-pin/template.twig +++ b/content-elements/form/form-pin/template.twig @@ -2,26 +2,34 @@ {% set formFieldElementId = elementId ?: 'form-pin-dafa5a0e' %} {% set formFieldElementPartId = elementPartId ?: 'form-field-part-eefc3ac5' %} {% set formFieldTextPartId = formTextPartId ?: 'form-field-part-text-cc1a1c62' %} + {% set formFieldErrorRequiredPartId = errorRequiredPartId ?: 'form-field-part-error-required-f3cf3728' %} {% set formFieldLabelText = (labelText ?: properties.formFieldLabelText) ?: bsi_cx_lorem(3) %} {% set formFieldInfoText = (infoText ?: properties.formFieldInfoText) ?: "" %} + {% set formFieldErrorRequiredText = (errorRequiredText ?: properties.errorRequiredText) ?: 'Bitte füllen Sie dieses Feld aus.' %} {# TODO: make translatable #}
-
- {# generated Inputs #} -
- - {# Preview Pin Inputs #} - - - - - -
-
- -
{{ formFieldInfoText }}
- +
+ +
{{ formFieldInfoText }}
+ +
+ +
+ {# Preview Pin Inputs #} + + + + + + +
+
+ {# generated Inputs #} +
+
+ +
{% endapply %} \ No newline at end of file From c9529f0b76829d8ce815272fe45a050c1e6b3ae6 Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Mon, 29 Apr 2024 17:25:55 +0200 Subject: [PATCH 6/9] combine container- and input-pin to one element --- configs/styles/pin-label.js | 2 +- .../form/form-container-pin/index.js | 29 --- .../form/form-container-pin/styles.scss | 156 ------------ .../form/form-container-pin/template.twig | 32 --- content-elements/form/form-pin/form-pin.js | 90 +++++-- content-elements/form/form-pin/index.js | 22 +- content-elements/form/form-pin/styles.scss | 241 ++++++++++++++---- content-elements/form/form-pin/template.twig | 73 ++++-- content-elements/layout/col-one/index.js | 2 +- 9 files changed, 322 insertions(+), 325 deletions(-) delete mode 100644 content-elements/form/form-container-pin/index.js delete mode 100644 content-elements/form/form-container-pin/styles.scss delete mode 100644 content-elements/form/form-container-pin/template.twig diff --git a/configs/styles/pin-label.js b/configs/styles/pin-label.js index aeb3980..64cf80e 100644 --- a/configs/styles/pin-label.js +++ b/configs/styles/pin-label.js @@ -8,7 +8,7 @@ module.exports = cx.style cx.cssClass /*.withLabel('No gradient')*/ .withLabel('Mit Nummerierung') - .withCssClass('default'), + .withCssClass('pin-label-visible'), cx.cssClass /*.withLabel('Show gradient')*/ .withLabel('Ohne Nummerierung') diff --git a/content-elements/form/form-container-pin/index.js b/content-elements/form/form-container-pin/index.js deleted file mode 100644 index 08c8191..0000000 --- a/content-elements/form/form-container-pin/index.js +++ /dev/null @@ -1,29 +0,0 @@ -require('./styles.scss'); -const {cx, Icon} = require('@bsi-cx/design-build'); - -const element = cx.contentElement; - -/** - * @returns {ContentElement} - */ -module.exports = element; -element.withFile(require('./template.twig')) - .withElementId('form-container-pin-384aa4d6') - /*.withLabel('Form')*/ - .withLabel('Pin-Element') - .withIcon(Icon.ONE_COLUMN) - .withStyleConfigs( - require('../../../configs/styles/form-width'), - require('../../../configs/styles/form-layout'), - require('../../../configs/styles/form-color'), - require('../../../configs/styles/form-info-text')) - .withParts( - cx.part.form - .withId('form-container-pin-30c44d0d') - /*.withLabel('Form'))*/ - .withLabel('Pin-Element')) - .withDropzones( - cx.dropzone - .withDropzone('form-container-dropzone-6b6f360e') - .withAllowedElements( - require('../form-pin'))); \ No newline at end of file diff --git a/content-elements/form/form-container-pin/styles.scss b/content-elements/form/form-container-pin/styles.scss deleted file mode 100644 index e00a208..0000000 --- a/content-elements/form/form-container-pin/styles.scss +++ /dev/null @@ -1,156 +0,0 @@ -@import "../../../styles/properties"; - -.bsi-element-form-container-692qIu { - padding-right: 0px; - padding-left: 0px; - - .form-text { - margin-top: 0 !important; - } - input, select, textarea, input.bsi-form-tel-input-element, .bsi-poll-radio-group, .form-radio { - margin-top: 0.5rem !important; - } - label { - margin-bottom: 0; - } - - .card, input, select, textarea { - border: 1px solid rgba(56, 62, 66, .3); - } - - &.bsi-form-slim { - max-width: 540px; - } - - &.bsi-form-card-visible .card-body { - padding-right: 32px; - padding-left: 32px; - } - - &.bsi-form-card-hide { - .card { - box-shadow: none !important; - border: none; - } - - .card-body { - padding-right: 0; - padding-left: 0; - } - } - - &.bsi-corner-sharp { - input { - border-radius: 0; - } - } - - $colors: ("primary": $primary, "secondary": $secondary); - @each $name, $color in $colors { - input:focus, select:focus, textarea:focus { - border-color: rgba($color, .25); - box-shadow: 0 0 0 .25rem rgba($color, .25); - } - - &.bsi-form-btn-outline .btn-submit { - color: $color; - background-color: transparent; - border-color: $color; - - &:hover { - color: $light; - background-color: $color; - border-color: $color; - } - } - - &.bsi-form-btn-filled .btn-submit { - color: $light; - background-color: $color; - border-color: $color; - - &:hover { - color: $color; - background-color: transparent; - border-color: $color; - } - } - - input[type=range]::-webkit-slider-thumb { - background: $color; - } - - input[type=range]::-moz-range-thumb { - background: $color; - } /* Firefox */ - - input[type=range]::-ms-thumb { - background: $color; - } /* IE */ - - input[type=range]:focus::-webkit-slider-thumb { - box-shadow: 0 0 0 .25rem rgba($color, .25); - } - - input[type=range]:focus::-moz-range-thumb { - box-shadow: 0 0 0 .25rem rgba($color, .25); - } /* Firefox */ - - input[type=range]:focus::-ms-thumb { - box-shadow: 0 0 0 .25rem rgba($color, .25); - } /* IE */ - - i.bi-info-circle { - color: $color; - } - } - - - &.bsi-form-btn-filled .btn-outline-info { - color: $light; - background-color: $dark; - border-color: $dark; - - &:hover { - color: $dark; - background-color: transparent; - border-color: $dark; - } - } - - input[type=submit], input[type=reset], .bsi-btn-element { - margin: 0 0.25rem 0.25rem 0 !important; - } - - input[type=reset][disabled] { - display: none; - } - - .text-danger { - list-style-type: none; - } - - .form-label-and-info-text { - &.contains-tooltip { - display: flex; - gap: 0.5rem; - - .form-text { - display: none; - } - } - - i.bi-info-circle { - display: none; - - &.tooltip-visible { - display: block; - } - } - } -} - -.bsi-tooltip { - --bs-tooltip-bg: var(--bs-gray-dark); - --bs-tooltip-color: var(--bs-light); -} \ No newline at end of file diff --git a/content-elements/form/form-container-pin/template.twig b/content-elements/form/form-container-pin/template.twig deleted file mode 100644 index 4cc85e6..0000000 --- a/content-elements/form/form-container-pin/template.twig +++ /dev/null @@ -1,32 +0,0 @@ -{% apply spaceless %} - {% set formWidth = (formWidth ?: properties.formWidth) ?: 'bsi-form-wide' %} - {% set formLayout = (formLayout ?: properties.formLayout) ?: 'bsi-form-card-visible' %} - {% set formBorderRadius = (formBorderRadius ?: properties.formBorderRadius) ?: 'bsi-corner-rounded' %} - {% set formLabelPosition = (formLabelPosition ?: properties.formLabelPosition) ?: 'bsi-form-label-top' %} - {% set formColor = (formColor ?: properties.formColor) ?: 'bsi-form-color-primary' %} - {% set formButtonLayout = (formButtonLayout ?: properties.formButtonLayout) ?: 'bsi-form-btn-outline' %} - -
-
-
-
-
- {% block form_container_dropzone %} - {% include '../form-pin/template.twig' %} - {% endblock %} -
-
-
    -
  • -
-
-
-
- -
-
-
-
-
-
-{% endapply %} \ No newline at end of file diff --git a/content-elements/form/form-pin/form-pin.js b/content-elements/form/form-pin/form-pin.js index abbdb31..b9d1900 100644 --- a/content-elements/form/form-pin/form-pin.js +++ b/content-elements/form/form-pin/form-pin.js @@ -1,13 +1,62 @@ import Alpine from '@alpinejs/csp'; +import { Tooltip } from 'bootstrap'; Alpine.data('formPin', () => ({ bsiInputElement: null, // Input field required for CX story / value flow maxlength: null, requiredErrorElement: null, + form: null, + root: null, + + initForm() { + this.form = this.$el; + this.root = this.$root; + + if (this.root.classList.contains('bsi-form-label-floating')) { + for(const floatingElement of this.form.getElementsByClassName('bsi-label-floating-element')) { + this._initFloatingLabels(floatingElement); + } + } + + if (this.root.classList.contains('bsi-form-info-as-tooltip') + && ['bsi-form-label-top', 'bsi-form-label-left'].some(labelClass => this.root.classList.contains(labelClass))) { + this.form.querySelectorAll('.bsi-form-element').forEach((formElement) => { + let infoTextField = formElement.querySelector('.form-text'); + let tooltipIcon = formElement.querySelector('i'); + if (infoTextField && infoTextField.innerText && tooltipIcon) { + tooltipIcon.classList.add('tooltip-visible'); + tooltipIcon.parentElement.classList.add('contains-tooltip'); + tooltipIcon.setAttribute('title', infoTextField.innerText); + new Tooltip(tooltipIcon); + } + }) + } + }, + + submitForm(e) { + if (!this.form.checkValidity()) { + e.preventDefault(); + e.stopPropagation(); + this.validateInput(); + } + this.form.classList.add('was-validated'); + }, + + initRequiredError() { + this.requiredErrorElement = this.$el; + }, + + validateInput() { + if (this.bsiInputElement.value.length != this.maxlength) { + this.requiredErrorElement.style.display = "block"; + } else { + this.requiredErrorElement.style.display = "none"; + } + }, initPinNumberFields() { this.bsiInputElement = this.$root.querySelector('.bsi-form-field-input-original'); - let containerDiv = this.$root.querySelector('.generated-inputs'); + let containerDiv = this.$root.querySelector('.bsi-form-pin-element'); const maxLength = this.bsiInputElement.getAttribute('maxlength'); if (maxLength == null) { @@ -22,20 +71,21 @@ Alpine.data('formPin', () => ({ }, _initPinNumberField(containerDiv, i) { - let inputWrapper = document.createElement('div'); - inputWrapper.classList = 'input-wrapper'; - containerDiv.appendChild(inputWrapper); - + let div = document.createElement('div'); let label = document.createElement('label'); + let pinInput = document.createElement('input'); + + div.classList = 'input-wrapper'; label.classList = 'form-label'; label.innerHTML = (i + 1) + "."; - inputWrapper.appendChild(label); - - let pinBox = document.createElement('input'); - pinBox.setAttribute('x-init', 'initFormPinInput'); - pinBox.setAttribute('required', 'true'); - pinBox.classList = 'bsi-form-field-input form-control bsi-form-field-input pin'; - inputWrapper.appendChild(pinBox); + pinInput.classList = 'bsi-form-field-input form-control bsi-form-field-input pin'; + + pinInput.setAttribute('x-init', 'initFormPinInput'); + pinInput.setAttribute('required', 'true'); + + div.appendChild(label); + div.appendChild(pinInput); + containerDiv.appendChild(div); }, initFormPinInput() { @@ -66,18 +116,6 @@ Alpine.data('formPin', () => ({ }); }, - initRequiredError() { - this.requiredErrorElement = this.$el; - }, - - validateInput() { - if (this.bsiInputElement.value.length != this.maxlength) { - this.requiredErrorElement.style.display = "block"; - } else { - this.requiredErrorElement.style.display = "none"; - } - }, - _autoFocusNextPinInput() { let inputPin = this.$el; let nextWrapper = inputPin.parentNode.nextElementSibling; @@ -102,8 +140,8 @@ Alpine.data('formPin', () => ({ }, _autoSubmitIfFilledIn() { - let form = this.$root.closest('form'); - if (form && this.bsiInputElement.value.length == this.maxlength) { + let form = this.$root.querySelector('.formular-pin');; + if (form && (this.bsiInputElement.value.length == this.maxlength)) { form.submit(); } }, diff --git a/content-elements/form/form-pin/index.js b/content-elements/form/form-pin/index.js index 45ba82f..00548e9 100644 --- a/content-elements/form/form-pin/index.js +++ b/content-elements/form/form-pin/index.js @@ -1,14 +1,22 @@ require('./styles.scss'); - const {cx, Icon} = require('@bsi-cx/design-build'); -module.exports = cx.contentElement - .withFile(require('./template.twig')) - .withElementId('form-pin-dafa5a0e') - .withLabel('PIN') - .withDescription('') - .withIcon(Icon.FORMFIELD) +const element = cx.contentElement; + +/** + * @returns {ContentElement} + */ +module.exports = element; +element.withFile(require('./template.twig')) + .withElementId('form-container-pin-384aa4d6') + /*.withLabel('Form')*/ + .withLabel('Pin-Element') + .withIcon(Icon.ONE_COLUMN) .withStyleConfigs( + require('../../../configs/styles/form-width'), + require('../../../configs/styles/form-layout'), + require('../../../configs/styles/form-color'), + require('../../../configs/styles/form-info-text'), require('../../../configs/styles/pin-label'), require('../../../configs/styles/pin-auto-submit')) .withParts( diff --git a/content-elements/form/form-pin/styles.scss b/content-elements/form/form-pin/styles.scss index 0bad183..b6e287b 100644 --- a/content-elements/form/form-pin/styles.scss +++ b/content-elements/form/form-pin/styles.scss @@ -1,66 +1,211 @@ -@use '../../form/form-field/prototype/styles.scss' as element; - -@include element.styles('form-pin-dafa5a0e'); - -.bsi-element-form-pin-dafa5a0e { - - .hide { display: none; } - - .bsi-form-pin-element { - display: flex; - text-align: center; - column-gap: 2%; - - input{ - height: 64px; - padding: 10px 10px; - text-align: center; - font-size: 25px; - font-weight: 400; - color: rgb(0, 0, 0, 0.60); - font-style: normal; - align-items: center; - align-self: stretch; - } - - .input-wrapper{ - min-width: 40px; - max-width: 7%; - } +@import "../../../styles/properties"; + +.bsi-element-form-container-692qIu { + padding-right: 0px; + padding-left: 0px; + + .form-text { + margin-top: 0 !important; + } + input, select, textarea { + margin-top: 0.5rem !important; + } + label { + margin-bottom: 0; + } + + .card, input, select, textarea { + border: 1px solid rgba(56, 62, 66, .3); + } + + &.bsi-form-slim { + max-width: 540px; + } + + &.bsi-form-card-visible .card-body { + padding-right: 32px; + padding-left: 32px; + } + + &.bsi-form-card-hide { + .card { + box-shadow: none !important; + border: none; + } + + .card-body { + padding-right: 0; + padding-left: 0; + } + } + + &.bsi-corner-sharp { + input { + border-radius: 0; + } + } + + $colors: ("primary": $primary, "secondary": $secondary); + @each $name, $color in $colors { + input:focus, select:focus, textarea:focus { + border-color: rgba($color, .25); + box-shadow: 0 0 0 .25rem rgba($color, .25); + } + + &.bsi-form-btn-outline .btn-submit { + color: $color; + background-color: transparent; + border-color: $color; + + &:hover { + color: $light; + background-color: $color; + border-color: $color; + } + } + + &.bsi-form-btn-filled .btn-submit { + color: $light; + background-color: $color; + border-color: $color; + + &:hover { + color: $color; + background-color: transparent; + border-color: $color; + } + } + + input[type=range]::-webkit-slider-thumb { + background: $color; + } + + input[type=range]::-moz-range-thumb { + background: $color; + } /* Firefox */ + + input[type=range]::-ms-thumb { + background: $color; + } /* IE */ + + input[type=range]:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 .25rem rgba($color, .25); } - .generated-inputs{ - flex-wrap: wrap; + input[type=range]:focus::-moz-range-thumb { + box-shadow: 0 0 0 .25rem rgba($color, .25); + } /* Firefox */ + + input[type=range]:focus::-ms-thumb { + box-shadow: 0 0 0 .25rem rgba($color, .25); + } /* IE */ + + i.bi-info-circle { + color: $color; } - - &.pin-label-invisible .bsi-form-pin-element label.form-label { + } + + &.bsi-form-btn-filled .btn-outline-info { + color: $light; + background-color: $dark; + border-color: $dark; + + &:hover { + color: $dark; + background-color: transparent; + border-color: $dark; + } + } + + input[type=submit], input[type=reset], .bsi-btn-element { + margin: 0 0.25rem 0.25rem 0 !important; + } + + input[type=reset][disabled] { + display: none; + } + + .text-danger { + list-style-type: none; + } + + .form-label-and-info-text { + &.contains-tooltip { + display: flex; + gap: 0.5rem; + + .form-text { display: none; + } + } + + i.bi-info-circle { + display: none; + + &.tooltip-visible { + display: block; + } } + } - /* Chrome, Safari, Edge, Opera */ - input::-webkit-outer-spin-button, - input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; + .hide { display: none; } + + .bsi-form-pin-element { + display: flex; + flex-wrap: wrap; + text-align: center; + column-gap: 2%; + + input{ + height: 64px; + padding: 10px 10px; + text-align: center; + font-size: 25px; + font-weight: 400; + color: rgb(0, 0, 0, 0.60); + font-style: normal; + align-items: center; + align-self: stretch; } - /* Firefox */ - input[type=number] { - -moz-appearance: textfield; + .input-wrapper, .preview-input{ + min-width: 40px; + max-width: 7%; } + } + + &.pin-label-invisible .bsi-form-pin-element label.form-label { + display: none; + } + + /* Chrome, Safari, Edge, Opera */ + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + /* Firefox */ + input[type=number] { + -moz-appearance: textfield; + } } .was-validated .form-control:valid, .form-control.is-valid { - padding: 10px 10px; - background-image: none !important; - background-color:#ffff !important; + padding: 10px 10px; + background-image: none !important; + background-color:#ffff !important; } .was-validated .form-control:invalid, .form-control.is-invalid { - padding: 10px 10px; - background-image: none !important; - background-color: rgb(217, 19, 41, 0.05) !important; - border: 1px solid #d91329 !important; + padding: 10px 10px; + background-image: none !important; + background-color: rgb(217, 19, 41, 0.05) !important; + border: 1px solid #d91329 !important; +} + +.bsi-tooltip { + --bs-tooltip-bg: var(--bs-gray-dark); + --bs-tooltip-color: var(--bs-light); } \ No newline at end of file diff --git a/content-elements/form/form-pin/template.twig b/content-elements/form/form-pin/template.twig index 9969404..ab5402d 100644 --- a/content-elements/form/form-pin/template.twig +++ b/content-elements/form/form-pin/template.twig @@ -1,35 +1,58 @@ {% apply spaceless %} - {% set formFieldElementId = elementId ?: 'form-pin-dafa5a0e' %} + {% set formWidth = (formWidth ?: properties.formWidth) ?: 'bsi-form-wide' %} + {% set formLayout = (formLayout ?: properties.formLayout) ?: 'bsi-form-card-visible' %} + {% set formBorderRadius = (formBorderRadius ?: properties.formBorderRadius) ?: 'bsi-corner-rounded' %} + {% set formLabelPosition = (formLabelPosition ?: properties.formLabelPosition) ?: 'bsi-form-label-top' %} + {% set formColor = (formColor ?: properties.formColor) ?: 'bsi-form-color-primary' %} + {% set formButtonLayout = (formButtonLayout ?: properties.formButtonLayout) ?: 'bsi-form-btn-outline' %} + {% set formPinLabel = (formPinLabel ?: properties.formPinLabel) ?: 'pin-label-invisible' %} {% set formFieldElementPartId = elementPartId ?: 'form-field-part-eefc3ac5' %} {% set formFieldTextPartId = formTextPartId ?: 'form-field-part-text-cc1a1c62' %} {% set formFieldErrorRequiredPartId = errorRequiredPartId ?: 'form-field-part-error-required-f3cf3728' %} {% set formFieldLabelText = (labelText ?: properties.formFieldLabelText) ?: bsi_cx_lorem(3) %} {% set formFieldInfoText = (infoText ?: properties.formFieldInfoText) ?: "" %} {% set formFieldErrorRequiredText = (errorRequiredText ?: properties.errorRequiredText) ?: 'Bitte füllen Sie dieses Feld aus.' %} {# TODO: make translatable #} - -
-
-
- -
{{ formFieldInfoText }}
- + + {# Pin-Container #} +
+
+
+
+ {# Pin-Element #} +
+
+
+ +
{{ formFieldInfoText }}
+ +
+ +
+ {# generated Inputs #} + + + + + + +
+
+ +
+
+
+
+
    +
  • +
+
+
+
+ +
+
+
- -
- {# Preview Pin Inputs #} - - - - - - -
-
- {# generated Inputs #} -
-
- -
-
+
{% endapply %} \ No newline at end of file diff --git a/content-elements/layout/col-one/index.js b/content-elements/layout/col-one/index.js index c1db87b..10a1670 100644 --- a/content-elements/layout/col-one/index.js +++ b/content-elements/layout/col-one/index.js @@ -34,4 +34,4 @@ element.withElementId('col-one-l2ZclN') ...contentElements, ...advancedElements, require('../../form/form-container'), - require('../../form/form-container-pin'))); \ No newline at end of file + require('../../form/form-pin'))); \ No newline at end of file From 97ee5e94d462b5cd5bac1d246d5a34331f9ef836 Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Mon, 29 Apr 2024 17:25:55 +0200 Subject: [PATCH 7/9] code adjustment, remove tooltip --- configs/styles/pin-auto-submit.js | 6 +- configs/styles/pin-label.js | 6 +- content-elements/form/form-pin/form-pin.js | 97 ++++++-------------- content-elements/form/form-pin/index.js | 1 - content-elements/form/form-pin/styles.scss | 24 ----- content-elements/form/form-pin/template.twig | 1 - 6 files changed, 34 insertions(+), 101 deletions(-) diff --git a/configs/styles/pin-auto-submit.js b/configs/styles/pin-auto-submit.js index 29015cb..9b9acd2 100644 --- a/configs/styles/pin-auto-submit.js +++ b/configs/styles/pin-auto-submit.js @@ -2,14 +2,14 @@ const {cx} = require('@bsi-cx/design-build'); module.exports = cx.style .withIdentifier('pin-auto-submit-ae00c3ca') - /*.withLabel('Footer gradient')*/ + /*.withLabel('Pin auto submit')*/ .withLabel('automatisch versenden ') .withCssClasses( cx.cssClass - /*.withLabel('No gradient')*/ + /*.withLabel('No auto submit')*/ .withLabel('nein') .withCssClass('default'), cx.cssClass - /*.withLabel('Show gradient')*/ + /*.withLabel('Show auto submit')*/ .withLabel('ja') .withCssClass('auto-submit')); \ No newline at end of file diff --git a/configs/styles/pin-label.js b/configs/styles/pin-label.js index 64cf80e..b49b9c3 100644 --- a/configs/styles/pin-label.js +++ b/configs/styles/pin-label.js @@ -2,14 +2,14 @@ const {cx} = require('@bsi-cx/design-build'); module.exports = cx.style .withIdentifier('pin-label-numbering-ba3c80c7') - /*.withLabel('Footer gradient')*/ + /*.withLabel('Numbered label')*/ .withLabel('Nummerierung') .withCssClasses( cx.cssClass - /*.withLabel('No gradient')*/ + /*.withLabel('Show numbering')*/ .withLabel('Mit Nummerierung') .withCssClass('pin-label-visible'), cx.cssClass - /*.withLabel('Show gradient')*/ + /*.withLabel('No numbering')*/ .withLabel('Ohne Nummerierung') .withCssClass('pin-label-invisible')); \ No newline at end of file diff --git a/content-elements/form/form-pin/form-pin.js b/content-elements/form/form-pin/form-pin.js index b9d1900..8bc9509 100644 --- a/content-elements/form/form-pin/form-pin.js +++ b/content-elements/form/form-pin/form-pin.js @@ -1,9 +1,8 @@ import Alpine from '@alpinejs/csp'; -import { Tooltip } from 'bootstrap'; Alpine.data('formPin', () => ({ bsiInputElement: null, // Input field required for CX story / value flow - maxlength: null, + maxLength: null, requiredErrorElement: null, form: null, root: null, @@ -17,20 +16,6 @@ Alpine.data('formPin', () => ({ this._initFloatingLabels(floatingElement); } } - - if (this.root.classList.contains('bsi-form-info-as-tooltip') - && ['bsi-form-label-top', 'bsi-form-label-left'].some(labelClass => this.root.classList.contains(labelClass))) { - this.form.querySelectorAll('.bsi-form-element').forEach((formElement) => { - let infoTextField = formElement.querySelector('.form-text'); - let tooltipIcon = formElement.querySelector('i'); - if (infoTextField && infoTextField.innerText && tooltipIcon) { - tooltipIcon.classList.add('tooltip-visible'); - tooltipIcon.parentElement.classList.add('contains-tooltip'); - tooltipIcon.setAttribute('title', infoTextField.innerText); - new Tooltip(tooltipIcon); - } - }) - } }, submitForm(e) { @@ -47,7 +32,7 @@ Alpine.data('formPin', () => ({ }, validateInput() { - if (this.bsiInputElement.value.length != this.maxlength) { + if (this.bsiInputElement.value.length != this.maxLength) { this.requiredErrorElement.style.display = "block"; } else { this.requiredErrorElement.style.display = "none"; @@ -58,14 +43,9 @@ Alpine.data('formPin', () => ({ this.bsiInputElement = this.$root.querySelector('.bsi-form-field-input-original'); let containerDiv = this.$root.querySelector('.bsi-form-pin-element'); - const maxLength = this.bsiInputElement.getAttribute('maxlength'); - if (maxLength == null) { - this.maxlength = 6; - } else { - this.maxlength = this.bsiInputElement.getAttribute('maxlength'); - } + this.maxLength = this.bsiInputElement.getAttribute('maxlength') ?? 6; - for (let i = 0; i < this.maxlength; i++) { + for (let i = 0; i < this.maxLength; i++) { this._initPinNumberField(containerDiv, i); } }, @@ -73,59 +53,52 @@ Alpine.data('formPin', () => ({ _initPinNumberField(containerDiv, i) { let div = document.createElement('div'); let label = document.createElement('label'); - let pinInput = document.createElement('input'); + let inputPin = document.createElement('input'); div.classList = 'input-wrapper'; label.classList = 'form-label'; label.innerHTML = (i + 1) + "."; - pinInput.classList = 'bsi-form-field-input form-control bsi-form-field-input pin'; + inputPin.classList = 'bsi-form-field-input form-control bsi-form-field-input pin'; - pinInput.setAttribute('x-init', 'initFormPinInput'); - pinInput.setAttribute('required', 'true'); + inputPin.setAttribute('required', 'true'); + inputPin.setAttribute('inputmode', 'numeric'); + inputPin.setAttribute('type', "number"); div.appendChild(label); - div.appendChild(pinInput); + div.appendChild(inputPin); containerDiv.appendChild(div); - }, - - initFormPinInput() { - let inputPin = this.$el; - inputPin.setAttribute('inputmode', 'numeric'); - inputPin.setAttribute('pattern', "[0-9]"); inputPin.addEventListener('focusin', (e) => { inputPin.setAttribute('old', inputPin.value); }); inputPin.addEventListener('keydown', (e) => { - if (e.key ==='Backspace' && !inputPin.value) { - this._autoFocusPreviousPinInput(); + if ((e.key =='Backspace') && !inputPin.value) { + this._autoFocusPreviousPinInput(inputPin); } }); - + inputPin.addEventListener('input', (e) => { const inputPinList = this.$root.querySelectorAll('input.pin'); - this._cleanUp(); + this._cleanUp(inputPin); this.bsiInputElement.value = Array.from(inputPinList).reduce((result, input) => { return result + input.value; }, ""); if (this.$root.classList.contains('auto-submit')) { this._autoSubmitIfFilledIn(); } - this._autoFocusNextPinInput(); + this._autoFocusNextPinInput(inputPin); }); }, - _autoFocusNextPinInput() { - let inputPin = this.$el; + _autoFocusNextPinInput(inputPin) { let nextWrapper = inputPin.parentNode.nextElementSibling; - if (inputPin.value && !this._isLastPinElement()) { + if (inputPin.value && !this._isLastPinElement(inputPin)) { this._autoFocus(nextWrapper); } }, - _autoFocusPreviousPinInput() { - let inputPin = this.$el; + _autoFocusPreviousPinInput(inputPin) { let previousWrapper = inputPin.parentNode.previousSibling; if (previousWrapper != null) { this._autoFocus(previousWrapper); @@ -140,40 +113,26 @@ Alpine.data('formPin', () => ({ }, _autoSubmitIfFilledIn() { - let form = this.$root.querySelector('.formular-pin');; - if (form && (this.bsiInputElement.value.length == this.maxlength)) { + let form = this.$root.querySelector('.formular-pin'); + if (form && (this.bsiInputElement.value.length == this.maxLength)) { form.submit(); } }, - _cleanUp() { - // TODO: auch im DOM lösbar? - let inputPin = this.$el; + _cleanUp(inputPin) { if (inputPin.value) { - if (this._isLastPinElement()){ + if (this._isLastPinElement(inputPin)){ inputPin.value = inputPin.value.slice(-1); - } - - const numberPattern = /^[0-9]+$/; - if (inputPin.value.length > 1) { + } else if (inputPin.value.length > 1) { var oldValue = inputPin.getAttribute('old'); - var currentValue = inputPin.value; - - if (!numberPattern.test(inputPin.value)) { - inputPin.value = oldValue; - } else { - var newValue = currentValue.replace(oldValue, ''); - inputPin.value = newValue; - oldValue = newValue; + var newValue = inputPin.value.replace(oldValue, ''); + inputPin.value = newValue; + oldValue = newValue; } - - } else if (!numberPattern.test(inputPin.value)) { - inputPin.value = null; - } } }, - _isLastPinElement() { - return this.$el.parentNode.nextElementSibling == null; + _isLastPinElement(inputPin) { + return inputPin.parentNode.nextElementSibling == null; }, })); diff --git a/content-elements/form/form-pin/index.js b/content-elements/form/form-pin/index.js index 00548e9..3a97aaf 100644 --- a/content-elements/form/form-pin/index.js +++ b/content-elements/form/form-pin/index.js @@ -16,7 +16,6 @@ element.withFile(require('./template.twig')) require('../../../configs/styles/form-width'), require('../../../configs/styles/form-layout'), require('../../../configs/styles/form-color'), - require('../../../configs/styles/form-info-text'), require('../../../configs/styles/pin-label'), require('../../../configs/styles/pin-auto-submit')) .withParts( diff --git a/content-elements/form/form-pin/styles.scss b/content-elements/form/form-pin/styles.scss index b6e287b..5c1ce66 100644 --- a/content-elements/form/form-pin/styles.scss +++ b/content-elements/form/form-pin/styles.scss @@ -129,25 +129,6 @@ list-style-type: none; } - .form-label-and-info-text { - &.contains-tooltip { - display: flex; - gap: 0.5rem; - - .form-text { - display: none; - } - } - - i.bi-info-circle { - display: none; - - &.tooltip-visible { - display: block; - } - } - } - .hide { display: none; } .bsi-form-pin-element { @@ -203,9 +184,4 @@ background-image: none !important; background-color: rgb(217, 19, 41, 0.05) !important; border: 1px solid #d91329 !important; -} - -.bsi-tooltip { - --bs-tooltip-bg: var(--bs-gray-dark); - --bs-tooltip-color: var(--bs-light); } \ No newline at end of file diff --git a/content-elements/form/form-pin/template.twig b/content-elements/form/form-pin/template.twig index ab5402d..43ecb3c 100644 --- a/content-elements/form/form-pin/template.twig +++ b/content-elements/form/form-pin/template.twig @@ -24,7 +24,6 @@
{{ formFieldInfoText }}
-
From 48714cbe995b2fed6244063922aa2368624dc43a Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Tue, 30 Apr 2024 09:57:47 +0200 Subject: [PATCH 8/9] auto focus first input --- content-elements/form/form-pin/form-pin.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/content-elements/form/form-pin/form-pin.js b/content-elements/form/form-pin/form-pin.js index 8bc9509..2b2979f 100644 --- a/content-elements/form/form-pin/form-pin.js +++ b/content-elements/form/form-pin/form-pin.js @@ -44,10 +44,10 @@ Alpine.data('formPin', () => ({ let containerDiv = this.$root.querySelector('.bsi-form-pin-element'); this.maxLength = this.bsiInputElement.getAttribute('maxlength') ?? 6; - for (let i = 0; i < this.maxLength; i++) { this._initPinNumberField(containerDiv, i); } + this._autoFocusFirstPinInput(); }, _initPinNumberField(containerDiv, i) { @@ -91,6 +91,11 @@ Alpine.data('formPin', () => ({ }); }, + _autoFocusFirstPinInput() { + let wrapper = this.$root.querySelectorAll('.input-wrapper'); + this._autoFocus(wrapper[0]); + }, + _autoFocusNextPinInput(inputPin) { let nextWrapper = inputPin.parentNode.nextElementSibling; if (inputPin.value && !this._isLastPinElement(inputPin)) { From 5c40baa136772bff17c1c563d7c3a9306dfa0108 Mon Sep 17 00:00:00 2001 From: Sophia Wild Date: Thu, 26 Sep 2024 17:29:37 +0200 Subject: [PATCH 9/9] pin styling --- content-elements/form/form-pin/styles.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content-elements/form/form-pin/styles.scss b/content-elements/form/form-pin/styles.scss index 5c1ce66..81b6d1f 100644 --- a/content-elements/form/form-pin/styles.scss +++ b/content-elements/form/form-pin/styles.scss @@ -1,6 +1,6 @@ @import "../../../styles/properties"; -.bsi-element-form-container-692qIu { +.form-container-pin-384aa4d6 { padding-right: 0px; padding-left: 0px;