3

I am trying to do drag and drop from a parent page into an iframe which is cross-domain. The iframe is loaded by content script through chrome extension. But because of cross-domain iframe loaded by content script, I can't just use HTML5 drag and drop from parent page to iframe.

The reason I am going through the pain of using iframe is to avoid CSS corruption.

The approach I am trying to take is:

There is a way to communicate between parent and a cross-origin iframe through window.postMessage(). So I thought I will try to simulate drag operation happening in parent page inside iframe, by sending every drag related operation info inside parent to child iframe.

What I did was create a div inside iframe with contents of the dragged element on dragstart in parent. And on drag, continuously drag this div inside iframe with the coordinates provided by parent.

// CONTENT SCRIPT CODE

const setEventListener = name => {
  document.body.addEventListener(name, event => {
    const data = {
      dndType: name,
      clientX: event.clientX,   // clientX for iframe should map from clientX from parent exactly, I think
      clientY: iframeContainer.getBoundingClientRect().top - event.clientY,    // iframeContainer is placed at the bottom
      htmlContent: name === 'dragstart' && event.dataTransfer.getData('text/html')
    }
    iframe.contentWindow.postMessage(data, '*')
  })
}
setEventListener('dragstart')
setEventListener('drag')
setEventListener('dragend')



// IFRAME CODE

let dragger
window.addEventListener('message', function(e) {
  if (!dragger) {
    dragger = document.createElement('div')
    document.body.appendChild(dragger)
  }
  if (e.data.dndType) {
    if (e.data.htmlContent && e.data.htmlContent.length > 0) {
      dragger.innerHTML = e.data.htmlContent
    }
    const newEvent = createEvent(
      e.data.dndType,
      {
        clientX: e.data.clientX,
        clientY: e.data.clientY,
        dataTransfer: new DndSimulatorDataTransfer(),
      }
    )
    newEvent.dataTransfer.setData('text/html', dragger.innerHTML)
    dragger.dispatchEvent(newEvent)
  }
})

const createEvent = (eventName, options) => {
  var event = document.createEvent("CustomEvent");
  event.initCustomEvent(eventName, true, true, null);

  event.view = window;
  // event.detail = 0;
  event.ctlrKey = false;
  event.altKey = false;
  event.shiftKey = false;
  event.metaKey = false;
  event.button = 0;
  event.relatedTarget = null;

  /* if the clientX and clientY options are specified,
  also calculated the desired screenX and screenY values */
  if(options.clientX && options.clientY) {
      event.screenX = window.screenX + options.clientX;
      event.screenY = window.screenY + options.clientY;
 }

 /* copy the rest of the options into
  the event object */
  for (var prop in options) {
      event[prop] = options[prop];
  }

  return event;
}

var DndSimulatorDataTransfer = function() {
    this.data = {};
};
DndSimulatorDataTransfer.prototype.setData = function(format, data) {
    this.data[format] = data;
    this.items.push(data);
    this.types.push(format); 
};
// Remaining DndSimulatorDataTransfer prototype methods
// Taken from https://github.com/Photonios/JS-DragAndDrop-Simulator/blob/master/dndsim.js

I have tried different variations in this code but there is still no activity in iframe side. I am not even sure if this approach should work.

Is this even technically possible? Or is there any other way I should try. I think this guy is talking about this same approach.

Need help!

abhinav
  • 341
  • 1
  • 4
  • 15
  • Mouse events over iframe aren't fired in the parent document so there's nothing to relay. The usual workaround is to add a transparent div over the iframe so that the div will receive the events. This is what your jQuery forum link is about, basically. – wOxxOm Oct 10 '17 at 18:14
  • Just understood the concept of transparent div. I will try that. Thanks! – abhinav Oct 11 '17 at 02:38
  • Other than transparent div, do you see any major issue with my code? – abhinav Oct 11 '17 at 02:39
  • Transparent div concept worked like a charm.... Thank You @wOxxOm – abhinav Oct 12 '17 at 10:05
  • I need to go the other way, drag selected text from an iframe-ed document, which is from another domain, into a form on the top-level page. I'm having trouble seeing how the above concepts apply. Is the idea that a transparent div over the iframe intercepts the text selection and drag, and creates something in the top document that looks like that text being dragged? – enigment Mar 13 '18 at 17:56

0 Answers0