function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Brandon Coston 15Brandon Coston 15 

I'm running into some issues with event.dataTransfer.setDragImage() while using a library in a Lightning component.

I have a hierarchy lightning component and I'm using https://github.com/dabeng/OrgChart as a static resource to generate the hierarchy chart.  For the most part it works great.  However I am running into an issue with drag and drop functionality that I can't seem to figure out.  That library has a section of code to generate a drag image when the user has panned the chart due to some older browsers (and Safari) not handling the transform correctly.  The problem is that when used in a lightning component on Salesforce it throws an error.  It seems like dataTransfer.setDragImage(img, xOffset, yOffset) doesn't work.  I even tried simplifying the code in the library to one of the most basic examples in this tutorial and was still running into issues.  The error I keep seeing is "[Argument 1 ('image') to DataTransfer.setDragImage must be an instance of Element]" however if I debug and look at the element that it's trying to use everything seems fine with it.  Does anyone know if something in Locker Service is interfering with this or have any ideas what else may be going on?

Here's the function that is having issues:

createGhostNode: function (event) {
      var $nodeDiv = $(event.target);
      var opts = this.options;
      var origEvent = event.originalEvent;
      var isFirefox = /firefox/.test(window.navigator.userAgent.toLowerCase());
      if (isFirefox) {
        origEvent.dataTransfer.setData('text/html', 'hack for firefox');
      }
      var ghostNode, nodeCover;
      if (!document.querySelector('.ghost-node')) {
        ghostNode = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        ghostNode.classList.add('ghost-node');
        nodeCover = document.createElementNS('http://www.w3.org/2000/svg','rect');
        ghostNode.appendChild(nodeCover);
        $nodeDiv.closest('.orgchart').append(ghostNode);
      } else {
        ghostNode = $nodeDiv.closest('.orgchart').children('.ghost-node').get(0);
        nodeCover = $(ghostNode).children().get(0);
      }
      var transValues = $nodeDiv.closest('.orgchart').css('transform').split(',');
      var scale = Math.abs(window.parseFloat((opts.direction === 't2b' || opts.direction === 'b2t') ? transValues[0].slice(transValues[0].indexOf('(') + 1) : transValues[1]));
      ghostNode.setAttribute('width', $nodeDiv.outerWidth(false));
      ghostNode.setAttribute('height', $nodeDiv.outerHeight(false));
      nodeCover.setAttribute('x',5 * scale);
      nodeCover.setAttribute('y',5 * scale);
      nodeCover.setAttribute('width', 120 * scale);
      nodeCover.setAttribute('height', 40 * scale);
      nodeCover.setAttribute('rx', 4 * scale);
      nodeCover.setAttribute('ry', 4 * scale);
      nodeCover.setAttribute('stroke-width', 1 * scale);
      var xOffset = origEvent.offsetX * scale;
      var yOffset = origEvent.offsetY * scale;
      if (opts.direction === 'l2r') {
        xOffset = origEvent.offsetY * scale;
        yOffset = origEvent.offsetX * scale;
      } else if (opts.direction === 'r2l') {
        xOffset = $nodeDiv.outerWidth(false) - origEvent.offsetY * scale;
        yOffset = origEvent.offsetX * scale;
      } else if (opts.direction === 'b2t') {
        xOffset = $nodeDiv.outerWidth(false) - origEvent.offsetX * scale;
        yOffset = $nodeDiv.outerHeight(false) - origEvent.offsetY * scale;
      }
      if (isFirefox) { // hack for old version of Firefox(< 48.0)
        nodeCover.setAttribute('fill', 'rgb(255, 255, 255)');
        nodeCover.setAttribute('stroke', 'rgb(191, 0, 0)');
        var ghostNodeWrapper = document.createElement('img');
        ghostNodeWrapper.src = 'data:image/svg+xml;utf8,' + (new XMLSerializer()).serializeToString(ghostNode);
        origEvent.dataTransfer.setDragImage(ghostNodeWrapper, xOffset, yOffset);
      } else {
        origEvent.dataTransfer.setDragImage(ghostNode, xOffset, yOffset);
      }
    }


I also tried simplifying it down to this code and it still throws the same error:

createGhostNode: function (event) {
      var $nodeDiv = $(event.target);
      var origEvent = event.originalEvent;
      var ghostNode = document.createElement('img');
      ghostNode.classList.add('ghost-node');
      ghostNode.setAttribute('width', 50);
      ghostNode.setAttribute('height', 50);
      ghostNode.setAttribute('background-color', 'red');
      $nodeDiv.closest('.orgchart').append(ghostNode);
      origEvent.dataTransfer.setDragImage(ghostNode, 0, 0);
    }
Karthik KKarthik K
Hi Brandan, Have tried the earlier versions like 39.0
That would help you segregate the locker service issue or not. Older API versions are not be impacted with LockerService. 
Brandon Coston 15Brandon Coston 15
Good call!  It does not crash when I change the API version to 39 so is most likely related to locker service.  Unfortunately this is for an app on the appExchange, so it does need to be compatible with locker service.  Any clue what part of that function is incompatible with lightning service and what I may be able to do to get it to be compatible?  I suspect it's either the document.createElement() function or the origEvent.dataTransfer.setDragImage() function.  I don't know enough to be able to tell which one is the issue or how to go about fixing it though.
Akansha RangariAkansha Rangari
Hi Brandon, I'm facing the same issue for drag and drop. Can you please help in this