-
-
Save florentbr/60ef7cb8d9b1ae690cafc82aad52da73 to your computer and use it in GitHub Desktop.
from selenium import webdriver | |
import time | |
# JavaScript: HTML5 Drag and drop script | |
# param1 (WebElement): Source element to drag | |
# param2 (WebElement): Optional - target element for the drop | |
# param3 (int): Optional - Drop offset x relative to the target if any or source element | |
# param4 (int): Optional - Drop offset y relative to the target if any or source element | |
# param4 (int): Optional - Delay in milliseconds (default = 1ms) for dragging and dropping | |
# param5 (string): Optional - Key pressed (alt or ctrl or shilf) | |
JS_DRAG_AND_DROP = "var t=arguments,e=t[0],n=t[1],i=t[2]||0,o=t[3]||0,r=t[4]||1,a=t[5]||'',s='alt'===a||'\ue00a'===a,l='ctrl'===a||'\ue009'===a,c='shift'===a||'\ue008'===a,u=e.ownerDocument,f=e.getBoundingClientRect(),g=n?n.getBoundingClientRect():f,p=f.left+f.width/2,d=f.top+f.height/2,h=g.left+(i||g.width/2),m=g.top+(o||g.height/2),v=u.elementFromPoint(p,d),y=u.elementFromPoint(h,m);if(!v||!y){var E=new Error('source or target element is not interactable');throw E.code=15,E}var _={constructor:DataTransfer,effectAllowed:null,dropEffect:null,types:[],files:Object.setPrototypeOf([],null),_items:Object.setPrototypeOf([],{add:function(t,e){this[this.length]={_data:''+t,kind:'string',type:e,getAsFile:function(){},getAsString:function(t){t(this._data)}},_.types.push(e)},remove:function(t){Array.prototype.splice.call(this,65535&t,1),_.types.splice(65535&t,1)},clear:function(t,e){this.length=0,_.types.length=0}}),setData:function(t,e){this.clearData(t),this._items.add(e,t)},getData:function(t){for(var e=this._items.length;e--&&this._items[e].type!==t;);return e>=0?this._items[e]._data:null},clearData:function(t){for(var e=this._items.length;e--&&this._items[e].type!==t;);this._items.remove(e)},setDragImage:function(t){}};function w(t,e,n,i){for(var o=0;o<e.length;++o){var r=u.createEvent('MouseEvent');r.initMouseEvent(e[o],!0,!0,u.defaultView,0,0,0,p,d,l,s,c,!1,0,null),t.dispatchEvent(r)}i&&setTimeout(i,n)}function D(t,e,n,i){var o=u.createEvent('DragEvent');o.initMouseEvent(e,!0,!0,u.defaultView,0,0,0,p,d,l,s,c,!1,0,null),Object.setPrototypeOf(o,null),o.dataTransfer=_,Object.setPrototypeOf(o,DragEvent.prototype),t.dispatchEvent(o),i&&setTimeout(i,n)}'items'in DataTransfer.prototype&&(_.items=_._items),w(v,['pointerdown','mousedown'],1,function(){for(var t=v;t&&!t.draggable;)t=t.parentElement;if(t&&t.contains(v)){var e=y.getBoundingClientRect();D(v,'dragstart',r,function(){var t=y.getBoundingClientRect();p=t.left+h-e.left,d=t.top+m-e.top,D(y,'dragenter',1,function(){D(y,'dragover',r,function(){D(u.elementFromPoint(p,d),'drop',1,function(){D(v,'dragend',1,function(){w(u.elementFromPoint(p,d),['mouseup','pointerup'])})})})})})}})" | |
def drag_and_drop(driver, source, target=None, offsetX=0, offsetY=0, delay=25, key=None) : | |
driver.execute_script(JS_DRAG_AND_DROP, source, target, offsetX, offsetY, delay, key) | |
time.sleep(delay * 2 / 1000) | |
driver = webdriver.Chrome() | |
driver.get("http://react-dnd.github.io/react-dnd/examples-dustbin-copy-or-move.html") | |
# drag and drop Glass | |
source = driver.find_element_by_xpath("//*[not(./*)][normalize-space()='Glass']") | |
target = driver.find_element_by_xpath("//*[text()[contains(.,'Works with any drop effect')]]") | |
drag_and_drop(driver, source, target) | |
# drag and drop Banana with alt key pressed | |
source = driver.find_element_by_xpath("//*[not(./*)][normalize-space()='Banana']") | |
target = driver.find_element_by_xpath("//*[text()[contains(.,'Works with copy drop effect')]]") | |
drag_and_drop(driver, source, target, key='alt') | |
# drag and drop Paper by offset | |
source = driver.find_element_by_xpath("//*[not(./*)][normalize-space()='Paper']") | |
drag_and_drop(driver, source, offsetX=250, offsetY=-100) | |
var args = arguments, | |
elemSrc = args[0], | |
elemDst = args[1], | |
offsetX = args[2] || 0, | |
offsetY = args[3] || 0, | |
delay = args[4] || 1, | |
key = args[5] || '', | |
alt = key === 'alt' || key === '\uE00A', | |
ctrl = key === 'ctrl' || key === '\uE009', | |
shift = key === 'shift' || key === '\uE008', | |
doc = elemSrc.ownerDocument, | |
box1 = elemSrc.getBoundingClientRect(), | |
box2 = elemDst ? elemDst.getBoundingClientRect() : box1, | |
x = box1.left + (box1.width / 2), | |
y = box1.top + (box1.height / 2), | |
x2 = box2.left + (offsetX ? offsetX : box2.width / 2), | |
y2 = box2.top + (offsetY ? offsetY : box2.height / 2), | |
source = doc.elementFromPoint(x, y), | |
target = doc.elementFromPoint(x2, y2); | |
if (!source || !target) { | |
var ex = new Error('source or target element is not interactable'); | |
ex.code = 15; | |
throw ex; | |
} | |
var dataTransfer = { | |
constructor : DataTransfer, | |
effectAllowed : null, | |
dropEffect : null, | |
types : [ ], | |
files : Object.setPrototypeOf([], null), | |
_items : Object.setPrototypeOf([], { | |
add : function add(data, type) { | |
this[this.length] = { | |
_data : '' + data, | |
kind : 'string', | |
type : type, | |
getAsFile : function () { }, | |
getAsString : function (callback) { callback(this._data) } | |
}; | |
dataTransfer.types.push(type); | |
}, | |
remove : function remove(i) { | |
Array.prototype.splice.call(this, i & 65535, 1); | |
dataTransfer.types.splice(i & 65535, 1); | |
}, | |
clear : function clear(data, type) { | |
this.length = 0; | |
dataTransfer.types.length = 0; | |
} | |
}), | |
setData : function setData(format, data) { | |
this.clearData(format); | |
this._items.add(data, format); | |
}, | |
getData : function getData(format) { | |
for (var i = this._items.length; i-- && this._items[i].type !== format;); | |
return i >= 0 ? this._items[i]._data : null; | |
}, | |
clearData : function clearData(format) { | |
for (var i = this._items.length; i-- && this._items[i].type !== format;); | |
this._items.remove(i); | |
}, | |
setDragImage : function setDragImage(format) { } | |
}; | |
if ('items' in DataTransfer.prototype) | |
dataTransfer.items = dataTransfer._items; | |
emit_mouse(source, [ 'pointerdown', 'mousedown' ], 1, function () { | |
var elem = source; | |
while (elem && !elem.draggable) | |
elem = elem.parentElement; | |
if (!elem || !elem.contains(source)) | |
return; | |
var box2 = target.getBoundingClientRect(); | |
emit_drag(source, 'dragstart', delay, function () { | |
var box3 = target.getBoundingClientRect(); | |
x = box3.left + x2 - box2.left; | |
y = box3.top + y2 - box2.top; | |
emit_drag(target, 'dragenter', 1, function () { | |
emit_drag(target, 'dragover', delay, function () { | |
emit_drag(doc.elementFromPoint(x, y), 'drop', 1, function () { | |
emit_drag(source, 'dragend', 1, function () { | |
emit_mouse(doc.elementFromPoint(x, y), [ 'mouseup', 'pointerup' ]); | |
})})})})})}); | |
function emit_mouse(element, types, delay, callback) { | |
for (var i=0; i < types.length; ++i) { | |
var event = doc.createEvent('MouseEvent'); | |
event.initMouseEvent(types[i], true, true, doc.defaultView, 0, 0, 0, x, y, ctrl, alt, shift, false, 0, null); | |
element.dispatchEvent(event); | |
} | |
callback && setTimeout(callback, delay); | |
} | |
function emit_drag(element, type, delay, callback) { | |
var event = doc.createEvent('DragEvent'); | |
event.initMouseEvent(type, true, true, doc.defaultView, 0, 0, 0, x, y, ctrl, alt, shift, false, 0, null); | |
Object.setPrototypeOf(event, null); | |
event.dataTransfer = dataTransfer; | |
Object.setPrototypeOf(event, DragEvent.prototype); | |
element.dispatchEvent(event); | |
callback && setTimeout(callback, delay); | |
} | |
var t=arguments,e=t[0],n=t[1],i=t[2]||0,o=t[3]||0,r=t[4]||1,a=t[5]||'',s='alt'===a||'\ue00a'===a,l='ctrl'===a||'\ue009'===a,c='shift'===a||'\ue008'===a,u=e.ownerDocument,f=e.getBoundingClientRect(),g=n?n.getBoundingClientRect():f,p=f.left+f.width/2,d=f.top+f.height/2,h=g.left+(i||g.width/2),m=g.top+(o||g.height/2),v=u.elementFromPoint(p,d),y=u.elementFromPoint(h,m);if(!v||!y){var E=new Error('source or target element is not interactable');throw E.code=15,E}var _={constructor:DataTransfer,effectAllowed:null,dropEffect:null,types:[],files:Object.setPrototypeOf([],null),_items:Object.setPrototypeOf([],{add:function(t,e){this[this.length]={_data:''+t,kind:'string',type:e,getAsFile:function(){},getAsString:function(t){t(this._data)}},_.types.push(e)},remove:function(t){Array.prototype.splice.call(this,65535&t,1),_.types.splice(65535&t,1)},clear:function(t,e){this.length=0,_.types.length=0}}),setData:function(t,e){this.clearData(t),this._items.add(e,t)},getData:function(t){for(var e=this._items.length;e--&&this._items[e].type!==t;);return e>=0?this._items[e]._data:null},clearData:function(t){for(var e=this._items.length;e--&&this._items[e].type!==t;);this._items.remove(e)},setDragImage:function(t){}};function w(t,e,n,i){for(var o=0;o<e.length;++o){var r=u.createEvent('MouseEvent');r.initMouseEvent(e[o],!0,!0,u.defaultView,0,0,0,p,d,l,s,c,!1,0,null),t.dispatchEvent(r)}i&&setTimeout(i,n)}function D(t,e,n,i){var o=u.createEvent('DragEvent');o.initMouseEvent(e,!0,!0,u.defaultView,0,0,0,p,d,l,s,c,!1,0,null),Object.setPrototypeOf(o,null),o.dataTransfer=_,Object.setPrototypeOf(o,DragEvent.prototype),t.dispatchEvent(o),i&&setTimeout(i,n)}'items'in DataTransfer.prototype&&(_.items=_._items),w(v,['pointerdown','mousedown'],1,function(){for(var t=v;t&&!t.draggable;)t=t.parentElement;if(t&&t.contains(v)){var e=y.getBoundingClientRect();D(v,'dragstart',r,function(){var t=y.getBoundingClientRect();p=t.left+h-e.left,d=t.top+m-e.top,D(y,'dragenter',1,function(){D(y,'dragover',r,function(){D(u.elementFromPoint(p,d),'drop',1,function(){D(v,'dragend',1,function(){w(u.elementFromPoint(p,d),['mouseup','pointerup'])})})})})})}}) | |
"drag-drop.min.js"
This worked for me....I'm trying to drag and drop elements in my application from past three days....your awsome :)
Im using Protractor Type script.
Implimentation:
const DragAndDrop = "function h(a,b,c,d){var k=l.createEvent('DragEvent');k.initMouseEvent(b,!0,!0,l.defaultView,0,0,0,m,n,w,x,y,!1,0,null);Object.setPrototypeOf(k,null);k.dataTransfer=g;Object.setPrototypeOf(k,DragEvent.prototype);a.dispatchEvent(k);setTimeout(d,c)}var a=arguments,c=a[0],d=a[1],q=a[2]||0,r=a[3]||0,t=a[4]||1;a=a[5]||'';var x='alt'===a||'\ue00a'===a,w='ctrl'===a||'\ue009'===a,y='shift'===a||'\ue008'===a,l=c.ownerDocument;a=c.getBoundingClientRect();var e=d?d.getBoundingClientRect():a,m=a.left+a.width/2,n=a.top+a.height/2,u=e.left+(q?q:e.width/2),v=e.top+(r?r:e.height/2),p=l.elementFromPoint(m,n),f=l.elementFromPoint(u,v);for(d=p;d&&!d.draggable;)d=d.parentElement;if(!d||!c.contains(p))throw c=Error('source element is not interactable/draggable'),c.code=15,c;if(!f)throw c=Error('target element is not interactable'),c.code=15,c;var g={constructor:DataTransfer,effectAllowed:null,dropEffect:null,types:[],files:Object.setPrototypeOf([],null),_items:Object.setPrototypeOf([],{add:function(a,b){this[this.length]={_data:''+_data,kind:'string',type:b,getAsFile:function(){},getAsString:function(a){a(this._data)}};g.types.push(b)},remove:function(a){Array.prototype.splice.call(this,a&65535,1);g.types.splice(a&65535,1)},clear:function(a,b){this.length=0;g.types.length=0}}),setData:function(a,b){this.clearData(a);this._items.add(b,a)},getData:function(a){for(var b=this._items.length;b--&&this._items[b].type!==a;);return 0<=b?this._items[b]._data:null},clearData:function(a){for(var b=this._items.length;b--&&this._items[b].type!==a;);this._items.remove(b)},setDragImage:function(a){}};'items'in DataTransfer.prototype&&(g.items=g._items);e=f.getBoundingClientRect();h(p,'dragstart',t,function(){var a=f.getBoundingClientRect();m=a.left+u-e.left;n=a.top+v-e.top;h(f,'dragenter',1,function(){h(f,'dragover',t,function(){f=l.elementFromPoint(m,n);h(f,'drop',1,function(){h(p,'dragend',1,function(){})})})})})";
let dragElement : ElementFinder = element(by.xpath("your element xpath))
let dropElement: ElementFinder = element(by.xpath("your element xpath"))
await browser.executeScript(DragAndDrop, dragElement ,dropElement);
Note: need to do few changes to make code look good
Implimentation of "drag-drop.min.js" in Protractor typescript framework:
const DND = "function h(a,b,c,d){var k=l.createEvent('DragEvent');k.initMouseEvent(b,!0,!0,l.defaultView,0,0,0,m,n,w,x,y,!1,0,null);Object.setPrototypeOf(k,null);k.dataTransfer=g;Object.setPrototypeOf(k,DragEvent.prototype);a.dispatchEvent(k);setTimeout(d,c)}var a=arguments,c=a[0],d=a[1],q=a[2]||0,r=a[3]||0,t=a[4]||1;a=a[5]||'';var x='alt'===a||'\ue00a'===a,w='ctrl'===a||'\ue009'===a,y='shift'===a||'\ue008'===a,l=c.ownerDocument;a=c.getBoundingClientRect();var e=d?d.getBoundingClientRect():a,m=a.left+a.width/2,n=a.top+a.height/2,u=e.left+(q?q:e.width/2),v=e.top+(r?r:e.height/2),p=l.elementFromPoint(m,n),f=l.elementFromPoint(u,v);for(d=p;d&&!d.draggable;)d=d.parentElement;if(!d||!c.contains(p))throw c=Error('source element is not interactable/draggable'),c.code=15,c;if(!f)throw c=Error('target element is not interactable'),c.code=15,c;var g={constructor:DataTransfer,effectAllowed:null,dropEffect:null,types:[],files:Object.setPrototypeOf([],null),_items:Object.setPrototypeOf([],{add:function(a,b){this[this.length]={_data:''+_data,kind:'string',type:b,getAsFile:function(){},getAsString:function(a){a(this._data)}};g.types.push(b)},remove:function(a){Array.prototype.splice.call(this,a&65535,1);g.types.splice(a&65535,1)},clear:function(a,b){this.length=0;g.types.length=0}}),setData:function(a,b){this.clearData(a);this._items.add(b,a)},getData:function(a){for(var b=this._items.length;b--&&this._items[b].type!==a;);return 0<=b?this._items[b]._data:null},clearData:function(a){for(var b=this._items.length;b--&&this._items[b].type!==a;);this._items.remove(b)},setDragImage:function(a){}};'items'in DataTransfer.prototype&&(g.items=g._items);e=f.getBoundingClientRect();h(p,'dragstart',t,function(){var a=f.getBoundingClientRect();m=a.left+u-e.left;n=a.top+v-e.top;h(f,'dragenter',1,function(){h(f,'dragover',t,function(){f=l.elementFromPoint(m,n);h(f,'drop',1,function(){h(p,'dragend',1,function(){})})})})})";
await browser.executeScript(DND , dragingElement, droppingElement);
Note: Need to do changes to make your code look good.
Hi I'm currently working on an application which is developed in HTML5, so automating the drag and drops functionality has been a nightmare. I found your work to be really helpful. When implemented the code in my local test framework, I'm facing this error "TypeError: Object of type WalkthroughClient is not JSON serializable"
I have not include the drag_drop.js in the project folder. Is it because of this ?? If not please give me steps to implement
Hope below implementation steps by me helps you...:) happy coding
Were anyone able to drag and drop in this site with above piece od code?
Hi I'm currently working on an application which is developed in HTML5, so automating the drag and drops functionality has been a nightmare. I found your work to be really helpful. When implemented the code in my local test framework, I'm facing this error "TypeError: Object of type WalkthroughClient is not JSON serializable"
I have not include the drag_drop.js in the project folder. Is it because of this ?? If not please give me steps to implement