Is there a way to trigger mouseup when leaving the document body? - javascript

I found some code and I made a jsfillde with it. I need to know how to trigger mouseup in the function below, when you leave document body (in the fiddle example it's like dragging the object into HTML section for instance and leave the mouse click there).
function handleMouseMove(e) {
if (canMove) {
var left = getMousePosX(e);
var top = getMousePosY(e);
var newLeft = ($(elemToMove).css('left').toDecNum() + (left - lastPosX));
var newTop = ($(elemToMove).css('top').toDecNum() + (top - lastPosY));
$(elemToMove).css('left', newLeft);
$(elemToMove).css('top', newTop);
lastPosX = left;
lastPosY = top;
}
return false;
}
Thanks for any suggestion.

You can use
document.onmouseout = handleMouseUp;
This says that when the mouse leaves the document object, the handleMouseUp handler should be called.
Updated fiddle:
http://jsfiddle.net/vp14utt1/1/
-
P.S. for event handlers that simply take the event as an argument, you can just use the function name without wrapping it.
document.onmousedown = function (e) { handleMouseDown(e); };
document.onmousedown = handleMouseDown;

$(elemToMove).trigger('mouseup');
Should do it.

Add this line (new Fiddle):
document.onmouseleave = function (e) { handleMouseUp(e); };
This fires your 'mouse up' logic when the mouse is dragged off the browser window.
To quote The difference between mouseout() and mouseleave():
The mouseout event triggers when the mouse pointer leaves any child elements as well the selected element.
The mouseleave event is only triggered when the mouse pointer leaves the selected element.
I think you want the later.

Related

How do I reference and manipulate a targeted object from a called function outside the function's scope?

I am trying to create a program (chess) such that div elements created via JS dom can be dragged with your cursor. However I have it setup so I add an event listener to each piece created which calls a function adding an event listener to the window which then calls the function to move each piece. I can't reference "this" since the target of the movement function is the window and not the piece with the "mousedown" event. Can I reference the intended target from a completely different function?
I'd tried to do var targetedPiece=this.targetedPiece in the "mouseDown" function
Followed by targetedPiece.style.left=cursor.x+'px' in the "movePiece" function but to no avail.
//Basic chess board creation, creating elements with DOM
var board = document.getElementById('gameBoard');
var newSquare = document.createElement('div');
var newPiece = document.createElement('div');
newPiece.addEventListener('mousedown', mouseDown, false);
newSquare.appendChild(newPiece);
board.appendChild(newSquare);
//Assigns cursor position to cursor.x & cursor.y respectively
function getCursorPos(e) {
let cursor = {
x: e.pageX - board.offsetLeft,
y: e.pageY - board.offsetTop
};
}
//Registers last mouseup/mousedown actions
function mouseDown(targetedPiece) {
window.addEventListener('mousemove', movePiece, true);
//This is the function I'm calling with the piece
}
function mouseUp() {
window.removeEventListener('mousemove', movePiece, true);
}
//Function for actually moving pieces with cursor
function movePiece() {
//What do I put here? The targeted piece calls mouseDown, can I reference it in this function?
//The idea is targetedPiece.style.left=cursor.x & targetedPiece.style.top=cursor.y
}
board.addEventListener('mousemove', getCursorPos, true);
window.addEventListener('mouseup', mouseUp, false);
<div id='gameBoard'></div>

Always suppress a click event after drag in d3

Decoupling of click and drag events is discussed in some previous questions here, e.g. this one
Typically, it is recommended to use if (d3.event.defaultPrevented === false) {...} in the click handler. However, this doesn't seem to work (at least in some browsers) if mouseup and mousedown are not in the same element. Consider this jsfiddle (code below). Here is the behavior I want: click anywhere in SVG triggers click event (rectangle flashes), drag anywhere in SVG drags the rectangle. Observed behavior (Chrome 33): if the mousedown of the click is inside the rectangle and mouseup is outside, both the drag and click events trigger. If both mousedown and mouseup are inside or both are outside, click event is not triggered.
Can someone explain why the click event is triggered if mouseup and mousedown are not in the same element, and how to reliably prevent this from happening?
var container, rect, dragBehavior;
svg = d3.select('svg').attr("width", 500).attr("height", 300);
container = svg.append('g');
rect = container.append('rect').attr('width', 100).attr('height', 100);
dragBehavior = d3.behavior.drag()
.on('dragend', onDragStart)
.on('drag', onDrag)
.on('dragend', onDragEnd);
svg.call(dragBehavior).on('click', onClick);
function flashRect() { rect.attr('fill', 'red').transition().attr('fill', 'black'); }
function onDragStart() { console.log('onDragStart'); }
function onDrag() {
console.log('onDrag');
var x = (d3.event.sourceEvent.pageX - 50);
container.attr('transform', 'translate(' + x + ')');
}
function onDragEnd() { console.log('onDragEnd'); }
function onClick(d) {
if (d3.event.defaultPrevented === false) {
console.log('onClick');
flashRect();
} else {
console.log("default prevented");
}
}
Add dragBehavior to the rectangle instead of the whole svg element.
Here is the fiddle link with the fix http://jsfiddle.net/Mn4Uk/27/
rect
.call(dragBehavior)
.on('click', onClick);

JointJS - Mouse click event triggers cell position change event

I need to define mouse click event for my each cell. I used cell:pointerup event; but this event is triggered when I change positions of cells too. How can I differentiate these 2 events?
Thanks in advance.
What you can do is to create a custom element view and distinct click from dragging by checking whether a pointermove event was triggered between pointerdown and pointerup events.
var ClickableView = joint.dia.ElementView.extend({
pointerdown: function () {
this._click = true;
joint.dia.ElementView.prototype.pointerdown.apply(this, arguments);
},
pointermove: function () {
this._click = false;
joint.dia.ElementView.prototype.pointermove.apply(this, arguments);
},
pointerup: function (evt, x, y) {
if (this._click) {
// triggers an event on the paper and the element itself
this.notify('cell:click', evt, x, y);
} else {
joint.dia.ElementView.prototype.pointerup.apply(this, arguments);
}
}
});
And then tell the joint.dia.Paper to use the view.
var paper = new joint.dia.Paper({
// el, width, height etc.
elementView: ClickableView
});
A fiddle can be found here.

Differentiate between focus event triggered by keyboard/mouse

I'm using jquery ui autocomplete and want to decipher between focus events triggered by keyboard interaction and mouse interaction. How would I go about this?
$('input').autocomplete({
source: function(request, response) {
...
},
focus: function(event, ui) {
// If focus triggered by keyboard interaction
alert('do something');
// If focus event triggered by mouse interaction
alert('do something else');
}
});
Thanks
The only way I can think of doing this is to have a handler listen in on the keypress and click events, and toggle a boolean flag on/off. Then on the focus handler of your input, you can just check what the value of your flag is, and go from there.
Probably something like
var isClick;
$(document).bind('click', function() { isClick = true; })
.bind('keypress', function() { isClick = false; })
;
var focusHandler = function () {
if (isClick) {
// clicky!
} else {
// tabby!
}
}
$('input').focus(function() {
// we set a small timeout to let the click / keypress event to trigger
// and update our boolean
setTimeout(focusHandler,100);
});
Whipped up a small working prototype on jsFiddle (don't you just love this site?). Check it out if you want.
Of course, this is all running off a focus event on an <input>, but the focus handler on the autocomplete works in the same way.
The setTimeout will introduce a bit of lag, but at 100ms, it might be negligible, based on your needs.
You should actually be able to determine this from the event-Object that is passed into the focus-event. Depending on your code structure this might be different, but there is usually a property called originalEvent in there, which might be nested to some depth. Examine the event-object more closely to determine the correct syntax. Then test on mousenter or keydown via regular expression. Something like this:
focus: function(event, ui){
if(/^key/.test(event.originalEvent.originalEvent.type)){
//code for keydown
}else{
//code for mouseenter and any other event
}
}
The easiest and most elegant way I've found of achieving this is to use the "What Input?" library. It's tiny (~2K minified), and gives you access to the event type both in scripts:
if (whatInput.ask() === 'mouse') {
// do something
}
...and also (via a single data attribute that it adds to the document body) styles:
[data-whatinput="mouse"] :focus,
[data-whatinput="touch"] :focus {
// focus styles for mouse and touch only
}
I particularly like the fact that where you just want a different visual behaviour for mouse / keyboard it makes it possible to do that in the stylesheet (where it really belongs) rather than via some hacky bit of event-checking Javascript (though of course if you do need to do something that's not just purely visual, the former approach lets you handle it in Javascript instead).
The first thing that comes to mind is that you can find the position of the mouse and check to see if its within the position of the element
Use this to store the position of the element:
var input = $('#your_autocompleted_element_id'),
offset = input.offset(),
input_x = offset.top,
input_y = offset.left,
input_w = input.outerWidth(),
input_h = input.outerHeight();
Then use this to find absolute position of the mouse within the window:
var cur_mx, cur_my;
$(document).mousemove(function(e){
cur_mx = e.pageX;
cur_my = e.pageY;
});
Then in your autcomplete setup:
focus: function(event, ui) {
// mouse is doing the focus when...
// mouse x is greater than input x and less than input x + input width
// and y is greater than input y and less than input y + input height
if (cur_mx >= input_x && cur_mx <= input_x + input_w && cur_my >= input_y && cur_my <= input_y + input_h) {
// do your silly mouse focus witchcraft here
} else {
// keyboard time!
}
}
This can be handled using mousedown event, see my example below.
this.focusFrom = 'keyboard' =>
onFocus = () => {
if (this.focusFrom === 'keyboard') {
// do something when focus from keyboard
}
}
handleMouseDown = () => {
this.focusFrom = 'mouse';
}
handleOnClick = () => {
this.focusFrom = 'keyboard';
}

Is it possible to trigger Mouseevents by a divcontainer?

I have an div Element with the ID mypointer, wich has an absolute position. I animate this div on a page with jquery. The goal is a presentation where the elements show the same reaktion on the div element like the mousepointer. So I want to simulate mouseover, click and rightclick events.
Is that possible? Can someone give me an example which show me how to do that?
Thank you for your answers
Lara
P.S.
Example here
link text
the red square is over an h1 element. Is it possible to execute the h1 mouseover event, when there is a collision of the mypointer and an h1 element?
I'm not quite sure if I get you well, but to 'simulate' events like mouseover et cetera, you can always use jQuery's .trigger() in a form like:
$('#my_div_id').trigger('mouseover');
You can also call a more 'detailed' version, where you can specify the events arguments
$('#my_div_id').trigger({
type: 'keypress',
which: 13,
ctrlKey: true
});
which infact would simulate a return key while ctrl key is pressed to 'my_div_id'. If you just need the event handler code to execute, use .triggerHandler().
Maybe i don't understand your idea completely, but i wrote some code.
It works very simple. We bind two events "click mouseover" on #mypointer and also on h1 (or any other selector). When the event fires on #mypointer we check every h1 element to match it's position with position of #mypointer and if match -- trigger the event on matched element.
"use strict";
/*global $*/
function getElementCoordinates(el) {
return {
left: el.offsetLeft,
right: el.offsetLeft + el.offsetWidth,
top: el.offsetTop,
bottom: el.offsetTop + el.offsetHeight
};
}
function checkIntersection($el) {
var pointer = getElementCoordinates($('#mypointer')[0]);
var element = getElementCoordinates($el[0]);
if ((pointer.left >= element.left && pointer.left = element.left && pointer.right = element.bottom && pointer.bottom = element.bottom && pointer.top
$(function () {
$('#mypointer').live('click mouseover', function (e) {
//here write selectors you want to check for collision
$('h1').each(function () {
if (checkIntersection($(this))) {
$(this).trigger(e.type);
return false;
}
});
});
$('h1').live('click mouseover', function (e) {
$("#output").html(e.type + ' fired on ' + e.target.nodeName);
});
});
Sorry, parser "eat" checkIntersection function, so full code available on http://www.everfall.com/paste/id.php?263utdc1nmqy
wbr,
Roman.

Categories

Resources