JavaScript click () method works only once in Chrome extension

I am trying to upload multiple files to a Chrome extension. The following code creates a dummy link to the file, then fires the .click () event, which loads the file. The problem is that only the first .click () event fires the download. Subsequent .click () events are ignored.

Here is manifest.json :

{ "name": "Simple File Downloader", "version": "0.1", "permissions": ["contextMenus", "http://*/"], "background": { "persistent": false, "scripts": ["sample.js"] }, "content_security_policy": "script-src 'self'; object-src 'self'", "manifest_version": 2 } 

Here is sample.js :

 function onClickHandler(info, tab) { var a = document.createElement('a'); a.href = 'http://or.cdn.sstatic.net/chat/so.mp3'; a.download = 'so.mp3'; document.body.appendChild(a); a.click(); // this click triggers the download // this timeout violates content security policy // setTimeout(a, 300); a.click(); // this click doesn't do anything document.body.removeChild(a); a = document.createElement('a'); a.href = 'http://or.cdn.sstatic.net/chat/so.mp3'; a.download = 'so.mp3'; document.body.appendChild(a); a.click(); // this click doesn't do anything either document.body.removeChild(a); }; chrome.contextMenus.onClicked.addListener(onClickHandler); chrome.runtime.onInstalled.addListener(function() { chrome.contextMenus.create({"title": "Download File", "id":"download_file"}); }); 

I tried:

I am surprised why it is so difficult to just save multiple files. Appreciate any help.

+6
source share
2 answers

The trick is not to use the element.click method, but to create multiple MouseEvent . To do this, you need to create one MouseEvent for each click.

 function clicker(el, clickCount) { var mousedownEvent; while(clickCount--) { mousedownEvent = document.createEvent("MouseEvent"); mousedownEvent.initMouseEvent("click", true, true, window, 0, null, null, null, null, false , false, false, false, 0, null); el.dispatchEvent(mousedownEvent); } } clicker(a, 3); // your anchor 'a' gets clicked on 3 times. 

When using this method in Chrome, however, you get a warning from the browser asking, "This site is trying to upload multiple files. Do you want to allow this? [Deny] [Allow]." Thus, if you do this on an additional extension page, the background page receives a warning, the user cannot see it, so the user does not have the opportunity to click "Allow".

A (rude / unpleasant) workaround is to create a tab that "clicks" on the anchor. Something like that:

 function _anchorDownloader(url, filename) { var timeout = 500; return 'javascript:\'<!doctype html><html>'+ '<head></head>' + '<script>' + 'function initDownload() {'+ 'var el = document.getElementById("anchor");'+ 'el.click();' + 'setTimeout(function() { window.close(); }, ' + timeout + ');' + '}'+ '</script>' + '<body onload="initDownload()">' + '<a id="anchor" href="' + url + '" download="'+ filename + '"></a>'+ '</body>' + '</html>\''; }; function downloadResource(info, tab) { // ... chrome.tabs.create( { 'url' : _anchorDownloader( url, filename ), 'active' : false } ); // ... } chrome.contextMenus.create({"title": "Save Image…", "contexts":["image"], "onclick": downloadResource }); 

For this to work, the extension must have "tabs" as permission in manifest.json . You can set a timeout to close the tab, however, if you close it too quickly, then the download will not happen.

+4
source

Instead of using the .live() method, which is no longer recommended, try .on()

 $(document).on("click", "a", function( event ){ // do whatever }); 

here is the documentation

0
source

All Articles