|
/** |
|
* @description Creates a modal that can be displayed while things are loading |
|
*/ |
|
(function () |
|
{ |
|
"use strict"; |
|
|
|
var loadingModal = {}; |
|
var queue = {}; |
|
var currentQueueIndex = 0; |
|
var isShown = false; |
|
var modalStateChangingPromise = Promise.resolve(); /** IE 11 breaks if we try to do anything with the modal before Bootstrap is done chaning its state */ |
|
var modal = $( |
|
'<div class="modal fade" aria-hidden="true" role="dialog">' + |
|
' <div class="modal-dialog modal-sm modal-dialog-centered" role="document">' + |
|
' <div class="modal-content">' + |
|
' <div class="modal-body">' + |
|
' <h5 class="modal-title text-muted text-center" style="word-wrap: break-word;"></h5>' + |
|
' <p class="text-center text-primary mt-1">' + |
|
' <i class="fas fa-cog fa-pulse fa-5x"></i>' + |
|
' </p>' + |
|
' </div>' + |
|
' </div>' + |
|
' </div>' + |
|
'</div>' |
|
); |
|
|
|
var UpdateModal = function () |
|
{ |
|
return modalStateChangingPromise |
|
.then(function () |
|
{ |
|
var queueIndexes = Object.keys(queue); |
|
var options; |
|
|
|
/** |
|
* If there is nothing left to display then exit. |
|
*/ |
|
if (0 === queueIndexes.length) |
|
{ |
|
/** |
|
* If the modal is still showing then hide it before we exit |
|
*/ |
|
if (true === isShown) |
|
{ |
|
isShown = false; |
|
modalStateChangingPromise = modalStateChangingPromise |
|
.then(function () |
|
{ |
|
return new Promise(function (resolve) |
|
{ |
|
modal.on('hidden.bs.modal', function () |
|
{ |
|
/** |
|
* Clean up the DOM |
|
*/ |
|
modal.off('hidden.bs.modal'); |
|
modal.detach(); |
|
resolve(); |
|
return; |
|
}); |
|
modal.modal('hide'); |
|
return; |
|
}); |
|
}); |
|
} |
|
return; |
|
} |
|
|
|
/** |
|
* If the modal is not in the DOM then add it (the DOM gets cleaned when it is hidden) |
|
*/ |
|
if (false === $.contains(document.documentElement, modal[0])) |
|
{ |
|
$("body").append(modal); |
|
} |
|
|
|
/** |
|
* Get the options for the first thing on the queue. |
|
* Update the modal with those options. |
|
*/ |
|
options = queue[queueIndexes[0]]; |
|
if ("string" !== typeof (options.message)) |
|
{ |
|
options.message = "Loading..."; |
|
} |
|
modal.find(".modal-title").html(options.message); |
|
|
|
/** |
|
* Display the modal if it is hidden |
|
*/ |
|
if (false === isShown) |
|
{ |
|
isShown = true; |
|
modalStateChangingPromise = modalStateChangingPromise |
|
.then(function () |
|
{ |
|
return new Promise(function (resolve) |
|
{ |
|
modal.on('shown.bs.modal', function () |
|
{ |
|
modal.off('shown.bs.modal'); |
|
resolve(); |
|
return; |
|
}) |
|
|
|
modal.modal({ |
|
keyboard: false, |
|
backdrop: 'static', |
|
focus: true, |
|
show: true |
|
}); |
|
return; |
|
}); |
|
}); |
|
} |
|
return; |
|
}); |
|
}; |
|
|
|
/** |
|
* @description Displays the modal |
|
* @param {object} options |
|
* @param {string} [options.message] - Message to display in the modal |
|
* @return {string} Modal ID |
|
*/ |
|
loadingModal.Show = function (options) |
|
{ |
|
var modalId; |
|
|
|
/** |
|
* Param check |
|
*/ |
|
if ("object" !== typeof options || |
|
null === options) |
|
{ |
|
options = {}; |
|
} |
|
|
|
/** |
|
* Save the current queue index and increment to the next queue index |
|
*/ |
|
modalId = currentQueueIndex + ""; |
|
currentQueueIndex++; |
|
queue[modalId] = options; |
|
|
|
/** |
|
* The user will see a flash on the screen if the modal is displayed for only a brief time. |
|
* This will give the process a chance to finish before displaying it. |
|
* 300 milliseconds is when a user will feel like a process is not instant and there is a delay, therefore we need a dialog |
|
* Also showing a loading dialog can make a user feel like things are slower than they really are |
|
* https://medium.com/@luisvieira_gmr/understanding-the-critical-rendering-path-rendering-pages-in-1-second-735c6e45b47a |
|
*/ |
|
setTimeout(function () |
|
{ |
|
UpdateModal(); |
|
return; |
|
}, 300); |
|
return modalId; |
|
} |
|
|
|
/** |
|
* @description Hides the modal |
|
* @param {object} options |
|
* @param {string} options.id - Modal ID |
|
* @return {void} |
|
*/ |
|
loadingModal.Hide = function (options) |
|
{ |
|
if ("object" !== typeof options || |
|
null === options) |
|
{ |
|
return; |
|
} |
|
if ("string" !== typeof options.id) |
|
{ |
|
return; |
|
} |
|
|
|
if ("object" === typeof queue[options.id]) |
|
{ |
|
/** |
|
* Remove this from the queue so it is not shown |
|
*/ |
|
delete queue[options.id]; |
|
} |
|
UpdateModal(); |
|
return; |
|
} |
|
|
|
/** |
|
* Export this so it can be used in the global space |
|
*/ |
|
window.LoadingModal = loadingModal; |
|
})(); |