I have a program at this fiddle where sometimes the mouseup
event doesn't trigger. I tried everything I could do to prevent dragging, by putting draggable="false"
on every element, by calling e.preventDefault()
in my mousedown function, and adding a dragend
event listener. However, the dragend
event doesn't trigger and mouseup still fails to trigger. Any help would be appreciated.
Asked
Active
Viewed 1,446 times
1

Aplet123
- 33,825
- 1
- 29
- 55
-
the mouseup event is definitely triggering, you can see this if you add a console.log statement to your mouse up event listener (this habit will make debugging far easier than the method in your fiddle). The dragend event only triggers when an element is defined as draggable. – bryan60 Sep 01 '17 at 14:02
-
I can replicate the issue when I click on the grey space between tiles the mouse up event does not trigger. – Alessi 42 Sep 01 '17 at 14:04
-
The mouse up event is definitely triggering on every mouse up. The problem lies elsewhere in the code. – bryan60 Sep 01 '17 at 14:04
-
FYI you should get rid of all the drag event related stuff in this code. The drag and drop api has specific purposes, mostly data transfer via a drag and drop interface, which is not what you're after here. – bryan60 Sep 01 '17 at 14:08
-
The problem seems to be that something in the toggleMove() is silently failing and causing the mouseup event to not fire on clicks between tiles. if you comment out toggleMove() in the tileClick() function then it always fires. – bryan60 Sep 01 '17 at 14:22
2 Answers
1
Not sure why clicking between tiles causes the mouseup to not fire, but you can solve this by moving the mouseup funcion into it's own function and adding to the window and setting it to the event listener:
function mouseUp() {
console.log('mouse up');
mouseDown = false;
mode = "add";
}
document.body.addEventListener("mouseup", mouseUp);
window.mouseUp = mouseUp;
and then adding it to the tile's onmouseup event:
onmouseup: 'mouseUp()',

bryan60
- 28,215
- 4
- 48
- 65
1
The issue lies with appending to the innerHTML, mysvg.innerHTML +=
will (as discused here) remove the event listeners in document stopping your mouse up event firing.
By replacing mysvg.innerHTML +=
with mysvg.insertAdjacentHTML('beforeend',
in your setMoveOnBoard function you can preserve mouse up event listener, as insertAdjacentHTML() does not destroy the DOM tree.
Example:
function makeSVGTag(tagName, properties) {
var keys = Object.keys(properties);
var ret = "<" + tagName;
for (var i = 0; i < keys.length; i++) {
ret += " " + keys[i] + '="' + properties[keys[i]] + '"';
}
ret += "/>";
return ret;
}
function makeSVGTagContent(tagName, properties, content) {
var keys = Object.keys(properties);
var ret = "<" + tagName;
for (var i = 0; i < keys.length; i++) {
ret += " " + keys[i] + '="' + properties[keys[i]] + '"';
}
ret += ">" + content.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</" + tagName + ">";
return ret;
}
function setMoveOnBoard(color1, color2, color3, color4, symbol1, symbol2, x, y) {
mysvg.insertAdjacentHTML('beforeend', makeSVGTag("rect", {
height: 10,
width: 10,
stroke: color2,
"stroke-width": 2,
x: Number(x) + 3,
y: Number(y) + 3,
fill: color1,
class: "move move-display",
"data-index": (Number(y) / 16) * 15 + Number(x) / 16,
draggable: false
}));
mysvg.insertAdjacentHTML('beforeend', makeSVGTagContent("text", {
x: Number(x) + 4,
y: Number(y) + 10,
"font-family": "Verdana",
"font-size": 10,
stroke: "none",
fill: color3,
class: "move-symbol move-symbol1 move-display",
"data-index": (Number(y) / 16) * 15 + Number(x) / 16,
draggable: false
}, symbol1));
mysvg.insertAdjacentHTML('beforeend', makeSVGTagContent("text", {
x: Number(x) + 4,
y: Number(y) + 10,
"font-family": "Verdana",
"font-size": 10,
stroke: "none",
fill: color4,
class: "move-symbol move-symbol2 move-display",
"data-index": (Number(y) / 16) * 15 + Number(x) / 16,
draggable: false
}, symbol2));
}
var config = {
color1: "#f00",
color2: "#000",
color3: "#0f0",
color4: "#00f",
symbol1: ">",
symbol2: "<"
};
var mode = "add";
function toggleMove(i) {
if (getMove(i)[0]) {
mode = "remove";
getMove(i)[0].remove();
getMove(i)[1].remove();
getMove(i)[2].remove();
} else {
mode = "add";
setMoveOnBoard(config.color1, config.color2, config.color3, config.color4, config.symbol1, config.symbol2, mysvg.children[i].getAttribute("x"), mysvg.children[i].getAttribute("y"));
}
}
function changeMove(i) {
if (mode == "add") {
setMoveOnBoard(config.color1, config.color2, config.color3, config.color4, config.symbol1, config.symbol2, mysvg.children[i].getAttribute("x"), mysvg.children[i].getAttribute("y"));
} else {
if (typeof getMove(i)[0].remove == "function") {
getMove(i)[0].remove();
}
if (typeof getMove(i)[1].remove == "function") {
getMove(i)[1].remove();
}
if (typeof getMove(i)[2].remove == "function") {
getMove(i)[2].remove();
}
}
}
var mouseDown = false;
document.body.addEventListener("mouseup", function() {
mouseDown = false;
mode = "add";
});
document.body.addEventListener("dragend", function() {
mouseDown = false;
mode = "add";
});
function getMove(index) {
var ret = [, , ];
var moveList = mysvg.getElementsByClassName("move");
for (var i = 0; i < moveList.length; i++) {
if (moveList[i].getAttribute("data-index") == index) {
ret[0] = moveList[i];
}
}
moveList = mysvg.getElementsByClassName("move-symbol1");
for (var i = 0; i < moveList.length; i++) {
if (moveList[i].getAttribute("data-index") == index) {
ret[1] = moveList[i];
}
}
moveList = mysvg.getElementsByClassName("move-symbol2");
for (var i = 0; i < moveList.length; i++) {
if (moveList[i].getAttribute("data-index") == index) {
ret[2] = moveList[i];
}
}
return ret;
}
function tileClick(i, e) {
e.preventDefault();
mouseDown = true;
if (i != 112) {
toggleMove(i);
}
}
function tileDrag(i, e) {
if (mouseDown && i != 112) {
changeMove(i);
}
}
window.tileClick = tileClick;
window.tileDrag = tileDrag;
for (var i = 0; i < 225; i++) {
mysvg.innerHTML += makeSVGTag("rect", {
height: 16,
width: 16,
stroke: "#888",
"stroke-width": 1,
x: (i % 15) * 16,
y: Math.floor(i / 15) * 16,
fill: i % 2 ? "#eee" : "#fff",
onmousedown: 'tileClick(' + i + ', event)',
onmouseover: 'tileDrag(' + i + ', event)',
class: "tile",
"data-index": i,
draggable: false
});
}
mysvg.innerHTML += makeSVGTag("circle", {
cx: 120,
cy: 120,
r: 5,
class: "piece",
"data-index": 112,
draggable: false
});
text {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
<svg width="251" height="251" id="mysvg" style="padding-left:2px;padding-top:2px;" class="board" draggable="false">
</svg>
<p>
Console:
</p>
<textarea id="evalconsole"></textarea>
<button onclick="returnstatement.innerText=eval(evalconsole.value)">
Eval!
</button>
<p id="returnstatement"></p>
Hope this helps!

Alessi 42
- 1,112
- 11
- 26