sortablejs 支持 iframe 跨域拖拽

背景

最近研究拖拽生成页面,遇到一个跨iframe拖拽的功能的问题。在此记录下心得。git

页面里面的 iframe 在没有跨域的状况下,SortableJS 是支持跨iframe拖拽的,官方仓库给了例子。若是跨域了,咱们拿不到 iframe 的 contentDocument,没法监听事件,因此 Sortable 默认状况下是不能工做的。github

思路 - 模拟拖拽

理论上 Sortable 是经过监听事件来完成拖拽的功能,咱们手动构造 drag 事件,通知 Sortable,也是能够完成任务的。跨域

实践 - 模拟拖拽

拖拽须要处理三个事件节点dom

  • dragstart
  • dragover
  • dragend

dragstart

Sortable 一开始不会在 dom 节点加上 draggable 属性,必须点击了才会,因此模拟时,须要先触发一个 pointdown 事件,而后触发 dargstrat 事件post

var downEvent = new PointerEvent("pointerdown", {
 //    pointerId: 1,
 bubbles: true,
 cancelable: true,
 // pointerType: "touch",
 width: 100,
 height: 100,
 isPrimary: true,
});
var startE = new DragEvent("dragstart", { bubbles: true });

dragover

父页面的 dragover 事件不会传递到 iframe 内(废话),因此咱们只能在 iframe 内监听 mousemove 事件, 而后构造一个 dragover 事件,传递给dom,告诉 Sortable 咱们拖动了Sortable元素到该dom上面,看看是否是须要改变位置。spa

document.addEventListener("mousemove", (e) => {
 console.log(e.type);
 if (e.target.classList.contains("list-group-item")) {
     e.target.dispatchEvent(
     new DragEvent("dragover", { clientY: e.clientY, bubbles: true }) ); // 用mousemove代替
 }
})

dragend

触发被拖拽 dom 的 dragend 事件便可code

dragEl.dispatchEvent(new DragEvent("dragend"));

父子页面通信

在页面中模拟拖拽成功后,接下来就是分开成两个页面,经过 postMessage 通信事件

隐藏的 Sortable 实例

这里把隐藏的 Sortable 实例称做影子节点, 在父页面开始拖拽某个 dom 时,iframe 内部须要同时触发一个 pull mode 的拖拽开始事件,而且将父页面拖拽的 dom 的 innerHTML 写入到影子节点get

demo 代码

https://github.com/larry011/s...iframe

相关文章
相关标签/搜索