JavaScript + Chrome - Event capture - javascript

I am trying to figure out how events are working. I have this piece of code:
document.captureEvents(Event.MOUSEMOVE);
document.onmousemove = mousePos;
document.onkeypress = keyPressed;
var keyStroke = 0;
var mouseX = 0;
var mouseY = 0;
function mousePos(e) {
console.log(e);
mouseX = e.pageX;
mouseY = e.pageY;
document.formex.mousex.value = mouseX;
document.formex.mousey.value = mouseY;
return true;
}
function keyPressed(e) {
console.log(e);
keyClicked = e.key;
document.formex.keypress.value = keyStroke;
return true;
}
What confuses me - inside of keyPressed function console.log(e) yields KeyboardEvent, inside of mousePos(e) it yields MouseEvent. I can't tell how the differentiation between these two 'e' happens?

What confuses me - inside of keyPressed function console.log(e) yields KeyboardEvent, inside of mousePos(e) it yields MouseEvent. I can't tell how the differentiation between these two 'e' happens?
The browser creates event objects and fires them at the document elements. When the event relates to the keyboard, the browser creates a KeyboardEvent. When it relates to the mouse, it fires a MouseEvent. If it relates to something else, it will create and fire a different kind of event.
The "differentiation" is based on what caused the event to be fired: A keyboard action or a mouse action.

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.

Global variable between event handlers

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;
});

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);
});

Please explain what this code means

I'm going through the tutorial at the address: http://www.stanford.edu/~ouster/cgi-bin/cs142-spring12/lecture.php?topic=event.
And I don't understand about code at the lines that I have marked with asterisks.
function Dragger(id) {
this.isMouseDown = false;
this.element = document.getElementById(id);
var obj = this;
this.element.onmousedown = function(event) {
obj.mouseDown(event);
}
}
Dragger.prototype.mouseDown = function(event) {
var obj = this;
this.oldMoveHandler = document.body.onmousemove; /******/
document.body.onmousemove = function(event) { /******/
obj.mouseMove(event);
}
this.oldUpHandler = document.body.onmouseup; /******/
document.body.onmouseup = function(event) { /******/
obj.mouseUp(event);
}
this.oldX = event.clientX;
this.oldY = event.clientY;
this.isMouseDown = true;
}
Dragger.prototype.mouseMove = function(event) {
if (!this.isMouseDown) {
return;
}
this.element.style.left = (this.element.offsetLeft
+ (event.clientX - this.oldX)) + "px";
this.element.style.top = (this.element.offsetTop
+ (event.clientY - this.oldY)) + "px";
this.oldX = event.clientX;
this.oldY = event.clientY;
}
Dragger.prototype.mouseUp = function(event) {
this.isMouseDown = false;
document.body.onmousemove = this.oldMoveHandler; /******/
document.body.onmouseup = this.oldUpHandler; /******/
}
The purpose of the this.oldMoveHandler references are to store whatever event handlers a previous developer of the page may have added to "document.body.onmousemove", with the goal of not interrupting whatever behavior that developer no doubt spend painful hours to build. It goes like this:
Press down with the mouse, store the old handler, add our fancy dragging handler.
Move the mouse, lovely dragging behavior occurs.
Release the mouse, dragging behavior stops, restore old handler (even if it's null).
This is a way to stay out of the way of previous code, although it's a bad solution. The much preferred way is to use addEventListener/removeEventListener or attachEvent/detachEvent for barbaric IE browsers. These functions are designed so that multiple handlers can subscribe to the same event without stepping on each other. Here's some good reading:
http://www.quirksmode.org/js/introevents.html
Setting document.body.onmousemove is one (ugly) way to listen for mousemove events on the document.body element.
Therefore, this.oldMoveHandler = document.body.onmousemove; is simply storing a reference to the event handler function, if any.
Please note that using element.addEventListener is preferred for attaching event handlers.
As noted in the comments the use of intrusive event handling is very old fashioned and not recommended now.
However to answer your question the code is implementing drag and drop, when the mousedown event is triggered by a mouse press the current event handlers for mouseup and mouseover (first 4 lines of marked code) are "saved" and replaced by the event handlers that will perform the drag and drop.
When the dragged element is "dropped" i.e. the mouseup event fires, the mousemove and mouseup event handlers are replaced with the original event handlers that were saved (last 2 lines of marked code)

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
};

Categories