i wanna make event when i click on element and move cursor to another element then release cursor.
i made it using mouseup and mousedown events.
but some time mouseup not work!!!
the cursor change to hand and cant release it on another element.
for(var i=0;i<20;i++) {
for(var j=0;j<20;j++) {
var circle = document.createElement("div");
circle.setAttribute("class","circle");
circle.setAttribute("id",20*(i-1)+j);
circle.setAttribute("style","left:"+(35*(j+1)+20*j)+"px;top:"+(10*(i+1)+20*i)+"px;");
circle.addEventListener("mouseup",function() { ...});
circle.addEventListener("mousedown",function() { ...});
body.appendChild(circle);
}
}
If you mousedown and then mousemove away from the element, the mouseup event never fires.
Try adding preventDefault() to your mousedown handler...
circle.addEventListener("mousedown",function(e) { e.preventDefault(); ... });
You may also try binding the mouseleave event to trigger the mouseup
Related
There is a rect on mousedown mouseup click event . but when I click the rect mouseup Event dosen`t trigger https://jsfiddle.net/f0vbc94s/
there is my code:
var rect=d3.select(".text").append("rect")
.attr("width",1000).attr("height",1000)
.style("fill","#00ff00");
rect.on("click",function(){
d3.event.preventDefault
d3.select(this).style("fill","#000000")
})
.on("mousedown",function(){
d3.select(this).style("fill","#ff0000")
}).on("mouseup",function(){
d3.event.preventDefault;
d3.select(this).style("fill","#00ff00")
})
Your click event is overwriting the mouseup event. When you click
and hold the mouse at down position, mousedown event fires and
changed the color. When you release the mouse, mouseup event fired,
changed the color and then click event fired immediately and changed
the color. So you couldn't recognise it.
If you comment the click event, you can see the mouseup event fired.
Try this,
var rect=d3.select(".text").append("rect")
.attr("width",1000).attr("height",1000)
.style("fill","#00ff00");
//rect.on("click",function(){
//d3.event.preventDefault
//d3.select(this).style("fill","#000000")
//})
rect.on("mousedown",function(){
d3.select(this).style("fill","#ff0000")
}).on("mouseup",function(){
d3.event.preventDefault;
d3.select(this).style("fill","#00ff00")
})
Is there a way to do.
$("#controlId").suspendEvents();
$("#controlId").resumeEvents();
I'm aware of preventDefault and stopPropagation. I want to do from outside the event.
Please consider the following in your answer.
I cannot modify these bound events.
I do not know the bound events (Although it will be possible it will take me long time to do it). so it is not possible to .off() and then add them back one by one.
I was able to put together answers from 2 other questions.
1.Bind an event handler to front of the queue
2.Attach handler to all events in a control
The idea is to bind an event handler with e.stopImmediatePropagation to front of the queue for all events. It seems crude i would be glad if this can be improved.
The solution...
$.fn.preBind = function (type, data, fn) {
this.each(function () {
var $this = $(this);
$this.bind(type, data, fn);
$.each(type.split(/ +/), function () {
var currentBindings = $this.data('events')[this];
if ($.isArray(currentBindings)) {
currentBindings.unshift(currentBindings.pop());
}
});
});
return this;
};
$.fn.suspendEvents = function () {
this.preBind("click keydown keyup keypress mouseover mouseenter mouseout mouseleave mousedown mouseup mousemove change blur focus focusin focusout scroll resize load unload beforeunload", null, blockEvents);
}
$.fn.resumeEvents = function () {
var _this = this;
$.each("click keydown keyup keypress mouseover mouseenter mouseout mouseleave mousedown mouseup mousemove change blur focus focusin focusout scroll resize load unload beforeunload".split(/ +/), function () {
_this.unbind(this, blockEvents);
});
}
function blockEvents(e) {
e.stopImmediatePropagation();
}
Now i could use
$("#controlId").suspendEvents();
$("#controlId").resumeEvents();
EDIT: Modified resumeEvents() to overcome IE issue.
everything bubbles up, so catch any event in body and prevent them.
alternative
var myCtlrs = $("all i want").attr("disabled", disabled");
then
myCtlrs.removeAttr("disabled");
I'm trying to create a file drag/drop handler (drag a file into the browser window, to be used for upload).
For some reason when I bind the drag/drop listener to $("body") instead of to a $("div") in the body the events fire several times in a row, sometimes even non-stop (seemingly looping). What could be causing this?
Here's a trimmed down version of the code: http://jsfiddle.net/WxMwK/9/
var over = false;
$("body")
.on("dragover", function(e){
e.preventDefault();
if (! over) {
over = true;
$("ul").append($("<li/>").text("dragover"));
}
})
.on("dragleave", function(e){
e.preventDefault();
if (over) {
over = false;
$("ul").append($("<li/>").text("dragleave"));
}
})
.on("drop", function(e){
e.preventDefault();
if (over) {
over = false;
$("ul").append($("<li/>").text("drop"));
}
});
To test: drag a file into the orange area, you'll see the event firing multiple times in a row.
The anon is (mostly) correct. To put it simply: when the mouse moves over the edge of an element inside your drop target, you get a dropenter for the element under the cursor and a dropleave for the element that was under the cursor previously. This happens for absolutely any descendant.
You can't check the element associated with dragleave, because if you move the mouse from your drop target onto a child element, you'll get a dropenter for the child and then a dropleave for the target! It's kind of ridiculous and I don't see how this is a useful design at all.
Here's a crappy jQuery-based solution I came up with some time ago.
var $drop_target = $(document.body);
var within_enter = false;
$drop_target.bind('dragenter', function(evt) {
// Default behavior is to deny a drop, so this will allow it
evt.preventDefault();
within_enter = true;
setTimeout(function() { within_enter = false; }, 0);
// This is the part that makes the drop area light up
$(this).addClass('js-dropzone');
});
$drop_target.bind('dragover', function(evt) {
// Same as above
evt.preventDefault();
});
$drop_target.bind('dragleave', function(evt) {
if (! within_enter) {
// And this makes it un-light-up :)
$(this).removeClass('js-dropzone');
}
within_enter = false;
});
// Handle the actual drop effect
$drop_target.bind('drop', function(evt) {
// Be sure to reset your state down here
$(this).removeClass('js-dropzone');
within_enter = false;
evt.preventDefault();
do_whatever(evt.originalEvent.dataTransfer.files);
});
The trick relies on two facts:
When you move the mouse from a grandchild into a child, both dragenter and dragleave will be queued up for the target element—in that order.
The dragenter and dragleave are queued together.
So here's what happens.
In the dragenter event, I set some shared variable to indicate that the drag movement hasn't finished resolving yet.
I use setTimeout with a delay of zero to immediately change that variable back.
But! Because the two events are queued at the exact same time, the browser won't run any scheduled functions until both events have finished resolving. So the next thing that happens is dragleave's event handler.
If dragleave sees that it was paired with a dragenter on the same target element, that means the mouse must have moved from some descendant to some other descendant. Otherwise, the mouse is actually leaving the target element.
Then the setTimeout finally resolves zero seconds later, setting back the variable before another event can come along.
I can't think of a simpler approach.
You are adding a listener on the BODY HTMLElement for the dragover, dragleave and drop.
When you continue to drag over the DIV, there is a dragleave that is fired because the mouse is no more dragging over the BODY, but over the DIV.
Secondly, as you are not stopping the bubble event on the DIV (no listener is set), the dragover fired on the DIV is bubling to the BODY.
If I resume:
The mouse enter the body (in dragover)
--> fire drag over (body)
The mouse enter the DIV in the body
--> fire drag leave (of BODY)
--> fire drag over (of DIV) --> event bubling --> fire drag over (of BODY)
There is a similar problem with mouseover and mouseout, which is fixed by using mouseenter and mouseleave.
May be you can try the same code using dragenter event type. If its not working, you can check if the event.target is the BODY. This test could help to skip undesired drag event.
Good luck
var over = false;
$("body")
.on("dragover", function(e){
e.preventDefault();
if (! over) {
over = true;
$("ul").append($("<li/>").text("dragover"));
}
})
.on("dragleave", function(e){
e.preventDefault();
if (over) {
over = false;
$("ul").append($("<li/>").text("dragleave"));
}
})
.on("drop", function(e){
e.preventDefault();
if (over) {
over = false;
}
});
Or you could just use stop(); to stop animation buildup
See this jsfiddle:
http://jsfiddle.net/CB87X/6/
Click and hold the button, drag off the button and release. As you can see, the mouseup event never fires if the mouse is not over the element when the mouse button is released. Thus, the styling in my example never changes back to its original. How do you fire the mouseup event if the mouse button is released when not over the clicked element?
Edit1: BTW I have looked at several solutions on this site, implemented them, and the mouseup event still did not fire.
The mouseup event is relative to where the pointer is and this is expected behaviour. If you want your button to style properly, bind the mouseleave event as well.
This should do the trick. If you left click on the button (.but) and drag off, you can mouseup anywhere on the page and still fire the click event. If you mouseleave the page 'body' and mouseup, the binded mouseleave event is unbinded.
$('.but').mousedown( function(e) {
if (e.which == 1) {
var $this = $(this);
$this.bind('mouseleave', function(){
$('body').one('mouseup', function() {
$this.click();
});
});
$this.mouseup(function() {
$(this).unbind('mouseleave');
});
}
});
Forked your exemple to provide a working example:
http://jsfiddle.net/67Rrs/2/
Once the button is mousedowned, an event is bound to the next mouseup, wherever it happens, that resets the style.
Just use $(document).on('mouseup dragend', somefunc);
I have got a problem with a slider. When i grab the handler, i change the .src of the image, just to change its color. However, i want it to change back to the original color when i release the mouse button. I have tried two things.
1) Changing it back on the handler mouseup event: this works only if i release the button over the handler, so this is not a solution.
2)Changin it back on the window mouseup event: the event is not firing properly. If i click and release on any place of the window, the event fires normaly, but if i click in the handler, move the cursor to any other point of the window, and then release the button, the event will not fire.
Btw, im using the prototype js framework.
Solutions? Thanks
Here is the code. I load the handler function when the document is ready.
function handler()
{
var handler = $('handler');
Event.observe(window, "mouseup", function(){
alert('salta'); //to see when mouseup fires
if(handler.src=='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png'){ //orange
handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper.png';} //grey
});
Event.observe(handler,'mousedown',function(){handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png';}); //orange
}
You should be attaching the mouseup handler to the document object.
How about onmouseout event?
Here is the code. I load the handler function when the document is ready.
function handler()
{
var handler = $('handler');
Event.observe(window, "mouseup", function(){
alert('salta'); //to see when mouseup fires
if(handler.src=='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png'){ //orange
handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper.png';} //grey
});
Event.observe(handler,'mousedown',function(){handler.src='http://localhost/moodle/blocks/videoavatar/eggface/trunk/gripper_o.png';}); //orange
}