I am using a drag and drop interface for a game I am developing. I am currently using jQuery draggable and droppable to manage my reverting, limitations, grid snap, etc, but I also want to make make it such that if a user right clicks while dragging, the game piece rotates but does not stop dragging. However, the right click of the mouse automatically ends the drag event, even if I put an event listener with event.stopPropagation()
and event.preventDefault()
on right click. Any ideas how to achieve this?
I have a half working snippet here, where a right click does rotate the game piece but causes the drag to stop. Note that copying it from my source messed with some of the scaling and offsetting but functionality for this demos's purpose is still intact.
var board = function(parentDIV, size, options = {}) {
this.ship = this.ship.bind(this);
this.flip = this.flip.bind(this);
this.update = this.update.bind(this);
this.ajaxExport = this.ajaxExport.bind(this);
this.scale = this.scale.bind(this);
this.size = size / 10;
this.callback = {
onvalid: options.onvalid,
oninvalid: options.oninvalid,
ondrag: options.ondrag,
onstart: options.onstart,
ondrop: options.ondrop
};
this.containerDIV = $("<div>").css({"position": "relative", "padding": "-1px"}).attr("id", "board-container");
this.boardDIV = $("<div>").css({"display": "table", "border-collapse": "collapse"}).on("contextmenu", function() { event.stopPropagation; event.preventDefault(); });
var rowDIV = $("<div>").css({"display": "table-row"});
var cellDIV = $("<div>").css({"display": "table-cell", "border": "2px #000 solid", "padding": "-1px", "width": this.size.toString() + "px", "height": this.size.toString() + "px"})
for(var i = 0; i < 10; i++) {
var cloneRow = rowDIV.clone();
for(var ii = 0; ii < 10; ii++) cloneRow.append(cellDIV.clone());
this.boardDIV.append(cloneRow);
}
this.ships = [
this.ship("carrier", 1, 5, 1, 1),
this.ship("battleship", 4, 1, 4, 3),
this.ship("cruiser", 1, 3, 8, 6),
this.ship("submarine", 3, 1, 2, 8),
this.ship("destroyer", 1, 2, 0, 8)
];
this.containerDIV.append(this.boardDIV);
$(parentDIV).append(this.containerDIV);
this.update();
};
board.prototype.update = function() {
this.layout = [
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0]
];
for(var i = 0; i < this.ships.length; i++) {
var width = depx(this.ships[i].css("width")) / this.size;
var height = depx(this.ships[i].css("height")) / this.size;
var left = depx(this.ships[i].css("left")) / this.size;
var top = depx(this.ships[i].css("top")) / this.size;
if(width == 1) for(var ii = top; ii < top + height; ii++) this.layout[ii][left] = i + 1;
if(height == 1) for(var ii = left; ii < left + width; ii++) this.layout[top][ii] = i + 1;
}
var pattern = new RegExp(/(?=^[^1]*(?:1,1,1,1,1|1\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+1\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+1\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+1\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+[^1]\D+1)[^1]*$)(?=^[^2]*(?:2,2,2,2|2\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+2\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+2\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+[^2]\D+2)[^2]*$)(?=^[^3]*(?:3,3,3|3\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+3\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+[^3]\D+3)[^3]*$)(?=^[^4]*(?:4,4,4|4\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+4\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+[^4]\D+4)[^4]*$)(?=^[^5]*(?:5,5|5\D+[^5]\D+[^5]\D+[^5]\D+[^5]\D+[^5]\D+[^5]\D+[^5]\D+[^5]\D+[^5]\D+5)[^5]*$)^\[\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\],\[[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5],[0-5]\]\]$/);
if(pattern.test(JSON.stringify(this.layout))) if(this.callback.onvalid) this.callback.onvalid();
else if(this.callback.oninvalid) this.callback.oninvalid();
function depx(str) {
return Number(str.substring(0, str.length - 2));
}
};
board.prototype.ajaxExport = function() {
var inputs = {
type: "uploadGameBoard",
game: null,
board: this.layout
};
AJAXrequest("GET", inputs, function(response) {
if(response == "success") {
}
});
};
board.prototype.random = function() {
};
board.prototype.default = function() {
};
board.prototype.scale = function() {
console.log(this.containerDIV.parent());
};
board.prototype.set = function() {
};
board.prototype.ship = function(name, width, height, left, top) {
return $("<div>")
.attr("id", name)
.addClass("ship")
.draggable({
containment: "parent",
preventCollision: true,
grid: [this.size, this.size],
cursor: "none",
start: function() { },
stop: this.update,
drag: this.validate })
.css({
"position": "absolute",
"width": (width * this.size).toString() + "px",
"height": (height * this.size).toString() + "px",
"background-color": "#000",
"top": (top * this.size).toString() + "px",
"left": (left * this.size).toString() + "px"})
.on("contextmenu", function() { event.stopPropagation(); event.preventDefault(); })
.on("mousedown", this.flip)
.appendTo(this.boardDIV);
};
board.prototype.validate = function() {
};
board.prototype.flip = function() {
if(event.which == 3) {
var ship = $(event.target);
var width = ship.css("height");
var height = ship.css("width");
var left = ship.css("left");
var top = ship.css("top");
ship.css({"width": width, "height": height});
var offsetx = depx(width) + depx(left);
var offsety = depx(height) + depx(top);
var size = this.size * 10;
if(offsetx > size) ship.css("left", String(size - depx(width)) + "px");
else if(offsety > size) ship.css("top", String(size - depx(height)) + "px");
this.update();
}
function depx(str) {
return Number(str.substring(0, str.length - 2));
}
};
board.prototype.disable = function() {
for(var i = 0; i < this.ships.length; i++) this.ships[i].draggable( "option", "disabled", true );
};
board.prototype.enable = function() {
for(var i = 0; i < this.ships.length; i++) this.ships[i].draggable( "option", "enable", true );
};
window.onload = function() {new board(document.body, 500); };
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
body {
margin 0;
}
</style>
</head>
<body>
</body>
</html>