1+ import { FieldsetValidationElement } from './fieldset-validation-element.js'
2+
3+ import {
4+ skipFieldsetChangeEvent ,
5+ skipFieldsetFocusoutEvent
6+ } from './util.js'
7+
8+ import {
9+ clearErrorListForFieldset ,
10+ renderCustomErrorMessageForFieldset
11+ } from './rendering.js'
12+
13+ /**
14+ * Checks that there is at least N values in the `FormData` for the given
15+ * `fieldName` in the `fieldset`'s form.
16+ * @param {FieldsetElement } fieldset
17+ * @param {string } fieldName
18+ * @param {integer } minimum
19+ * @return {boolean } if there is at least 1 record for `fieldName` in the fieldset form's `FormData`
20+ */
21+ export function minimumCountOfFieldNameSelected ( fieldset , fieldName , minimum ) {
22+ const formData = new FormData ( fieldset . form )
23+ return formData . getAll ( fieldName ) . length >= minimum
24+ }
25+
26+
27+ /**
28+ * Calls {@link MinimumFieldValuesFieldsetValidationElement#reportValidity} unless
29+ * {@link skipFieldsetChangeEvent} returns `true`
30+ */
31+ export function changeValidationEventHandler ( event ) {
32+ if ( skipFieldsetChangeEvent ( event ) ) { return }
33+ const element = event . currentTarget
34+ element . reportValidity ( )
35+ }
36+
37+ /**
38+ * Calls {@link MinimumFieldValuesFieldsetValidationElement#reportValidity} unless
39+ * {@link focusoutValidationEventHandler} returns `true`
40+ */
41+ export function focusoutValidationEventHandler ( event ) {
42+ if ( skipFieldsetFocusoutEvent ( event ) ) { return }
43+ const element = event . currentTarget
44+ element . reportValidity ( )
45+ }
46+
47+ /**
48+ * @class
49+ * @classdesc
50+ * @extends FieldsetValidationElement
51+ * A custom element that can validate that a minimum number of values for the given `field-name`
52+ * Match `
53+ */
54+ export class MinimumFieldValuesFieldsetValidationElement extends FieldsetValidationElement {
55+ /**
56+ * Returns the value of the `min`, parsed as an Integer
57+ */
58+ get min ( ) {
59+ return Number . parseInt ( this . getAttribute ( `min` ) )
60+ }
61+
62+ /**
63+ * Returns the value of the `validation-message`, throwing a `TypeError`` if it is missing
64+ */
65+ get validationMessage ( ) {
66+ const message = this . getAttribute ( `validation-message` )
67+ if ( ! message || message . trim ( ) === "" ) { throw new TypeError ( `validation-message missing` ) }
68+
69+ return message
70+ }
71+
72+ /**
73+ * Returns the value of the `validation-message`, throwing a `TypeError`` if it is missing
74+ */
75+ get type ( ) {
76+ const type = this . getAttribute ( `type` )
77+ if ( ! type || type . trim ( ) === "" ) { throw new TypeError ( `type missing` ) }
78+
79+ return type
80+ }
81+
82+ /**
83+ * Calls:
84+ * - {@link clearErrorListForFieldset}
85+ * - {@link minimumCountOfFieldNameSelected}
86+ * - {@link renderCustomErrorMessageForFieldset}
87+ */
88+ reportValidity ( ) {
89+ clearErrorListForFieldset ( this . fieldset )
90+
91+ if ( minimumCountOfFieldNameSelected ( this . fieldset , this . fieldName , this . min ) ) {
92+ return true
93+ }
94+
95+ renderCustomErrorMessageForFieldset ( this . fieldset , this . validationMessage , this . type )
96+
97+ return false
98+ }
99+
100+ connectedCallback ( ) {
101+ super . connectedCallback ( )
102+ this . addEventListeners ( )
103+ }
104+
105+ addEventListeners ( ) {
106+ this . addEventListener ( `change` , changeValidationEventHandler )
107+ this . addEventListener ( `focusout` , focusoutValidationEventHandler )
108+
109+ const element = this
110+ const submitValidationEventHandler = function ( event ) {
111+ const isValid = element . reportValidity ( )
112+
113+ if ( ! isValid ) {
114+ event . preventDefault ( )
115+ element . fieldset . querySelector ( `input:first-child` ) . focus ( )
116+ }
117+ }
118+
119+ this . form . addEventListener ( `submit` , submitValidationEventHandler )
120+ }
121+ }
122+
123+ if ( ! window . customElements . get ( 'minimum-field-values-fieldset-validation' ) ) {
124+ window . customElements . define (
125+ 'minimum-field-values-fieldset-validation' ,
126+ MinimumFieldValuesFieldsetValidationElement )
127+ ;
128+ }
0 commit comments