#2 Adding Font Awesome Icons To The Page With Minimal Javascript
Saturday, August 29, 2020
In this video we will create the necessary javascript for us to be able to add a tag to our html, with the appropriate css classes, and have that tag replaced with the corresponding Font Awesome icon.
Parts
- Part 2: Font Awesome Javascript
- Part 1: Font Awesome Mixins
Code Snippets
main.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
meta(http-equiv="X-UA-Compatible", content="ie=edge")
title Font Awesome
link(rel="stylesheet", href="main.css")
body
div#app
script(src="main.js")
icons.js
...
function toCamelCase(str) {
return str.replace(/([-_][a-z])/gi, ($1) => {
return $1.toUpperCase().replace("-", "").replace("_", "");
});
}
const keyObjects = Object.keys(sprite.attributes).map((x) => ({
class: sprite.attributes[x].class,
id: x,
enum: toCamelCase(x),
viewBox: sprite.attributes[x].viewBox,
}));
console.log(keyObjects);
icons.js
...
const keyObjects = keys.map((x) => ({
...
width: (parseInt(sprite.attributes[x].viewBox.split(" ")[2], 10) / 512) * 16,
}));
...
icons.js
...
const os = require("os");
...
const enumName = "Icons";
const outputEnum = `export enum ${enumName} {
${keyObjects
.map((x, i) => {
const end = i < keyObjects.length - 1 ? os.EOL : "";
return ` ${x.enum},${end}`;
})
.reduce((prev, cur) => `${prev}${cur}`, "")}
}`;
const output = `// tslint:disable
/* eslint-disable */
${outputEnum}
`;
fs.writeFile(path.join(__dirname, "fa-icons.ts"), output, (err) => {
if (err) {
throw err;
}
});
icons.js
...
function keyObjectToString(fn) {
return keyObjects
.map((x, i) => {
const end = i < keyObjects.length - 1 ? os.EOL : "";
return ` ${fn(x)},${end}`;
})
.reduce((prev, cur) => `${prev}${cur}`, "");
}
...
const outputEnum = `export enum ${enumName} {
${keyObjectToString((x) => `${x.enum}`)}
}`;
...
icons.js
...
const outputIconMap = `export const faIconMap = new Map<${enumName}, { class: string; id: string; viewBox: string; width: number; }>([
${keyObjectToString(
(x) => `[${enumName}.${x.enum}, { class: "${x.class}", id: "${x.id}", viewBox: "${x.viewBox}", width: ${x.width} }]`
)}
]);`;
const output = `...
${outputIconMap}
`;
...
Advertisement
main.ts
import {faIconMap, Icons} from "./fa-icons";
function faSvgFromIcon(icon: Icons, scale: number = 1) {
const aria = 'aria-hidden="true"';
const focus = 'focusable="false"';
const role = 'role="img"';
const xmlns = 'xlmns="http://www.w3.org/2000/svg"';
const ic = faIconMap.get(icon)!;
const css = `class="${ic.class} fa-${scale}x"`;
const viewBox = `viewBox="${ic.viewBox}"`;
const href = `href="/fa-icons.svg#${ic.id}"`;
return `<svg ${css} ${viewBox} ${aria} ${focus} ${role} ${xmlns}><use ${href}></use></svg>`;
}
const app = document.getElementById("app")!;
const div = document.createElement("div");
div.innerHTML = faSvgFromIcon(Icons.fasFaCamera, 3);
app.appendChild(div);
icons.js
...
const outputSvgFromIconFn = `export function faSvgFromIcon(icon: ${enumName}, scale: number = 1) {
const aria = 'aria-hidden="true"';
const focus = 'focusable="false"';
const role = 'role="img"';
const xmlns = 'xlmns="http://www.w3.org/2000/svg"';
const ic = faIconMap.get(icon)!;
const css = \`class="\${ic.class} fa-\${scale}x"\`;
const viewBox = \`viewBox="\${ic.viewBox}"\`;
const href = \`href="/fa-icons.svg#\${ic.id}"\`;
return \`<svg \${css} \${viewBox} \${aria} \${focus} \${role} \${xmlns}><use \${href}></use></svg>\`;
}`;
const output = `...
${outputSvgFromIconFn}
`;
main.ts
import {faSvgFromIcon, Icons} from "./fa-icons";
const app = document.getElementById("app")!;
const div = document.createElement("div");
div.innerHTML = faSvgFromIcon(Icons.fasFaCamera, 3);
app.appendChild(div);
main.pug
...
html(lang="en")
...
body
i.fa.fas-fa-camera.fa-3x
script(src="main.js")
icons.js
...
const outputIdMap = `export const faIdMap = new Map<string, ${enumName}>([
${keyObjectToString((x) => `["${x.id}", ${enumName}.${x.enum}]`)}
]);`;
const output = `...
${outputIdMap()}
...`;
...
main.ts
import {faIdMap, faSvgFromIcon} from "./fa-icons";
function faSvgReplace(document: Document, faClass: string = "fa") {
const collection = document.getElementsByClassName(faClass);
for (const element of collection) {
for (const className of element.classList) {
const icon = faIdMap.get(className);
if (typeof icon !== "undefined") {
const container = document.createElement("span");
element.classList.forEach((x) => {
if (x === faClass || x === className) {
return;
}
container.classList.add(x);
});
container.innerHTML = faSvgFromIcon(icon);
element.parentElement!.replaceChild(container, element);
break;
}
}
}
}
faSvgReplace(document);
icons.js
...
const outputSvgReplaceFn = `export function faSvgReplace(document: Document, faClass: string = "fa") {
const collection = document.getElementsByClassName("fa");
for (const element of collection) {
for (const className of element.classList) {
const icon = faIdMap.get(className);
if (typeof icon !== "undefined") {
const div = document.createElement("div");
element.classList.forEach((x) => {
if (x === faClass || x === className) {
return;
}
div.classList.add(x);
});
div.innerHTML = faSvgFromIcon(icon);
element.parentElement!.replaceChild(div, element);
break;
}
}
}
}`;
const output = `...
${outputSvgReplaceFn}
`;
...
main.ts
import {faSvgReplace} from "./fa-icons";
faSvgReplace(document);
Exciton Interactive LLC