Global variable between event handlers - javascript

I have a map inside my canvas.
I want to drag this map using mouse pointer.
I set global variable dragMap to false at the beginning and
set it to true when the mouse is down and then set it back to false when it's up.
For dragging I check this global variable value inside handler for mousemove event and
if it's true, I redraw the map with offset.
Written above is what I want my code to do but it doesn't work. Inside the mousemove handler dragMap varialbe is always false. When I click and drad this map my console log shows:
true
14 false
The first "true" occures from mousedown handler, the "falses" - from mosemove event.
What am I doing wrong?
$(document).ready(function(){
var dragMap = false;
var startDragMapX;
var startDragMapY;
$("#myCanvas").mousedown(function(e){
dragMap = true;
startDragMapX = e.pageX;
startDragMapY = e.pageY;
console.log(dragMap);
//var x = e.pageX - this.offsetLeft;
//var y = e.pageY - this.offsetTop;
});
$("#myCanvas").mousemove(function(e){
console.log(dragMap);
if(dragMap) {
console.log(2);
oX = e.pageX-startDragMapX;
oY = e.pageY-startDragMapY;
draw(ctx,1,1,oX,oY);
}
});
$("#myCanvas").mousedown(function(){
dragMap = false;
});
});

You have used mousedown instead of mouseup in the third handler
$("#myCanvas").mouseup(function(){
dragMap = false;
});
So when the mousedown happens first the flag is set to true, then the second mousedown handler runs setting it to false so in mousemove handler you will have dragMap == false.
Also these variables are not Global variables(window scoped) they are closure scoped variables.

your binding mousedown two times,
change
$("#myCanvas").mousedown(function(){
dragMap = false;
});
to
$("#myCanvas").mouseup(function(){
dragMap = false;
});
so dragmap is false when mousebutton is released

$("#myCanvas").mousedown(function(){
dragMap = false;
});
at the end of code must be mouseup
$("#myCanvas").mouseup(function(){
dragMap = false;
});

Related

Why event listener persists after manual removal

All,
I try to build a resizer UI like this:
My code is like:
<span class="grabber" draggable="false" #mousedown="grab"></span>
grab: function(e) {
var initX = e.screenX;
var mousemove = function(e) {
var offset = e.screenX - initX
initX = e.screenX;
}
var cancel = function(e) {
$(document).off("mousemove")
$(document).off("mouseup")
}
$(document).on("mousemove", mousemove)
$(document).on("mouseup", cancel)
mousemove = null;
cancel = null;
}
Basic idea is: I attach that grab event handler to mousedown, inside which I listen to mousemove until mouseup, then I remove those two event handlers from document.
I am pretty new to Chrome Performance tool, so I just simply record some drag of that resizer, then mouseup and drag again.
The result is confused, especially the number of listener goes up like crazy(but there seems no memory leak). I wonder where did I do wrong?
So what is happening here:
<span class="grabber" draggable="false" #mousedown="grab"></span>
every time mousedown happens vue runs grab
The safer thing to do in this case is attach the events directly to e.target also setting your handler function to null in the cancel function.
grab: function(e) {
var initX = e.screenX;
var target = e.target;
var mousemove = function(e) {
var offset = e.screenX - initX
initX = e.screenX;
}
var cancel = function(e) {
$(target).off("mousemove")
$(target).off("mouseup")
mousemove = null;
cancel = null;
}
$(target).on("mousemove", mousemove)
$(target).on("mouseup", cancel)
}
Use a flag variable instead of adding and removing the handler.
var mouseIsDown = false;
$(document).on("mousedown", function() {
mouseIsDown = true;
});
$(document).on("mouseup", function() {
mouseIsDown = false;
})
$(document).on("mousemove", function() {
if (mouseIsDown) {
// do what you want
}
});
The mousedown handler could be attached to specific elements that you can grab, rather than document.

Javascript/jQuery focusout event that changes layout causes click event to not fire

I have a field that when you leave focus on it, it changes the layout of the page. I also have buttons on the page that submit my form.
If I go into my field and type a value, then click the button, the button click event never fires. This seems to happen because the layout is changing before the click event gets fired, which means the button changes places. By the time the click event fires, it's firing on an empty area, not the button.
Here is a jsfiddle of the issue: http://jsfiddle.net/xM88p/
I figured out a way to solve this for IE but after extensive research I can't find/access the same object in FF/Chrome:
//only works in IE
if(event.originalEvent.toElement){
$("#"+event.originalEvent.toElement.id).click();
}
http://jsfiddle.net/xM88p/2/
Use mousedown instead of click:
$("#btn_test").on('mousedown', function (event){
alert("clicked!");
});
$('#test').focusout(function (event){
$('<p>Test</p>').insertAfter(this);
});
Edit
Okay, I got a little more creative with the event handlers. The new solution keeps track of mousedown/mouseup events as well as the position of the click. It uses these values to check whether mouse up should execute an alert.
var testClicked = false;
var lastX, lastY;
$(document).on('mouseup', function (event) {
if (testClicked === true && lastX === event.clientX && lastY === event.clientY) {
alert("clicked!");
}
testClicked = false;
lastX = null;
lastY = null;
});
$("#btn_test").on('mousedown', function (event){
testClicked = true;
lastX = event.clientX;
lastY = event.clientY;
});
$('#test').focusout(function (event){
$('<p>Test</p>').insertAfter(this);
});

HTML5 Canvas : How to handle mousedown mouseup mouseclick

I been playing around with html5 canvas and ran into a problem.
canvas.onmousedown = function(e){
dragOffset.x = e.x - mainLayer.trans.x;
dragOffset.y = e.y - mainLayer.trans.y;
canvas.onmousemove = mouseMove;
}
canvas.onmouseup = function(e){
canvas.onmousemove = null;
}
canvas.onmouseclick = mouseClick;
function mouseMove(e){
mainLayer.trans.x = e.x - dragOffset.x;
mainLayer.trans.y = e.y - dragOffset.y;
return false;
}
function mouseClick(e){
// click action
}
In this code, I make my mouse click+drag pan the canvas view by translating by the drag offset. But I also have a click event. Right now, whenever I drag my mouse and let go, it runs both onmouseup AND onclick.
Are there any techniques to make them unique?
A click event happens after a successful mousedown and mouseup on an element. Is there any particular reason you are using click on top of the mouse events? You should be fine with just mousedown/mouseup, click is a convenience event that saves you a little bit of coding.
I would generally do it this way:
var mouseIsDown = false;
canvas.onmousedown = function(e){
dragOffset.x = e.x - mainLayer.trans.x;
dragOffset.y = e.y - mainLayer.trans.y;
mouseIsDown = true;
}
canvas.onmouseup = function(e){
if(mouseIsDown) mouseClick(e);
mouseIsDown = false;
}
canvas.onmousemove = function(e){
if(!mouseIsDown) return;
mainLayer.trans.x = e.x - dragOffset.x;
mainLayer.trans.y = e.y - dragOffset.y;
return false;
}
function mouseClick(e){
// click action
}
in the function mouse move set a boolean to say that a move occured, encompase all the code in mouseup and click with an if statement to check that a drag did not occur. After these if statements and before the end of the functions set the dragging boolean to false.
Try declaring a variable such as clickStatus = 0; and at the start of each function check to ensure the correct value.
if (clickstatus == 0) {
clickstatus =1;
...//function code
};

boolean function to know position of mousebutton

is it possible to check the state of the mousebutton (pressed or released). I know that this is the purpose of the eventhandling in jquery, but I wonder if it would be possible to do a function if the button of the mouse isn't pressed without the need of a change in position of the button (pressed to released or vice versa)?
Try below code, DEMO here
$(document).mousedown (function () {
$('#result').text('Pressed');
}).mouseup (function () {
$('#result').text('Released');
});
$(function () {
//setup flag for the state of the mouse button and create an object that converts an event type into a boolean for the flag
var mousePressed = false,
mouseConvert = {
mousedown : true,
mouseup : false
};
//bind to the document's mousedown and mouseup events to change the flag when necessary
$(document).on('mousedown mouseup', function (event) {
//set the flag to the new state of the mouse button
mousePressed = mouseConvert[event.type];
//if you only want to watch one mouse button and not all of them then
//you can create an if/then statement here that checks event.which
//and only updates the flag if it is the button you want, check-out Rob W.'s
//answer to see the different values for event.which with respect to the mouse
});
//now you can check the value of the `mousePressed` variable, if it is equal to `true` then the mouse is currently pressed
});
You can use the mousedown and mouseup event to detect changed mouse events. This event should be bound to window. Demo: http://jsfiddle.net/uwzbn/
var mouseState = (function(){
var mousestatus = 0;
$(window).mousedown(function(e) {
mousestatus = e.which;
}).mouseup(function(e){
mousestatus = 0;
});
return function() {
return mousestatus;
}
})();
This function returns four possible values:
0 Mouse released false
1 Left click true
2 Middle click true
3 Right click true
In a boolean context, the function return's value evaluates to false when the mouse is not down. When the mouse is pressed, you can read which mouse key is pressed (as a bonus).

How do I handle these events and why is my code not working?

I need to do the following. As soon as the user clicks on a div, i want to save the mouse coordinations while the user is moving the cursor over the div and is holding the left mouse button. When the user leaves the div or releases the left button, i want to stop recording the coordinates. I've got the following code:
$(document).ready(function() {
var coordhdl = new coordinateHandler();
$("#test").mousedown(function(e) {
$("#test").mousemove(function(ee) {
$("#test").mouseup(function(e) {
stopIt = true;
});
if(stopIt == false)
{
coordhdl.addCords(ee.pageX - this.offsetLeft, ee.pageY - this.offsetTop);
}
});
});
});
The problems with this code are:
It records coordinate even when the user only clicked the div without pressing the left button.
It doesn't stop recording the coordinates once it has been clicked.
I am new to Javascript/jQuery, so I don't know very much about it.
Something like this should work. It sets a flag to true/false when the mouse is pressed/released respectively. When the mouse moves, if the flag is set, the coordinates are added:
$(document).ready(function() {
var isDown = false,
coordhdl = new coordinateHandler();
$("#test").mousedown(function() {
isDown = true;
}).mouseup(function() {
isDown = false;
}).mousemove(function(e) {
if(isDown) {
coordhdl.addCords(ee.pageX - this.offsetLeft, ee.pageY - this.offsetTop);
}
});
});
Here's a demo of something similar in action (it simply writes the coordinates to a p element instead of using your coordinateHandler object).
Don't attach the event handlers inside the event handlers. On every mouse move you attach a new mouseup event handler. They don't get overridden, they get appended.
Use a "global" flag instead:
$(document).ready(function() {
var coordhdl = new coordinateHandler(),
recording = false;
$("#test").mousedown(function(e) {
recording = true;
}).mousemove(function(e) {
if(recording) {
coordhdl.addCords(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
}
}).mouseup(function(e) {
recording = false;
});
});
Every time there is a mousedown event, you add a mousemove handler, and every time the mouse moves, you add another mouseup handler. I can't see where the stopIt variable is declared so the scope of this variable may also be an issue. You don't need to nest the handlers, so try it this way.
$(document).ready(function() {
var coordhdl = new coordinateHandler();
var isRecording = false;
$("#test").mousedown(function(e) { isRecording = true })
.mouseup(function(e) { isRecording = false })
.mousemove(function(ee) {
if(isRecording)
{
coordhdl.addCords(ee.pageX - this.offsetLeft, ee.pageY - this.offsetTop);
}
});
});

Categories