@terrahq/helpers
v0.0.67
Published
These functions play a crucial role in project development, establishing identity, streamlining processes, and expediting progress. Whether it's preloading assets, integrating reCAPTCHA, or incorporating HubSpot interactions, these simple functions facili
Downloads
101
Keywords
Readme
Helpers by Terra
These functions play a crucial role in project development, establishing identity, streamlining processes, and expediting progress. Whether it's preloading assets, integrating reCAPTCHA, or incorporating HubSpot interactions, these simple functions facilitate rapid development, contributing to the sustainable growth of our projects.
npm i @terrahq/helpers
Preload
Images
Under the hood it uses ImagesLoaded, This is an async await operation
Preloads images asynchronously and resolves the Promise when all images are loaded. Optionally, a callback function can be provided, which will be called after the images have preloaded. A debug option can be enabled to log information about the images that match the selector. The selector can be a class or selector: 'img' for all images. If no selector is provided, preloadImages will look for img tags by default.
import { preloadImages } from "@terrahq/helpers/preloadImages";
await preloadImages({
selector: "img",
callback: () => {
console.log("All images loaded");
},
debug: false,
});
import { preloadImages } from "@terrahq/helpers/preloadImages";
await preloadImages({
selector: document.querySelectorAll(".js--image"),
callback: () => {
console.log("All images loaded");
},
debug: true,
});
Videos
Under the hood it uses canplaythrough, This is an async await operation
Preloads video elements asynchronously and resolves the Promise when either all videos can play through, or the maximum time limit is reached. Optionally, a callback function can be provided, which will be called after the videos have preloaded or the time limit is reached. A debug option can be enabled to log information about the video elements that match the selector.
import { preloadVideos } from "@terrahq/helpers/preloadVideos";
await preloadVideos({
selector: document.querySelectorAll(".js--video"),
maxTime: 1300,
callback: (payload) => {
console.log("All videos are loaded");
},
debug: true,
});
Lottie
Under the hood it uses lottie-web , This is an async await operation
Preloads Lottie animations asynchronously and resolves the Promise when all animations are loaded. Optionally, a callback function can be provided, which will be called after all Lottie animations are loaded. A debug option can be enabled to log information about the Lottie elements being processed.
import { preloadLotties } from "@terrahq/helpers/preloadLotties";
await preloadLotties({
debug: true,
selector: document.querySelectorAll(".js--lottie-element"),
callback: (payload) => {
console.log("All lotties loaded", payload);
},
});
Expected HTML structure for each Lottie element
<div class="js--lottie-element" data-path="filename.json" data-animType="svg" data-loop="true" data-autoplay="false" data-name="myLottie"></div>
Controlling Lottie animations via JavaScript
window.WL["myLottie"].play(); // Play the Lottie animation
window.WL["myLottie"].pause(); // Pause the Lottie animation
window.WL["myLottie"].stop(); // Stop the Lottie animation
Marketing
Hubspot
Helper to submit directly to Hubspot. Using axios. Submits form data to the HubSpot API using the specified portal ID and form ID. Optionally, a debug option can be enabled to log detailed information during the submission process, and a callback function can be provided to handle the response after the submission is completed.
- This endpoint has a rate limit of 50 requests per 10 seconds.
- When using this endpoint to integrate custom forms with HubSpot, keep in mind that the available endpoints do not log any API calls. Users will need to store their own logs.
- In addition to accepting server-side HTTP requests, this endpoint will accept cross-origin AJAX (CORS) requests, allowing you to submit form data directly to HubSpot client-side using JavaScript.
- This endpoint does not support reCAPTCHA. If reCAPTCHA has been enabled on the form, submissions will not be accepted.
import { submitToHubspot } from "@terrahq/helpers/hubspot";
const payload = {
portalId: "YOUR_PORTAL_ID",
formId: "YOUR_FORM_ID",
formInputs: {
firstName: "John",
lastName: "Doe",
email: "[email protected]",
},
callback: (result) => {
console.log("Callback result:", result);
if (result.success) {
// Handle successful submission
} else {
// Handle submission error
}
},
debug: true, // Enable debug mode
};
try {
const submissionResult = await submitToHubspot(payload);
console.log(submissionResult.message);
} catch (error) {
// Handle unexpected errors during submission
console.error("Submission error:", error.message);
}
Miscellaneous
Breakpoints
Helper function that returns all breakpoints for Terra
import { breakpoints } from "@terrahq/helpers/breakpoints";
let bk = breakpoints.reduce((target, inner) => Object.assign(target, inner), {});
console.log(bk.mobile);
TerraDebugger
Helper function to develop better testing for Developers + UX/ui, it returns breakpoint name and clickup space.
import { terraDebugger } from "@terrahq/helpers/terraDebugger";
function getQueryParam(param) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.has(param); // returns true if the parameter is present, otherwise false
}
var terraDebug = getQueryParam("debug");
if (terraDebug) {
terraDebugger({ submitQA: "your_QA_app" });
}
Dig Element
Helper function designed to inspect a specified HTML element for mutations in its styles, classes, data attributes, or the structure of its children.
The function returns a Promise resolving in true or rejecting with error message.
import { digElement } from "@terrahq/helpers/digElement";
4 different ways of implementing it:
1 - Style Search
Promise.all(
elements.map(async (element) => {
await digElement({
element: element,
search: {
type: "style",
lookFor: ["max-height"],
},
intervalFrequency: 1500,
timer: 5000,
debug: true,
callback: () => console.log("COMPLETED!"),
});
})
)
.then(() => {
console.log("READY");
})
.catch((error) => console.log(error.message));
| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'style' | | 3 | search.lookFor | Array | Array of styles properties to look for | | 4 | intervalFrequency | Number | Interval frequency in seconds | | 5 | timer | Number | The duration in seconds after which the interval will be finished | | 6 | callback | Function | A callback function to execute once the promise is resolved |
Class Search
Promise.all(
elements.map(async (element) => {
await digElement({
element: element,
search: {
type: "class",
lookFor: ["test-class"],
},
intervalFrequency: 1500,
timer: 5000,
debug: true,
callback: () => console.log("COMPLETED!"),
});
})
)
.then(() => {
console.log("READY");
})
.catch((error) => console.log(error.message));
| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'class' | | 3 | search.lookFor | Array | Array of classes to look for | | 4 | intervalFrequency | Number | Interval frequency in seconds | | 5 | timer | Number | The duration in seconds after which the interval will be finished | | 6 | callback | Function | A callback function to execute once the promise is resolved |
Attribute Search and look for a specific value
Promise.all(
elements.map(async (element) => {
await digElement({
element: element,
search: {
type: "class",
attribute: "data-test",
lookFor: ["value"],
},
intervalFrequency: 1500,
timer: 5000,
debug: true,
callback: () => console.log("COMPLETED!"),
});
})
)
.then(() => {
console.log("READY");
})
.catch((error) => console.log(error.message));
Here's the information you provided in table format:
| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'class' | | 3 | search.attribute | String | The data attribute to check | | 4 | search.lookFor | Array | Array of possible values for the data attribute | | 5 | intervalFrequency | Number | Interval frequency in seconds | | 6 | timer | Number | The duration in seconds after which the interval will be finished | | 7 | callback | Function | A callback function to execute once the promise is resolved |
Search for children inside element
Promise.all(
elements.map(async (element) => {
await digElement({
element: element,
search: {
type: "hasChildren",
},
intervalFrequency: 1500,
timer: 5000,
debug: true,
callback: () => console.log("COMPLETED!"),
});
})
)
.then(() => {
console.log("READY");
})
.catch((error) => console.log(error.message));
Here's the information in table format:
| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'hasChildren' | | 3 | intervalFrequency | Number | Interval frequency in seconds | | 4 | timer | Number | The duration in seconds after which the interval will be finished | | 5 | callback | Function | A callback function to execute once the promise is resolved |
Manipulate Scroll
Helper function designed to enable/disable scrolling in your website.
import { manipulateScroll } from "@terrahq/helpers/manipulateScroll";
manipulateScroll("block");
manipulateScroll("scroll");
Get ID by Slug
Helper function designed to get the ID/s of the specified pages/post types looking by slug (it works only for WordPress projects).
import { getIDbySlug } from "@terrahq/helpers/getIDbySlug";
const payload = {
slug: "my-page-slug",
type: ["pages", "posts"],
callback: () => {
console.log("This is a callback!");
},
debug: true,
};
const postID = await getIDbySlug(payload);
if (postID) {
console.log(`Found post with ID: ${postID}`);
} else {
console.log("No post found with the specified slug.");
}
Get ID by Title
Helper function designed to get the ID/s of the specified pages/post types looking by title (it works only for WordPress projects).
import { getIDbyTitle } from "@terrahq/helpers/getIDbyTitle";
const payload = {
title: "my-page-title",
type: ["pages", "posts"],
callback: () => {
console.log("This is a callback!");
},
debug: true,
};
const postID = await getIDbyTitle(payload);
if (postID) {
console.log(`Found post with ID: ${postID}`);
} else {
console.log("No post found with the specified title.");
}
hasQueryParameter
This function checks if a specific query parameter is present in the URL of the current window location and retrieves its value if it exists. It is particularly useful for accessing and manipulating URL parameters dynamically in client-side applications.
import { hasQueryParameter } from "@terrahq/helpers/hasQueryParameter";
let result = hasQueryParameter({ name: "user" });
if (result) {
console.log(`Query parameter 'user' has the value: ${result}`);
} else {
console.log("Query parameter 'user' is not present in the URL.");
}
scrollYis
This function checks if the current vertical scroll position (window.scrollY) of the window is equal to a specified distance. It is typically used in scenarios where you need to verify if the window has been scrolled to a particular vertical position.
import { scrollYis } from "@terrahq/helpers/scrollYis";
if (scrollYis({ distance: 30 })) {
console.log("The scroll position is exactly 30 pixels or more from the top.");
} else {
console.log("The scroll position is below 30 pixels.");
}
Google Scripts Detection
This utility function, hasGoogleScripts
, is designed to asynchronously check for the presence of Google Analytics and Google Tag Manager scripts on a webpage. It returns a promise that resolves with a boolean value indicating whether the specified Google scripts are detected within a given timeframe.
import { hasGoogleScripts } from "@terrahq/helpers/hasGoogleScripts";
Function Signature
async hasGoogleScripts(options = { detect: ['analytics', 'gtm'], maxTime: 5000, debug: false })
options
: Optional configuration object.detect
: Array specifying which Google scripts to detect. Default is['analytics', 'gtm']
. You can also detect Google Ads by adding a 'ads' to the array.maxTime
: Maximum time in milliseconds to wait for script detection. Default is5000
.debug
: Default false, you can show the console logs withdebug: true
.
Usage
The function can be used with await
inside an async function, or with .then()
for promise handling. Here's an example using .then()
for handling the detection result:
await hasGoogleScripts().then((detected) => {
if (detected) {
// Code to execute if the specified Google scripts are detected, e.g., load GTM
this.loadGTM();
} else {
// Code to execute if the scripts are not detected within the specified time
console.log("Google Scripts not detected");
}
});
Recaptcha
Helper to add recaptcha v3 to forms. It has several functions. 1st Asynchronously loads the reCAPTCHA script from Google with the specified API key.
import { GET_RECAPTCHA_SCRIPT_FROM_GOOGLE } from "@terrahq/helpers/recaptcha";
var publicKey = "XXXXXXX";
var loadRecaptchaScript = await GET_RECAPTCHA_SCRIPT_FROM_GOOGLE({
API_KEY: publicKey,
});
2nd Asynchronously retrieves a reCAPTCHA client token by executing the reCAPTCHA challenge.
import { GET_RECAPTCHA_CLIENT_TOKEN } from "@terrahq/helpers/recaptcha";
var google_access_token = await GET_RECAPTCHA_CLIENT_TOKEN({
API_KEY: publicKey,
action: "submit",
});
3rd Validates a Google reCAPTCHA token on the server-side using either PHP or Node.js.
import { VALIDATE_RECAPTCHA_SERVER } from "@terrahq/helpers/recaptcha";
var response_from_server = await VALIDATE_RECAPTCHA_SERVER({
type: "node",
postUrl: "yoursite.com/api/validate_recaptcha",
action: "recaptcha_validate",
google_access_token: google_access_token,
});
Note : you could use these reference as a draft, this is not production ready, samples for Node or PHP
WPCF7 Delay Recaptcha
Dynamically injects Google reCAPTCHA and required scripts into the document head, optimizing load times for Contact Form 7 forms with reCAPTCHA. Includes optional debug logging and supports a callback function post-injection.
import { wpcf7DelayRecaptcha } from "@terrahq/helpers/wpcf7DelayRecaptcha";
wpcf7DelayRecaptcha({
scripts: {
recaptchaScript: 'google-recaptcha-js',
polyfill: 'wp-polyfill-js',
recaptchaExtraScriptId: 'wpcf7-recaptcha-js-extra',
wpcf7RecaptchaScriptId: 'wpcf7-recaptcha-js'
},
siteKey: 'XXXXXXX',
debug: true,
callback: () => {
console.log("reCAPTCHA scripts have been successfully injected!");
}
});
---
## Accessible Tab Nav
It handles focus on 'skip to main content' and/or anchor to section enter keydown.
```javascript
import { accessibleTabNav } from "@terrahq/helpers/accessibleTabNav";
| # | Parameter | Type | Description | | --- | ----------------- | ------------- | ------------------------------------------------------------------------------------------- | | 1 | focusableElements | Array | It specifies which types of elements will be included as focusables within the focus target |
Trigger elements must include:
class: 'js--trigger-focus'
data-focus-target='${focusTargetID}'
Target elements must include:
- id: '${focusTargetID}'
HTML - Example 1:
//header.php
<main id="swup">
<button class="js--trigger-focus" data-focus-target="main-content" tabindex="1">Skip to Main Content</button>
<div id="main-content">...</div>
...
</main>
HTML - Example 2:
//card-a.php
<a href="test" class="c--card-a js--trigger-focus" data-focus-target="3">
<div class="c--card-a__ft-items">
<h2 class="c--card-a__ft-items__title">Title</h2>
<p class="c--card-a__ft-items__subtitle">Subtitle</p>
<div class="c--card-a__ft-items__btn">Link</div>
</div>
</a>
//random-module.php
<span id="3" class="js--invisible-span" style="position: relative; display:block;"></span>
<section class="">
<div class="f--container">Content</div>
</section>
JavaScript:
accessibleTabNav();
accessibleTabNav({
focusableElements: ["a", "button"],
});