Search code examples
javascripthtmldrag-and-drop

Prevent drag event to interfere with input elements in Firefox using HTML5 drag/drop


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.


Solution

  • 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.