UNPKG

jspanel4

Version:

A JavaScript library to create highly configurable multifunctional floating panels that can also be used as modal, tooltip, hint or contextmenu

157 lines (140 loc) 5.86 kB
/** * jsPanel - A JavaScript library to create highly configurable multifunctional floating panels that can also be used as modal, tooltip, hint or contextmenu * @version v4.16.1 * @homepage https://jspanel.de/ * @license MIT * @author Stefan Sträßer - info@jspanel.de * @author of dialog extension: Michael Daumling - michael@terrapinlogo.com * @github https://github.com/Flyer53/jsPanel4.git */ import {jsPanel} from '../../jspanel.js'; if (!jsPanel.contextmenu) { jsPanel.contextmenu = { version: '1.2.0', date: '2021-01-13 10:40', defaults: { //position: is set in jsPanel.contextmenu.create() //container: is set in jsPanel.contextmenu.create() dragit: false, resizeit: false, header: false, headerControls: 'none', closeOnMouseleave: true }, cmOverflow(elmt) { let cltX = elmt.cmEvent.clientX, cltY = elmt.cmEvent.clientY, panelW = elmt.offsetWidth, panelH = elmt.offsetHeight, corrLeft = window.innerWidth - (cltX + panelW), corrTop = window.innerHeight - (cltY + panelH); if (corrLeft < 0) { elmt.style.left = cltX + (window.scrollX || window.pageXOffset) - panelW + 'px'; } if (corrTop < 0) { elmt.style.top = cltY + (window.scrollY || window.pageYOffset) - panelH + 'px'; } }, create(options = {}, evt = 'contextmenu') { options.paneltype = 'contextmenu'; let target = options.target; if (!target) { return false; } if (typeof target === 'string') { target = document.querySelector(target); } target.addEventListener( evt, e => { e.preventDefault(); // close all contextmenus first document .querySelectorAll('.jsPanel-contextmenu') .forEach(item => { item.close(); }); let l = (e.pageX || e.touches[0].pageX) + 'px', t = (e.pageY || e.touches[0].pageY) + 'px', opts = options; if (options.config) { opts = Object.assign({}, options.config, options); delete opts.config; } opts = Object.assign({}, this.defaults, opts, { position: false, container: 'body' }); jsPanel.create(opts, cm => { jsPanel.setStyle(cm, { position: 'absolute', left: l, top: t }); // check whether contextmenu is triggered from within a modal panel or panel and if so update z-index let closestModal = target.closest('.jsPanel-modal'); if (closestModal) { cm.style.zIndex = closestModal.style.zIndex; } else { let closestPanel = target.closest('.jsPanel'); if (closestPanel) { closestPanel.front(); } cm.style.zIndex = jsPanel.zi.next(); } // save event object as property of cm outer div (needed in checkContextmenuOverflow()) cm.cmEvent = e; // update left/top values if menu overflows browser viewport jsPanel.contextmenu.cmOverflow(cm); if (opts.closeOnMouseleave) { cm.addEventListener( 'mouseleave', () => { cm.close(); }, false ); } // don't close contextmenu on mousedown in contextmenu jsPanel.pointerdown.forEach(function(evt) { cm.addEventListener(evt, function(e) { e.stopPropagation(); }); }); }); }, false ); } }; // add overflow check to jsPanel.contentAjax always callback jsPanel.ajaxAlwaysCallbacks.push(function(xhr, obj) { if (obj && obj.classList && obj.classList.contains('jsPanel-contextmenu')) { jsPanel.contextmenu.cmOverflow(obj); } }); // close tooltips on pointerdown in document jsPanel.pointerdown.forEach(function(evt) { document.addEventListener( evt, function(e) { document .querySelectorAll('.jsPanel-contextmenu') .forEach(function(item) { if (!e.target.closest('.jsPanel-contextmenu')) { item.close(); } }); }, false ); }); }