PageSourceSearch

https://www.hacienda.cl/assets/@confidare/ui-bundle/controller-6c3ir77.js

js hacienda.cl collected 2026-09-24 08:41:48 UTC 14,750 bytes, 425 lines download raw bytes

1import { Controller } from '@hotwired/stimulus';
2import * as bootstrap from 'bootstrap';
3
4export default class extends Controller {
5    static targets = [ "modal", "offcanvas" ]
6
7    modal
8    offcanvas
9    focused
10
11    connect() {
12        //
13        // Preparar offcanvas
14        //
15        const offcanvas_selector = 'data-confidare--ui--ui-target="offcanvas"';
16
17        document.body.insertAdjacentHTML('beforeend', `
18            <div class="offcanvas offcanvas-end" tabindex="-1" ${offcanvas_selector}>
19                <div class="offcanvas-header">
20                    <div class="offcanvas-title w-100"></div>
21                </div>
22                <div class="offcanvas-body">
23                </div>
24            </div>
25        `)
26
27        this.offcanvas = new bootstrap.Offcanvas(`[${offcanvas_selector}]`);
28
29        document
30            .querySelector(`[${offcanvas_selector}]`)
31            .addEventListener(
32                'shown.bs.offcanvas',
33                ev => {
34                    ev.target.querySelector('button, a')?.focus();
35                }
36            );
37
38        //
39        // Preparar modal
40        //
41
42        const modal_selector = 'data-confidare--ui--ui-target="modal"';
43
44        document.body.insertAdjacentHTML('beforeend', `
45            <div class="modal" tabindex="-1" ${modal_selector}>
46                <div class="modal-dialog modal-lg modal-dialog-centered">
47                    <div class="modal-content">
48                        <div class="modal-header">
49                            <div class="modal-title"></div>
50                        </div>
51                        <div class="modal-body">
52                        </div>
53                    </div>
54                </div>
55            </div>
56        `)
57
58        this.modal = new bootstrap.Modal(`[${modal_selector}]`);
59
60        document
61            .querySelector(`[${modal_selector}]`)
62            .addEventListener(
63                'shown.bs.modal',
64                ev => {
65                    ev.target.querySelector('button, a')?.focus();
66                }
67            );
68        //
69        // Reaplicar búsquedas rápidas guardadas
70        //
71        document.querySelectorAll('input[type=search]').forEach((input) => {
72            const stored_search = sessionStorage.getItem(
73                this.quickSearchSessionKey(
74                    input.getAttribute('data-filter-selector')
75                )
76            );
77
78            if (stored_search !== null) {
79                input.value = stored_search;
80            }
81
82            input.dispatchEvent(new Event('search'));
83        });
84
85        //
86        // Observar scroll para aplicar header-not-at-top
87        //
88        if (
89            "IntersectionObserver" in window &&
90            "IntersectionObserverEntry" in window &&
91            "intersectionRatio" in window.IntersectionObserverEntry.prototype
92        ) {
93            document.body.insertAdjacentHTML('afterbegin', '<div id="top"></div>');
94
95            let observer = new IntersectionObserver(entries => {
96                if (entries[0].boundingClientRect.y < 0) {
97                    document.body.classList.add("header-not-at-top");
98                    document.body.classList.remove("header-at-top");
99                } else {
100                    document.body.classList.add("header-at-top");
101                    document.body.classList.remove("header-not-at-top");
102                }
103            });
104            observer.observe(document.querySelector("#top"));
105        }
106    }
107
108    focus(elem) {
109        if (this.focused) {
110            this.focused.classList.remove('focus')
111        }
112
113        elem.classList.add('focus')
114        this.focused = elem
115    }
116
117    inLocalContainer(ev) {
118        const container = document.querySelector(ev.params.container)
119        container.innerText = ''
120        container.insertAdjacentHTML('beforeend', '<div class="d-flex justify-content-center"><div class="spinner-border text-primary" role="status"></div></div>');
121
122        ev.preventDefault()
123
124        this.focus(ev.currentTarget)
125
126        const context = this
127
128        fetch(ev.currentTarget.getAttribute('href'), {
129            method: 'GET',
130            mode: 'same-origin',
131            cache: 'no-cache'
132        })
133            .then(response => response.text())
134            .then(data => {
135                var parser = new DOMParser()
136                var doc = parser.parseFromString(data, 'text/html')
137
138                container.innerText = ''
139                container.appendChild(doc.querySelector('.title'))
140                container.appendChild(doc.querySelector('.body'))
141
142                const popoverTriggerList = container.querySelectorAll('[data-bs-toggle="popover"]')
143                const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
144            })
145
146    }
147
148    inModal(ev) {
149        ev.preventDefault()
150        const context = this
151        fetch(ev.currentTarget.getAttribute('href'), {
152            method: 'GET',
153            mode: 'same-origin',
154            cache: 'no-cache'
155        })
156            .then(response => response.text())
157            .then(data => {
158                var parser = new DOMParser()
159                var doc = parser.parseFromString(data, 'text/html')
160
161                context.modal._element.querySelector('.modal-title').innerText = ''
162                context.modal._element.querySelector('.modal-title').appendChild(
163                    doc.querySelector(ev.sourceTitle ?? '.title') ?? document.createElement('div')
164                )
165
166                context.modal._element.querySelector('.modal-body').innerText = ''
167                context.modal._element.querySelector('.modal-body').appendChild(
168                    doc.querySelector(ev.sourceBody ?? '.body') ?? document.createElement('div')
169                )
170
171                context.openModal(context.modal._element)
172            })
173
174    }
175
176    inOffcanvas(ev) {
177        ev.preventDefault()
178        const context = this
179        fetch(ev.currentTarget.getAttribute('href'), {
180            method: 'GET',
181            mode: 'same-origin',
182            cache: 'no-cache'
183        })
184            .then(response => response.text())
185            .then(data => {
186                var parser = new DOMParser()
187                var doc = parser.parseFromString(data, 'text/html')
188
189                context.offcanvas._element.querySelector('.offcanvas-title').innerText = ''
190                context.offcanvas._element.querySelector('.offcanvas-title').appendChild(
191                    doc.querySelector(ev.sourceTitle ?? '.title') ?? document.createElement('div')
192                )
193
194                context.offcanvas._element.querySelector('.offcanvas-body').innerText = ''
195                context.offcanvas._element.querySelector('.offcanvas-body').appendChild(
196                    doc.querySelector(ev.sourceBody ?? '.body') ?? document.createElement('div')
197                )
198
199                context.openOffCanvas(context.offcanvas._element)
200            })
201
202    }
203
204    openOffCanvas() {
205        this.offcanvas.show()
206
207        const popoverTriggerList = this.offcanvas._element.querySelectorAll('[data-bs-toggle="popover"]')
208        const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
209    }
210
211    openModal() {
212        this.modal.show()
213
214        const popoverTriggerList = this.offcanvas._element.querySelectorAll('[data-bs-toggle="popover"]')
215        const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
216    }
217
218    confirm(ev) {
219        const ctx = this
220        const oc_title = this.offcanvasTarget.querySelector('.offcanvas-title')
221        const oc_body = this.offcanvasTarget.querySelector('.offcanvas-body')
222
223        ev.preventDefault()
224
225        oc_title.innerHTML = '<span class="lead">' + ev.currentTarget.getAttribute('data-confirm-title') + '</span>'
226        oc_body.innerText = ev.currentTarget.getAttribute('data-confirm-body')
227
228        var butg = document.createElement('div')
229        butg.classList.add('btn-group', 'd-flex', 'mt-3')
230
231        var btn_y = document.createElement('a')
232        btn_y.setAttribute('href', ev.currentTarget.getAttribute('href'))
233        btn_y.innerHTML = '<i class="bi bi-exclamation-triangle"></i> Sí'
234        btn_y.classList.add('btn', 'btn-danger')
235
236        var btn_n = document.createElement('a')
237        btn_n.textContent = 'No'
238        btn_n.classList.add('btn', 'btn-outline-secondary')
239        btn_n.addEventListener('click', () => {
240            ctx.offcanvas.hide()
241        })
242
243        butg.appendChild(btn_y)
244        butg.appendChild(btn_n)
245
246        oc_body.appendChild(butg)
247
248        this.offcanvas.show()
249    }
250
251    confirmForm(ev) {
252        const ctx = this
253        const oc_title = this.offcanvasTarget.querySelector('.offcanvas-title')
254        const oc_body = this.offcanvasTarget.querySelector('.offcanvas-body')
255
256        ev.preventDefault()
257
258        oc_title.innerHTML = '<span class="lead">' + ev.currentTarget.getAttribute('data-confirm-title') + '</span>'
259        oc_body.innerText = ev.currentTarget.getAttribute('data-confirm-body')
260
261        var butg = document.createElement('div')
262        butg.classList.add('btn-group', 'd-flex', 'mt-3')
263
264        var btn_y = document.createElement('a')
265        btn_y.setAttribute('href', '#')
266        btn_y.innerHTML = '<i class="bi bi-exclamation-triangle"></i> Sí'
267        btn_y.classList.add('btn', 'btn-danger')
268        btn_y.addEventListener('click', () => {
269            ctx.offcanvas.hide()
270            ev.target.submit()
271        })
272
273        var btn_n = document.createElement('a')
274        btn_n.textContent = 'No'
275        btn_n.classList.add('btn', 'btn-outline-secondary')
276        btn_n.addEventListener('click', () => {
277            ctx.offcanvas.hide()
278        })
279
280        butg.appendChild(btn_y)
281        butg.appendChild(btn_n)
282
283        oc_body.appendChild(butg)
284
285        this.offcanvas.show()
286    }
287
288    prompt(ev) {
289        ev.preventDefault()
290
291        const ctx = this
292        const oc_title = this.offcanvasTarget.querySelector('.offcanvas-title')
293        const oc_body = this.offcanvasTarget.querySelector('.offcanvas-body')
294        const t = ev.currentTarget
295        const required = (t.getAttribute('data-prompt-required') ?? 'required') == 'required'
296        const w_attr = 'id="confidare--ui--ui--prompt--obs" name="obs" class="form-control"'
297
298        var widget;
299        switch (t.getAttribute('data-prompt-widget')) {
300            case 'input':
301            case 'text':
302                widget = `<input ${w_attr} ${required? 'required': ''}>`
303                break
304            case 'pin':
305                widget = `<input type="password" pattern="[0-9]*" autocomplete="one-time-code" pattern="[0-9]{4}" maxlength="4" inputmode="numeric" ${w_attr} ${required? 'required': ''}>`
306                break
307            default:
308                widget = `<textarea ${w_attr} ${required? 'required': ''}></textarea>`
309                break
310        }
311
312        oc_title.innerHTML = '<span class="lead">' + t.getAttribute('data-prompt-title') + '</span>'
313        oc_body.innerText = t.getAttribute('data-prompt-body')
314        oc_body.insertAdjacentHTML('beforeend', `
315            <form action="${t.getAttribute('href')}" method="${t.getAttribute('data-prompt-method') ?? 'GET'}">
316                <label for="confidare--ui--ui--prompt--obs" class="form-label mt-3">
317                    ${t.getAttribute('data-prompt-label')}
318                    ${required? '': '<small>(opcional)</small>'}
319                </label>
320                ${widget}
321                <div class="btn-group d-flex mt-3">
322                    <button type="submit" class="btn-primary btn">Aceptar</button>
323                    <a href="#" class="btn btn-outline-secondary">Cancelar</a>
324                </div>
325            </form>
326        `)
327
328        oc_body.querySelector('a').addEventListener('click', () => {
329            ctx.offcanvas.hide()
330        })
331
332        this.offcanvas.show()
333
334        this.offcanvas._element.addEventListener(
335            'shown.bs.offcanvas',
336            ev => {
337                ev.target.querySelector('*[name="obs"]').focus();
338            }
339        );
340    }
341
342    filter(ev) {
343        sessionStorage.setItem(
344            this.quickSearchSessionKey(ev.currentTarget.getAttribute('data-filter-selector')),
345            ev.currentTarget.value,
346        );
347
348        var resultados = 0;
349
350        document.querySelectorAll(
351            ev
352            .currentTarget
353            .getAttribute('data-filter-selector')
354        ).forEach((elem) => {
355            var selector;
356            var search_in;
357
358            if ((selector = ev.currentTarget.getAttribute('data-filter-text')) != null) {
359                search_in = elem.querySelector(selector).textContent;
360            } else {
361                search_in = elem.textContent;
362            }
363
364            if (
365                ev.currentTarget.value == '' ||
366                this.normalize(search_in).includes(
367                    this.normalize(ev.currentTarget.value)
368                )
369            ) {
370                elem.style.display = '';
371                resultados++;
372            } else {
373                elem.style.display = 'none';
374            }
375        })
376
377        ev.currentTarget.classList.remove('border-info');
378        ev.currentTarget.classList.remove('border-danger');
379
380        if (ev.currentTarget.value != '') {
381            if (resultados > 0) {
382                ev.currentTarget.classList.add('border-info');
383            } else {
384                ev.currentTarget.classList.add('border-danger');
385            }
386        }
387
388        document.querySelector(ev.currentTarget.getAttribute('data-filter-selector')).parentElement.classList.remove('d-none');
389    }
390
391    quickSearchSessionKey(dataFilterSelector) {
392        return 'quick_search_' + this.slugify(dataFilterSelector) + '_' + this.slugify(window.location);
393    }
394
395    normalize(string) {
396        return string
397            .toUpperCase()
398            .normalize('NFD')
399            .replace(/\p{Diacritic}/gu, '');
400    }
401
402    slugify(string) {
403        return string
404            .toString()
405            .normalize('NFKD')
406            .toLowerCase()
407            .trim()
408            .replace(/\s+/g, '_')
409            .replace(/[^\w\_]+/g, '_')
410            .replace(/\_\_+/g, '_');
411    }
412
413    popup(ev) {
414        const modal_id = ev.params.id;
415        const session_key = 'popup_dismissed_' + ev.params.id;
416        const once = ev.params.once;
417
418        if (!once || !sessionStorage.getItem(session_key)) {
419            const popup = new bootstrap.Modal(document.getElementById(modal_id), {})
420            popup.show()
421
422            sessionStorage.setItem(session_key, 1);
423        }
424    }
425}

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.