UNPKG

6.7 kBJavaScriptView Raw
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 'use strict'
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)