1(function ($, undefined) { 2 "use strict"; 3 4 $.widget("rec1.waitingListWaivers", { 5 6 options: { 7 item: null, 8 $item: null, 9 catalog: null, 10 $catalog: null, 11 values: null 12 }, 13 endpoints: { 14 loadModal: "/waivers/waitingListWaivers/", 15 submitWaivers: "/catalog/addUsersToWaitingList/" 16 }, 17 _initialized: false, 18 $modal: null, 19 $waiverSignatureModal: null, 20 21 _create: function () { 22 if (!this._initialized) { 23 this._initialized = true; 24 this._init(); 25 } 26 }, 27 28 _init: function () { 29 if (this.$waiverSignatureModal !== null) { 30 return; 31 } 32 33 34 this._renderWaiverSignatureModal(); 35 }, 36 37 _renderWaiverSignatureModal: function () { 38 var html = '<div class="modal fade" id="waiver-signature-modal" tabindex="-1" role="dialog" aria-labelledby="waiver-signature-modal-title" ' + 39 'aria-hidden="true"> ' + 40 '<div class="modal-dialog"> ' + 41 '<div class="modal-content"> ' + 42 '<div class="modal-header"> ' + 43 // Bootstrap 3 close button MUST come first for proper float positioning 44 '<button type="button" class="close" data-dismiss="modal" data-bs-dismiss="modal" aria-label="Close" style="font-size: 28px !important; padding: 0 !important; background: transparent !important; border: 0 !important; font-weight: 700 !important; line-height: 1 !important; color: #000 !important; opacity: .5 !important; cursor: pointer !important; position: absolute !important; right: 1rem !important; top: 1rem !important; z-index: 1 !important;">' + 45 '<span aria-hidden="true" style="font-size: 28px !important;">×</span>' + 46 '</button> ' + 47 '<h4 class="modal-title" id="waiver-signature-modal-title">Waiver Signature</h4> ' + 48 '</div> ' + 49 '<div class="modal-body"> ' + 50 '<p>Please sign below:</p> ' + 51 '<div id="waiver-signature-box"></div> ' + 52 '<div class="waiver-signature-type-name"> ' + 53 '<div> ' + 54 '<label for="waiver-signature-type-name-input">Typed Signature:</label> ' + 55 '<input type="text" class="form-control waiver-signature-type-name-input" id="waiver-signature-type-name-input" placeholder="Type your Signature here"> ' + 56 '</div> ' + 57 '<button type="button" class="btn btn-outline-secondary waiver-add-signature-button">Add Signature</button> ' + 58 '</div> ' + 59 '</div> ' + 60 '<div class="modal-footer"> ' + 61 '<button class="btn btn-link waiver-signature-reset" type="button">Clear/Reset</button> ' + 62 '<button type="button" class="btn btn-default" data-dismiss="modal" data-bs-dismiss="modal">Close</button> ' + 63 '<button type="button" class="btn btn-primary waiver-signature-modal-save">Save</button> ' + 64 '</div> ' + 65 '</div> ' + 66 '</div> ' + 67 '</div>'; 68 69 this.$waiverSignatureModal = $(html); 70 $("body").append(this.$waiverSignatureModal); 71 72 // Set initial z-index to ensure it appears above parent modals 73 this.$waiverSignatureModal.css('z-index', 2000); 74 this.$waiverSignatureModal.modal('hide'); 75 }, 76 77 _initModalEvents: function () { 78 if (this.$modal !== null) { 79 this.$modal.enhanceWithin(); 80 81 var _this = this; 82 this.$modal.on("hidden.bs.modal", function (e) { 83 _this.hide(); 84 }); 85 this.$modal.on("click", ".btn-submit-waivers", function (e) { 86 _this._submitWaivers(e); 87 }); 88 89 var signatures = [], 90 signaturePromise = null,
91 $signatureBox = this.$waiverSignatureModal.find("#waiver-signature-box"); 92 93 // todo refactor to support other pages, currently using waivers-standard.js file for the functionality 94 this.$modal.on("change", ".waiver-agreement-checkbox", function () { 95 var $checkbox = $(this), 96 checked = $checkbox.prop('checked'), 97 $container = $checkbox.closest('.waiver-user-agreement'), 98 $signatureData = $container.find(".waiver-agreement-signature-data"), 99 $signatureDisplay = $container.find(".waiver-agreement-signature").find("img"); 100 101 if(checked) { 102 signaturePromise = window.promptForSignature($checkbox, $container, $signatureData, $signatureDisplay, $signatureBox, _this.$waiverSignatureModal); 103 } 104 }); 105 106 // Use event delegation for signature reset - reusing waivers-standard.js functionality 107 this.$waiverSignatureModal.on("click", ".waiver-signature-reset", function() { 108 $signatureBox.jSignature('reset'); 109 $('.waiver-signature-type-name-input').val(''); 110 }); 111 112 // Use event delegation for signature typing - reusing waivers-standard.js functionality 113 this.$waiverSignatureModal.on("click", ".waiver-add-signature-button", function() { 114 var text = $('.waiver-signature-type-name-input').val().trim(); 115 if (!text) { 116 alert("Please enter a name for the signature."); 117 return; 118 } 119 120 var jSignatureCanvas = $signatureBox.find('.jSignature')[0]; 121 if (!jSignatureCanvas) { 122 console.error("jSignature canvas not found."); 123 return; 124 } 125 126 var ctx = jSignatureCanvas.getContext('2d'); 127 128 // Clear canvas 129 ctx.clearRect(0, 0, jSignatureCanvas.width, jSignatureCanvas.height); 130 131 // Background color 132 ctx.fillStyle = '#fff'; 133 ctx.fillRect(0, 0, jSignatureCanvas.width, jSignatureCanvas.height); 134 ctx.stroke(); 135 136 // Draw text as signature 137 ctx.fillStyle = '#000'; 138 ctx.font = '30px arial helvetica'; 139 ctx.fillText(text, 20, 50); 140 141 // Convert to image and set data 142 var dataUrl = jSignatureCanvas.toDataURL('image/png'); 143 $signatureBox.jSignature('reset'); 144 $signatureBox.jSignature('setData', dataUrl); 145 }); 146 147 this.$waiverSignatureModal.on("click", ".waiver-signature-modal-save", function() { 148 if(signaturePromise) { 149 150 signaturePromise.resolve(); 151 } 152 }); 153 154 // Bootstrap 3 & 5 compatible modal event handling 155 // Handle both show.bs.modal (BS3/5) events 156 this.$waiverSignatureModal.on("show.bs.modal show", function(e){ 157 // Set a very high z-index to ensure it appears above the parent modal 158 var $modal = $(this); 159 $modal.css('z-index', 2000); 160 161 // Store the current backdrop count 162 $modal.data('backdropCountOnShow', $('.modal-backdrop').length); 163 164 // Also handle backdrop immediately 165 setTimeout(function() { 166 $('.modal-backdrop').last().css('z-index', 1999); 167 }, 0); 168 }); 169 170 // Handle both shown.bs.modal (BS3/5) events 171 this.$waiverSignatureModal.on("shown.bs.modal shown", function(e){ 172 // Find and adjust the backdrop z-index to be just below the signature modal 173 $('.modal-backdrop').last().css('z-index', 1999); 174 }); 175
176 // Handle both hidden.bs.modal (BS3/5) events 177 // keep body set to open only if the waiverSignatureModal is closed so the waivers agreement modal still works 178 this.$waiverSignatureModal.on("hidden.bs.modal hidden", function(e){ 179 var $signatureModal = $(this); 180 // Small delay to let Bootstrap finish its cleanup 181 setTimeout(function() { 182 var $allBackdrops = $('.modal-backdrop'); 183 184 // Check if main waiver modal is still visible 185 var mainModalVisible = _this.$modal && _this.$modal.is(':visible'); 186 187 if (mainModalVisible) { 188 if ($allBackdrops.length === 0) { 189 // Bootstrap removed all backdrops - recreate one for the main modal 190 var backdrop = $('<div class="modal-backdrop fade"></div>'); 191 $('body').append(backdrop); 192 // Trigger reflow to enable CSS transition 193 backdrop[0].offsetHeight; 194 // Add active classes for both BS3 and BS5 195 backdrop.addClass('in show'); 196 } else if ($allBackdrops.length > 1) { 197 // Multiple backdrops - keep only the first one 198 $allBackdrops.not(':first').remove(); 199 } 200 201 // CRITICAL: Reset backdrop z-index to default by removing inline style 202 // The signature modal set it to 1999, we need to clear that 203 $allBackdrops.first().css('z-index', ''); 204 205 // Ensure modal-open class is present 206 $('body').addClass('modal-open'); 207 } else { 208 // Main modal is not visible - remove all backdrops 209 $allBackdrops.remove(); 210 $('body').removeClass('modal-open'); 211 } 212 }, 50); 213 }); 214 } 215 }, 216 217 _submitWaivers: function (e) { 218 var catalog = this.options.catalog, 219 url = this.endpoints.submitWaivers + catalog.checkoutKey + '/' + this.options.item.id, 220 _this = this; 221 222 var userIds = this.options.hasOwnProperty("values") && Object.keys(this.options.values).length ? this.options.values.userIds : [], 223 $waitingListUsersContainer = this.$modal.find("#waiversForm").find(".waitinglist-waivers-users-container"); 224 225 $waitingListUsersContainer.html(''); 226 for(var i in userIds){ 227 var $input = $("<input>"); 228 $input.attr("type", "hidden"); 229 $input.attr("name", "userIds[]"); 230 $input.val(userIds[i]); 231 $waitingListUsersContainer.append($input); 232 } 233 234 $.rec1.ajax({ 235 url: catalog.getPath(url), 236 data: this.$modal.find("#waiversForm").serialize(), 237 loadingmask: this.$modal, 238 success: function (data) { 239 // Hide the waiver modal 240 _this.hide(false); 241 242 // Trigger success event - the parent handler will display the receipt 243 _this._trigger("success", {}, data); 244 } 245 }); 246 247 }, 248 249 show: function () { 250 if (this.$modal !== null) { 251 this.$modal.modal("destroy").remove(); 252 } 253 254 if (this.options.item === null || this.options.values === null) { 255 console.error("unable to show waitingListWaivers modal"); 256 return; 257 } 258 259 var _this = this, 260 $modal = $("<div></div>"); 261 262 $modal[0].className = "modal fade"; 263 $modal.attr("role", "dialog"); 264 $modal.attr("id", "waitingListWaiversModal"); 265 $modal.attr("tabindex", "-1"); 266 $modal.attr("aria-labelledby", "waitingListWaiversModalLabel"); 267 $modal.attr("aria-hidden", "true"); 268 269 var catalog = this.options.catalog, 270 sessionId = this.options.item.id, 271 url = this.endpoints.loadModal + sessionId, 272 data = $.extend(this.options.values, catalog.getFilterValues()); 273 274 catalog.ajax({ 275 data: data, 276 url: catalog.getPath(url), 277 dataType: 'html', 278 success: function (html) { 279 $modal.html(html); 280 _this.$modal = $modal; 281 _this._initModalEvents(); 282 _this.$modal.modal("show"); 283 } 284 }); 285 }, 286 287 _destroy: function () { 288 this.hide(); 289 }, 290 291 hide: function (triggerEvent) { 292 293 var trigger = typeof triggerEvent !== "undefined" && triggerEvent; 294 295 if (typeof this.$modal !== "undefined" && this.$modal !== null) { 296 var $modal = this.$modal; 297 298 // Unbind events to prevent interference 299 $modal.off('.bs.modal');
300 if (this.$waiverSignatureModal) { 301 this.$waiverSignatureModal.off('.bs.modal'); 302 } 303 304 // Hide the modal 305 $modal.modal("hide"); 306 307 // Wait for hide animation, then cleanup 308 setTimeout(function() { 309 try { 310 $modal.modal("destroy"); 311 } catch (e) {} 312 313 $modal.remove(); 314 315 // Only clean up backdrops if triggerEvent is true 316 // If false, another modal (like receipt) is coming, so leave infrastructure in place 317 if (trigger) { 318 $('.modal-backdrop').remove(); 319 $('body').removeClass('modal-open').css({ 320 'overflow': '', 321 'padding-right': '' 322 }); 323 } 324 }, 50); 325 326 this.$modal = null; 327 } 328 329 if(trigger){ 330 // trigger hidden/destroy to catalog event 331 this._trigger("hidden", []); 332 } 333 } 334 }); 335 336 337})(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.