| //download.js v4.0, by dandavis; 2008-2015. [CCBY2] see http://danml.com/download.html for tests/usage | 
| // v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime | 
| // v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs | 
| // v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling. | 
| // v4 adds AMD/UMD, commonJS, and plain browser support | 
| // https://github.com/rndme/download | 
|   | 
| (function (root, factory) { | 
|     if (typeof define === 'function' && define.amd) { | 
|         // AMD. Register as an anonymous module. | 
|         define([], factory); | 
|     } else if (typeof exports === 'object') { | 
|         // Node. Does not work with strict CommonJS, but | 
|         // only CommonJS-like environments that support module.exports, | 
|         // like Node. | 
|         module.exports = factory(); | 
|     } else { | 
|         // Browser globals (root is window) | 
|         root.download = factory(); | 
|   } | 
| }(this, function () { | 
|   | 
|     return function download(data, strFileName, strMimeType) { | 
|   | 
|         var self = window, // this script is only for browsers anyway... | 
|             u = "application/octet-stream", // this default mime also triggers iframe downloads | 
|             m = strMimeType || u, | 
|             x = data, | 
|             D = document, | 
|             a = D.createElement("a"), | 
|             z = function(a){return String(a);}, | 
|             B = (self.Blob || self.MozBlob || self.WebKitBlob || z); | 
|             B=B.call ? B.bind(self) : Blob ; | 
|             var fn = strFileName || "download", | 
|             blob, | 
|             fr; | 
|   | 
|   | 
|         if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback | 
|             x=[x, m]; | 
|             m=x[0]; | 
|             x=x[1]; | 
|         } | 
|   | 
|   | 
|   | 
|   | 
|         //go ahead and download dataURLs right away | 
|         if(String(x).match(/^data\:[\w+\-]+\/[\w+\-]+[,;]/)){ | 
|             return navigator.msSaveBlob ?  // IE10 can't do a[download], only Blobs: | 
|                 navigator.msSaveBlob(d2b(x), fn) : | 
|                 saver(x) ; // everyone else can save dataURLs un-processed | 
|         }//end if dataURL passed? | 
|   | 
|         blob = x instanceof B ? | 
|             x : | 
|             new B([x], {type: m}) ; | 
|   | 
|   | 
|         function d2b(u) { | 
|             var p= u.split(/[:;,]/), | 
|             t= p[1], | 
|             dec= p[2] == "base64" ? atob : decodeURIComponent, | 
|             bin= dec(p.pop()), | 
|             mx= bin.length, | 
|             i= 0, | 
|             uia= new Uint8Array(mx); | 
|   | 
|             for(i;i<mx;++i) uia[i]= bin.charCodeAt(i); | 
|   | 
|             return new B([uia], {type: t}); | 
|          } | 
|   | 
|         function saver(url, winMode){ | 
|   | 
|             if ('download' in a) { //html5 A[download] | 
|              | 
|                 //change base64 to blob, to aviod chrome crash with large file | 
|                 if(String(url).match(/^data\:[\w+\-]+\/[\w+\-]+[,;]/)){ | 
|                     // atob to base64_decode the data-URI | 
|                     var image_data = atob(url.split(',')[1]); | 
|                     // Use typed arrays to convert the binary data to a Blob | 
|                     var arraybuffer = new ArrayBuffer(image_data.length); | 
|                     var view = new Uint8Array(arraybuffer); | 
|                     for (var i=0; i<image_data.length; i++) { | 
|                         view[i] = image_data.charCodeAt(i) & 0xff; | 
|                     } | 
|                     try { | 
|                         // This is the recommended method: | 
|                         var blob = new Blob([arraybuffer], {type: 'application/octet-stream'}); | 
|                     } catch (e) { | 
|                         // The BlobBuilder API has been deprecated in favour of Blob, but older | 
|                         // browsers don't know about the Blob constructor | 
|                         // IE10 also supports BlobBuilder, but since the `Blob` constructor | 
|                         //  also works, there's no need to add `MSBlobBuilder`. | 
|                         var bb = new (window.WebKitBlobBuilder || window.MozBlobBuilder); | 
|                         bb.append(arraybuffer); | 
|                         var blob = bb.getBlob('application/octet-stream'); // <-- Here's the Blob | 
|                     } | 
|   | 
|                     // Use the URL object to create a temporary URL | 
|                     url = (window.webkitURL || window.URL).createObjectURL(blob); | 
|                 } | 
|                  | 
|                 a.href = url; | 
|                 a.setAttribute("download", fn); | 
|                 a.innerHTML = "downloading..."; | 
|                 D.body.appendChild(a); | 
|                 setTimeout(function() { | 
|                     a.click(); | 
|                     D.body.removeChild(a); | 
|                     if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(a.href);}, 250 );} | 
|                 }, 66); | 
|                 return true; | 
|             } | 
|              | 
|             if(typeof safari !=="undefined" ){ // handle non-a[download] safari as best we can: | 
|                 url="data:"+url.replace(/^data:([\w\/\-\+]+)/, u); | 
|                 if(!window.open(url)){ // popup blocked, offer direct download: | 
|                     if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){ location.href=url; } | 
|                 } | 
|                 return true; | 
|             } | 
|   | 
|             //do iframe dataURL download (old ch+FF): | 
|             var f = D.createElement("iframe"); | 
|             D.body.appendChild(f); | 
|   | 
|             if(!winMode){ // force a mime that will download: | 
|                 url="data:"+url.replace(/^data:([\w\/\-\+]+)/, u); | 
|             } | 
|             f.src=url; | 
|             setTimeout(function(){ D.body.removeChild(f); }, 333); | 
|   | 
|         }//end saver | 
|   | 
|   | 
|   | 
|   | 
|         if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL) | 
|             return navigator.msSaveBlob(blob, fn); | 
|         } | 
|   | 
|         if(self.URL){ // simple fast and modern way using Blob and URL: | 
|             saver(self.URL.createObjectURL(blob), true); | 
|         }else{ | 
|             // handle non-Blob()+non-URL browsers: | 
|             if(typeof blob === "string" || blob.constructor===z ){ | 
|                 try{ | 
|                     return saver( "data:" +  m   + ";base64,"  +  self.btoa(blob)  ); | 
|                 }catch(y){ | 
|                     return saver( "data:" +  m   + "," + encodeURIComponent(blob)  ); | 
|                 } | 
|             } | 
|   | 
|             // Blob but not URL: | 
|             fr=new FileReader(); | 
|             fr.onload=function(e){ | 
|                 saver(this.result); | 
|             }; | 
|             fr.readAsDataURL(blob); | 
|         } | 
|         return true; | 
|     }; /* end download() */ | 
| })); |