hotline.mjs/hotline.min.mjs

20 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";/**
* @name hotline.mjs
*
* @description
* Module for creating "hot lines"
*
* @class
* @public
*
* @example
* сonst instance = new hotline(shell);
* instance.step = '-5';
* instance.start();
*
* {@link https://git.mirzaev.sexy/mirzaev/hotline.mjs}
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
export class hotline{#e;#t={};#s={};#n=null;#i=null;interval=10;alive=!0;#l=!1;#r="false";get moving(){return this.#r}movable=!0;wheel=!1;delta=30;button=0;hover=!0;step=1;transfer=!0;#o=!0;sticky=!1;#a=Object.freeze({beginning:Symbol("beginning"),center:Symbol("center"),end:Symbol("end")});get magnetism(){return this.#a}magnetic=null;magnet=1;vertical=!1;observe=!1;#h=null;events=new Map([["ready",!1],["started",!1],["stopped",!1],["configured",!1],["move",!1],["move.mouse",!1],["move.touch",!1],["move.freezed",!1],["move.unfreezed",!1],["moved.forward",!1],["moved.backward",!1],["offset",!1],["transfer.beginning",!0],["transfer.end",!0],["observer.started",!1],["observer.stopped",!1]]);#m=new Set(["events"]);#v=new Map;constructor(e,t=!1){e instanceof HTMLElement&&(this.#e=e,t&&(this.#e.hotline=this),this.#e.childElementCount>1&&(this.#n="ready",this.events.get("ready")&&this.#e.dispatchEvent(new CustomEvent("hotline.ready"))))}start(){if(null===this.#i){const e=this;this.#i=setInterval((()=>{e.#t.element=e.#e.firstElementChild,e.#t.rectangle=e.#t.element.getBoundingClientRect(),e.vertical?(e.#t.position=parseFloat(e.#t.element.style.marginTop)||0,e.#t.offset=parseFloat(getComputedStyle(e.#t.element).marginBottom)||0,e.#t.end=e.#t.rectangle.y+e.#t.rectangle.height+e.#t.offset):(e.#t.position=parseFloat(e.#t.element.style.marginLeft)||0,e.#t.offset=parseFloat(getComputedStyle(e.#t.element).marginRight)||0,e.#t.end=e.#t.rectangle.x+e.#t.rectangle.width+e.#t.offset),e.vertical&&Math.round(e.#t.end)<e.#e.offsetTop||!e.vertical&&Math.round(e.#t.end)<e.#e.offsetLeft?!0===e.transfer&&e.#o&&(e.#e.appendChild(e.#t.element),e.vertical?(e.#t.element.style.marginTop=null,e.events.get("transfer.end")&&e.#e.dispatchEvent(new CustomEvent("hotline.transfer.end",{detail:{element:e.#t.element,offset:-(e.#t.rectangle.height+e.#t.offset)}})),e.#t={}):(e.#t.element.style.marginLeft=null,e.events.get("transfer.end")&&e.#e.dispatchEvent(new CustomEvent("hotline.transfer.end",{detail:{element:e.#t.element,offset:-(e.#t.rectangle.width+e.#t.offset)}})),e.#t={})):e.vertical&&Math.round(e.#t.rectangle.y)>e.#e.offsetTop||!e.vertical&&Math.round(e.#t.rectangle.x)>e.#e.offsetLeft?!0===e.transfer&&e.#o&&(e.#s.element=e.#e.lastElementChild,e.#s.rectangle=e.#s.element.getBoundingClientRect(),e.#e.insertBefore(e.#s.element,e.#t.element),e.vertical?(e.#s.offset=parseFloat(getComputedStyle(e.#s.element).marginBottom)||e.#t.offset||0,e.events.get("transfer.beginning")&&e.#e.dispatchEvent(new CustomEvent("hotline.transfer.beginning",{detail:{element:e.#s.element,offset:e.#s.rectangle.height+e.#s.offset}})),e.#s.element.style.marginTop=-e.#s.rectangle.height-e.#s.offset+"px",e.#t.element.style.marginTop=null,e.#t={}):(e.#s.offset=parseFloat(getComputedStyle(e.#s.element).marginRight)||e.#t.offset||0,e.events.get("transfer.beginning")&&e.#e.dispatchEvent(new CustomEvent("hotline.transfer.beginning",{detail:{element:e.#s.element,offset:e.#s.rectangle.width+e.#s.offset}})),e.#s.element.style.marginLeft=-e.#s.rectangle.width-e.#s.offset+"px",e.#t.element.style.marginLeft=null,e.#t={})):!0===this.alive&&!1===this.#l&&e.move()}),e.interval),this.hover?(this.#v.set("hover",(t=>{e.#l=!0,e.events.get("moving.freezed")&&e.#e.dispatchEvent(new CustomEvent("hotline.moving.freezed",{detail:{event:t}}))})),this.#e.addEventListener("mouseover",this.#v.get("hover"))):(this.#e.removeEventListener("mouseover",this.#v.get("hover")),this.#v.delete("hover")),this.wheel?(this.#v.set("wheel",(t=>{"started"===e.#n&&e.position((parseFloat(e.#e.firstElementChild.style[e.vertical?"marginTop":"marginLeft"])||0)+(null===e.delta?t.wheelDelta:t.wheelDelta>0?e.delta:-e.delta))})),this.#e.addEventListener("wheel",this.#v.get("wheel"))):(this.#e.removeEventListener("wheel",this.#v.get("wheel")),this.#v.delete("wheel"));let t=0;const s=function(e){t+=e.detail.offset??0};e.movable?(e.#v.set("move.start",(n=>{if("touchstart"===n.type||n.button===e.button){e.#l=!0,e.events.get("moving.freezed")&&e.#e.dispatchEvent(new CustomEvent("hotline.moving.freezed",{detail:{event:n}}));const i=n.pageX||n.touches&&n.touches[0]?.pageX||0,l=n.pageY||n.touches&&n.touches[0]?.pageY||0;e.#e.addEventListener("hotline.transfer.beginning",s),e.#e.addEventListener("hotline.transfer.end",s);const r=e.#t.position;e.#v.set("moving",(s=>{if("started"===e.#n){if(e.#r=!0,e.vertical){const n=s.pageY||s.touches&&s.touches[0].pageY||0;e.position(n-(l+t-r))}else{const n=s.pageX||s.touches&&s.touches[0].pageX||0;e.position(n-(i+t-r))}"mousemove"===s.type?e.events.get("move.mouse")&&e.#e.dispatchEvent(new CustomEvent("hotline.move.mouse",{detail:{from:r,to:e.#t.position}})):"touchmove"===s.type&&e.events.get("move.touch")&&e.#e.dispatchEvent(new CustomEvent("hotline.move.touch",{detail:{from:r,to:e.#t.position}}))}})),document.addEventListener("mousemove",e.#v.get("moving")),document.addEventListener("touchmove",e.#v.get("moving"))}})),e.#e.addEventListener("mousedown",e.#v.get("move.start")),e.#e.addEventListener("touchstart",e.#v.get("move.start")),e.#v.set("move.leaved",(()=>{document.removeEventListener("mousemove",e.#v.get("moving")),e.#v.delete("moving"),document.removeEventListener("mouseleave",e.#v.get("move.leaved"))})),document.addEventListener("mouseleave",e.#v.get("move.leaved")),e.#v.set("move.end",(n=>{if(e.#r=!1,document.removeEventListener("mousemove",e.#v.get("moving")),document.removeEventListener("touchmove",e.#v.get("moving")),e.#v.delete("moving"),t=0,e.#e.removeEventListener("hotline.transfer.beginning",s),e.#e.removeEventListener("hotline.transfer.end",s),!1===e.hover&&e.#e.contains(n.target)||(e.#l=!1,e.events.get("move.unfreezed")&&e.#e.dispatchEvent(new CustomEvent("hotline.move.unfreezed"))),null!==e.magnetic)if(n.target===e.#e);else{let t=n.target,s=100;for(;t.parentElement!==e.#e&&0!=--s;)t=t.parentElement;t instanceof HTMLElement&&t.parentElement===e.#e&&e.magnetize(t,e.magnetic)}})),e.#e.addEventListener("mouseup",e.#v.get("move.end")),e.#e.addEventListener("touchend",e.#v.get("move.end")),e.#v.set("move.leave",(n=>{t=0,!1===e.sticky&&(e.#r=!1,document.removeEventListener("mousemove",e.#v.get("moving")),document.removeEventListener("touchmove",e.#v.get("moving")),e.#v.delete("moving"),e.#e.removeEventListener("hotline.transfer.beginning",s),e.#e.removeEventListener("hotline.transfer.end",s)),e.#l=!1,e.events.get("move.unfreezed")&&e.#e.dispatchEvent(new CustomEvent("hotline.move.unfreezed"))})),e.#e.addEventListener("mouseleave",e.#v.get("move.leave"))):(e.#e.removeEventListener("mousedown",e.#v.get("move.start")),e.#e.removeEventListener("touchstart",e.#v.get("move.start")),e.#v.delete("move.start"),e.#r=!1,document.removeEventListener("mousemove",e.#v.get("moving")),document.removeEventListener("touchmove",e.#v.get("moving")),e.#v.delete("moving"),t=0,e.#e.removeEventListener("mouseup",e.#v.get("move.end")),e.#e.removeEventListener("touchend",e.#v.get("move.end")),e.#v.delete("move.end"),e.#e.addEventListener("mouseleave",e.#v.get("move.leave")),e.#v.delete("move.leave")),this.#n="started",e.events.get("started")&&this.#e.dispatchEvent(new CustomEvent("hotline.started"))}this.observe?null===this.#h&&(this.#h=new MutationObserver((function(e){for(const t of e)"attributes"===t.type&&this.configure(t.attributeName);this.restart()})),this.#h.observe(this.#e,{attributes:!0}),this.events.get("observer.started")&&this.#e.dispatchEvent(new CustomEvent("hotline.observer.started",{detail:{instance:this.#h}}))):this.#h instanceof MutationObserver&&(this.#h.disconnect(),this.#h=null,this.events.get("observer.stopped")&&this.#e.dispatchEvent(new CustomEvent("hotline.observer.stopped")))}stop(){clearInterval(this.#i),this.#i=null,this.#n="stopped",this.events.get("stopped")&&this.#e.dispatchEvent(new CustomEvent("hotline.stopped"))}restart(){this.stop(),this.start()}configure(e){const t=(/^data-hotline-(\w+)$/.exec(e)??[,null])[1];if("string"==typeof t){if(this.#m.has(t))return;const s=this.#e.getAttribute(e);"magnetic"===t&&"symbol"==typeof this.magnetism[s]?this.magnetic=this.magnetism[s]:"string"==typeof s&&(this[t]="true"===s||"on"===s||"yes"===s||"false"!==s&&"off"!==s&&"no"!==s&&(parseFloat(s)||s),this.events.get("configured")&&this.#e.dispatchEvent(new CustomEvent("hotline.configured",{detail:{name:t,value:this[t]}})))}}position(e){const t=this.#t.position||void 0;return void 0===this.#t.element&&(this.#t.element=this.#e.firstElementChild),this.#t.element instanceof HTMLElement?(this.#t.position=e,this.#t.element.style[this.vertical?"marginTop":"marginLeft"]=this.#t.position+"px",this.events.get("position")&&this.#e.dispatchEvent(new CustomEvent("hotline.position",{detail:{from:t,to:e}})),e-(t||0)):null}move(e){const t=this.#t.position,s=this.#t.position+(e||this.step),n=this.position(s);return this.events.get("moving")&&document.dispatchEvent(new CustomEvent("hotline.moving",{detail:{from:t,to:s}})),n}forward(){return new Promise(((e,t)=>{let s,n=Math.abs(this.step)||1;const i=setInterval((()=>{++n,this.move(n)}),this.interval),l=()=>{n>10&&(clearInterval(i),clearTimeout(s),this.events.get("moved.forward")&&this.#e.dispatchEvent(new CustomEvent("hotline.moved.forward")),this.#e.removeEventListener("hotline.transfer.beginning",l),e())};this.#e.addEventListener("hotline.transfer.beginning",l,!1),s=setTimeout((()=>{clearTimeout(i),t()}),5e3)}))}backward(){return new Promise(((e,t)=>{let s,n=-Math.abs(this.step)||-1;const i=setInterval((()=>{--n,this.move(n)}),this.interval),l=()=>{n<-10&&(clearInterval(i),clearTimeout(s),this.events.get("moved.backward")&&this.#e.dispatchEvent(new CustomEvent("hotline.moved.backward")),this.#e.removeEventListener("hotline.transfer.end",l),e())};this.#e.addEventListener("hotline.transfer.end",l,!1),s=setTimeout((()=>{clearTimeout(i),t()}),5e3)}))}magnetize(e,t){return new Promise(((s,n)=>{if(e instanceof HTMLElement){const i=e.getBoundingClientRect(),l=this.#e.getBoundingClientRect();let r;switch(t){case this.#a.beginning:break;case this.#a.center:r=i.x+i.width/2-(l.x+l.width/2);break;case this.#a.end:break;default:return}if(r>0){let e,i=-Math.abs(this.magnet)||-Math.abs(this.step)||0;const l=setInterval((()=>{--i;r+i<=0&&(i=-r),r+=this.move(i)||0,0===r&&(clearInterval(l),clearTimeout(e),this.events.get("magnetized")&&this.#e.dispatchEvent(new CustomEvent("hotline.magnetized",{detail:{magnetism:t}})),s(t))}),this.interval);e=setTimeout((()=>{clearTimeout(l),n()}),5e3)}else if(r<0){let e,i=Math.abs(this.magnet)||Math.abs(this.step)||0;const l=setInterval((()=>{++i;r+i>=0&&(i=-r),r+=this.move(i)||0,0===r&&(clearInterval(l),clearTimeout(e),this.events.get("magnetized")&&this.#e.dispatchEvent(new CustomEvent("hotline.magnetized",{detail:{magnetism:t}})),s(t))}),this.interval);e=setTimeout((()=>{clearTimeout(l),n()}),5e3)}else this.events.get("magnetized")&&this.#e.dispatchEvent(new CustomEvent("hotline.magnetized",{detail:{magnetism:t}})),s(t)}}))}static preprocessing(e=!1,t=!1){const s=new Set;for(const e of document.querySelectorAll('*[data-hotline="true"]')){const n=new this(e,t);for(const t of e.getAttributeNames())n.configure(t);n.start(),s.add(n)}return e&&document.dispatchEvent(new CustomEvent("hotline.preprocessed"),{detail:{generated:s}}),s}}