Установка
Установить такую «модалку» просто. Скачиваете js-файл и подключаете. Он не зависит от каких-то событий или библиотек, так что можете подключать где вам нужно. Вот ссылка на github
Инициализация
На той странице на которой вам нужно вызвать вы пишите в js:
new XMC({
bodyID: 'body',
backgroundLayerID: 'wrapper',
selector: 'data-type',
selectorValue: 'openModalForm',
btnId: 'mfClose',
content: 'Привет',
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: '6'
},
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'
}
});
Подробнее о пунктах в объекте
Есть 6 обязательных пунктов:
- bodyID – это идентификатор блока в котором будет содержаться контент модального окна
- backgroundLayerID – id затемняющего слоя
- selector – html атрибут который будет у всех кнопок которые будут вызывать модальное окно
- selectorValue – значение селектора
- bntID – id кнопки закрытия модального окна
- content – текст или html внутри модального окна
Необязательные, но очень важные пункты:
- classListBg, classListBody, classListBtn – массивы классов для затемняющего слоя, основного окна и кнопки закрыть соответственно
- styleBg, styleBody, btnStyle – объекты со стилями затемняющего слоя, основного окна и кнопки закрыть соответственно
Немного о самом модальном окне
Я уже говорил, что основная задача, которую решает это модальное окно — это вызов с нескольких кнопок. Клик по нескольким кнопка для вызова js это типичный пример делегирования и в XMC (так я назвал своё модальное окно) оно реализовано так:
XMC.prototype.delegateClick = function () {
var mf = this;
window.addEventListener('click', function () {
// Проверяю есть ли у элемента, на который я нажимаю соответствующий атрибут и его значение
if(event.target.hasAttribute(mf.selector) && event.target.getAttribute(mf.selector) === mf.selectorValue ){
mf.show(); // Показываю модальное окно
mf.delegateClose(); // Вешаю обработчик на закрытие
}
}, mf, false);
};
Соответственно и в конструкторе нужно прописать:
var XMC = function (object) {
/* Прочий код */
this.delegateClick();
}
Кстати, в своё время, мне помогла с этим разобраться статья с learn javascript. Ознакомиться с ней будет полезным.
AJAX для формы
В моём «кейсе» необходимо было загружать форму по 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.sendClickDelegate(mf.form);
mf.i18n();
}
};
xhttp.open('POST', localizationPreloader.adminUrl + "?action=my_action", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("data="+data);
return this;
}
Такой код запроса у меня был для CMS Wordpress.
Итог
В итоге благодаря объектному подходу у меня получилось сделать не просто всплывающие окно, а почти web-приложение в котором у меня 2 ajax для получения формы и отправки, перевод в зависимости от браузера, чтение cookie, анимация загрузки. Благодаря этому же мне не пришлось искать новые элементы по различным селекторам для перевода или работы с данными формы, которая «прилетела» по ajax.
Надеюсь, что для вас будет полезна моя статья. Удачи!
Комментарии (57)
dopusteam
19.11.2018 18:38+1Использовать такую поделку в проде крайне не рекомендую.
Неужели нельзя найти готовое решение на js?vlreshet
19.11.2018 18:45+1Всегда когда вижу пост который начинается с фразы вроде «я занимаюсь разработкой сайтов на wordpress и bitrix» ожидаю увидеть привет из 2010-го, и что-то вроде кривой библиотеки на PHP, очумительной вёрстки таблицами, или вот такой вот поделки. И ещё ни разу чутьё меня не подводило!
P.S Интересный факт — «из коробки» закрыть модалку крестиком невозможно. Крестик есть, а толку нет. codepen.io/anon/pen/GwORRE
ThunderCat
19.11.2018 18:49+1Конечно можно, bootstrap modal, magnific popup, fancybox, это самые очевидные решения которые уже обкатаны и хорошо задокументированы.
Grox
20.11.2018 02:15Одно из ограничений было не использовать jquery
Ну вы предлагаете то, что уже сразу нарушает условие задачи.ThunderCat
20.11.2018 15:35Одно из ограничений было не использовать jquery
Ну вы предлагаете то, что уже сразу нарушает условие задачи.
Уже на этапе постановки задачи можно определить что нужно в проекте и что не нужно, так что если это «без жквери по тому что, ну, мы же крутые!», то как архитектору и программисту вам грош цена. Если есть необходимость в каком-то функционале, который уже 40 раз реализован и обкатан, его не пилят на коленке «по тому что могут», а берут готовый. С ходу слабо могу представить чем не угодила библиотека весом 70 кб. Бутстрап тоже нельзя? А то там тоже жквери нужен… С таким проектом я бы вообще постеснялся не то что бы на Хабр, на прикабу публиковаться…Grox
20.11.2018 16:28Мы не знаем, по каким причинам у автора это ограничение. Но есть много поводов не тащить в зависимости Jquery или другие крупные либы ради одной мелкой задачи.
andreymal
20.11.2018 17:06Бутстрап тоже нельзя?
Да, он ужасен по всем параметрам — от проблем с изоляцией (см. БЭМ, например) до проблем с гибкостью и протеканием стилей из CSS-файлов в вёрстку.
библиотека весом 70 кб
Многовато для библиотеки, которая (в вашем примере) сама по себе ничего не делает и является лишь основой для других библиотек.
jQuery есть смысл тащить, когда есть очень качественное готовое решение, построенное на базе jQuery, и взять его намного проще, чем взять что-то другое, но вот лично в моей практике обычно оказывалось вполне возможно или взять другое готовое решение на базе ванильного JS (тоже вполне качественное), или вообще написать всё своё конкретно под свою задачу за час-другой. За последние шесть лет мне ни разу не понадобились ни jQuery, ни бутстрап (не считая поддержки сайтов, сделанных не мной).
ThunderCat
21.11.2018 00:09Многовато для библиотеки, которая (в вашем примере) сама по себе ничего не делает и является лишь основой для других библиотек.
Спорно, учитывая как раз то что на ее основе написано более 70% популярных инструментов. Собственно ее задача — качественный сахар с удобным набором функций и коротким читаемым синтаксисом.
лично в моей практике обычно оказывалось вполне возможно или взять другое готовое решение на базе ванильного JS (тоже вполне качественное), или вообще написать всё своё конкретно под свою задачу за час-другой.
Любой более-менее крупный проект включает 5-6 типовых задач, таких как попапы, слайдеры, табы, галереи, загрузчики, редакторы и еще много всякого. На 1 ванильный модуль приходится 3-5 написаных под jq. Причем чаще всего и функционалом и качеством не в пользу ванилы. Прям вот по вышеперечисленным задачам у меня уже есть набор готовых хорошо зарекомендовавших себя библиотек, из них на ваниле только ckeditor. Не вижу причины отказываться от готовых отлаженных решений ради такого вот костылестроения, как представленный в топике код. Да, он короткий, без жквери и без особых претензий, но до магнифика ему еще весьма далеко, а пилить самому такой функционал имхо расточительно, разве что если времени дофига, а заняться нечем.andreymal
21.11.2018 00:19+1качественный сахар с удобным набором функций и коротким читаемым синтаксисом
Как хорошо, что всё перечисленное давно есть в ES6 и всех современных браузерах
попапы
Пара строчек на classList.toggle
слайдеры
Навалом ванильных. Да и свой простенький тоже можно написать за 10-20 минут
табы
Реализуются без единой строчки на js
галереи
Слишком общее слово
загрузчики
<input type="file">
? Ладно, шучу, dropzone покрывает большинство потребностей и не требует никакого jQuery. Хотя я писал свой собственный загрузчик без каких-либо проблем (если я правильно понял о чём речь)
редакторы
Опять же, навалом ванильных. А также на реакте, на Vue и прочих модных нынче вещах
На 1 ванильный модуль приходится 3-5 написаных под jq
Которые не нужны, потому что можно взять этот самый 1 ванильный модуль. Или даже самому написать, зачастую это нетрудно
Причем чаще всего и функционалом и качеством не в пользу ванилы.
Вы где-то проспали последние лет пять
ckeditor
Ну точно проспали
Не вижу причины отказываться от готовых отлаженных решений ради такого вот костылестроения
Отказываться от прогресса — ваш выбор, окей
представленный в топике код
Он ужасен, я с этим не спорю
магнифика
Очередной слайдер сомнительной нужности, причём разработка заброшена
dopusteam
21.11.2018 12:22Как хорошо, что всё перечисленное давно есть в ES6 и всех современных браузерах
Не всегда современных браузеров достаточно. (Только не говорите, что идите лесом пользователи IE)
Пара строчек на classList.toggle
Продемонстрируйте, пожалуйста, очень интересно посмотреть как Вы парой строчек это сделайте
Навалом ванильных. Да и свой простенький тоже можно написать за 10-20 минут
А если не простенький, а так чтоб работал хорошо? Что входит в понятие 'простенький'?
Реализуются без единой строчки на js
Думаю, с поддержкой браузерами проблемы будут, покажите пример тогда уж
Опять же, навалом ванильных.
Покажите ванильные редакторы? Сколько они весят?
Которые не нужны, потому что можно взять этот самый 1 ванильный модуль. Или даже самому написать, зачастую это нетрудно
Выбор — это всегда хорошо. А написать всё что угодно можно, но нужно ли? Вы хотите заниматься бизнес логикой или переписывать в сотый раз слайдеры и попапы?
Отказываться от прогресса — ваш выбор, окей
Интересное мнение, что костыли и велосипеды — это прогресс
Он ужасен, я с этим не спорю
Как и в любом решении, которое 'несложно самому написать' или 'можно написать за 10-20 минут'. Ну ладно, практически в любом, если не тратить время на поддержку и допилы
Если всё писать самому и с нуля на ваниле, то рано или поздно Вы напишите подобие jq только с худшей поддержкой, без тестов, без комьюнити.andreymal
21.11.2018 12:30(Только не говорите, что идите лесом пользователи IE)
Нормально жить можно уже начиная с IE9
Продемонстрируйте, пожалуйста, очень интересно посмотреть как Вы парой строчек это сделайте
Что конкретно? Огласите полное ТЗ, пожалуйста
А если не простенький, а так чтоб работал хорошо?
Что такое «чтоб работал хорошо»? Самый-самый простой слайдер сводится и переключению классов prev/next/current у слайдов в пару десятков строчек, и это работает вполне хорошо там, где такое решение уместно.
Думаю, с поддержкой браузерами проблемы будут
IE9+. В интернете примеров много, гуглите css tabs
Покажите ванильные редакторы? Сколько они весят?
Лучше вы расскажите, чем вам это всё не угодило, потому что в моей практике пока не попадалось задач, где был бы позарез нужен редактор, и я в этой теме не особо компетентен
Вы хотите заниматься бизнес логикой или переписывать в сотый раз слайдеры и попапы?
Во-первых, одно другому не мешает, во-вторых, это всё пишется один раз
Интересное мнение, что костыли и велосипеды — это прогресс
Интересное мнение, что использование протухших библиотек пяти- и десятилетней давности (в том числе jQuery) это прогресс
Как и в любом решении, которое 'несложно самому написать' или 'можно написать за 10-20 минут'. Ну ладно, практически в любом, если не тратить время на поддержку и допилы
Демагогия какая-то
dopusteam
21.11.2018 12:40качественный сахар с удобным набором функций и коротким читаемым синтаксисом
Нормально жить можно уже начиная с IE9
То есть начиная с IE9 ничего нового нет?
Что конкретно? Огласите полное ТЗ, пожалуйста
Попап, который принимает рандомный контент, центруется корректно, блокирует всё, то под ним, позволяет закрыть его, который можно двигать с анимацией появления\удаления
Лучше вы расскажите, чем вам это всё не угодило, потому что в моей практике пока не попадалось задач, где был бы позарез нужен редактор, и я в этой теме не особо компетентен
Что именно 'это'? Покажите ванильный сначала редактор, я не знаю таких
Во-первых, одно другому не мешает, во-вторых, это всё пишется один раз
Мешает. Время отнимает. И пишется не один раз, отнюдь. Допиливать придётся, как всегда бывает. Вам даже в комментах указали уже на неработающую кнопку 'закрыть'. (Да, Вы её поправили, но, блин, это самый базовый функционал). Или Вы хотите сказать, что Вы написали попап уже один раз и его можно использовать? Больше Вы ничего править не будете?
Интересное мнение, что использование протухших библиотек пяти- и десятилетней давности (в том числе jQuery) это прогресс
Замените jq на angular (vue etc...), суть не меняется. Не стОит самому писАть то, что написано уже тысячу раз. Мой коммент не конкретно о jq
Демагогия какая-то
Серьёзно? Я не прав?andreymal
21.11.2018 12:52То есть начиная с IE9 ничего нового нет?
Я такого не говорил. В IE9 есть достаточно для нормальной жизни, а для полной радости есть Babel и core-js
Попап, который принимает рандомный контент
innerHTML
центруется корректно
flex
блокирует всё, то под ним
overlay
позволяет закрыть его
overlay.onclick
который можно двигать
Нафига его двигать? Но ладно, это тоже должен любой js-программист уметь писать, это даже на learn.javascript.ru описывается
с анимацией появления\удаления
CSS3 transition и classList.toggle
Ваши желания в пару строчек уже не уместятся.
Что именно 'это'?
А это я вас спрашиваю. Не я же тут про редакторы ною
Покажите ванильный сначала редактор
В гугле забанили?
Мешает. Время отнимает.
Жаль вас, если вы такой медленный специалист
И пишется не один раз, отнюдь. Допиливать придётся, как всегда бывает.
Допиливать ? переписывать с нуля
Вам даже в комментах указали уже на неработающую кнопку 'закрыть'.
Если внимательно прочитать ники комментаторов, то можно заметить, что это я и указал :)
(Да, Вы её поправили, но, блин, это самый базовый функционал).
Поправил не я, но опять же — поправилось за минуту.
Или Вы хотите сказать, что Вы написали попап уже один раз и его можно использовать? Больше Вы ничего править не будете?
Вот когда возникнет задача что-нибудь поправить, тогда и поправится. Но опять же, многие вещи правятся за минуту.
Замените jq на angular (vue etc...), суть не меняется.
Ничего из упомянутого я в своих сайтах не использую
Не стОит самому писАть то, что написано уже тысячу раз.
Полностью согласен. Но это не значит, что нужно брать готовое решение только ради того, чтобы взять готовое решение. Иногда проще, гибче и быстрее (!) написать своё. Особенно в перспективе на будущие правки, когда готовое решение может оказаться недостаточно гибким и придётся от него отказываться — замена одного готового решения на другое готовое решение может оказаться даже дольше, чем самостоятельное написание с нуля.
Демагогия какая-то
Серьёзно? Я не прав?
Мне нечего на это ответить, потому что демагогия какая-то
dopusteam
21.11.2018 13:02flex
Внезапно flex не работает в IE 9
overlay
Кода нет, ну ок,
Ваши желания в пару строчек уже не уместятся.
Я Вам о том же толкую. Сделать самое простое решение можно и самому, но надолго ли его хватит?
В гугле забанили?
Я даже не знаю, что Вам ответить
Жаль вас, если вы такой медленный специалист
Ну на личности то зачем
Допиливать ? переписывать с нуля
Хаха, очень удобно. Можно бесконечно перепиливать, (утрирую) тратить по 8 часов в день, но ПИШЕТСЯ ЖЕ ОДИН РАЗ, я просто переписываю
Если внимательно прочитать ники комментаторов, то можно заметить, что это я и указал :)
Да, уже заметил, прошу прощения. Но это лишь подтверждает мою правоту
Поправил не я, но опять же — поправилось за минуту.
Я не знаю, как Вас убедить. Если 'простое решение', которое 'делается' за 5 минут имеет проблемы в базовой функциональности, то может стОит всё же взять готовое решение? Сколько потенциальны ошибок будет при допиле?
Ничего из упомянутого я в своих сайтах не использую
Советую всё же попробовать. Круто писАть всё с нуля, все так делали, наверное, но нужно тратить время на решение нерешённых задач
Иногда проще, гибче и быстрее (!) написать своё.
Имхо, лучше форкнуть готовое решение. Свой велосипед в 99% будет худшим решением. Для замены обычно можно сделать свою обёртку над готовым решением и тогда замена не такая болезненная.
Нафига его двигать?
Я просто зашёл на jquery popup и взял первую базовую демку.
Заказчик так хочет и, внезапно, это удобно бывает. Особенно если ресайзить можно ещё.
Вы сказали, что сделать это можно парой строчек кода, а когда я накинул требований Вы ничего вдруг не делаете.
А это я вас спрашиваю. Не я же тут про редакторы ною
Опять же, навалом ванильных.
Покажите хоть один ужеandreymal
21.11.2018 13:16-1Внезапно flex не работает в IE 9
Зато работает в IE11. Но в самом крайнем случае (а то говорят, что flex в IE11 баганутый) можно сделать хоть для IE5, высчитывая координаты в JS — опять же пара строчек с getBoundingClientRect и тривиальнейшей арифметикой.
Я Вам о том же толкую. Сделать самое простое решение можно и самому, но надолго ли его хватит?
Ваши желания влезут в пару сотен строчек, и тащить jQuery или готовые библиотеки для них совсем не обязательно (ну разве что для drag&drop можно притащить, там код нетривиальный всё-таки)
Хаха, очень удобно. Можно бесконечно перепиливать, (утрирую) тратить по 8 часов в день, но ПИШЕТСЯ ЖЕ ОДИН РАЗ, я просто переписываю
Снова демагогия
имеет проблемы в базовой функциональности
Это автор поста такой 'хороший' специалист. Естественно, если не уметь кодить на js, то, очевидно, лучше всегда брать готовые решения. Но я вот, например, умею кодить на js — мне готовые решения в большинстве случаев просто не нужны. (Для совсем тяжёлых задач вроде того же редактора взять готовое решение пожалуй стоит, но какой-нибудь попап явно не относится к таким сложным задачам)
Имхо, лучше форкнуть готовое решение.
А потом разбираться в тамошнем говнокоде в три раза дольше, чем писать своё с нуля. Плавали, знаем
Вы сказали, что сделать это можно парой строчек кода
Я сказал это до появления таких странных требований
Я просто зашёл на jquery popup и взял первую базовую демку. Заказчик так хочет и, внезапно, это удобно бывает.
А потом у заказчика появится ещё какое-нибудь одно требование, которое не решается найденным готовым решением. И придётся или искать другое, или форкать имеющееся, или писать своё. И что-то я совсем не уверен, что первые два варианта быстрее третьего
Я даже не знаю, что Вам ответить
Наверно, на этом можно и закончить)
ThunderCat
21.11.2018 15:44Нормально жить можно уже начиная с IE9
Неправда, до 11 включительно полной совместимости нет.
Интересное мнение, что использование протухших библиотек пяти- и десятилетней давности (в том числе jQuery) это прогресс
JQ — последний пул реквест 7 денй назад, не думаю что дата создания проекта влияет на протухлость продукта. Хабр вот использует JQ «и не жужжит». Тот же дропзон тоже древний, причем изначально тоже был на JQ. И сейчас регистрируется как его модуль, если доступен. В целом в большинстве случаев прогресс ради прогресса нафиг никому не сдался, все упирается в стоимость решения, блидинг эйдж используется на 0,1% задач. Eсли есть что-то рабочее уже сейчас — писать что-то новое на ваниле как минимум не рационально.
Магнифик — Очередной слайдер сомнительной нужности, причём разработка заброшена
Его большое преимущество — он работает и имеет много гитик, внешний вид вообще зависит только от самого блока попапа, так что вообще не понятно причем тут наружность, код легко правится если чего-то не хватает. Ничего ванильного лежащего рядом пока не встретил. 3 наиболее популярные альтернативы с примерно подходящим функционалом тоже на JQ. Напишите что-то похожее на ваниле — с удовольствием перейду на ваш.andreymal
21.11.2018 16:03-1Неправда, до 11 включительно полной совместимости нет.
Не поленился и проверил код по ссылке — всё отлично добавляется даже вместе с svg-элементом в IE11 в Windows 7. Так что или автор что-то не договаривает, или просто врёт. Вы, следовательно, тоже врёте.
Кроме того, у меня есть целых два сайта, которые целиком полагаются на innerHTML, и они тоже отлично работают в IE11.
JQ — последний пул реквест 7 денй назад
Всего лишь поддержка легаси, даты коммитов сами по себе ничего не значат
Хабр вот использует JQ «и не жужжит»
Всего лишь поддержка легаси. А вот какой-нибудь GitHub взял и отказался от jQuery, например
причем изначально [дропзон] тоже был на JQ.
Воот, дропзон очень даже развивается :)
прогресс ради прогресса нафиг никому не сдался
Примерно поэтому мир говно (не только в программировании, вообще везде)
Напишите что-то похожее на ваниле
Огласите полный список требований, пожалуйста. Я, посмотрев примеры на сайте, вообще не понял, зачем он нужен
ThunderCat
21.11.2018 17:11пруф на SO, работает НЕ ТАК КАК В ДРУГИХ БРАУЗЕРАХ, то есть совместимости нет, + на момент вопроса было проверено что представленный в первом линке код тоже не работал в ваниле.
Примерно поэтому мир говно (не только в программировании, вообще везде)
Да не все так мрачно, все же 0,1% использует и двигает все вперед, просто это выбор единиц, ибо не все готовы положить еще 1 день на алтарь прогресса, когда старое работает и выполняет все как надо.
Всего лишь поддержка легаси. А вот какой-нибудь GitHub взял и отказался от jQuery, например
Это говорит лишь о том что там он не нужен, или как в примере ТС — «давайте сделаем без жквери!» сказали сверху, и причины могут быть абсолютно разные, вплоть до имиджевых. Никто не говорит что нельзя, просто рынок ищет наиболее выгодные решения минимум затрат/максимум выработки.andreymal
21.11.2018 17:20+1пруф на SO
Не увидел в вашем «пруфе» воспроизводимого примера, который я бы мог проверить.
Попытавшись запустить те несчастные три строчки из кода вопроса, я получил в IE11 поведение, полностью аналогичное фаерфоксу — контент не изменился (и не должен был измениться).
Так что нет, не пруф. Всё работает.
Я даже попытался использовать таблицу
<table id="mainForm:table_1">
как упомянуто в комментарии к вопросу — и нет, она тоже работает!
Это говорит лишь о том что там он не нужен
Он не нужен почти везде.
рынок ищет наиболее выгодные решения минимум затрат/максимум выработки
Как я уже говорил,
Примерно поэтому мир говно
Рынок со мной обсуждать нет смысла.
ArsenAbakarov
19.11.2018 18:44classList, styleBg…
Раз уж прям ничего нельзя использовать (а я сомневаюсь..), берешь data атрибут, пихаешь роль popup, делаешь еще data атрибут, связывешь контрол с контентом, в js находишь свои контролы с нужной ролью, подписываешься на нужное событие, в коллбеке находишь контент и рендеришь со свистелками и перделками, все стили в css.
BigDflz
19.11.2018 19:18-3ну если для таких поделок пишут статью то не грех и без написания похвастаться
github.com/JonHappy/JonHappy.github.io — описание
jonhappy.github.io демка
Rulexec
19.11.2018 21:51Зачем нужны обязательные идентификаторы, которые будут присвоены элементам? Если для стилей, то лучше сделать их опциональными. Хорошо, что есть возможность задавать классы. Идентификаторы никогда не стоит использовать. Если очень нужно — генерировать уникальные.
В конструкторе вы используете оператор in для проверки наличия опций и записываете их в this. А дальше проверяете эти опции на !== null. Что-то мне кажется, что если не подать classListBg, случится исключение в setClasses. in не нужен, вместо x !== null для таких проверок лучше просто проверять x, либо typeof x === 'string', либо Array.isArray(x), в зависимости от того, что ожидаем. Ещё лучше — хранить в опциях дефолтные валидные значения, использование которых ничего не изменит (вроде пустого списка/нуля/etc), чтобы проверки вообще не были нужны.
Ваш delegateClick создаёт утечку памяти. Вы подписываетесь на клики по всему окну, но никогда не отписываетесь. Каждый раз, когда я буду создавать экземпляр XMC, я буду подписываться на клики и держать указатель на mf/this, который будет держать всё остальное.
Хотя и никаких методов для того, чтобы удалить все созданные элементы из DOM тоже нет.
this.body.innerHTML = this.content;
Никогда не используйте innerHTML. Кроме случаев, когда HTML небольшой, находится прямо перед глазами и в него ничего не вклеивается. Передавайте всё элементами/фрагментами. Если нужно показать текст — document.createTextNode('text'), если нужна более сложная структура — как-нибудь постройте дерево элементов, выберите узлы и используйте textContent.
А если я хочу анимацию появления окна? А если у меня в проекте уже есть модуль, отвечающий за оверлеинг интерфейса (то, что у вас делает backgroundLayer)?
Для библиотеки слишком много лишних вещей, которые могут быть мало кому нужны и нет возможностей кастомизировать поведение.
Помню тоже как-то на хабр про свой велосипедный PHP-шаблонизатор писал. Не расстраивайтесь, продолжайте абстрагировать.
andreymal
19.11.2018 21:54Никогда не используйте innerHTML.
Почему?
как-нибудь постройте дерево элементов
Где-то по хабру ходили слухи, что у innerHTML производительность лучше
Rulexec
19.11.2018 22:11Потому что когда-нибудь получится:
div.innerHTML = '<span>' + item.getDescription() + '</span>';
А в description однозначно проникнет:
<script src='//example.org/evil.js'></script>
Где-то по хабру ходили слухи, что у innerHTML производительность лучше
Тоже видел, не могу найти. Если этот HTML показывает не просто статику, а является куском интерфейса, в любом случае придётся селекторами выбирать из него элементы, чтобы навешивать обработчики/управлять отображением. И тогда cloneNode(true) должен быть быстрее, ибо не нужно парсить строку. По крайней мере в 2009 был.
andreymal
19.11.2018 22:16'<span>' + item.getDescription() + '</span>'
А, ну в таком случае да. Только вот два нюанса: во-первых, innerHTML блокирует запуск
скриптовтегов <script> (впрочем, от произвольного html-кода тоже ничего приятного, да), а во-вторых, если стоит задача просто отобразить кусок html-кода, пришедшего с сервера по аяксу, то такого не будет
в любом случае придётся селекторами выбирать из него элементы, чтобы навешивать обработчики
delegateClick :) (ну, если взять адекватную реализацию)
andreymal
19.11.2018 22:29Меня терзали смутные сомненья, перепроверил — не, onclick в innerHTML всё-таки не блокируется, слава XSS
Правда, теперь стало непонятно, зачем блокировать <script> и при этом не блокировать onclick
ZaEzzz
20.11.2018 07:43Вроде script там не блокируется, а просто не исполняется, так как событие для этого уже прошло. По этому onclick и «не блокируется». Есть DOM элемент с onclick. Почему нельзя его выполнить? Зачем браузеру помнить о том, что вставлено через innerHTML итд?
andreymal
20.11.2018 13:22О каком событии речь? Если создать script через createElement, то он исполняется, например, поэтому как-то больше похоже на специальную блокировку
Зачем браузеру помнить о том, что вставлено через innerHTML итд?
Теоретически можно было бы вычищать все onclick'и при парсинге innerHTML-кода, и помнить ничего не надо
mayorovp
20.11.2018 13:30Затем, что когда-то давно любили делать
document.body.innetHTML += '...';
. Было бы печально если бы этот код начал повторно выполнять все скрипты на странице.andreymal
20.11.2018 13:49Это многое объясняет, спасибо
Обнаружил интересный факт: IE6-8 всё же исполняют скрипты при наличии атрибута defer
BigDflz
19.11.2018 22:30+1Если этот HTML показывает не просто статику, а является куском интерфейса, в любом случае придётся селекторами выбирать из него элементы, чтобы навешивать обработчики/управлять отображением.
совершенно лишняя операция.
learn.javascript.ru/event-delegation
один раз обработчик вешается на родителя и меняйте внутренности родителя как угодно
клики (к примеру) будут отработаны на нужном элементе
BigDflz
20.11.2018 22:33andreymal
Rulexec
сделал простейшую демку для сравнения
github.com/JonHappy/innerHTML_VS
innerHTML быстрееmayorovp
21.11.2018 08:57Конечно быстрее — когда у вас готовый HTML есть. А вы попробуйте превратить ваш json в html циклом… И обработчики событий на элементы развесить не забудьте!
BigDflz
21.11.2018 09:00Конечно быстрее — когда у вас готовый HTML есть
Ура!
А вы попробуйте превратить ваш json в html циклом...
смысл делать такую глупость? когда можно сделать готовый html на сервере сразу из нужных данных?mayorovp
21.11.2018 09:03Затем что, сам вопрос "что быстрее — innerHTML или createElement" возникает в тех ситуациях когда, сюрприз, готового HTML нету!
andreymal
21.11.2018 10:56Смысл делать готовый html на сервере, когда можно передать json на клиент и уменьшить нагрузку на сервер? :)
BigDflz
21.11.2018 13:55-1для сервера что json, что html — это простые строки и нагрузка на сервер что для формирования json, что для формирования html одинакова.
если рассматривать ответы fw то можно увидеть, что в json включают одним из полей и строку html.
это объясняется тем, что протокол ajax требует на один запрос — один ответ, поэтому передаются и данные и строка html, json это позволяет.
при использовании ws такой необходимости нет — можно одним ответом отправить только строку html, а вторым ответом — набор данных в виде json.
а то что fw не брезгуют отправкой html строки достаточно нагуглить серверный рендеринг
BigDflz
19.11.2018 22:18вот небольшое объяснение,
learn.javascript.ru/memory-removechild-innerhtml
learn.javascript.ru/multi-insert
но ни чего про быстродействие.
суть в том на чем будет потеря, если вы вставляете (допустим в див всю таблицу) вы можете вставить через innerHTML, и произойдет удаление и вставка. dom обработает это все за один раз. но если вы будете вставлять через другие команды вам потребуется ещё и циклы js что соответственно добавит к небольшому времени работы команд поэлементной вставки дополнительное время.
в итоге суммарное время будет больше.
вставка таким методом ul.innerHTML = ul.innerHTML + "..." — совершенно не верная.andreymal
19.11.2018 22:20вставка таким методом ul.innerHTML = ul.innerHTML + "..." — совершенно не верная.
Ну о таком методе никто здесь речи и не ведёт, это очевидно неправильное использование innerHTML, я не об этом
BigDflz
19.11.2018 22:35про такую вставку — чисто дополнение :)
а так проверял — innerHTML быстрее. если учесть что с сервера пришла готовая строка HTML — это называется «серверный рендеринг»
BigDflz
21.11.2018 07:35Никогда не используйте innerHTML.
Почему?
потому что автор не знает что такое серверный рендеринг :)
sazareks
Еще бы рабочую дэмку!
xakplant Автор
codepen.io/xakplant/pen/XyzqGz
andreymal
При клике по кнопкам пишет в js-консоль ошибку
ReferenceError: event is not defined
и ничего не происходит. Даже на кроссбраузерность не проверяли?xakplant Автор
Да, действительно, моя ошибка у себя на продакшн версии исправил, а на гитхаб нет.
Я исправил в примере и на codepen'е