PageSourceSearch

https://www.bielersee.ch/_assets/7aa38234bb2f6c17b0ab46a08d2f8843/JavaScript/Frontend/form.js?1780305262

js bielersee.ch collected 2026-10-02 11:43:13 UTC 3,505 bytes, 168 lines download raw bytes

1class RecaptchaForm {
2  /**
3   * @type {string}
4   */
5  #fieldSelector = '[data-recaptcha-form-field]';
6
7  #submitSelector = '[data-recaptcha-form-submit]';
8
9  #invisibleSubmitSelector = '[data-invisible-recaptcha-form-submit]';
10
11  /**
12   * @type {Recaptcha}
13   */
14  #recaptcha = null;
15
16  /**
17   * @type {HTMLFormElement}
18   */
19  #form = null;
20
21  /**
22   * @type {HTMLInputElement}
23   */
24  #field = null;
25
26  /**
27   * @param {Recaptcha} recaptcha
28   * @param {HTMLFormElement} form
29   */
30  constructor(recaptcha, form) {
31    this.#recaptcha = recaptcha;
32    this.#form = form;
33
34    this.initializeElements(form);
35    this.initializeEvents();
36  }
37
38  /**
39   * @param {HTMLFormElement} form
40   */
41  initializeElements(form) {
42    this.#field = form.querySelector(this.#fieldSelector);
43  }
44
45  initializeEvents() {
46    // used with visible recaptcha
47    [...this.#form.querySelectorAll(this.#submitSelector)]
48      .map(button => button.addEventListener('click', event => this.visibleRecaptchaButtonClicked(event)));
49    // used with invisible recaptcha
50    [...this.#form.querySelectorAll(this.#invisibleSubmitSelector)]
51      .map(button => button.addEventListener('click', () => this.#recaptcha.setLastForm(this)));
52  }
53
54  /**
55   * @param {PointerEvent} event
56   */
57  visibleRecaptchaButtonClicked(event) {
58    if (!this.#form.reportValidity() || !this.fieldValid()) {
59      event.preventDefault();
60    }
61  }
62
63  /**
64   * @return {boolean}
65   */
66  fieldValid() {
67    return this.#field.value !== '' && this.#field.value === this.#recaptcha.getResponse();
68  }
69
70  setFieldValue(value) {
71    this.#field.value = value;
72  }
73
74  /**
75   * @return {boolean}
76   */
77  reportValidity() {
78    return this.#form.reportValidity();
79  }
80
81  submit() {
82    this.#form.submit();
83  }
84}
85
86class Recaptcha {
87  /**
88   * @type {RecaptchaForm[]}
89   */
90  #forms = [];
91
92  /**
93   * @type {RecaptchaForm}
94   */
95  #lastForm = null;
96
97  /**
98   * @type {string}
99   */
100  #response = '';
101
102  constructor() {
103    this.initializeForms();
104    this.registerCallback();
105  }
106
107  initializeForms() {
108    [...document.querySelectorAll('form .g-recaptcha')]
109      .map(element => {
110        const form = element.closest('form');
111        if (form) {
112          this.#forms.push(new RecaptchaForm(this, form));
113        }
114      })
115  }
116
117  registerCallback() {
118    // for box recaptcha
119    window.onRecaptchaCallback = (response) => this.recaptchaCallback(response);
120    window.onRecaptchaExpired = () => this.recaptchaExpired();
121    window.onRecaptchaError = () => this.recaptchaError();
122    // for invisible recaptcha
123    window.onRecaptchaSubmit = (response) => this.recaptchaSubmit(response);
124  }
125
126  /**
127   * @param {string} response
128   */
129  recaptchaCallback(response) {
130    this.#response = response;
131    this.#forms.forEach(form => form.setFieldValue(response));
132  }
133
134  recaptchaExpired() {
135    this.#lastForm = null;
136    this.#response = '';
137    this.#forms.forEach(form => form.setFieldValue(''));
138  }
139
140  recaptchaError() {
141    this.#lastForm = null;
142    this.#response = '';
143    this.#forms.forEach(form => form.setFieldValue(''));
144  }
145
146  /**
147   * @param {string} response
148   */
149  recaptchaSubmit(response) {
150    this.#response = response;
151    if (this.#lastForm && this.#lastForm.reportValidity()) {
152      this.#lastForm.setFieldValue(response);
153      this.#lastForm.submit();
154    }
155  }
156
157  /**
158   * @returns {string}
159   */
160  getResponse() {
161    return this.#response;
162  }
163
164  setLastForm(lastForm) {
165    this.#lastForm = lastForm;
166  }
167}
168new Recaptcha();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.