1import Form from "./form.js"; 2import GlobalListeners from "./global-listeners.js"; 3import Utils from "./utils.js"; 4class DynamicModal { 5 static instance; 6 $modalContainer; 7 $modalHeader; 8 $modalBody; 9 $loading; 10 isShown = false; 11 modalsInQueue = []; 12 constructor() { 13 this.$modalContainer = $("#dynamic-modal"); 14 this.$modalHeader = this.$modalContainer.find('.modal-content .modal-header'); 15 this.$modalBody = this.$modalContainer.find('.modal-content .modal-body'); 16 this.$loading = this.$modalContainer.find('.loading'); 17 this.$modalContainer 18 .on('show.bs.modal', () => this.showModalHandler()) 19 .on('hide.bs.modal', () => this.hideModalHandler()) 20 .on('hidden.bs.modal', () => this.hiddenModalHandler()); 21 } 22 static getInstance() { 23 if (!DynamicModal.instance) { 24 DynamicModal.instance = new DynamicModal(); 25 } 26 return DynamicModal.instance; 27 } 28 async LoadAndShow(param) { 29 if (param == undefined) { 30 console.error("DynamicModal.LoadAndShow: invalid parameters"); 31 return; 32 } 33 if (typeof param === "string") { 34 var props = new DynamicModalProps(); 35 props.contentSource = param; 36 await this.LoadAndShow(props); 37 return; 38 } 39 var props = param; 40 this.$loading.show(); 41 if (!props.closeButton) { 42 this.$modalHeader.addClass("hidden"); 43 } 44 else { 45 this.$modalHeader.removeClass("hidden"); 46 } 47 if (props.staticBackdrop === false) { 48 this.$modalContainer.on('hidePrevented.bs.modal', function () { 49 $(this).modal('hide'); 50 }); 51 } 52 $(this.$modalContainer).find(".modal-dialog").removeClass("modal-xl modal-lg modal-md modal-sm").addClass(`modal-${props.size}`); 53 if (!this.isShown) { 54 this.$modalContainer.modal('show'); 55 } 56 var content = await this.getContent(props.contentSource); 57 this.replaceWithContent(content); 58 this.$loading.hide(); 59 } 60 async Hide() { 61 if (this.isShown) { 62 this.$modalContainer.modal('hide'); 63 } 64 } 65 AddToQueue(props) { 66 this.modalsInQueue.push(props); 67 } 68 handleBackButton() { 69 // look in content for div with class "back-url" and take it's data-content into a variable 70 var $modalBackButton = this.$modalHeader.find(".modal-back"); 71 var backUrl = this.$modalBody.find(".back-url").first().data("content"); 72 if (!backUrl) { 73 $modalBackButton.css("display", "none"); 74 return; 75 } 76 $modalBackButton.attr("data-content", backUrl); 77 $modalBackButton.css("display", "flex"); 78 $modalBackButton.off("click"); 79 $modalBackButton.on("click", () => { 80 this.LoadAndShow(backUrl); 81 }); 82 } 83 replaceWithContent(content) { 84 // check if content starts with <div class="modal-body"> 85 this.$modalBody.remove(); 86 if (content.trimStart().startsWith('<div class="modal-body')) { 87 this.$modalBody = $(content); 88 } 89 else { 90 this.$modalBody = $('<div class="modal-body"></div>'); 91 this.$modalBody.html(content); 92 } 93 this.$modalContainer.find('.modal-content').append(this.$modalBody); 94 var context = this; 95 this.$modalContainer.find("form").each(function () { 96 if ($(this).hasClass("cancel-modal-form-hook")) 97 return; 98 new Form($(this), context.$loading, (data) => context.handleSuccess(data)); 99 }); 100 this.handleBackButton(); 101 GlobalListeners.Initialize(this.$modalContainer); 102 } 103 async handleSuccess(response) { 104 var data = await response.text(); 105 if (data.startsWith("success")) { 106 var dataArr = data.split(";"); 107 if (dataArr.length == 1) { 108 // no redirect 109 location.reload(); 110 return; 111 } 112 var redirectUrl = dataArr[1]; 113 location.href = redirectUrl; 114 } 115 else { 116 this.replaceWithContent(data); 117 this.$loading.hide(); 118 } 119 } 120 async getContent(contentSource) { 121 if (contentSource == null || contentSource == "") 122 return Promise.resolve(null); 123 return new Promise((resolve, reject) => { 124 if (contentSource.startsWith('/')) { 125 // load content from url 126 $.get(contentSource, (data) => { 127 resolve(data); 128 }).fail((jqXHR, textStatus, error) => { 129 console.debug(jqXHR); 130 var displayedError = jqXHR.responseText.length > 300 131 ? error 132 : jqXHR.responseText; 133 toastr.error(displayedError); 134 }); 135 } 136 else if (contentSource.startsWith('#')) { 137 // load content from element 138 const content = $(contentSource).html(); 139 if (content) { 140 resolve(content); 141 } 142 else { 143 reject(new Error(`Failed to load content from element: ${contentSource}`)); 144 } 145 } 146 else { 147 resolve(contentSource); 148 } 149 }); 150 } 151 showModalHandler() { 152 Utils.PauseAllVideos(); 153 this.isShown = true; 154 } 155 hideModalHandler() { 156 Utils.PauseAllVideos(); 157 this.isShown = false;
158 this.$modalContainer.off('hidePrevented.bs.modal'); 159 } 160 hiddenModalHandler() { 161 GlobalListeners.Dispose(this.$modalBody); 162 this.$modalBody.html(""); 163 // reset classes to default 164 this.$modalHeader.removeClass("hidden"); 165 // reattach event handlers 166 // to get rid of all other attached handlers from specific modals 167 this.$modalContainer.off(); 168 this.$modalContainer 169 .on('show.bs.modal', () => this.showModalHandler()) 170 .on('hide.bs.modal', () => this.hideModalHandler()) 171 .on('hidden.bs.modal', () => this.hiddenModalHandler()); 172 // load next modal from queue 173 if (this.modalsInQueue.length > 0) { 174 var props = this.modalsInQueue.shift(); 175 this.LoadAndShow(props); 176 } 177 } 178} 179export function InitializeDynamicModalTrigger($trigger) { 180 var props = new DynamicModalProps; 181 { 182 props.contentSource = $trigger.data("content"); 183 props.closeButton = $trigger.dataBool("close-button"); 184 props.size = $trigger.data("size"); 185 props.staticBackdrop = $trigger.dataBool("static-backdrop"); 186 } 187 var autoShow = $trigger.dataBool("auto-show"); 188 if (autoShow) { 189 if (!dynamicModal.isShown) { 190 dynamicModal.LoadAndShow(props); 191 } 192 else { 193 dynamicModal.AddToQueue(props); 194 } 195 return; 196 } 197 $trigger.on("click", function () { 198 dynamicModal.LoadAndShow(props); 199 }); 200} 201export class DynamicModalProps { 202 contentSource; 203 closeButton = true; 204 size = "md"; 205 staticBackdrop = true; 206} 207export const dynamicModal = DynamicModal.getInstance(); 208//# sourceMappingURL=dynamic-modal.js.map
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.