icons
This commit is contained in:
parent
b1e5c22101
commit
db02888776
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<span class="icon" :class="sizeClass" @click="$emit('click', $event)">
|
<span class="icon" :class="sizeClass" @click="$emit('click', $event)" ref="container">
|
||||||
<img ref="img" :class="['iconic', 'iconic-fluid', size]" v-bind="extraIconAttributes" :style="{padding: svgPadding}" />
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -20,15 +20,101 @@
|
|||||||
import StarEmpty from "../iconic/svg/smart/star-empty";
|
import StarEmpty from "../iconic/svg/smart/star-empty";
|
||||||
import X from "../iconic/svg/smart/x";
|
import X from "../iconic/svg/smart/x";
|
||||||
|
|
||||||
const iconicInstance = IconicJs({
|
const SVG_CACHE = {};
|
||||||
autoInjectSelector: null
|
let REMAP_COUNT = 0;
|
||||||
});
|
|
||||||
|
|
||||||
class IconData {
|
class IconData {
|
||||||
constructor(url, dataAttributes) {
|
constructor(svgData, dataAttributes) {
|
||||||
this.url = url;
|
this.svgData = svgData;
|
||||||
this.dataAttributes = dataAttributes || {};
|
this.dataAttributes = dataAttributes || {};
|
||||||
this.dataAttributes['src'] = url;
|
this.svgTemplate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSvg() {
|
||||||
|
if (this.svgTemplate === null) {
|
||||||
|
const iconicName = this.svgData.attributes.class;
|
||||||
|
|
||||||
|
this.svgTemplate = SVG_CACHE[iconicName] || null;
|
||||||
|
|
||||||
|
if (this.svgTemplate === null) {
|
||||||
|
this.svgTemplate = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
|
SVG_CACHE[iconicName] = this.svgTemplate;
|
||||||
|
|
||||||
|
for (let attr in this.svgData.attributes) {
|
||||||
|
this.svgTemplate.setAttribute(attr, this.svgData.attributes[attr]);
|
||||||
|
}
|
||||||
|
this.svgTemplate.innerHTML = this.svgData.content;
|
||||||
|
|
||||||
|
|
||||||
|
// Find then prune the scripts
|
||||||
|
const scripts = [...this.svgTemplate.querySelectorAll('script')];
|
||||||
|
|
||||||
|
scripts.filter(s => {
|
||||||
|
let scriptType = s.getAttribute("type");
|
||||||
|
return !scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript'
|
||||||
|
}).forEach(s => {
|
||||||
|
new Function(s.innerText || s.textContent)(window);
|
||||||
|
this.svgTemplate.removeChild(s);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clone = this.svgTemplate.cloneNode(true);
|
||||||
|
this.remapIds(clone);
|
||||||
|
this.attachIconicApi(clone);
|
||||||
|
for (let attr in this.dataAttributes) {
|
||||||
|
clone.setAttribute(`data-${attr}`, this.dataAttributes[attr]);
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
remapIds(svg) {
|
||||||
|
const iriElementsAndProperties = {
|
||||||
|
'clipPath': ['clip-path'],
|
||||||
|
'color-profile': ['color-profile'],
|
||||||
|
'cursor': ['cursor'],
|
||||||
|
'filter': ['filter'],
|
||||||
|
'linearGradient': ['fill', 'stroke'],
|
||||||
|
'marker': ['marker', 'marker-start', 'marker-mid', 'marker-end'],
|
||||||
|
'mask': ['mask'],
|
||||||
|
'pattern': ['fill', 'stroke'],
|
||||||
|
'radialGradient': ['fill', 'stroke']
|
||||||
|
};
|
||||||
|
|
||||||
|
REMAP_COUNT += 1;
|
||||||
|
|
||||||
|
let element, elementDefs, properties, currentId, newId;
|
||||||
|
Object.keys(iriElementsAndProperties).forEach(function (key) {
|
||||||
|
element = key;
|
||||||
|
properties = iriElementsAndProperties[key];
|
||||||
|
|
||||||
|
elementDefs = svg.querySelectorAll('defs ' + element + '[id]');
|
||||||
|
for (var i = 0, elementsLen = elementDefs.length; i < elementsLen; i++) {
|
||||||
|
currentId = elementDefs[i].id;
|
||||||
|
newId = currentId + '-' + REMAP_COUNT;
|
||||||
|
|
||||||
|
// All of the properties that can reference this element type
|
||||||
|
var referencingElements;
|
||||||
|
properties.forEach(function (property) {
|
||||||
|
// :NOTE: using a substring match attr selector here to deal with IE "adding extra quotes in url() attrs"
|
||||||
|
referencingElements = svg.querySelectorAll('[' + property + '*="' + currentId + '"]');
|
||||||
|
for (var j = 0, referencingElementLen = referencingElements.length; j < referencingElementLen; j++) {
|
||||||
|
referencingElements[j].setAttribute(property, 'url(#' + newId + ')');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
elementDefs[i].id = newId;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
attachIconicApi(svg) {
|
||||||
|
const key = svg.getAttribute("data-icon");
|
||||||
|
const apis = window.iconicSmartIconApis;
|
||||||
|
if (key && apis[key]) {
|
||||||
|
const iconApi = apis[key](svg);
|
||||||
|
for (let func in iconApi) svg[func] = iconApi[func]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +125,43 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IconicQueue {
|
||||||
|
constructor(iconicInstance) {
|
||||||
|
this.iconic = iconicInstance;
|
||||||
|
this.updateQueue = [];
|
||||||
|
this.isTimerRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
processQueues() {
|
||||||
|
if (this.updateQueue.length > 0) {
|
||||||
|
console.log(`updating ${this.updateQueue.length}`);
|
||||||
|
this.iconic.update(this.updateQueue);
|
||||||
|
this.updateQueue.forEach(s => (s.style.visibility = null));
|
||||||
|
this.updateQueue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isTimerRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureTimer() {
|
||||||
|
if (!this.isTimerRunning) {
|
||||||
|
this.isTimerRunning = true;
|
||||||
|
setTimeout(() => this.processQueues());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSvg(svgElem) {
|
||||||
|
this.updateQueue.push(svgElem);
|
||||||
|
this.ensureTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconicInstance = IconicJs({
|
||||||
|
autoInjectSelector: "#notreal-noinjection"
|
||||||
|
});
|
||||||
|
|
||||||
|
const iconicQueue = new IconicQueue(iconicInstance);
|
||||||
|
|
||||||
const iconMap = {
|
const iconMap = {
|
||||||
'caret-bottom': new IconData(Caret, {direction: 'bottom'}),
|
'caret-bottom': new IconData(Caret, {direction: 'bottom'}),
|
||||||
'caret-top': new IconData(Caret, {direction: 'top'}),
|
'caret-top': new IconData(Caret, {direction: 'top'}),
|
||||||
@ -97,15 +220,6 @@
|
|||||||
return sizeMap[this.size];
|
return sizeMap[this.size];
|
||||||
},
|
},
|
||||||
|
|
||||||
extraIconAttributes() {
|
|
||||||
const attrs = {};
|
|
||||||
|
|
||||||
for (let attr in this.iconData.dataAttributes) {
|
|
||||||
attrs[`data-${attr}`] = this.iconData.dataAttributes[attr];
|
|
||||||
}
|
|
||||||
return attrs;
|
|
||||||
},
|
|
||||||
|
|
||||||
sizeClass() {
|
sizeClass() {
|
||||||
return this.sizeData.bulmaIconClass;
|
return this.sizeData.bulmaIconClass;
|
||||||
},
|
},
|
||||||
@ -115,22 +229,42 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
methods: {
|
||||||
const self = this;
|
insertSvg() {
|
||||||
|
const parent = this.$refs.container;
|
||||||
|
|
||||||
|
while (parent.firstChild) {
|
||||||
|
parent.removeChild(parent.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
const svg = this.iconData.getSvg();
|
||||||
|
this.injectedSvg = svg;
|
||||||
|
|
||||||
|
svg.style.padding = this.svgPadding;
|
||||||
|
svg.style.visibility = "hidden";
|
||||||
|
svg.classList.add("iconic-fluid");
|
||||||
|
parent.appendChild(svg);
|
||||||
|
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
iconicInstance.inject(this.$refs.img, {
|
//svg.style.visibility = "visible";
|
||||||
each: function(svg) { self.injectedSvg = svg; }
|
//iconicInstance.update(svg);
|
||||||
});
|
iconicQueue.updateSvg(svg);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
updated() {
|
mounted() {
|
||||||
if (this.injectedSvg) {
|
let self = this;
|
||||||
for(let attr in this.extraIconAttributes) {
|
this.$watch(
|
||||||
this.injectedSvg.setAttribute(attr, this.extraIconAttributes[attr]);
|
function() { return this.icon + this.size + this.padding },
|
||||||
}
|
function() {
|
||||||
iconicInstance.update(this.injectedSvg);
|
this.insertSvg();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@ const vue = require('./loaders/vue');
|
|||||||
const svg = require('./loaders/svg');
|
const svg = require('./loaders/svg');
|
||||||
|
|
||||||
environment.loaders.append('vue', vue);
|
environment.loaders.append('vue', vue);
|
||||||
//environment.loaders.prepend('svg', svg);
|
environment.loaders.prepend('svg', svg);
|
||||||
|
|
||||||
//const fileLoader = environment.loaders.get('file');
|
const fileLoader = environment.loaders.get('file');
|
||||||
//fileLoader.exclude = /\.(svg)$/i;
|
fileLoader.exclude = /\.(svg)$/i;
|
||||||
|
|
||||||
module.exports = environment;
|
module.exports = environment;
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
|
const path = require("path");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
test: /\.svg$/,
|
test: /\.svg$/,
|
||||||
use: [{
|
use: [{
|
||||||
loader: 'url-loader',
|
loader: path.join(__dirname, 'svg_loader.js')
|
||||||
options: {
|
|
||||||
limit: 10000
|
|
||||||
}
|
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// module.exports = {
|
||||||
|
// test: /\.svg$/,
|
||||||
|
// use: [{
|
||||||
|
// loader: 'url-loader',
|
||||||
|
// options: {
|
||||||
|
// limit: 10000
|
||||||
|
// }
|
||||||
|
// }]
|
||||||
|
// };
|
||||||
|
27
config/webpack/loaders/svg_loader.js
Normal file
27
config/webpack/loaders/svg_loader.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
module.exports = function(content) {
|
||||||
|
this.cacheable && this.cacheable();
|
||||||
|
|
||||||
|
var match = content.match(/<svg([^>]+)+>([\s\S]+)<\/svg>/i);
|
||||||
|
var attrs = {};
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
attrs = match[1];
|
||||||
|
if (attrs) {
|
||||||
|
attrs = attrs.match(/([\w-:]+)(=)?("[^<>"]*"|'[^<>']*'|[\w-:]+)/g)
|
||||||
|
.reduce(function(obj, attr){
|
||||||
|
var split = attr.split('=');
|
||||||
|
var name = split[0];
|
||||||
|
var value = true;
|
||||||
|
if (split && split[1]) {
|
||||||
|
value = split[1].replace(/['"]/g, '');
|
||||||
|
}
|
||||||
|
obj[name] = value;
|
||||||
|
return obj;
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
content = match[2] || '';
|
||||||
|
};
|
||||||
|
|
||||||
|
return "module.exports = " + JSON.stringify({attributes: attrs, content: content});
|
||||||
|
};
|
@ -3,21 +3,50 @@ namespace :dev do
|
|||||||
desc 'Run both rails server and webpack dev server'
|
desc 'Run both rails server and webpack dev server'
|
||||||
task :run do
|
task :run do
|
||||||
|
|
||||||
pids = []
|
rails_pid = fork do
|
||||||
|
|
||||||
pids << fork do
|
|
||||||
exec 'rails s'
|
exec 'rails s'
|
||||||
end
|
end
|
||||||
|
|
||||||
pids << fork do
|
webpack_pid = fork do
|
||||||
exec 'bin/webpack-dev-server'
|
exec 'bin/webpack-dev-server'
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
running = true
|
||||||
Process.wait
|
shutdown = false
|
||||||
rescue SignalException
|
shutdown_start = nil
|
||||||
puts 'shutting down...'
|
|
||||||
pids.each { |pid| Process.kill("SIGINT", pid) }
|
Signal.trap('SIGINT') do
|
||||||
|
shutdown = true
|
||||||
|
end
|
||||||
|
|
||||||
|
while running
|
||||||
|
rails_check ||= Process.waitpid(rails_pid, Process::WNOHANG)
|
||||||
|
webpack_check ||= Process.waitpid(webpack_pid, Process::WNOHANG)
|
||||||
|
running = rails_check.nil? || webpack_check.nil?
|
||||||
|
|
||||||
|
if shutdown
|
||||||
|
if shutdown_start.nil?
|
||||||
|
puts "Shutting down..."
|
||||||
|
shutdown_start = Time.now
|
||||||
|
#Process.kill("SIGINT", rails_pid) rescue Errno::ESRCH
|
||||||
|
#Process.kill("SIGINT", webpack_pid) rescue Errno::ESRCH
|
||||||
|
end
|
||||||
|
|
||||||
|
if (Time.now - shutdown_start) > 5
|
||||||
|
if rails_check.nil?
|
||||||
|
puts "Force killing rails..."
|
||||||
|
Process.kill("KILL", rails_pid)
|
||||||
|
end
|
||||||
|
|
||||||
|
if webpack_check.nil?
|
||||||
|
puts "Force killing webpack..."
|
||||||
|
Process.kill("KILL", webpack_pid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep 0.25
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user