├── README.md └── slider.js /README.md: -------------------------------------------------------------------------------- 1 | # sliderjs 2 | 3 | Simple slider the way I like it 4 | By Andrea "6502" Griffini 5 | 6 | This is free and unencumbered software released into the public domain. 7 | 8 | Anyone is free to copy, modify, publish, use, compile, sell, or 9 | distribute this software, either in source code form or as a compiled 10 | binary, for any purpose, commercial or non - commercial, and by any 11 | means. 12 | 13 | In jurisdictions that recognize copyright laws, the author or authors 14 | of this software dedicate any and all copyright interest in the 15 | software to the public domain. We make this dedication for the benefit 16 | of the public at large and to the detriment of our heirs and 17 | successors. We intend this dedication to be an overt act of 18 | relinquishment in perpetuity of all present and future rights 19 | to this software under copyright law. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | For more information, please refer to < http://unlicense.org/ > 30 | -------------------------------------------------------------------------------- /slider.js: -------------------------------------------------------------------------------- 1 | // 2 | // Simple slider the way I like it 3 | // By Andrea "6502" Griffini 4 | // 5 | // This is free and unencumbered software released into the public domain. 6 | // 7 | // Anyone is free to copy, modify, publish, use, compile, sell, or 8 | // distribute this software, either in source code form or as a compiled 9 | // binary, for any purpose, commercial or non - commercial, and by any 10 | // means. 11 | // 12 | // In jurisdictions that recognize copyright laws, the author or authors 13 | // of this software dedicate any and all copyright interest in the 14 | // software to the public domain. We make this dedication for the benefit 15 | // of the public at large and to the detriment of our heirs and 16 | // successors. We intend this dedication to be an overt act of 17 | // relinquishment in perpetuity of all present and future rights 18 | // to this software under copyright law. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | // OTHER DEALINGS IN THE SOFTWARE. 27 | // 28 | // For more information, please refer to < http://unlicense.org/ > 29 | // 30 | function slider(opts) { 31 | let low = opts.low === undefined ? 0 : opts.low, 32 | high = opts.high === undefined ? low+100 : opts.high, 33 | x = opts.value === undefined ? (low + high)/2 : opts.value, 34 | format = opts.format === undefined ? x => x.toFixed(2) : opts.format, 35 | caption = opts.caption; 36 | let p = document.body.appendChild(document.createElement("div")), 37 | c = caption ? p.appendChild(document.createElement("div")) : null, 38 | d = p.appendChild(document.createElement("div")), 39 | t = d.appendChild(document.createElement("div")), 40 | i = p.appendChild(document.createElement("input")); 41 | p.style.position = "relative"; 42 | p.style.background = opts.background === undefined ? "#EEE" : opts.background; 43 | p.style.display = "inline-block"; 44 | p.style.margin = "8px"; 45 | p.style.padding = "8px"; 46 | p.style.boxShadow = "inset 1px 1px 1px rgba(0, 0, 0, 0.25)"; 47 | p.style.borderRadius = "4px"; 48 | p.style.textAlign = "center"; 49 | if (caption) c.textContent = caption; 50 | 51 | i.style.width = "60px"; 52 | i.style.display = "inline-block"; 53 | i.style.textAlign = "center"; 54 | i.style.marginLeft = "4px"; 55 | i.style.verticalAlign = "middle"; 56 | 57 | d.style.display = "inline-block"; 58 | d.style.width = "120px"; 59 | d.style.height = "4px"; 60 | d.style.borderRadius = "2px"; 61 | d.style.marginTop = "15px"; 62 | d.style.marginBottom = "15px"; 63 | d.style.background = "#888"; 64 | d.style.verticalAlign = "middle"; 65 | d.style.position = "relative"; 66 | 67 | t.style.display = "inline-block"; 68 | t.style.width = "12px"; 69 | t.style.height = "20px"; 70 | t.style.border = "solid 1px #888"; 71 | t.style.background = "#FFF"; 72 | t.style.borderRadius = "3px"; 73 | t.style.boxShadow = "2px 2px 2px rgba(0, 0, 0, 0.25)"; 74 | t.style.position = "absolute"; 75 | function update() { 76 | t.style.left = (d.offsetWidth - t.offsetWidth) * (x - low) / (high - low) + "px"; 77 | t.style.top = (d.offsetHeight - t.offsetHeight) / 2 + "px"; 78 | } 79 | 80 | function changed() { 81 | var evt = document.createEvent("HTMLEvents"); 82 | evt.initEvent("change", false, true); 83 | i.value = format(x); 84 | p.dispatchEvent(evt); 85 | update(); 86 | } 87 | 88 | i.value = format(x); 89 | i.onchange = event => { 90 | event.preventDefault(); 91 | event.stopPropagation(); 92 | x = Math.max(low, Math.min(high, +i.value)); 93 | changed(); 94 | }; 95 | update(); 96 | t.onmousedown = event => { 97 | event.preventDefault(); 98 | event.stopPropagation(); 99 | i.focus(); 100 | let ox = event.clientX, k = (high - low) / (d.offsetWidth - t.offsetWidth); 101 | function mm(event) { 102 | event.preventDefault(); 103 | event.stopPropagation(); 104 | x = Math.max(low, Math.min(high, x + (event.clientX - ox) * k)); 105 | ox = event.clientX; 106 | changed(); 107 | } 108 | function mu(event) { 109 | event.preventDefault(); 110 | event.stopPropagation(); 111 | document.removeEventListener("mousemove", mm); 112 | document.removeEventListener("mouseup", mu); 113 | } 114 | document.addEventListener("mousemove", mm); 115 | document.addEventListener("mouseup", mu); 116 | }; 117 | function norec(f) { 118 | let cf = false; 119 | return function(...args) { 120 | let res = undefined; 121 | if (!cf) { 122 | cf = true; 123 | res = f(...args); 124 | cf = false; 125 | } 126 | return res; 127 | }; 128 | } 129 | Object.defineProperty(p, "value", { 130 | get() { return x; }, 131 | set: norec(v => { 132 | x = Math.max(low, Math.min(high, +v)); 133 | changed(); 134 | }) 135 | }); 136 | Object.defineProperty(p, "low", { 137 | get() { return low; }, 138 | set: norec(v => { low = v; p.value = x; }) 139 | }); 140 | Object.defineProperty(p, "high", { 141 | get() { return high; }, 142 | set: norec(v => { high = v; p.value = x; }) 143 | }); 144 | let focused = false; 145 | i.onfocus = () => focused = true; 146 | i.onblur = () => focused = false; 147 | p.onwheel = event => { 148 | if (focused) { 149 | event.preventDefault(); 150 | event.stopPropagation(); 151 | p.value = x + event.deltaY*[0.01, 0.1, 0.25][event.deltaMode]/20*(high-low); 152 | } 153 | }; 154 | return p; 155 | } 156 | --------------------------------------------------------------------------------