mirror of
https://github.com/photonstorm/phaser
synced 2024-11-28 07:31:11 +00:00
Merge pull request #3071 from pavle-goloskokovic/master
Adding fallback for loading files on browsers where URL API is not supported
This commit is contained in:
commit
dc592967ae
6 changed files with 62 additions and 335 deletions
|
@ -162,4 +162,52 @@ var File = new Class({
|
|||
|
||||
});
|
||||
|
||||
/**
|
||||
* Static method for creating object URL using URL API and setting it as image 'src' attribute.
|
||||
* If URL API is not supported (usually on old browsers) it falls back to creating Base64 encoded url using FileReader.
|
||||
*
|
||||
* @method createObjectURL
|
||||
* @static
|
||||
* @param image {Image} Image object which 'src' attribute should be set to object URL.
|
||||
* @param blob {Blob} A Blob object to create an object URL for.
|
||||
* @param defaultType {string} Default mime type used if blob type is not available.
|
||||
*/
|
||||
File.createObjectURL = function (image, blob, defaultType)
|
||||
{
|
||||
if(URL)
|
||||
{
|
||||
image.src = URL.createObjectURL(blob);
|
||||
}
|
||||
else
|
||||
{
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function()
|
||||
{
|
||||
delete image.crossOrigin;
|
||||
image.src = 'data:' + (blob.type || defaultType) + ';base64,' + reader.result.split(',')[1];
|
||||
};
|
||||
|
||||
reader.onerror = image.onerror;
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Static method for releasing an existing object URL which was previously created
|
||||
* by calling {@link File#createObjectURL} method.
|
||||
*
|
||||
* @method revokeObjectURL
|
||||
* @static
|
||||
* @param image {Image} Image object which 'src' attribute should be revoked.
|
||||
*/
|
||||
File.revokeObjectURL = function (image)
|
||||
{
|
||||
if(URL)
|
||||
{
|
||||
URL.revokeObjectURL(image.src);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = File;
|
||||
|
|
|
@ -74,7 +74,7 @@ var HTMLFile = new Class({
|
|||
|
||||
this.data.onload = function ()
|
||||
{
|
||||
URL.revokeObjectURL(_this.data.src);
|
||||
File.revokeObjectURL(_this.data);
|
||||
|
||||
_this.onComplete();
|
||||
|
||||
|
@ -83,14 +83,14 @@ var HTMLFile = new Class({
|
|||
|
||||
this.data.onerror = function ()
|
||||
{
|
||||
URL.revokeObjectURL(_this.data.src);
|
||||
File.revokeObjectURL(_this.data);
|
||||
|
||||
_this.state = CONST.FILE_ERRORED;
|
||||
|
||||
callback(_this);
|
||||
};
|
||||
|
||||
this.data.src = URL.createObjectURL(blob);
|
||||
File.createObjectURL(this.data, blob, 'image/svg+xml');
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -56,7 +56,7 @@ var ImageFile = new Class({
|
|||
|
||||
this.data.onload = function ()
|
||||
{
|
||||
URL.revokeObjectURL(_this.data.src);
|
||||
File.revokeObjectURL(_this.data);
|
||||
|
||||
_this.onComplete();
|
||||
|
||||
|
@ -65,14 +65,15 @@ var ImageFile = new Class({
|
|||
|
||||
this.data.onerror = function ()
|
||||
{
|
||||
URL.revokeObjectURL(_this.data.src);
|
||||
File.revokeObjectURL(_this.data);
|
||||
|
||||
_this.state = CONST.FILE_ERRORED;
|
||||
|
||||
callback(_this);
|
||||
};
|
||||
|
||||
this.data.src = URL.createObjectURL(this.xhrLoader.response);
|
||||
File.createObjectURL(this.data, this.xhrLoader.response, 'image/png');
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -56,7 +56,10 @@ var SVGFile = new Class({
|
|||
|
||||
this.data.onload = function ()
|
||||
{
|
||||
URL.revokeObjectURL(_this.data.src);
|
||||
if(!retry)
|
||||
{
|
||||
File.revokeObjectURL(_this.data);
|
||||
}
|
||||
|
||||
_this.onComplete();
|
||||
|
||||
|
@ -65,16 +68,14 @@ var SVGFile = new Class({
|
|||
|
||||
this.data.onerror = function ()
|
||||
{
|
||||
URL.revokeObjectURL(_this.data.src);
|
||||
|
||||
// Safari 8 re-try
|
||||
if (!retry)
|
||||
{
|
||||
retry = true;
|
||||
|
||||
var url = 'data:image/svg+xml,' + encodeURIComponent(svg.join(''));
|
||||
File.revokeObjectURL(_this.data);
|
||||
|
||||
_this.data.src = URL.createObjectURL(url);
|
||||
_this.data.src = 'data:image/svg+xml,' + encodeURIComponent(svg.join(''));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -84,7 +85,7 @@ var SVGFile = new Class({
|
|||
}
|
||||
};
|
||||
|
||||
this.data.src = URL.createObjectURL(blob);
|
||||
File.createObjectURL(this.data, blob, 'image/svg+xml');
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -1,322 +0,0 @@
|
|||
var g = (typeof global !== 'undefined') ? global
|
||||
: ((typeof window !== 'undefined') ? window
|
||||
: ((typeof self !== 'undefined') ? self : this));
|
||||
|
||||
|
||||
(function(global) {
|
||||
/**
|
||||
* Polyfill URLSearchParams
|
||||
*
|
||||
* Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js
|
||||
*/
|
||||
|
||||
var checkIfIteratorIsSupported = function() {
|
||||
try {
|
||||
return !!Symbol.iterator;
|
||||
} catch(error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var iteratorSupported = checkIfIteratorIsSupported();
|
||||
|
||||
var createIterator = function(items) {
|
||||
var iterator = {
|
||||
next: function() {
|
||||
var value = items.shift();
|
||||
return { done: value === void 0, value: value };
|
||||
}
|
||||
};
|
||||
|
||||
if(iteratorSupported) {
|
||||
iterator[Symbol.iterator] = function() {
|
||||
return iterator;
|
||||
};
|
||||
}
|
||||
|
||||
return iterator;
|
||||
};
|
||||
|
||||
var polyfillURLSearchParams= function() {
|
||||
|
||||
var URLSearchParams = function(searchString) {
|
||||
Object.defineProperty(this, '_entries', { value: {} });
|
||||
|
||||
if(typeof searchString === 'string') {
|
||||
if(searchString !== '') {
|
||||
searchString = searchString.replace(/^\?/, '');
|
||||
var attributes = searchString.split('&');
|
||||
var attribute;
|
||||
for(var i = 0; i < attributes.length; i++) {
|
||||
attribute = attributes[i].split('=');
|
||||
this.append(
|
||||
decodeURIComponent(attribute[0]),
|
||||
(attribute.length > 1) ? decodeURIComponent(attribute[1]) : ''
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if(searchString instanceof URLSearchParams) {
|
||||
var _this = this;
|
||||
searchString.forEach(function(value, name) {
|
||||
_this.append(value, name);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var proto = URLSearchParams.prototype;
|
||||
|
||||
proto.append = function(name, value) {
|
||||
if(name in this._entries) {
|
||||
this._entries[name].push(value.toString());
|
||||
} else {
|
||||
this._entries[name] = [value.toString()];
|
||||
}
|
||||
};
|
||||
|
||||
proto.delete = function(name) {
|
||||
delete this._entries[name];
|
||||
};
|
||||
|
||||
proto.get = function(name) {
|
||||
return (name in this._entries) ? this._entries[name][0] : null;
|
||||
};
|
||||
|
||||
proto.getAll = function(name) {
|
||||
return (name in this._entries) ? this._entries[name].slice(0) : [];
|
||||
};
|
||||
|
||||
proto.has = function(name) {
|
||||
return (name in this._entries);
|
||||
};
|
||||
|
||||
proto.set = function(name, value) {
|
||||
this._entries[name] = [value.toString()];
|
||||
};
|
||||
|
||||
proto.forEach = function(callback, thisArg) {
|
||||
var entries;
|
||||
for(var name in this._entries) {
|
||||
if(this._entries.hasOwnProperty(name)) {
|
||||
entries = this._entries[name];
|
||||
for(var i = 0; i < entries.length; i++) {
|
||||
callback.call(thisArg, entries[i], name, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
proto.keys = function() {
|
||||
var items = [];
|
||||
this.forEach(function(value, name) { items.push(name); });
|
||||
return createIterator(items);
|
||||
};
|
||||
|
||||
proto.values = function() {
|
||||
var items = [];
|
||||
this.forEach(function(value) { items.push(value); });
|
||||
return createIterator(items);
|
||||
};
|
||||
|
||||
proto.entries = function() {
|
||||
var items = [];
|
||||
this.forEach(function(value, name) { items.push([name, value]); });
|
||||
return createIterator(items);
|
||||
};
|
||||
|
||||
if(iteratorSupported) {
|
||||
proto[Symbol.iterator] = proto.entries;
|
||||
}
|
||||
|
||||
proto.toString = function() {
|
||||
var searchString = '';
|
||||
this.forEach(function(value, name) {
|
||||
if(searchString.length > 0) searchString+= '&';
|
||||
searchString += encodeURIComponent(name) + '=' + encodeURIComponent(value);
|
||||
});
|
||||
return searchString;
|
||||
};
|
||||
|
||||
global.URLSearchParams = URLSearchParams;
|
||||
};
|
||||
|
||||
if(!('URLSearchParams' in global)) {
|
||||
polyfillURLSearchParams();
|
||||
}
|
||||
|
||||
// HTMLAnchorElement
|
||||
|
||||
})(g);
|
||||
|
||||
(function(global) {
|
||||
/**
|
||||
* Polyfill URL
|
||||
*
|
||||
* Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js
|
||||
*/
|
||||
|
||||
var checkIfURLIsSupported = function() {
|
||||
try {
|
||||
var u = new URL('b', 'http://a');
|
||||
u.pathname = 'c%20d';
|
||||
return (u.href === 'http://a/c%20d') && u.searchParams;
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var polyfillURL = function() {
|
||||
var _URL = global.URL;
|
||||
|
||||
var URL = function(url, base) {
|
||||
if(typeof url !== 'string') throw new TypeError('Failed to construct \'URL\': Invalid URL');
|
||||
|
||||
var doc = document.implementation.createHTMLDocument('');
|
||||
window.doc = doc;
|
||||
if(base) {
|
||||
var baseElement = doc.createElement('base');
|
||||
baseElement.href = base;
|
||||
doc.head.appendChild(baseElement);
|
||||
}
|
||||
|
||||
var anchorElement = doc.createElement('a');
|
||||
anchorElement.href = url;
|
||||
doc.body.appendChild(anchorElement);
|
||||
anchorElement.href = anchorElement.href; // force href to refresh
|
||||
|
||||
if(anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) {
|
||||
throw new TypeError('Invalid URL');
|
||||
}
|
||||
|
||||
Object.defineProperty(this, '_anchorElement', {
|
||||
value: anchorElement
|
||||
});
|
||||
};
|
||||
|
||||
var proto = URL.prototype;
|
||||
|
||||
var linkURLWithAnchorAttribute = function(attributeName) {
|
||||
Object.defineProperty(proto, attributeName, {
|
||||
get: function() {
|
||||
return this._anchorElement[attributeName];
|
||||
},
|
||||
set: function(value) {
|
||||
this._anchorElement[attributeName] = value;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
};
|
||||
|
||||
['hash', 'host', 'hostname', 'port', 'protocol', 'search']
|
||||
.forEach(function(attributeName) {
|
||||
linkURLWithAnchorAttribute(attributeName);
|
||||
});
|
||||
|
||||
Object.defineProperties(proto, {
|
||||
|
||||
'toString': {
|
||||
get: function() {
|
||||
var _this = this;
|
||||
return function() {
|
||||
return _this.href;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
'href' : {
|
||||
get: function() {
|
||||
return this._anchorElement.href.replace(/\?$/,'');
|
||||
},
|
||||
set: function(value) {
|
||||
this._anchorElement.href = value;
|
||||
},
|
||||
enumerable: true
|
||||
},
|
||||
|
||||
'pathname' : {
|
||||
get: function() {
|
||||
return this._anchorElement.pathname.replace(/(^\/?)/,'/');
|
||||
},
|
||||
set: function(value) {
|
||||
this._anchorElement.pathname = value;
|
||||
},
|
||||
enumerable: true
|
||||
},
|
||||
|
||||
'origin': {
|
||||
get: function() {
|
||||
return this._anchorElement.protocol + '//' + this._anchorElement.hostname + (this._anchorElement.port ? (':' + this._anchorElement.port) : '');
|
||||
},
|
||||
enumerable: true
|
||||
},
|
||||
|
||||
'password': { // TODO
|
||||
get: function() {
|
||||
return '';
|
||||
},
|
||||
set: function(value) {
|
||||
},
|
||||
enumerable: true
|
||||
},
|
||||
|
||||
'username': { // TODO
|
||||
get: function() {
|
||||
return '';
|
||||
},
|
||||
set: function(value) {
|
||||
},
|
||||
enumerable: true
|
||||
},
|
||||
|
||||
'searchParams': {
|
||||
get: function() {
|
||||
var searchParams = new URLSearchParams(this.search);
|
||||
var _this = this;
|
||||
['append', 'delete', 'set'].forEach(function(methodName) {
|
||||
var method = searchParams[methodName];
|
||||
searchParams[methodName] = function() {
|
||||
method.apply(searchParams, arguments);
|
||||
_this.search = searchParams.toString();
|
||||
};
|
||||
});
|
||||
return searchParams;
|
||||
},
|
||||
enumerable: true
|
||||
}
|
||||
});
|
||||
|
||||
URL.createObjectURL = function(blob) {
|
||||
return _URL.createObjectURL.apply(_URL, arguments);
|
||||
};
|
||||
|
||||
URL.revokeObjectURL = function(url) {
|
||||
return _URL.revokeObjectURL.apply(_URL, arguments);
|
||||
};
|
||||
|
||||
global.URL = URL;
|
||||
|
||||
};
|
||||
|
||||
if(!checkIfURLIsSupported()) {
|
||||
polyfillURL();
|
||||
}
|
||||
|
||||
if((global.location !== void 0) && !('origin' in global.location)) {
|
||||
var getOrigin = function() {
|
||||
return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : '');
|
||||
};
|
||||
|
||||
try {
|
||||
Object.defineProperty(global.location, 'origin', {
|
||||
get: getOrigin,
|
||||
enumerable: true
|
||||
});
|
||||
} catch(e) {
|
||||
setInterval(function() {
|
||||
global.location.origin = getOrigin();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
})(g);
|
|
@ -7,4 +7,3 @@ require('./Math.trunc');
|
|||
require('./performance.now');
|
||||
require('./requestAnimationFrame');
|
||||
require('./Uint32Array');
|
||||
require('./URL');
|
||||
|
|
Loading…
Reference in a new issue