Модальное окно, которое можно вызвать везде. Чистый JS

Йоу-йоу! Занимался я очень долго одним проектом, в котором много JS и моё большое желание не использовать jQuery. Настал тот момент, когда мне стало нужно вызывать модальное окно с разных кнопок. А еще нужно было динамически создавать модальное окно. И вместо использования готовых модальных окон, я решил сделать своё в объектно-ориентированном стиле. Наверное для тех кому нужно такое всплывающие окно самое важное это сделать вызов с разных кнопок. Об этом я и расскажу в первую очередь. 

Вызов модального окна с разных кнопок

Вообще подобная задача — это типичный пример делегирования события. И вот мой пример:

var XMC = function (object){    // Конструктор     this.delegateClick(); } XMC.prototype.delegateClick = function () {     // Это нужно потому что в событие this другое значение     var mf = this;     // Вешаю событие на window     window.addEventListener('click', function (event) {             // Проверяю есть ли у элемента нужный атрибут и правильное ли у него значение            if(event.target.hasAttribute(mf.selector) && event.target.getAttribute(mf.selector) === mf.selectorValue ){                // Открываю окно                mf.show();            }     }, mf, false);     return this; };

Думаю, что часть читателей этой статьи закроют её, так как уже поняли то что им нужно. А для ленивых, которые не хотят возиться с кодом, я выложил ссылку на github с примером и сейчас расскажу как этим пользоваться.

Установка и инициализация

Ничего особенного делать не нужно, копируете код с моего github и вставляете из файла xmcmodal.js. Подключаем его как обычный скрипт. Приступим к инициализации. В файле, на который я дал вам ссылку, уже есть пример. Я расскажу что к чему. Смотрите код и комментарии

new XMC({     // ID для блока, в котором будет контент модального окна     bodyID: 'tModlaContentBox',     // ID заднего слоя     backgroundLayerID: 'tModalContentWraper',     // Селектор который будет у всех элементов, которые будут вызывать окно     selector: 'data-type',     // Значение селектора     selectorValue: 'openModalForm',     // ID для кнопки закрыть     btnId: 'fbgmfClose',     // html во всплывающем окне или текст     content: 'wait...',     // Классы для заднего слоя     classListBg: ['zuzu', 'zaza'],     // Классы для основного блока     classListBody: ['zuzu', 'zaza2'],     // Классы для кнопки закрыть     classListBtn: ['zuzu', 'zaza3'],     // Стили для заднего слоя     styleBg: {         top: '0',         left:'0',         right: '0',         bottom: '0',         position: 'fixed',         background: '#00000090',         justifyContent: 'center',         alignItems: 'center',         zIndex: '11000'     },     // Стили для блока с контентом     styleBody: {         minWidth: '200px',         minHeight: '200px',         background: '#ffffff',         justifyContent: 'center',         alignItems: 'center',     },     // Стили кнопки закрыть     btnStyle: {         width: '40px',         height: "40px",         background: '#ffffff',         display: 'flex',         justifyContent: 'center',         alignItems: 'center',         position: 'absolute',         top: '5%',         right: '5%',         cursor: 'pointer',         zIndex: '7'     } });

Конструктор получился очень гибким. В нём можно указать всё что нужно, а потом динамически менять.

Расширение функционала

Сейчас в моём модальном окне 149 строк кода, если считать с пробелами. Но в конечном счёте, в моём проекте оно выросло до 367 строк и я рад этому. В начале моего проекта мне нужно было просто модальное окно. Но потом мне понадобилось загружать в него форму с contact form 7 по ajax, так же и отправлять данные, валидировать форму, переводить форму на 2 языка, проверять куки. И с XMC (название моего модального окна) это очень просто, потому что ты не ищешь элементы, не назначаешь множество переменных. У тебя всё хранится внутри объекта и ты имеешь доступ к его данным. Вот например как я сделал ajax-запрос формы:

XMC.prototype.ajax = function () {     var mf = this;     var data = new Object();     data = JSON.stringify(data);     var xhttp = new XMLHttpRequest();     xhttp.onreadystatechange = function () {         if(this.readyState == 4 && this.status == 200){             mf.body.innerHTML = this.responseText;             mf.form = mf.body.firstChild;             mf.form = mf.form.querySelector('form');             mf.form.setAttribute('action', '#wpcf7-f41-o1');             var el = document.createElement('div');             el.id = 'wpcf7-f41-o1';             mf.body.appendChild(el); if(window.screen.width < '758'){ var submit = mf.form.querySelector('input[type="submit"]'); mf.btnClose.classList.add('btn'); mf.btnClose.setAttribute('type', 'button'); mf.btnClose.classList.add('btn-warning'); mf.btnClose.classList.add('rounded-circle'); submit.insertAdjacentElement('afterend', mf.btnClose); }             mf.sendClickDelegate(mf.form);             mf.i18n();         }     };     xhttp.open('POST', localizationPreloader.adminUrl + "?action=fgb_modal_one_form", true);     xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");     xhttp.send("data="+data);     return this; };

this.body — это основной блок «модалки», в которую по ajax подгружаю форму. А сам ajax я вызываю initBackground() в условии если задний слой равен null. Этим я достигаю того, что ajax форма делается один раз, а не каждый раз как происходит нажатие.