I want to cancel an HTML5 drag operation based on some condition. I have tried to search this but found nothing useful. It seems that there is no way to cancel an HTML5 drag and drop using JavaScript. returning false in the dragstart doesn't seem to do anything. Any ideas?
You can cancel it by calling event.preventDefault() in the event handler.
For example this should work:
<p id="p1" draggable="true" ondragstart="dragstart_handler(event);">This element is draggable.</p>
<script>
var enableDragDrop = true;
function dragstart_handler(ev) {
if (!enableDragDrop) {
ev.preventDefault();
}
console.log("dragStart");
}
</script>
I think you need to do something tricky to make it work, for I do not know how to stop a drag from js, but you can fake a drag with mousedown,mousedown,mouseup and a isDragging flag
some code look like:
var isDragging = false
var fakeDraggingElement
var currentDragging
$('#item').mousedown(function(e){
e.preventDefault()
isDragging = true
currentDragging = this
//change your cursor and make it loos like dragging
$('#parent').css({cursor: 'move'})
//fake dragging element
fakeDraggingElement = $(this).clone().css({
opacity:0.5,
position:'absolute',
top:e.pageY+offsetY, //parent offset
left:e.pageX+offsetX,//parent offset
}).appendTo(parent)
}).mousemove(function(e){
if(!isDragging){
return
}
fakeDraggingElement.css({
top:e.pageY+offsetY, //parent offset
left:e.pageX+offsetX,//parent offset
})
}).mousedown(function(e){
if(!isDragging){
return
}
cancleDrag()
//your old drop
ondrop(currentDragging,e.target)
})
function cancleDrag(){
isDragging = false
$(currentDragging).remove()
currentDragging = undefined
}
EDIT:
got it. Its a bit roundabout, but works. Take advantage of the fact that the drag event is a cancellable mouse event, and cancelling it stops all further drag actions. Create a drag event on your condition and call preventDefault(). The following cancels it after 3 seconds:
setTimeout(function(){document.getElementById("drag").ondrag = function(e){
e.preventDefault();
this.ondrag = null;
return false;
};},3000);
Note first that I clear all ondrag events after it is cancelled, which you may need to adjust if you need other ondrag events, and second that this truly cancels all parts of the drag, so you don't get an ondragend event after, as shown in this jsfiddle:
http://jsfiddle.net/MaxPRafferty/aCkbR/
Source: HTML5 Spec: http://www.w3.org/html/wg/drafts/html/master/editing.html#dndevents
Related
Go to kitchensink, using middle button of mouse, try to click and hold the mouse on empty area of canvas and move the mouse.
The selection rectangle is displayed. How to disable this? I ask because, I have middle mouse button click and drag bound to canvas pan in previous version of fabric. Upgrading to new version, the canvas is behaving in unexpected manner.
I've tried to disable selection on the canvas on mouse down if the event.button == 1 by doing canvas.selectable = false; in mousedown and set it to true back in mouseup event handler.
That didn't work.
Any ideas how to disable the selection using middle mouse button click and drag?
The problem is that fabric recently enabled click for other button rather than left.
The point is that left is handled, right is handled, middle is not...
I guess the middle button follow the flow of the left button just because it is not the right one.
here a snippet from the mousedown handler function of fabric as at version 1.7.3 ( current as feb 2017 ).
__onMouseDown: function (e) {
var target = this.findTarget(e);
// if right click just fire events
var isRightClick = 'which' in e ? e.which === 3 : e.button === 2;
if (isRightClick) {
if (this.fireRightClick) {
this._handleEvent(e, 'down', target ? target : null);
}
return;
}
... continue normal flow ...
so this require a proper fix.
Posting a custom event as suggested is a patch, but normally this should not happen at all.
(since i m a mantainer for the project i m going to fix this)
Prasanth, your problem is simple. You have typo. Try to use like this:
canvas.selection = false;
Here is a code which you can try:
canvas.on('mouse:down',function(e){
canvas.selection = true;
});
canvas.on('mouse:down',function(e){
if( e.e.button == 1 ) {
canvas.selection = false;
};
});
I am trying to make it so that when a user clicks down, this happens.
In order,
Does something. (Not being specific, this isn't the important part.)
Mouse up is triggered.
Using: angular, html, css.
Not using: jQuery
Any suggestions?
Thanks!
You attach two event listeners, one while the user has the mouse pressed down mousedown. Once the user lets go the mouseup event is triggered. All mouse event listeners are passed an event object you can use to get information about the event ie: mouse x, and y positions.one of the methods available is event.preventDefault() this will stop the browser doing what it usually wants to do. Example: cmd/ctrl + s will cause the browser to save the html page. preventDefault will stop this.
document.addEventListener('mousedown' function (event) {
// Do something
})
document.addEventListener('mouseup', function (event) {
event.preventDefault()
})
To address OP comment:
var noMouseUp = true
document.addEventListener('mousedown', function () {
if (noMouseUp) {
// do something
noMouseUp = false
}
})
document.addEventListener('mouseup', function (event) {
if (!noMouseUp) {
noMouseUp = true
}
})
Use events.preventDefault(); in the mouseup callback.
Use, right after, event.stopPropagation(); to avoid the event passing to other layered elements.
bypassed_element.onclick = function(event){
event.preventDefault();
event.stopPropagation();
};
I am implementing drag'n'drop functionality on the page. The idea is that user can start dragging image from special place and drop it (release left mouse button) inside textarea, where special tag insertion will occur.
I have no issues with the dragging itself, the problem I got is that I can't determine position of the mouse inside textarea. I know x and y positions from mouseup event and I definetely know the mouse pointer is inside textarea, but can't determine at which position do I need to insert the required tag. Since the focus is not inside the textarea, selectionStart and selectionEnd properties are 0. Also, it is worth noticing that I prevent default behavior by returning false in mousemove handler - otherwise default behavior will put the image itself inside the textarea (which is extremely bad for base64 images).
Below is the code I currently have.
window.onPreviewItemMouseDown = function (e) {
var curTarget = $(e.currentTarget);
var container = curTarget.parent();
window.draggingImage = funcToGetId();
$(document).on("mousemove", window.onPreviewItemDragged);
$(document).on("mouseup", window.onPreviewItemDropped);
};
window.onPreviewItemDragged = function (e) {
return false;
};
window.onPreviewItemDropped = function (e) {
var target = $(e.target);
$(document).off("mousemove");
$(document).off("mouseup");
if (target[0].id === ID_TEXTAREA_TEXT) {
// here I need to get mouse pointer position inside the text somehow
}
return false;
};
Any help is appreciated.
In your case it would be easier to use native ondragstart event instead of a complex mousedown-move-up implementation, and manipulate the data to drop. Something like this:
document.getElementById('img').addEventListener('dragstart', function (e) {
e.dataTransfer.setData("text", '[img]' + this.id + '[/img]');
});
A live demo at jsFiddle. Or a delegated version. Notice that you can also delegate to the "special place" element, which might make the page running a little bit faster.
I'm currently stuck at the following problem:
I need to create a delay when dragover happens en then check if current dragover object is still the same. When it's the same object -> execute code.
This is my code:
var draggedId = null;
var triggered = false;
function allowDrop(ev) {
draggedId = ev.target.id;
setTimeout(function () {
if (draggedId == ev.target.id && ev.target.id != "" && !triggered) {
triggered = true;
draggedId = "";
ev.preventDefault();
}
}, 2000);
}
function drop(ev) {
ev.preventDefault();
}
function dragLeave(ev) {
draggedId == "";
triggered = false;
}
Allowdrop function is the dragover event.
ev.preventDefault() to allow the drop can't happen there because that function is assync.
Any idea's?
Thanks,
Mathias
Can you explain more about what you are trying to achieve and I can answer more fully ?
It's generally the case that you cannot always say for certain whether a drop will work, the best you can do is to setup drop zones on your page and have them cancel the dragover event based on what you can tell about the drop. If you want to make your application work with cross window dragging, then you cannot rely on a global variable to store information about what is being dragged, and you cannot actually see what is inside the drag - you can only know what kind of thing is being dragged. So if the drop might be acceptable you need to cancel the event. See this question
I think that maybe you are confused about how dragevents propagate which is the reason you think you need a timeout ? But blocking the event queue to figure out whether you accept a drop, or trying to cancel the drag event after it has already bubbled to the top and been handled in the default way by the browser (which is to not accept the drop) isn't going to work.
I want to detect whenever someone clicks in a div (essentially I want to know when a user is interacting with a section of text on my site, be that by selecting some text or clicking on a link), but I don't want to interfere with what the user is doing.
If I put a onmousedown or onclick event on the div it ends up breaking selection, links, etc. Is there any way to catch these events without causing any interference ?
Onmousedown or onclick shouldn't interfere with anything as long as it doesn't return false;.
You can do this:
document.getElementById("spy-on-me").onmousedown = function () {
console.log("User moused down");
return true; // Not needed, as long as you don't return false
};
If you have other scripts that are attaching behaviour via this method on the page, then to prevent overriding them you can do:
var spyElement = document.getElementById("spy-on-me");
var oldMousedown = spyElement.onmousedown;
spyElement.onmousedown = function () {
console.log("User moused down");
if(oldMousedown) oldMousedown();
};
Yes, I suspect you are currently returning false at the end of the event binding, just don't do that or any of the things in this binding:
$('a').click(function(e) {
e.stopPropagation();
e.preventDefault();
return false;
});
If you do not do any of these three things, jQuery will not stop the event from bubbling up to the browser.
Edit: Sorry didn't realise it was a plain JavaScript question.
you can use do it by adding a event listener as well
var myNode= document.querySelector('.imagegrid');
myNode.addEventListener("click",function(e){
alert(e.target+" clicked");
});
A similar example is demonstrated here
Can't you simply add a click event to the div?
<div id="secretDiv" (click)="secretDivClick()">
then on your component:
secretDivClick() {
console.log('clicked');
}