最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Trigger 'drop' event while providing the file data - Stack Overflow

programmeradmin0浏览0评论

Question

How could I, while providing the file, trigger a drop event of a field, on which I do not have access at loading.

Details

There is a page with a field on which is attached a drop listener that process an image when dropped. I would like to be able to use this process by pasting an image. I know how to get the file from a paste, but I do not know how to dispatch a drop event that would contains this very file.

The obstacles are:

  • The code is obfuscated, I cannot access the function linked with the listener by name.
  • There is no way to get the drop listener after it being attached to an element. It seems there is some way to do it in the console, but not from a script.
  • I do not control the page rendering; i.e. I cannot intercept the event listener addition.
  • Vanilla Javascript & could only work in Chrome (extension).
  • This page is built in vanilla; i.e. no jQuery or anything.

Does anyone have an idea on how to tackle this task?

I am looking into DragEvent but "although this interface has a constructor, it is not possible to create a useful DataTransfer object from script, since DataTransfer objects have a processing and security model that is coordinated by the browser during drag-and-drops."

I saw a possible approach but I want to mimic a real drop event with its data, i.e. pass a file I got via clipboardData.items[0].getAsFile(); instead of just text.

Question

How could I, while providing the file, trigger a drop event of a field, on which I do not have access at loading.

Details

There is a page with a field on which is attached a drop listener that process an image when dropped. I would like to be able to use this process by pasting an image. I know how to get the file from a paste, but I do not know how to dispatch a drop event that would contains this very file.

The obstacles are:

  • The code is obfuscated, I cannot access the function linked with the listener by name.
  • There is no way to get the drop listener after it being attached to an element. It seems there is some way to do it in the console, but not from a script.
  • I do not control the page rendering; i.e. I cannot intercept the event listener addition.
  • Vanilla Javascript & could only work in Chrome (extension).
  • This page is built in vanilla; i.e. no jQuery or anything.

Does anyone have an idea on how to tackle this task?

I am looking into DragEvent but "although this interface has a constructor, it is not possible to create a useful DataTransfer object from script, since DataTransfer objects have a processing and security model that is coordinated by the browser during drag-and-drops."

I saw a possible approach https://stackoverflow./a/39066443/1004274 but I want to mimic a real drop event with its data, i.e. pass a file I got via clipboardData.items[0].getAsFile(); instead of just text.

Share Improve this question edited Dec 23, 2021 at 6:45 Glorfindel 22.7k13 gold badges89 silver badges119 bronze badges asked Sep 14, 2016 at 9:46 BenoîtBenoît 15k7 gold badges64 silver badges88 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

You can fake the drop event, and fake pretty much everything that's in there. What you'll have problem doing is triggering a default event, such as opening a file in a tab by dropping it. The reason isn't so much because of the dataTransfer object being protected, but the event not being trusted. By having trusted event and protected dataTransfer, you can be sure you won't pass data to a trusted event, and that you won't trigger default event with unwanted data.

But depending on how the drop function is accessing the file that is dropped, you might be able to trick it with a fake drop event and a fake dataTransfer object. See this fiddle for a general idea of how it may work:

var a = document.getElementById('link');
var dropZone1 = document.getElementById('dropZone1');
var dropZone2 = document.getElementById('dropZone2');
var fakeDropBtn = document.getElementById('fakeDropBtn');

dropZone1.addEventListener('dragover', function(e) {
  e.preventDefault();
});

dropZone2.addEventListener('dragover', function(e) {
  e.preventDefault();
});

dropZone1.addEventListener('drop', function(e) {
  // This first drop zone is simply to get access to a file.
  // In your case the file would e from the clipboard
  // but you need to work with an extension to have access
  // to paste data, so here I use a drop event
  e.preventDefault();
  fakeDropBtn.classList.remove('disabled');
  dropZone2.classList.remove('disabled');
  var fileToDrop = e.dataTransfer.files[0];

  // You create a drop event
  var fakeDropEvent = new DragEvent('drop');
  // You override dataTransfer with whichever property
  // and method the drop function needs
  Object.defineProperty(fakeDropEvent, 'dataTransfer', {
    value: new FakeDataTransfer(fileToDrop)
  });

  fakeDropBtn.addEventListener('click', function(e) {
    e.preventDefault();

    // the fake event will be called on the button click
    dropZone2.dispatchEvent(fakeDropEvent);
  });
});



dropZone2.addEventListener('drop', function(e) {
    e.preventDefault();
  // this is the fake event being called. In this case for 
  // example, the function gets access to dataTransfer files.
  // You'll see the result will be the same with a real
  // drop event or with a fake drop event. The only thing
  // that matters is to override the specific property this function
  // is using.
  var url = window.URL.createObjectURL(e.dataTransfer.files[0]);
  a.href = url;
  a.click();
  window.URL.revokeObjectURL(url); 
});

function FakeDataTransfer(file) {
  this.dropEffect = 'all';
  this.effectAllowed = 'all';
  this.items = [];
  this.types = ['Files'];
  this.getData = function() {

    return file;
  };
  this.files = [file];
};

https://jsfiddle/5m2u0tux/6/

发布评论

评论列表(0)

  1. 暂无评论