I’m creating a slider widget to let me manage ranges of values, and have most of it complete.
Here is a demo of it: https://jsfiddle.net/d1wqb63a/
I want to set it up to actually trigger an onmouseup event when the mouse is released, with additional data in it. That is working, except that it is now triggers the onmouseup twice. Once directly by the browser and once by my code.
You can see that in the jsfiddle demo above. The output to the console is “undefined” when called by the normal event, and some actual data when called by mine, as it’s trying to access the custom info I added.
Here’s what I’m doing to trigger the event:
var e = new Event('mouseup'); e.sliderValues = JSON.parse(JSON.stringify(config.values)); element.dispatchEvent(e);
What I don’t know is how to disable the already triggered event; i.e, stop the browser from triggering the actual onmouseup event despite my adding the onmouseup callback. Is that even doable?
Advertisement
Answer
Alexander‘s answer above is the best generally speaking.
Though looking at your code I think that there is a more precise solution for you.
Solution
Try saving the values you want into the slider element. Then appending your mouseup function to the sildebar element itself instead of the document. Without the need to active a new event, like so:
// save your config sidler values to the element: // (inside your mousemove event) element.dataset.sliderValues = JSON.parse(JSON.stringify(config.values)); // then at the end of the code call it like so: let slideBar = document.getElementById('example'); slideBar.onmouseup = function(e){ console.log(JSON.stringify(slideBar.dataset.sliderValues)); }
Your working fiddle:
function buildSlider(element, config){ var boundingBox = element.getBoundingClientRect(); var n; // let's make sure all of the necessary parameters are in place var defaults = { min : 0, max : 100, step : 0, values : {i : 0}, reversible: false, bevel : true }; if(config == undefined) config = {}; for(n in defaults){ if(config[n] == undefined){ config[n] = defaults[n]; } } config.step = Math.abs(config.step); // <-- idiot proofing // now we can add style and events element.classList.add('slider'); for(idx in config.values){ var widget = document.createElement('div'); element.appendChild(widget); // center it vertically var halfHeight = boundingBox.height / 2; widget.style.marginTop = -(widget.getBoundingClientRect().height / 2) + 'px'; widget.style.top = halfHeight + 'px'; // initialize each handle (function(component, idx){ // set the initial position var xOffset = component.getBoundingClientRect().width >> 1; component.style.left = (boundingBox.width * (config.values[idx] - config.min) / (config.max - config.min) - xOffset) + 'px'; // add events component.onmousedown = function(){ document.onmousemove = function(e){ var x, value; x = e.clientX - boundingBox.left; // make sure we're within the range of the widget x = x < 0 ? 0 : (x > boundingBox.width ? boundingBox.width : x); value = x / boundingBox.width * (config.max - config.min) + config.min; if(config.step > 0){ // if we have a step value, snap to that value = Math.round(value / config.step) * config.step; x = boundingBox.width * (value - config.min) / (config.max - config.min); } config.values[idx] = value; component.style.left = (x - xOffset) + 'px'; // var e = new Event('change') // ### change 1 ##### element.dataset.sliderValues = JSON.parse(JSON.stringify(config.values)); } // ### document.onmouseup here was deleted } })(widget, idx); } } window.onload = function(){ buildSlider(document.getElementById('example'), {min: -50, max : 50, step : 5, values: {a : -25, b : 25}}) // ### change 2 ##### const sliderEl = document.getElementById('example') sliderEl.offsetWidth sliderEl.addEventListener('mouseup', function(){ document.onmousemove = null; console.log(JSON.stringify(sliderEl.dataset.sliderValues)); }) };
.slider{ border-radius: 1000cm; /* stupid css lacking an elegant way for dynamic circluar ends */ position: relative; border: 1px solid; /*box-shadow: rgb(0 0 0 / 50%) -2px -2px 2px 2px inset, rgb(255 255 255 / 60%) 2px 2px 2px 2px inset;*/ } .slider > div{ border: inherit; display:inline-block; position: absolute; background-color: inherit; border-radius: inherit; box-shadow: inherit; height: 5mm; width: 5mm; /* make it unselectable */ -moz-user-select: -moz-none; -khtml-user-select: none; -webkit-user-select: none; -o-user-select: none; user-select: none; }
<body style="padding: 2em"> <div> <div id="example" style="width: 10em; height: 1em; background-color:#FED; display: inline-block; margin-left:3cm"></div> </div> </body>