What steps will reproduce the problem?
In order to reproduce this issue, I've created a crude script that slightly
changes the Closure dragdrop demo to support subtargets. This can be done in
the following manner (with Google Chrome):
1. Open the dragdrop demo in
http://closure-library.googlecode.com/svn-history/r1801/trunk/closure/goog/demos
/dragdrop.html
2. Open the Javascript console in Chrome
3. Paste the following code:
list1.setSubtargetFunction(function(item, box, x, y) {
var height = box.bottom - box.top;
var subtarget = "bottom";
if ((box.top + height / 2) > y) {
subtarget = "top";
}
return subtarget;
});
newDragOver = function(e) {
if (window.previousDropTargetElement) {
window.previousDropTargetElement.style.marginTop = '0';
window.previousDropTargetElement.style.marginBottom = '0';
}
if (e.subtarget == "top") { e.dropTargetItem.element.style.background = 'red' } else { e.dropTargetItem.element.style.background = 'yellow'; }
window.previousDropTargetElement = e.dropTargetItem.element;
console.log("Reported subtarget: ", e.subtarget);
};
goog.events.listen(list1, 'dragover', newDragOver);
var testSubtargets = function() {
list1.items_[2].mouseDown_({type: goog.events.EventType.MOUSEDOWN, target:list1.items_[2].element, clientX: 90, clientY: 140, isMouseActionButton: function(){return true;}, preventDefault:function(){}})
list1.items_[2].mouseMove_({type: goog.events.EventType.MOUSEMOVE, clientX: 100, clientY: 140, isMouseActionButton: function(){return true;}, preventDefault:function(){}})
console.log("1st move, the item 1.3 should be draggable.");
dragger = list1.getDragger();
debugger;
dragger.handleMove_({type: goog.events.EventType.MOUSEMOVE, clientX: 100, clientY: 125, preventDefault:function(){}});
console.log("2nd move, should be on the 'bottom' subtarget of item 1.2 (bg should be yellow). Stored active sub target should be 'bottom', it currently is: ", list1.activeSubtarget_);
debugger;
dragger.handleMove_({type: goog.events.EventType.MOUSEMOVE, clientX: 100, clientY: 110, preventDefault:function(){}});
console.log("3rd move, should be on the 'bottom' subtarget of item 1.1 (bg should be yellow). Stored active sub target should be 'bottom', it currently is: ", list1.activeSubtarget_);
debugger;
dragger.handleMove_({type: goog.events.EventType.MOUSEMOVE, clientX: 100, clientY: 95, preventDefault:function(){}});
console.log("4th move, should be on the 'top' subtarget of item 1.1 (bg should be red). Stored active sub target should be 'top', it currently is: ", list1.activeSubtarget_);
console.log("!!! Note that in this move no dragover event was fired, even though the pointer moved from the bottom subtarget to the top subtarget in item 1.1");
debugger;
dragger.handleMove_({type: goog.events.EventType.MOUSEMOVE, clientX: 100, clientY: 110, preventDefault:function(){}});
console.log("5th move, should be on the 'bottom' subtarget of item 1.1 (bg should be yellow). Stored active sub target should be 'bottom', it currently is: ", list1.activeSubtarget_);
debugger;
dragger.handleMove_({type: goog.events.EventType.MOUSEMOVE, clientX: 100, clientY: 95, preventDefault:function(){}});
console.log("6th move, should be on the 'top' subtarget of item 1.1 (bg should be red). Stored active sub target should be 'top', it currently is: ", list1.activeSubtarget_);
}
What is the expected output? What do you see instead?
With the pasted code above, this is what should happen:
- When the pointer is on the "bottom" subtarget, the background on the target item should be set to yellow.
- When the pointer is on the "top" subtarget, the background on the target item should be set to red.
In order to see the bug in action, call the function testSubtargets(). It will
output the current result (along with the expected values) in the Javascript
console.
Note that the bug appears on the 4th move, when the pointer moves from the
"bottom" subtarget in item 1.1 to the "top" subtarget. This subtarget change is
not reported and the item background stays yellow instead of changing to red.
---
Although it's possible to reproduce solely by using the mouse, it's really hard
to do it reliably, because that depends on moving from the "bottom" subtarget
of the item 1.2 to the "bottom" subtarget of the item 1.1, without passing
through the "top" subtarget of the item 1.2. This requires a rapid and precise
movement, that's why I'm reproducing it programmatically.
What version of the product are you using? On what operating system?
Google Chrome on Mac OS X.
Please provide any additional information below.
Even though it's a slight bug (and it might seem rare), it may cause more
annoyances than expected on more complicated situations.
In my case I'm moving the target items up or down in order to create a blank
space indicating the position where the source item is going to fall.
When the user drags too quickly (which is common in the case of my app), more
than often the subtarget is erroneously reported and drawn on the screen (i.e.
the blank space is rendered on the wrong position), misleading the user.
Suggested fix:
In goog/fx/abstractdragdrop.js, change the line 633 from:
subtarget = this.subtargetFunction_(activeTarget.item_,
To:
this.activeSubtarget_ = subtarget = this.subtargetFunction_(activeTarget.item_,
This will update the active subtarget in the expected manner. Perhaps it will
not break any other app using this component. :-)
Original issue reported on code.google.com by alo.and on 2 May 2012 at 7:24
Original issue reported on code.google.com by
alo.and
on 2 May 2012 at 7:24