|
171 | 171 | window.attachEvent("on" + event, callback); |
172 | 172 | } |
173 | 173 | }, |
| 174 | + /** |
| 175 | + * Adds a delegated event listener to the document. |
| 176 | + * |
| 177 | + * This allows event handling for elements that may not exist when |
| 178 | + * the listener is registered (similar to jQuery's '.on()'). |
| 179 | + * It listens for the specified event type on the entire document, |
| 180 | + * and when the event bubbles up, checks if the event target (or one |
| 181 | + * of its ancestors) matches the provided CSS selector. |
| 182 | + * |
| 183 | + * @function delegate |
| 184 | + * @memberof csk.ui |
| 185 | + * @param {string} event - The name of the event to listen for. |
| 186 | + * @param {string} selector - A CSS selector to match the event target or its ancestors. |
| 187 | + * @param {Function} handler - The callback function to execute when a match is found. |
| 188 | + * @return {void} |
| 189 | + */ |
| 190 | + delegate: function(event, selector, handler) { |
| 191 | + document.addEventListener(event, function(e) { |
| 192 | + const target = e.target.closest(selector); |
| 193 | + if (target) { |
| 194 | + handler.call(target, e); |
| 195 | + } |
| 196 | + }); |
| 197 | + }, |
174 | 198 | /** |
175 | 199 | * Lazy load images. |
176 | 200 | * @since 2.0 |
|
596 | 620 | }; |
597 | 621 |
|
598 | 622 | /** |
599 | | - * SKeleton Ping. |
| 623 | + * Skeleton Ping. |
600 | 624 | * @since 2.100 |
601 | 625 | */ |
602 | | - |
603 | 626 | csk.ping = { |
604 | 627 | init : function(options) { |
605 | 628 | var defaults = { |
|
624 | 647 | } |
625 | 648 | }; |
626 | 649 |
|
| 650 | + /** |
| 651 | + * Media Browser |
| 652 | + * @since 3.10.2 |
| 653 | + */ |
| 654 | + csk.media = { |
| 655 | + /** |
| 656 | + * Currently selected editor for the opened media browser. |
| 657 | + * @type {HTMLElement} |
| 658 | + */ |
| 659 | + editor: null, |
| 660 | + |
| 661 | + /** |
| 662 | + * Opens Media browser. |
| 663 | + * @param {HTMLElement} editor Summernote editor note. |
| 664 | + * @return {void} |
| 665 | + */ |
| 666 | + browse: function(editor) { |
| 667 | + csk.media.editor = editor; |
| 668 | + const $modal = $("#media-modal"); |
| 669 | + const $browser = $("#media-browser"); |
| 670 | + const $insert = $("#media-insert-btn"); |
| 671 | + |
| 672 | + $browser.html('<div class="text-center py-5 text-muted">'+csk.i18n.default.loading+'...</div>'); |
| 673 | + $insert.prop('disabled', true); |
| 674 | + |
| 675 | + // Load existing media |
| 676 | + csk.ajax.request(csk.config.adminURL + '/ajax/media', { |
| 677 | + type: 'GET', |
| 678 | + success: function(response) { |
| 679 | + if (response.results && response.results.length) { |
| 680 | + let html = ''; |
| 681 | + response.results.forEach(file => { |
| 682 | + var source = document.getElementById("media-template").innerHTML, |
| 683 | + template = Handlebars.compile(source); |
| 684 | + html += template(file); |
| 685 | + }); |
| 686 | + |
| 687 | + $browser.html(html); |
| 688 | + } else { |
| 689 | + $browser.html('<div class="text-center py-5 text-muted">'+csk.i18n.default.no_data+'</div>'); |
| 690 | + } |
| 691 | + } |
| 692 | + }); |
| 693 | + |
| 694 | + $modal.modal('show'); |
| 695 | + }, |
| 696 | + |
| 697 | + /** |
| 698 | + * Handles media file selection. |
| 699 | + * @return {void} |
| 700 | + */ |
| 701 | + select: function() { |
| 702 | + $('#media-modal .media-item').removeClass('selected'); |
| 703 | + $(this).addClass('selected'); |
| 704 | + $('#media-modal #media-insert-btn').prop('disabled', false); |
| 705 | + }, |
| 706 | + |
| 707 | + /** |
| 708 | + * Handles inserting media into Summernote editor. |
| 709 | + * @return {void} |
| 710 | + */ |
| 711 | + insert: function() { |
| 712 | + const selected = $('#media-modal .media-item.selected'); |
| 713 | + if (!selected.length || !csk.media.editor) return; |
| 714 | + |
| 715 | + const $editor = $(csk.media.editor); |
| 716 | + if (!$editor.hasClass('summernote')) { |
| 717 | + console.warn('Invalid editor reference:', $editor); |
| 718 | + return; |
| 719 | + } |
| 720 | + |
| 721 | + const url = selected.data('url'); |
| 722 | + $editor.summernote('insertImage', url); |
| 723 | + $('#media-modal').modal('hide'); |
| 724 | + }, |
| 725 | + |
| 726 | + init: function () { |
| 727 | + if (csk.media._initialized) return; |
| 728 | + csk.ui.delegate('click', '#media-modal .media-item', csk.media.select); |
| 729 | + csk.ui.delegate('click', '#media-modal #media-insert-btn', csk.media.insert); |
| 730 | + csk.media._initialized = true; |
| 731 | + } |
| 732 | + }; |
| 733 | + |
627 | 734 | /** Things to do when the page is ready! */ |
628 | 735 | $(document).ready(function() { |
629 | 736 | /** |
|
1243 | 1350 | if (typeof file !== "object") { |
1244 | 1351 | return false; |
1245 | 1352 | } |
1246 | | - var source = document.getElementById("attachment-template").innerHTML, |
| 1353 | + var source = document.getElementById("media-template").innerHTML, |
1247 | 1354 | template = Handlebars.compile(source), |
1248 | 1355 | html = template(file); |
1249 | 1356 | $(html).hide().prependTo(".dropZone").fadeIn("slow"); |
|
0 commit comments