Модальное окно, которое можно вызвать везде. Чистый 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 формы делается один раз, а не каждый раз как происходит нажатие.