Advertisement

#2 Adding Font Awesome Icons To The Page With Minimal Javascript

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

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")
root ⟩ main.pug

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);
root ⟩ icons.js

icons.js

...
const keyObjects = keys.map((x) => ({
    ...
    width: (parseInt(sprite.attributes[x].viewBox.split(" ")[2], 10) / 512) * 16,
}));
...
root ⟩ icons.js

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;
    }
});
root ⟩ icons.js

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}`)}
}`;
...
root ⟩ icons.js

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}
`;
...
root ⟩ icons.js

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);
root ⟩ main.ts

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}
`;
root ⟩ icons.js

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);
root ⟩ main.ts

main.pug

...
html(lang="en")
    ...
    body
        i.fa.fas-fa-camera.fa-3x
        script(src="main.js")
root ⟩ main.pug

icons.js

...
const outputIdMap = `export const faIdMap = new Map<string, ${enumName}>([
${keyObjectToString((x) => `["${x.id}", ${enumName}.${x.enum}]`)}
]);`;

const output = `...
${outputIdMap()}
...`;
...
root ⟩ icons.js

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);
root ⟩ main.ts

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}
`;
...
root ⟩ icons.js

main.ts

import {faSvgReplace} from "./fa-icons";

faSvgReplace(document);
root ⟩ main.ts

Exciton Interactive LLC
Advertisement