Skip to content

Instantly share code, notes, and snippets.

@MohammadMD1383
Last active December 14, 2020 11:25
Show Gist options
  • Save MohammadMD1383/8f21843e6e3b465379ab3e3cdc2820b9 to your computer and use it in GitHub Desktop.
Save MohammadMD1383/8f21843e6e3b465379ab3e3cdc2820b9 to your computer and use it in GitHub Desktop.
use this module to create your bootstrap modals easily with javascript.
export default class Modal {
/** @type {boolean} */
static #isModalOpen = false;
/** @type {boolean} */
static #isRtl = false;
/** @param {boolean} bool */
static set isRtl(bool) {
if (typeof bool !== "boolean") return;
this.#isRtl = bool;
}
/** @type {Object} */
static buttonMod = Object.freeze({
close: 0,
ok: 1,
okCancel: 2,
yesNo: 3,
yesNoCancel: 4,
cancel: 5,
});
/** @type {Object} */
static #buttonText = {
/** @type {string} */
closeBtn: "Close",
/** @type {string} */
okBtn: "Ok",
/** @type {string} */
yesBtn: "Yes",
/** @type {string} */
noBtn: "No",
/** @type {string} */
cancelBtn: "Cancel",
};
/** @type {Object} */
static lang = Object.freeze({
fa: 0,
en: 1,
});
/** @param {number} language */
static set buttonsLanguage(language) {
if (language < 0 || language >= Object.keys(this.lang).length) return;
switch (language) {
case this.lang.fa:
this.#buttonText.closeBtn = "بستن";
this.#buttonText.okBtn = "خب";
this.#buttonText.yesBtn = "بلی";
this.#buttonText.noBtn = "خیر";
this.#buttonText.cancelBtn = "لغو";
break;
case this.lang.en:
this.#buttonText.closeBtn = "Close";
this.#buttonText.okBtn = "Ok";
this.#buttonText.yesBtn = "Yes";
this.#buttonText.noBtn = "No";
this.#buttonText.cancelBtn = "Cancel";
break;
}
}
/** @param {string} text */
static set closeBtnText(text) {
this.#buttonText.closeBtn = text;
}
/** @param {string} text */
static set okBtnText(text) {
this.#buttonText.okBtn = text;
}
/** @param {string} text */
static set yesBtnText(text) {
this.#buttonText.yesBtn = text;
}
/** @param {string} text */
static set noBtnText(text) {
this.#buttonText.noBtn = text;
}
/** @param {string} text */
static set cancelBtnText(text) {
this.#buttonText.cancelBtn = text;
}
/** @type {Object} */
events = {
onCloseBtnClick: () => {
},
onOkBtnClick: () => {
},
onYesBtnClick: () => {
},
onNoBtnClick: () => {
},
onCancelBtnClick: () => {
},
onIgnore: () => {
},
onClose: () => {
},
};
/** @type {Object} */
#modalObject = (() => {
/** @type {Object} */
const obj = {
/** @type {HTMLDivElement} */
modal: (() => {
const modal = document.createElement("div");
modal.classList.add("modal", "fade");
return modal;
})(),
/** @type {HTMLDivElement} */
modalDialog: (() => {
const modal_dialog = document.createElement("div");
modal_dialog.classList.add("modal-dialog", "modal-dialog-scrollable");
return modal_dialog;
})(),
/** @type {HTMLDivElement} */
modalContent: (() => {
const modal_content = document.createElement("div");
modal_content.classList.add("modal-content");
return modal_content;
})(),
/** @type {HTMLDivElement} */
modalHeader: (() => {
const modal_header = document.createElement("div");
modal_header.classList.add("modal-header");
modal_header.style.userSelect = "none";
modal_header.style.alignItems = "center";
if (Modal.#isRtl) {
modal_header.classList.add("flex-row-reverse")
}
return modal_header;
})(),
/** @type {HTMLHeadingElement} */
modalHeader_heading: (() => {
const heading = document.createElement("h4");
heading.classList.add("modal-title");
return heading;
})(),
/** @type {HTMLButtonElement} */
modalHeader_closeBtn: (() => {
const closeBtn = document.createElement("button");
closeBtn.setAttribute("type", "button");
closeBtn.classList.add("close");
closeBtn.style.marginLeft = "0";
closeBtn.dataset.dismiss = "modal";
closeBtn.innerHTML = "&times;";
closeBtn.onclick = () => {
this.events.onIgnore();
};
if (Modal.#isRtl) {
closeBtn.style.marginLeft = "-1rem";
closeBtn.style.marginRight = "0";
}
return closeBtn;
})(),
/** @type {HTMLDivElement} */
modalBody: (() => {
const modal_body = document.createElement("div");
modal_body.classList.add("modal-body");
if (Modal.#isRtl) {
modal_body.classList.add("text-right");
}
return modal_body;
})(),
/** @type {HTMLDivElement} */
modalFooter: (() => {
const modal_footer = document.createElement("div");
modal_footer.classList.add("modal-footer");
modal_footer.style.userSelect = "none";
if (Modal.#isRtl) {
modal_footer.classList.add("flex-row-reverse");
}
return modal_footer;
})(),
/** @type {HTMLButtonElement} */
modalFooter_closeBtn: (() => {
const closeBtn = document.createElement("button");
closeBtn.setAttribute("type", "button");
closeBtn.classList.add("btn", "btn-secondary");
closeBtn.dataset.dismiss = "modal";
closeBtn.textContent = Modal.#buttonText.closeBtn;
closeBtn.onclick = () => {
this.events.onCloseBtnClick();
};
return closeBtn;
})(),
/** @type {HTMLButtonElement} */
modalFooter_okBtn: (() => {
const okBtn = document.createElement("button");
okBtn.setAttribute("type", "button");
okBtn.classList.add("btn", "btn-primary");
okBtn.dataset.dismiss = "modal";
okBtn.textContent = Modal.#buttonText.okBtn;
okBtn.onclick = () => {
this.events.onOkBtnClick();
};
return okBtn;
})(),
/** @type {HTMLButtonElement} */
modalFooter_yesBtn: (() => {
const yesBtn = document.createElement("button");
yesBtn.setAttribute("type", "button");
yesBtn.classList.add("btn", "btn-success");
yesBtn.dataset.dismiss = "modal";
yesBtn.textContent = Modal.#buttonText.yesBtn;
yesBtn.onclick = () => {
this.events.onYesBtnClick();
};
return yesBtn;
})(),
/** @type {HTMLButtonElement} */
modalFooter_noBtn: (() => {
const noBtn = document.createElement("button");
noBtn.setAttribute("type", "button");
noBtn.classList.add("btn", "btn-danger");
noBtn.dataset.dismiss = "modal";
noBtn.textContent = Modal.#buttonText.noBtn;
noBtn.onclick = () => {
this.events.onNoBtnClick();
};
return noBtn;
})(),
/** @type {HTMLButtonElement} */
modalFooter_cancelBtn: (() => {
const cancelBtn = document.createElement("button");
cancelBtn.setAttribute("type", "button");
cancelBtn.classList.add("btn", "btn-secondary");
cancelBtn.dataset.dismiss = "modal";
cancelBtn.textContent = Modal.#buttonText.cancelBtn;
cancelBtn.onclick = () => {
this.events.onCancelBtnClick();
};
return cancelBtn;
})(),
};
obj.modal.appendChild(obj.modalDialog);
obj.modalDialog.appendChild(obj.modalContent);
obj.modalContent.appendChild(obj.modalHeader);
obj.modalContent.appendChild(obj.modalBody);
obj.modalContent.appendChild(obj.modalFooter);
obj.modalHeader.appendChild(obj.modalHeader_heading);
obj.modalFooter.appendChild(obj.modalFooter_closeBtn);
return obj;
})();
/** @param {string} text */
set titleText(text) {
this.#modalObject.modalHeader_heading.innerHTML = text;
this.#modalObject.modalHeader.prepend(this.#modalObject.modalHeader_heading);
}
/** @param {string} content */
set headerContent(content) {
this.#modalObject.modalHeader.innerHTML = content;
}
/** @param {string} content */
set bodyContent(content) {
this.#modalObject.modalBody.innerHTML = content;
}
/** @param {string} content */
set footerContent(content) {
this.#modalObject.modalFooter.innerHTML = content;
}
/** @param {number} btnMod */
set footerButtons(btnMod) {
if (btnMod < 0 || btnMod >= Object.keys(Modal.buttonMod).length) return;
this.#modalObject.modalFooter.innerHTML = "";
switch (btnMod) {
case Modal.buttonMod.close:
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_closeBtn);
break;
case Modal.buttonMod.ok:
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_okBtn);
break;
case Modal.buttonMod.okCancel:
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_cancelBtn);
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_okBtn);
break;
case Modal.buttonMod.yesNo:
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_noBtn);
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_yesBtn);
break;
case Modal.buttonMod.yesNoCancel:
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_cancelBtn);
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_noBtn);
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_yesBtn);
break;
case Modal.buttonMod.cancel:
this.#modalObject.modalFooter.appendChild(this.#modalObject.modalFooter_cancelBtn);
break;
}
}
/** @param {boolean} bool */
set showIgnoreButton(bool) {
switch (bool) {
case true:
this.#modalObject.modalHeader.appendChild(this.#modalObject.modalHeader_closeBtn);
break;
case false:
this.#modalObject.modalHeader.removeChild(this.#modalObject.modalHeader_closeBtn);
break;
}
}
/** @type {boolean|string} */
#backdrop = "static";
/** @param {boolean|string} value */
set hasBackdrop(value) {
if (typeof value !== "boolean" && value !== "static") return;
this.#backdrop = value;
}
/** @type {boolean} */
#keyboard = true;
/** @param {boolean} bool */
set keyboardClosable(bool) {
if (typeof bool !== "boolean") return;
this.#keyboard = bool;
}
/** @returns {void} */
show() {
if (Modal.#isModalOpen) return;
Modal.#isModalOpen = true;
$(document.body).append(this.#modalObject.modal);
const dynamicModal = $(this.#modalObject.modal);
dynamicModal.modal({
backdrop: this.#backdrop,
keyboard: this.#keyboard,
});
dynamicModal.on("hidden.bs.modal", () => {
dynamicModal.remove();
this.events.onClose();
Modal.#isModalOpen = false;
});
}
/** @returns {void} */
close() {
$(this.#modalObject.modal).modal("hide");
}
}
@MohammadMD1383
Copy link
Author

MohammadMD1383 commented Dec 14, 2020

use this module to create your bootstrap modals easily with javascript

if you want to use it outside a module just delete the "export default" from line one.

before creating your first modal object:

  • {boolean} Modal.isRtl [default = false] -- defines the direction of the content of the modal
  • {enum} Modal.buttonsLanguage [default = Modal.lang.en] -- change this to customize the language of displaying the footer buttons
  • {string} Modal.{BUTTON_NAME}BtnText [default is set by lang.en] -- use this setter to have your own texts on buttons

after creating your modal object:

  • {boolean} modal.keyboardClosable [default = true] -- you can close the modal by ESC key on your keyboard
  • {boolean|string} modal.hasBackdrop [default = 'static'] -- the backdrop status of the modal
  • {string} modal.titleText [no default] -- changes the text of the default heading (h4 tag)
  • {string} modal.headerContent [default is an empty h4 tag] -- the header part of the modal; use it if you want to put your custom tags or content
  • {string} modal.bodyContent [no default] -- the body of the modal
  • {string} modal.footerContent [default is a close button] -- use this if you want to put custom buttons or content in the modal footer
  • {enum} modal.footerButtons [default is set by buttonMod.close] -- use this to change the buttons of the footer
  • {boolean} modal.showIgnoreButton [default = false] -- change this to show/hide the (X) button in the header of the modal
  • {event} modal.events.{EVENT_NAME} [no default event] -- use this to control the button click events of the modal

methods:

  • {void} show() -- shows the modal
  • {void} close() -- closes the modal

references:

  • Modal.lang.{LANG}

    • en [default]
    • fa
  • Modal.{BTN_NAME}BtnText

    • close [default = Close]
    • ok [default = Ok]
    • yes [default = Yes]
    • no [default = No]
    • cancel [default = Cancel]
  • Modal.buttonMod.{BTN_MODE}

    • close [default]
    • ok
    • okCancel
    • yesNo
    • yesNoCancel
    • cancel
  • modal.events.{EVENT_NAME}

    • onCloseBtnClick
    • onOkBtnClick
    • onYesBtnClick
    • onNoBtnClick
    • onCancelBtnClick
    • onIgnore
    • onClose -- triggers when the modal is completely closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment