PageSourceSearch

https://www.henkvanderveer.nl/modules/lib.js

js henkvanderveer.nl collected 2026-10-02 14:15:20 UTC 18,460 bytes, 433 lines download raw bytes

1'use strict';
2
3export const lib = {
4    ajax: function (method, url, data, cb) {
5        let r = new XMLHttpRequest();
6        if (typeof cb === 'function') {
7            r.onreadystatechange = function () {
8                if (this.readyState === 4 && this.status !== 0) {
9                    try {
10                        if (this.status >= 200 && this.status < 400) {
11                            cb(this.responseText);
12                            // } else {
13                            //     cb(null); // is dit slim?
14                        }
15                    } catch (e) {
16                        if (url !== '/e') {
17                            let data2 = {
18                                data: {
19                                    method: method, url: url, data: data, cb: cb, status: this.status, response: this.responseText
20                                }, error: null
21                            }
22                            try {
23                                data2.error = {
24                                    error: e.error, filename: e.filename, lineno: e.lineno, colno: e.colno, message: e.message
25                                };
26                            } catch (e) {
27                            }
28                            ajax('POST', '/e', data2);
29                        }
30                        throw e;
31                    }
32                }
33            };
34        }
35        r.open(method, url, true);
36        r.setRequestHeader("Cache-Control", "no-cache, no-store, must-revalidate");
37        r.setRequestHeader("X-Requested-With", "XMLHttpRequest");
38        if (data instanceof FormData) {
39        } else {
40            r.setRequestHeader("Content-type", "application/json");
41            data = JSON.stringify(data);
42        }
43        r.send(data);
44        return r;
45    },
46
47    getJSON: function (url, cb) {
48        const controller = new AbortController();
49        fetch(url, {signal: controller.signal, headers: {'X-Requested-With': 'XMLHttpRequest'}}).then((response) => response.json()).then(cb).catch((e) => {
50            console.log(e);
51        });
52        return controller;
53    },
54
55    postJSON: function (url, data, cb) {
56        return ajax('POST', url, data, function (result) {
57            if (typeof cb === 'function') {
58                let json = null;
59                try {
60                    json = JSON.parse(result);
61                } catch (e) {
62                }
63                cb(json)
64            }
65        });
66    },
67
68    delayed: function (fn, delay) {
69        let d = function () {
70            if (d.t) {
71                clearTimeout(d.t);
72            }
73            d.t = setTimeout(fn, delay);
74        }
75        d.t = null;
76        return d;
77    }, cookies: {
78        set: function (key, value, expiry) { // expiry in days
79            let expires = '';
80            if (expiry) {
81                let d = new Date();
82                d.setTime(d.getTime() + (expiry * 24 * 60 * 60 * 1000));
83                expires = ';expires=' + d.toUTCString();
84            }
85            document.cookie = key + '=' + value + expires + ';SameSite=Strict;secure';
86        }, get: function (key) {
87            let keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');
88            return keyValue ? keyValue[2] : null;
89        }
90    }, dedupe: function (arr) {
91        return Array.from(new Set(arr));
92    }, form: {
93        serialize: function (form, complex) {
94            let obj = {}, data = new FormData(form);
95
96            for (let [name, value] of data) {
97                let basename = name.replace(/^(.*)\[.*\]$/, '$1');
98                let name2 = complex !== true ? name.replace(/^(.*)\[\]$/, '$1') : name;
99
100                let el = form[name];
101                if (!el) {
102                    console.log(el, form, name);
103                }
104                if (el instanceof RadioNodeList) {
105                    el = el[0];
106                    if (el.type === 'checkbox') {
107                        value = [value];
108                        if (obj[name2]) value = obj[name2].concat(value);
109                    }
110                }
111
112                let d = el.closest('[data-type]');
113                switch (d.getAttribute('data-type')) {
114                    case 'slider':
115                        if (value === '0') {
116                            value = '';
117                        }
118                        break;
119                }
120                //if (/*value === '' ||*/ ['lastminutes'].includes(name)) continue;
121                if (/*value === '' ||*/ ['lastminutes'].includes(name)) continue;
122
123                if (name !== basename && form[basename]) {
124                    if (form[basename].value === '') {
125                        continue; // gasten selectie
126                    }
127                }
128                let match = name2.match(/^(.*)(\[.*?\])$/);
129                if (match) {
130                    let temp = obj;
131                    let matches = match[2].match(/\[([^\]]*)\]/g);
132                    matches.unshift('[' + match[1] + ']');
133                    for (let i = 0, j = matches.length; i < j; i++) {
134                        let key = matches[i].slice(1, -1);
135                        if (typeof temp[key] === 'undefined') {
136                            temp[key] = i + 1 < j ? {} : value;
137                        }
138                        temp = temp[key];
139                    }
140                } else {
141                    obj[name2] = value;
142                }
143            }
144
145            return obj;
146        }, clear: function (form) {
147            let data = {};
148            for (let i = 0; i < form.elements.length; i++) {
149                data[form.elements[i].name] = '';
150            }
151            Lib.form.fill(form, data);
152        }, fill: function (form, data, complex) {
153            let value, el;
154            return Object.keys(data).map(function (name) {
155                let name2 = (complex !== true && form[name + '[]']) ? name + '[]' : name;
156                if (form[name2] && !form[name2].disabled) {
157                    value = data[name].toString();
158                    el = form.elements[name2];
159                    if (!el) return;
160                    if (el instanceof RadioNodeList) {
161                        for (let i = 0; i < el.length; i++) {
162                            if (el[i].type === 'checkbox') {
163                                if (value.includes(el[i].value)) el[i].checked = true;
164                            } else {
165                                if (el[i].value === value) el[i].checked = true;
166                            }
167                        }
168                    } else {
169                        if (el = el.closest('[data-type]')) {
170                            switch (el.getAttribute('data-type')) {
171                                case 'checkbox':
172                                    if (value) {
173                                        if (!form[name2].checked) {
174                                            form[name2].checked = true;
175                                            form[name2].dispatchEvent(new Event('change', {
176                                                bubbles: true, cancelable: false
177                                            }));
178                                        }
179                                    }
180                                    break;
181                                default:
182                                    if (form[name2].value !== value) {
183                                        form[name2].value = value;
184                                        form[name2].dispatchEvent(new Event('change', {
185                                            bubbles: true, cancelable: false
186                                        }));
187                                    }
188                                    break;
189                            }
190                        }
191                    }
192                }
193            });
194        }, onsubmit: function (e) {
195            console.log(this, e);
196            let form = this;
197            e.preventDefault();
198            var loader = new moduleLoader(form);
199            loader.show();
200            let postData = new FormData(form);
201            let request = new XMLHttpRequest();
202            let alert_danger = form.querySelector('.alert--danger');
203            let alert_success = form.querySelector('.alert--success');
204            if (alert_danger) alert_danger.classList.remove('alert--visible');
205            if (alert_success) alert_success.classList.remove('alert--visible');
206
207            form.querySelectorAll('[data-name]').forEach(function (node) {
208                node.classList.remove('input-error');
209            });
210
211            request.open('POST', '', true);
212            request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
213            if (form.closest('.popup .popup__content') || form.closest('.popup-dialog .popup-dialog__content')) {
214                request.setRequestHeader('X-Posted-From', 'popup');
215            }
216
217            request.onreadystatechange = function () {
218                if (this.readyState === 4) {
219                    try {
220                        if (this.status === 200) {
221                            let response = null;
222                            try {
223                                response = JSON.parse(this.responseText);
224                            } catch (e) {
225                                if (alert_danger) {
226                                    alert_danger.querySelector('.alert--inner').innerHTML = 'Er is een onverwachte fout opgetreden.';
227                                    alert_danger.classList.add('alert--visible');
228                                }
229                                loader.hide();
230                                return;
231                            }
232
233                            if (response.success) {
234                                if (typeof gtag === 'function') {
235                                    gtag('event', 'mm_form_sent', {mm_id: form.dataset.id});
236                                }
237                                if (document.location && response.action === 'redirect') {
238                                    document.location = response.data.redirect;
239                                    return; // keep the loader
240                                } else if (response.action === 'refresh') {
241                                    let r = document.createElement('meta');
242                                    r.httpEquiv = 'refresh';
243                                    r.content = 0;
244                                    document.documentElement.appendChild(r);
245                                    return;
246                                } else {
247                                    if (alert_success) {
248                                        display_messages(alert_success, response);
249                                    }
250                                    form.reset();
251                                }
252                            } else {
253                                if (alert_danger) {
254                                    if (response.data && response.data.message) { // zie LayerForm:500
255                                        alert_danger.querySelector('.alert--inner').innerHTML = response.data.message;
256                                    }
257                                    display_messages(alert_danger, response);
258                                }
259
260                                if (response.errors && Object.keys(response.errors).length) {
261                                    for (let id in response.errors) {
262                                        let node = form.querySelector('[data-name="' + id + '"]');
263                                        if (node) {
264                                            node.classList.add('input-error');
265                                            node.dataset.error = response.errors[id];
266                                        }
267                                    }
268                                    if (alert_danger) alert_danger.classList.add('alert--visible');
269                                }
270                            }
271
272                        }
273                    } catch (e) {
274                        loader.hide();
275                        throw e;
276                    }
277                    loader.hide();
278                }
279            };
280            request.send(postData);
281
282            function display_messages(node, response) {
283                if (response.messages && Array.isArray(response.messages)) {
284                    if (response.messages.length > 1) {
285                        node.querySelector('.alert--inner').innerHTML = '<ul>' + response.messages.map(s => '<li>' + s + '</li>').join('') + '</ul>';
286                    } else {
287                        node.querySelector('.alert--inner').innerHTML = response.messages[0];
288                    }
289                }
290                node.classList.add('alert--visible');
291            }
292        }
293    }, url: function (base, qs, hash) {
294        if (typeof qs === 'object') qs = Lib.qs.build(qs);
295        if (typeof hash === 'object') hash = Lib.qs.build(hash);
296        return base + (qs ? '?' + qs : '') + (hash ? '#' + hash : '');
297    }, qs: {
298        parse: function (url) {
299            if (typeof url === 'undefined') url = location.search.slice(1);
300            let pairs = url.split('&');
301            let result = {}, k;
302            pairs.forEach(function (pair) {
303                pair = pair.split('=');
304                if ((pair.length === 2) && (k = decodeURIComponent(pair[0]))) {
305                    result[k] = decodeURIComponent(pair[1].replace(/\+/g, ' ') || '');
306                }
307            });
308            return result;
309        }, build: function (obj) {
310            let s = function (o, base) {
311                if (typeof o !== 'object') {
312                    return '=' + encodeURIComponent(o);
313                }
314                return Object.keys(o).filter(function (k) {
315                    return obj[k] !== '' && obj[k] !== null;
316                }).map(function (k) {
317                    return (base || '') + '[' + encodeURIComponent(k) + "]" + s(o[k]);
318                }).join("&");
319            }
320
321            let m = function (obj) {
322                return Object.keys(obj).filter(function (k) {
323                    return obj[k] !== '' && obj[k] !== null;
324                }).map(function (k) {
325                    if (typeof obj[k] !== 'object') {
326                        if (obj[k] !== '' && obj[k] !== null) {
327                            return encodeURIComponent(k) + "=" + encodeURIComponent(obj[k]);
328                        }
329                        return null;
330                    }
331                    return s(obj[k], encodeURIComponent(k));
332                }).join("&");
333            }
334            return m(obj);
335        },
336    }, format: {
337        dateToISO: function (date) {
338            if (!date) return null;
339            const year = date.getFullYear(), month = date.getMonth() + 1, day = date.getDate();
340            return [year, month < 10 ? '0' + month : month, day < 10 ? '0' + day : day].join('-');
341        }, dateToLocalDateString: function (date) {
342            let day = ('0' + date.getDate()).slice(-2);
343            let monthIndex = ('0' + (date.getMonth() + 1)).slice(-2);
344            let year = date.getFullYear();
345            return day + '-' + monthIndex + '-' + year;
346        }, dateToShortLocalDateString: function (date) {
347            return date.toLocaleDateString('nl', {day: 'numeric', month: 'short', year: '2-digit'});
348        }, moneyFormat: function (s, d) {
349            return s ? s.toFixed(isNaN(parseInt(d)) ? 2 : parseInt(d)).replace(/\./g, ',') : '';
350        },
351    }, deepMerge: function (obj1, obj2) {
352        const f = (obj1, obj2) => {
353            for (let key in obj2) {
354                if (obj2.hasOwnProperty(key)) {
355                    if (obj2[key] instanceof Object && obj1[key] instanceof Object) {
356                        obj1[key] = f(obj1[key], obj2[key]);
357                    } else {
358                        obj1[key] = obj2[key];
359                    }
360                }
361            }
362            return obj1;
363        }
364        return f(obj1, obj2);
365    }, process_queue: function (queue, callback) {
366        if (queue.length) {
367            queue = [...queue]; // make a copy
368            const q = function () {
369                if (queue.length) {
370                    let called = false;
371                    if (false !== queue.pop()(function () {
372                        called = true;
373                        q()
374                    }) && !called) {
375                        q();
376                    }
377                } else if (typeof callback === 'function') {
378                    callback();
379                }
380            };
381            q();
382        } else if (typeof callback === 'function') {
383            callback();
384        }
385    },
386    hover: function (element, {onHover, onHoverEnd}) {
387        let isTouchUsed = false; // Track real touch interactions
388
389        init();
390
391        function init() {
392            window.addEventListener("touchstart", () => {
393                isTouchUsed = true;
394                console.log('touchstart');
395            }, {passive: true});
396
397            window.addEventListener("mousemove", () => {
398                // console.log('mousemove');
399                isTouchUsed = false; // If mouse moves, assume it's a real mouse
400            });
401
402            element.addEventListener("mouseenter", handleHover.bind(this));
403            element.addEventListener("mouseleave", handleHoverEnd.bind(this));
404            element.addEventListener("click", handleClick.bind(this));
405            document.addEventListener("click", handleClickOutside.bind(this));
406        }
407
408        function handleHover(e) {
409            console.log(isTouchUsed, e);
410            if (!isTouchUsed) onHover(e); // Only trigger hover if it's a real mouse
411        }
412
413        function handleHoverEnd(e) {
414            console.log(isTouchUsed, e);
415            if (!isTouchUsed) onHoverEnd(e);
416        }
417
418        function handleClick(event) {
419            event.stopPropagation();
420            if (element.classList.contains("active")) {
421                onHoverEnd(event);
422            } else {
423                onHover(event);
424            }
425        }
426
427        function handleClickOutside(event) {
428            if (!element.contains(event.target)) {
429                onHoverEnd(event);
430            }
431        }
432    }
433}

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.