HM-50. Сделан универсальный компонент модалки (#19)
This commit is contained in:
78
src/app.html
78
src/app.html
@ -9,18 +9,12 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- Шаблон верхнего меню -->
|
<!-- Шаблон верхнего меню -->
|
||||||
<template id='main-menu'>
|
<template id="main-menu">
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
<div class="Logo__box">
|
<div class="Logo__box">
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown"
|
||||||
class="navbar-toggler"
|
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
type="button"
|
|
||||||
data-toggle="collapse"
|
|
||||||
data-target="#navbarNavDropdown"
|
|
||||||
aria-controls="navbarNavDropdown"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
<div class="collapse navbar-collapse" id="navbarNavDropdown">
|
||||||
@ -52,45 +46,71 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Шаблон Modal -->
|
||||||
|
<template id="universal-modal">
|
||||||
|
<div class="Modal">
|
||||||
|
<div class="Modal__window modal">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title"></h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body"></div>
|
||||||
|
<div class="modal-footer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- Шаблон кнопки -->
|
<!-- Шаблон кнопки -->
|
||||||
<template id="test-button">
|
<template id="test-button">
|
||||||
<button type="button" class="btn btn-primary">Проверка сборки</button>
|
<button type="button" class="btn btn-primary">Проверка сборки</button>
|
||||||
</template>
|
</template>
|
||||||
<!-- Шаблон колонки таблицы -->
|
<!-- Шаблон колонки таблицы -->
|
||||||
<template id="table-column">
|
<template id="table-column">
|
||||||
<th scope='col' class='Table__column'></th>
|
<th scope="col" class="Table__column"></th>
|
||||||
</template>
|
</template>
|
||||||
<!-- Шаблон строки таблицы -->
|
<!-- Шаблон строки таблицы -->
|
||||||
<template id="table-row">
|
<template id="table-row">
|
||||||
<tr class="Table__body-row">
|
<tr class="Table__body-row">
|
||||||
<th class="Body__row-index"></th>
|
<th class="Body__row-index"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
<!-- Шаблон главной таблицы -->
|
<!-- Шаблон главной таблицы -->
|
||||||
<template id="main-table">
|
<template id="main-table">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead class="Table__head">
|
<thead class="Table__head">
|
||||||
<tr class='Table__head-row'>
|
<tr class="Table__head-row">
|
||||||
<th scope='col' class='Table__column'>#</th>
|
<th scope="col" class="Table__column">#</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class='Table__body'>
|
<tbody class="Table__body">
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</template>
|
</template>
|
||||||
<!-- Шаблон информации об апи -->
|
<!-- Шаблон информации об апи -->
|
||||||
<template id="api-info">
|
<template id="api-info">
|
||||||
<div class="card text-center Info__container">
|
<div class="card text-center Info__container">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h1 class="Info__title"></h1>
|
<h1 class="Info__title"></h1>
|
||||||
<div class="Info__controls">
|
<div class="Info__controls">
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pencil" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pencil" fill="currentColor"
|
||||||
<path fill-rule="evenodd" d="M11.293 1.293a1 1 0 0 1 1.414 0l2 2a1 1 0 0 1 0 1.414l-9 9a1 1 0 0 1-.39.242l-3 1a1 1 0 0 1-1.266-1.265l1-3a1 1 0 0 1 .242-.391l9-9zM12 2l2 2-9 9-3 1 1-3 9-9z"/>
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill-rule="evenodd" d="M12.146 6.354l-2.5-2.5.708-.708 2.5 2.5-.707.708zM3 10v.5a.5.5 0 0 0 .5.5H4v.5a.5.5 0 0 0 .5.5H5v.5a.5.5 0 0 0 .5.5H6v-1.5a.5.5 0 0 0-.5-.5H5v-.5a.5.5 0 0 0-.5-.5H3z"/>
|
<path fill-rule="evenodd"
|
||||||
|
d="M11.293 1.293a1 1 0 0 1 1.414 0l2 2a1 1 0 0 1 0 1.414l-9 9a1 1 0 0 1-.39.242l-3 1a1 1 0 0 1-1.266-1.265l1-3a1 1 0 0 1 .242-.391l9-9zM12 2l2 2-9 9-3 1 1-3 9-9z" />
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M12.146 6.354l-2.5-2.5.708-.708 2.5 2.5-.707.708zM3 10v.5a.5.5 0 0 0 .5.5H4v.5a.5.5 0 0 0 .5.5H5v.5a.5.5 0 0 0 .5.5H6v-1.5a.5.5 0 0 0-.5-.5H5v-.5a.5.5 0 0 0-.5-.5H3z" />
|
||||||
</svg>
|
</svg>
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-trash" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-trash" fill="currentColor"
|
||||||
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4L4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
|
<path
|
||||||
|
d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z" />
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4L4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -100,7 +120,7 @@
|
|||||||
<code contenteditable class="Info__editor"></code>
|
<code contenteditable class="Info__editor"></code>
|
||||||
</div>
|
</div>
|
||||||
<div class="Info__footer card-footer text-muted">
|
<div class="Info__footer card-footer text-muted">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
17
src/components/modal/Modal.css
Normal file
17
src/components/modal/Modal.css
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
.Modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: none;
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Modal__window {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Modal_show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
88
src/components/modal/Modal.js
Normal file
88
src/components/modal/Modal.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import Component from '../component/index';
|
||||||
|
|
||||||
|
import './Modal.css';
|
||||||
|
|
||||||
|
const EVENTS = {
|
||||||
|
TOGGLE: 'toggle',
|
||||||
|
CLICK: 'mousedown'
|
||||||
|
};
|
||||||
|
|
||||||
|
const TEMPLATE = '#universal-modal';
|
||||||
|
const MODAL = '.modal';
|
||||||
|
const MODAL_SHOW = 'Modal_show';
|
||||||
|
const CLOSE_BUTTON = '.close';
|
||||||
|
const MODAL_HEADER = '.modal-title';
|
||||||
|
const MODAL_CONTENT = '.modal-body';
|
||||||
|
const MODAL_FOOTER = '.modal-footer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function ModalListener
|
||||||
|
* @param {boolean} isOpen - принимает первым параметром новое состояние модалки
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Класс для создания модальных окон
|
||||||
|
* @param {Node} parentNode - родительский Node, в который следует положить модалку
|
||||||
|
* @param {{headerNode: Node; contentNode: Node; footerNode: Node}} options - Опции для размещения компонентов внутри модалки
|
||||||
|
*/
|
||||||
|
class Modal extends Component {
|
||||||
|
constructor (parentNode, {
|
||||||
|
headerNode,
|
||||||
|
contentNode,
|
||||||
|
footerNode,
|
||||||
|
} = {}) {
|
||||||
|
super(TEMPLATE, parentNode);
|
||||||
|
|
||||||
|
this.modal = this.mainNode.querySelector(MODAL);
|
||||||
|
this.closeButton = this.mainNode.querySelector(CLOSE_BUTTON);
|
||||||
|
this.header = this.mainNode.querySelector(MODAL_HEADER);
|
||||||
|
this.content = this.mainNode.querySelector(MODAL_CONTENT);
|
||||||
|
this.footer = this.mainNode.querySelector(MODAL_FOOTER);
|
||||||
|
|
||||||
|
if (headerNode) {
|
||||||
|
this.header.appendChild(headerNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentNode) {
|
||||||
|
this.content.appendChild(contentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (footerNode) {
|
||||||
|
this.footer.appendChild(footerNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addEventListener(this.modal, EVENTS.CLICK, (event) => {
|
||||||
|
if (event.target === this.modal) {
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.addEventListener(this.closeButton, EVENTS.CLICK, this.hide);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Показывает модальное окно
|
||||||
|
*/
|
||||||
|
show = () => {
|
||||||
|
this.mainNode.classList.add(MODAL_SHOW);
|
||||||
|
this.next(EVENTS.TOGGLE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Прячет модальное окно
|
||||||
|
*/
|
||||||
|
hide = () => {
|
||||||
|
this.mainNode.classList.remove(MODAL_SHOW);
|
||||||
|
this.next(EVENTS.TOGGLE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Метод для подписки на изменение состояний модалки
|
||||||
|
* @param {ModalListener} listener - коллбек
|
||||||
|
*/
|
||||||
|
onChangeShow = (listener) => {
|
||||||
|
this.subscribe(EVENTS.TOGGLE, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Modal;
|
||||||
3
src/components/modal/index.js
Normal file
3
src/components/modal/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import Modal from './Modal';
|
||||||
|
|
||||||
|
export default Modal;
|
||||||
@ -40,7 +40,7 @@ class EmitService {
|
|||||||
* _.next('click', arg1, arg2, ..., argN);
|
* _.next('click', arg1, arg2, ..., argN);
|
||||||
*/
|
*/
|
||||||
next = (eventName, ...args) => {
|
next = (eventName, ...args) => {
|
||||||
const listeners = this._events[eventName];
|
const listeners = this._events[eventName] || [];
|
||||||
listeners.forEach((listener) => {
|
listeners.forEach((listener) => {
|
||||||
listener(...args);
|
listener(...args);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user