17

It seems that an input element loses a lot of functionality when put into an element with draggable="true". This only seems to occur in firefox.

See my jsfiddle: http://jsfiddle.net/WC9Fe/3/

Html:

<div id="drag" draggable="true">
    Drag this div <br />
    <input id="message" type="text" />
</div>
<div id="drop">
    Drop area
</div>

JS:

$('#drag').on('dragstart', function(e){
    e.originalEvent.dataTransfer.setData('Text', $('#message').val());
    e.originalEvent.dataTransfer.effectAllowed = 'move';
});

var drop = $('#drop');
drop.on('dragover', function(e){
    e.preventDefault();
});
drop.on('dragenter', function(e){
    e.preventDefault();
});
drop.on('drop', function(e){
    alert('Target succesfully dropped: ' + e.originalEvent.dataTransfer.getData('Text'));
    e.preventDefault();
});

Now try to select text in the input using firefox. Seems impossible. Try the same in IE/Chrome. Seems to work just fine.

nicojs
  • 1,879
  • 2
  • 18
  • 34

5 Answers5

20

As far as I know this is a known bug in FF. A quick (and "dirty" workaround) would be to remove the draggable attribute on text input focus event, add it again on text input blur event, and disable text selection on #drag div to enable dragging once you clicked outside the focused input (clicking on #div directly).

Updated fiddle here.

Sample code:

JS:

$('#message')
    .on('focus', function(e) {
        $(this).closest('#drag').attr("draggable", false);
    })
    .on('blur', function(e) {
        $(this).closest('#drag').attr("draggable", true);
    });

CSS:

.disable-selection {
    /* event if these are not necessary, let's just add them */
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;

    /* this will add drag availability once you clicked the 
       #drag div while you're focusing #message div */
    -moz-user-select: none;
}

Hope it could help you.

gion_13
  • 41,171
  • 10
  • 96
  • 108
Nicolae Olariu
  • 2,487
  • 2
  • 18
  • 30
  • Thanks! A dirty workaround indeed... As for now: I removed the input element from the draggable zone, as I didn't achieve the desired effect in all browsers (IE8 was still a problem). Would you advice against using html5 drag and drop and use JQuery UI drag and drop instead? – nicojs Feb 12 '14 at 08:46
  • 1
    You can find more info by reading: [advantages of html5 drag and drop over jquery ui drag and drop](http://stackoverflow.com/questions/9524543/advantages-of-html-5-drag-and-drop-over-jquery-ui-drag-and-drop) and [html5 vs jquery ui drag and drop](http://stackoverflow.com/questions/6920741/html5-vs-jquery-drag-and-drop). If you need to target a wide range of browsers (legacy browsers also), if you don't want headaches and if you're short on time, I'd recommend using jQuery UI drag and drop. – Nicolae Olariu Feb 12 '14 at 10:54
10

See Firefox defect.

As an alternative, setting the draggable="false" on input focus event and replacing back to draggable="true" on input blur event works.

See jsfiddle for an example without any framework.

HTML:

<div draggable="true" id="draggableDiv">
    <textarea onfocus="onFocus();" onblur="onBlur();">Inside draggable (FIXED)</textarea>
</div>

JS:

onFocus= function(e) {
    document.getElementById("draggableDiv").setAttribute("draggable", "false");
}
onBlur= function(e) {
    document.getElementById("draggableDiv").setAttribute("draggable", "true");
}
user859740
  • 151
  • 2
  • 2
2

I used the onMouseEnter and onMouseLeave functions on the textarea to set the div draggable only when the mouse is outside the textarea.

I did this because I needed the focus to stay in the edit fields while dragging and dragging itself does not trigger a focus event.

JoeTron
  • 273
  • 2
  • 4
2

I have also found using onmouseenter and onmouseleave to toggle the draggable attribute works better because it places the cursor in the input box where you actually click. When using onfocus/onblur, the cursor always goes to the start or end of the text even if you click in the middle.

Stuart Welch
  • 409
  • 5
  • 3
1

If you are like me and come across this issue, and are using Sortable.js, you can use the filter option to specify elements that won't trigger dragging, and thus allow the input to operate normally.

JQuery:

$('#my-sortable').sortable({
    filter: ".my-text-input",   // Or whatever class you specify
    preventOnFilter: false      // Allow the input to operate normally
});

You can also find this information from the list of Sortable.js options found here: https://github.com/SortableJS/sortablejs

David Lowndes
  • 121
  • 1
  • 6