Skip to content

Instantly share code, notes, and snippets.

@reinaldorossetti
Forked from florentbr/#drag-drop.py
Last active July 15, 2021 16:49
Show Gist options
  • Save reinaldorossetti/074642e9f954b7119c557748836fcd42 to your computer and use it in GitHub Desktop.
Save reinaldorossetti/074642e9f954b7119c557748836fcd42 to your computer and use it in GitHub Desktop.
Selenium - HTML5 drag and drop
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
from time import sleep
from os import getcwd
# JavaScript: 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 center of the target or source element
# param4 (int): Optional - Drop offset y relative to the center of the target or source element
# param4 (int): Optional - Delay in milliseconds (default = 1ms) for dragging and dropping
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_draganddrop2")
driver.implicitly_wait(15)
driver.switch_to.frame("iframeResult")
cwd = getcwd()
JS_DRAG_DROP = open(cwd + '\\drag-drop.js', 'r').read()
print(JS_DRAG_DROP)
# drag and drop an element on another one
source = driver.find_element_by_css_selector("#drag1")
target = driver.find_element_by_css_selector("div#div2")
location1 = int(source.location['x'])
print(driver.execute_script(JS_DRAG_DROP, source, target))
driver.implicitly_wait(5)
source2 = driver.find_element_by_css_selector("#drag1")
print(source2.location)
location2 = int(source2.location['x'])
type(location1)
print(location1, location2)
assert(location2 > location1)
driver.get("http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_draganddrop")
driver.implicitly_wait(15)
driver.switch_to.frame("iframeResult")
source = driver.find_element_by_css_selector("img#drag1")
target = driver.find_element_by_css_selector("div#div1")
driver.execute_script(JS_DRAG_DROP, source, target, None, None, 101)
# Not have HTML 5, drag_and_drop_by_offset working very well.
driver.get("http://jsfiddle.net/davidThomas/DGbT3/3/")
driver.implicitly_wait(15)
# drag and drop an element by offset {x:500, y:200}
driver.find_element_by_css_selector("#run").click()
driver.switch_to.frame("result")
source3 = driver.find_element_by_css_selector("#dragThis")
target3 = driver.find_element_by_css_selector("#dropHere")
location1 = int(target3.location['x'])
location2 = int(target3.location['y'])
actions = ActionChains(driver)
actions.drag_and_drop_by_offset(source3, location1+10, location2+10)
actions.perform()
# Not Working
driver.execute_script(JS_DRAG_DROP, source3, None, 500, 200)
print(source3.location)
var args = arguments,
callback = args[args.length - 1],
source = args[0],
target = args[1],
offsetX = (args.length > 2 && args[2]) || 0,
offsetY = (args.length > 3 && args[3]) || 0,
delay = (args.length > 4 && args[4]) || 1;
if (!source.draggable) throw new Error('Source element is not draggable.');
var doc = source.ownerDocument,
win = doc.defaultView,
rect1 = source.getBoundingClientRect(),
rect2 = target ? target.getBoundingClientRect() : rect1,
x = rect1.left + (rect1.width >> 1),
y = rect1.top + (rect1.height >> 1),
x2 = rect2.left + (rect2.width >> 1) + offsetX,
y2 = rect2.top + (rect2.height >> 1) + offsetY,
dataTransfer = Object.create(Object.prototype, {
_items: { value: { } },
effectAllowed: { value: 'all', writable: true },
dropEffect: { value: 'move', writable: true },
files: { get: function () { return undefined } },
types: { get: function () { return Object.keys(this._items) } },
setData: { value: function (format, data) { this._items[format] = data } },
getData: { value: function (format) { return this._items[format] } },
clearData: { value: function (format) { delete this._items[format] } },
setDragImage: { value: function () { } }
});
target = doc.elementFromPoint(x2, y2);
if(!target) throw new Error('The target element is not interactable and need to be scrolled into the view.');
rect2 = target.getBoundingClientRect();
emit(source, 'dragstart', delay, function () {
var rect3 = target.getBoundingClientRect();
x = rect3.left + x2 - rect2.left;
y = rect3.top + y2 - rect2.top;
emit(target, 'dragenter', 1, function () {
emit(target, 'dragover', delay, function () {
target = doc.elementFromPoint(x, y);
emit(target, 'drop', 1, function () {
emit(source, 'dragend', 1, callback);
});});});});
function emit(element, type, delay, callback) {
var event = doc.createEvent('DragEvent');
event.initMouseEvent(type, true, true, win, 0, 0, 0, x, y, false, false, false, false, 0, null);
Object.defineProperty(event, 'dataTransfer', { get: function () { return dataTransfer } });
element.dispatchEvent(event);
win.setTimeout(callback, delay);
}
function e(e,t,n,i){var r=u.createEvent("DragEvent");r.initMouseEvent(t,!0,!0,c,0,0,0,d,s,!1,!1,!1,!1,0,null),Object.defineProperty(r,"dataTransfer",{get:function(){return m}}),e.dispatchEvent(r),c.setTimeout(i,n)}var t=arguments,n=t[t.length-1],i=t[0],r=t[1],o=t.length>2&&t[2]||0,a=t.length>3&&t[3]||0,l=t.length>4&&t[4]||1;if(!i.draggable)throw new Error("Source element is not draggable.");var u=i.ownerDocument,c=u.defaultView,g=i.getBoundingClientRect(),f=r?r.getBoundingClientRect():g,d=g.left+(g.width>>1),s=g.top+(g.height>>1),v=f.left+(f.width>>1)+o,h=f.top+(f.height>>1)+a,m=Object.create(Object.prototype,{_items:{value:{}},effectAllowed:{value:"all",writable:!0},dropEffect:{value:"move",writable:!0},files:{get:function(){return void 0}},types:{get:function(){return Object.keys(this._items)}},setData:{value:function(e,t){this._items[e]=t}},getData:{value:function(e){return this._items[e]}},clearData:{value:function(e){delete this._items[e]}},setDragImage:{value:function(){}}});if(r=u.elementFromPoint(v,h),!r)throw new Error("The target element is not interactable and need to be scrolled into the view.");f=r.getBoundingClientRect(),e(i,"dragstart",l,function(){var t=r.getBoundingClientRect();d=t.left+v-f.left,s=t.top+h-f.top,e(r,"dragenter",1,function(){e(r,"dragover",l,function(){r=u.elementFromPoint(d,s),e(r,"drop",1,function(){e(i,"dragend",1,n)})})})})
@as3379
Copy link

as3379 commented Nov 4, 2019

I have weblements (both source and target) with no IDs which looks like this:
image

How to implement the same logic here. Tried using:
source = self.driver.find_element_by_css_selector("div.el-card.sortable-chosen")

but received NoSuchElement exception

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment