|
|
@@ -0,0 +1,851 @@
|
|
|
+var DBG = 0;
|
|
|
+var DBG1 = 1;
|
|
|
+
|
|
|
+// Multiple modal require global state with list of opened modal:
|
|
|
+// - open (example: btn: p5Modal.openModal(event, this))
|
|
|
+// - close (ESC key, 'x' btn, click on overlay behind modal, ?cancel btn)
|
|
|
+
|
|
|
+// - only one overlay - under top modal
|
|
|
+// - when top modal closed, and has other modal, then show overlay under next top modal
|
|
|
+
|
|
|
+function p5UI__openModal__TORM(event, targetNode, props) {
|
|
|
+ event.stopPropagation()
|
|
|
+ event.preventDefault()
|
|
|
+ var defaultProps = {
|
|
|
+ source: null, // node id or null
|
|
|
+ };
|
|
|
+ var props = props || defaultProps;
|
|
|
+
|
|
|
+ if (!targetNode) targetNode = event.target;
|
|
|
+
|
|
|
+ // https://dev.to/aleksandrhovhannisyan/multiple-modals-on-one-page-using-html-css-and-javascript-353b#4-closing-a-stacked-modal-with-the-escape-key
|
|
|
+
|
|
|
+ // IDEA: global p5Modal manager which generates unique ids and manage close and other actions
|
|
|
+ p5Modal.openModal(targetNode)
|
|
|
+
|
|
|
+ // var name = targetNode.getAttribute('data-name');
|
|
|
+ // if (!name) throw "Missing 'name' in sidebar panel button";
|
|
|
+
|
|
|
+ // var idHtmlNode = 'p5__js-p5-side_panel-' + name;
|
|
|
+
|
|
|
+ // var panelNode = document.getElementById(idHtmlNode)
|
|
|
+ // if (!panelNode) throw "Missing content node";
|
|
|
+
|
|
|
+ // // if (panelNode.parentNode !== document.body)
|
|
|
+
|
|
|
+ // DBG1 && console.log("DBG:p5UI__openModal__TORM", {
|
|
|
+ // targetNode,
|
|
|
+ // name,
|
|
|
+ // parent: panelNode.parentNode,
|
|
|
+ // parentDiffBody: (panelNode.parentNode !== document.body),
|
|
|
+ // });
|
|
|
+
|
|
|
+ // if (panelNode.parentNode !== document.body) { // mv at the end of body if not
|
|
|
+ // document.body.appendChild(panelNode)
|
|
|
+ // }
|
|
|
+ // if (!panelNode._p5_onClick) panelNode._p5_onClick = function (event) {
|
|
|
+ // // DBG1 && console.log("DBG:_p5_onClick", { self: this })
|
|
|
+ // if (hasClass(event.target, 'p5-side_panel--js-close') || hasId(event.target, idHtmlNode)) {
|
|
|
+ // event.preventDefault();
|
|
|
+ // // removeClass(panelNode, 'p5-side_panel--is-visible');
|
|
|
+ // _closeSidePanel(panelNode); // TODO: check use this, not panelNode
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // if (!panelNode._p5_onEsc) panelNode._p5_onEsc = function (event) {
|
|
|
+ // // DBG1 && console.log("DBG:_p5_onEsc", { self: this })
|
|
|
+ // if (event.keyCode == 27) {
|
|
|
+ // _closeSidePanel(panelNode); // TODO: check use this, not panelNode
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // p5-side_panel p5-side_panel--from-right js-p5-side_panel-main p5-side_panel--is-visible
|
|
|
+ // addClass(panelNode, 'p5-side_panel--from-right'); // TODO: from props: left | right
|
|
|
+ // if (hasClass(panelNode, 'p5-side_panel--is-visible')) {
|
|
|
+ // // removeClass(panelNode, 'p5-side_panel--is-visible');
|
|
|
+ // _closeSidePanel(panelNode);
|
|
|
+ // } else {
|
|
|
+ // setTimeout(function () {
|
|
|
+ // // addClass(panelNode, 'p5-side_panel--is-visible')
|
|
|
+ // _openSidePanel(panelNode)
|
|
|
+ // }, 10)
|
|
|
+ // }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// https://dev.to/aleksandrhovhannisyan/multiple-modals-on-one-page-using-html-css-and-javascript-353b#4-closing-a-stacked-modal-with-the-escape-key
|
|
|
+
|
|
|
+// IDEA: global p5Modal manager which generates unique ids and manage close and other actions (refresh page/widget, go to url, etc.)
|
|
|
+
|
|
|
+if (!global.p5Modal) { // TODO: mv to global file
|
|
|
+
|
|
|
+ global.p5Modal = (function () {
|
|
|
+ var _openedModal = []; // [ props, ... ]
|
|
|
+ var _actionAfterClose = []; // [ '' | 'reload-page' | 'reload-#id' | 'reload-.class' , ... ]
|
|
|
+ // fire every _actionAfterClose after close last modal
|
|
|
+ // - if 'reload-page' in _actionAfterClose then only reload page
|
|
|
+ // fill _actionAfterClose after every modal close
|
|
|
+
|
|
|
+ var _escKeyListener = null;
|
|
|
+ function _addEscKeyListener() {
|
|
|
+ DBG && console.log('DBG:p5Modal:_addEscKeyListener #1');
|
|
|
+ if (_escKeyListener) return;
|
|
|
+ DBG && console.log('DBG:p5Modal:_addEscKeyListener #2');
|
|
|
+
|
|
|
+ _escKeyListener = true;
|
|
|
+ document.addEventListener('keyup', _handleEscKey);
|
|
|
+ }
|
|
|
+ function _removeEscKeyListener() {
|
|
|
+ document.removeEventListener('keyup', _handleEscKey);
|
|
|
+ _escKeyListener = false;
|
|
|
+ }
|
|
|
+ function _handleEscKey(event) {
|
|
|
+ DBG && console.log('DBG:p5Modal:onkeyup:_handleEscKey', {
|
|
|
+ keyCode: event.keyCode,
|
|
|
+ code: event.code,
|
|
|
+ key: event.key,
|
|
|
+ _openedModal: _openedModal,
|
|
|
+ });
|
|
|
+ // if ("Escape" === event.key)
|
|
|
+ if (27 === event.keyCode) {
|
|
|
+ _closeLastOpenedModal();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ function _closeLastOpenedModal() {
|
|
|
+ if (!_openedModal.length) {
|
|
|
+ // TODO: remove key listener
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var lastModalProps = _openedModal.pop();
|
|
|
+ var lastModalId = _openedModal.length;
|
|
|
+ var lastModalNode = document.getElementById(_modalHtmlId(lastModalId));
|
|
|
+ DBG && console.log('DBG:p5Modal:_closeLastOpenedModal', {
|
|
|
+ _openedModal: _openedModal,
|
|
|
+ lastModalProps: lastModalProps,
|
|
|
+ lastModalId: lastModalId,
|
|
|
+ });
|
|
|
+
|
|
|
+ // TODO: check props - is close allowed?
|
|
|
+
|
|
|
+ if (lastModalNode) {
|
|
|
+ lastModalNode.parentNode.removeChild(lastModalNode);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!_openedModal.length) _removeEscKeyListener();
|
|
|
+ }
|
|
|
+
|
|
|
+ function _px(size) { return '' + size + 'px'; }
|
|
|
+ var style = {};
|
|
|
+ // { w: window.innerWidth, h: window.innerHeight }
|
|
|
+
|
|
|
+ style.baseModal = {};
|
|
|
+ style.baseModal.overlay = {
|
|
|
+ display: 'block',
|
|
|
+ position: 'fixed',
|
|
|
+ zIndex: 10,
|
|
|
+ left: 0,
|
|
|
+ top: 0,
|
|
|
+ width: '100%',
|
|
|
+ height: '100%',
|
|
|
+ overflow: 'auto',
|
|
|
+ backgroundColor: '#000',
|
|
|
+ backgroundColor: '#0009',
|
|
|
+ };
|
|
|
+ style.baseModal.content = {
|
|
|
+ boxSizing: 'border-box',
|
|
|
+ backgroundColor: '#fefefe',
|
|
|
+ padding: '24px 32px',
|
|
|
+ };
|
|
|
+ style.baseModal.title = {
|
|
|
+ boxSizing: 'border-box',
|
|
|
+ backgroundColor: '#fefefe',
|
|
|
+ margin: '0',
|
|
|
+ padding: '6px 12px',
|
|
|
+ borderBottom: '1px solid #ddd',
|
|
|
+ fontSize: '14px',
|
|
|
+ };
|
|
|
+ style.baseModal.body = {
|
|
|
+ boxSizing: 'border-box',
|
|
|
+ backgroundColor: '#fff',
|
|
|
+ margin: '0',
|
|
|
+ padding: '6px 12px',
|
|
|
+ fontSize: '14px',
|
|
|
+ lineHeight: '1.6em',
|
|
|
+ };
|
|
|
+ style.baseModal.footer = {
|
|
|
+ boxSizing: 'border-box',
|
|
|
+ backgroundColor: '#fefefe',
|
|
|
+ margin: '0',
|
|
|
+ padding: '6px 12px',
|
|
|
+ borderTop: '1px solid #ddd',
|
|
|
+ fontSize: '14px',
|
|
|
+ };
|
|
|
+
|
|
|
+ var sidePanelWidth = Math.round(window.innerWidth * 0.8); // "80%",
|
|
|
+ style.side_panel = Object.assign({}, style.baseModal, {
|
|
|
+ overlay: Object.assign({}, style.baseModal.overlay),
|
|
|
+ content: Object.assign({}, style.baseModal.content, {
|
|
|
+ marginLeft: 'auto',
|
|
|
+ width: _px(sidePanelWidth),
|
|
|
+ height: _px(window.innerHeight),
|
|
|
+ border: 'none',
|
|
|
+ padding: '0',
|
|
|
+ }),
|
|
|
+ title: Object.assign({}, style.baseModal.title, {
|
|
|
+ padding: '0 24px',
|
|
|
+ height: '40px',
|
|
|
+ lineHeight: '40px',
|
|
|
+ }),
|
|
|
+ body: Object.assign({}, style.baseModal.body, {
|
|
|
+ height: _px(window.innerHeight - 40 - 40),
|
|
|
+ overflow: 'auto', // TODO: only Y ?
|
|
|
+ padding: '12px 24px',
|
|
|
+ }),
|
|
|
+ footer: Object.assign({}, style.baseModal.footer, {
|
|
|
+ width: _px(sidePanelWidth),
|
|
|
+ padding: '0 24px',
|
|
|
+ height: '40px',
|
|
|
+ lineHeight: '40px',
|
|
|
+ }),
|
|
|
+ });
|
|
|
+
|
|
|
+ style.modal = Object.assign({}, style.baseModal, {
|
|
|
+ overlay: Object.assign({}, style.baseModal.overlay),
|
|
|
+ content: Object.assign({}, style.baseModal.content, {
|
|
|
+ marginTop: _px(Math.round(window.innerHeight * 0.1)),
|
|
|
+ marginBottom: _px(Math.round(window.innerHeight * 0.1)),
|
|
|
+ marginLeft: 'auto',
|
|
|
+ marginRight: 'auto',
|
|
|
+ width: '80%',
|
|
|
+ maxWidth: '800px',
|
|
|
+ border: '1px solid #888',
|
|
|
+ borderRadius: '8px',
|
|
|
+ }),
|
|
|
+ title: Object.assign({}, style.baseModal.title, {
|
|
|
+ padding: '0 12px 24px 12px',
|
|
|
+ fontSize: '18px',
|
|
|
+ lineHeight: '2em',
|
|
|
+ textAlign: 'center',
|
|
|
+ border: 'none',
|
|
|
+ }),
|
|
|
+ body: Object.assign({}, style.baseModal.body, {
|
|
|
+ textAlign: 'center',
|
|
|
+ border: 'none',
|
|
|
+ }),
|
|
|
+ footer: Object.assign({}, style.baseModal.footer, {
|
|
|
+ padding: '24px 12px 0 12px',
|
|
|
+ textAlign: 'center',
|
|
|
+ border: 'none',
|
|
|
+ }),
|
|
|
+ });
|
|
|
+
|
|
|
+ // TODO: if body scroll
|
|
|
+ style.alert = Object.assign({}, style.baseModal, {
|
|
|
+ overlay: Object.assign({}, style.baseModal.overlay),
|
|
|
+ content: Object.assign({}, style.baseModal.content, {
|
|
|
+ width: '60%',
|
|
|
+ maxWidth: '800px',
|
|
|
+ marginTop: _px(Math.round(window.innerHeight * 0.3)),
|
|
|
+ marginBottom: _px(Math.round(window.innerHeight * 0.3)),
|
|
|
+ marginLeft: 'auto',
|
|
|
+ marginRight: 'auto',
|
|
|
+ padding: '24px',
|
|
|
+ border: '1px solid #888',
|
|
|
+ borderRadius: '8px',
|
|
|
+ }),
|
|
|
+ title: Object.assign({}, style.baseModal.title, {
|
|
|
+ padding: '0 12px 24px 12px',
|
|
|
+ fontSize: '20px',
|
|
|
+ lineHeight: '2em',
|
|
|
+ textAlign: 'center',
|
|
|
+ border: 'none',
|
|
|
+ }),
|
|
|
+ body: Object.assign({}, style.baseModal.body, {
|
|
|
+ textAlign: 'center',
|
|
|
+ border: 'none',
|
|
|
+ }),
|
|
|
+ footer: Object.assign({}, style.baseModal.footer, {
|
|
|
+ padding: '24px 12px 0 12px',
|
|
|
+ textAlign: 'center',
|
|
|
+ border: 'none',
|
|
|
+ }),
|
|
|
+ });
|
|
|
+
|
|
|
+ style.dropdownUnder = Object.assign({}, style.baseModal, {
|
|
|
+ overlay: Object.assign({}, style.baseModal.overlay, {
|
|
|
+ // display: 'block',
|
|
|
+ position: 'absolute',
|
|
|
+ // zIndex: 10,
|
|
|
+ // left: 0,
|
|
|
+ // top: 0,
|
|
|
+ // { w: window.innerWidth, h: window.innerHeight }
|
|
|
+ width: '100%',
|
|
|
+ height: '100%',
|
|
|
+ // overflow: 'auto',
|
|
|
+ // backgroundColor: '#000',
|
|
|
+ backgroundColor: '#0003', // '#0009',
|
|
|
+ }),
|
|
|
+ content: Object.assign({}, style.baseModal.content, {
|
|
|
+ position: 'absolute',
|
|
|
+ // top, left: under targetNode (button)
|
|
|
+ // width: '60%',
|
|
|
+ // maxWidth: '800px',
|
|
|
+ padding: '8px 0',
|
|
|
+ border: '1px solid #ccc',
|
|
|
+ borderRadius: '8px',
|
|
|
+ boxShadow: '0 6px 12px rgba(0,0,0,.175)',
|
|
|
+ }),
|
|
|
+ title: Object.assign({}, style.baseModal.title, {
|
|
|
+ display: 'none',
|
|
|
+ }),
|
|
|
+ body: Object.assign({}, style.baseModal.body, {
|
|
|
+ padding: '0 12px',
|
|
|
+ textAlign: 'left',
|
|
|
+ border: 'none',
|
|
|
+ }),
|
|
|
+ footer: Object.assign({}, style.baseModal.footer, {
|
|
|
+ display: 'none',
|
|
|
+ }),
|
|
|
+ });
|
|
|
+
|
|
|
+ function _style(type) {
|
|
|
+ return (type in style) ? style[type] : style.baseModal;
|
|
|
+ }
|
|
|
+
|
|
|
+ function _getPropsFromAttr(node) {
|
|
|
+ // 'title' => V::get('title', '', $props),
|
|
|
+ // 'data-url' => V::get('href', '', $props),
|
|
|
+ // 'data-cancel' => V::get('cancel', '', $props),
|
|
|
+ // 'data-cancel-label' => V::get('cancel-label', '', $props),
|
|
|
+ // 'data-success-reload' => V::get('success-reload', '', $props),
|
|
|
+ var props = {};
|
|
|
+ if (node.hasAttribute('data-source')) props.source = node.getAttribute('data-source');
|
|
|
+ return props;
|
|
|
+ }
|
|
|
+
|
|
|
+ function _openModal(event, targetNode, props) {
|
|
|
+ event.stopPropagation();
|
|
|
+ event.preventDefault();
|
|
|
+ targetNode.blur(); // loose focus from element
|
|
|
+ var modal = _createModal('modal', targetNode || event.target, props || {});
|
|
|
+ _setModalContent('modal', modal);
|
|
|
+ document.body.appendChild(modal.overlay);
|
|
|
+ modal.content.focus(); // TODO: BUG hit Enter after open modal will open the same modal on top of last
|
|
|
+ }
|
|
|
+
|
|
|
+ function _openSidePanel(event, targetNode, props) {
|
|
|
+ event.stopPropagation();
|
|
|
+ event.preventDefault();
|
|
|
+ DBG && console.log('DBG:p5Modal:_openSidePanel:', { targetNode, props });
|
|
|
+ targetNode.blur(); // loose focus from element
|
|
|
+ var modal = _createModal('side_panel', targetNode || event.target, props || {});
|
|
|
+ _setModalContent('side_panel', modal, props || {}); // require props.body = function (modal)
|
|
|
+ document.body.appendChild(modal.overlay);
|
|
|
+ modal.content.focus(); // TODO: BUG hit Enter after open modal will open the same modal on top of last
|
|
|
+ }
|
|
|
+
|
|
|
+ function _openAlert(event, targetNode, props) {
|
|
|
+ event.stopPropagation();
|
|
|
+ event.preventDefault();
|
|
|
+ targetNode.blur(); // loose focus from element
|
|
|
+ var modal = _createModal('alert', targetNode || event.target, props || {});
|
|
|
+ _setModalContent('alert', modal);
|
|
|
+ document.body.appendChild(modal.overlay);
|
|
|
+ modal.content.focus(); // TODO: BUG hit Enter after open modal will open the same modal on top of last
|
|
|
+ }
|
|
|
+
|
|
|
+ function _openDropdownUnder(event, targetNode, props) {
|
|
|
+ event.stopPropagation();
|
|
|
+ event.preventDefault();
|
|
|
+
|
|
|
+ var props = ('function' === typeof props) ? props() : props;
|
|
|
+
|
|
|
+ var targetNode = targetNode || event.target;
|
|
|
+ var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
|
|
+ var h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
|
|
|
+ var rect = targetNode.getBoundingClientRect();
|
|
|
+ DBG && console.log('DBG:p5Modal:_openDropdownUnder:rect', { rect, w, h });
|
|
|
+ targetNode.blur();
|
|
|
+ if (event.target !== targetNode) event.target.blur();
|
|
|
+
|
|
|
+ var bodyNode = document.body;
|
|
|
+ var htmlNode = document.documentElement;
|
|
|
+ var height = Math.max(bodyNode.scrollHeight, bodyNode.offsetHeight, htmlNode.clientHeight, htmlNode.scrollHeight, htmlNode.offsetHeight);
|
|
|
+ DBG && console.log('DBG:p5Modal:_openDropdownUnder:rect', {
|
|
|
+ height,
|
|
|
+ 'bodyNode.scrollHeight': bodyNode.scrollHeight,
|
|
|
+ 'bodyNode.offsetHeight': bodyNode.offsetHeight,
|
|
|
+ 'htmlNode.clientHeight': htmlNode.clientHeight,
|
|
|
+ 'htmlNode.scrollHeight': htmlNode.scrollHeight,
|
|
|
+ 'htmlNode.offsetHeight': htmlNode.offsetHeight,
|
|
|
+ });
|
|
|
+
|
|
|
+ var modal = _createModal('dropdownUnder', targetNode, props);
|
|
|
+ _setModalContent('dropdownUnder', modal, props);
|
|
|
+
|
|
|
+ var posY = window.scrollY + rect.y + rect.height + 2;
|
|
|
+ modal.content.style.top = _px(posY);
|
|
|
+ modal.content.style.left = _px(rect.x);
|
|
|
+ modal.content.style.maxHeight = _px(height - posY);
|
|
|
+ modal.body.style.maxHeight = _px(height - posY - 8 - 8 - 20);
|
|
|
+ modal.body.style.overflowY = 'auto';
|
|
|
+ DBG && console.log('DBG:p5Modal:_openDropdownUnder:rect', { outerWidth: window.outerWidth, outerHeight: window.outerHeight, posY });
|
|
|
+
|
|
|
+ var _handleDropdownUnderClick = (function (nr) {
|
|
|
+ return function ___handleDropdownUnderClick() {
|
|
|
+ DBG && console.log('DBG:p5Modal:_handleDropdownUnderClick', { nr: nr });
|
|
|
+ _closeModalByNr(nr);
|
|
|
+ }
|
|
|
+ })(modal.nr)
|
|
|
+
|
|
|
+ modal.content.addEventListener('click', _handleDropdownUnderClick, false); // useCapture = false - trigger after inside node event callbacks
|
|
|
+ document.body.appendChild(modal.overlay);
|
|
|
+ modal.content.focus(); // TODO: BUG hit Enter after open modal will open the same modal on top of last
|
|
|
+
|
|
|
+ // https://dev.to/aleksandrhovhannisyan/multiple-modals-on-one-page-using-html-css-and-javascript-353b#4-closing-a-stacked-modal-with-the-escape-key
|
|
|
+
|
|
|
+ // IDEA: global p5Modal manager which generates unique ids and manage close and other actions
|
|
|
+ // 'data-url'
|
|
|
+ // glyphicon glyphicon-chevron-left - for cancel btn
|
|
|
+ // glyphicon glyphicon-chevron-right - for continue btn
|
|
|
+ }
|
|
|
+
|
|
|
+ function _setModalContent(type, modal, props) {
|
|
|
+ DBG && console.log('DBG:p5Modal:_setModalContent(', {type, modal, props}, ')');
|
|
|
+ if (!props.body) {
|
|
|
+ DBG && console.log('DBG:p5Modal:_setModalContent:props.body missing props.body!');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if ('function' === typeof props.body) {
|
|
|
+ DBG && console.log('DBG:p5Modal:_setModalContent:props.body ...');
|
|
|
+ props.body(modal);
|
|
|
+ } else if ('string' === typeof props.body) {
|
|
|
+ // TODO: clone node document.getElementById(props.body)
|
|
|
+ // or innerHTML ('#...')
|
|
|
+ // or ajax call ('http...') + loading... text or anim
|
|
|
+ // - callback to handle response (success, fail) and modify modal content
|
|
|
+ DBG && console.log('DBG:p5Modal:_setModalContent:props.body string ...');
|
|
|
+ } else {
|
|
|
+ DBG && console.log('DBG:p5Modal:_setModalContent:props.body not implemented props.body ...');
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === 'dropdownUnder') {
|
|
|
+ modal.body.appendChild(document.createTextNode('TODO: dropdownUnder Body ...')); // TODO: DBG
|
|
|
+ } else {
|
|
|
+ modal.header.appendChild(document.createTextNode('TODO: Title ...')); // TODO: DBG
|
|
|
+ for (var i = 0; i < 100; i++) {
|
|
|
+ modal.body.appendChild(document.createTextNode('TODO: Body ...')); // TODO: DBG
|
|
|
+ modal.body.appendChild(document.createElement('br')); // TODO: DBG
|
|
|
+ }
|
|
|
+ modal.footer.appendChild(document.createTextNode('TODO: Footer ...')); // TODO: DBG
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function _createModal(type, targetNode, props) {
|
|
|
+ _addEscKeyListener();
|
|
|
+ var defaultProps = {
|
|
|
+ // type: 'modal', // modal | sidePanel | alert
|
|
|
+ source: null, // node id | url | js function | null
|
|
|
+ };
|
|
|
+ var attrProps = _getPropsFromAttr(targetNode);
|
|
|
+ var props = Object.assign(defaultProps, attrProps, props || {});
|
|
|
+ props.type = type;
|
|
|
+ DBG && console.log('DBG:p5Modal:openModal:' + props.type + ':', { targetNode, props });
|
|
|
+
|
|
|
+ // add to _openedModal
|
|
|
+ // get _openedModal to set id attribute on overlay node
|
|
|
+ var modal = {
|
|
|
+ nr: _insertModal(props),
|
|
|
+ overlay: document.createElement('div'),
|
|
|
+ content: document.createElement('div'),
|
|
|
+ header: document.createElement('div'),
|
|
|
+ body: document.createElement('div'),
|
|
|
+ footer: document.createElement('div'),
|
|
|
+ };
|
|
|
+ {
|
|
|
+ modal.overlay.setAttribute('id', _modalHtmlId(modal.nr));
|
|
|
+ _addStyle(modal.overlay, props.type, 'overlay', props);
|
|
|
+ jQuery(modal.overlay).on('click', _makeCloseModal(modal.nr));
|
|
|
+
|
|
|
+ {
|
|
|
+ modal.content.setAttribute('id', _modalContentHtmlId(modal.nr));
|
|
|
+ _addStyle(modal.content, props.type, 'content', props);
|
|
|
+ jQuery(modal.content).on('click', function (event) {
|
|
|
+ event.stopPropagation();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ modal.overlay.appendChild(modal.content);
|
|
|
+
|
|
|
+ {
|
|
|
+ modal.header.setAttribute('id', _modalTitleHtmlId(modal.nr));
|
|
|
+ _addStyle(modal.header, props.type, 'title', props);
|
|
|
+ }
|
|
|
+ modal.content.appendChild(modal.header);
|
|
|
+
|
|
|
+ {
|
|
|
+ modal.body.setAttribute('id', _modalBodyHtmlId(modal.nr));
|
|
|
+ _addStyle(modal.body, props.type, 'body', props);
|
|
|
+ }
|
|
|
+ modal.content.appendChild(modal.body);
|
|
|
+
|
|
|
+ {
|
|
|
+ modal.footer.setAttribute('id', _modalFooterHtmlId(modal.nr));
|
|
|
+ _addStyle(modal.footer, props.type, 'footer', props);
|
|
|
+ }
|
|
|
+ modal.content.appendChild(modal.footer);
|
|
|
+ }
|
|
|
+ return modal;
|
|
|
+ }
|
|
|
+
|
|
|
+ function _insertModal(props) {
|
|
|
+ _openedModal.push(props);
|
|
|
+ return _openedModal.length - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ function _modalHtmlId(nr) { return 'p5-modal-' + nr; }
|
|
|
+ function _modalContentHtmlId(nr) { return 'p5-modal-' + nr + '--content'; }
|
|
|
+ function _modalTitleHtmlId(nr) { return 'p5-modal-' + nr + '--title'; }
|
|
|
+ function _modalBodyHtmlId(nr) { return 'p5-modal-' + nr + '--body'; }
|
|
|
+ function _modalFooterHtmlId(nr) { return 'p5-modal-' + nr + '--footer'; }
|
|
|
+
|
|
|
+ function _closeModalByNr(nr) {
|
|
|
+ // TODO: validate if nr is last
|
|
|
+
|
|
|
+ if (!_openedModal.length) {
|
|
|
+ DBG && console.log('DBG:p5Modal:_closeModalByNr: empty _openedModal');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (nr != _openedModal.length - 1) {
|
|
|
+ DBG && console.log('DBG:p5Modal:_closeModalByNr: modal nr(' + nr + ') is not last _openedModal');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ _closeLastOpenedModal();
|
|
|
+
|
|
|
+ // var idHtml = _modalHtmlId(nr);
|
|
|
+ // // TODO: validte if may close - read props
|
|
|
+ // // - if not -> blink to get user focus
|
|
|
+ // var modalNode = document.getElementById(idHtml);
|
|
|
+ // if (!modalNode) DBG && console.log('DBG:p5Modal:BUG: missing modal node in html tree!');
|
|
|
+ // if (modalNode) document.body.removeChild(modalNode);
|
|
|
+ }
|
|
|
+
|
|
|
+ function _makeCloseModal(nr) {
|
|
|
+ return function __closeModalByNr(event) {
|
|
|
+ _closeModalByNr(nr);
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ function _addStyle(node, type, nodeName, props) {
|
|
|
+
|
|
|
+ if (type === 'dropdownUnder') {
|
|
|
+ node.className += 'p5-dropdown--' + nodeName;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var style = _style(type)[nodeName];
|
|
|
+
|
|
|
+ for (name in style) {
|
|
|
+ node.style[name] = style[name];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ getTotal: function () { return _openedModal.length; },
|
|
|
+ openModal: _openModal,
|
|
|
+ openSidePanel: _openSidePanel,
|
|
|
+ openAlert: _openAlert,
|
|
|
+ openDropdownUnder: _openDropdownUnder,
|
|
|
+ closeLast: _closeLastOpenedModal,
|
|
|
+ };
|
|
|
+ })();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+global.p5Modal__sidePanel_from_ButtonPost = function __p5Modal__sidePanel_from_ButtonPost(event, node) {
|
|
|
+ DBG && console.log('DBG:p5Modal__sidePanel_from_ButtonPost', { event, node })
|
|
|
+ event.stopPropagation();
|
|
|
+ event.preventDefault();
|
|
|
+ if (!node.form) {
|
|
|
+ DBG && console.log('DBG:p5Modal__sidePanel_from_ButtonPost -> !node.form -> return');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ DBG && console.log('DBG:p5Modal__sidePanel_from_ButtonPost: form', { form: node.form, elements: node.form.elements });
|
|
|
+ // node.form.method: "post"
|
|
|
+ // node.form.action: "https://biuro.biall.com.pl/dev-pl/se-rsync/index.php?id_order=3324&_route=UrlAction_KioskPanel"
|
|
|
+ // node.form.elements: HTMLFormControlsCollection(3)
|
|
|
+ // - 0: input
|
|
|
+ // - 1: input
|
|
|
+ // - 2: button.btn.btn.btn-default.btn-xs
|
|
|
+
|
|
|
+ var actionURL = node.form.action;
|
|
|
+ var values = {};
|
|
|
+ for (var idx = 0; idx < node.form.elements.length; idx++) {
|
|
|
+ var el = node.form.elements[idx];
|
|
|
+ var name = el.name;
|
|
|
+ if (name) {
|
|
|
+ values[name] = node.form[name].value;
|
|
|
+ }
|
|
|
+ DBG && console.log('DBG:p5Modal__sidePanel_from_ButtonPost: form.elements['+idx+']', { name, value: el.value, el });
|
|
|
+ }
|
|
|
+ // form.elements[0] {name: "_postTask", value: "printLogs", el: input}
|
|
|
+ // form.elements[1] {name: "id_order", value: "10", el: input}
|
|
|
+ // form.elements[2] {name: "", value: "", el: button.btn.btn.btn-default.btn-xs}
|
|
|
+
|
|
|
+ DBG && console.log('DBG:p5Modal__sidePanel_from_ButtonPost: values', { values, actionURL });
|
|
|
+
|
|
|
+ // '_postTask' -> '_modalAction' or just add _doModalAction=1 to form.action URL
|
|
|
+ if ('_postTask' in values) {
|
|
|
+ values['_modalAction'] = values['_postTask'];
|
|
|
+ delete values['_postTask'];
|
|
|
+ }
|
|
|
+
|
|
|
+ function _initFetchSidePanelContent(modal) {
|
|
|
+ DBG && console.log('DBG:p5Modal__sidePanel_from_ButtonPost: _initFetchSidePanelContent', { modal, values, actionURL });
|
|
|
+ var formData = new FormData();
|
|
|
+ for (var key in values) {
|
|
|
+ formData.append(key, values[key]);
|
|
|
+ }
|
|
|
+
|
|
|
+ global.fetch(actionURL
|
|
|
+ , (!values)
|
|
|
+ ? { method: 'GET',
|
|
|
+ // headers: { 'Content-Type': 'application/json' },
|
|
|
+ credentials: 'same-origin',
|
|
|
+ }
|
|
|
+ : { method: 'POST',
|
|
|
+ // headers: { 'Content-Type': 'application/json' },
|
|
|
+ credentials: 'same-origin',
|
|
|
+ body: formData
|
|
|
+ }
|
|
|
+ ).then(function (response) {
|
|
|
+ return response.json()
|
|
|
+ }).then(function (response) {
|
|
|
+ DBG && console.log('DBG:p5Modal__sidePanel_from_ButtonPost: _initFetchSidePanelContent -> response', { response, modal, values, actionURL });
|
|
|
+ if (!response) {
|
|
|
+ p5UI__buildDom([ 'div', { className: 'alert alert-danger' }, 'Error: empty response' ], modal.body);
|
|
|
+ } else if ('error' === response.type) {
|
|
|
+ p5UI__buildDom([ 'div', { className: 'alert alert-danger' }, response.msg || 'Error: empty response' ], modal.body);
|
|
|
+ } else if (response.body && response.body.modalBodyReactNode) {
|
|
|
+ p5UI__buildDom(response.body.modalBodyReactNode, modal.body);
|
|
|
+ if (response.body.modalHeaderReactNode) {
|
|
|
+ p5UI__buildDom(response.body.modalHeaderReactNode, modal.header);
|
|
|
+ } else {
|
|
|
+ // TODO: btn 'x'
|
|
|
+ }
|
|
|
+ if (response.body.modalFooterReactNode) {
|
|
|
+ p5UI__buildDom(response.body.modalFooterReactNode, modal.footer);
|
|
|
+ } else {
|
|
|
+ // TODO: modal.footer ?
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ p5UI__buildDom([ 'div', { className: 'alert alert-danger' }, 'Error' ], modal.body);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return p5Modal.openSidePanel(event, node, props = {
|
|
|
+ body: _initFetchSidePanelContent,
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+function _openSidePanel(panelNode) {
|
|
|
+ addClass(panelNode, 'p5-side_panel--is-visible');
|
|
|
+ document.addEventListener('keyup', panelNode._p5_onEsc);
|
|
|
+ panelNode.addEventListener('click', panelNode._p5_onClick);
|
|
|
+ // fix content scrollTop
|
|
|
+ var contentNode = panelNode.getElementsByClassName('p5-side_panel__content')
|
|
|
+ if (contentNode && contentNode[0]) {
|
|
|
+ contentNode[0].scrollTop = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function _closeSidePanel(panelNode) {
|
|
|
+ removeClass(panelNode, 'p5-side_panel--is-visible');
|
|
|
+ document.removeEventListener('keyup', panelNode._p5_onEsc)
|
|
|
+ panelNode.removeEventListener('click', panelNode._p5_onClick);
|
|
|
+}
|
|
|
+
|
|
|
+function hasId(el, id) {
|
|
|
+ return (id === el.getAttribute('id'));
|
|
|
+}
|
|
|
+//class manipulations - needed if classList is not supported
|
|
|
+//https://jaketrent.com/post/addremove-classes-raw-javascript/
|
|
|
+function hasClass(el, className) {
|
|
|
+ if (el.classList) return el.classList.contains(className);
|
|
|
+ else return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
|
|
|
+}
|
|
|
+
|
|
|
+function addClass(el, className) {
|
|
|
+ if (el.classList) el.classList.add(className);
|
|
|
+ else if (!hasClass(el, className)) el.className += ' ' + className;
|
|
|
+}
|
|
|
+
|
|
|
+function removeClass(el, className) {
|
|
|
+ if (el.classList) el.classList.remove(className);
|
|
|
+ else if (hasClass(el, className)) {
|
|
|
+ var reg = new RegExp('(\\s|^)' + className + '(\\s|$)');
|
|
|
+ el.className = el.className.replace(reg, ' ');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// module.exports['p5UI__openModal__TORM'] = p5UI__openModal__TORM;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// --------------
|
|
|
+
|
|
|
+function __buyIndeksAjax(ind, url) {
|
|
|
+ var n = document.getElementById('basket__' + ind + '_buy_input'),
|
|
|
+ wrap = document.getElementById('basket__' + ind),
|
|
|
+ val = n.value;
|
|
|
+ if (!n || !wrap) return true;
|
|
|
+
|
|
|
+ var tmpNodes = uslugiNode.getElementsByClassName('buy__info__' + ind)
|
|
|
+ var indeksInfoNode = tmpNodes ? tmpNodes[0] : null;
|
|
|
+ var tmpNodes = uslugiNode.getElementsByClassName('buy__noservice__' + ind)
|
|
|
+ var noServiceNode = tmpNodes ? tmpNodes[0] : null;
|
|
|
+ var serviceNodes = uslugiNode.getElementsByClassName('buy__usluga__' + ind)
|
|
|
+ var totalServiceNodes = serviceNodes.length;
|
|
|
+ if (!totalServiceNodes || !indeksInfoNode || !noServiceNode) {
|
|
|
+ return __buyIndeksAjax_simple(ind, url);
|
|
|
+ }
|
|
|
+
|
|
|
+ var buyModal = document.getElementById('modal__buy');
|
|
|
+ if (buyModal) document.body.removeChild(buyModal);
|
|
|
+ buyModal = document.createElement("div");
|
|
|
+ buyModal.setAttribute('id', 'modal__buy');
|
|
|
+ buyModal.style.display = "block";
|
|
|
+ buyModal.style.position = "fixed";
|
|
|
+ buyModal.style.zIndex = 1;
|
|
|
+ buyModal.style.left = 0;
|
|
|
+ buyModal.style.top = 0;
|
|
|
+ buyModal.style.width = "100%";
|
|
|
+ buyModal.style.height = "100%";
|
|
|
+ buyModal.style.overflow = "auto";
|
|
|
+ buyModal.style.backgroundColor = "#000";
|
|
|
+ buyModal.style.backgroundColor = "#0009";
|
|
|
+ jQuery(buyModal).on('click', __closeBuyIdneksModal)
|
|
|
+
|
|
|
+ var content = document.createElement("div");
|
|
|
+ content.style.backgroundColor = "#fefefe"
|
|
|
+ content.style.margin = "15% auto"
|
|
|
+ content.style.padding = "24px 32px"
|
|
|
+ content.style.border = "1px solid #888"
|
|
|
+ content.style.width = "80%"
|
|
|
+ content.style.maxWidth = "800px"
|
|
|
+ content.style.textAlign = "left"
|
|
|
+ content.style.fontSize = "14px"
|
|
|
+ jQuery(content).on('click', function (event) {
|
|
|
+ event.stopPropagation();
|
|
|
+ })
|
|
|
+
|
|
|
+ var nodeH3 = document.createElement("h3");
|
|
|
+ nodeH3.style.fontSize = "18px";
|
|
|
+ nodeH3.style.lineHeight = "1.6em";
|
|
|
+ nodeH3.style.marginBottom = "16px";
|
|
|
+ nodeH3.appendChild(document.createTextNode("Wybierz dodatkowe us�ugi:"));
|
|
|
+
|
|
|
+ var nodeInfo = document.createElement("div");
|
|
|
+ nodeInfo.style.marginBottom = "24px";
|
|
|
+ nodeInfo.appendChild(indeksInfoNode.cloneNode(true));
|
|
|
+
|
|
|
+ var nodeTable = document.createElement("table");
|
|
|
+ nodeTable.setAttribute('cellspacing', '0')
|
|
|
+ nodeTable.setAttribute('cellpadding', '0')
|
|
|
+ nodeTable.style.borderCollapse = "collapse";
|
|
|
+ nodeTable.style.width = "100%";
|
|
|
+ var nodeTr, nodeTd, nodeTdSelect;
|
|
|
+ for (var i = 0; i < totalServiceNodes; i++) {
|
|
|
+ idService = serviceNodes[i].getAttribute('data-service')
|
|
|
+ if (!idService) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ nodeTr = document.createElement("tr"); {
|
|
|
+ nodeTd = document.createElement("td");
|
|
|
+ nodeTd.style.padding = "24px";
|
|
|
+ nodeTd.style.border = "1px solid #ddd";
|
|
|
+ nodeTd.appendChild(serviceNodes[i].cloneNode(true));
|
|
|
+ }
|
|
|
+ nodeTr.appendChild(nodeTd); {
|
|
|
+ nodeTdSelect = document.createElement("td");
|
|
|
+ nodeTdSelect.style.padding = "24px";
|
|
|
+ nodeTdSelect.style.border = "1px solid #ddd";
|
|
|
+ nodeTdSelect.style.textAlign = "center";
|
|
|
+ var selectBtn = __createBuyWithServiceAjaxBtn(ind, idService, url);
|
|
|
+ nodeTdSelect.appendChild(selectBtn);
|
|
|
+ }
|
|
|
+ nodeTr.appendChild(nodeTdSelect);
|
|
|
+ }
|
|
|
+ nodeTable.appendChild(nodeTr);
|
|
|
+
|
|
|
+ { // no service
|
|
|
+ nodeTr = document.createElement("tr"); {
|
|
|
+ nodeTd = document.createElement("td");
|
|
|
+ nodeTd.style.padding = "24px";
|
|
|
+ nodeTd.style.border = "1px solid #ddd";
|
|
|
+ nodeTd.style.color = "#666";
|
|
|
+ nodeTd.appendChild(noServiceNode.cloneNode(true));
|
|
|
+ }
|
|
|
+ nodeTr.appendChild(nodeTd); {
|
|
|
+ nodeTdSelect = document.createElement("td");
|
|
|
+ nodeTdSelect.style.padding = "24px";
|
|
|
+ nodeTdSelect.style.border = "1px solid #ddd";
|
|
|
+ nodeTdSelect.style.textAlign = "center";
|
|
|
+ var selectBtn = __createSimpleBuyAjaxBtn(ind, url);
|
|
|
+ nodeTdSelect.appendChild(selectBtn);
|
|
|
+ }
|
|
|
+ nodeTr.appendChild(nodeTdSelect);
|
|
|
+ }
|
|
|
+ nodeTable.appendChild(nodeTr);
|
|
|
+
|
|
|
+ content.appendChild(nodeH3);
|
|
|
+ content.appendChild(nodeInfo);
|
|
|
+ content.appendChild(nodeTable);
|
|
|
+ buyModal.appendChild(content);
|
|
|
+ document.body.appendChild(buyModal);
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+function __createSimpleBuyAjaxBtn(ind, url) {
|
|
|
+ var nodeBtn = document.createElement("a");
|
|
|
+ nodeBtn.setAttribute('href', url + 'buy,' + ind + '.html')
|
|
|
+ nodeBtn.setAttribute('onclick', "return __buyIndeksAjax_simpleCloseModal('" + ind + "', '" + url + "');")
|
|
|
+ nodeBtn.setAttribute('class', "btn-shop")
|
|
|
+ nodeBtn.style.padding = "6px 16px";
|
|
|
+ nodeBtn.appendChild(document.createTextNode("Wybieram"));
|
|
|
+ return nodeBtn;
|
|
|
+}
|
|
|
+
|
|
|
+function __createBuyWithServiceAjaxBtn(ind, service, url) {
|
|
|
+ var nodeBtn = document.createElement("a");
|
|
|
+ nodeBtn.setAttribute('href', url + 'buy,' + ind + '.html')
|
|
|
+ nodeBtn.setAttribute('onclick', "return __buyIndeksAjax_withService('" + ind + "', '" + service + "', '" + url + "');")
|
|
|
+ nodeBtn.setAttribute('class', "btn-shop")
|
|
|
+ nodeBtn.style.padding = "6px 16px";
|
|
|
+ nodeBtn.appendChild(document.createTextNode("Wybieram"));
|
|
|
+ return nodeBtn;
|
|
|
+}
|
|
|
+
|
|
|
+function __buyIndeksAjax_simpleCloseModal(ind, url) {
|
|
|
+ __closeBuyIdneksModal();
|
|
|
+ __buyIndeksAjax_simple(ind, url);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+function __closeBuyIdneksModal() {
|
|
|
+ var buyModal = document.getElementById('modal__buy');
|
|
|
+ if (buyModal) document.body.removeChild(buyModal);
|
|
|
+}
|