jQuery UI #6859 - Jquery.Simulate drag behaves incorrect when container scrolled

http://bugs.jqueryui.com/ticket/6859

by rdworth

HTML

<script src="https://github.com/jquery/jquery-ui/raw/1.8.9/tests/jquery.simulate.js">
</script>
<div style="height:200px"></div>

<div class="scr" style="height:200px">
    <div class="scr" style="height:180px">
        <div class="scr" style="height:160px">
            <div class="scr" style="height:140px">
                <div id="draggable">Drag me</div>
            </div>
        </div>
    </div>
</div>

<button id="simulateDrag">simulate drag</button>
<button id="fixSimulate">fix simulate</button>

<div id="g"></div>
<div id="r"></div>

<div style="width:4000px;height:4000px"></div>

CSS

.scr { width: 500px; overflow: scroll; margin-left: 200px; }
#draggable { width: 100px; height: 100px; background: gray; color: white; }
button { margin-left: 200px; margin-top: 2em; }
#g { width:3px;height:3px;background:green;position:absolute; }
#r { width:3px;height:3px;background:red;position:absolute; }

JavaScript

// Make the gray box draggable
$("#draggable").draggable();
        
// Show green and red markers on start and stop of drag
$("#draggable").mousedown(function(event) {
    $("#g").show().css({
        left: event.pageX, top: event.pageY
    });
    $("#r").hide();
});
$(document).mouseup(function(event) {
    $("#r").show().css({
        left: event.pageX, top: event.pageY
    });
});
$("#g, #r").hide();
    
// Scroll the document        
$(document)
    .scrollTop(100)
    .scrollLeft(100);

// Scroll the wrapper elements around the gray box
$(".scr")
    .scrollLeft(180);
    
// Simulate drag on button click
$("#simulateDrag").click(function() {
    $("#draggable").simulate("drag", { dx: 3, dy: 3 });
});

// Apply fix to simulate findCenter function
$("#fixSimulate").click(function() {
    $.simulate.prototype.findCenter = function(el) {
        var el = $(this.target),
            o = el.offset(),
            d = $(document);
        return {
            x: o.left + el.outerWidth() / 2 - d.scrollLeft(),
            y: o.top + el.outerHeight() / 2 - d.scrollTop()
        };
    }
});