|
9 | 9 | * https://opensource.org/licenses/MIT
|
10 | 10 | */
|
11 | 11 |
|
12 |
| -/* global define, webkitURL, module */ |
| 12 | +/* global define, module, Promise, webkitURL */ |
13 | 13 |
|
14 | 14 | ;(function ($) {
|
15 | 15 | 'use strict'
|
16 | 16 |
|
17 | 17 | /**
|
18 | 18 | * Loads an image for a given File object.
|
19 |
| - * Invokes the callback with an img or optional canvas element |
20 |
| - * (if supported by the browser) as parameter:. |
21 | 19 | *
|
22 | 20 | * @param {File|Blob|string} file File or Blob object or image URL
|
23 |
| - * @param {Function} [callback] Image load event callback |
| 21 | + * @param {Function|object} [callback] Image load event callback or options |
24 | 22 | * @param {object} [options] Options object
|
25 |
| - * @returns {HTMLImageElement|HTMLCanvasElement|FileReader} image object |
| 23 | + * @returns {HTMLImageElement|HTMLCanvasElement|FileReader|Promise} Object |
26 | 24 | */
|
27 | 25 | function loadImage(file, callback, options) {
|
28 |
| - var img = document.createElement('img') |
29 |
| - var url |
30 | 26 | /**
|
31 |
| - * Callback for the fetchBlob call. |
| 27 | + * Promise executor |
32 | 28 | *
|
33 |
| - * @param {Blob} blob Blob object |
34 |
| - * @param {Error} err Error object |
| 29 | + * @param {Function} resolve Resolution function |
| 30 | + * @param {Function} reject Rejection function |
| 31 | + * @returns {HTMLImageElement|HTMLCanvasElement|FileReader} Object |
35 | 32 | */
|
36 |
| - function fetchBlobCallback(blob, err) { |
37 |
| - if (err) console.log(err) // eslint-disable-line no-console |
38 |
| - if (blob && loadImage.isInstanceOf('Blob', blob)) { |
39 |
| - // eslint-disable-next-line no-param-reassign |
40 |
| - file = blob |
41 |
| - url = loadImage.createObjectURL(file) |
42 |
| - } else { |
43 |
| - url = file |
44 |
| - if (options && options.crossOrigin) { |
45 |
| - img.crossOrigin = options.crossOrigin |
| 33 | + function executor(resolve, reject) { |
| 34 | + var img = document.createElement('img') |
| 35 | + var url |
| 36 | + /** |
| 37 | + * Callback for the fetchBlob call. |
| 38 | + * |
| 39 | + * @param {HTMLImageElement|HTMLCanvasElement} img Error object |
| 40 | + * @param {object} data Data object |
| 41 | + * @returns {undefined} Undefined |
| 42 | + */ |
| 43 | + function resolveWrapper(img, data) { |
| 44 | + if (resolve === reject) { |
| 45 | + // Not using Promises |
| 46 | + if (resolve) resolve(img, data) |
| 47 | + return |
46 | 48 | }
|
| 49 | + data = data || {} // eslint-disable-line no-param-reassign |
| 50 | + data.image = img |
| 51 | + resolve(data) |
47 | 52 | }
|
48 |
| - img.src = url |
49 |
| - } |
50 |
| - img.onerror = function (event) { |
51 |
| - return loadImage.onerror(img, event, file, url, callback, options) |
52 |
| - } |
53 |
| - img.onload = function (event) { |
54 |
| - return loadImage.onload(img, event, file, url, callback, options) |
55 |
| - } |
56 |
| - if (typeof file === 'string') { |
57 |
| - if (loadImage.requiresMetaData(options)) { |
58 |
| - loadImage.fetchBlob(file, fetchBlobCallback, options) |
59 |
| - } else { |
60 |
| - fetchBlobCallback() |
61 |
| - } |
62 |
| - return img |
63 |
| - } else if ( |
64 |
| - loadImage.isInstanceOf('Blob', file) || |
65 |
| - // Files are also Blob instances, but some browsers |
66 |
| - // (Firefox 3.6) support the File API but not Blobs: |
67 |
| - loadImage.isInstanceOf('File', file) |
68 |
| - ) { |
69 |
| - url = loadImage.createObjectURL(file) |
70 |
| - if (url) { |
| 53 | + /** |
| 54 | + * Callback for the fetchBlob call. |
| 55 | + * |
| 56 | + * @param {Blob} blob Blob object |
| 57 | + * @param {Error} err Error object |
| 58 | + */ |
| 59 | + function fetchBlobCallback(blob, err) { |
| 60 | + if (err && $.console) console.log(err) // eslint-disable-line no-console |
| 61 | + if (blob && loadImage.isInstanceOf('Blob', blob)) { |
| 62 | + file = blob // eslint-disable-line no-param-reassign |
| 63 | + url = loadImage.createObjectURL(file) |
| 64 | + } else { |
| 65 | + url = file |
| 66 | + if (options && options.crossOrigin) { |
| 67 | + img.crossOrigin = options.crossOrigin |
| 68 | + } |
| 69 | + } |
71 | 70 | img.src = url
|
72 |
| - return img |
73 | 71 | }
|
74 |
| - return loadImage.readFile(file, function (e) { |
75 |
| - var target = e.target |
76 |
| - if (target && target.result) { |
77 |
| - img.src = target.result |
78 |
| - } else if (callback) { |
79 |
| - callback(e) |
| 72 | + img.onerror = function (event) { |
| 73 | + return loadImage.onerror(img, event, file, url, reject, options) |
| 74 | + } |
| 75 | + img.onload = function (event) { |
| 76 | + return loadImage.onload(img, event, file, url, resolveWrapper, options) |
| 77 | + } |
| 78 | + if (typeof file === 'string') { |
| 79 | + if (loadImage.requiresMetaData(options)) { |
| 80 | + loadImage.fetchBlob(file, fetchBlobCallback, options) |
| 81 | + } else { |
| 82 | + fetchBlobCallback() |
80 | 83 | }
|
81 |
| - }) |
| 84 | + return img |
| 85 | + } else if ( |
| 86 | + loadImage.isInstanceOf('Blob', file) || |
| 87 | + // Files are also Blob instances, but some browsers |
| 88 | + // (Firefox 3.6) support the File API but not Blobs: |
| 89 | + loadImage.isInstanceOf('File', file) |
| 90 | + ) { |
| 91 | + url = loadImage.createObjectURL(file) |
| 92 | + if (url) { |
| 93 | + img.src = url |
| 94 | + return img |
| 95 | + } |
| 96 | + return loadImage.readFile(file, function (e) { |
| 97 | + var target = e.target |
| 98 | + if (target && target.result) { |
| 99 | + img.src = target.result |
| 100 | + } else if (reject) { |
| 101 | + reject(e) |
| 102 | + } |
| 103 | + }) |
| 104 | + } |
82 | 105 | }
|
| 106 | + if ($.Promise && typeof callback !== 'function') { |
| 107 | + options = callback // eslint-disable-line no-param-reassign |
| 108 | + return new Promise(executor) |
| 109 | + } |
| 110 | + return executor(callback, callback) |
83 | 111 | }
|
84 | 112 | // The check for URL.revokeObjectURL fixes an issue with Opera 12,
|
85 | 113 | // which provides URL.createObjectURL but doesn't properly implement it:
|
|
100 | 128 | }
|
101 | 129 | }
|
102 | 130 |
|
103 |
| - // Determines if meta data should be loaded automatically. |
104 |
| - // Requires the load image meta extension to load meta data. |
| 131 | + // Determines if metadata should be loaded automatically. |
| 132 | + // Requires the load image meta extension to load metadata. |
105 | 133 | loadImage.requiresMetaData = function (options) {
|
106 | 134 | return options && options.meta
|
107 | 135 | }
|
|
131 | 159 |
|
132 | 160 | loadImage.onload = function (img, event, file, url, callback, options) {
|
133 | 161 | revokeHelper(url, options)
|
134 |
| - if (callback) { |
135 |
| - loadImage.transform(img, options, callback, file, { |
136 |
| - originalWidth: img.naturalWidth || img.width, |
137 |
| - originalHeight: img.naturalHeight || img.height |
138 |
| - }) |
139 |
| - } |
| 162 | + loadImage.transform(img, options, callback, file, { |
| 163 | + originalWidth: img.naturalWidth || img.width, |
| 164 | + originalHeight: img.naturalHeight || img.height |
| 165 | + }) |
140 | 166 | }
|
141 | 167 |
|
142 | 168 | loadImage.createObjectURL = function (file) {
|
|
0 commit comments