Hello, noUiSlider!
noUiSlider is an MIT-licensed Javascript range-slider library with touch support. With it, you can create attractive and easy-to-style range sliders with multiple inputs, tooltips, and scales / pips. To use it in Observable, you may import (or copy-and-paste) the following cell:
noUiSlider = { if (!document.getElementById('nouislider-css')) { const href = await require.resolve("nouislider@12.1.0/distribute/nouislider.min.css"); document.head.appendChild(html`<link id='nouislider-css' href=${href} rel=stylesheet>`); } return await require('nouislider@12.1.0/distribute/nouislider.min.js'); }
Sliders from this library integrate fairly well with Observable's views. Here I create a div element with Observable's html tagged template literal and then attach a noUiSlider object to it. Then I update the value of the cell and dispatch an 'input' event when the slider's value changes.
viewof slider = { const slider = html`<div id=slider style='max-width:550px; margin:0 auto;'>`; noUiSlider.create(slider, { start: [20, 80], behaviour: 'drag', connect: true, tooltips: true, range: { 'min': 0, 'max': 100 } }); // This fires immediately when bound, so we don't need to assign slider.value separately on initialization. slider.noUiSlider.on('update', (e) => { slider.value = slider.noUiSlider.get(); slider.dispatchEvent(new CustomEvent('input')); }) return slider; }
slider
// Some CSS to auto-hide the tooltips, see https://refreshless.com/nouislider/examples/#section-hiding-tooltips html`<style> .noUi-tooltip { display: none; } .noUi-active .noUi-tooltip { display: block; } `
Note how the value is an array with one element for each handle on the slider. Here are two more examples from the website with minimal changes to get them to run in single Observable cells (outside of styling). Much more is possible, see the noUiSlider docs for more examples and info!
Colorpicker
viewof colorpicker = { const div = html`<div id="colorpicker"> <div class="sliders" id="red"></div> <div class="sliders" id="green"></div> <div class="sliders" id="blue"></div> <div id="result"></div>`; const resultElement = div.lastChild; const sliders = Array.from(div.childNodes).filter(d => d.className === 'sliders'); let colors = [0, 0, 0]; [].slice.call(sliders).forEach(function (slider, index) { noUiSlider.create(slider, { start: 127, connect: [true, false], orientation: "vertical", range: { 'min': 0, 'max': 255 }, }); }); [].slice.call(sliders).forEach(function (slider, index) { // Bind the color changing function to the update event. slider.noUiSlider.on('update', function () { colors[index] = slider.noUiSlider.get(); const color = 'rgb(' + colors.join(',') + ')'; resultElement.style.background = color; resultElement.style.color = color; div.value = Array.from(sliders).map(el => el.noUiSlider.get()); div.dispatchEvent(new CustomEvent('input')); }); }); return div; }
colorpicker
colorpickerStyles = html`<style> #red, #green, #blue { margin: 10px; display: inline-block; height: 200px; } #colorpicker { height: 240px; width: 310px; margin: 0 auto; padding: 10px; border: 1px solid #BFBFBF; } #result { margin: 60px 26px; height: 100px; width: 100px; display: inline-block; vertical-align: top; color: rgb(127, 127, 127); background: rgb(127, 127, 127); border: 1px solid #fff; box-shadow: 0 0 10px; } #red .noUi-connect { background: #c0392b; } #green .noUi-connect { background: #27ae60; } #blue .noUi-connect { background: #2980b9; } </style>`
Colored Connect Elements
viewof coloredconnect = { const slider = html`<div id=slider-color>`; noUiSlider.create(slider, { start: [4000, 8000, 12000, 16000], connect: [false, true, true, true, true], range: { 'min': [2000], 'max': [20000] } }); const connect = slider.querySelectorAll('.noUi-connect'); const classes = ['c-1-color', 'c-2-color', 'c-3-color', 'c-4-color', 'c-5-color']; for (var i = 0; i < connect.length; i++) { connect[i].classList.add(classes[i]); } slider.noUiSlider.on('update', (e) => { slider.value = slider.noUiSlider.get(); slider.dispatchEvent(new CustomEvent('input')); }) return slider; }
coloredconnect
coloredconnectStyles = html`<style> .c-1-color { background: red; } .c-2-color { background: yellow; } .c-3-color { background: green; } .c-4-color { background: blue; } .c-5-color { background: purple; } </style>`