@@ -602,26 +602,41 @@ public function dragAndDrop($source, $target, $xOffset = null, $yOffset = null)
602
602
if ($ xOffset === null && $ yOffset === null ) {
603
603
parent ::dragAndDrop ($ source , $ target );
604
604
} else {
605
+ // Call dragAndDropBy() first
605
606
$ sNode = $ this ->matchFirstOrFail ($ this ->baseElement , $ source );
606
607
$ tNode = $ this ->matchFirstOrFail ($ this ->baseElement , $ target );
607
-
608
- $ sHeight = $ sNode ->getSize ()->getHeight ();
609
- $ sWidth = $ sNode ->getSize ()->getWidth ();
610
-
611
- $ travelX = intval ($ tNode ->getLocation ()->getX () - $ sNode ->getLocation ()->getX () + $ xOffset );
612
- $ travelY = intval ($ tNode ->getLocation ()->getY () - $ sNode ->getLocation ()->getY () + $ yOffset );
613
-
608
+ $ travelX1 = intval ($ tNode ->getLocation ()->getX ()-$ sNode ->getLocation ()->getX ()+$ xOffset );
609
+ $ travelY1 = intval ($ tNode ->getLocation ()->getY ()-$ sNode ->getLocation ()->getY ()+$ yOffset );
614
610
$ action = new WebDriverActions ($ this ->webDriver );
615
- if ($ travelX >= 0 && $ travelY >= 0 && $ travelX <= $ sWidth && $ travelY <= $ sHeight ) {
616
- // Move to the middle of the source element when target is inside the source boundary
617
- $ action ->moveToElement ($ sNode )->perform ();
618
- } else {
619
- // Move to the top left of the source element when target is outside the source boundary
620
- $ action ->moveToElement ($ sNode , -$ sWidth /2 , -$ sHeight /2 )->perform ();
611
+ $ action ->dragAndDropBy ($ sNode , $ travelX1 , $ travelY1 )->perform ();
612
+ $ this ->waitForPageLoad (20 );
613
+
614
+ try {
615
+ // Try drag and drop in steps if source and target elements didn't change at all
616
+ $ sNode2 = $ this ->matchFirstOrFail ($ this ->baseElement , $ source );
617
+ $ tNode2 = $ this ->matchFirstOrFail ($ this ->baseElement , $ target );
618
+ if ($ sNode2 == $ sNode && $ tNode2 == $ tNode ) {
619
+ $ sHeight = $ sNode2 ->getSize ()->getHeight ();
620
+ $ sWidth = $ sNode2 ->getSize ()->getWidth ();
621
+ // Because we will move to the middle of source element to perform drag & drop, we need to deduct
622
+ // an additional half of source element's width for X, and half of source element's height for Y
623
+ // when calculating the travel distance.
624
+ $ travelX2 = intval (
625
+ $ tNode2 ->getLocation ()->getX () - $ sNode2 ->getLocation ()->getX () - $ sWidth /2 + $ xOffset
626
+ );
627
+ $ travelY2 = intval (
628
+ $ tNode2 ->getLocation ()->getY () - $ sNode2 ->getLocation ()->getY () - $ sHeight /2 + $ yOffset
629
+ );
630
+ $ action = new WebDriverActions ($ this ->webDriver );
631
+ // Move to the middle of source element
632
+ $ action ->moveToElement ($ sNode2 )->perform ();
633
+ $ action ->clickAndHold ($ sNode2 )->perform ();
634
+ $ action ->moveByOffset ($ travelX2 , $ travelY2 )->perform ();
635
+ $ action ->release ()->perform ();
636
+ }
637
+ } catch (\Exception $ e ) {
638
+ // dragAndDropBy() is probably succeeded
621
639
}
622
- $ action ->clickAndHold ($ sNode )->perform ();
623
- $ action ->moveByOffset ($ travelX , $ travelY )->perform ();
624
- $ action ->release ()->perform ();
625
640
}
626
641
}
627
642
0 commit comments