PageSourceSearch

https://www.ausgezeichnet.org/assets/controllers/single-review-share_controller-mG5rkOL.js

js ausgezeichnet.org collected 2026-10-01 15:08:44 UTC 3,385 bytes, 108 lines download raw bytes

1import { Controller } from '@hotwired/stimulus';
2
3export default class extends Controller {
4    static values = {
5        url: String,
6        title: String,
7        copiedLabel: String
8    };
9
10    connect() {
11        this.element
12            .querySelectorAll('[data-event="single_review_share"]:not([data-action])')
13            .forEach((el) => {
14                el.addEventListener('click', () => this.trackShare(el.dataset.network || ''));
15            });
16    }
17
18    trackShare(network) {
19        if (window.dataLayer && typeof window.dataLayer.push === 'function') {
20            window.dataLayer.push({
21                event: 'single_review_share',
22                network,
23                url: this.urlValue
24            });
25        }
26    }
27
28    async systemShare(event) {
29        event.preventDefault();
30        if (typeof navigator.share !== 'function') {
31            return;
32        }
33        try {
34            await navigator.share({ title: this.titleValue, url: this.urlValue });
35            this.trackShare('system');
36        } catch (e) {
37
38            // User dismissed / aborted; nothing to do.
39        }
40    }
41
42    async copy(event) {
43        event.preventDefault();
44        const ok = await this.copyUrl();
45        if (ok) {
46            this.trackShare('copy');
47            this.flashCopied(event.currentTarget);
48        }
49    }
50
51    // Copies this.urlValue to clipboard. Returns true on success.
52    // Extracted so `shareInstagram` can reuse it without re-handling the event.
53    async copyUrl() {
54        const url = this.urlValue;
55        try {
56            if (navigator.clipboard && window.isSecureContext) {
57                await navigator.clipboard.writeText(url);
58                return true;
59            }
60            if (window.Util && typeof window.Util.copyToClipboard === 'function') {
61                window.Util.copyToClipboard(url);
62                return true;
63            }
64        } catch (e) {
65
66            // fall through
67        }
68        return false;
69    }
70
71    flashCopied(btn) {
72        if (!btn) {
73            return;
74        }
75        const originalLabel = btn.getAttribute('aria-label');
76        const originalTitle = btn.getAttribute('title');
77        const label = this.copiedLabelValue || 'Copied';
78        btn.setAttribute('aria-label', label);
79        btn.setAttribute('title', label);
80        btn.classList.add('sr-copied');
81
82        // Visible confirmation: floating bubble above the button (matches the
83        // inline-script path in single_review_share.html.twig). Restart cleanly
84        // on rapid re-clicks by replacing any existing bubble.
85        const existing = btn.querySelector('.sr-copied-toast');
86        if (existing) {
87            existing.remove();
88        }
89        const toast = document.createElement('span');
90        toast.className = 'sr-copied-toast';
91        toast.setAttribute('aria-hidden', 'true');
92        toast.textContent = label;
93        btn.appendChild(toast);
94
95        window.setTimeout(() => {
96            if (originalLabel !== null) {
97                btn.setAttribute('aria-label', originalLabel);
98            }
99            if (originalTitle !== null) {
100                btn.setAttribute('title', originalTitle);
101            }
102            btn.classList.remove('sr-copied');
103            if (toast.parentNode === btn) {
104                btn.removeChild(toast);
105            }
106        }, 1500);
107    }
108}

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.