1 | /*
|
2 | * JavaScript Load Image
|
3 | * https://github.com/blueimp/JavaScript-Load-Image
|
4 | *
|
5 | * Copyright 2011, Sebastian Tschan
|
6 | * https://blueimp.net
|
7 | *
|
8 | * Licensed under the MIT license:
|
9 | * https://opensource.org/licenses/MIT
|
10 | */
|
11 |
|
12 | /* global define, module, Promise */
|
13 |
|
14 | ;(function ($) {
|
15 |
|
16 |
|
17 | var urlAPI = $.URL || $.webkitURL
|
18 |
|
19 | /**
|
20 | * Creates an object URL for a given File object.
|
21 | *
|
22 | * @param {Blob} blob Blob object
|
23 | * @returns {string|boolean} Returns object URL if API exists, else false.
|
24 | */
|
25 | function createObjectURL(blob) {
|
26 | return urlAPI ? urlAPI.createObjectURL(blob) : false
|
27 | }
|
28 |
|
29 | /**
|
30 | * Revokes a given object URL.
|
31 | *
|
32 | * @param {string} url Blob object URL
|
33 | * @returns {undefined|boolean} Returns undefined if API exists, else false.
|
34 | */
|
35 | function revokeObjectURL(url) {
|
36 | return urlAPI ? urlAPI.revokeObjectURL(url) : false
|
37 | }
|
38 |
|
39 | /**
|
40 | * Helper function to revoke an object URL
|
41 | *
|
42 | * @param {string} url Blob Object URL
|
43 | * @param {object} [options] Options object
|
44 | */
|
45 | function revokeHelper(url, options) {
|
46 | if (url && url.slice(0, 5) === 'blob:' && !(options && options.noRevoke)) {
|
47 | revokeObjectURL(url)
|
48 | }
|
49 | }
|
50 |
|
51 | /**
|
52 | * Loads a given File object via FileReader interface.
|
53 | *
|
54 | * @param {Blob} file Blob object
|
55 | * @param {Function} onload Load event callback
|
56 | * @param {Function} [onerror] Error/Abort event callback
|
57 | * @param {string} [method=readAsDataURL] FileReader method
|
58 | * @returns {FileReader|boolean} Returns FileReader if API exists, else false.
|
59 | */
|
60 | function readFile(file, onload, onerror, method) {
|
61 | if (!$.FileReader) return false
|
62 | var reader = new FileReader()
|
63 | reader.onload = function () {
|
64 | onload.call(reader, this.result)
|
65 | }
|
66 | if (onerror) {
|
67 | reader.onabort = reader.onerror = function () {
|
68 | onerror.call(reader, this.error)
|
69 | }
|
70 | }
|
71 | var readerMethod = reader[method || 'readAsDataURL']
|
72 | if (readerMethod) {
|
73 | readerMethod.call(reader, file)
|
74 | return reader
|
75 | }
|
76 | }
|
77 |
|
78 | /**
|
79 | * Cross-frame instanceof check.
|
80 | *
|
81 | * @param {string} type Instance type
|
82 | * @param {object} obj Object instance
|
83 | * @returns {boolean} Returns true if the object is of the given instance.
|
84 | */
|
85 | function isInstanceOf(type, obj) {
|
86 | // Cross-frame instanceof check
|
87 | return Object.prototype.toString.call(obj) === '[object ' + type + ']'
|
88 | }
|
89 |
|
90 | /**
|
91 | * @typedef { HTMLImageElement|HTMLCanvasElement } Result
|
92 | */
|
93 |
|
94 | /**
|
95 | * Loads an image for a given File object.
|
96 | *
|
97 | * @param {Blob|string} file Blob object or image URL
|
98 | * @param {Function|object} [callback] Image load event callback or options
|
99 | * @param {object} [options] Options object
|
100 | * @returns {HTMLImageElement|FileReader|Promise<Result>} Object
|
101 | */
|
102 | function loadImage(file, callback, options) {
|
103 | /**
|
104 | * Promise executor
|
105 | *
|
106 | * @param {Function} resolve Resolution function
|
107 | * @param {Function} reject Rejection function
|
108 | * @returns {HTMLImageElement|FileReader} Object
|
109 | */
|
110 | function executor(resolve, reject) {
|
111 | var img = document.createElement('img')
|
112 | var url
|
113 | /**
|
114 | * Callback for the fetchBlob call.
|
115 | *
|
116 | * @param {HTMLImageElement|HTMLCanvasElement} img Error object
|
117 | * @param {object} data Data object
|
118 | * @returns {undefined} Undefined
|
119 | */
|
120 | function resolveWrapper(img, data) {
|
121 | if (resolve === reject) {
|
122 | // Not using Promises
|
123 | if (resolve) resolve(img, data)
|
124 | return
|
125 | } else if (img instanceof Error) {
|
126 | reject(img)
|
127 | return
|
128 | }
|
129 | data = data || {} // eslint-disable-line no-param-reassign
|
130 | data.image = img
|
131 | resolve(data)
|
132 | }
|
133 | /**
|
134 | * Callback for the fetchBlob call.
|
135 | *
|
136 | * @param {Blob} blob Blob object
|
137 | * @param {Error} err Error object
|
138 | */
|
139 | function fetchBlobCallback(blob, err) {
|
140 | if (err && $.console) console.log(err) // eslint-disable-line no-console
|
141 | if (blob && isInstanceOf('Blob', blob)) {
|
142 | file = blob // eslint-disable-line no-param-reassign
|
143 | url = createObjectURL(file)
|
144 | } else {
|
145 | url = file
|
146 | if (options && options.crossOrigin) {
|
147 | img.crossOrigin = options.crossOrigin
|
148 | }
|
149 | }
|
150 | img.src = url
|
151 | }
|
152 | img.onerror = function (event) {
|
153 | revokeHelper(url, options)
|
154 | if (reject) reject.call(img, event)
|
155 | }
|
156 | img.onload = function () {
|
157 | revokeHelper(url, options)
|
158 | var data = {
|
159 | originalWidth: img.naturalWidth || img.width,
|
160 | originalHeight: img.naturalHeight || img.height
|
161 | }
|
162 | try {
|
163 | loadImage.transform(img, options, resolveWrapper, file, data)
|
164 | } catch (error) {
|
165 | if (reject) reject(error)
|
166 | }
|
167 | }
|
168 | if (typeof file === 'string') {
|
169 | if (loadImage.requiresMetaData(options)) {
|
170 | loadImage.fetchBlob(file, fetchBlobCallback, options)
|
171 | } else {
|
172 | fetchBlobCallback()
|
173 | }
|
174 | return img
|
175 | } else if (isInstanceOf('Blob', file) || isInstanceOf('File', file)) {
|
176 | url = createObjectURL(file)
|
177 | if (url) {
|
178 | img.src = url
|
179 | return img
|
180 | }
|
181 | return readFile(
|
182 | file,
|
183 | function (url) {
|
184 | img.src = url
|
185 | },
|
186 | reject
|
187 | )
|
188 | }
|
189 | }
|
190 | if ($.Promise && typeof callback !== 'function') {
|
191 | options = callback // eslint-disable-line no-param-reassign
|
192 | return new Promise(executor)
|
193 | }
|
194 | return executor(callback, callback)
|
195 | }
|
196 |
|
197 | // Determines if metadata should be loaded automatically.
|
198 | // Requires the load image meta extension to load metadata.
|
199 | loadImage.requiresMetaData = function (options) {
|
200 | return options && options.meta
|
201 | }
|
202 |
|
203 | // If the callback given to this function returns a blob, it is used as image
|
204 | // source instead of the original url and overrides the file argument used in
|
205 | // the onload and onerror event callbacks:
|
206 | loadImage.fetchBlob = function (url, callback) {
|
207 | callback()
|
208 | }
|
209 |
|
210 | loadImage.transform = function (img, options, callback, file, data) {
|
211 | callback(img, data)
|
212 | }
|
213 |
|
214 | loadImage.global = $
|
215 | loadImage.readFile = readFile
|
216 | loadImage.isInstanceOf = isInstanceOf
|
217 | loadImage.createObjectURL = createObjectURL
|
218 | loadImage.revokeObjectURL = revokeObjectURL
|
219 |
|
220 | if (typeof define === 'function' && define.amd) {
|
221 | define(function () {
|
222 | return loadImage
|
223 | })
|
224 | } else if (typeof module === 'object' && module.exports) {
|
225 | module.exports = loadImage
|
226 | } else {
|
227 | $.loadImage = loadImage
|
228 | }
|
229 | })((typeof window !== 'undefined' && window) || this)
|