diff --git a/src/pattern.class.js b/src/pattern.class.js index 4103f56212f..6c4ed865df1 100644 --- a/src/pattern.class.js +++ b/src/pattern.class.js @@ -75,9 +75,9 @@ // img src string var _this = this; this.source = fabric.util.createImage(); - fabric.util.loadImage(options.source, function(img) { + fabric.util.loadImage(options.source, function(img, isError) { _this.source = img; - callback && callback(_this); + callback && callback(_this, isError); }, null, this.crossOrigin); } }, diff --git a/src/shapes/image.class.js b/src/shapes/image.class.js index be5d3e90588..714912febc5 100644 --- a/src/shapes/image.class.js +++ b/src/shapes/image.class.js @@ -380,10 +380,10 @@ * @chainable */ setSrc: function(src, callback, options) { - fabric.util.loadImage(src, function(img) { + fabric.util.loadImage(src, function(img, isError) { this.setElement(img, options); this._setWidthHeight(); - callback && callback(this); + callback && callback(this, isError); }, this, options && options.crossOrigin); return this; }, @@ -687,9 +687,9 @@ */ fabric.Image.fromObject = function(_object, callback) { var object = fabric.util.object.clone(_object); - fabric.util.loadImage(object.src, function(img, error) { - if (error) { - callback && callback(null, error); + fabric.util.loadImage(object.src, function(img, isError) { + if (isError) { + callback && callback(null, true); return; } fabric.Image.prototype._initFilters.call(object, object.filters, function(filters) { @@ -699,7 +699,7 @@ fabric.util.enlivenObjects([object.clipPath], function(enlivedProps) { object.clipPath = enlivedProps[0]; var image = new fabric.Image(img, object); - callback(image); + callback(image, false); }); }); }); @@ -710,12 +710,12 @@ * Creates an instance of fabric.Image from an URL string * @static * @param {String} url URL to create an image from - * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument) + * @param {Function} [callback] Callback to invoke when image is created (newly created image is passed as a first argument). Second argument is a boolean indicating if an error occured or not. * @param {Object} [imgOptions] Options object */ fabric.Image.fromURL = function(url, callback, imgOptions) { - fabric.util.loadImage(url, function(img) { - callback && callback(new fabric.Image(img, imgOptions)); + fabric.util.loadImage(url, function(img, isError) { + callback && callback(new fabric.Image(img, imgOptions), isError); }, null, imgOptions && imgOptions.crossOrigin); }; diff --git a/src/static_canvas.class.js b/src/static_canvas.class.js index 8f204491da6..1a83f664e4d 100644 --- a/src/static_canvas.class.js +++ b/src/static_canvas.class.js @@ -296,7 +296,7 @@ * originY: 'top' * }); * @example Stretched overlayImage #1 - width/height correspond to canvas width/height - * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) { + * fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img, isError) { * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); * canvas.setOverlayImage(img, canvas.renderAll.bind(canvas)); * }); @@ -347,7 +347,7 @@ * originY: 'top' * }); * @example Stretched backgroundImage #1 - width/height correspond to canvas width/height - * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) { + * fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img, isError) { * img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'}); * canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas)); * }); @@ -442,25 +442,25 @@ * @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage} * or {@link fabric.StaticCanvas#overlayImage|overlayImage}) * @param {(fabric.Image|String|null)} image fabric.Image instance, URL of an image or null to set background or overlay to - * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay + * @param {Function} callback Callback to invoke when image is loaded and set as background or overlay. The first argument is the created image, the second argument is a flag indicating whether an error occured or not. * @param {Object} [options] Optional options to set for the {@link fabric.Image|image}. */ __setBgOverlayImage: function(property, image, callback, options) { if (typeof image === 'string') { - fabric.util.loadImage(image, function(img) { + fabric.util.loadImage(image, function(img, isError) { if (img) { var instance = new fabric.Image(img, options); this[property] = instance; instance.canvas = this; } - callback && callback(img); + callback && callback(img, isError); }, this, options && options.crossOrigin); } else { options && image.setOptions(options); this[property] = image; image && (image.canvas = this); - callback && callback(image); + callback && callback(image, false); } return this; diff --git a/src/util/misc.js b/src/util/misc.js index 207ead2741c..7d1921262e8 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -345,7 +345,7 @@ /** @ignore */ var onLoadCallback = function () { - callback && callback.call(context, img); + callback && callback.call(context, img, false); img = img.onload = img.onerror = null; }; diff --git a/test/lib/visualTestLoop.js b/test/lib/visualTestLoop.js index 89d4528d71e..ff9473d4641 100644 --- a/test/lib/visualTestLoop.js +++ b/test/lib/visualTestLoop.js @@ -76,11 +76,11 @@ var img = fabric.document.createElement('img'); img.onload = function() { img.onload = null; - callback(img); + callback(img, false); }; img.onerror = function(err) { img.onerror = null; - callback(img); + callback(img, true); console.log('Image loading errored', err); }; img.src = filename; diff --git a/test/unit/image.js b/test/unit/image.js index 1364f376cdd..8946a4e9401 100644 --- a/test/unit/image.js +++ b/test/unit/image.js @@ -29,6 +29,8 @@ IMG_WIDTH = 276, IMG_HEIGHT = 110; + var IMG_URL_NON_EXISTING = 'http://www.google.com/non-existing'; + var REFERENCE_IMG_OBJECT = { version: fabric.version, type: 'image', @@ -478,6 +480,16 @@ }); }); + QUnit.test('fromURL error', function(assert) { + var done = assert.async(); + assert.ok(typeof fabric.Image.fromURL === 'function'); + fabric.Image.fromURL(IMG_URL_NON_EXISTING, function(instance, isError) { + assert.ok(instance instanceof fabric.Image); + assert.equal(isError, true); + done(); + }); + }); + QUnit.test('fromElement', function(assert) { var done = assert.async(); diff --git a/test/unit/util.js b/test/unit/util.js index 3ba4bbf90d0..c3b7be67213 100644 --- a/test/unit/util.js +++ b/test/unit/util.js @@ -440,10 +440,11 @@ return; } - fabric.util.loadImage(IMG_URL, function(obj) { + fabric.util.loadImage(IMG_URL, function(obj, isError) { if (obj) { var oImg = new fabric.Image(obj); assert.ok(/fixtures\/very_large_image\.jpg$/.test(oImg.getSrc()), 'image should have correct src'); + assert.ok(!isError); } done(); }); @@ -473,9 +474,10 @@ return; } try { - fabric.util.loadImage(IMG_URL, function(img) { + fabric.util.loadImage(IMG_URL, function(img, isError) { assert.equal(img.src, IMG_URL, 'src is set'); assert.equal(img.crossOrigin, 'anonymous', 'crossOrigin is set'); + assert.ok(!isError); done(); }, null, 'anonymous'); }