(function(F){ const D = F.dom; F.PopupWidget = function f(opt){ opt = F.mergeLastWins(f.defaultOptions,opt); this.options = opt; const e = this.e = D.addClass(D.div(), opt.cssClass, "fossil-PopupWidget"); this.show(false); if(opt.style){ let k; for(k in opt.style){ if(opt.style.hasOwnProperty(k)) e.style[k] = opt.style[k]; } } D.append(document.body, e); D.copyStyle(e, opt.style); if(opt.init){ opt.init.call(this); delete opt.init; } }; F.PopupWidget.defaultOptions = { cssClass: 'fossil-tooltip', style: undefined, adjustX: (x)=>x, adjustY: (y)=>y, refresh: function(){}, init: undefined }; F.PopupWidget.prototype = { isShown: function(){return !this.e.classList.contains('hidden')}, refresh: function(){ if(this.options.refresh){ this.options.refresh.call(this); } return this; }, show: function(){ var x = undefined, y = undefined, showIt, wasShown = !this.e.classList.contains('hidden'); if(2===arguments.length){ x = arguments[0]; y = arguments[1]; showIt = true; }else if(1===arguments.length){ if(arguments[0] instanceof HTMLElement){ const p = arguments[0]; const r = p.getBoundingClientRect(); x = r.x + r.x/5; y = r.y - r.height/2; showIt = true; }else{ showIt = !!arguments[0]; } } if(showIt){ if(!wasShown) this.refresh(); x = this.options.adjustX.call(this,x); y = this.options.adjustY.call(this,y); x += window.pageXOffset; y += window.pageYOffset; } if(showIt){ if('number'===typeof x && 'number'===typeof y){ this.e.style.left = x+"px"; this.e.style.top = y+"px"; } D.removeClass(this.e, 'hidden'); }else{ D.addClass(this.e, 'hidden'); this.e.style.removeProperty('left'); this.e.style.removeProperty('top'); } return this; }, hide: function(){return this.show(false)}, installHideHandlers: function f(onClickSelf, onClickOther, onEsc){ if(!arguments.length) onClickSelf = onClickOther = onEsc = true; else if(1===arguments.length) onClickOther = onEsc = true; else if(2===arguments.length) onEsc = true; if(onClickSelf) this.e.addEventListener('click', ()=>this.hide(), false); if(onClickOther) document.body.addEventListener('click', ()=>this.hide(), true); if(onEsc){ const self = this; document.body.addEventListener('keydown', function(ev){ if(self.isShown() && 27===ev.which) self.hide(); }, true); } return this; } }; const toastImpl = function f(cssClass, durationMult, argsObject){ if(!f.toaster){ f.toaster = new F.PopupWidget({ cssClass: 'fossil-toast-message' }); D.attr(f.toaster.e, 'role', 'alert'); } const T = f.toaster; if(f._timer) clearTimeout(f._timer); D.clearElement(T.e); if(f._prevCssClass) T.e.classList.remove(f._prevCssClass); if(cssClass) T.e.classList.add(cssClass); f._prevCssClass = cssClass; D.append(T.e, Array.prototype.slice.call(argsObject,0)); T.show(F.toast.config.position.x, F.toast.config.position.y); f._timer = setTimeout( ()=>T.hide(), F.toast.config.displayTimeMs * durationMult ); return F.toast; }; F.toast = { config: { position: { x: 5, y: 5 }, displayTimeMs: 3000 }, message: function(){ return toastImpl(false,1, arguments); }, warning: function(){ return toastImpl('warning',1.5,arguments); }, error: function(){ return toastImpl('error',2,arguments); } }; F.helpButtonlets = { setup: function f(){ if(!f.hasOwnProperty('clickHandler')){ f.clickHandler = function fch(ev){ ev.preventDefault(); ev.stopPropagation(); if(!fch.popup){ fch.popup = new F.PopupWidget({ cssClass: ['fossil-tooltip', 'help-buttonlet-content'], refresh: function(){ } }); fch.popup.e.style.maxWidth = '80%'; fch.popup.installHideHandlers(); } D.append(D.clearElement(fch.popup.e), ev.target.$helpContent); var popupRect, rectElem = ev.target; while(rectElem){ popupRect = rectElem.getClientRects()[0]; if(popupRect) break; rectElem = rectElem.parentNode; } if(!popupRect) popupRect = {x:0, y:0, left:0, right:0}; var x = popupRect.left, y = popupRect.top; if(x<0) x = 0; if(y<0) y = 0; if(rectElem){ const rz = window.getComputedStyle(rectElem).zIndex; var myZ; if(rz && !isNaN(+rz)){ myZ = +rz + 1; }else{ myZ = 10000; } fch.popup.e.style.zIndex = myZ; } fch.popup.show(x, y); x = popupRect.left, y = popupRect.top; popupRect = fch.popup.e.getBoundingClientRect(); const rectBody = document.body.getClientRects()[0]; if(popupRect.right > rectBody.right){ x -= (popupRect.right - rectBody.right); } if(x + popupRect.width > rectBody.right){ x = rectBody.x + (rectBody.width*0.1); fch.popup.e.style.minWidth = '70%'; }else{ fch.popup.e.style.removeProperty('min-width'); x -= popupRect.width/2; } if(x<0) x = 0; fch.popup.show(x, y); return false; }; f.foreachElement = function(e){ if(e.classList.contains('processed')) return; e.classList.add('processed'); e.$helpContent = []; e.childNodes.forEach((ch)=>e.$helpContent.push(ch)); e.$helpContent.forEach((ch)=>ch.remove()); e.addEventListener('click', f.clickHandler, false); }; } var elems; if(!arguments.length){ arguments[0] = '.help-buttonlet:not(.processed)'; arguments.length = 1; } if(arguments.length){ if('string'===typeof arguments[0]){ elems = document.querySelectorAll(arguments[0]); }else if(arguments[0] instanceof HTMLElement){ elems = [arguments[0]]; }else if(arguments[0].forEach){ elems = arguments[0]; } } if(elems) elems.forEach(f.foreachElement); }, create: function(elem){ D.addClass(elem, 'help-buttonlet'); if(arguments.length>1){ const args = Array.prototype.slice.call(arguments,1); D.append(elem, args); } this.setup(elem); return elem; } }; F.onDOMContentLoaded( ()=>F.helpButtonlets.setup() ); })(window.fossil);