moodal
v0.1.3
Published
A pure JavaScript library for modal dialog.
Downloads
804
Maintainers
Readme
Moodal
A pure JavaScript library for modal dialog.
Get Started
1. Install
Install from NPM
npm install moodal --save
# or using yarn
yarn add moodal
// import Moodal js
import Moodal from 'moodal';
// import required style
import 'moodal/lib/css/moodal-core.css';
Use CDN
<script
src="https://unpkg.com/moodal/lib/standalone/moodal.min.js"
defer
></script>
<link
rel="stylesheet"
href="https://unpkg.com/moodal/lib/css/moodal-core.css"
/>
Use ES modules in browser.
<script type="module" src="https://unpkg.com/moodal/lib/esm/index.mjs"></script>
<link
rel="stylesheet"
href="https://unpkg.com/moodal/lib/css/moodal-core.css"
/>
2. Add markup
[data-moodal-container]
element is requied. And this shoud be left empty. (will be rewrited innerHTML)[data-moodal-close]
elements can be anywhere. The modal is close on it clicked.
<div class="c-moodal" tabindex="-1" aria-hidden="true">
<div class="c-moodal__bg"></div>
<div class="c-moodal__loader">...Loading</div>
<div class="c-moodal__container">
<!-- close modal on `data-moodal-close` element clicked -->
<div class="c-moodal__overlay" data-moodal-close></div>
<div class="c-moodal__inner">
<div class="c-moodal__body">
<button class="c-moodal__close" type="button" data-moodal-close>
Close
</button>
<div
class="c-moodal__content"
role="dialog"
aria-modal="true"
data-moodal-container
>
<!-- Will be appended content here -->
</div>
</div>
</div>
</div>
</div>
Minimum
<div class="c-moodal" tabindex="-1" aria-hidden="true">
<div class="c-moodal__container">
<div class="c-moodal__inner">
<div class="c-moodal__body">
<div
class="c-moodal__content"
role="dialog"
aria-modal="true"
data-moodal-container
></div>
</div>
</div>
</div>
</div>
3. Initialize Core
new Moodal( wrapperElement: string|HTMLElement, <options>)
;
// Init Core
const myModal = new Moodal('.c-moodal'); // selector or HTMLElement
// Init Core with options
const myModal = new Moodal('.c-moodal', {
noBackgroundScroll: true,
backgroundElement: document.querySelector('.page-wrapper'),
waitContentLoaded: true,
stateClasses: {
isVissible: 'is-vissible',
isLoading: 'is-loading',
},
});
4. Add Controller
moodal.addController(<params>)
- Example 1: Get content from DOM element in the page.
<!-- controller -->
<button type="button" data-moodal-anchor="myContent">
Show Modal of `myContent`
</button>
<!-- template for content -->
<template id="myContent" style="display:none;">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,...</p>
</template>
const modalCtrl = myModal.addController({
controllerAttr: 'data-moodal-anchor',
getContent: (trigger) => {
// `trigger` is value of attribute `data-moodal-anchor`.
const targetEl = document.getElementById(trigger);
if (!targetEl) return;
const content = document.createElement('div');
content.innerHTML = targetEl.innerHTML;
// Must return a HTMLElement
return content;
},
});
// You can show/hide modal by JavaScript
modalCtrl.show('myContent');
modalCtrl.hide();
- Example 2: Get content from page by fetch
<!-- controller -->
<button data-moodal-ajax="target.html">Show Modal of `target.html`</button>
const modalCtrlAjax = myModal.addController({
controllerAttr: 'data-moodal-ajax',
getContent: async (trigger) => {
const response = await fetch(trigger, {
method: 'GET',
});
const data = await response.text();
const wrapper = document.createElement('div');
wrapper.innerHTML = data;
const content = wrapper.querySelector('article');
if (!content) {
throw new Error('No Content!');
}
return content;
},
});
5. Styling
No theme styles is included in this library.
You need to add the theme css yourself.
.c-moodal__bg {
background-color: rgba(0, 0, 0, 0.7);
}
.c-moodal__inner {
padding-top: 60px;
padding-bottom: 60px;
}
.c-moodal__body {
border-radius: 6px;
padding: 40px;
background-color: #fff;
}
Life cycle
Core Params
| Param Name | Type | Default | Desc |
| ----------------------- | ------------------ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| containerSelector | string | "[data-moodal-container]" | Selector for the element appended content |
| hideOnClickSelector | string | "[data-moodal-close]" | Selector for elements that close modal when clicked |
| noBackgroundScroll | boolean | false | if true, fix scrolling element |
| backgroundElement | HTMLElement | undefined | The element you want to stop scrolling. ex. document.querySelector(".page-wrapper")
* require if noBackgroundScroll
is true |
| waitContentLoaded | boolean | true | if true, the modal is shown after <img>
or <iframe>
element is loaded. |
| stateClasses | Object | | Classes for showing / loading state |
| stateClasses.isVissible | string | string[] | is-vissible | Class on showing modal |
| stateClasses.isLoading | string | string[] | is-loading | Class on loading modal |
| logLevel | number | 2 | 0 = off, 1 = error, 2 = warning, 3 = info, 4 = debug |
| enableFocusTrap | boolean | true | Trap focus within a modal container on showing |
| hideByEscKey | boolean | true | Hide modadal using the ESC Key |
Controller Params
myModal.addController({
getContent: (trigger) => {
// You must make content element form `trigger`
// ...some code
return content; // return HTMLElement
},
controllerAttr: 'data-modal-control',
});
| Param Name | Type | Default | Desc |
| ----------------- | ---------------------------------------------------------- | ------------------------------ | --------------------------------------------------- |
| getContent | (trigger: string) => Promise<HTMLElement> | HTMLElement | undefind * required | Get the content(HTMLElement) from trigger
argment |
| controllerAttr | string | "" | Data attribute name for button elements. |
| waitContentLoaded | boolean | initialParam.waitContentLoaded | Overide the core option |
| manualShow | boolean | false | if true, you need show the modal manualy |
Lifecycle Hooks
myModal.addController({
getContent: (target)=> {
...
},
beforeAppend: (context) => {
// context argment is object { content: HTMLElement, trigger:string }
console.log('on before append:',context);
},
afterAppend: ({content,trigger}) => {
// if this return `Promise`, proccess wait for resolve.
return new Promise((resolve, rejects) => {
console.log('content:',content,'trigger:',trigger);
setTimeout(() => {
console.log('1000ms later after appending');
resolve();
}, 1000);
});
}
})
Hooks
| Hook Name | Type | Desc | | ------------ | ------------------------------------- | --------------------------------- | | beforeAppend | (context) => Promise<void> | void; | Hook before appending the content | | afterAppend | (context) => Promise<void> | void; | Hook after appending the content | | beforeShow | (context) => Promise<void> | void; | Hook before showing the modal | | afterShow | (context) => Promise<void> | void; | Hook after showing the modal | | beforeHide | (context) => Promise<void> | void; | Hook before hiding the modal | | afterHide | (context) => Promise<void> | void; | Hook after hiding the modal |
Filter
| Hook Name | Type | Desc |
| ---------------- | ------------------------------------------------------------------------ | --------------------------------------------------- |
| contentCreated() | (content: HTMLElement) => HTMLElement | Promise<HTMLElement> | void; | Filtering the content before beforeAppend
running |
Browser support
Moodal is using Promose. Can I use
If you need support legacy browser like IE11, use polyfill