Question

Is it possible to make it so that clicking anywhere on a draggable, if if that means clicking on a child element such as an <input type="file"/>?

I've got a demo fiddle of what I mean here. Notice how if you click on the "Choose file" button, or the text that says "no file chosen", you cannot drag the element.

I want to be able to click anywhere on my draggable container and drag the element around, even if I click on the "Choose File" button. I can understand that the click event is firing on the button and probably not the draggable, but why does it work for the <label> below? I can click anywhere on the label's text and drag it around.

I also thought maybe changing the z-index of my draggable container to be higher than the child element so that maybe the click would register there, but that didn't change anything:

<div class="draggable">
    <input type="file" style="z-index:1"/>
</div>

.draggable{
    border: 1px solid black;
    z-index:2;
}

Is there some way I can set my draggable container to be a transparent overlay so that you always click that (and, therefore can drag)? I realize that this would make the <input type="file"/> read-only and ultimately unusable, but that is exactly what I need for this scenario.

Was it helpful?

Solution

You should dispatch event:

DEMO jsFiddle

$(".draggable").draggable();
$(".draggable input").on('mousedown', function (e) {
    var mdown = document.createEvent("MouseEvents");
    mdown.initMouseEvent("mousedown", false, true, window, 0, e.screenX, e.screenY, e.clientX, e.clientY, true, false, false, true, 0, null);
    $(this).closest('.draggable')[0].dispatchEvent(mdown);
});

For a more expected behaviour, see:

DEMO jsFiddle (complete)

$(".draggable").draggable({
    start: function( event, ui ) {
       $(this).data('preventBehaviour', true);
    }
});
$(".draggable input").on('mousedown', function (e) {
    var mdown = document.createEvent("MouseEvents");
    mdown.initMouseEvent("mousedown", false, true, window, 0, e.screenX, e.screenY, e.clientX, e.clientY, true, false, false, true, 0, null);
    $(this).closest('.draggable')[0].dispatchEvent(mdown);
}).on('click', function(e){
    var $draggable = $(this).closest('.draggable');
    if($draggable.data("preventBehaviour")){
        e.preventDefault();
        $draggable.data("preventBehaviour", false)
    }
});

EDIT following comment regarding jQuery UI sortable:

Let dispatched event bubble to the sortable container:

SORTABLE DEMO

mdown.initMouseEvent("mousedown", true, true, window, 0, e.screenX, e.screenY, e.clientX, e.clientY, true, false, false, true, 0, null);
$(this).closest('.item')[0].dispatchEvent(mdown);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top