0
votes

I am having issue with simple knockout Drag and Drop functions in Firefox browser.

Issue:

On "dragenter" and "dragleave" I am changing the text for inner side of div. It's working fine in all browsers except Firefox. The issue is when ever I over on changed text in "dragenter", it's automatically changing to "dragleave" state.

Please have a look below fiddle in all browsers with "dragenter" and "dragleave".

Fiddle

function ViewModel(){
    var self = this;
    this.dropZones = ko.observableArray([{
        'elements' : ko.observableArray([])  // just to see that the output is correct
    }]);

    this.dragover = function(e){
        console.log('dragOver');
        e.stopPropagation();
        e.preventDefault();
    }

    this.drop = function(e, data){
        console.log('drop');
        e.stopPropagation();
        e.preventDefault();
        var files = e.dataTransfer.files;
        for (var i = 0, f; f = files[i]; i++) {
            data.elements.push(f.name);
        }
        $('.drop_zone').css('background-color', '#ffffff');
        $('.drop_zone').removeClass('over');
        $('.drop_zone').text('Drop files here');
    }

    this.dragenter = function(e, index){
        console.log('dragEnter');
        $('.drop_zone').eq(index).css('background-color', '#00ff00');
        $('.drop_zone').eq(index).addClass('over');
         $('.drop_zone').text('Over on this text soome thing happened');
    }

    this.dragleave = function(e, index){
        console.log('end');
        $('.drop_zone').eq(index).css('background-color', '#ffffff');
                $('.drop_zone').eq(index).removeClass('over');
         $('.drop_zone').text('Drop files here');
    }
}

ko.applyBindings(new ViewModel());
.drop_zone {
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    padding:40px 25px;
    text-align: center;
    font: 20pt bold'Vollkorn';
    color: #bbb;
    height:300px;
    border:1px solid red;
}
.drop_zone.over{
    border: 1px dashed red;
    
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="col-md-12" data-bind="foreach: dropZones">
    <div class="drop_zone" data-bind="event:{
                dragover:   function(data, e){ $root.dragover(e);},
                drop:       function(data, e){ $root.drop(e, $data);},
                dragenter:  function(data, e){ $root.dragenter(e, $index());},
                dragleave:  function(data, e){ $root.dragleave(e, $index());}
            }">Drop files here</div>
    <ul data-bind="foreach: elements" style="height: 100px">
        <li data-bind="text: $data"></li>
    </ul>
</div>

Note: Just hover the changed text with drag enter Image. Then you will get to know what is happening.

enter image description here

1
Your changes to the DOM should be done by changing observables, not by direct manipulation via jQuery.Roy J

1 Answers

1
votes

There is a jQuery-based solution to the Firefox dragleave-when-entering-a-child issue here: How to detect the dragleave event in Firefox when dragging outside the window

I have made a version of your Fiddle that works in Firefox. The basic idea is that it keeps a count of enters minus leaves, and you're still in drag mode while that count > 0. I also got rid of the jQuery DOM-fiddling.

Most significant code bits are:

function dropZone() {
    var self = {
        'elements': ko.observableArray([]),
            'style': ko.observable(),
            'text': ko.observable('Drop files here'),
            'enteredCount': ko.observable(0)
        // just to see that the output is correct
    };
    self.isOver = ko.computed(function () {
        return self.enteredCount() > 0;
    });
    return self;
}

and

this.dragenter = function (data, e) {
    data.enteredCount(data.enteredCount() + 1);
    data.text('Over on this text some thing happened');
};

this.dragleave = function (data, e) {
    data.enteredCount(data.enteredCount() - 1);
    data.text('Drop files here');
};

http://jsfiddle.net/hgaow1pq/4/