From f6e31a5968a91399845174c298d2dadcbd00198a Mon Sep 17 00:00:00 2001 From: empathicqubit Date: Mon, 22 Mar 2021 14:54:31 -0400 Subject: [PATCH] Initial commit --- ds.min.js | 1 + index.css | 48 +++++++ index.html | 11 ++ index.js | 357 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 417 insertions(+) create mode 100644 ds.min.js create mode 100644 index.css create mode 100644 index.html create mode 100644 index.js diff --git a/ds.min.js b/ds.min.js new file mode 100644 index 0000000..bfcac9e --- /dev/null +++ b/ds.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DragSelect=t()}(this,(function(){"use strict";function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t(e,t){for(var i=0;ie.length)&&(t=e.length);for(var i=0,r=new Array(t);i1&&void 0!==arguments[1]?arguments[1]:0;return{left:e.x,top:e.y,right:e.x,bottom:e.y,width:t,height:t}},y=function(){var e,t,i,r;return{y:(null===(e=document.body)||void 0===e?void 0:e.scrollTop)||(null===(t=document.documentElement)||void 0===t?void 0:t.scrollTop)||0,x:(null===(i=document.body)||void 0===i?void 0:i.scrollLeft)||(null===(r=document.documentElement)||void 0===r?void 0:r.scrollLeft)||0}},b=function(e){return!e||e instanceof Document?y():{x:e.scrollLeft>=0?e.scrollLeft:y().x,y:e.scrollTop>=0?e.scrollTop:y().y}},_=function(e){var t=e.elementRect,i=e.containerRect,r=e.tolerance,n=void 0===r?{x:0,y:0}:r,o=[];return t.top-n.yi.bottom&&o.push("bottom"),t.right+n.y>i.right&&o.push("right"),o},D=function(e){var t=e.event;return{x:t.clientX,y:t.clientY}},w=function(e){var t={x:0,y:0},i=window.getComputedStyle(e);if(!i.transform||"none"===i.transform)return t;if(i.transform.indexOf("3d")>=0){var r=i.transform.trim().match(/matrix3d\((.*?)\)/);if(r&&r.length){var n,o=null===(n=r[1])||void 0===n?void 0:n.split(",");t.x=parseInt(o[12])||0,t.y=parseInt(o[13])||0}return t}var s=i.transform.trim().match(/matrix\((.*?)\)/);if(s&&s.length){var a,l=null===(a=s[1])||void 0===a?void 0:a.split(",");t.x=parseInt(l[4])||0,t.y=parseInt(l[5])||0}return t},x=function(e,t){return t?function(e){var t=e.style.transform;if(!t||t.indexOf("translate")<0)return w(e);var i={x:0,y:0},r=t.trim().match(/translate[3dD]*?\(.*?\)/);if(r){var n,o=null===(n=r[0])||void 0===n?void 0:n.split("(");if(o){var s,a=null===(s=o[1])||void 0===s?void 0:s.split(",");i.x=parseInt(a[0])||0,i.y=parseInt(a[1])||0}}return i.x||i.x?i:w(e)}(e):function(e){var t=e.style,i={x:parseInt(t.left)||0,y:parseInt(t.top)||0};if(!i.x&&!i.x){var r=window.getComputedStyle(e);return{x:parseInt(r.left)||0,y:parseInt(r.top)||0}}return i}(e)},k=function(e){var t=e.computedStyle,i=e.node,r=t.position;i instanceof HTMLDocument||("absolute"===r||"relative"===r||"fixed"===r)||(i.style.position="relative")},E=function(e,t){return e.leftt.left&&e.topt.top},I=function(e){var t=e.element,i=e.posDirection,r=e.containerRect,n=e.useTransform,o=x(t,n),s=m(o,"+",i);P(t,s,n);var a=t.getBoundingClientRect();!function(e){var t=e.element,i=e.edges,r=e.elementRect,n=e.containerRect,o=e.elementPos,s=e.useTransform;i.includes("top")&&P(t,{y:o.y+n.top-r.top,x:o.x},s),i.includes("left")&&P(t,{y:o.y,x:o.x+n.left-r.left},s),i.includes("bottom")&&P(t,{y:o.y+n.bottom-r.bottom,x:o.x},s),i.includes("right")&&P(t,{y:o.y,x:o.x+n.right-r.right},s)}({element:t,edges:_({elementRect:a,containerRect:r}),elementRect:a,containerRect:r,elementPos:s,useTransform:n})},P=function(e,t,i){if(i){var r=e.style.transform;e.style.transform="translate3d(".concat(t.x,"px,").concat(t.y,"px,1px) ").concat(r.replace(/translate.*?\)/g,""))}else e.style.left="".concat(t.x,"px"),e.style.top="".concat(t.y,"px");return e},A=function(e){return e?!Array.isArray(e)&&(e instanceof HTMLElement||e instanceof SVGElement)?[e]:v(e):[]},L=function(e,t){e.style.left="".concat(t.left,"px"),e.style.top="".concat(t.top,"px"),e.style.width="".concat(t.width,"px"),e.style.height="".concat(t.height,"px")},T=function(){function t(i){var n,o,s,a=this,l=i.area,c=i.PS,u=i.zoom;e(this,t),r(this,"_modificationCallback",void 0),r(this,"_modificationObserver",void 0),r(this,"_zoom",void 0),r(this,"_node",void 0),r(this,"_parentNodes",void 0),r(this,"_computedStyle",void 0),r(this,"_computedBorder",void 0),r(this,"_rect",void 0),r(this,"start",(function(){var e,t,i;e=a.parentNodes,t=a._modificationCallback,i=a._modificationObserver,window.addEventListener("resize",t),window.addEventListener("scroll",t),e.forEach((function(e,t){i.observe(e,{childList:0!==t,attributes:!0})}))})),r(this,"reset",(function(){a._computedStyle=void 0,a._rect=void 0,a._computedBorder=void 0,a._parentNodes=void 0})),r(this,"stop",(function(){var e,t;e=a._modificationObserver,t=a._modificationCallback,window.removeEventListener("resize",t),window.removeEventListener("scroll",t),e.disconnect(),a.reset()})),r(this,"scroll",(function(e,t){!function(e,t,i){if(t.length){var r=document&&document.documentElement&&document.documentElement.scrollTop&&document.documentElement,n=e instanceof HTMLDocument?r||document.body:e,o=t.includes("top")&&n.scrollTop>0,s=t.includes("bottom")&&n.scrollTop0,l=t.includes("right")&&n.scrollLeft1&&void 0!==arguments[1]?arguments[1]:0,n=null===(i=t[r])||void 0===i?void 0:i.parentNode;return n?(t.push(n),e(t,++r)):t}([this.HTMLNode]),this._parentNodes}}]),t}(),C=function(){function t(i){var n=this,o=i.DS,s=i.useTransform,a=i.dragKeys,l=i.keyboardDragSpeed,c=i.zoom;e(this,t),r(this,"_useTransform",void 0),r(this,"_prevCursorPos",void 0),r(this,"_prevScrollPos",void 0),r(this,"_elements",[]),r(this,"_dragKeys",void 0),r(this,"_dragKeysFlat",void 0),r(this,"_keyboardDragSpeed",void 0),r(this,"_zoom",void 0),r(this,"keyboardDrag",(function(e){var t=e.event,i=e.key;if(n._dragKeysFlat.includes(i)&&n.DS.SelectedSet.size){n._isKeyboard=!0,n.DS.publish("Interaction:start",{event:t,isDragging:!0}),n._elements=n.DS.getSelection(),n.handleZIndex(!0);var r=function(e){var t=e.shiftKey,i=e.keyboardDragSpeed,r=e.zoom,n=e.key,o=e.dragKeys,s=e.scrollDiff,a=e.canScroll,l=e.scrollCallback,c={x:0,y:0},u=t?4*i*r:i*r;return o.left.includes(n)&&(c.x=s.x||-u,t||s.x||!a||l(["left"],i)),o.right.includes(n)&&(c.x=s.x||u,t||s.x||!a||l(["right"],i)),o.up.includes(n)&&(c.y=s.y||-u,t||s.y||!a||l(["top"],i)),o.down.includes(n)&&(c.y=s.y||u,t||s.y||!a||l(["bottom"],i)),c}({shiftKey:n.DS.stores.KeyStore.currentValues.includes("shift"),keyboardDragSpeed:n._keyboardDragSpeed,zoom:n._zoom,key:i,scrollCallback:n.DS.Area.scroll,scrollDiff:n._scrollDiff,canScroll:n.DS.stores.ScrollStore.canScroll,dragKeys:n._dragKeys});n._elements.forEach((function(e){return I({element:e,posDirection:r,containerRect:n.DS.SelectorArea.rect,useTransform:n._useTransform})})),n.DS.publish("Interaction:update",{event:t,isDragging:!0}),n._isKeyboard=!1}})),r(this,"keyboardEnd",(function(e){var t=e.event,i=e.key;n._dragKeysFlat.includes(i)&&n.DS.SelectedSet.size&&(n._isKeyboard=!0,n.DS.publish("Interaction:end",{event:t,isDragging:!0}),n._isKeyboard=!1)})),r(this,"start",(function(e){e.isDragging&&!n._isKeyboard&&(n._prevCursorPos=null,n._prevScrollPos=null,n._elements=n.DS.getSelection(),n.handleZIndex(!0))})),r(this,"stop",(function(){n._isKeyboard||(n._prevCursorPos=null,n._prevScrollPos=null,n.handleZIndex(!1),n._elements=[])})),r(this,"update",(function(e){if(e.isDragging&&n._elements.length&&!n._isKeyboard){var t=m(n._cursorDiff,"+",n._scrollDiff);n._elements.forEach((function(e){return I({element:e,posDirection:t,containerRect:n.DS.SelectorArea.rect,useTransform:n._useTransform})}))}})),r(this,"handleZIndex",(function(e){n._elements.forEach((function(t){return t.style.zIndex="".concat((parseInt(t.style.zIndex)||0)+e?9999:-9998)}))})),this.DS=o,this._useTransform=s,this._keyboardDragSpeed=l,this._zoom=c,this._dragKeys={up:a.up.map((function(e){return e.toLowerCase()})),down:a.down.map((function(e){return e.toLowerCase()})),left:a.left.map((function(e){return e.toLowerCase()})),right:a.right.map((function(e){return e.toLowerCase()}))},this._dragKeysFlat=[].concat(v(this._dragKeys.up),v(this._dragKeys.down),v(this._dragKeys.left),v(this._dragKeys.right)),this.DS.subscribe("Interaction:start",this.start),this.DS.subscribe("Interaction:end",this.stop),this.DS.subscribe("Interaction:update",this.update),this.DS.subscribe("KeyStore:down",this.keyboardDrag),this.DS.subscribe("KeyStore:up",this.keyboardEnd)}return i(t,[{key:"_cursorDiff",get:function(){var e=this.DS.stores.PointerStore.currentVal,t=this._prevCursorPos?m(e,"-",this._prevCursorPos):{x:0,y:0};return this._prevCursorPos=e,t}},{key:"_scrollDiff",get:function(){var e=this.DS.stores.ScrollStore.currentVal,t=this._prevScrollPos?m(e,"-",this._prevScrollPos):{x:0,y:0};return this._prevScrollPos=e,t}}]),t}(),V=function(){function t(i){var n=this,o=i.areaElement,s=i.DS,a=i.draggability,l=i.immediateDrag;e(this,t),r(this,"_areaElement",void 0),r(this,"_draggability",void 0),r(this,"_immediateDrag",void 0),r(this,"isInteracting",void 0),r(this,"isDragging",void 0),r(this,"init",(function(){n.stop(),n._areaElement.addEventListener("mousedown",n.start),n._areaElement.addEventListener("touchstart",n.start,{passive:!1}),n.DS.publish("Interaction:init",{})})),r(this,"start",(function(e){"touchstart"===e.type&&e.preventDefault(),n._canInteract(e)&&(n.isInteracting=!0,n.isDragging=n.isDragEvent(e),n.DS.publish("Interaction:start",{event:e,isDragging:n.isDragging}),document.addEventListener("mouseup",n.reset),document.addEventListener("touchend",n.reset))})),r(this,"isDragEvent",(function(e){return!(!n._draggability||n.DS.stores.KeyStore.isMultiSelectKeyPressed(e)||!n.DS.SelectableSet.has(e.target))&&(n._immediateDrag&&(n.DS.SelectedSet.size?n.DS.SelectedSet.has(e.target)||(n.DS.SelectedSet.clear(),n.DS.SelectedSet.add(e.target)):n.DS.SelectedSet.add(e.target)),!!n.DS.SelectedSet.has(e.target))})),r(this,"onClick",(function(e){var t=e.event;if(n._canInteract(t)&&!(t.detail>0)){var i=n.DS,r=i.stores,o=r.PointerStore,s=r.KeyStore,a=i.SelectableSet,l=i.SelectedSet,c=i.publish;o.start(t);var u=t.target;a.has(u)&&(s.isMultiSelectKeyPressed(t)||l.clear(),l.toggle(u),c("Interaction:end",{event:t,isDragging:n.isDragging}))}})),r(this,"stop",(function(){n.isInteracting=!1,n.isDragging=!1,n._areaElement.removeEventListener("mousedown",n.start),n._areaElement.removeEventListener("touchstart",n.start,{passive:!1}),document.removeEventListener("mouseup",n.reset),document.removeEventListener("touchend",n.reset)})),r(this,"update",(function(e){var t=e.event,i=e.data;n.isInteracting&&n.DS.publish("Interaction:update",{event:t,data:i,isDragging:n.isDragging})})),r(this,"reset",(function(e){var t=n.isDragging;n.stop(),n.init(),n.DS.publish("Interaction:end",{event:e,isDragging:t})})),this._areaElement=o,this._draggability=a,this._immediateDrag=l,this.DS=s,this.DS.subscribe("PointerStore:updated",this.update),this.DS.subscribe("Selectable:click",this.onClick),this.DS.subscribe("Selectable:pointer",(function(e){var t=e.event;return n.start(t)})),this.DS.subscribe("Area:scroll",this.update)}return i(t,[{key:"_canInteract",value:function(e){return!(2===e.button||this.isInteracting||e.target&&!this.DS.SelectorArea.isInside(e.target))}}]),t}(),N=function t(){var i=this;e(this,t),r(this,"subscribers",{}),r(this,"subscribe",(function(e,t){return Array.isArray(i.subscribers[e])||(i.subscribers[e]=[]),i.subscribers[e].push(t),i.subscribers[e].length-1})),r(this,"unsubscribe",(function(e,t,r){r>=0?i.subscribers[e].splice(r,1):t&&(i.subscribers[e]=i.subscribers[e].filter((function(e){return e!==t})))})),r(this,"publish",(function(e,t){Array.isArray(i.subscribers[e])&&i.subscribers[e].forEach((function(e){return e(t)}))}))},M=function(t){n(a,t);var s=h(a);function a(t){var i,n=t.elements,o=t.className,l=t.hoverClassName,c=t.draggability,d=t.useTransform,h=t.DS;return e(this,a),r(u(i=s.call(this)),"_initElements",void 0),r(u(i),"_className",void 0),r(u(i),"_hoverClassName",void 0),r(u(i),"_useTransform",void 0),r(u(i),"_draggability",void 0),r(u(i),"init",(function(){return i._initElements.forEach((function(e){return i.add(e)}))})),r(u(i),"clear",(function(){return i.forEach((function(e){return i.delete(e)}))})),r(u(i),"_onClick",(function(e){return i.DS.publish("Selectable:click",{event:e})})),r(u(i),"_onPointer",(function(e){return i.DS.publish("Selectable:pointer",{event:e})})),r(u(i),"addAll",(function(e){return e.forEach((function(e){return i.add(e)}))})),r(u(i),"deleteAll",(function(e){return e.forEach((function(e){return i.delete(e)}))})),i.DS=h,i._initElements=A(n),i._className=o,i._hoverClassName=l,i._useTransform=d,i._draggability=c,i.DS.subscribe("Interaction:init",i.init),i}return i(a,[{key:"add",value:function(e){return e.classList.add(this._className),e.addEventListener("click",this._onClick),e.addEventListener("mousedown",this._onPointer),e.addEventListener("touchstart",this._onPointer,{passive:!1}),this._draggability&&!this._useTransform&&k({computedStyle:window.getComputedStyle(e),node:e}),f(o(a.prototype),"add",this).call(this,e)}},{key:"delete",value:function(e){return e.classList.remove(this._className),e.classList.remove(this._hoverClassName),e.removeEventListener("click",this._onClick),e.removeEventListener("mousedown",this._onPointer),e.removeEventListener("touchstart",this._onPointer,{passive:!1}),f(o(a.prototype),"delete",this).call(this,e)}},{key:"elements",get:function(){return Array.from(this.values())}}]),a}(c(Set)),K=function(t){n(a,t);var s=h(a);function a(t){var i,n=t.className,o=t.DS;return e(this,a),r(u(i=s.call(this)),"_className",void 0),r(u(i),"clear",(function(){return i.forEach((function(e){return i.delete(e)}))})),r(u(i),"addAll",(function(e){return e.forEach((function(e){return i.add(e)}))})),r(u(i),"deleteAll",(function(e){return e.forEach((function(e){return i.delete(e)}))})),i.DS=o,i._className=n,i}return i(a,[{key:"add",value:function(e){if(!f(o(a.prototype),"has",this).call(this,e))return f(o(a.prototype),"add",this).call(this,e),e.classList.add(this._className),this.DS.publish("Selected:added",{items:this.elements,item:e}),e.style.zIndex="".concat((parseInt(e.style.zIndex)||0)+1),this}},{key:"delete",value:function(e){if(f(o(a.prototype),"has",this).call(this,e)){var t=f(o(a.prototype),"delete",this).call(this,e);return e.classList.remove(this._className),this.DS.publish("Selected:removed",{items:this.elements,item:e}),e.style.zIndex="".concat((parseInt(e.style.zIndex)||0)-1),t}}},{key:"toggle",value:function(e){return this.has(e)?this.delete(e):this.add(e),e}},{key:"elements",get:function(){return Array.from(this.values())}}]),a}(c(Set)),z=function(){function t(i){var n=this,o=i.DS,s=i.hoverClassName,a=i.multiSelectToggling;e(this,t),r(this,"_prevSelectedSet",void 0),r(this,"_hoverClassName",void 0),r(this,"_multiSelectToggling",void 0),r(this,"start",(function(e){var t=e.event;e.isDragging||(n._storePrevious(t),n._handleInsideSelection(!0,t))})),r(this,"update",(function(e){e.isDragging||n._handleInsideSelection()})),r(this,"_handleInsideSelection",(function(e,t){for(var i=n.DS,r=i.SelectableSet,o=i.SelectorArea,s=i.Selector,a=r.elements.map((function(e){return[e,e.getBoundingClientRect()]})),l=[],c=[],u=0,d=a.length;ui.x-t.x?(n.left=i.x-t.x,n.width=r.x-i.x+t.x):(n.left=r.x,n.width=i.x-r.x-t.x),r.y>i.y-t.y?(n.top=i.y-t.y,n.height=r.y-i.y+t.y):(n.top=r.y,n.height=i.y-r.y-t.y),n}({scrollAmount:i.scrollAmount,initialPointerPos:r.initialValArea,pointerPos:r.currentValArea});L(n.HTMLNode,o),n._rect=null}})),this.DS=o,this.HTMLNode=s||function(e){var t=document.createElement("div");return t.style.position="absolute",e||(t.style.background="rgba(0, 0, 255, 0.1)",t.style.border="1px solid rgba(0, 0, 255, 0.45)",t.style.display="none",t.style.pointerEvents="none"),t}(l),this.HTMLNode.classList.add(a),this.DS.subscribe("Interaction:start",this.start),this.DS.subscribe("Interaction:update",this.update),this.DS.subscribe("Interaction:end",this.stop)}return i(t,[{key:"rect",get:function(){return this._rect?this._rect:this._rect=this.HTMLNode.getBoundingClientRect()}}]),t}(),R=function(){function t(i){var n=this,o=i.DS,s=i.selectorAreaClass,a=i.autoScrollSpeed,l=i.overflowTolerance;e(this,t),r(this,"_autoScrollSpeed",void 0),r(this,"_scrollInterval",void 0),r(this,"_rect",void 0),r(this,"currentEdges",[]),r(this,"_overflowTolerance",void 0),r(this,"updatePos",(function(){n._rect=null;var e=n.DS.Area.rect,t=n.DS.Area.computedBorder,i=n.HTMLNode.style,r="".concat(e.top+t.top,"px"),o="".concat(e.left+t.left,"px"),s="".concat(e.width,"px"),a="".concat(e.height,"px");i.top!==r&&(i.top=r),i.left!==o&&(i.left=o),i.width!==s&&(i.width=s),i.height!==a&&(i.height=a)})),r(this,"startAutoScroll",(function(){n.currentEdges=[],n._scrollInterval=setInterval((function(){return n.handleAutoScroll()}),16)})),r(this,"handleAutoScroll",(function(){var e=n.DS,t=e.stores.PointerStore,i=e.Area;n.currentEdges=_({elementRect:p(t.currentVal),containerRect:n.rect,tolerance:n._overflowTolerance}),n.currentEdges.length&&i.scroll(n.currentEdges,n._autoScrollSpeed)})),r(this,"stopAutoScroll",(function(){n.currentEdges=[],clearInterval(n._scrollInterval)})),r(this,"isInside",(function(e,t){return!(!n.DS.Area.HTMLNode.contains(e)||!n.DS.stores.ScrollStore.canScroll)||E(n.rect,t||e.getBoundingClientRect())})),this._autoScrollSpeed=a,this._overflowTolerance=l,this.DS=o,this.HTMLNode=function(e){var t=document.createElement("div");return t.style.position="fixed",t.style.overflow="hidden",t.style.pointerEvents="none",t.style.zIndex="999999999999999999",t.classList.add(e),t}(s),this.HTMLNode.appendChild(this.DS.Selector.HTMLNode);var c=document.body?"body":"documentElement";document[c].appendChild(this.HTMLNode),this.DS.subscribe("Area:modified",this.updatePos),this.DS.subscribe("Interaction:start",this.startAutoScroll),this.DS.subscribe("Interaction:end",(function(){n.updatePos(),n.stopAutoScroll()}))}return i(t,[{key:"isClicked",value:function(){var e=this.DS.stores.PointerStore;return E({left:e.initialVal.x,top:e.initialVal.y,right:e.initialVal.x,bottom:e.initialVal.y},this.rect)}},{key:"rect",get:function(){return this._rect?this._rect:this._rect=this.HTMLNode.getBoundingClientRect()}}]),t}(),O=function(){function t(i){var n=this,o=i.DS,s=i.multiSelectKeys,a=i.multiSelectMode;e(this,t),r(this,"_multiSelectMode",void 0),r(this,"_multiSelectKeys",void 0),r(this,"_currentValues",new Set),r(this,"_keyMapping",{control:"ctrlKey",shift:"shiftKey",meta:"metaKey"}),r(this,"init",(function(){document.addEventListener("keydown",n.keydown),document.addEventListener("keyup",n.keyup),window.addEventListener("blur",n.reset)})),r(this,"keydown",(function(e){var t=e.key.toLowerCase();n._currentValues.add(t),n.DS.publish("KeyStore:down",{event:e,key:t})})),r(this,"keyup",(function(e){var t=e.key.toLowerCase();n._currentValues.delete(t),n.DS.publish("KeyStore:up",{event:e,key:t})})),r(this,"stop",(function(){document.removeEventListener("keydown",n.keydown),document.removeEventListener("keyup",n.reset),window.removeEventListener("blur",n.reset),n.reset()})),r(this,"reset",(function(){return n._currentValues.clear()})),this.DS=o,this._multiSelectMode=a,this._multiSelectKeys=s.map((function(e){var t={ctrlKey:"Control",shiftKey:"Shift",metaKey:"Meta"}[e];return t?(console.warn("[DragSelect] ".concat(e,' is deprecated. Use "').concat(t,'" instead. Act Now!. See docs for more info')),t.toLowerCase()):e.toLowerCase()})),this.DS.subscribe("Interaction:init",this.init)}return i(t,[{key:"isMultiSelectKeyPressed",value:function(e){var t=this;return!!this._multiSelectMode||(!!this.currentValues.some((function(e){return t._multiSelectKeys.includes(e)}))||!(!e||!this._multiSelectKeys.some((function(i){return e[t._keyMapping[i]]}))))}},{key:"currentValues",get:function(){return Array.from(this._currentValues.values())}}]),t}(),B=function(){function t(i){var n=this,o=i.DS;e(this,t),r(this,"_isMouseInteraction",!1),r(this,"_initialValArea",void 0),r(this,"_currentValArea",void 0),r(this,"_lastValArea",void 0),r(this,"_initialVal",void 0),r(this,"_currentVal",void 0),r(this,"_lastVal",void 0),r(this,"_lastTouch",void 0),r(this,"init",(function(){document.addEventListener("mousemove",n.update),document.addEventListener("touchmove",n.update,{passive:!1})})),r(this,"update",(function(e){e&&(n.currentVal=D({event:n._normalizedEvent(e)}),n._isMouseInteraction&&n.DS.publish("PointerStore:updated",{event:e}))})),r(this,"stop",(function(){document.removeEventListener("mousemove",n.update),document.removeEventListener("touchmove",n.update,{passive:!1}),setTimeout((function(){return n._isMouseInteraction=!1}),100)})),r(this,"reset",(function(e){e&&(n.currentVal=n.lastVal=D({event:n._normalizedEvent(e)}),n.stop(),n.init())})),this.DS=o,this.DS.subscribe("Interaction:init",this.init),this.DS.subscribe("Interaction:start",(function(e){var t=e.event;return n.start(t)})),this.DS.subscribe("Interaction:end",(function(e){var t=e.event;return n.reset(t)}))}return i(t,[{key:"start",value:function(e){e&&(this._isMouseInteraction=!0,this.currentVal=this.initialVal=D({event:this._normalizedEvent(e)}))}},{key:"_normalizedEvent",value:function(e){return"touches"in e&&"touchend"!==e.type&&(this._lastTouch=e),"touches"in e?this._lastTouch.touches[0]:e}},{key:"initialValArea",get:function(){return this._initialValArea?this._initialValArea:{x:0,y:0}}},{key:"currentValArea",get:function(){return this._currentValArea?this._currentValArea:{x:0,y:0}}},{key:"lastValArea",get:function(){return this._lastValArea?this._lastValArea:{x:0,y:0}}},{key:"initialVal",get:function(){return this._initialVal?this._initialVal:{x:0,y:0}},set:function(e){this._initialVal=e,this._initialValArea=e&&m(e,"-",m(g(this.DS.Area.rect),"+",g(this.DS.Area.computedBorder)))}},{key:"currentVal",get:function(){return this._currentVal?this._currentVal:{x:0,y:0}},set:function(e){this._currentVal=e,this._currentValArea=e&&m(e,"-",m(g(this.DS.Area.rect),"+",g(this.DS.Area.computedBorder)))}},{key:"lastVal",get:function(){return this._lastVal?this._lastVal:{x:0,y:0}},set:function(e){this._lastVal=e,this._lastValArea=e&&m(e,"-",m(g(this.DS.Area.rect),"+",g(this.DS.Area.computedBorder)))}}]),t}(),j=function(){function t(i){var n=this,o=i.DS,s=i.areaElement,a=i.zoom;e(this,t),r(this,"_initialVal",void 0),r(this,"_currentVal",void 0),r(this,"_areaElement",void 0),r(this,"_canScroll",void 0),r(this,"init",(function(){return n._areaElement.addEventListener("scroll",n.update)})),r(this,"start",(function(){n._currentVal=n._initialVal=b(n._areaElement),n._areaElement.addEventListener("scroll",n.update)})),r(this,"update",(function(){return n._currentVal=b(n._areaElement)})),r(this,"stop",(function(){n._areaElement.removeEventListener("scroll",n.update),n._initialVal={x:0,y:0},n._canScroll=null})),r(this,"reset",(function(){n.stop(),n.start()})),this._areaElement=s,this.DS=o,this.zoom=a,this.DS.subscribe("Interaction:init",this.init),this.DS.subscribe("Interaction:start",(function(){return n.start()})),this.DS.subscribe("Interaction:end",(function(){return n.reset()}))}return i(t,[{key:"canScroll",get:function(){return"boolean"==typeof this._canScroll?this._canScroll:this._canScroll=(e=this._areaElement,!!((t=b(e)).x||t.y||(e instanceof HTMLDocument?e.body?e.body.scrollTop=1:e.documentElement.scrollTop=1:e.scrollTop=1)));var e,t}},{key:"scrollAmount",get:function(){var e,t=m(this.currentVal,"-",this.initialVal),i={x:e=this.zoom,y:e},r=m(m(t,"*",i),"-",t);return{x:t.x+r.x,y:t.y+r.y}}},{key:"initialVal",get:function(){return this._initialVal?this._initialVal:{x:0,y:0}}},{key:"currentVal",get:function(){return this._currentVal||(this._currentVal=b(this._areaElement)),this._currentVal}}]),t}();return function(){function t(i){var n=this,o=i.area,s=void 0===o?document:o,a=i.selectables,l=void 0===a?[]:a,c=i.autoScrollSpeed,u=void 0===c?5:c,d=i.overflowTolerance,h=void 0===d?{x:25,y:25}:d,f=i.zoom,v=void 0===f?1:f,S=i.customStyles,m=void 0!==S&&S,g=i.multiSelectMode,p=void 0!==g&&g,y=i.multiSelectToggling,b=void 0===y||y,_=i.multiSelectKeys,D=void 0===_?["Control","Shift","Meta"]:_,w=i.selector,x=void 0===w?void 0:w,k=i.draggability,E=void 0===k||k,I=i.immediateDrag,P=void 0===I||I,A=i.dragKeys,L=i.keyboardDragSpeed,U=void 0===L?10:L,W=i.useTransform,F=void 0===W||W,Z=i.hoverClass,G=void 0===Z?"ds-hover":Z,X=i.selectableClass,Y=void 0===X?"ds-selectable":X,$=i.selectedClass,q=void 0===$?"ds-selected":$,J=i.selectorClass,Q=void 0===J?"ds-selector":J,ee=i.selectorAreaClass,te=void 0===ee?"ds-selector-area":ee,ie=i.callback,re=i.onDragMove,ne=i.onDragStartBegin,oe=i.onDragStart,se=i.onElementSelect,ae=i.onElementUnselect;e(this,t),r(this,"start",(function(){return n.Interaction.init()})),r(this,"getSelection",(function(){return n.SelectedSet.elements})),r(this,"getSelectables",(function(){return n.SelectableSet.elements})),r(this,"getInitialCursorPosition",(function(){return n.stores.PointerStore.initialVal})),r(this,"getCurrentCursorPosition",(function(){return n.stores.PointerStore.currentVal})),r(this,"getPreviousCursorPosition",(function(){return n.stores.PointerStore.lastVal})),r(this,"getInitialCursorPositionArea",(function(){return n.stores.PointerStore.initialValArea})),r(this,"getCurrentCursorPositionArea",(function(){return n.stores.PointerStore.currentValArea})),r(this,"getPreviousCursorPositionArea",(function(){return n.stores.PointerStore.lastValArea})),r(this,"isMultiSelect",(function(e){return n.stores.KeyStore.isMultiSelectKeyPressed(e)})),r(this,"isDragging",(function(){return n.Interaction.isDragging})),this.PubSub=new N,this.subscribe=this.PubSub.subscribe,this.unsubscribe=this.PubSub.unsubscribe,this.publish=this.PubSub.publish,this._callbacksTemp({callback:ie,onDragMove:re,onDragStart:oe,onDragStartBegin:ne,onElementSelect:se,onElementUnselect:ae}),this.stores={PointerStore:new B({DS:this}),ScrollStore:new j({DS:this,areaElement:s,zoom:v}),KeyStore:new O({DS:this,multiSelectKeys:D,multiSelectMode:p})},this.Area=new T({area:s,PS:this.PubSub,zoom:v}),this.Selector=new H({DS:this,selector:x,selectorClass:Q,customStyles:m}),this.SelectorArea=new R({DS:this,selectorAreaClass:te,autoScrollSpeed:u,overflowTolerance:h}),this.SelectableSet=new M({elements:l,DS:this,className:Y,hoverClassName:G,useTransform:F,draggability:E}),this.SelectedSet=new K({DS:this,className:q}),this.Selection=new z({DS:this,hoverClassName:G,multiSelectToggling:b}),this.Drag=new C({DS:this,useTransform:F,dragKeys:Object.assign({up:["ArrowUp"],down:["ArrowDown"],left:["ArrowLeft"],right:["ArrowRight"]},A),zoom:v,keyboardDragSpeed:U}),this.Interaction=new V({areaElement:s,DS:this,draggability:E,immediateDrag:P}),this.subscribe("Selected:added",(function(e){var t=e.items,i=e.item;return n.publish("elementselect",{items:t,item:i,isDragging:n.Interaction.isDragging})})),this.subscribe("Selected:removed",(function(e){var t=e.items,i=e.item;return n.publish("elementunselect",{items:t,item:i,isDragging:n.Interaction.isDragging})})),this.subscribe("Interaction:update",(function(e){var t=e.event,i=e.isDragging;t&&n.publish("dragmove",{items:n.getSelection(),event:t,isDragging:i})})),this.subscribe("Area:scroll",(function(e){var t=e.scroll_directions,i=e.scroll_multiplier;n.publish("autoscroll",{items:n.getSelection(),scroll_directions:t,scroll_multiplier:i,isDragging:n.Interaction.isDragging})})),this.subscribe("Interaction:start",(function(e){var t=e.event,i=e.isDragging;return n.publish("dragstart",{items:n.getSelection(),event:t,isDragging:i})})),this.subscribe("Interaction:end",(function(e){var t=e.event,i=e.isDragging;return n.publish("callback",{items:n.getSelection(),event:t,isDragging:i})})),this.start()}return i(t,[{key:"_callbacksTemp",value:function(e){var t=e.callback,i=e.onDragMove,r=e.onDragStart,n=e.onDragStartBegin,o=e.onElementSelect,s=e.onElementUnselect,a=function(e,t){return console.warn("[DragSelect] ".concat(e,' is deprecated. Use DragSelect.subscribe("').concat(t,'", (callbackObject) => {}) instead. Act Now! See docs for more info'))};t&&(a("callback","callback"),this.subscribe("callback",(function(e){var i=e.items,r=(e.item,e.event);return t(i,r)}))),i&&(a("onDragMove","dragmove"),this.subscribe("dragmove",(function(e){e.items,e.item;var t=e.event;return i(t)}))),r&&(a("onDragStart","dragstart"),this.subscribe("dragstart",(function(e){e.items,e.item;var t=e.event;return r(t)}))),n&&(a("onDragStartBegin","dragstart"),this.subscribe("dragstart",(function(e){e.items,e.item;var t=e.event;return n(t)}))),o&&(a("onElementSelect","elementselect"),this.subscribe("elementselect",(function(e){e.items;var t=e.item,i=e.event;return o(t,i)}))),s&&(a("onElementUnselect","elementunselect"),this.subscribe("elementunselect",(function(e){e.items;var t=e.item,i=e.event;return s(t,i)})))}},{key:"stop",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];i&&this.publish("callback",{items:this.getSelection()}),this.Interaction.stop(),this.Area.stop(),this.Drag.stop(),this.Selector.stop(),this.stores.KeyStore.stop(),this.stores.PointerStore.stop(),this.stores.ScrollStore.stop(),e&&this.SelectableSet.clear(),t&&this.SelectedSet.clear()}},{key:"addSelection",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this.SelectedSet.addAll(A(e)),i||this.addSelectables(e),t&&this.PubSub.publish("callback",{items:this.getSelection()}),this.getSelection()}},{key:"removeSelection",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this.SelectedSet.deleteAll(A(e)),i&&this.removeSelectables(e),t&&this.PubSub.publish("callback",{items:this.getSelection()}),this.getSelection()}},{key:"toggleSelection",value:function(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return A(e).forEach((function(n){return t.SelectedSet.has(n)?t.removeSelection(e,i,r):t.addSelection(e,i,r)})),i&&this.PubSub.publish("callback",{items:this.getSelection()}),this.getSelection()}},{key:"setSelection",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this.clearSelection(),this.addSelection(e,t,i),this.getSelection()}},{key:"clearSelection",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return this.SelectedSet.clear(),e&&this.PubSub.publish("callback",{items:this.getSelection()}),this.getSelection()}},{key:"addSelectables",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=A(e);return this.SelectableSet.addAll(i),t&&this.SelectedSet.addAll(i),e}},{key:"setSelectables",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this.removeSelectables(e,t),this.addSelectables(e,i)}},{key:"removeSelectables",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.SelectedSet.clear(),t&&this.SelectedSet.clear(),e}},{key:"getCursorPositionDifference",value:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];console.warn("[DragSelect] Using .getCursorPositionDifference is deprecated. Calculate yourself instead. i.e. `.getCurrentCursorPosition().x - .getInitialCursorPosition().x`");var t=this.getCurrentCursorPosition(),i=e?this.getPreviousCursorPosition():this.getInitialCursorPosition();return m(t,"-",i)}}]),t}()})); \ No newline at end of file diff --git a/index.css b/index.css new file mode 100644 index 0000000..f9da332 --- /dev/null +++ b/index.css @@ -0,0 +1,48 @@ + +input[type="color"] { + width: 5em; + height: 5em; +} + +button.reset { + width: 5em; + height: 5em; +} + +.controls { + display: flex; + vertical-align: middle; +} + +label { + margin: auto .25em auto 1em; +} + +.keyboard-layout { + user-select: none; + display: flex; + flex-direction: column; + font-family: monospace; + background-color: black; + color: white; + font-weight: 900; + min-width: 50em; +} + +.keyboard-layout .row { + display: table; +} + +.keyboard-layout .key { + box-sizing: border-box; + padding: .5em; + display: table-cell; + width: 3em; + height: 3em; + text-align: center; + vertical-align: middle; +} + +.keyboard-layout .key.selected { + border: 2px dashed blue +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..6377395 --- /dev/null +++ b/index.html @@ -0,0 +1,11 @@ + + + + + +
+ + + \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..ef1196b --- /dev/null +++ b/index.js @@ -0,0 +1,357 @@ +import "./ds.min.js" + +const initKeys = () => [ + [ + {name:"Esc", code: 0}, + {name:"F1", code: 1}, + {name:"F2", code: 2}, + {name:"F3", code: 3}, + {name:"F4", code: 4}, + {name:"F5", code: 5}, + {name:"F6", code: 6}, + {name:"F7", code: 7}, + {name:"F8", code: 8}, + {name:"F9", code: 9}, + {name:"F10", code: 10}, + {name:"F11", code: 11}, + {name:"F12", code: 12}, + {name:"PrtSc", code: 13}, + {name:"Ins", code: 14}, + {name:"Del", code: 15}, + {name:"Home", code: 16}, + {name:"End", code: 17}, + {name:"PgUp", code: 18}, + {name:"PgDn", code: 19}, + ], + [ + {name:"`", code: 32}, + {name:"1", code: 33}, + {name:"2", code: 34}, + {name:"3", code: 35}, + {name:"4", code: 36}, + {name:"5", code: 37}, + {name:"6", code: 38}, + {name:"7", code: 39}, + {name:"8", code: 40}, + {name:"9", code: 41}, + {name:"0", code: 42}, + {name:"-", code: 43}, + {name:"=", code: 45}, + {name:"Bk", code: 46}, + {name:"Sp", code: 47}, + {name:"Num Lk", code: 48}, + {name:"/", code: 49}, + {name:"*", code: 50}, + {name:"-", code: 51}, + ], + [ + {name:"Tab", code:64}, + {name:"<->", code:65}, + {name:"Q", code:66}, + {name:"W", code:67}, + {name:"E", code:68}, + {name:"R", code:69}, + {name:"T", code:70}, + {name:"Y", code:71}, + {name:"U", code:72}, + {name:"I", code:73}, + {name:"O", code:74}, + {name:"P", code:75}, + {name:"[", code:76}, + {name:"]", code:77}, + {name:"\\", code:78}, + {name:"7", code:80}, + {name:"8", code:81}, + {name:"9", code:82}, + {name:"+", code:83}, + ], + [ + {name:"Caps", code:96}, + {name:"Lock", code:97}, + {name:"A", code:98}, + {name:"S", code:99}, + {name:"D", code:100}, + {name:"F", code:101}, + {name:"G", code:102}, + {name:"H", code:103}, + {name:"J", code:104}, + {name:"K", code:105}, + {name:"L", code:106}, + {name:";", code:107}, + {name:"'", code:108}, + {name:"En", code:110}, + {name:"ter", code:111}, + {name:"4", code:112}, + {name:"5", code:113}, + {name:"6", code:114}, + {name:"+", code:115}, + ], + [ + {name:"^Sh", code:128}, + {name:"ift", code:130}, + {name:"Z", code:131}, + {name:"X", code:132}, + {name:"C", code:133}, + {name:"V", code:134}, + {name:"B", code:135}, + {name:"N", code:136}, + {name:"M", code:137}, + {name:",", code:138}, + {name:".", code:139}, + {name:"/", code:140}, + {name:"^Sh", code:141}, + {name:"ift", code:142}, + {name:"^", code:143}, + {name:"1", code:144}, + {name:"2", code:145}, + {name:"3", code:146}, + {name:"Enter", code:147}, + ], + [ + {name:"Ct", code:160}, + {name:"rl", code:161}, + {name:"Fn", code:162}, + {name:"#", code:163}, + {name:"Alt", code:164}, + {name:"[_", code:165}, + {name:"__", code:166}, + {name:"__", code:168}, + {name:"_]", code:169}, + {name:"Alt", code:170}, + {name:"=", code:171}, + {name:"Ct", code:172}, + {name:"rl", code:173}, + {name:"<", code:174}, + {name:"\\/", code:175}, + {name:">", code:176}, + {name:"0", code:177}, + {name:".", code:178}, + {name:"Enter", code:179}, + ] +]; + +const state = { + kb: null, + filename: '', + saved: [], + selected: [], + keys: initKeys(), +} + +state.saved = JSON.parse(localStorage.getItem('saved_items') || '[]') + +const resetKeys = async () => { + await state.kb.sendFeatureReport(0xcc, Uint8Array.from([ + 0x00, 0x0c, + 0x00, 0x00, 0x00, + 0x7f + ])); +} + +const setKey = async (key, red, green, blue) => { + await state.kb.sendFeatureReport(0xcc, Uint8Array.from([ + 0x01, key, + red, green, blue, + 0x7f + ])); +} + +const connect = async () => { + state.kb = (await navigator.hid.requestDevice({ filters: [{vendorId: 0x048d }] }))[0]; + await state.kb.open(); + await resetKeys(); + render(); +}; + +const processItem = (parent, item) => { + if(!item) { + return; + } + + if(item.nodeType !== undefined) { + parent.appendChild(item); + } + else if(typeof item != "object") { + const elem = document.createTextNode(item); + parent.appendChild(elem); + } + else { + for(const kid of item) { + processItem(parent, kid); + } + } +} + +const e = (name, attrs, kids) => { + const elem = document.createElement(name); + for(const a in attrs) { + if(a == 'style' || a == 'dataset') { + for(const s in attrs[a]) { + elem[a][s] = attrs[a][s]; + } + } + else { + elem[a] = attrs[a]; + } + } + + processItem(elem, kids); + + return elem; +} + +const selectKey = (key) => { + if(!mouseDown) { + return; + } + + const idx = state.selected.indexOf(key); + if(idx != -1) { + state.selected.splice(idx, 1); + } + else { + state.selected.push(key); + } + + render(); +} + +const deselectKeys = () => { + state.selected = []; + render(); + return false; +} + +const selectColor = (e) => { + const color = parseInt(e.target.value.replace('#', ''), 16) + const r = (color >>> 16) & 0xff; + const g = (color >>> 8) & 0xff; + const b = color & 0xff; + + for(const key of state.selected) { + key.color = color + setKey(key.code, r, g, b); + } + + render(); +} + +const resetColors = () => { + for(const row of state.keys) { + for(const key of row) { + key.color = undefined; + } + } + + resetKeys(); + + render(); +} + +const saveFile = () => { + const existing = state.saved.findIndex(x => x.filename == state.filename); + const keys = state.keys.map(row => row.map(key => ({ code: key.code, name: key.name, color: key.color }))); + const file = { + filename: state.filename, + keys: keys, + }; + + if(existing != -1) { + state.saved[existing] = file; + } + else { + state.saved.push(file); + } + + localStorage.setItem('saved_items', JSON.stringify(state.saved)); + + render(); +} + +const loadFile = (filename) => { + const file = state.saved.find(x => x.filename == filename); + state.keys = file.keys.map(row => row.map(key => ({ code: key.code, name: key.name, color: key.color }))); + for(const row of state.keys) { + for(const key of row) { + const r = (key.color >>> 16) & 0xff; + const g = (key.color >>> 8) & 0xff; + const b = key.color & 0xff; + setKey(key.code, r, g, b); + } + } + render(); +} + +const keyboardLayout = () => { + const rows = + state.keys.map(row => e('div', { className: 'row' }, + row.map(key => e('div', + { + dataset: { + code: key.code, + }, + className: 'key ' + (state.selected.includes(key) ? 'selected' : ''), + style: { + color: key.color !== undefined ? `#${key.color.toString(16)}` : undefined, + }, + }, + key.name, + )), + )); + + const keyboardLayout = e("div", { className: "keyboard-layout" }, rows); + + const ds = new DragSelect({ + area: keyboardLayout, + draggability: false, + selectables: rows.flatMap(x => Array.from(x.querySelectorAll('.key'))) + }) + + ds.subscribe('callback', ({items, event}) => { + state.selected = items.map(x => { + const code = parseInt(x.dataset.code); + for(const row of state.keys) { + for(const key of row) { + if(code == key.code) { + return key; + } + } + } + }); + + ds.stop(); + render(); + }); + + return [ + keyboardLayout, + e("div", { className: "controls"}, [ + e("button", { className: "reset", onclick: () => resetColors() }, "Reset All Keys"), + e('label', { for: "key-color" }, "Color:"), + e('input', { type: "color", id: "key-color", oninput: (e) => selectColor(e) }), + e('label', { for: "filename" }, "Filename:"), + e('input', { type: "text", id: "filename", oninput: (e) => { state.filename = e.target.value } }), + e("button", { className: "reset", onclick: () => saveFile() }, "Save"), + e("select", { onchange: (e) => loadFile(e.target.value) }, + state.saved.map(x => + e('option', { value: x.filename }, x.filename) + ) + ) + ]) + ]; +}; + +const render = () => { + const content = e("div", { id: "content"}, + state.kb == null + ? [ + "Keyboard is not connected", + e("button", { onclick: connect }, "Connect") + ] + : keyboardLayout() + ); + + document.getElementById("content").replaceWith(content); +} + +render(); \ No newline at end of file