gd-bs
Version:
Bootstrap JavaScript, TypeScript and Web Components library.
314 lines (313 loc) • 11.9 kB
JavaScript
import { ClassNames } from "../classNames";
import { Base } from "../base";
import { appendContent } from "../common";
import { HTML } from "./templates";
/**
* Offcanvas Size
*/
export var OffcanvasSize;
(function (OffcanvasSize) {
OffcanvasSize[OffcanvasSize["Small"] = 1] = "Small";
OffcanvasSize[OffcanvasSize["Small1"] = 2] = "Small1";
OffcanvasSize[OffcanvasSize["Small2"] = 3] = "Small2";
OffcanvasSize[OffcanvasSize["Small3"] = 4] = "Small3";
OffcanvasSize[OffcanvasSize["Medium"] = 5] = "Medium";
OffcanvasSize[OffcanvasSize["Medium1"] = 6] = "Medium1";
OffcanvasSize[OffcanvasSize["Medium2"] = 7] = "Medium2";
OffcanvasSize[OffcanvasSize["Medium3"] = 8] = "Medium3";
OffcanvasSize[OffcanvasSize["Large"] = 9] = "Large";
OffcanvasSize[OffcanvasSize["Large1"] = 10] = "Large1";
OffcanvasSize[OffcanvasSize["Large2"] = 11] = "Large2";
OffcanvasSize[OffcanvasSize["Large3"] = 12] = "Large3";
OffcanvasSize[OffcanvasSize["XLarge"] = 13] = "XLarge";
OffcanvasSize[OffcanvasSize["XXLarge"] = 14] = "XXLarge";
OffcanvasSize[OffcanvasSize["Full"] = 15] = "Full";
})(OffcanvasSize || (OffcanvasSize = {}));
/**
* Offcanvas Size Classes
*/
export const OffcanvasSizeClassNames = new ClassNames([
"offcanvas-sm",
"offcanvas-size-sm1",
"offcanvas-size-sm2",
"offcanvas-size-sm3",
"offcanvas-md",
"offcanvas-size-md1",
"offcanvas-size-md2",
"offcanvas-size-md3",
"offcanvas-lg",
"offcanvas-size-lg1",
"offcanvas-size-lg2",
"offcanvas-size-lg3",
"offcanvas-xl",
"offcanvas-xxl",
"offcanvas-size-full"
]);
/**
* Offcanvas Types
*/
export var OffcanvasTypes;
(function (OffcanvasTypes) {
OffcanvasTypes[OffcanvasTypes["Bottom"] = 1] = "Bottom";
OffcanvasTypes[OffcanvasTypes["End"] = 2] = "End";
OffcanvasTypes[OffcanvasTypes["Start"] = 3] = "Start";
OffcanvasTypes[OffcanvasTypes["Top"] = 4] = "Top";
})(OffcanvasTypes || (OffcanvasTypes = {}));
/**
* Offcanvas Types Classes
*/
export const OffcanvasTypesClassNames = new ClassNames([
"offcanvas-bottom",
"offcanvas-end",
"offcanvas-start",
"offcanvas-top"
]);
/**
* Offcanvas
*/
class _Offcanvas extends Base {
// Constructor
constructor(props, template = HTML) {
super(template, props);
this._autoClose = null;
this._eventCreated = false;
this._tranisitioningFl = false;
// Configure the offcanvas
this.configure();
// Configure the events
this.configureEvents();
// Configure the parent
this.configureParent();
}
// Configure the card group
configure() {
// Set the attributes
this.props.id ? this.el.id = this.props.id : null;
// Set the size & type
this.setSize(this.props.size);
this.setType(this.props.type);
// Get the options
let options = this.props.options || {
backdrop: true,
keyboard: true,
scroll: false
};
// Set the properties
options.backdrop ? this.el.setAttribute("data-bs-body", "backdrop") : null;
options.scroll ? this.el.setAttribute("data-bs-body", "scroll") : null;
// Set the header
appendContent(this.el.querySelector(".offcanvas-header > div"), this.props.title);
// Set the body
appendContent(this.el.querySelector(".offcanvas-body"), this.props.body);
// Set the focus
if (options.focus) {
this.el.focus();
}
// Set the visibility
if (options.visible) {
this.toggle();
}
}
// Configures the auto-close event
configureAutoCloseEvent() {
// See if the event exists
if (this._eventCreated) {
return;
}
// Ensure the body exists
if (document.body) {
// Add a click event to the modal
document.body.addEventListener("click", (ev) => {
// See if the auto close flag is set
if (this._autoClose) {
// Do nothing if we are tranisitionsing
if (this._tranisitioningFl) {
return;
}
// Do nothing if we clicked within the offcanvas
if (ev.composedPath().includes(this.el)) {
return;
}
else {
// Get the mouse coordinates
let x = ev.clientX;
let y = ev.clientY;
let elCoordinate = this.el.getBoundingClientRect();
// See if we clicked within the offcanvas
if (x <= elCoordinate.right && x >= elCoordinate.left && y <= elCoordinate.bottom && y >= elCoordinate.top) {
return;
}
// Else, see if something was selected
else if (x == 0 && y == 0) {
return;
}
}
// Close the offcanvas if it's visible
if (this.isVisible) {
this.toggle();
}
}
});
// Set the flag
this._eventCreated = true;
}
else {
// Add the load event
window.addEventListener("load", () => {
// Configure the event
this.configureAutoCloseEvent();
});
}
}
// Configure the events
configureEvents() {
// Execute the events
this.props.onRenderHeader ? this.props.onRenderHeader(this.el.querySelector(".offcanvas-header > div"), this.props) : null;
this.props.onRenderBody ? this.props.onRenderBody(this.el.querySelector(".offcanvas-body"), this.props) : null;
// Get the close button
let elClose = this.el.querySelector(".btn-close");
if (elClose) {
// Add a click event
elClose.addEventListener("click", () => {
// Hide the modal
this.hide();
});
}
// Set the flag to determine if the modal is sticky
this.setAutoClose(this.props.options && typeof (this.props.options.autoClose) === "boolean" ? this.props.options.autoClose : true);
// See if the keyboard option is set
if (this.props.options && this.props.options.keyboard) {
// Add a click event
this.el.addEventListener("keydown", ev => {
// See if the escape key was clicked and the modal is visible
if ((ev.key === "Escape" || ev.keyCode == 27) && this.isVisible) {
// Toggle the modal
this.toggle();
}
});
}
}
/**
* Public Interface
*/
// Hides the modal
hide() {
// See if a transition is currently happening
if (this._tranisitioningFl) {
// Wait for the transition to complete
let id = setInterval(() => {
// See if the transition is complete
if (!this._tranisitioningFl) {
// Stop the loop
clearInterval(id);
// Toggle the modal
this.isVisible ? this.toggle() : null;
}
}, 250);
}
else {
// Toggle the modal
this.isVisible ? this.toggle() : null;
}
}
// Returns true if the modal is visible
get isVisible() { return this.el.classList.contains("show"); }
// Updates the auto close flag
setAutoClose(value) {
// Set the flag
this._autoClose = value;
// Configure the event if we are setting the value
this._autoClose ? this.configureAutoCloseEvent() : null;
}
// Sets the offcanvas size
setSize(offcanvasSize) {
// Parse the class names
OffcanvasSizeClassNames.parse(className => {
// Remove the class names
this.el.classList.remove(className);
});
// Set the class name
let className = OffcanvasSizeClassNames.getByType(offcanvasSize);
if (className) {
this.el.classList.add(className);
}
}
// Sets the offcanvas type
setType(offcanvasType) {
// Parse the class names
OffcanvasTypesClassNames.parse(className => {
// Remove the class names
this.el.classList.remove(className);
});
// Set the class name
let className = OffcanvasTypesClassNames.getByType(offcanvasType) || OffcanvasTypesClassNames.getByType(OffcanvasTypes.End);
this.el.classList.add(className);
}
// Shows the modal
show() {
// See if a transition is currently happening
if (this._tranisitioningFl) {
// Wait for the transition to complete
let id = setInterval(() => {
// See if the transition is complete
if (!this._tranisitioningFl) {
// Stop the loop
clearInterval(id);
// Toggle the modal
this.isVisible ? null : this.toggle();
}
}, 250);
}
else {
// Toggle the modal
this.isVisible ? null : this.toggle();
}
}
// Toggles the modal
toggle() {
let backdrop = document.querySelector(".offcanvas-backdrop");
// Set the flag
this._tranisitioningFl = true;
// See if this modal is visible
if (this.isVisible) {
// Hide the modal
this.el.classList.add("offcanvas-toggling");
this.el.classList.remove("show");
// Wait for the animation to complete
setTimeout(() => {
this.el.style.visibility = "hidden";
this.el.classList.remove("offcanvas-toggling");
// Remove the backdrop
backdrop ? document.body.removeChild(backdrop) : null;
backdrop = null;
// Set the flag
this._tranisitioningFl = false;
// Call the event
this.props.onClose ? this.props.onClose(this.el) : null;
}, 250);
}
else {
// Create the backdrop if we are showing it
let showBackdrop = this.props.options && typeof (this.props.options.backdrop) === "boolean" ? this.props.options.backdrop : true;
if (showBackdrop && backdrop == null) {
backdrop = document.createElement("div");
backdrop.classList.add("offcanvas-backdrop");
backdrop.classList.add("fade");
backdrop.classList.add("show");
document.body.appendChild(backdrop);
}
// Show the modal
this.el.style.visibility = "visible";
this.el.classList.add("offcanvas-toggling");
this.el.classList.add("show");
// Wait for the animation to complete
setTimeout(() => {
// Update the class
this.el.classList.remove("offcanvas-toggling");
// Set the flag
this._tranisitioningFl = false;
}, 250);
}
}
}
export const Offcanvas = (props, template) => { return new _Offcanvas(props, template); };