PageSourceSearch

https://www.kavalier.cz/wp-content/plugins/toret-toolkit/vendor/to…/src/assets/js/toret-draw.js?ver=1782116949

js kavalier.cz collected 2026-10-02 12:08:43 UTC 10,075 bytes, 279 lines download raw bytes

1(function (window, document, $) {
2    'use strict';
3
4    const state = {
5        loader: {
6            currentButton: null,
7            originalContent: null
8        }
9    };
10
11    const Loader = {
12        initStyles: function () {
13            if (!document.getElementById('dashicon-rotate-style')) {
14                const style = document.createElement('style');
15                style.id = 'dashicon-rotate-style';
16                style.textContent = `
17                    @keyframes rotate {
18                        0% { transform: rotate(0deg); }
19                        100% { transform: rotate(360deg); }
20                    }
21                    .button-spinner.dashicons {
22                        display: inline-block;
23                        animation: rotate 1s linear infinite;
24                        text-align: center;
25                        flex-shrink: 0;
26                    }
27                `;
28                document.head.appendChild(style);
29            }
30        },
31
32        show: function (button) {
33            if (state.loader.currentButton === button) return;
34
35            state.loader.currentButton = button;
36            state.loader.originalContent = button.innerHTML;
37
38            const rect = button.getBoundingClientRect();
39            button.style.height = rect.height + 'px';
40            button.style.minWidth = rect.width + 'px';
41            button.style.width = 'auto';
42            button.style.whiteSpace = 'nowrap';
43
44            const computedStyle = window.getComputedStyle(button);
45            if (computedStyle.display !== 'flex') {
46                button.style.display = 'inline-flex';
47                button.style.justifyContent = 'center';
48                button.style.alignItems = 'center';
49                button.style.gap = '8px';
50            }
51
52            const spinner = document.createElement('span');
53            spinner.className = 'button-spinner dashicons dashicons-update';
54
55            const existingIcon = button.querySelector('.dashicons');
56            if (existingIcon) {
57                existingIcon.replaceWith(spinner);
58            } else {
59                button.prepend(spinner);
60            }
61        },
62
63        restore: function () {
64            const btn = state.loader.currentButton;
65            if (btn && state.loader.originalContent !== null) {
66                btn.innerHTML = state.loader.originalContent;
67
68                btn.style.width = '';
69                btn.style.minWidth = '';
70                btn.style.height = '';
71                btn.style.display = '';
72                btn.style.justifyContent = '';
73                btn.style.alignItems = '';
74                btn.style.gap = '';
75                btn.style.whiteSpace = '';
76            }
77
78            state.loader.currentButton = null;
79            state.loader.originalContent = null;
80        }
81    };
82
83    const Popup = {
84        open: function (id) {
85            const overlay = document.getElementById(id + '-overlay');
86            if (overlay) overlay.style.display = 'flex';
87            if (typeof Loader !== 'undefined') Loader.restore();
88        },
89
90        close: function (overlayElement) {
91            if (overlayElement) overlayElement.style.display = 'none';
92            if (typeof Loader !== 'undefined') Loader.restore();
93        },
94
95        handleGlobalClick: function (e) {
96            const target = e.target;
97
98            if (target.closest('.torlib-popup-close') || target.classList.contains('torlib-popup-overlay') || target.classList.contains('torlib-popup-close-footer')) {
99                e.preventDefault();
100                e.stopPropagation();
101                const overlay = target.closest('.torlib-popup-overlay');
102                this.close(overlay);
103                return;
104            }
105
106            const button = target.closest('[data-popup-target], .torlib-action-loader');
107
108            if (button) {
109                e.stopPropagation();
110
111                if (button.querySelector('.button-spinner')) {
112                    e.preventDefault();
113                    return;
114                }
115
116                const isPopupTrigger = button.hasAttribute('data-popup-target');
117
118                if (button.classList.contains('tf-no-loader')) {
119                    e.preventDefault();
120                    if (isPopupTrigger) {
121                        const targetId = button.getAttribute('data-popup-target');
122                        this.open(targetId);
123                    }
124                    e.stopImmediatePropagation();
125                    return;
126                }
127
128                const isLink = button.tagName === 'A';
129                const href = button.getAttribute('href');
130                const hasRealHref = isLink && href && href !== '#' && !href.startsWith('javascript');
131
132                if (isPopupTrigger || !hasRealHref) {
133                    e.preventDefault();
134                }
135
136                if (hasRealHref && !isPopupTrigger) {
137                    Loader.show(button);
138                    setTimeout(() =>
138 Loader.restore(), 3000);
139                    return;
140                }
141
142                requestAnimationFrame(() => Loader.show(button));
143
144                if (isPopupTrigger) {
145                    const targetId = button.getAttribute('data-popup-target');
146                    if (targetId) {
147                        setTimeout(() => this.open(targetId), 150);
148                    }
149                }
150            }
151        }
152    };
153
154    const Media = {
155        init: function () {
156            if (typeof wp === 'undefined' || !wp.media) {
157                return;
158            }
159            document.addEventListener('click', this.handleClick.bind(this));
160        },
161
162        handleClick: function (e) {
163            const uploadBtn = e.target.closest('.toret-media-upload-btn');
164            if (uploadBtn) {
165                e.preventDefault();
166                this.openUploader(uploadBtn);
167                return;
168            }
169
170            const removeBtn = e.target.closest('.toret-media-remove-btn');
171            if (removeBtn) {
172                e.preventDefault();
173                this.removeImage(removeBtn);
174                return;
175            }
176        },
177
178        openUploader: function (button) {
179            const container = button.closest('.toret-media-uploader');
180
181            const inputPath = container.querySelector('input.toret-media-id');
182            const previewImg = container.querySelector('.toret-media-preview');
183            const placeholderIcon = container.querySelector('.dashicons');
184            const removeBtn = container.querySelector('.toret-media-remove-btn');
185            const previewWrapper = container.querySelector('.toret-media-preview-wrapper');
186
187            const repeaterRow = button.closest('.repeater-row') || button.closest('tr') || button.closest('.field-wrap');
188
189            let frame = button.frame;
190
191            if (!frame) {
192                frame = wp.media({
193                    title: 'Select Image',
194                    button: { text: 'Use this image' },
195                    multiple: false
196                });
197
198                button.frame = frame;
199
200                frame.on('select', function () {
201                    const attachment = frame.state().get('selection').first().toJSON();
202
203                    if (inputPath) {
204                        inputPath.value = attachment.id;
205                    }
206
207                    if (repeaterRow) {
208                        const hiddenImgId = repeaterRow.querySelector('input[name*="[imgid]"]');
209                        if (hiddenImgId) {
210                            hiddenImgId.value = attachment.id;
211                        }
212                    }
213
214                    if (previewImg) {
215                        previewImg.src = attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
216                        previewImg.classList.remove('hidden');
217                    }
218
219                    if (placeholderIcon) placeholderIcon.classList.add('hidden');
220                    if (removeBtn) removeBtn.classList.remove('hidden');
221                    if (previewWrapper) previewWrapper.classList.remove('no-image');
222                });
223            }
224
225            frame.open();
226        },
227
228        removeImage: function (button) {
229            const container = button.closest('.toret-media-uploader');
230            const inputPath = container.querySelector('input.toret-media-id');
231            const previewImg = container.querySelector('.toret-media-preview');
232            const placeholderIcon = container.querySelector('.dashicons');
233            const previewWrapper = container.querySelector('.toret-media-preview-wrapper');
234            const repeaterRow = button.closest('.repeater-row') || button.closest('tr') || button.closest('.field-wrap');
235
236            if (inputPath) inputPath.value = '';
237
238            if (repeaterRow) {
239                const hiddenImgId = repeaterRow.querySelector('input[name*="[imgid]"]');
240                if (hiddenImgId) hiddenImgId.value = '';
241            }
242
243            if (previewImg) {
244                previewImg.src = '';
245                previewImg.classList.add('hidden');
246            }
247
248            if (placeholderIcon) placeholderIcon.classList.remove('hidden');
249            button.classList.add('hidden');
250            if (previewWrapper) previewWrapper.classList.add('no-image');
251        }
252    };
253
254    const UI = {
255        initCopyLink: function () {
256            $(document).on("click", '.toret-copy-link', function (e) {
257                const link = this.getAttribute('data-link');
258                if (link && navigator.clipboard) {
259                    navigator.clipboard.writeText(link);
260                }
261            });
262        }
263    };
264
265    window.ToretLib = {
266        showButtonLoader: Loader.show,
267        restoreButton: Loader.restore,
268        openPopup: Popup.open
269    };
270
271    $(function () {
272        Loader.initStyles();
273        UI.initCopyLink();
274        Media.init();
275
276        document.addEventListener('click', Popup.handleGlobalClick.bind(Popup), true);
277    });
278
279})(window, document, jQuery);

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.