Spaces:
Running
Running
/** | |
* SVGInject - Version 1.2.3 | |
* A tiny, intuitive, robust, caching solution for injecting SVG files inline into the DOM. | |
* | |
* https://github.com/iconfu/svg-inject | |
* | |
* Copyright (c) 2018 INCORS, the creators of iconfu.com | |
* @license MIT License - https://github.com/iconfu/svg-inject/blob/master/LICENSE | |
*/ | |
(function(window, document) { | |
// constants for better minification | |
var _CREATE_ELEMENT_ = 'createElement'; | |
var _GET_ELEMENTS_BY_TAG_NAME_ = 'getElementsByTagName'; | |
var _LENGTH_ = 'length'; | |
var _STYLE_ = 'style'; | |
var _TITLE_ = 'title'; | |
var _UNDEFINED_ = 'undefined'; | |
var _SET_ATTRIBUTE_ = 'setAttribute'; | |
var _GET_ATTRIBUTE_ = 'getAttribute'; | |
var NULL = null; | |
// constants | |
var __SVGINJECT = '__svgInject'; | |
var ID_SUFFIX = '--inject-'; | |
var ID_SUFFIX_REGEX = new RegExp(ID_SUFFIX + '\\d+', "g"); | |
var LOAD_FAIL = 'LOAD_FAIL'; | |
var SVG_NOT_SUPPORTED = 'SVG_NOT_SUPPORTED'; | |
var SVG_INVALID = 'SVG_INVALID'; | |
var ATTRIBUTE_EXCLUSION_NAMES = ['src', 'alt', 'onload', 'onerror']; | |
var A_ELEMENT = document[_CREATE_ELEMENT_]('a'); | |
var IS_SVG_SUPPORTED = typeof SVGRect != _UNDEFINED_; | |
var DEFAULT_OPTIONS = { | |
useCache: true, | |
copyAttributes: true, | |
makeIdsUnique: true | |
}; | |
// Map of IRI referenceable tag names to properties that can reference them. This is defined in | |
// https://www.w3.org/TR/SVG11/linking.html#processingIRI | |
var IRI_TAG_PROPERTIES_MAP = { | |
clipPath: ['clip-path'], | |
'color-profile': NULL, | |
cursor: NULL, | |
filter: NULL, | |
linearGradient: ['fill', 'stroke'], | |
marker: ['marker', 'marker-end', 'marker-mid', 'marker-start'], | |
mask: NULL, | |
pattern: ['fill', 'stroke'], | |
radialGradient: ['fill', 'stroke'] | |
}; | |
var INJECTED = 1; | |
var FAIL = 2; | |
var uniqueIdCounter = 1; | |
var xmlSerializer; | |
var domParser; | |
// creates an SVG document from an SVG string | |
function svgStringToSvgDoc(svgStr) { | |
domParser = domParser || new DOMParser(); | |
return domParser.parseFromString(svgStr, 'text/xml'); | |
} | |
// searializes an SVG element to an SVG string | |
function svgElemToSvgString(svgElement) { | |
xmlSerializer = xmlSerializer || new XMLSerializer(); | |
return xmlSerializer.serializeToString(svgElement); | |
} | |
// Returns the absolute url for the specified url | |
function getAbsoluteUrl(url) { | |
A_ELEMENT.href = url; | |
return A_ELEMENT.href; | |
} | |
// Load svg with an XHR request | |
function loadSvg(url, callback, errorCallback) { | |
if (url) { | |
var req = new XMLHttpRequest(); | |
req.onreadystatechange = function() { | |
if (req.readyState == 4) { | |
// readyState is DONE | |
var status = req.status; | |
if (status == 200) { | |
// request status is OK | |
callback(req.responseXML, req.responseText.trim()); | |
} else if (status >= 400) { | |
// request status is error (4xx or 5xx) | |
errorCallback(); | |
} else if (status == 0) { | |
// request status 0 can indicate a failed cross-domain call | |
errorCallback(); | |
} | |
} | |
}; | |
req.open('GET', url, true); | |
req.send(); | |
} | |
} | |
// Copy attributes from img element to svg element | |
function copyAttributes(imgElem, svgElem) { | |
var attribute; | |
var attributeName; | |
var attributeValue; | |
var attributes = imgElem.attributes; | |
for (var i = 0; i < attributes[_LENGTH_]; i++) { | |
attribute = attributes[i]; | |
attributeName = attribute.name; | |
// Only copy attributes not explicitly excluded from copying | |
if (ATTRIBUTE_EXCLUSION_NAMES.indexOf(attributeName) == -1) { | |
attributeValue = attribute.value; | |
// If img attribute is "title", insert a title element into SVG element | |
if (attributeName == _TITLE_) { | |
var titleElem; | |
var firstElementChild = svgElem.firstElementChild; | |
if (firstElementChild && firstElementChild.localName.toLowerCase() == _TITLE_) { | |
// If the SVG element's first child is a title element, keep it as the title element | |
titleElem = firstElementChild; | |
} else { | |
// If the SVG element's first child element is not a title element, create a new title | |
// ele,emt and set it as the first child | |
titleElem = document[_CREATE_ELEMENT_ + 'NS']('http://www.w3.org/2000/svg', _TITLE_); | |
svgElem.insertBefore(titleElem, firstElementChild); | |
} | |
// Set new title content | |
titleElem.textContent = attributeValue; | |
} else { | |
// Set img attribute to svg element | |
svgElem[_SET_ATTRIBUTE_](attributeName, attributeValue); | |
} | |
} | |
} | |
} | |
// This function appends a suffix to IDs of referenced elements in the <defs> in order to to avoid ID collision | |
// between multiple injected SVGs. The suffix has the form "--inject-X", where X is a running number which is | |
// incremented with each injection. References to the IDs are adjusted accordingly. | |
// We assume tha all IDs within the injected SVG are unique, therefore the same suffix can be used for all IDs of one | |
// injected SVG. | |
// If the onlyReferenced argument is set to true, only those IDs will be made unique that are referenced from within the SVG | |
function makeIdsUnique(svgElem, onlyReferenced) { | |
var idSuffix = ID_SUFFIX + uniqueIdCounter++; | |
// Regular expression for functional notations of an IRI references. This will find occurences in the form | |
// url(#anyId) or url("#anyId") (for Internet Explorer) and capture the referenced ID | |
var funcIriRegex = /url\("?#([a-zA-Z][\w:.-]*)"?\)/g; | |
// Get all elements with an ID. The SVG spec recommends to put referenced elements inside <defs> elements, but | |
// this is not a requirement, therefore we have to search for IDs in the whole SVG. | |
var idElements = svgElem.querySelectorAll('[id]'); | |
var idElem; | |
// An object containing referenced IDs as keys is used if only referenced IDs should be uniquified. | |
// If this object does not exist, all IDs will be uniquified. | |
var referencedIds = onlyReferenced ? [] : NULL; | |
var tagName; | |
var iriTagNames = {}; | |
var iriProperties = []; | |
var changed = false; | |
var i, j; | |
if (idElements[_LENGTH_]) { | |
// Make all IDs unique by adding the ID suffix and collect all encountered tag names | |
// that are IRI referenceable from properities. | |
for (i = 0; i < idElements[_LENGTH_]; i++) { | |
tagName = idElements[i].localName; // Use non-namespaced tag name | |
// Make ID unique if tag name is IRI referenceable | |
if (tagName in IRI_TAG_PROPERTIES_MAP) { | |
iriTagNames[tagName] = 1; | |
} | |
} | |
// Get all properties that are mapped to the found IRI referenceable tags | |
for (tagName in iriTagNames) { | |
(IRI_TAG_PROPERTIES_MAP[tagName] || [tagName]).forEach(function (mappedProperty) { | |
// Add mapped properties to array of iri referencing properties. | |
// Use linear search here because the number of possible entries is very small (maximum 11) | |
if (iriProperties.indexOf(mappedProperty) < 0) { | |
iriProperties.push(mappedProperty); | |
} | |
}); | |
} | |
if (iriProperties[_LENGTH_]) { | |
// Add "style" to properties, because it may contain references in the form 'style="fill:url(#myFill)"' | |
iriProperties.push(_STYLE_); | |
} | |
// Run through all elements of the SVG and replace IDs in references. | |
// To get all descending elements, getElementsByTagName('*') seems to perform faster than querySelectorAll('*'). | |
// Since svgElem.getElementsByTagName('*') does not return the svg element itself, we have to handle it separately. | |
var descElements = svgElem[_GET_ELEMENTS_BY_TAG_NAME_]('*'); | |
var element = svgElem; | |
var propertyName; | |
var value; | |
var newValue; | |
for (i = -1; element != NULL;) { | |
if (element.localName == _STYLE_) { | |
// If element is a style element, replace IDs in all occurences of "url(#anyId)" in text content | |
value = element.textContent; | |
newValue = value && value.replace(funcIriRegex, function(match, id) { | |
if (referencedIds) { | |
referencedIds[id] = 1; | |
} | |
return 'url(#' + id + idSuffix + ')'; | |
}); | |
if (newValue !== value) { | |
element.textContent = newValue; | |
} | |
} else if (element.hasAttributes()) { | |
// Run through all property names for which IDs were found | |
for (j = 0; j < iriProperties[_LENGTH_]; j++) { | |
propertyName = iriProperties[j]; | |
value = element[_GET_ATTRIBUTE_](propertyName); | |
newValue = value && value.replace(funcIriRegex, function(match, id) { | |
if (referencedIds) { | |
referencedIds[id] = 1; | |
} | |
return 'url(#' + id + idSuffix + ')'; | |
}); | |
if (newValue !== value) { | |
element[_SET_ATTRIBUTE_](propertyName, newValue); | |
} | |
} | |
// Replace IDs in xlink:ref and href attributes | |
['xlink:href', 'href'].forEach(function(refAttrName) { | |
var iri = element[_GET_ATTRIBUTE_](refAttrName); | |
if (/^\s*#/.test(iri)) { // Check if iri is non-null and internal reference | |
iri = iri.trim(); | |
element[_SET_ATTRIBUTE_](refAttrName, iri + idSuffix); | |
if (referencedIds) { | |
// Add ID to referenced IDs | |
referencedIds[iri.substring(1)] = 1; | |
} | |
} | |
}); | |
} | |
element = descElements[++i]; | |
} | |
for (i = 0; i < idElements[_LENGTH_]; i++) { | |
idElem = idElements[i]; | |
// If set of referenced IDs exists, make only referenced IDs unique, | |
// otherwise make all IDs unique. | |
if (!referencedIds || referencedIds[idElem.id]) { | |
// Add suffix to element's ID | |
idElem.id += idSuffix; | |
changed = true; | |
} | |
} | |
} | |
// return true if SVG element has changed | |
return changed; | |
} | |
// For cached SVGs the IDs are made unique by simply replacing the already inserted unique IDs with a | |
// higher ID counter. This is much more performant than a call to makeIdsUnique(). | |
function makeIdsUniqueCached(svgString) { | |
return svgString.replace(ID_SUFFIX_REGEX, ID_SUFFIX + uniqueIdCounter++); | |
} | |
// Inject SVG by replacing the img element with the SVG element in the DOM | |
function inject(imgElem, svgElem, absUrl, options) { | |
if (svgElem) { | |
svgElem[_SET_ATTRIBUTE_]('data-inject-url', absUrl); | |
var parentNode = imgElem.parentNode; | |
if (parentNode) { | |
if (options.copyAttributes) { | |
copyAttributes(imgElem, svgElem); | |
} | |
// Invoke beforeInject hook if set | |
var beforeInject = options.beforeInject; | |
var injectElem = (beforeInject && beforeInject(imgElem, svgElem)) || svgElem; | |
// Replace img element with new element. This is the actual injection. | |
parentNode.replaceChild(injectElem, imgElem); | |
// Mark img element as injected | |
imgElem[__SVGINJECT] = INJECTED; | |
removeOnLoadAttribute(imgElem); | |
// Invoke afterInject hook if set | |
var afterInject = options.afterInject; | |
if (afterInject) { | |
afterInject(imgElem, injectElem); | |
} | |
} | |
} else { | |
svgInvalid(imgElem, options); | |
} | |
} | |
// Merges any number of options objects into a new object | |
function mergeOptions() { | |
var mergedOptions = {}; | |
var args = arguments; | |
// Iterate over all specified options objects and add all properties to the new options object | |
for (var i = 0; i < args[_LENGTH_]; i++) { | |
var argument = args[i]; | |
for (var key in argument) { | |
if (argument.hasOwnProperty(key)) { | |
mergedOptions[key] = argument[key]; | |
} | |
} | |
} | |
return mergedOptions; | |
} | |
// Adds the specified CSS to the document's <head> element | |
function addStyleToHead(css) { | |
var head = document[_GET_ELEMENTS_BY_TAG_NAME_]('head')[0]; | |
if (head) { | |
var style = document[_CREATE_ELEMENT_](_STYLE_); | |
style.type = 'text/css'; | |
style.appendChild(document.createTextNode(css)); | |
head.appendChild(style); | |
} | |
} | |
// Builds an SVG element from the specified SVG string | |
function buildSvgElement(svgStr, verify) { | |
if (verify) { | |
var svgDoc; | |
try { | |
// Parse the SVG string with DOMParser | |
svgDoc = svgStringToSvgDoc(svgStr); | |
} catch(e) { | |
return NULL; | |
} | |
if (svgDoc[_GET_ELEMENTS_BY_TAG_NAME_]('parsererror')[_LENGTH_]) { | |
// DOMParser does not throw an exception, but instead puts parsererror tags in the document | |
return NULL; | |
} | |
return svgDoc.documentElement; | |
} else { | |
var div = document.createElement('div'); | |
div.innerHTML = svgStr; | |
return div.firstElementChild; | |
} | |
} | |
function removeOnLoadAttribute(imgElem) { | |
// Remove the onload attribute. Should only be used to remove the unstyled image flash protection and | |
// make the element visible, not for removing the event listener. | |
imgElem.removeAttribute('onload'); | |
} | |
function errorMessage(msg) { | |
console.error('SVGInject: ' + msg); | |
} | |
function fail(imgElem, status, options) { | |
imgElem[__SVGINJECT] = FAIL; | |
if (options.onFail) { | |
options.onFail(imgElem, status); | |
} else { | |
errorMessage(status); | |
} | |
} | |
function svgInvalid(imgElem, options) { | |
removeOnLoadAttribute(imgElem); | |
fail(imgElem, SVG_INVALID, options); | |
} | |
function svgNotSupported(imgElem, options) { | |
removeOnLoadAttribute(imgElem); | |
fail(imgElem, SVG_NOT_SUPPORTED, options); | |
} | |
function loadFail(imgElem, options) { | |
fail(imgElem, LOAD_FAIL, options); | |
} | |
function removeEventListeners(imgElem) { | |
imgElem.onload = NULL; | |
imgElem.onerror = NULL; | |
} | |
function imgNotSet(msg) { | |
errorMessage('no img element'); | |
} | |
function createSVGInject(globalName, options) { | |
var defaultOptions = mergeOptions(DEFAULT_OPTIONS, options); | |
var svgLoadCache = {}; | |
if (IS_SVG_SUPPORTED) { | |
// If the browser supports SVG, add a small stylesheet that hides the <img> elements until | |
// injection is finished. This avoids showing the unstyled SVGs before style is applied. | |
addStyleToHead('img[onload^="' + globalName + '("]{visibility:hidden;}'); | |
} | |
/** | |
* SVGInject | |
* | |
* Injects the SVG specified in the `src` attribute of the specified `img` element or array of `img` | |
* elements. Returns a Promise object which resolves if all passed in `img` elements have either been | |
* injected or failed to inject (Only if a global Promise object is available like in all modern browsers | |
* or through a polyfill). | |
* | |
* Options: | |
* useCache: If set to `true` the SVG will be cached using the absolute URL. Default value is `true`. | |
* copyAttributes: If set to `true` the attributes will be copied from `img` to `svg`. Dfault value | |
* is `true`. | |
* makeIdsUnique: If set to `true` the ID of elements in the `<defs>` element that can be references by | |
* property values (for example 'clipPath') are made unique by appending "--inject-X", where X is a | |
* running number which increases with each injection. This is done to avoid duplicate IDs in the DOM. | |
* beforeLoad: Hook before SVG is loaded. The `img` element is passed as a parameter. If the hook returns | |
* a string it is used as the URL instead of the `img` element's `src` attribute. | |
* afterLoad: Hook after SVG is loaded. The loaded `svg` element and `svg` string are passed as a | |
* parameters. If caching is active this hook will only get called once for injected SVGs with the | |
* same absolute path. Changes to the `svg` element in this hook will be applied to all injected SVGs | |
* with the same absolute path. It's also possible to return an `svg` string or `svg` element which | |
* will then be used for the injection. | |
* beforeInject: Hook before SVG is injected. The `img` and `svg` elements are passed as parameters. If | |
* any html element is returned it gets injected instead of applying the default SVG injection. | |
* afterInject: Hook after SVG is injected. The `img` and `svg` elements are passed as parameters. | |
* onAllFinish: Hook after all `img` elements passed to an SVGInject() call have either been injected or | |
* failed to inject. | |
* onFail: Hook after injection fails. The `img` element and a `status` string are passed as an parameter. | |
* The `status` can be either `'SVG_NOT_SUPPORTED'` (the browser does not support SVG), | |
* `'SVG_INVALID'` (the SVG is not in a valid format) or `'LOAD_FAILED'` (loading of the SVG failed). | |
* | |
* @param {HTMLImageElement} img - an img element or an array of img elements | |
* @param {Object} [options] - optional parameter with [options](#options) for this injection. | |
*/ | |
function SVGInject(img, options) { | |
options = mergeOptions(defaultOptions, options); | |
var run = function(resolve) { | |
var allFinish = function() { | |
var onAllFinish = options.onAllFinish; | |
if (onAllFinish) { | |
onAllFinish(); | |
} | |
resolve && resolve(); | |
}; | |
if (img && typeof img[_LENGTH_] != _UNDEFINED_) { | |
// an array like structure of img elements | |
var injectIndex = 0; | |
var injectCount = img[_LENGTH_]; | |
if (injectCount == 0) { | |
allFinish(); | |
} else { | |
var finish = function() { | |
if (++injectIndex == injectCount) { | |
allFinish(); | |
} | |
}; | |
for (var i = 0; i < injectCount; i++) { | |
SVGInjectElement(img[i], options, finish); | |
} | |
} | |
} else { | |
// only one img element | |
SVGInjectElement(img, options, allFinish); | |
} | |
}; | |
// return a Promise object if globally available | |
return typeof Promise == _UNDEFINED_ ? run() : new Promise(run); | |
} | |
// Injects a single svg element. Options must be already merged with the default options. | |
function SVGInjectElement(imgElem, options, callback) { | |
if (imgElem) { | |
var svgInjectAttributeValue = imgElem[__SVGINJECT]; | |
if (!svgInjectAttributeValue) { | |
removeEventListeners(imgElem); | |
if (!IS_SVG_SUPPORTED) { | |
svgNotSupported(imgElem, options); | |
callback(); | |
return; | |
} | |
// Invoke beforeLoad hook if set. If the beforeLoad returns a value use it as the src for the load | |
// URL path. Else use the imgElem's src attribute value. | |
var beforeLoad = options.beforeLoad; | |
var src = (beforeLoad && beforeLoad(imgElem)) || imgElem[_GET_ATTRIBUTE_]('src'); | |
if (!src) { | |
// If no image src attribute is set do no injection. This can only be reached by using javascript | |
// because if no src attribute is set the onload and onerror events do not get called | |
if (src === '') { | |
loadFail(imgElem, options); | |
} | |
callback(); | |
return; | |
} | |
// set array so later calls can register callbacks | |
var onFinishCallbacks = []; | |
imgElem[__SVGINJECT] = onFinishCallbacks; | |
var onFinish = function() { | |
callback(); | |
onFinishCallbacks.forEach(function(onFinishCallback) { | |
onFinishCallback(); | |
}); | |
}; | |
var absUrl = getAbsoluteUrl(src); | |
var useCacheOption = options.useCache; | |
var makeIdsUniqueOption = options.makeIdsUnique; | |
var setSvgLoadCacheValue = function(val) { | |
if (useCacheOption) { | |
svgLoadCache[absUrl].forEach(function(svgLoad) { | |
svgLoad(val); | |
}); | |
svgLoadCache[absUrl] = val; | |
} | |
}; | |
if (useCacheOption) { | |
var svgLoad = svgLoadCache[absUrl]; | |
var handleLoadValue = function(loadValue) { | |
if (loadValue === LOAD_FAIL) { | |
loadFail(imgElem, options); | |
} else if (loadValue === SVG_INVALID) { | |
svgInvalid(imgElem, options); | |
} else { | |
var hasUniqueIds = loadValue[0]; | |
var svgString = loadValue[1]; | |
var uniqueIdsSvgString = loadValue[2]; | |
var svgElem; | |
if (makeIdsUniqueOption) { | |
if (hasUniqueIds === NULL) { | |
// IDs for the SVG string have not been made unique before. This may happen if previous | |
// injection of a cached SVG have been run with the option makedIdsUnique set to false | |
svgElem = buildSvgElement(svgString, false); | |
hasUniqueIds = makeIdsUnique(svgElem, false); | |
loadValue[0] = hasUniqueIds; | |
loadValue[2] = hasUniqueIds && svgElemToSvgString(svgElem); | |
} else if (hasUniqueIds) { | |
// Make IDs unique for already cached SVGs with better performance | |
svgString = makeIdsUniqueCached(uniqueIdsSvgString); | |
} | |
} | |
svgElem = svgElem || buildSvgElement(svgString, false); | |
inject(imgElem, svgElem, absUrl, options); | |
} | |
onFinish(); | |
}; | |
if (typeof svgLoad != _UNDEFINED_) { | |
// Value for url exists in cache | |
if (svgLoad.isCallbackQueue) { | |
// Same url has been cached, but value has not been loaded yet, so add to callbacks | |
svgLoad.push(handleLoadValue); | |
} else { | |
handleLoadValue(svgLoad); | |
} | |
return; | |
} else { | |
var svgLoad = []; | |
// set property isCallbackQueue to Array to differentiate from array with cached loaded values | |
svgLoad.isCallbackQueue = true; | |
svgLoadCache[absUrl] = svgLoad; | |
} | |
} | |
// Load the SVG because it is not cached or caching is disabled | |
loadSvg(absUrl, function(svgXml, svgString) { | |
// Use the XML from the XHR request if it is an instance of Document. Otherwise | |
// (for example of IE9), create the svg document from the svg string. | |
var svgElem = svgXml instanceof Document ? svgXml.documentElement : buildSvgElement(svgString, true); | |
var afterLoad = options.afterLoad; | |
if (afterLoad) { | |
// Invoke afterLoad hook which may modify the SVG element. After load may also return a new | |
// svg element or svg string | |
var svgElemOrSvgString = afterLoad(svgElem, svgString) || svgElem; | |
if (svgElemOrSvgString) { | |
// Update svgElem and svgString because of modifications to the SVG element or SVG string in | |
// the afterLoad hook, so the modified SVG is also used for all later cached injections | |
var isString = typeof svgElemOrSvgString == 'string'; | |
svgString = isString ? svgElemOrSvgString : svgElemToSvgString(svgElem); | |
svgElem = isString ? buildSvgElement(svgElemOrSvgString, true) : svgElemOrSvgString; | |
} | |
} | |
if (svgElem instanceof SVGElement) { | |
var hasUniqueIds = NULL; | |
if (makeIdsUniqueOption) { | |
hasUniqueIds = makeIdsUnique(svgElem, false); | |
} | |
if (useCacheOption) { | |
var uniqueIdsSvgString = hasUniqueIds && svgElemToSvgString(svgElem); | |
// set an array with three entries to the load cache | |
setSvgLoadCacheValue([hasUniqueIds, svgString, uniqueIdsSvgString]); | |
} | |
inject(imgElem, svgElem, absUrl, options); | |
} else { | |
svgInvalid(imgElem, options); | |
setSvgLoadCacheValue(SVG_INVALID); | |
} | |
onFinish(); | |
}, function() { | |
loadFail(imgElem, options); | |
setSvgLoadCacheValue(LOAD_FAIL); | |
onFinish(); | |
}); | |
} else { | |
if (Array.isArray(svgInjectAttributeValue)) { | |
// svgInjectAttributeValue is an array. Injection is not complete so register callback | |
svgInjectAttributeValue.push(callback); | |
} else { | |
callback(); | |
} | |
} | |
} else { | |
imgNotSet(); | |
} | |
} | |
/** | |
* Sets the default [options](#options) for SVGInject. | |
* | |
* @param {Object} [options] - default [options](#options) for an injection. | |
*/ | |
SVGInject.setOptions = function(options) { | |
defaultOptions = mergeOptions(defaultOptions, options); | |
}; | |
// Create a new instance of SVGInject | |
SVGInject.create = createSVGInject; | |
/** | |
* Used in onerror Event of an `<img>` element to handle cases when the loading the original src fails | |
* (for example if file is not found or if the browser does not support SVG). This triggers a call to the | |
* options onFail hook if available. The optional second parameter will be set as the new src attribute | |
* for the img element. | |
* | |
* @param {HTMLImageElement} img - an img element | |
* @param {String} [fallbackSrc] - optional parameter fallback src | |
*/ | |
SVGInject.err = function(img, fallbackSrc) { | |
if (img) { | |
if (img[__SVGINJECT] != FAIL) { | |
removeEventListeners(img); | |
if (!IS_SVG_SUPPORTED) { | |
svgNotSupported(img, defaultOptions); | |
} else { | |
removeOnLoadAttribute(img); | |
loadFail(img, defaultOptions); | |
} | |
if (fallbackSrc) { | |
removeOnLoadAttribute(img); | |
img.src = fallbackSrc; | |
} | |
} | |
} else { | |
imgNotSet(); | |
} | |
}; | |
window[globalName] = SVGInject; | |
return SVGInject; | |
} | |
var SVGInjectInstance = createSVGInject('SVGInject'); | |
if (typeof module == 'object' && typeof module.exports == 'object') { | |
module.exports = SVGInjectInstance; | |
} | |
})(window, document); |