diegoles / closure-library

Automatically exported from code.google.com/p/closure-library
0 stars 0 forks source link

goog.fx.AbstractDragDrop: issue with subtargets #461

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago

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