- Linting (ESLint): Stricter rules (or switch to warning)
- Breaking internal API change: `updateGripCursor` moved to be class method of Selector rather than instance method - Breaking internal API change: `subpathIsClosed` moved to be class method of `Path` rather than instance method - Refactoring: Reuse utilities base64 encoder for SVG icons plugin - Docs (JSDoc): Fix return of the `mouseUp` (can also be an object) and `mouseDown` (may also be a boolean) of `pathActions`; other JSDoc additions/improvements
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
// Todo: Move to own module (and have it import a modular base64 encoder)
|
||||
import {encode64} from '../utilities.js';
|
||||
/**
|
||||
* SVG Icon Loader 2.0
|
||||
*
|
||||
@@ -96,18 +98,22 @@ $(function() {
|
||||
* @param {external:jQuery} $ Its keys include all icon IDs and the values, the icon as a jQuery object
|
||||
* @returns {external:jQuery} The enhanced jQuery object
|
||||
*/
|
||||
export default function ($) {
|
||||
export default function jQueryPluginSVGIcons ($) {
|
||||
const svgIcons = {};
|
||||
|
||||
let fixIDs;
|
||||
/**
|
||||
* List of raster images with each
|
||||
* key being the SVG icon ID to replace, and the value the image file name
|
||||
* @typedef {PlainObject.<string, string>} external:jQuery.svgIcons.Fallback
|
||||
*/
|
||||
/**
|
||||
* @function external:jQuery.svgIcons
|
||||
* @param {string} file The location of a local SVG or SVGz file
|
||||
* @param {PlainObject} [opts]
|
||||
* @param {Float} [opts.w] The icon widths
|
||||
* @param {Float} [opts.h] The icon heights
|
||||
* @param {PlainObject.<string, string>} [opts.fallback] List of raster images with each
|
||||
key being the SVG icon ID to replace, and the value the image file name
|
||||
* @param {external:jQuery.svgIcons.Fallback} [opts.fallback]
|
||||
* @param {string} [opts.fallback_path] The path to use for all images
|
||||
listed under "fallback"
|
||||
* @param {boolean} [opts.replace] If set to `true`, HTML elements will be replaced by,
|
||||
@@ -132,8 +138,10 @@ export default function ($) {
|
||||
iconW = opts.w || 24,
|
||||
iconH = opts.h || 24;
|
||||
let elems, svgdoc, testImg,
|
||||
iconsMade = false, dataLoaded = false, loadAttempts = 0;
|
||||
const isOpera = !!window.opera,
|
||||
iconsMade = false,
|
||||
dataLoaded = false,
|
||||
loadAttempts = 0;
|
||||
const isOpera = Boolean(window.opera),
|
||||
// ua = navigator.userAgent,
|
||||
// isSafari = (ua.includes('Safari/') && !ua.includes('Chrome/')),
|
||||
dataPre = 'data:image/svg+xml;charset=utf-8;base64,';
|
||||
@@ -169,24 +177,28 @@ export default function ($) {
|
||||
$(function () {
|
||||
useFallback();
|
||||
});
|
||||
} else {
|
||||
if (err.responseText) {
|
||||
svgdoc = parser.parseFromString(err.responseText, 'text/xml');
|
||||
} else if (err.responseText) {
|
||||
svgdoc = parser.parseFromString(err.responseText, 'text/xml');
|
||||
|
||||
if (!svgdoc.childNodes.length) {
|
||||
$(useFallback);
|
||||
}
|
||||
$(function () {
|
||||
getIcons('ajax');
|
||||
});
|
||||
} else {
|
||||
if (!svgdoc.childNodes.length) {
|
||||
$(useFallback);
|
||||
}
|
||||
$(function () {
|
||||
getIcons('ajax');
|
||||
});
|
||||
} else {
|
||||
$(useFallback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {"ajax"|0|undefined} evt
|
||||
* @param {boolean} [noWait]
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function getIcons (evt, noWait) {
|
||||
if (evt !== 'ajax') {
|
||||
if (dataLoaded) return;
|
||||
@@ -231,6 +243,14 @@ export default function ($) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {external:jQuery} target
|
||||
* @param {external:jQuery} icon A wrapped `defs` or Image
|
||||
* @param {string} id SVG icon ID
|
||||
* @param {string} setID
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function setIcon (target, icon, id, setID) {
|
||||
if (isOpera) icon.css('visibility', 'hidden');
|
||||
if (opts.replace) {
|
||||
@@ -249,6 +269,11 @@ export default function ($) {
|
||||
}
|
||||
|
||||
let holder;
|
||||
/**
|
||||
* @param {external:jQuery} icon A wrapped `defs` or Image
|
||||
* @param {string} id SVG icon ID
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function addIcon (icon, id) {
|
||||
if (opts.id_match === undefined || opts.id_match !== false) {
|
||||
setIcon(holder, icon, id, true);
|
||||
@@ -256,7 +281,13 @@ export default function ($) {
|
||||
svgIcons[id] = icon;
|
||||
}
|
||||
|
||||
function makeIcons (toImage, fallback) {
|
||||
/**
|
||||
*
|
||||
* @param {boolean} [toImage]
|
||||
* @param {external:jQuery.svgIcons.Fallback} [fallback]
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function makeIcons (toImage = false, fallback) {
|
||||
if (iconsMade) return;
|
||||
if (opts.no_img) toImage = false;
|
||||
|
||||
@@ -359,13 +390,14 @@ export default function ($) {
|
||||
let idElems;
|
||||
if (isOpera) {
|
||||
idElems = defs.find('*').filter(function () {
|
||||
return !!this.id;
|
||||
return Boolean(this.id);
|
||||
});
|
||||
} else {
|
||||
idElems = defs.find('[id]');
|
||||
}
|
||||
|
||||
const allElems = svgEl[0].getElementsByTagName('*'), len = allElems.length;
|
||||
const allElems = svgEl[0].getElementsByTagName('*'),
|
||||
len = allElems.length;
|
||||
|
||||
idElems.each(function (i) {
|
||||
const {id} = this;
|
||||
@@ -409,49 +441,20 @@ export default function ($) {
|
||||
return svgEl;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function useFallback () {
|
||||
if (file.includes('.svgz')) {
|
||||
const regFile = file.replace('.svgz', '.svg');
|
||||
if (window.console) {
|
||||
console.log('.svgz failed, trying with .svg');
|
||||
console.log('.svgz failed, trying with .svg'); // eslint-disable-line no-console
|
||||
}
|
||||
$.svgIcons(regFile, opts);
|
||||
} else if (opts.fallback) {
|
||||
makeIcons(false, opts.fallback);
|
||||
}
|
||||
}
|
||||
|
||||
function encode64 (input) {
|
||||
// base64 strings are 4/3 larger than the original string
|
||||
if (window.btoa) return window.btoa(input);
|
||||
const _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
const output = new Array(Math.floor((input.length + 2) / 3) * 4);
|
||||
|
||||
let i = 0, p = 0;
|
||||
do {
|
||||
const chr1 = input.charCodeAt(i++);
|
||||
const chr2 = input.charCodeAt(i++);
|
||||
const chr3 = input.charCodeAt(i++);
|
||||
|
||||
const enc1 = chr1 >> 2;
|
||||
const enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
|
||||
let enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
let enc4 = chr3 & 63;
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = 64;
|
||||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
|
||||
output[p++] = _keyStr.charAt(enc1);
|
||||
output[p++] = _keyStr.charAt(enc2);
|
||||
output[p++] = _keyStr.charAt(enc3);
|
||||
output[p++] = _keyStr.charAt(enc4);
|
||||
} while (i < input.length);
|
||||
|
||||
return output.join('');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user