/////////////////////////////////////////////////////////////////
// Sircl 2.x - Bootstrap4 extension
// www.getsircl.com
// Copyright (c) 2019-2023 Rudi Breedenraedt
// Sircl is released under the MIT license, see sircl-license.txt
/////////////////////////////////////////////////////////////////
/* tslint:disabled */
// Initialize sircl lib:
if (typeof sircl === "undefined") console.warn("The 'sircl-bootstrap4' component should be registered after the 'sircl' component. Please review order of script files.");
if (typeof bootstrap === "undefined") console.warn("The 'sircl-bootstrap4' component requires the 'bootstrap' component. See https://getbootstrap.com/");
//// Initialize Bootstrap popovers, tooltips, etc. using a $$() function as in:
//
// Use a Bootstrap spinner:
sircl.html_spinner = ' ';
//#region Hide or dispose elements before unloading their container
$$("before", function sircl_bs4_init_beforeHandler() {
try {
// Hide all popovers in scope:
$(this).find("[data-bs-toggle='popover'], [data-toggle='popover']").popover("dispose");
// Hide all tooltips in scope:
$(this).find("[data-bs-toggle='tooltip'], [data-toggle='tooltip']").tooltip("dispose");
} catch (ex) {
console.warn("Error trying to dispose Bootstrap 4 popovers and tooltips in scope.", ex, "sircl_bs4_init_beforeHandler");
}
});
//#endregion
//#region Handling Bootstrap NavBars
sircl.addRequestHandler("beforeSend", function sircl_bs4_navbar_beforeSend_requestHandler(req) {
var processor = this;
// Collapse any expanded navbar before loading:
var $expandedNavbar = $(".navbar-collapse.show");
$expandedNavbar.each(function () {
$(this).removeClass("show");
});
// Move to next handler:
processor.next(req);
});
//#endregion
//#region Handling Bootstrap Modals
sircl.addRequestHandler("beforeSend", function sircl_bs4_modal_beforeSend_requestHandler1(req) {
var processor = this;
// Close any opened modal that is not the target if target has beforeload-showmodal class and is not open:
var $closedTarget = req.$initialTarget.closest(".modal.beforeload-showmodal:not(.show)");
var $openModals = $(".modal.show");
if (req.isForeground == true && $openModals.length > 0 && $closedTarget.length > 0) {
if (!$.contains($openModals[0], req.$initialTarget[0]) && !$openModals.is(req.$initialTarget)) {
// Delay move to next handler:
$openModals[0]._onCloseOnce = function (e) {
processor.next(req);
};
// Close modal:
$openModals.modal("hide");
} else {
// Move to next handler:
processor.next(req);
}
} else {
// Move to next handler:
processor.next(req);
}
});
sircl.addRequestHandler("beforeSend", function sircl_bs4_modal_beforeSend_requestHandler2(req) {
var processor = this;
// Open any non-open modal holding the initial target and having class "beforeload-showmodal":
req._bsModalOpened = req.$initialTarget.closest(".modal.beforeload-showmodal:not(.show)");
if (req._bsModalOpened.length > 0) {
// Delay move to next handler:
req._bsModalOpened[0]._onOpenOnce = function (e) {
processor.next(req);
};
// Open modal:
req._bsModalOpened.modal("show");
} else {
// Move to next handler:
processor.next(req);
}
});
sircl.addRequestHandler("afterSend", function sircl_bs4_modal_afterSend_requestHandler(req) {
var processor = this;
// On error, undo opened modals:
if (!req.succeeded && req._bsModalOpened.length > 0) {
// Delay move to next handler:
req._bsModalOpened[0]._onCloseOnce = function (e) {
processor.next(req);
};
// Close modal:
req._bsModalOpened.modal("hide");
} else if (req.status == "204") {
// Else, if status "204" (no content), close target modal:
var $dlg = req.$initialTarget.closest(".modal.show");
if ($dlg.length > 0) {
// Delay move to next handler:
$dlg[0]._onCloseOnce = function (e) {
processor.next(req);
};
// Close modal:
$dlg.modal("hide");
} else {
// Move to next handler:
processor.next(req);
}
} else {
// Move to next handler:
processor.next(req);
}
});
sircl.addRequestHandler("beforeRender", function sircl_bs4_modal_beforeRender_requestHandler(req) {
var processor = this;
// Close any opened modal that is not the target:
var $openModals = $(".modal.show");
if (req.isForeground == true && $openModals.length > 0) {
if (!$.contains($openModals[0], req.$finalTarget[0]) && !$openModals.is(req.$finalTarget)) {
// Delay move to next handler:
$openModals[0]._onCloseOnce = function (e) {
processor.next(req);
};
// Close modal:
$openModals.modal("hide");
} else {
// Move to next handler:
processor.next(req);
}
} else {
// Move to next handler:
processor.next(req);
}
});
sircl.addRequestHandler("afterRender", function sircl_bs4_modal_afterRender_requestHandler(req) {
var processor = this;
// Open modal on final target:
var $modal = req.$finalTarget.closest(".modal:not(.show)");
if ($modal.length > 0) {
// Delay move to next handler:
$modal[0]._onOpenOnce = function (e) {
processor.next(req);
};
// Open modal:
$modal.modal("show");
} else {
// Move to next handler:
processor.next(req);
}
});
document.addEventListener("DOMContentLoaded", function () {
// Perform onOpen action once:
$(document).on("shown.bs.modal", ".modal", function (event) {
if (this._onOpenOnce) {
var fx = this._onOpenOnce;
this._onOpenOnce = undefined;
fx();
}
});
// Perform onClose action once:
$(document).on("hidden.bs.modal", ".modal", function (event) {
if (this._onCloseOnce) {
var fx = this._onCloseOnce;
this._onCloseOnce = undefined;
fx();
}
});
// When opening modal, set focus:
$(document).on("shown.bs.modal", ".modal", function (event) {
$(this).find("*[autofocus]:first").each(function (index) {
try { this.focus(); } catch (x) { }
try { this.select(); } catch (x) { }
});
});
// Reset content of a modal with onclose-restore when closing the modal:
$(document).on("hidden.bs.modal", ".modal.onclose-restore", function (event) {
var originalContent = $(this)[0]._originalContent;
if (originalContent !== undefined) $(this).html(originalContent);
});
// Dynamically load content on showing modal:
$(document).on("shown.bs.modal", ".modal", function (event) {
var $container = $(this).find("[onshowmodal-load]");
if ($container.length > 0) {
$container.load($container.attr("onshowmodal-load"));
if ($container.is(".noreload")) $container.removeAttr("onshowmodal-load");
}
});
});
$$(function sircl_bs4_modal_processHandler() {
// Backup original content of onclose-restore modals to be able to reset on close:
$(this).find(".modal.onclose-restore").each(function (index, elem) {
elem._originalContent = $(elem).html();
});
// Automatically show modals after load:
var $modals = $(this).find(".modal[onload-showmodalafter]");
if ($modals.length > 0) {
var modal = $modals[0];
// Parse delay ("seconds" or "[hh:]mm:ss"):
var delaypart = $(modal).attr("onload-showmodalafter").split(":");
var delay = 0;
for (var i = 0; i < delaypart.length; i++) delay = parseFloat(delaypart[i]) + (60 * delay);
// Set timer:
setTimeout(function (mdl) {
// Only show if no other modals shown yet:
if ($(".modal.show").length == 0) {
$(mdl).modal("show");
}
}, 1000 * delay, modal);
}
});
//#endregion
//#region Handling Bootstrap Tab & Pill navs
document.addEventListener("DOMContentLoaded", function () {
// Dynamically load content on showing tab:
$(document).on("show.bs.tab", "[data-toggle='tab'], [data-toggle='pill']", function (event) {
// Find target tab:
var trigger = event.target;
var target$;
if (trigger.hasAttribute("data-target")) {
target$ = trigger.getAttribute("data-target");
} else if (trigger.hasAttribute("href")) {
target$ = trigger.getAttribute("href");
} else {
return;
}
// If target tab has ifactivetab-load attribute, apply it:
if ($(target$).hasAttr("ifactivetab-load")) {
$(target$).load($(target$).attr("ifactivetab-load"));
$(target$).removeAttr("ifactivetab-load");
}
});
});
$$(function sircl_bs4_tabs_processHandler() {
// Dynamically load content on initially shown tab:
$(".nav-link.active[data-toggle='tab'], .nav-link.active[data-toggle='pill']").each(function () {
// Find target tab:
var trigger = this;
var target$;
if (trigger.hasAttribute("data-target")) {
target$ = trigger.getAttribute("data-target");
} else if (trigger.hasAttribute("href")) {
target$ = trigger.getAttribute("href");
} else {
return;
}
// If target tab has ifactivetab-load attribute, apply it:
if ($(target$).hasAttr("ifactivetab-load")) {
$(target$).load($(target$).attr("ifactivetab-load"));
$(target$).removeAttr("ifactivetab-load");
}
});
});
//#endregion
//#region Handling Bootstrap Toasts
$$(function sircl_bs4_toasts_processHandler() {
// Automatically show toasts with .onload-showtoast on init:
$(this).find(".toast.onload-showtoast").toast("show");
});
//#endregion
//#region Handling Bootstrap Collapse
document.addEventListener("DOMContentLoaded", function () {
// On check checkbox, expand, else collapse:
$(document.body).on("change", "INPUT[type=checkbox][ifchecked-expand]", function (event) {
var $this = $(this);
var $target = sircl.ext.$select($this, $this.attr("ifchecked-expand"));
if ($target.hasClass("collapse")) {
if ($this.prop('checked')) {
$target.collapse('show');
} else {
$target.collapse('hide');
}
}
});
// On check radio, expand, else collapse for all radios with same name in same form:
$(document.body).on("change", "INPUT[type=radio][ifchecked-expand]", function (event) {
var $this = $(this);
var $all;
if ($this.attr("name").length > 0) {
$all = $this.closest("FORM").length > 0
? $this.closest("FORM").find("INPUT[type=radio][ifchecked-expand][name='" + $this.attr("name") + "']")
: $("INPUT[type=radio][ifchecked-expand][name='" + $this.attr("name") + "']");
} else {
$all = $this;
}
$all.each(function () {
var $target = sircl.ext.$select($(this), $(this).attr("ifchecked-expand"));
if ($target.hasClass("collapse")) {
if ($(this).prop('checked')) {
$target.collapse('show');
} else {
$target.collapse('hide');
}
}
});
});
// On expand, set state:
$(document.body).on("show.bs.collapse", ".collapse[onexpand-set]", function (event) {
var $this = $(this);
var name = $(this).attr("onexpand-set");
var $input;
if (name == null || name.length == 0) {
return;
} else if ($this.closest("FORM").length > 0) {
$input = $this.closest("FORM").find("INPUT[name='" + name + "']");
} else {
$input = $("INPUT[name='" + name + "']");
}
if (["true", "on"].indexOf($input.val().toLowerCase()) < 0) {
$input.val("true");
$input.change();
}
});
// On collapse, set state:
$(document.body).on("hide.bs.collapse", ".collapse[onexpand-set]", function (event) {
var $this = $(this);
var name = $(this).attr("onexpand-set");
var $input;
if (name == null || name.length == 0) {
return;
} else if ($this.closest("FORM").length > 0) {
$input = $this.closest("FORM").find("INPUT[name='" + name + "']");
} else {
$input = $("INPUT[name='" + name + "']");
}
if (["false", "off"].indexOf($input.val().toLowerCase()) < 0) {
$input.val("false");
$input.change();
}
});
// On expand, load content:
$(document.body).on("show.bs.collapse", ".collapse[ifexpanded-load]", function (event) {
var url = $(this).attr("ifexpanded-load");
$(this).removeAttr("ifexpanded-load")
$(this).load(url);
});
});
$$(function sircl_bs4_collapse_processHandler() {
// If checked, expand, else collapse:
$("INPUT[type=checkbox][ifchecked-expand], INPUT[type=radio][ifchecked-expand]").each(function () {
var $this = $(this);
var $target = sircl.ext.$select($this, $this.attr("ifchecked-expand"));
if ($target.hasClass("collapse")) {
if ($this.prop('checked')) {
$target.collapse('show');
} else {
$target.collapse('hide');
}
}
});
// Load content on initially expanded items:
$(".collapse.show[ifexpanded-load]").each(function () {
var url = $(this).attr("ifexpanded-load");
$(this).removeAttr("ifexpanded-load")
$(this).load(url);
});
});
//#endregion
//#region Bootstrap load progress handling
sircl.addRequestHandler("beforeSend", function sircl_bs4_loadprogess_beforeSend_requestHandler(req) {
req._bsProgressToResetAfterSend = []
req._bsProgressToHideAfterSend = []
if (req.xhr != null) {
// Show and add event handler to upload progresses:
var $uploadProgresses = sircl.ext.$select(req.$initialTarget, req.$initialTarget.attr("upload-progress")).filter(".progress");
if ($uploadProgresses.length > 0) {
$uploadProgresses.each(function () {
// Set initial value:
$(this).find(".progress-bar").css("width", "0%");
req._bsProgressToResetAfterSend.push(this);
// Make hidden progresses visible:
if (!sircl.ext.visible(this)) {
req._bsProgressToHideAfterSend.push(this);
sircl.ext.visible(this, true);
}
});
// Add event handler to show upload progress:
req.xhr.upload.addEventListener("progress", function (e) {
if (e.lengthComputable) {
$uploadProgresses.each(function () {
$(this).find(".progress-bar").css("width", Math.ceil(100 * e.loaded / e.total) + "%");
});
}
});
}
// Show and add event handler to download progresses:
var $downloadProgresses = sircl.ext.$select(req.$initialTarget, req.$initialTarget.attr("download-progress")).filter(".progress");
if ($downloadProgresses.length > 0) {
$downloadProgresses.each(function () {
// Set initial value:
$(this).find(".progress-bar").css("width", "0%");
req._bsProgressToResetAfterSend.push(this);
// Make hidden progresses visible:
if (!sircl.ext.visible(this)) {
req._bsProgressToHideAfterSend.push(this);
sircl.ext.visible(this, true);
}
});
// Add event handler to show download progress:
req.xhr.addEventListener("progress", function (e) {
if (e.lengthComputable) {
$downloadProgresses.each(function () {
$(this).find(".progress-bar").css("width", Math.ceil(100 * e.loaded / e.total) + "%");
});
}
});
}
}
// Move to next handler:
this.next(req);
});
sircl.addRequestHandler("afterSend", function sircl_bs4_loadprogess_afterSend_requestHandler(req) {
// Hide progresses that were hidden before send:
req._bsProgressToHideAfterSend.forEach(function (elem) {
sircl.ext.visible(elem, false);
});
// Reset progresses to 0:
req._bsProgressToResetAfterSend.forEach(function (elem) {
$(elem).find(".progress-bar").css("width", "0%");
});
// Move to next handler:
this.next(req);
});
//#endregion
//#region ifroute-setactive
sircl.addAfterHistoryHandler(function sircl_bs4_activeRoute_afterHistoryHandler() {
$(document).find("[ifroute-setactive]").each(function () {
var regex = new RegExp($(this).attr("ifroute-setactive"), "i");
if (regex.exec(location.pathname) !== null) {
$(this).addClass("active");
} else {
$(this).removeClass("active");
}
});
});
//#endregion