在JavaScript中,我可以防止触发onmouseup事件,用我自己的事件代替吗?
In JavaScript, can I prevent the onmouseup event from being triggered, replacing it with my own event?
我正在创建一个滑块小部件来管理值的范围,并完成其中的大部分。
这是一个演示:https://jsfiddle.net/d1wqb63a/
我想将其设置为在释放鼠标时实际触发 onmouseup 事件,其中包含其他数据。这是有效的,只是它现在触发了两次 onmouseup。一次直接通过浏览器,一次通过我的代码。
您可以在上面的 jsfiddle 演示中看到这一点。当正常事件调用时,控制台的输出是“未定义的”,而当我调用时,控制台输出一些实际数据,因为它正在尝试访问我添加的自定义信息。
这是我触发事件的方法:
var e = new Event('mouseup');
e.sliderValues = JSON.parse(JSON.stringify(config.values));
element.dispatchEvent(e);
我不知道如何禁用已经触发的事件;即,尽管我添加了 onmouseup 回调,但阻止浏览器触发实际的 onmouseup 事件。这甚至可行吗?
无论您在何处拦截本机鼠标弹起事件,您都可以接受原始事件作为处理程序的参数,然后调用 originalEvent.preventDefault()
-- and possibly originalEvent.stopPropagation()
。 preventDefault()
将阻止执行原始事件的正常操作,stopPropagation()
将阻止向上或向下冒泡到任何其他处理程序。
whateverElement.onmouseup = function (originalEvent) {
originalEvent.preventDefault();
originalEvent.stopPropagation();
// create and dispatch your custom event here
}
Alexander上面的回答一般来说是最好的。
虽然看了你的代码,我认为有一个更精确的解决方案。
解决方案
尝试将您想要的值保存到滑块元素中。
然后将 mouseup 函数附加到 sildebar 元素本身而不是文档。无需激活新事件,如下所示:
// 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));
}
你的工作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>
注意:此 fiddle 记录 [对象对象],因为它不支持 JSON。我把它复制到你的 fiddle 并且它工作正常。
我正在创建一个滑块小部件来管理值的范围,并完成其中的大部分。
这是一个演示:https://jsfiddle.net/d1wqb63a/
我想将其设置为在释放鼠标时实际触发 onmouseup 事件,其中包含其他数据。这是有效的,只是它现在触发了两次 onmouseup。一次直接通过浏览器,一次通过我的代码。
您可以在上面的 jsfiddle 演示中看到这一点。当正常事件调用时,控制台的输出是“未定义的”,而当我调用时,控制台输出一些实际数据,因为它正在尝试访问我添加的自定义信息。
这是我触发事件的方法:
var e = new Event('mouseup');
e.sliderValues = JSON.parse(JSON.stringify(config.values));
element.dispatchEvent(e);
我不知道如何禁用已经触发的事件;即,尽管我添加了 onmouseup 回调,但阻止浏览器触发实际的 onmouseup 事件。这甚至可行吗?
无论您在何处拦截本机鼠标弹起事件,您都可以接受原始事件作为处理程序的参数,然后调用 originalEvent.preventDefault()
-- and possibly originalEvent.stopPropagation()
。 preventDefault()
将阻止执行原始事件的正常操作,stopPropagation()
将阻止向上或向下冒泡到任何其他处理程序。
whateverElement.onmouseup = function (originalEvent) {
originalEvent.preventDefault();
originalEvent.stopPropagation();
// create and dispatch your custom event here
}
Alexander上面的回答一般来说是最好的。
虽然看了你的代码,我认为有一个更精确的解决方案。
解决方案
尝试将您想要的值保存到滑块元素中。 然后将 mouseup 函数附加到 sildebar 元素本身而不是文档。无需激活新事件,如下所示:
// 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));
}
你的工作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>