Dispatch event instead of using a.click()
closes #465

added a changelog
closes #466

Made third argument as a object instead for easier transition to v2
This commit is contained in:
Jimmy Wärting
2018-09-26 17:04:34 +02:00
parent f3b45ae580
commit 70c261d026
8 changed files with 106 additions and 37 deletions
+2 -2
View File
@@ -60,10 +60,10 @@ import { saveAs } from 'file-saver/FileSaver';
```
```js
FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Boolean autoBOM)
FileSaver saveAs(Blob/File/Url, optional DOMString filename, optional Object { autoBOM })
```
Pass `true` for `autoBOM` if you want FileSaver.js to automatically provide Unicode text encoding hints (see: [byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark)).
Pass `{ autoBOM: true }` if you want FileSaver.js to automatically provide Unicode text encoding hints (see: [byte order mark](https://en.wikipedia.org/wiki/Byte_order_mark)).
Examples
--------
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "file-saver",
"main": "dist/FileSaver.min.js",
"version": "2.0.0-rc.1",
"version": "2.0.0-rc.2",
"homepage": "https://github.com/eligrey/FileSaver.js",
"authors": [
"Eli Grey <me@eligrey.com>"
+30
View File
@@ -0,0 +1,30 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.0-rc.2] - 2018-09-26
- Added a changelog.md
- Reverted `a.click()` to use dispatch with a try-catch (#382)
- Made third argument to an object where you have to pass `{ autoBom: true }`
- boolean are depricated but still works
## [2.0.0-rc.1] - 2018-09-26
- saveAs don't return anything
- The object that dispatched `writestart progress write writeend` are gone
- detecting such features was never possible and nobody seems to use it.
- Removed the demo folder
- Removed date/version from top of the file
- Dosen't crash in web workers (#449)
- Support saving urls (#260 with workarounds for cross origin)
- Uses babel universal module pattern (UMD) to export the package
- Provides source map now as well.
- use a[download] before msSaveAs (#193, #294)
- removed dist from .gitignore (npm uses it if it don't find a .npmignore)
- autoBom is now reversed so you have to tell when you want to use autoBom (#432)
- `a.click()` since there are new and depricated event constructors that works differently (#382)
- opens up a new popup (tab) directly for the fallback method since the FileReader is async
- removed the explicitly MSIE [1-9] check
+37 -15
View File
@@ -40,11 +40,18 @@
}
}();
function bom(blob, autoBom) {
if (!autoBom) return blob; // prepend BOM for UTF-8 XML and text/* types (including HTML)
function bom(blob, opts) {
if (typeof opts === 'undefined') opts = {
autoBom: false
};else if (typeof opts !== 'object') {
console.warn('Depricated: Expected third argument to be a object');
opts = {
autoBom: !opts
};
} // prepend BOM for UTF-8 XML and text/* types (including HTML)
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
return new Blob([String.fromCharCode(0xFEFF), blob], {
type: blob.type
});
@@ -53,13 +60,13 @@
return blob;
}
function download(url, name, autoBom) {
function download(url, name, opts) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = function () {
saveAs(xhr.response, name, autoBom);
saveAs(xhr.response, name, opts);
};
xhr.onerror = function () {
@@ -75,13 +82,24 @@
xhr.open('HEAD', url, false);
xhr.send();
return xhr.status >= 200 && xhr.status <= 299;
} // `a.click()` don't work for all browsers (#465)
function click(node) {
try {
node.dispatchEvent(new MouseEvent('click'));
} catch (e) {
var evt = document.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
node.dispatchEvent(evt);
}
}
var saveAs = _global.saveAs || // probably in some web worker
typeof window !== 'object' || window !== _global ? function saveAs() {}
/* noop */
// Use download attribute first if possible (#193 Lumia mobile)
: 'download' in HTMLAnchorElement.prototype ? function saveAs(blob, name, autoBom) {
: 'download' in HTMLAnchorElement.prototype ? function saveAs(blob, name, opts) {
var URL = _global.URL || _global.webkitURL;
var a = document.createElement('a');
name = name || blob.name || 'download';
@@ -95,9 +113,9 @@
a.href = blob;
if (a.origin !== location.origin) {
corsEnabled(a.href) ? download(blob, name, autoBom) : a.click(a.target = '_blank');
corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank');
} else {
a.click();
click(a);
}
} else {
// Support blobs
@@ -106,26 +124,30 @@
URL.revokeObjectURL(a.href);
}, 4E4); // 40s
setTimeout(a.click.bind(a), 0);
setTimeout(function () {
click(a);
}, 0);
}
} // Use msSaveOrOpenBlob as a second approch
: 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, autoBom) {
: 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) {
name = name || blob.name || 'download';
if (typeof blob === 'string') {
if (corsEnabled(blob)) {
download(blob, name, autoBom);
download(blob, name, opts);
} else {
var a = document.createElement('a');
a.href = blob;
a.target = '_blank';
setTimeout(a.click.bind(a));
setTimeout(function () {
clikc(a);
});
}
} else {
navigator.msSaveOrOpenBlob(bom(blob, autoBom), name);
navigator.msSaveOrOpenBlob(bom(blob, opts), name);
}
} // Fallback to using FileReader and a popup
: function saveAs(blob, name, autoBom, popup) {
: function saveAs(blob, name, opts, popup) {
// Open a popup immediately do go around popup blocker
// Mostly only avalible on user interaction and the fileReader is async so...
popup = popup || open('', '_blank');
@@ -134,7 +156,7 @@
popup.document.title = popup.document.body.innerText = 'downloading...';
}
if (typeof blob === 'string') return download(blob, name, autoBom);
if (typeof blob === 'string') return download(blob, name, opts);
var force = blob.type === 'application/octet-stream';
var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
+1 -1
View File
@@ -1,3 +1,3 @@
(function(a,b){if("function"==typeof define&&define.amd)define(["exports"],b);else if("undefined"!=typeof exports)b(exports);else{var c={exports:{}};b(c.exports),a.FileSaver=c.exports}})(this,function(a){"use strict";function b(a,b){return b?/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a:a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){f(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;return b.open("HEAD",a,!1),b.send(),200<=b.status&&299>=b.status}Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var e=function(){try{return Function("return this")()||(42,eval)("this")}catch(a){return"object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:this}}(),f=e.saveAs||"object"!=typeof window||window!==e?function(){}:"download"in HTMLAnchorElement.prototype?function(b,f,g){var h=e.URL||e.webkitURL,i=document.createElement("a");f=f||b.name||"download",i.download=f,i.rel="noopener","string"==typeof b?(i.href=b,i.origin===location.origin?i.click():d(i.href)?c(b,f,g):i.click(i.target="_blank")):(i.href=h.createObjectURL(b),setTimeout(function(){h.revokeObjectURL(i.href)},4E4),setTimeout(i.click.bind(i),0))}:"msSaveOrOpenBlob"in navigator?function(e,f,g){if(f=f||e.name||"download","string"!=typeof e)navigator.msSaveOrOpenBlob(b(e,g),f);else if(d(e))c(e,f,g);else{var h=document.createElement("a");h.href=e,h.target="_blank",setTimeout(h.click.bind(h))}}:function(a,b,d,f){if(f=f||open("","_blank"),f&&(f.document.title=f.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(e.HTMLElement)||e.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"object"==typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),f?f.location.href=a:location=a,f=null},j.readAsDataURL(a)}else{var k=e.URL||e.webkitURL,l=k.createObjectURL(a);f?f.location=l:location.href=l,f=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}};e.saveAs=f;a.default=f});
(function(a,b){if("function"==typeof define&&define.amd)define(["exports"],b);else if("undefined"!=typeof exports)b(exports);else{var c={exports:{}};b(c.exports),a.FileSaver=c.exports}})(this,function(a){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Depricated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;return b.open("HEAD",a,!1),b.send(),200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var f=function(){try{return Function("return this")()||(42,eval)("this")}catch(a){return"object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:this}}(),g=f.saveAs||"object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(e,f,g){if(f=f||e.name||"download","string"!=typeof e)navigator.msSaveOrOpenBlob(b(e,g),f);else if(d(e))c(e,f,g);else{var h=document.createElement("a");h.href=e,h.target="_blank",setTimeout(function(){clikc(h)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"object"==typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}};f.saveAs=g;a.default=g});
//# sourceMappingURL=FileSaver.min.js.map
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "file-saver",
"version": "2.0.0-rc.1",
"version": "2.0.0-rc.2",
"description": "An HTML5 saveAs() FileSaver implementation",
"main": "dist/FileSaver.min.js",
"module": "src/FileSaver.js",
+33 -16
View File
@@ -24,22 +24,27 @@ var _global = (function () {
}
})()
function bom (blob, autoBom) {
if (!autoBom) return blob
function bom (blob, opts) {
if (typeof opts === 'undefined') opts = { autoBom: false }
else if (typeof opts !== 'object') {
console.warn('Depricated: Expected third argument to be a object')
opts = { autoBom: !opts }
}
// prepend BOM for UTF-8 XML and text/* types (including HTML)
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
return new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type })
}
return blob
}
function download (url, name, autoBom) {
function download (url, name, opts) {
var xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.responseType = 'blob'
xhr.onload = function () {
saveAs(xhr.response, name, autoBom)
saveAs(xhr.response, name, opts)
}
xhr.onerror = function () {
console.error('could not download file')
@@ -55,6 +60,18 @@ function corsEnabled (url) {
return xhr.status >= 200 && xhr.status <= 299
}
// `a.click()` don't work for all browsers (#465)
function click(node) {
try {
node.dispatchEvent(new MouseEvent('click'))
} catch (e) {
var evt = document.createEvent('MouseEvents')
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80,
20, false, false, false, false, 0, null)
node.dispatchEvent(evt)
}
}
var saveAs = _global.saveAs ||
// probably in some web worker
(typeof window !== 'object' || window !== _global)
@@ -62,7 +79,7 @@ var saveAs = _global.saveAs ||
// Use download attribute first if possible (#193 Lumia mobile)
: 'download' in HTMLAnchorElement.prototype
? function saveAs (blob, name, autoBom) {
? function saveAs (blob, name, opts) {
var URL = _global.URL || _global.webkitURL
var a = document.createElement('a')
name = name || blob.name || 'download'
@@ -78,40 +95,40 @@ var saveAs = _global.saveAs ||
a.href = blob
if (a.origin !== location.origin) {
corsEnabled(a.href)
? download(blob, name, autoBom)
: a.click(a.target = '_blank')
? download(blob, name, opts)
: click(a, a.target = '_blank')
} else {
a.click()
click(a)
}
} else {
// Support blobs
a.href = URL.createObjectURL(blob)
setTimeout(function () { URL.revokeObjectURL(a.href) }, 4E4) // 40s
setTimeout(a.click.bind(a), 0)
setTimeout(function () { click(a) }, 0)
}
}
// Use msSaveOrOpenBlob as a second approch
: 'msSaveOrOpenBlob' in navigator
? function saveAs (blob, name, autoBom) {
? function saveAs (blob, name, opts) {
name = name || blob.name || 'download'
if (typeof blob === 'string') {
if (corsEnabled(blob)) {
download(blob, name, autoBom)
download(blob, name, opts)
} else {
var a = document.createElement('a')
a.href = blob
a.target = '_blank'
setTimeout(a.click.bind(a))
setTimeout(function () { clikc(a) })
}
} else {
navigator.msSaveOrOpenBlob(bom(blob, autoBom), name)
navigator.msSaveOrOpenBlob(bom(blob, opts), name)
}
}
// Fallback to using FileReader and a popup
: function saveAs (blob, name, autoBom, popup) {
: function saveAs (blob, name, opts, popup) {
// Open a popup immediately do go around popup blocker
// Mostly only avalible on user interaction and the fileReader is async so...
popup = popup || open('', '_blank')
@@ -120,7 +137,7 @@ var saveAs = _global.saveAs ||
popup.document.body.innerText = 'downloading...'
}
if (typeof blob === 'string') return download(blob, name, autoBom)
if (typeof blob === 'string') return download(blob, name, opts)
var force = blob.type === 'application/octet-stream'
var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari