Reputation: 12112
The following load
function is not being recognised in Safari on macOS, but works perfectly in Chrome and Firefox (all on latest stable releases as of today, jquery is v3.1.0):
Image.prototype.load = function (url) {
var thisImg = this;
xmlHTTP = new XMLHttpRequest();
xmlHTTP.open('GET', url, true);
xmlHTTP.responseType = 'arraybuffer';
xmlHTTP.onload = function (e) {
var blob = new Blob([this.response]);
thisImg.src = window.URL.createObjectURL(blob);
};
xmlHTTP.onprogress = function (e) {
var percLoaded = parseInt((e.loaded / e.total) * 100);
thisImg.completedPercentage = percLoaded;
};
xmlHTTP.onloadstart = function () {
thisImg.completedPercentage = 0;
};
xmlHTTP.onloadend = function() {
thisImg.completedPercentage = 100;
// put the image blob we just created in the dom
createImgElement(index, img);
};
xmlHTTP.onabort = function() {
console.log('abort called.');
};
xmlHTTP.send();
};
Image.prototype.completedPercentage = 0;
var imgURL = '/folder/example.jpg';
var img = new Image();
img.load(imgURL);
Safari reports that:
jQuery.Deferred exception: img.load is not a function. (In 'img.load(imgURL)', 'img.load' is undefined)
I don't understand, as Image.prototype.load
is very evidently declared a few lines above it. Researching jquery
load
issues on Safari, I've come across a few that seem to have since been addressed in updates. I haven't come across any that show a load
function ontop of an Image
object being classed as undefined.
MDN web docs suggest that object.prototype
is compatible with Safari.
I'm pretty stumped. There seems to be no mention of incompatibilities in this area with Safari. Similar question on SO and elsewhere usually end up as a scope or order issue. That's still my best hunch but I've gone over this again and again and tried switching orders just for empirical evidence it's not the issue. Those have all resulted in understandable undefined
errors, but this... I can't get my around.
https://jsfiddle.net/14no0q12/
If you check the console in most browsers it will report that:
Uncaught ReferenceError: createImgElement is not defined
at XMLHttpRequest.xmlHTTP.onloadend ((index):64)
which makes sense, I haven't provided that function in the example. However, run the example in Safari and it doesn't get as far as seeing this function doesn't exist. Instead, it aborts after reporting:
TypeError: img.load is not a function. (In 'img.load(imgURL)', 'img.load' is undefined)
console.log(img)
straight after its creation is successfully reporting back the existence of the object without errors in all browsers.
console.log(img.__proto__)
at the same point shows load
is present on Chrome and Firefox but absent in the list of functions in Safari. Something about declaring Image.prototype.load = function()
is not satisfying Safari that this is a function to attach to an inherited object.
My problem code, reduced to its simplest form is still still producing the same error:
Image.prototype.load = function () {
console.log('Success!');
};
var img = new Image();
img.load(); // produces the same undefined error
Although, if I create my own object, it works?
function testObject() {};
testObject.prototype.load = function () {
console.log('Success!');
};
var img = new testObject();
img.load(); // outputs 'success!'
Something about using established javascript objects is not working in Safari. How do I go about defining this properly?
Upvotes: 1
Views: 635
Reputation: 12112
A user in the later version of this question left a comment that led me to suspect this may be a bug with my version of Safari (10.1), which was the latest version for the version of macOS I was using (10.12.4) but the latest release (10.1.2) for the latest release of macOS (10.12.6).
I've just upgraded macOS and Safari to these latest versions and the problem remains. Unexpected but helpful in isolating what the problem is. I disable all extensions and suddenly it works. Frustrated I didn't try this originally (I didn't think a core aspect of javascript would be affected) I tried each extension individually and found the culprit to be the current beta of uBlock Origin.
I don't have a solution yet (other than not using the extension) but have an answer, at least, and will not raise the question with them.
Upvotes: 1