| 
      
            Lines 1-232
          
      
      
        Link Here
      
     | 
  
            
              | 1 | 
              /* FileSaver.js  | 
               | 
               | 
            
            
              | 2 | 
               * A saveAs() FileSaver implementation.  | 
            
            
              | 3 | 
               * 2013-10-21  | 
            
            
              | 4 | 
               *  | 
            
            
              | 5 | 
               * By Eli Grey, http://eligrey.com  | 
            
            
              | 6 | 
               * License: X11/MIT  | 
            
            
              | 7 | 
               *   See LICENSE.md  | 
            
            
              | 8 | 
               */  | 
            
            
              | 9 | 
               | 
            
            
              | 10 | 
              /*global self */  | 
            
            
              | 11 | 
              /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,  | 
            
            
              | 12 | 
                plusplus: true */  | 
            
            
              | 13 | 
               | 
            
            
              | 14 | 
              /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */  | 
            
            
              | 15 | 
               | 
            
            
              | 16 | 
              var saveAs = saveAs  | 
            
            
              | 17 | 
                || (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))  | 
            
            
              | 18 | 
                || (function(view) { | 
            
            
              | 19 | 
              	"use strict";  | 
            
            
              | 20 | 
              	var  | 
            
            
              | 21 | 
              		  doc = view.document  | 
            
            
              | 22 | 
              		  // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet  | 
            
            
              | 23 | 
              		, get_URL = function() { | 
            
            
              | 24 | 
              			return view.URL || view.webkitURL || view;  | 
            
            
              | 25 | 
              		}  | 
            
            
              | 26 | 
              		, URL = view.URL || view.webkitURL || view  | 
            
            
              | 27 | 
              		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") | 
            
            
              | 28 | 
              		, can_use_save_link =  !view.externalHost && "download" in save_link  | 
            
            
              | 29 | 
              		, click = function(node) { | 
            
            
              | 30 | 
              			var event = doc.createEvent("MouseEvents"); | 
            
            
              | 31 | 
              			event.initMouseEvent(  | 
            
            
              | 32 | 
              				"click", true, false, view, 0, 0, 0, 0, 0  | 
            
            
              | 33 | 
              				, false, false, false, false, 0, null  | 
            
            
              | 34 | 
              			);  | 
            
            
              | 35 | 
              			node.dispatchEvent(event);  | 
            
            
              | 36 | 
              		}  | 
            
            
              | 37 | 
              		, webkit_req_fs = view.webkitRequestFileSystem  | 
            
            
              | 38 | 
              		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem  | 
            
            
              | 39 | 
              		, throw_outside = function (ex) { | 
            
            
              | 40 | 
              			(view.setImmediate || view.setTimeout)(function() { | 
            
            
              | 41 | 
              				throw ex;  | 
            
            
              | 42 | 
              			}, 0);  | 
            
            
              | 43 | 
              		}  | 
            
            
              | 44 | 
              		, force_saveable_type = "application/octet-stream"  | 
            
            
              | 45 | 
              		, fs_min_size = 0  | 
            
            
              | 46 | 
              		, deletion_queue = []  | 
            
            
              | 47 | 
              		, process_deletion_queue = function() { | 
            
            
              | 48 | 
              			var i = deletion_queue.length;  | 
            
            
              | 49 | 
              			while (i--) { | 
            
            
              | 50 | 
              				var file = deletion_queue[i];  | 
            
            
              | 51 | 
              				if (typeof file === "string") { // file is an object URL | 
            
            
              | 52 | 
              					URL.revokeObjectURL(file);  | 
            
            
              | 53 | 
              				} else { // file is a File | 
            
            
              | 54 | 
              					file.remove();  | 
            
            
              | 55 | 
              				}  | 
            
            
              | 56 | 
              			}  | 
            
            
              | 57 | 
              			deletion_queue.length = 0; // clear queue  | 
            
            
              | 58 | 
              		}  | 
            
            
              | 59 | 
              		, dispatch = function(filesaver, event_types, event) { | 
            
            
              | 60 | 
              			event_types = [].concat(event_types);  | 
            
            
              | 61 | 
              			var i = event_types.length;  | 
            
            
              | 62 | 
              			while (i--) { | 
            
            
              | 63 | 
              				var listener = filesaver["on" + event_types[i]];  | 
            
            
              | 64 | 
              				if (typeof listener === "function") { | 
            
            
              | 65 | 
              					try { | 
            
            
              | 66 | 
              						listener.call(filesaver, event || filesaver);  | 
            
            
              | 67 | 
              					} catch (ex) { | 
            
            
              | 68 | 
              						throw_outside(ex);  | 
            
            
              | 69 | 
              					}  | 
            
            
              | 70 | 
              				}  | 
            
            
              | 71 | 
              			}  | 
            
            
              | 72 | 
              		}  | 
            
            
              | 73 | 
              		, FileSaver = function(blob, name) { | 
            
            
              | 74 | 
              			// First try a.download, then web filesystem, then object URLs  | 
            
            
              | 75 | 
              			var  | 
            
            
              | 76 | 
              				  filesaver = this  | 
            
            
              | 77 | 
              				, type = blob.type  | 
            
            
              | 78 | 
              				, blob_changed = false  | 
            
            
              | 79 | 
              				, object_url  | 
            
            
              | 80 | 
              				, target_view  | 
            
            
              | 81 | 
              				, get_object_url = function() { | 
            
            
              | 82 | 
              					var object_url = get_URL().createObjectURL(blob);  | 
            
            
              | 83 | 
              					deletion_queue.push(object_url);  | 
            
            
              | 84 | 
              					return object_url;  | 
            
            
              | 85 | 
              				}  | 
            
            
              | 86 | 
              				, dispatch_all = function() { | 
            
            
              | 87 | 
              					dispatch(filesaver, "writestart progress write writeend".split(" ")); | 
            
            
              | 88 | 
              				}  | 
            
            
              | 89 | 
              				// on any filesys errors revert to saving with object URLs  | 
            
            
              | 90 | 
              				, fs_error = function() { | 
            
            
              | 91 | 
              					// don't create more object URLs than needed  | 
            
            
              | 92 | 
              					if (blob_changed || !object_url) { | 
            
            
              | 93 | 
              						object_url = get_object_url(blob);  | 
            
            
              | 94 | 
              					}  | 
            
            
              | 95 | 
              					if (target_view) { | 
            
            
              | 96 | 
              						target_view.location.href = object_url;  | 
            
            
              | 97 | 
              					} else { | 
            
            
              | 98 | 
                                      window.open(object_url, "_blank");  | 
            
            
              | 99 | 
                                  }  | 
            
            
              | 100 | 
              					filesaver.readyState = filesaver.DONE;  | 
            
            
              | 101 | 
              					dispatch_all();  | 
            
            
              | 102 | 
              				}  | 
            
            
              | 103 | 
              				, abortable = function(func) { | 
            
            
              | 104 | 
              					return function() { | 
            
            
              | 105 | 
              						if (filesaver.readyState !== filesaver.DONE) { | 
            
            
              | 106 | 
              							return func.apply(this, arguments);  | 
            
            
              | 107 | 
              						}  | 
            
            
              | 108 | 
              					};  | 
            
            
              | 109 | 
              				}  | 
            
            
              | 110 | 
              				, create_if_not_found = {create: true, exclusive: false} | 
            
            
              | 111 | 
              				, slice  | 
            
            
              | 112 | 
              			;  | 
            
            
              | 113 | 
              			filesaver.readyState = filesaver.INIT;  | 
            
            
              | 114 | 
              			if (!name) { | 
            
            
              | 115 | 
              				name = "download";  | 
            
            
              | 116 | 
              			}  | 
            
            
              | 117 | 
              			if (can_use_save_link) { | 
            
            
              | 118 | 
              				object_url = get_object_url(blob);  | 
            
            
              | 119 | 
              				// FF for Android has a nasty garbage collection mechanism  | 
            
            
              | 120 | 
              				// that turns all objects that are not pure javascript into 'deadObject'  | 
            
            
              | 121 | 
              				// this means `doc` and `save_link` are unusable and need to be recreated  | 
            
            
              | 122 | 
              				// `view` is usable though:  | 
            
            
              | 123 | 
              				doc = view.document;  | 
            
            
              | 124 | 
              				save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"); | 
            
            
              | 125 | 
              				save_link.href = object_url;  | 
            
            
              | 126 | 
              				save_link.download = name;  | 
            
            
              | 127 | 
              				var event = doc.createEvent("MouseEvents"); | 
            
            
              | 128 | 
              				event.initMouseEvent(  | 
            
            
              | 129 | 
              					"click", true, false, view, 0, 0, 0, 0, 0  | 
            
            
              | 130 | 
              					, false, false, false, false, 0, null  | 
            
            
              | 131 | 
              				);  | 
            
            
              | 132 | 
              				save_link.dispatchEvent(event);  | 
            
            
              | 133 | 
              				filesaver.readyState = filesaver.DONE;  | 
            
            
              | 134 | 
              				dispatch_all();  | 
            
            
              | 135 | 
              				return;  | 
            
            
              | 136 | 
              			}  | 
            
            
              | 137 | 
              			// Object and web filesystem URLs have a problem saving in Google Chrome when  | 
            
            
              | 138 | 
              			// viewed in a tab, so I force save with application/octet-stream  | 
            
            
              | 139 | 
              			// http://code.google.com/p/chromium/issues/detail?id=91158  | 
            
            
              | 140 | 
              			if (view.chrome && type && type !== force_saveable_type) { | 
            
            
              | 141 | 
              				slice = blob.slice || blob.webkitSlice;  | 
            
            
              | 142 | 
              				blob = slice.call(blob, 0, blob.size, force_saveable_type);  | 
            
            
              | 143 | 
              				blob_changed = true;  | 
            
            
              | 144 | 
              			}  | 
            
            
              | 145 | 
              			// Since I can't be sure that the guessed media type will trigger a download  | 
            
            
              | 146 | 
              			// in WebKit, I append .download to the filename.  | 
            
            
              | 147 | 
              			// https://bugs.webkit.org/show_bug.cgi?id=65440  | 
            
            
              | 148 | 
              			if (webkit_req_fs && name !== "download") { | 
            
            
              | 149 | 
              				name += ".download";  | 
            
            
              | 150 | 
              			}  | 
            
            
              | 151 | 
              			if (type === force_saveable_type || webkit_req_fs) { | 
            
            
              | 152 | 
              				target_view = view;  | 
            
            
              | 153 | 
              			}  | 
            
            
              | 154 | 
              			if (!req_fs) { | 
            
            
              | 155 | 
              				fs_error();  | 
            
            
              | 156 | 
              				return;  | 
            
            
              | 157 | 
              			}  | 
            
            
              | 158 | 
              			fs_min_size += blob.size;  | 
            
            
              | 159 | 
              			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { | 
            
            
              | 160 | 
              				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { | 
            
            
              | 161 | 
              					var save = function() { | 
            
            
              | 162 | 
              						dir.getFile(name, create_if_not_found, abortable(function(file) { | 
            
            
              | 163 | 
              							file.createWriter(abortable(function(writer) { | 
            
            
              | 164 | 
              								writer.onwriteend = function(event) { | 
            
            
              | 165 | 
              									target_view.location.href = file.toURL();  | 
            
            
              | 166 | 
              									deletion_queue.push(file);  | 
            
            
              | 167 | 
              									filesaver.readyState = filesaver.DONE;  | 
            
            
              | 168 | 
              									dispatch(filesaver, "writeend", event);  | 
            
            
              | 169 | 
              								};  | 
            
            
              | 170 | 
              								writer.onerror = function() { | 
            
            
              | 171 | 
              									var error = writer.error;  | 
            
            
              | 172 | 
              									if (error.code !== error.ABORT_ERR) { | 
            
            
              | 173 | 
              										fs_error();  | 
            
            
              | 174 | 
              									}  | 
            
            
              | 175 | 
              								};  | 
            
            
              | 176 | 
              								"writestart progress write abort".split(" ").forEach(function(event) { | 
            
            
              | 177 | 
              									writer["on" + event] = filesaver["on" + event];  | 
            
            
              | 178 | 
              								});  | 
            
            
              | 179 | 
              								writer.write(blob);  | 
            
            
              | 180 | 
              								filesaver.abort = function() { | 
            
            
              | 181 | 
              									writer.abort();  | 
            
            
              | 182 | 
              									filesaver.readyState = filesaver.DONE;  | 
            
            
              | 183 | 
              								};  | 
            
            
              | 184 | 
              								filesaver.readyState = filesaver.WRITING;  | 
            
            
              | 185 | 
              							}), fs_error);  | 
            
            
              | 186 | 
              						}), fs_error);  | 
            
            
              | 187 | 
              					};  | 
            
            
              | 188 | 
              					dir.getFile(name, {create: false}, abortable(function(file) { | 
            
            
              | 189 | 
              						// delete file if it already exists  | 
            
            
              | 190 | 
              						file.remove();  | 
            
            
              | 191 | 
              						save();  | 
            
            
              | 192 | 
              					}), abortable(function(ex) { | 
            
            
              | 193 | 
              						if (ex.code === ex.NOT_FOUND_ERR) { | 
            
            
              | 194 | 
              							save();  | 
            
            
              | 195 | 
              						} else { | 
            
            
              | 196 | 
              							fs_error();  | 
            
            
              | 197 | 
              						}  | 
            
            
              | 198 | 
              					}));  | 
            
            
              | 199 | 
              				}), fs_error);  | 
            
            
              | 200 | 
              			}), fs_error);  | 
            
            
              | 201 | 
              		}  | 
            
            
              | 202 | 
              		, FS_proto = FileSaver.prototype  | 
            
            
              | 203 | 
              		, saveAs = function(blob, name) { | 
            
            
              | 204 | 
              			return new FileSaver(blob, name);  | 
            
            
              | 205 | 
              		}  | 
            
            
              | 206 | 
              	;  | 
            
            
              | 207 | 
              	FS_proto.abort = function() { | 
            
            
              | 208 | 
              		var filesaver = this;  | 
            
            
              | 209 | 
              		filesaver.readyState = filesaver.DONE;  | 
            
            
              | 210 | 
              		dispatch(filesaver, "abort");  | 
            
            
              | 211 | 
              	};  | 
            
            
              | 212 | 
              	FS_proto.readyState = FS_proto.INIT = 0;  | 
            
            
              | 213 | 
              	FS_proto.WRITING = 1;  | 
            
            
              | 214 | 
              	FS_proto.DONE = 2;  | 
            
            
              | 215 | 
               | 
            
            
              | 216 | 
              	FS_proto.error =  | 
            
            
              | 217 | 
              	FS_proto.onwritestart =  | 
            
            
              | 218 | 
              	FS_proto.onprogress =  | 
            
            
              | 219 | 
              	FS_proto.onwrite =  | 
            
            
              | 220 | 
              	FS_proto.onabort =  | 
            
            
              | 221 | 
              	FS_proto.onerror =  | 
            
            
              | 222 | 
              	FS_proto.onwriteend =  | 
            
            
              | 223 | 
              		null;  | 
            
            
              | 224 | 
               | 
            
            
              | 225 | 
              	view.addEventListener("unload", process_deletion_queue, false); | 
            
            
              | 226 | 
              	return saveAs;  | 
            
            
              | 227 | 
              }(this.self || this.window || this.content));  | 
            
            
              | 228 | 
              // `self` is undefined in Firefox for Android content script context  | 
            
            
              | 229 | 
              // while `this` is nsIContentFrameMessageManager  | 
            
            
              | 230 | 
              // with an attribute `content` that corresponds to the window  | 
            
            
              | 231 | 
               | 
            
            
              | 232 | 
              if (typeof module !== 'undefined') module.exports = saveAs;  |