2
0
mirror of https://github.com/iconify/iconify.git synced 2024-11-16 17:45:09 +00:00

Split exported and local functions, rebuild build process

This commit is contained in:
cyberalien 2017-04-06 20:11:26 +03:00
parent d44afefa15
commit 469d45e7be
36 changed files with 757 additions and 514 deletions

15
build/_template.js Normal file
View File

@ -0,0 +1,15 @@
"use strict";
if (self.SimpleSVG === void 0) {
self.SimpleSVG = {
isReady: false
};
(function (SimpleSVG, global) {
var local = {
config: {}
};
/* content */
})(self.SimpleSVG, self);
}

View File

@ -22,6 +22,7 @@ const fs = require('fs'),
let codeDir = 'src',
distDir = 'dist',
baseName = 'simple-svg',
/**
* List of files in order of compilation.
* Dependencies are listed in comments after each image, except for config.js dependence
@ -30,9 +31,15 @@ let codeDir = 'src',
*/
filesOrder = [
// Core
'event.js',
'init.js',
// Configuration
'defaults.js',
'config.js', // requires defaults.js
'polyfill.js', // requires config.js
// Polyfill
'polyfill.js', // requires config.js and event.js
// Common files
'storage.js',
@ -56,7 +63,6 @@ let codeDir = 'src',
let resolvedCodeDir = path.resolve(__dirname, '../' + codeDir),
resolvedDistDir = path.resolve(__dirname, '../' + distDir),
compiled = {},
content;
function addFile(file, callback) {
@ -74,21 +80,21 @@ function addFile(file, callback) {
// Remove strict
content = content.replace(/["']use strict["'];\s?/g, '');
// Handle special common files
// Handle node.js modules
if (file.slice(0, 7) === 'common/') {
content = '(function (SimpleSVG) {\n\t' +
content = '(function() {\n\t' +
content.replace(/\n/g, '\n\t') +
'\n})(self.SimpleSVG);';
'\n})();';
let split = file.split('/');
switch (split.pop()) {
case 'storage.js':
content = content.replace('module.exports = Storage;', 'SimpleSVG._Storage = Storage;');
content = content.replace('module.exports = Storage;', 'local.Storage = Storage;');
break;
case 'svg.js':
content = content.replace('module.exports = SVG;', 'SimpleSVG._SVG = SVG;')
.replace('require(\'./storage\')', 'SimpleSVG._Storage');
content = content.replace('module.exports = SVG;', 'local.SVG = SVG;')
.replace('require(\'./storage\')', 'local.Storage');
break;
default:
@ -101,12 +107,13 @@ function addFile(file, callback) {
content = callback(content);
}
return content;
return content.trim();
}
// Parse all files
function parse(config) {
let content = '"use strict";\n\nself.SimpleSVG = {};\n\n';
let content = '',
template = fs.readFileSync(__dirname + '/_template.js', 'utf8');
// List of files
let testFiles = [];
@ -122,11 +129,11 @@ function parse(config) {
// Add all files
testFiles.forEach(file => {
if (Helper.exists(resolvedCodeDir + '/' + file)) {
content += '\n' + addFile(file) + '\n';
content += '\n\t\t' + addFile(file).replace(/\n/g, '\n\t\t') + '\n';
}
});
return content;
return template.replace('/* content */', content);
}
function save(file, content) {

View File

@ -27,19 +27,81 @@ let resolvedSourceDir = path.resolve(__dirname, '../' + sourceDir),
resolvedTargetDir = path.resolve(__dirname, '../' + targetDir),
resolvedCodeDir = path.resolve(__dirname, '../' + codeDir);
// Find all files, parse them
/**
* Helper functions for test builders
*/
let TestHelper = {
replace: (content, search, replace, error) => {
if (content.indexOf(search) === -1) {
throw new Error(error);
}
return content.replace(search, replace);
},
// Get common/storage.js
getStorage: () => {
return '(function (local) {\n' +
fs.readFileSync(resolvedCodeDir + '/common/storage.js', 'utf8')
.replace('module.exports = Storage;', 'local.Storage = Storage;') +
'\n})(local);\n';
},
// Get common/svg.js
getSVG: () => {
return '(function (local) {\n' +
fs.readFileSync(resolvedCodeDir + '/common/svg.js', 'utf8')
.replace('module.exports = SVG;', 'local.SVG = SVG;')
.replace('require(\'./storage\')', 'local.Storage') +
'\n})(local);\n';
},
// Fake events.js
fakeEvents: () => {
return 'local.event = function(name, params) { if (local[name] !== void 0) local[name](params); };'
},
// Fake init.js
fakeInit: () => {
let content = fs.readFileSync(resolvedCodeDir + '/browser/init.js', 'utf8');
content = TestHelper.replace(
content,
'if (document.readyState === \'complete\' || (document.readyState !== \'loading\' && !document.documentElement.doScroll)) {',
'if (true) {',
'Cannot find required code in init.js'
);
content = TestHelper.replace(
content,
'SimpleSVG.ready = function(callback) {',
'SimpleSVG.ready = function(callback) { local.initQueue.push(callback); return; ',
'Cannot find required code in init.js'
);
return content;
}
};
/**
* Find all files, parse them
*/
glob(resolvedSourceDir + '/**/*.js', {
dot: true
}, (err, files) => {
files.forEach(file => {
if (file.slice(-9) === '.build.js') {
let code = require(file)(Helper, resolvedCodeDir, file.replace('.build.', '.test.')),
targetFile = resolvedTargetDir + file.slice(resolvedSourceDir.length).replace('.build.', '.');
let code = require(file)(Helper, resolvedCodeDir, file.replace('.build.', '.test.'), TestHelper),
targetFile = resolvedTargetDir + file.slice(resolvedSourceDir.length).replace('.build.', '.'),
test = targetDir + targetFile.slice(resolvedTargetDir.length);
if (!code.length) {
console.log('Ignoring compiled test:', test);
return;
}
Helper.mkdir(path.dirname(targetFile));
fs.writeFileSync(targetFile, code, 'utf8');
let test = targetDir + targetFile.slice(resolvedTargetDir.length);
console.log('Compiled test:', test);
tests.push(test);
return;

View File

@ -9,46 +9,85 @@
*/
/**
* Merge custom and default configuration
* Merge custom and default configuration and functions for changing config values
*
* It will merge with existing SimpleSVG.config and SimpleSVGConfig objects, adding only items that aren't set
* It will merge default config with SimpleSVGConfig object if it exists
*/
(function(global, SimpleSVG) {
(function(SimpleSVG, global, config) {
"use strict";
var customConfig = SimpleSVG.config === void 0 ? null : SimpleSVG.config;
function merge(list) {
Object.keys(SimpleSVG.config).forEach(function(key) {
if (list[key] === void 0) {
/**
* Change config value
*
* @param {string} key
* @param {*} value
* @param {boolean} canChangeHardcoded
*/
function setConfig(key, value, canChangeHardcoded) {
if (!canChangeHardcoded && key.slice(0, 1) === '_') {
return;
}
switch (key) {
case 'customCDN':
case 'SVGAttributes':
// Merge objects
Object.keys(list[key]).forEach(function(key2) {
SimpleSVG.config[key][key2] = list[key][key2];
Object.keys(value).forEach(function (key2) {
config[key][key2] = value[key2];
});
break;
default:
// Overwrite config
SimpleSVG.config[key] = list[key];
config[key] = value;
}
}
/**
* Merge configuration objects
*
* @param {object} list
* @param {boolean} canChangeHardcoded
*/
function mergeConfig(list, canChangeHardcoded) {
Object.keys(list).forEach(function(key) {
setConfig(key, list[key], canChangeHardcoded);
});
}
SimpleSVG.config = SimpleSVG._defaultConfig;
/**
* Change configuration option
*
* @param {string} name
* @param {*} value
*/
SimpleSVG.setConfig = function(name, value) {
setConfig(key, value, false);
};
// Merge with SimpleSVGConfig object
/**
* Set custom CDN URL
*
* @param {string} prefix Collection prefix
* @param {string} url JSONP URL
*/
SimpleSVG.setCustomCDN = function(prefix, url) {
config['customCDN'][prefix] = url;
};
/**
* Get configuration value
*
* @param {string} name
* @return {*}
*/
SimpleSVG.getConfig = function(name) {
return config[name];
};
// Merge configuration with SimpleSVGConfig object
if (global.SimpleSVGConfig !== void 0 && typeof global.SimpleSVGConfig === 'object') {
merge(global.SimpleSVGConfig);
mergeConfig(global.SimpleSVGConfig, true);
}
// Merge with existing config object
if (customConfig !== null) {
merge(customConfig);
}
})(self, self.SimpleSVG);
})(SimpleSVG, global, local.config);

View File

@ -9,38 +9,39 @@
*/
/**
* Default configuration
* Default configuration.
* Configuration variables that cannot be changed after script has loaded start with _
*
* Additional defaults.js are included in sub-directories, with different content for different builds
*/
(function(SimpleSVG) {
(function(config) {
"use strict";
SimpleSVG._defaultConfig = {
// Custom default attributes for SVG
SVGAttributes: {
},
config.SVGAttributes = {};
// Class name for icons
imageClass: 'simple-svg',
config._imageClass = 'simple-svg';
// Class name for image that is being loaded
loadingClass: 'svg-loading',
config._loadingClass = 'svg-loading';
// Attribute that stores icon name
iconAttribute: 'data-icon',
config._iconAttribute = 'data-icon';
// Tag for SVG placeholder
placeholderTag: 'svg-placeholder',
config._placeholderTag = 'svg-placeholder';
// Rotation and flip classes
rotationClasses: {
config._rotationClasses = {
'1': 'svg-rotate-90',
'2': 'svg-rotate-180',
'3': 'svg-rotate-270'
},
hFlipClass: 'svg-flip-horizontal',
vFlipClass: 'svg-flip-vertical'
};
config._hFlipClass = 'svg-flip-horizontal';
config._vFlipClass = 'svg-flip-vertical';
})(self.SimpleSVG);
// Event to call when SimpleSVG is ready
config._readyEvent = 'SimpleSVGReady';
})(local.config);

48
src/browser/event.js Normal file
View File

@ -0,0 +1,48 @@
/**
* This file is part of the simple-svg package.
*
* (c) Vjacheslav Trushkin <cyberalien@gmail.com>
*
* For the full copyright and license information, please view the license.txt
* file that was distributed with this source code.
* @license MIT
*/
/**
* Function to fire custom event and IE9 polyfill
*/
(function(local) {
"use strict";
/**
* CustomEvent polyfill for IE9
* From https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
*/
(function() {
if (typeof window.CustomEvent === 'function') return false;
function CustomEvent(event, params) {
var evt;
params = params || { bubbles: false, cancelable: false, detail: void 0 };
evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
})();
/**
* Dispatch custom event
*
* @param {string} name Event name
* @param {object} [params] Event parameters
*/
local.event = function(name, params) {
document.dispatchEvent(new CustomEvent(name, params));
};
})(local);

View File

@ -11,15 +11,13 @@
/**
* Functions that find images in DOM
*/
(function(SimpleSVG) {
(function(SimpleSVG, local, config) {
"use strict";
var imageClass = SimpleSVG.config.imageClass,
loadingClass = SimpleSVG.config.loadingClass,
hFlipClass = SimpleSVG.config.hFlipClass,
vFlipClass = SimpleSVG.config.vFlipClass,
iconAttribute = SimpleSVG.config.iconAttribute,
placeholderTag = SimpleSVG.config.placeholderTag,
var imageClass = config._imageClass,
loadingClass = config._loadingClass,
iconAttribute = config._iconAttribute,
placeholderTag = config._placeholderTag,
newSelectorExtra = ':not(.' + loadingClass + ')',
loadingSelectorExtra = '.' + loadingClass;
@ -116,12 +114,13 @@
* @param {Element} root Root element
* @param {boolean} [loading] Filter images by loading status. If missing, result will not be filtered
* @return {Array}
* @private
*/
SimpleSVG._findNewImages = function(root, loading) {
local.findNewImages = function(root, loading) {
var results = [],
duplicates = [];
root = root === void 0 ? (config._root === void 0 ? document.querySelector('body') : config._root) : root;
finderKeys.forEach(function(key) {
var finder = finders[key],
selector = loading === true ? finder.selectorLoading : (loading === false ? finder.selectorNew : finder.selector);
@ -135,7 +134,7 @@
if (icon && duplicates.indexOf(node) === -1) {
duplicates.push(node);
results.push(SimpleSVG._newImage(node, icon, finder));
results.push(local.newImage(node, icon, finder));
}
}
});
@ -150,9 +149,8 @@
* @param {string} tag Element tag
* @param {boolean} hidden Status
* @return {Array}
* @private
*/
SimpleSVG._findHiddenOrParsedImages = function(root, tag, hidden) {
local.findHiddenOrParsedImages = function(root, tag, hidden) {
var results = [];
var nodes = root.querySelectorAll(tag + '.' + imageClass),
@ -163,7 +161,7 @@
icon = node.getAttribute(iconAttribute);
if (icon) {
results.push(SimpleSVG._parsedImage(node, icon, hidden));
results.push(local.parsedImage(node, icon, hidden));
}
}
@ -175,10 +173,9 @@
*
* @param {Element} root Root element
* @return {Array}
* @private
*/
SimpleSVG._findHiddenImages = function(root) {
return SimpleSVG._findHiddenOrParsedImages(root, placeholderTag, true);
local.findHiddenImages = function(root) {
return local.findHiddenOrParsedImages(root, placeholderTag, true);
};
/**
@ -186,10 +183,9 @@
*
* @param {Element} root Root element
* @return {Array}
* @private
*/
SimpleSVG._findParsedImages = function(root) {
return SimpleSVG._findHiddenOrParsedImages(root, 'svg', false);
local.findParsedImages = function(root) {
return local.findHiddenOrParsedImages(root, 'svg', false);
};
})(self.SimpleSVG);
})(SimpleSVG, local, local.config);

View File

@ -11,12 +11,12 @@
/**
* Functions that create image objects
*/
(function(SimpleSVG) {
(function(local, config) {
"use strict";
var iconAttribute = SimpleSVG.config.iconAttribute,
loadingClass = SimpleSVG.config.loadingClass,
imageClass = SimpleSVG.config.imageClass;
var iconAttribute = config._iconAttribute,
loadingClass = config._loadingClass,
imageClass = config._imageClass;
/**
* Create object for new image
@ -25,9 +25,8 @@
* @param {string} icon Icon name
* @param {function} parser Parser function
* @return {{element: Element, icon: string, parser: function, loading: boolean}}
* @private
*/
SimpleSVG._newImage = function(element, icon, parser) {
local.newImage = function(element, icon, parser) {
return {
element: element,
icon: icon,
@ -43,9 +42,8 @@
* @param {string} icon Icon name
* @param {boolean} [hidden] True if image is hidden
* @return {{element: Element, icon: string, hidden: boolean}}
* @private
*/
SimpleSVG._parsedImage = function(element, icon, hidden) {
local.parsedImage = function(element, icon, hidden) {
return {
element: element,
icon: icon,
@ -58,9 +56,8 @@
*
* @param {object} image
* @return {object}
* @private
*/
SimpleSVG._getImageAttributes = function(image) {
local.getImageAttributes = function(image) {
var results = {},
i, attr;
@ -80,7 +77,7 @@
if (image.parser && image.parser.filterAttributes !== void 0) {
results = image.parser.filterAttributes(image, results);
} else if (image.element.tagName === 'SVG') {
SimpleSVG._SVG.defaultAttributes.forEach(function(attr) {
local.SVG.defaultAttributes.forEach(function(attr) {
delete results[attr];
});
}
@ -101,4 +98,4 @@
return results;
};
})(self.SimpleSVG);
})(local, local.config);

View File

@ -11,25 +11,27 @@
/**
* Main file
*/
(function(SimpleSVG, scope) {
(function(SimpleSVG, local) {
"use strict";
var initialized = false;
/**
* Find new icons and change them
*/
function findNewIcons() {
var paused = false;
SimpleSVG._findNewImages(SimpleSVG.config.rootElement === void 0 ? document.body : SimpleSVG.config.rootElement).forEach(function(image) {
if (SimpleSVG._loadImage(image)) {
if (!SimpleSVG.isReady) {
return;
}
local.findNewImages().forEach(function(image) {
if (local.loadImage(image)) {
if (!paused) {
paused = true;
SimpleSVG.pauseObserving();
}
SimpleSVG._renderSVG(image, !SimpleSVG._imageVisible(image));
local.renderSVG(image, !local.imageVisible(image));
}
});
@ -38,53 +40,29 @@
}
}
/**
* Callback when new icons were added to storage
*/
function newIcons() {
findNewIcons();
}
/**
* Callback when DOM was changed
*/
function scanDOM() {
if (!SimpleSVG.isReady) {
return;
}
// Find new icons
findNewIcons();
// Check visibility of existing icons
if (SimpleSVG._checkLazyLoader !== void 0) {
SimpleSVG._checkLazyLoader();
// TODO: Check visibility of existing icons
}
}
SimpleSVG._scanDOM = scanDOM;
/**
* Start script
* Set local functions
*/
function init() {
if (initialized) {
return;
}
initialized = true;
local.iconsAdded = findNewIcons;
local.nodesAdded = scanDOM;
// Setup events
SimpleSVG._onIconsAdded = newIcons;
SimpleSVG._onNodesAdded = scanDOM;
// window.addEventListener('load', scanDOM);
/**
* Scan DOM when script is ready
*/
local.initQueue.push(scanDOM);
// Scan DOM
scanDOM();
}
switch (document.readyState) {
case 'loading':
document.addEventListener('DOMContentLoaded', init);
document.onreadystatechange = init;
break;
default:
init();
}
})(self.SimpleSVG, self);
})(SimpleSVG, local);

103
src/browser/init.js Normal file
View File

@ -0,0 +1,103 @@
/**
* This file is part of the simple-svg package.
*
* (c) Vjacheslav Trushkin <cyberalien@gmail.com>
*
* For the full copyright and license information, please view the license.txt
* file that was distributed with this source code.
* @license MIT
*/
/**
* Check if DOM is ready, fire stuff when it is
*/
(function(SimpleSVG, local, config) {
"use strict";
var loaded = false,
initialized = false;
/**
* DOM is ready. Initialize stuff
*/
function DOMReady() {
loaded = true;
local.init();
}
/**
* Remove event listeners and call DOMReady()
*/
function DOMLoaded() {
document.removeEventListener('DOMContentLoaded', DOMLoaded);
window.removeEventListener('load', DOMLoaded);
DOMReady();
}
/**
* List of callbacks to call to test if script is ready
* Callback should return false if not ready, true if ready
*
* @type {[function]}
*/
local.preInitQueue = [function() {
return loaded;
}];
/**
* List of callbacks to call when SimpleSVG is ready
*
* @type {[function]}
*/
local.initQueue = [];
/**
* Initialize SimpleSVG
*/
local.init = function() {
if (initialized) {
return;
}
// Filter all callbacks, keeping only those that return false
local.preInitQueue = local.preInitQueue.filter(function(callback) {
return !callback();
});
// Callbacks queue is empty - script is ready to be initialized
if (!local.preInitQueue.length) {
initialized = true;
window.setTimeout(function() {
SimpleSVG.isReady = true;
local.initQueue.forEach(function(callback) {
callback();
});
local.event(config._readyEvent);
});
}
};
/**
* Events to run when SimpleSVG is ready
*
* @param {function} callback
*/
SimpleSVG.ready = function(callback) {
if (SimpleSVG.isReady) {
window.setTimeout(callback);
} else {
document.addEventListener(config._readyEvent, callback);
}
};
// Do stuff on next tick after script has loaded
window.setTimeout(function() {
if (document.readyState === 'complete' || (document.readyState !== 'loading' && !document.documentElement.doScroll)) {
DOMReady();
} else {
document.addEventListener('DOMContentLoaded', DOMLoaded);
window.addEventListener('load', DOMLoaded);
}
});
})(SimpleSVG, local, local.config);

View File

@ -11,17 +11,5 @@
/**
* Replacement for loader module when CDN is disabled
*/
(function(SimpleSVG) {
"use strict";
/**
* Check if image exists in library
*
* @param {object} image Image object
* @param {boolean} [checkQueue] True if queue should be checked. Default = true
* @return {boolean}
* @private
*/
SimpleSVG._loadImage = SimpleSVG.iconExists;
})(self.SimpleSVG);
local.loadImage = SimpleSVG.iconExists;

View File

@ -11,11 +11,7 @@
/**
* Replacement for lazy loader when lazy loader is disabled
*/
(function(SimpleSVG) {
"use strict";
SimpleSVG._imageVisible = function(image) {
local.imageVisible = function(image) {
return true;
};
})(self.SimpleSVG);
};

View File

@ -11,10 +11,6 @@
/**
* Replacement for observer module when observer is disabled
*/
(function(SimpleSVG) {
"use strict";
SimpleSVG.pauseObserving = function() {};
SimpleSVG.resumeObserving = function() {};
})(self.SimpleSVG);
SimpleSVG.pauseObserving = function() {};
SimpleSVG.resumeObserving = function() {};

View File

@ -19,7 +19,10 @@
*
* @type {[string]}
*/
var faReserved = ['fa-lg', 'fa-2x', 'fa-3x', 'fa-4x', 'fa-5x', 'fa-fw', 'fa-ul', 'fa-li', 'fa-border', 'fa-pull-left', 'fa-pull-right', 'fa-spin', 'fa-pulse', 'fa-rotate-90', 'fa-rotate-180', 'fa-rotate-270', 'fa-flip-horizontal', 'fa-flip-vertical', 'fa-stack', 'fa-stack-1x', 'fa-stack-2x', 'fa-inverse'];
var faReserved = ['fa-lg', 'fa-2x', 'fa-3x', 'fa-4x', 'fa-5x', 'fa-fw', 'fa-ul', 'fa-li', 'fa-border', 'fa-pull-left', 'fa-pull-right', 'fa-spin', 'fa-pulse', 'fa-rotate-90', 'fa-rotate-180', 'fa-rotate-270', 'fa-flip-horizontal', 'fa-flip-vertical', 'fa-stack', 'fa-stack-1x', 'fa-stack-2x', 'fa-inverse'],
rotationClasses = SimpleSVG.getConfig('_rotationClasses'),
hFlipClass = SimpleSVG.getConfig('_hFlipClass'),
vFlipClass = SimpleSVG.getConfig('_vFlipClass');
/**
* Add finder to list of finders
@ -59,23 +62,23 @@
for (var i = 0; i < list.length; i++) {
switch (list[i]) {
case 'fa-rotate-90':
results.push(SimpleSVG.config.rotationClasses['1']);
results.push(rotationClasses['1']);
break;
case 'fa-rotate-180':
results.push(SimpleSVG.config.rotationClasses['2']);
results.push(rotationClasses['2']);
break;
case 'fa-rotate-270':
results.push(SimpleSVG.config.rotationClasses['3']);
results.push(rotationClasses['3']);
break;
case 'fa-flip-horizontal':
results.push(SimpleSVG.config.hFlipClass);
results.push(hFlipClass);
break;
case 'fa-flip-vertical':
results.push(SimpleSVG.config.vFlipClass);
results.push(vFlipClass);
break;
default:
@ -89,4 +92,4 @@
}
});
})(self.SimpleSVG);
})(SimpleSVG);

View File

@ -11,23 +11,23 @@
/**
* Module for changing images
*/
(function(SimpleSVG) {
(function(SimpleSVG, local, config) {
"use strict";
var placeholderTag = SimpleSVG.config.placeholderTag,
iconAttribute = SimpleSVG.config.iconAttribute,
loadingClass = SimpleSVG.config.loadingClass,
imageClass = SimpleSVG.config.imageClass,
hFlipClass = SimpleSVG.config.hFlipClass,
vFlipClass = SimpleSVG.config.vFlipClass,
rotationClasses = SimpleSVG.config.rotationClasses,
var placeholderTag = config._placeholderTag,
iconAttribute = config._iconAttribute,
loadingClass = config._loadingClass,
imageClass = config._imageClass,
hFlipClass = config._hFlipClass,
vFlipClass = config._vFlipClass,
rotationClasses = config._rotationClasses,
transformationChanges = {},
transformationClasses;
/**
* Generate SVG code
*
* @param {string} html SVG code with all attributes
* @param {string} html Empty SVG element with all attributes
* @param {string} body Body
* @return {string}
*/
@ -81,17 +81,16 @@
*
* @param {object} image
* @param {boolean} [hidden]
* @private
*/
SimpleSVG._renderSVG = function(image, hidden) {
var attributes = SimpleSVG._getImageAttributes(image),
local.renderSVG = function(image, hidden) {
var attributes = local.getImageAttributes(image),
item = SimpleSVG.getIcon(image.icon),
svg, el, el2, data, html;
hidden = hidden === true;
attributes[iconAttribute] = image.icon;
svg = new SimpleSVG._SVG(item, hidden);
svg = new local.SVG(item, hidden);
el = document.createElement(hidden ? placeholderTag : 'svg');
// flip and rotate
@ -150,7 +149,7 @@
return false;
}
svg = new SimpleSVG._SVG(SimpleSVG.getIcon(name));
svg = new local.SVG(SimpleSVG.getIcon(name));
data = svg.svgObject(properties, false);
el = document.createElement('svg');
@ -161,4 +160,4 @@
return generateSVG(el.outerHTML, data.body);
};
})(self.SimpleSVG);
})(SimpleSVG, local, local.config);

View File

@ -9,13 +9,13 @@
*/
/**
* Replacement for observer module when observer is disabled
* Icons storage handler
*/
(function(SimpleSVG) {
(function(SimpleSVG, local) {
"use strict";
var eventQueued = false,
storage = new SimpleSVG._Storage();
storage = new local.Storage();
/**
* Triggers callback
@ -25,23 +25,21 @@
return;
}
eventQueued = false;
if (typeof SimpleSVG._onIconsAdded === 'function') {
SimpleSVG._onIconsAdded();
}
local.iconsAdded();
}
/**
* Function to add library
* Function to add collection
*
* @param {object} json JSON data
* @return {number} Number of added items
*/
SimpleSVG.addLibrary = function(json) {
var result = storage.addLibrary(json);
SimpleSVG.addCollection = function(json) {
var result = storage.addCollection(json);
if (result) {
if (!eventQueued) {
eventQueued = true;
setTimeout(triggerCallback, 0);
window.setTimeout(triggerCallback, 0);
}
}
};
@ -58,7 +56,7 @@
if (result) {
if (!eventQueued) {
eventQueued = true;
setTimeout(triggerCallback, 0);
window.setTimeout(triggerCallback, 0);
}
}
return result;
@ -88,4 +86,4 @@
*/
SimpleSVG.listIcons = storage.list.bind(storage);
})(self.SimpleSVG);
})(SimpleSVG, local);

View File

@ -9,21 +9,21 @@
*/
/**
* Default configuration when CDN is included
* Default configuration when CDN module is included
*/
(function(SimpleSVG, scope) {
(function(config) {
"use strict";
// CDN callback script
SimpleSVG._defaultConfig.defaultCDN = '//cdn.simplesvg.com/json/?callback={callback}&icons={icons}';
config.defaultCDN = '//cdn.simplesvg.com/json/?callback={callback}&icons={icons}';
// Custom CDN list. Key = prefix, value = CDN URL
SimpleSVG._defaultConfig.customCDN = {};
config.customCDN = {};
// Maximum URL size for CDN
SimpleSVG._defaultConfig.loaderMaxURLSize = 500;
config.loaderMaxURLSize = 500;
// Custom event to call when new set of images is added
SimpleSVG._defaultConfig.loaderEvent = 'newSSVGImages';
config._loaderEvent = 'SimpleSVGAddedIcons';
})(self.SimpleSVG, self);
})(local.config);

View File

@ -11,7 +11,7 @@
/**
* Module for loading images from remote location
*/
(function(global, SimpleSVG) {
(function(SimpleSVG, local, config, global) {
"use strict";
/**
@ -35,8 +35,8 @@
function loadQueue() {
var queues = {},
URLLengths = {},
limit = SimpleSVG.config.loaderMaxURLSize,
prefixes = Object.keys(SimpleSVG.config.customCDN);
limit = config.loaderMaxURLSize,
prefixes = Object.keys(config.customCDN);
/**
* Send JSONP request by adding script tag to document
@ -45,7 +45,7 @@
* @param {Array} items
*/
function addScript(prefix, items) {
var url = prefix === '.' ? SimpleSVG.config.defaultCDN : SimpleSVG.config.customCDN[prefix],
var url = prefix === '.' ? config.defaultCDN : config.customCDN[prefix],
element;
url = url.replace('{callback}', 'SimpleSVG._loaderCallback').replace('{icons}', items.join(','));
@ -65,7 +65,7 @@
* @return {number|null}
*/
function baseLength(prefix) {
var url = prefix === '.' ? SimpleSVG.config.defaultCDN : SimpleSVG.config.customCDN[prefix];
var url = prefix === '.' ? config.defaultCDN : config.customCDN[prefix];
return url.indexOf('{icons}') === -1 ? null : url.replace('{callback}', 'SimpleSVG._loaderCallback').replace('{icons}', '').length;
}
@ -135,7 +135,7 @@
queue.push(image);
if (!queued) {
queued = true;
setTimeout(loadQueue, 0);
window.setTimeout(loadQueue, 0);
}
return true;
}
@ -148,10 +148,11 @@
*/
SimpleSVG._loaderCallback = function(data) {
if (typeof data === 'object') {
SimpleSVG.addLibrary(data);
SimpleSVG.addCollection(data);
// Dispatch event
document.dispatchEvent(new CustomEvent(SimpleSVG.config.loaderEvent));
console.log('Added few images, dispatching event');
local.event(config._loaderEvent);
}
};
@ -161,16 +162,15 @@
* @param {object} image Image object
* @param {boolean} [checkQueue] True if queue should be checked. Default = true
* @return {boolean}
* @private
*/
SimpleSVG._loadImage = function(image, checkQueue) {
local.loadImage = function(image, checkQueue) {
if (SimpleSVG.iconExists(image.icon)) {
return true;
}
if (checkQueue !== false && addToQueue(image.icon)) {
// Mark as loading
image.element.classList.add(SimpleSVG.config.loadingClass);
image.element.classList.add(config._loadingClass);
}
return false;
@ -193,25 +193,4 @@
return queued;
};
/**
* CustomEvent polyfill for IE9
* From https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
*/
(function() {
if (typeof window.CustomEvent === 'function') return false;
function CustomEvent(event, params) {
var evt;
params = params || { bubbles: false, cancelable: false, detail: void 0 };
evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
})();
})(self, self.SimpleSVG);
})(SimpleSVG, local, local.config, global);

View File

@ -11,20 +11,20 @@
/**
* Default configuration when lazy loading is enabled
*/
(function(SimpleSVG) {
(function(config) {
"use strict";
// Enable lazy loading: true/false
SimpleSVG._defaultConfig.lazy = true;
config.lazy = true;
// True if loader should check parent element's visibility instead of SVG image
SimpleSVG._defaultConfig.lazyParent = true;
config.lazyParent = true;
// Time after scroll/resize event when lazy loading is tested.
// Used to reduce calculations when scroll/resize is called too often
SimpleSVG._defaultConfig.lazyDelay = 250;
config.lazyDelay = 250;
// True if lazy loader should wait until scrolling has ended before loading images.
SimpleSVG._defaultConfig.lazyWaitEndOfScroll = true;
config.lazyWaitEndOfScroll = true;
})(self.SimpleSVG);
})(local.config);

View File

@ -9,20 +9,19 @@
*/
/**
* Replacement for lazy loader when lazy loader is disabled
* Lazy loader - renders only SVG icons that are visible
*/
(function(SimpleSVG) {
(function(local) {
"use strict";
/**
* TODO!
*
* @param image
* @param {object} image
* @return {boolean}
* @private
*/
SimpleSVG._imageVisible = function(image) {
local.imageVisible = function(image) {
return true;
};
})(self.SimpleSVG);
})(local);

View File

@ -12,15 +12,15 @@
* Observer function
*
* This function waits for new nodes to be added to DOM, then calls
* private function SimpleSVG._onNodesAdded(nodes)
* function local.nodesAdded(nodes)
*
* Callback argument "nodes" is not checked for duplicate nodes and list could be incorrect when using IE
*
* Observer should be paused before adding any new items using SimpleSVG.pauseObserving()
* and resumed after that using SimpleSVG.resumeObserving()
* Observer can be paused using SimpleSVG.pauseObserving()
* and resumed using SimpleSVG.resumeObserving()
* Pause/resume can stack, so if you call pause twice, resume should be called twice.
*/
(function(SimpleSVG, scope) {
(function(SimpleSVG, local, config, global) {
"use strict";
var observer = null,
@ -32,25 +32,6 @@
subtree: true
};
/**
* Setup dummy functions that replace observer
*/
function setupDummy() {
SimpleSVG.pauseObserving = function() {};
SimpleSVG.resumeObserving = function() {};
}
/**
* Trigger callback function
*
* @param {Array} nodes List of added nodes
*/
function triggerEvent(nodes) {
if (typeof SimpleSVG._onNodesAdded === 'function') {
SimpleSVG._onNodesAdded(nodes);
}
}
/**
* Process all pending mutations
*/
@ -60,7 +41,7 @@
addedNodes = false;
if (temp !== false && temp.length) {
// At least 1 node was added
triggerEvent(temp);
local.nodesAdded(temp);
}
}
@ -76,7 +57,7 @@
// Parse on next tick to collect all mutations
if (addedNodes === false) {
addedNodes = [];
setTimeout(processPendingMutations, 0);
window.setTimeout(processPendingMutations, 0);
}
if (mutation.addedNodes) {
for (i = 0; i < mutation.addedNodes.length; i++) {
@ -90,33 +71,7 @@
* Start/resume observing
*/
function observe() {
observer.observe(SimpleSVG.config.rootElement === void 0 ? document.body : SimpleSVG.config.rootElement, params);
}
/**
* Create observer instance and start observing
*/
function init() {
observer = new scope.MutationObserver(processMutations);
observe();
}
/**
* Queue polyfill callback
*/
function queuePolyfill() {
var oldCallback = SimpleSVG._onPolyfillLoaded;
SimpleSVG._onPolyfillLoaded = function() {
// Init observer and scan
init(true);
triggerEvent([]);
// Call previous callback
if (oldCallback !== void 0) {
oldCallback();
}
};
observer.observe(config._root === void 0 ? document.querySelector('body') : config._root, params);
}
/**
@ -126,8 +81,10 @@
*/
SimpleSVG.pauseObserving = function() {
if (observer === null) {
paused ++;
return;
}
if (!paused) {
// Store pending records, stop observer
queue = observer.takeRecords();
@ -142,7 +99,11 @@
SimpleSVG.resumeObserving = function() {
var temp;
if (observer === null || !paused) {
if (observer === null) {
paused --;
return;
}
if (!paused) {
return;
}
@ -156,10 +117,14 @@
}
};
if (SimpleSVG._loadingPolyfill) {
queuePolyfill();
} else {
init();
/**
* Start observing when all modules and DOM are ready
*/
local.initQueue.push(function () {
observer = new global.MutationObserver(processMutations);
if (!paused) {
observe();
}
});
})(self.SimpleSVG, self);
})(SimpleSVG, local, local.config, global);

View File

@ -11,10 +11,10 @@
/**
* Default configuration when observer is included
*/
(function(SimpleSVG) {
(function(config) {
"use strict";
// Polyfill script URL
SimpleSVG._defaultConfig.polyfill = '//cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.24/webcomponents-lite.min.js';
config._polyfill = '//cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/0.7.24/webcomponents-lite.min.js';
})(self.SimpleSVG);
})(local.config);

View File

@ -11,21 +11,18 @@
/**
* Observer function
*
* This function waits for new nodes to be added to DOM, then calls
* private function SimpleSVG._onNodesAdded(nodes)
*
* Callback argument "nodes" is not checked for duplicate nodes and list could be incorrect when using IE
*
* Observer automatically loads polyfill for MutationObserver for IE9-10 from CDN that can be configured
* See polyfill.js
*
* Observer should be paused before adding any new items using SimpleSVG.pauseObserving()
* and resumed after that using SimpleSVG.resumeObserving()
* Pause/resume can stack, so if you call pause twice, resume should be called twice.
*/
(function(SimpleSVG, scope) {
(function(local, config, global) {
"use strict";
var poly = false;
var polyCounter = false,
polyLoaded = true;
/**
* Try to load polyfill
@ -36,20 +33,18 @@
var timer, element;
function check() {
if (!scope.MutationObserver || !scope.WeakMap) {
poly ++;
if (!global.MutationObserver || !global.WeakMap) {
polyCounter ++;
// Check up to 50 times (25 seconds), then give up
if (poly > 50) {
if (polyCounter > 50) {
clearInterval(timer);
}
} else {
clearInterval(timer);
// Loaded!
SimpleSVG._loadingPolyfill = false;
if (SimpleSVG._onPolyfillLoaded !== void 0) {
SimpleSVG._onPolyfillLoaded();
}
polyLoaded = true;
local.init();
}
}
@ -57,7 +52,7 @@
element.setAttribute('src', url);
element.setAttribute('type', 'text/javascript');
element.setAttribute('async', true);
poly = 1;
polyCounter = 1;
document.head.appendChild(element);
@ -66,11 +61,13 @@
// Check if MutationObserver is available in browser
// P.S. IE must die!
SimpleSVG._loadingPolyfill = false;
if ((!scope.MutationObserver || !scope.WeakMap) && SimpleSVG.config.polyfill) {
if ((!global.MutationObserver || !global.WeakMap) && config._polyfill) {
// Try to load polyfill
SimpleSVG._loadingPolyfill = true;
loadPolyFill(SimpleSVG.config.polyfill);
polyLoaded = false;
local.preInitQueue.push(function() {
return polyLoaded;
});
loadPolyFill(config._polyfill);
}
})(self.SimpleSVG, self);
})(local, local.config, global);

View File

@ -177,12 +177,12 @@ function Storage() {
this.items = {};
/**
* Function to add library
* Function to add collection
*
* @param {object} json JSON data
* @return {number} Number of added items
*/
this.addLibrary = function(json) {
this.addCollection = function(json) {
// Get default values
var defaults = {},
items = this.items,

View File

@ -49,7 +49,12 @@
mocha.run();
});
(function() {
var oldLog = console.log;
console.log = function() {
oldLog.apply(this, arguments);
var html = '';
for (var i = 0; i < arguments.length; i ++) {
switch (typeof arguments[i]) {
@ -65,6 +70,8 @@
}
$('#log').append($('<p />').text(html));
};
})();
</script>
</body>
</html>

View File

@ -5,7 +5,7 @@
const fs = require('fs');
module.exports = (Helper, codeDir, testFile) => {
module.exports = (Helper, codeDir, testFile, TestHelper) => {
let code = fs.readFileSync(testFile, 'utf8'),
modules = [
fs.readFileSync(codeDir + '/browser/defaults.js', 'utf8'),
@ -15,7 +15,7 @@ module.exports = (Helper, codeDir, testFile) => {
];
// Replace code
modules = modules.map(item => item.replace('self.SimpleSVG', 'SimpleSVG')).join('');
modules = modules.join('');
// Merge modules and test
code = code.replace('/* Modules() */', modules);

View File

@ -4,12 +4,21 @@
var expect = chai.expect,
should = chai.should();
function load(SimpleSVG) {
function load(SimpleSVG, local) {
var global = {};
if (SimpleSVG.isReady === void 0) {
SimpleSVG.isReady = true;
}
local.config = {};
/* Modules() */
}
describe('Testing image finder', function() {
var SimpleSVG,
local,
containerID = 'finder-container',
validIconsID = 'finder-basic',
invalidIconsID = 'finder-invalid',
@ -52,48 +61,49 @@
// Setup fake SimpleSVG instance
SimpleSVG = {};
local = {};
// Load libraries
load(SimpleSVG);
load(SimpleSVG, local);
expect(typeof SimpleSVG._findNewImages).to.be.equal('function');
expect(typeof SimpleSVG._findHiddenImages).to.be.equal('function');
expect(typeof SimpleSVG._findParsedImages).to.be.equal('function');
expect(typeof local.findNewImages).to.be.equal('function');
expect(typeof local.findHiddenImages).to.be.equal('function');
expect(typeof local.findParsedImages).to.be.equal('function');
});
it('finding valid images', function() {
var results;
// Find new icons
results = SimpleSVG._findNewImages(validIconsRoot, false);
results = local.findNewImages(validIconsRoot, false);
expect(results.length).to.be.equal(4, 'Wrong number of new images');
expect(results.map(function(item) {
return item.icon
})).to.be.eql(['fa-bear', 'fa-apple', 'fa-apple', 'mdi-arrow-up']);
// Find icons that are being loaded
results = SimpleSVG._findNewImages(validIconsRoot, true);
results = local.findNewImages(validIconsRoot, true);
expect(results.length).to.be.equal(2, 'Wrong number of images awaiting loader');
expect(results.map(function(item) {
return item.icon
})).to.be.eql(['fa-login', 'mdi-home']);
// Find all icons that have not been parsed
results = SimpleSVG._findNewImages(validIconsRoot);
results = local.findNewImages(validIconsRoot);
expect(results.length).to.be.equal(6, 'Wrong number of unparsed images');
expect(results.map(function(item) {
return item.icon
})).to.be.eql(['fa-bear', 'fa-apple', 'fa-apple', 'mdi-arrow-up', 'fa-login', 'mdi-home']);
// Find all icons awaiting lazy loader
results = SimpleSVG._findHiddenImages(validIconsRoot);
results = local.findHiddenImages(validIconsRoot);
expect(results.length).to.be.equal(2, 'Wrong number of hidden images');
expect(results.map(function(item) {
return item.icon
})).to.be.eql(['icon-home', 'mdi-close']);
// Find all parsed icons
results = SimpleSVG._findParsedImages(validIconsRoot);
results = local.findParsedImages(validIconsRoot);
expect(results.length).to.be.equal(1, 'Wrong number of parsed images');
expect(results.map(function(item) {
return item.icon
@ -104,26 +114,26 @@
var results;
// Find new icons
results = SimpleSVG._findNewImages(invalidIconsRoot, false);
results = local.findNewImages(invalidIconsRoot, false);
expect(results.length).to.be.equal(0, 'Wrong number of new images');
// Find icons that are being loaded
results = SimpleSVG._findNewImages(invalidIconsRoot, true);
results = local.findNewImages(invalidIconsRoot, true);
expect(results.length).to.be.equal(0, 'Wrong number of images awaiting loader');
// Find all icons that have not been parsed
results = SimpleSVG._findNewImages(invalidIconsRoot);
results = local.findNewImages(invalidIconsRoot);
expect(results.length).to.be.equal(0, 'Wrong number of unparsed images');
// Find all icons awaiting lazy loader
results = SimpleSVG._findHiddenImages(invalidIconsRoot);
results = local.findHiddenImages(invalidIconsRoot);
expect(results.length).to.be.equal(1, 'Wrong number of hidden images');
expect(results.map(function(item) {
return item.icon
})).to.be.eql(['pending-placeholder']);
// Find all parsed icons
results = SimpleSVG._findParsedImages(invalidIconsRoot);
results = local.findParsedImages(invalidIconsRoot);
expect(results.length).to.be.equal(1, 'Wrong number of parsed images');
expect(results.map(function(item) {
return item.icon
@ -134,28 +144,29 @@
var results;
// Find new icons
results = SimpleSVG._findNewImages(containerRoot, false);
results = local.findNewImages(containerRoot, false);
expect(results.length).to.be.equal(4, 'Wrong number of new images');
// Find icons that are being loaded
results = SimpleSVG._findNewImages(containerRoot, true);
results = local.findNewImages(containerRoot, true);
expect(results.length).to.be.equal(2, 'Wrong number of images awaiting loader');
// Find all icons that have not been parsed
results = SimpleSVG._findNewImages(containerRoot);
results = local.findNewImages(containerRoot);
expect(results.length).to.be.equal(6, 'Wrong number of unparsed images');
// Find all icons awaiting lazy loader
results = SimpleSVG._findHiddenImages(containerRoot);
results = local.findHiddenImages(containerRoot);
expect(results.length).to.be.equal(3, 'Wrong number of hidden images');
// Find all parsed icons
results = SimpleSVG._findParsedImages(containerRoot);
results = local.findParsedImages(containerRoot);
expect(results.length).to.be.equal(2, 'Wrong number of parsed images');
});
it('checking custom finder', function() {
var SimpleSVG = {},
var SimpleSVG,
local,
containerID = 'custom-finder',
containerRoot, faReserved, results;
@ -172,9 +183,10 @@
// Setup fake SimpleSVG instance
SimpleSVG = {};
local = {};
// Load libraries
load(SimpleSVG);
load(SimpleSVG, local);
// Add FontAwesome finder
faReserved = ['fa-lg', 'fa-2x', 'fa-3x', 'fa-4x', 'fa-5x', 'fa-fw', 'fa-ul', 'fa-li', 'fa-border', 'fa-pull-left', 'fa-pull-right', 'fa-spin', 'fa-pulse', 'fa-rotate-90', 'fa-rotate-180', 'fa-rotate-270', 'fa-flip-horizontal', 'fa-flip-vertical', 'fa-stack', 'fa-stack-1x', 'fa-stack-2x', 'fa-inverse'];
@ -195,35 +207,35 @@
});
// Find new icons
results = SimpleSVG._findNewImages(containerRoot, false);
results = local.findNewImages(containerRoot, false);
expect(results.length).to.be.equal(4, 'Wrong number of new images');
expect(results.map(function(item) {
return item.icon
}).sort()).to.be.eql(['mdi-bear', 'fa-star', 'fa-apple', 'fa-bookmark'].sort());
// Find icons that are being loaded
results = SimpleSVG._findNewImages(containerRoot, true);
results = local.findNewImages(containerRoot, true);
expect(results.length).to.be.equal(2, 'Wrong number of images awaiting loader');
expect(results.map(function(item) {
return item.icon
}).sort()).to.be.eql(['mdi-login', 'fa-home'].sort());
// Find all icons that have not been parsed
results = SimpleSVG._findNewImages(containerRoot);
results = local.findNewImages(containerRoot);
expect(results.length).to.be.equal(6, 'Wrong number of unparsed images');
expect(results.map(function(item) {
return item.icon
}).sort()).to.be.eql(['mdi-bear', 'fa-star', 'fa-apple', 'fa-bookmark', 'mdi-login', 'fa-home'].sort());
// Find all icons awaiting lazy loader
results = SimpleSVG._findHiddenImages(containerRoot);
results = local.findHiddenImages(containerRoot);
expect(results.length).to.be.equal(1, 'Wrong number of hidden images');
expect(results.map(function(item) {
return item.icon
})).to.be.eql(['mdi-close']);
// Find all parsed icons
results = SimpleSVG._findParsedImages(containerRoot);
results = local.findParsedImages(containerRoot);
expect(results.length).to.be.equal(1, 'Wrong number of parsed images');
expect(results.map(function(item) {
return item.icon

View File

@ -5,7 +5,7 @@
const fs = require('fs');
module.exports = (Helper, codeDir, testFile) => {
module.exports = (Helper, codeDir, testFile, TestHelper) => {
let code = fs.readFileSync(testFile, 'utf8'),
modules = [
fs.readFileSync(codeDir + '/browser/defaults.js', 'utf8'),
@ -14,7 +14,7 @@ module.exports = (Helper, codeDir, testFile) => {
];
// Replace code
modules = modules.map(item => item.replace('self.SimpleSVG', 'SimpleSVG')).join('');
modules = modules.join('');
// Merge modules and test
code = code.replace('/* Modules() */', modules);

View File

@ -4,13 +4,22 @@
var expect = chai.expect,
should = chai.should();
function load(SimpleSVG) {
function load(SimpleSVG, local) {
var global = {};
if (SimpleSVG.isReady === void 0) {
SimpleSVG.isReady = true;
}
local.config = {};
/* Modules() */
}
describe('Testing image object', function() {
it('filtering attributes and classes', function() {
var SimpleSVG = {},
local = {},
prefix = 'image-id-',
image, result;
@ -23,23 +32,23 @@
// Setup fake SimpleSVG instance and load libraries
// Load libraries
load(SimpleSVG);
load(SimpleSVG, local);
// Empty image
image = SimpleSVG._newImage(document.querySelector('#' + prefix + 'empty > i'), 'foo', {});
result = SimpleSVG._getImageAttributes(image);
image = local.newImage(document.querySelector('#' + prefix + 'empty > i'), 'foo', {});
result = local.getImageAttributes(image);
expect(result).to.be.eql({});
// Simple image
image = SimpleSVG._newImage(document.querySelector('#' + prefix + 'simple > i'), 'foo', {});
result = SimpleSVG._getImageAttributes(image);
image = local.newImage(document.querySelector('#' + prefix + 'simple > i'), 'foo', {});
result = local.getImageAttributes(image);
expect(result).to.be.eql({
'class': ''
});
// Many attributes
image = SimpleSVG._newImage(document.querySelector('#' + prefix + 'custom > i'), 'foo', {});
result = SimpleSVG._getImageAttributes(image);
image = local.newImage(document.querySelector('#' + prefix + 'custom > i'), 'foo', {});
result = local.getImageAttributes(image);
expect(result).to.be.eql({
'class': 'icon fa fa-home loaded',
style: 'height: 1em;',
@ -48,7 +57,7 @@
});
// Using class filter
image = SimpleSVG._newImage(document.querySelector('#' + prefix + 'custom > i'), 'foo', {
image = local.newImage(document.querySelector('#' + prefix + 'custom > i'), 'foo', {
filterClasses: function(image, list) {
var results = [],
item;
@ -68,7 +77,7 @@
}
});
result = SimpleSVG._getImageAttributes(image);
result = local.getImageAttributes(image);
expect(result).to.be.eql({
'class': 'icon loaded',
style: 'height: 1em;',

View File

@ -5,26 +5,27 @@
const fs = require('fs');
module.exports = (Helper, codeDir, testFile) => {
module.exports = (Helper, codeDir, testFile, TestHelper) => {
let code = fs.readFileSync(testFile, 'utf8'),
modules = [
'(function (SimpleSVG) {\n' +
fs.readFileSync(codeDir + '/common/storage.js', 'utf8')
.replace('module.exports = Storage;', 'SimpleSVG._Storage = Storage;') +
'\n})(self.SimpleSVG);\n',
TestHelper.fakeEvents() +
TestHelper.fakeInit() +
TestHelper.getStorage() +
fs.readFileSync(codeDir + '/browser/storage.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/defaults.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/with-cdn/defaults.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/config.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/image.js', 'utf8'),
'(function (SimpleSVG) {\n' +
'SimpleSVG.testLoaderURL = function() { return true; }' +
'\n})(self.SimpleSVG);\n',
// Temporary function
'SimpleSVG.testLoaderURL = function() { return true; };' +
// Replace content of addScript()
fs.readFileSync(codeDir + '/browser/with-cdn/loader.js', 'utf8').replace('// Create script', 'if (!SimpleSVG.testLoaderURL(url)) return;')
];
// Replace code
modules = modules.map(item => item.replace('self.SimpleSVG', 'SimpleSVG')).join('');
modules = modules.join('');
// Merge modules and test
code = code.replace('/* Modules() */', modules);

View File

@ -4,13 +4,25 @@
var expect = chai.expect,
should = chai.should();
function load(SimpleSVG) {
function load(SimpleSVG, local) {
var global = {};
if (SimpleSVG.isReady === void 0) {
SimpleSVG.isReady = true;
}
local.config = {};
local.iconsAdded = function() {};
/* Modules() */
}
describe('Testing image loader', function() {
it('loading images', function(done) {
var SimpleSVG = {},
var SimpleSVG = {
},
local = {
},
containerID = 'loader-basic',
firstCallback = true,
containerRoot, apple, star, star2, star3;
@ -26,7 +38,7 @@
containerRoot = document.getElementById(containerID);
// Add event listener
document.addEventListener('newSSVGImagesTest', function() {
local.newSSVGImagesTest = function() {
if (firstCallback) {
// First time callback is called, check class names
expect(apple.element.classList.contains('svg-loading')).to.be.equal(true, 'apple icon should have class svg-loading');
@ -40,11 +52,11 @@
expect(SimpleSVG.iconExists('fa-star-half-empty')).to.be.equal(false, 'fa-star-half-empty should not exist (2)');
// loadImage should return true for existing icon
expect(SimpleSVG._loadImage(star)).to.be.equal(true, 'fa-star should be loaded (1)');
expect(SimpleSVG._loadImage(star2)).to.be.equal(true, 'fa-star should be loaded (2)');
expect(local.loadImage(star)).to.be.equal(true, 'fa-star should be loaded (1)');
expect(local.loadImage(star2)).to.be.equal(true, 'fa-star should be loaded (2)');
// Load 1 more icon
expect(SimpleSVG._loadImage(star3)).to.be.equal(false, 'fa-star-half-full should not be loaded');
expect(local.loadImage(star3)).to.be.equal(false, 'fa-star-half-full should not be loaded');
firstCallback = false;
return;
@ -58,24 +70,24 @@
expect(SimpleSVG.iconExists('fa-star-half-full')).to.be.equal(true, 'fa-star-half-full should exist');
expect(SimpleSVG.iconExists('fa-star-half-empty')).to.be.equal(true, 'fa-star-half-empty should exist - alias of fa-star-half-full');
expect(SimpleSVG._loadImage(star2)).to.be.equal(true, 'star2 should be loaded');
expect(SimpleSVG._loadImage(star2)).to.be.equal(true, 'star2 should be loaded');
expect(local.loadImage(star2)).to.be.equal(true, 'star2 should be loaded');
expect(local.loadImage(star2)).to.be.equal(true, 'star2 should be loaded');
done();
});
};
// Load libraries
load(SimpleSVG);
SimpleSVG.config.defaultCDN = SimpleSVG.config.defaultCDN.replace('{callback}', 'window.SSVGLoaderTest1');
SimpleSVG.config.loaderEvent = 'newSSVGImagesTest';
load(SimpleSVG, local);
local.config.defaultCDN = local.config.defaultCDN.replace('{callback}', 'window.SSVGLoaderTest1');
local.config.loaderEvent = 'newSSVGImagesTest';
window.SSVGLoaderTest1 = SimpleSVG._loaderCallback;
// Find icons
apple = SimpleSVG._newImage(containerRoot.querySelector('.fa.fa-apple'), 'fa-apple', null);
star = SimpleSVG._newImage(containerRoot.querySelector('.star'), 'fa-star', null);
star2 = SimpleSVG._newImage(containerRoot.querySelector('.another-star'), 'fa-star', null);
apple = local.newImage(containerRoot.querySelector('.fa.fa-apple'), 'fa-apple', null);
star = local.newImage(containerRoot.querySelector('.star'), 'fa-star', null);
star2 = local.newImage(containerRoot.querySelector('.another-star'), 'fa-star', null);
// fa-star-half-full is alias of fa-star-half-empty
star3 = SimpleSVG._newImage(containerRoot.querySelector('.third-star'), 'fa-star-half-full', null);
star3 = local.newImage(containerRoot.querySelector('.third-star'), 'fa-star-half-full', null);
// Check if icons exist
expect(SimpleSVG.iconExists('fa-apple')).to.be.equal(false, 'fa-apple should not exist');
@ -84,12 +96,15 @@
expect(SimpleSVG.iconExists('fa-star-half-empty')).to.be.equal(false, 'fa-star-half-empty should not exist');
// Load icons
expect(SimpleSVG._loadImage(apple)).to.be.equal(false, 'fa-apple should not be loaded');
expect(SimpleSVG._loadImage(star)).to.be.equal(false, 'fa-star should not be loaded');
expect(local.loadImage(apple)).to.be.equal(false, 'fa-apple should not be loaded');
expect(local.loadImage(star)).to.be.equal(false, 'fa-star should not be loaded');
});
it('multiple CDNs and icons limit', function(done) {
var SimpleSVG = {},
var SimpleSVG = {
},
local = {
},
element = document.createElement('div'),
expecting = [
'default?icons=mdi-home,mdi-arrow-left,emoji-cat',
@ -100,7 +115,7 @@
icons;
// Load libraries
load(SimpleSVG);
load(SimpleSVG, local);
SimpleSVG.testLoaderURL = function(url) {
var index = expecting.indexOf(url);
expect(index).to.not.be.equal(-1, 'Unexpected callback URL: ' + url);
@ -110,16 +125,16 @@
}
return false;
};
SimpleSVG.config.defaultCDN = 'default?icons={icons}';
SimpleSVG.config.customCDN['fa'] = 'fa?icons={icons}';
SimpleSVG.config.customCDN['test'] = 'test?icons={icons}';
SimpleSVG.config.loaderMaxURLSize = 50;
SimpleSVG._debugLoader = true;
local.config.defaultCDN = 'default?icons={icons}';
local.config.customCDN['fa'] = 'fa?icons={icons}';
local.config.customCDN['test'] = 'test?icons={icons}';
local.config.loaderMaxURLSize = 50;
local._debugLoader = true;
// Add dummy icons
icons = {};
['fa-apple', 'fa-home', 'mdi-home', 'mdi-arrow-left', 'emoji-cat', 'foo-bar', 'test-foo', 'mdi-arrow-right'].forEach(function(key) {
icons[key] = SimpleSVG._newImage(element, key, null);
icons[key] = local.newImage(element, key, null);
});
// Check if icons exist
@ -129,7 +144,7 @@
// Load icons
Object.keys(icons).forEach(function(key) {
expect(SimpleSVG._loadImage(icons[key])).to.be.equal(false, key + ' should not be loaded');
expect(local.loadImage(icons[key])).to.be.equal(false, key + ' should not be loaded');
});
});
});

View File

@ -5,25 +5,24 @@
const fs = require('fs');
module.exports = (Helper, codeDir, testFile) => {
module.exports = (Helper, codeDir, testFile, TestHelper) => {
let code = fs.readFileSync(testFile, 'utf8'),
observerCode = fs.readFileSync(codeDir + '/browser/with-observer/observer.js', 'utf8'),
search, pos, index;
observerCode = fs.readFileSync(codeDir + '/browser/with-observer/observer.js', 'utf8');
// Change observer code
search = '(function';
pos = observerCode.indexOf(search);
if (pos === -1) {
throw new Error('Could not find required code in observer.js');
}
observerCode = 'function Observer' + observerCode.slice(pos + search.length);
observerCode = TestHelper.replace(
observerCode,
'(function(SimpleSVG, local, config, global) {',
'function Observer(SimpleSVG, local, global) { var config = local.config; ',
'Could not find required code in observer.js'
);
search = '})(self.SimpleSVG, self);';
pos = observerCode.indexOf(search);
if (pos === -1) {
throw new Error('Could not find required code in observer.js');
}
observerCode = observerCode.slice(0, pos) + '}';
observerCode = TestHelper.replace(
observerCode,
'})(SimpleSVG, local, local.config, global);',
'}',
'Could not find required code in observer.js (2)'
);
// Merge observer and test
code = code.replace('/* Observer() */', observerCode);

View File

@ -18,8 +18,8 @@
/* Observer() */
describe('Testing observer', function() {
it('dummy observer', function(done) {
var context, SimpleSVG,
it('inactive observer', function(done) {
var context, SimpleSVG, local,
tempId = 'observer-dummy',
called = false;
@ -31,24 +31,29 @@
// Setup fake global scope and SimpleSVG instance
context = {
MutationObserver: MutationObserver
};
SimpleSVG = {
isReady: true
};
local = {
config: {
observe: true,
rootElement: document.getElementById(tempId)
_root: document.getElementById(tempId)
},
_onNodesAdded: function(nodes) {
initQueue: [],
nodesAdded: function(nodes) {
called = true;
},
_loadingPolyfill: true
};
// Load observer
Observer(SimpleSVG, context);
Observer(SimpleSVG, local, context);
expect(typeof SimpleSVG.pauseObserving).to.be.equal('function', 'SimpleSVG.pauseObserving is missing');
expect(typeof SimpleSVG.resumeObserving).to.be.equal('function', 'SimpleSVG.resumeObserving is missing');
// Do not initialize observer!
// Check if observer is working
expect(called).to.be.equal(false, 'Observer callback was triggered too early');
jQuery('#' + tempId).append('<div />');
@ -59,7 +64,7 @@
});
it('setting up working observer', function(done) {
var context, SimpleSVG,
var context, SimpleSVG, local,
tempId = 'observer-basic',
called = false;
@ -75,21 +80,29 @@
MutationObserver: MutationObserver
};
SimpleSVG = {
isReady: true
};
local = {
config: {
observe: true,
rootElement: document.getElementById(tempId)
_root: document.getElementById(tempId)
},
_onNodesAdded: function(nodes) {
initQueue: [],
nodesAdded: function(nodes) {
called = true;
}
};
// Load observer
Observer(SimpleSVG, context);
Observer(SimpleSVG, local, context);
expect(typeof SimpleSVG.pauseObserving).to.be.equal('function', 'SimpleSVG.pauseObserving is missing');
expect(typeof SimpleSVG.resumeObserving).to.be.equal('function', 'SimpleSVG.resumeObserving is missing');
// Init observer
local.initQueue.forEach(function(callback) {
callback();
});
// Check if observer is working
expect(called).to.be.equal(false, 'Observer callback was triggered too early');
jQuery('#' + tempId).append('<span />');
@ -101,7 +114,7 @@
});
it('pause and resume observer', function(done) {
var context, SimpleSVG,
var context, SimpleSVG, local,
tempId = 'observer-pause',
callbackResult = false;
@ -117,21 +130,29 @@
MutationObserver: MutationObserver
};
SimpleSVG = {
isReady: true
};
local = {
config: {
observe: true,
rootElement: document.getElementById(tempId)
_root: document.getElementById(tempId)
},
_onNodesAdded: function(nodes) {
initQueue: [],
nodesAdded: function(nodes) {
callbackResult = nodes;
}
};
// Load observer
Observer(SimpleSVG, context);
Observer(SimpleSVG, local, context);
expect(typeof SimpleSVG.pauseObserving).to.be.equal('function', 'SimpleSVG.pauseObserving is missing');
expect(typeof SimpleSVG.resumeObserving).to.be.equal('function', 'SimpleSVG.resumeObserving is missing');
// Init observer
local.initQueue.forEach(function(callback) {
callback();
});
// Call observer
expect(callbackResult).to.be.equal(false, 'Observer callback was triggered too early');
jQuery('#' + tempId).append('<p />');
@ -164,6 +185,5 @@
});
});
});
});
})();

View File

@ -5,32 +5,32 @@
const fs = require('fs');
module.exports = (Helper, codeDir, testFile) => {
module.exports = (Helper, codeDir, testFile, TestHelper) => {
let code = fs.readFileSync(testFile, 'utf8'),
modules = [
'(function (SimpleSVG) {\n' +
fs.readFileSync(codeDir + '/common/storage.js', 'utf8')
.replace('module.exports = Storage;', 'SimpleSVG._Storage = Storage;') +
'\n})(self.SimpleSVG);\n',
// Core
TestHelper.fakeEvents(),
TestHelper.fakeInit(),
// Common files
TestHelper.getStorage(),
fs.readFileSync(codeDir + '/browser/storage.js', 'utf8'),
TestHelper.getSVG(),
'(function (SimpleSVG) {\n' +
fs.readFileSync(codeDir + '/common/svg.js', 'utf8')
.replace('module.exports = SVG;', 'SimpleSVG._SVG = SVG;')
.replace('require(\'./storage\')', 'SimpleSVG._Storage') +
'\n})(self.SimpleSVG);\n',
// Files needed for test
fs.readFileSync(codeDir + '/browser/defaults.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/with-cdn/defaults.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/config.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/image.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/finder.js', 'utf8'),
fs.readFileSync(codeDir + '/browser/with-cdn/loader.js', 'utf8'),
// Main file
fs.readFileSync(codeDir + '/browser/renderer.js', 'utf8'),
];
// Replace code
modules = modules.map(item => item.replace('self.SimpleSVG', 'SimpleSVG')).join('');
modules = modules.join('');
// Merge modules and test
code = code.replace('/* Modules() */', modules);

View File

@ -4,13 +4,23 @@
var expect = chai.expect,
should = chai.should();
function load(SimpleSVG) {
function load(SimpleSVG, local, global) {
/* Modules() */
}
describe('Testing renderer', function() {
it('rendering svg images', function(done) {
var SimpleSVG = {},
var SimpleSVG = {
isReady: false
},
local = {
config: {}
},
global = {
SimpleSVGConfig: {
_readyEvent: 'RendererTestReadyEvent1'
}
},
containerID = 'renderer-svg',
containerRoot,
pending = 0;
@ -25,32 +35,30 @@
containerRoot = document.getElementById(containerID);
// Setup fake SimpleSVG instance
SimpleSVG = {
_onIconsAdded: renderImages
};
// Load libraries
load(SimpleSVG);
SimpleSVG.config.defaultCDN = SimpleSVG.config.defaultCDN.replace('{callback}', 'window.SSVGRenderTest');
local.iconsAdded = renderImages;
load(SimpleSVG, local, global);
local.config.defaultCDN = local.config.defaultCDN.replace('{callback}', 'window.SSVGRenderTest');
window.SSVGRenderTest = SimpleSVG._loaderCallback;
SimpleSVG.ready(() => {
// Load images, start tests when images are available
SimpleSVG._findNewImages(containerRoot).forEach(function(image) {
if (!SimpleSVG._loadImage(image)) {
local.findNewImages(containerRoot).forEach(function(image) {
if (!local.loadImage(image)) {
pending ++;
} else {
SimpleSVG._renderSVG(image);
local.renderSVG(image);
}
});
if (!pending) {
test();
}
});
}
// Callback to load pending images
function renderImages() {
SimpleSVG._findNewImages(containerRoot).forEach(function(image) {
SimpleSVG._renderSVG(image);
local.findNewImages(containerRoot).forEach(function(image) {
local.renderSVG(image);
});
test();
}
@ -77,7 +85,17 @@
});
it('rendering placeholder', function(done) {
var SimpleSVG = {},
var SimpleSVG = {
isReady: false
},
local = {
config: {}
},
global = {
SimpleSVGConfig: {
_readyEvent: 'RendererTestReadyEvent1'
}
},
containerID = 'renderer-placeholder',
containerRoot,
pending = 0;
@ -92,18 +110,14 @@
containerRoot = document.getElementById(containerID);
// Setup fake SimpleSVG instance
SimpleSVG = {
_onIconsAdded: renderImages
};
// Load libraries
load(SimpleSVG);
SimpleSVG.config.defaultCDN = SimpleSVG.config.defaultCDN.replace('{callback}', 'window.SSVGRenderTest2');
local.iconsAdded = renderImages;
load(SimpleSVG, local, global);
local.config.defaultCDN = local.config.defaultCDN.replace('{callback}', 'window.SSVGRenderTest2');
window.SSVGRenderTest2 = SimpleSVG._loaderCallback;
// Load images, start tests when images are available
SimpleSVG._findNewImages(containerRoot).forEach(function(image) {
if (!SimpleSVG._loadImage(image)) {
local.findNewImages(containerRoot).forEach(function(image) {
if (!local.loadImage(image)) {
pending ++;
}
});
@ -114,8 +128,8 @@
// Render images
function renderImages() {
SimpleSVG._findNewImages(containerRoot).forEach(function(image) {
SimpleSVG._renderSVG(image, true);
local.findNewImages(containerRoot).forEach(function(image) {
local.renderSVG(image, true);
});
test();
}
@ -136,8 +150,8 @@
expect(image2.getAttribute('style')).to.be.equal(null, 'Second placeholder should not have style attribute');
// Change images to SVG
SimpleSVG._findHiddenImages(containerRoot).forEach(function(image) {
SimpleSVG._renderSVG(image);
local.findHiddenImages(containerRoot).forEach(function(image) {
local.renderSVG(image);
});
image1 = containerRoot.childNodes[0];

View File

@ -83,7 +83,7 @@
expect(storage.get('foo-baz').width).to.be.equal(16);
});
it('library', function() {
it('collection', function() {
var storage = new Storage();
storage.addIcon('single', {
@ -91,7 +91,7 @@
width: 48,
height: 36
});
storage.addLibrary({
storage.addCollection({
icons: {
icon1: {
body: '<path d="" />'
@ -127,7 +127,7 @@
expect(storage.get('icon3').height).to.be.equal(20);
// Add items without width
storage.addLibrary({
storage.addCollection({
icons: {
icon11: {
// missing width - invalid icon
@ -154,7 +154,7 @@
expect(storage.list()).to.be.eql(['single', 'icon1', 'icon2', 'icon3', 'icon12']);
// Add aliases
storage.addLibrary({
storage.addCollection({
icons: {
icon21: {
body: '<path d="" />',