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 onm ouseup event when the mouse is released, with additional data in it. That is working, except that it is now triggers the onm ouseup 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 onm ouseup event despite my adding the onm ouseup callback. Is that even doable?
CodePudding user response:
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>
Note: this fiddle logs [object object] since it doesnt support JSON. I copied it to your fiddle and it works fine.
CodePudding user response:
Wherever it is that you are intercepting the native mouse up event you can accept the original event as an arg to the handler, and then call originalEvent.preventDefault()
-- and possibly originalEvent.stopPropagation()
. preventDefault()
will prevent the original event's normal action from being taken and stopPropagation()
will prevent from bubbling up or down to any other handlers.
whateverElement.onmouseup = function (originalEvent) {
originalEvent.preventDefault();
originalEvent.stopPropagation();
// create and dispatch your custom event here
}