
Updated:
May 2025
Instructions
Components and properties marked with ⚡ use custom code for enhanced functionality. Follow the steps below, to activate the full capabilities of FlowGuide.
1. Copy script and paste into before </body> tag.
This unlocks all FlowGuide functionality, including auto-generated menu and pagination.
<script>
// ========================================================
// 01 — Auto-Generate Menu
// ========================================================
$(document).ready(function () {
// ============================
// Primary Navigation (fg-nav)
// ============================
if ($("[fg-nav-generate='true']").length) {
// Process each item with fg-show-menu="true"
$("[fg-show-menu='true']").each(function (index) {
var title = $(this).attr("fg-nav-title");
// Set text for the corresponding text element
$("[fg-nav='text" + (index + 1) + "']").text(title);
// Set href for the corresponding link element
$("[fg-nav='link" + (index + 1) + "']").attr("href", "#" + title);
});
// Remove all link elements that didn't get set (i.e., with index greater than the count of fg-show-menu="true")
$("[fg-nav^='link']").each(function () {
var navAttr = $(this).attr("fg-nav");
var num = parseInt(navAttr.replace("link", ""), 10);
var count = $("[fg-show-menu='true']").length;
if (num > count) {
$(this).remove(); // Remove the element from the DOM
}
});
}
// ============================
// Sub Navigation (fg-subnav)
// ============================
if ($("[fg-subnav-generate='true']").length) {
// Process each item with fg-show-menu="true"
$("[fg-show-menu='true']").each(function (index) {
var title = $(this).attr("fg-nav-title");
// Set text for the corresponding subnav text element
$("[fg-subnav='text" + (index + 1) + "']").text(title);
// Set href for the corresponding subnav link element
$("[fg-subnav='link" + (index + 1) + "']").attr("href", "#" + title);
});
// Remove all subnav link elements that didn't get set
$("[fg-subnav^='link']").each(function () {
var navAttr = $(this).attr("fg-subnav");
var num = parseInt(navAttr.replace("link", ""), 10);
var count = $("[fg-show-menu='true']").length;
if (num > count) {
$(this).remove(); // Remove the element from the DOM
}
});
}
});
// ========================================================
// 02 – Keyboard Shortcuts
// ========================================================
$(document).ready(function () {
// Listen for keydown events (works better for non-printable and number keys)
$(document).keydown(function (e) {
// Get the pressed key's value
var key = String.fromCharCode(e.which).toLowerCase(); // Convert to lowercase
// Check for number keys (1-9)
if (e.which >= 49 && e.which <= 57) {
key = String.fromCharCode(e.which); // Treat as the number itself
}
// Loop through all shortcut elements (for the number keys or letter shortcuts)
$("[fg-nav^='shortcut']").each(function () {
var shortcutText = $(this).text().toLowerCase(); // Get the text of the current shortcut
// If the shortcut text matches the pressed key, trigger the corresponding link
if (shortcutText === key) {
var link = $("[fg-nav='link" + $(this).attr("fg-nav").replace("shortcut", "") + "']");
// Trigger the click event on the matching link
if (link.length) {
link[0].click(); // Simulate a click on the matching link
}
}
});
// Special case for 'shortcut-cta' (CTA trigger on 'c')
if (key === "c") { // If the key pressed is 'C', trigger the CTA link
var linkCta = $("[fg-nav='link-cta']"); // Find the matching CTA link
if (linkCta.length) {
linkCta[0].click(); // Simulate a click on the CTA link
}
}
});
});
// ========================================================
// 03 – Close tablet/mobile menu on anchor link click
// ========================================================
$(document).ready(function () {
const $links = $('[fg-nav^="link"], [fg-subnav^="link"]');
const $button = $('[fg-nav="button"]');
$links.on('click', function () {
if ($(window).width() <= 991) {
$button.trigger('click');
}
});
});
// ========================================================
// 04 — Copy HEX code
// ========================================================
$(document).on("click", "[fg-element='color']", function() {
let hexValue = $(this).find("[fg-element='hex']").first().text().trim();
if (hexValue) navigator.clipboard.writeText(hexValue);
});
// ========================================================
// 05 — Typewriter (Font Section)
// ========================================================
$(document).ready(function () {
function isLargeDevice() {
return window.matchMedia("(min-width: 991px)").matches;
}
function typeWriter($element, text, callback) {
if (!isLargeDevice()) {
$element.text(text);
if (callback) callback();
return;
}
// Find direct parent with fg-element="font-preview-name-wrapper"
const $wrapper = $element.closest('[fg-element="font-preview-name-wrapper"]');
const $target = $wrapper.length ? $element : $element;
const words = text.split(" ");
const html = words
.map((word) => {
return `<span style="white-space: nowrap; display: inline-block;">
${word
.split("")
.map(
(char) =>
`<span style="opacity: 0; display: inline-block;">${char}</span>`
)
.join("")}
</span><span style="opacity: 0; display: inline-block;"> </span>`;
})
.join("");
// Replace content at the correct level
$target.html(html);
const $chars = $target.find('span span');
let i = 0;
function revealNext() {
if (i < $chars.length) {
$chars.eq(i).css({
opacity: "1",
transition: "opacity 50ms",
});
i++;
setTimeout(revealNext, 50);
} else if (callback) {
callback();
}
}
revealNext();
}
// Cache the original content and structure
const $components = $('[fg-element="font-preview-component"]');
$components.each(function () {
const $this = $(this);
const $text = $this.find('[fg-element="font-preview-text"]');
const $name = $this.find('[fg-element="font-preview-name"]');
const $nameWrapper = $this.find('[fg-element="font-preview-name-wrapper"]');
// Store original HTML structure
$text.data("original-html", $text.html());
$name.data("original-html", $name.html());
$nameWrapper.data("original-html", $nameWrapper.html());
});
if (isLargeDevice()) {
$components.on("mouseenter", function () {
const $nameWrapper = $(this).find('[fg-element="font-preview-name-wrapper"]');
const $text = $(this).find('[fg-element="font-preview-text"]');
$nameWrapper.hide();
$text.show();
typeWriter($text, $text.data("original-html"));
});
$components.on("mouseleave", function () {
const $this = $(this);
const $sampleWrapper = $this.find('[fg-element="font-preview-sample-wrapper"]');
const $nameWrapper = $this.find('[fg-element="font-preview-name-wrapper"]');
const $name = $this.find('[fg-element="font-preview-name"]');
const $text = $this.find('[fg-element="font-preview-text"]');
// Reset text to original state
$text.html($text.data("original-html"));
// Reset name wrapper to original state before starting new animation
$nameWrapper.html($nameWrapper.data("original-html"));
$sampleWrapper.show();
$nameWrapper.show();
// Find the name element again after resetting HTML
const $newName = $nameWrapper.find('[fg-element="font-preview-name"]');
typeWriter($newName, $newName.text());
});
}
let resizeTimer;
$(window).on("resize", function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
if (!isLargeDevice()) {
$components.off("mouseenter mouseleave");
// Reset all elements to their original structure
$components.each(function () {
const $this = $(this);
const $text = $this.find('[fg-element="font-preview-text"]');
const $nameWrapper = $this.find('[fg-element="font-preview-name-wrapper"]');
$text.html($text.data("original-html"));
$nameWrapper.html($nameWrapper.data("original-html"));
});
$('[fg-element="font-preview-name-wrapper"]').show();
}
}, 250);
});
});
// ========================================================
// 06 — Pagination
// ========================================================
$(document).ready(function () {
if ($("[fg-pagination-generate='true']").length === 0) {
return; // Exit if the attribute is not found
}
var links = $("[fg-nav^='link']").filter(function () {
return $(this).attr("href") && $(this).attr("href") !== "#";
});
var currentLink = links.filter(".w--current");
var index = links.index(currentLink);
var totalLinks = links.length;
var prevLink = index > 0 ? $(links[index - 1]).attr("href") : null;
var prevText = index > 0 ? $(links[index - 1]).find("[fg-nav^='text']").text() : null;
var prevShortcut = index > 0 ? $(links[index - 1]).find("[fg-nav^='shortcut']").text() : null;
var nextLink = index < totalLinks - 1 ? $(links[index + 1]).attr("href") : null;
var nextText = index < totalLinks - 1 ? $(links[index + 1]).find("[fg-nav^='text']").text() : null;
var nextShortcut = index < totalLinks - 1 ? $(links[index + 1]).find("[fg-nav^='shortcut']").text() : null;
// Set previous page attributes
$('[fg-pagination="prev-link"]').attr("href", prevLink);
$('[fg-pagination="prev-shortcut"]').text(prevShortcut);
$('[fg-pagination="prev-text"]').text(prevText);
// Set next page attributes
$('[fg-pagination="next-link"]').attr("href", nextLink);
$('[fg-pagination="next-shortcut"]').text(nextShortcut);
$('[fg-pagination="next-text"]').text(nextText);
// Hide elements if no prev or next page exists
if (!prevLink) {
$('[fg-pagination="prev-link"], [fg-pagination="prev-shortcut"], [fg-pagination="prev-text"]').hide();
}
if (!nextLink) {
$('[fg-pagination="next-link"], [fg-pagination="next-shortcut"], [fg-pagination="next-text"]').hide();
}
});
</script>
The custom code activates the following features:

Add caption here
Auto-generate menu

Add caption here
Keyboard shortcuts for menu

Add caption here
Auto-generate pagination

Add caption here
Typewriter animation

Add caption here
Copy HEX color code

Add caption here
Mobile menu closes by tapping an anchor link