The throttle
returns a new function that will execute no more than once every delay
milliseconds.
throttle(delay, [ noTrailing || false ], callback, debounceMode)
delay: number
: zero or greater delay
in millisecondsnoTrailing: boolean
: Optional, defaults to false. If noTrailing
is true, the callback will only execute every delay
milliseconds while the throttled function is being called. If noTrailing
is false or unspecified, the callback will be executed one final time after the last throttled function call. (After the throttled function has not been called for delay
milliseconds, the internal counter is reset).callback: Function
: function to execute after the delay
debounceMode: boolean
: If debounceMode
is true (at begin), schedule clear to execute after delay
milliseconds. If debounceMode
is false (at the end), schedule callback to execute after delay
milliseconds.The debounce
function returns a function that will execute only once, coalescing multiple sequential calls into a single execution at either the very beginning or end.
debounce(delay, [ atBegin || false ], callback)
delay: number
: zero or greater delay
in millisecondsatBegin: boolean
: Optional, defaults to false. If atBegin
is false or unspecified, the callback will only be executed after delay
since the last debounced function call. If atBegin
is true, the callback will be executed only at the first debounced function call. (After the debounced function has not been called for delay
milliseconds, the internal counter is reset).callback: Function
: function to execute after the delay
To cancel created throttle or debounce methods, simply call the cancel()
function.
Example:
import Component from '../component/component';
import { debounce, throttle } from '../helpers/helpers';
export default class ClassName extends Component {
static initSelector: string = '.selector-class';
private throttleScroll: throttle<() => void>;
private debounceResize: debounce<() => void>;
constructor(target: HTMLElement) {
super(target);
this.throttleScroll = throttle(100, false, this.resizeHandler.bind(this), false);
this.debounceResize = debounce(100, true, this.resizeHandler.bind(this));
this.init();
}
init(): void {
$(window).on('scroll', this.throttleScroll);
$(window).on('resize', this.debounceResize);
}
resizeHandler(): void {
// code to execute
}
destroy(): void {
$(document).off('scroll', this.throttleScroll);
$(document).off('resize', this.debounceResize);
this.throttleScroll.cancel();
this.debounceResize.cancel();
}
}
The breakPoints
object is used to store the project’s media query breakpoint values to be used in different situations in JavaScript.
When modifying the values in variables.scss
, you should also change them in helpers.ts
accordingly.
Prefer using window.matchMedia
over window.width
when dealing with screen sizes in JavaScript.
Example:
const mediaQuery: string = `(min-width: ${Helpers.breakPoints.md}px)`;
if (window.matchMedia(mediaQuery).matches) {
// do something here
}
Limit the width of content and center it horizontally.
<div class="h-container ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-container"
}
body {
overflow-y: scroll;
background: $L-background-light;
}
#page { // stylelint-disable selector-max-id
body.is-scroll-disabled & {
overflow-y: hidden;
position: fixed;
width: 100%;
}
}
.h-container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $container-padding;
position: relative;
@include bp(md-min) {
padding: 0 $container-padding-md;
}
}
@media only screen and (max-width: 767.99px) {
.h-cancel-container {
margin: 0 (-$container-padding);
width: calc(100% + 2 * $container-padding);
}
}
.h-visibility-hidden {
visibility: hidden;
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.h-visually-hidden {
@include visually-hidden();
}
.h-hidden {
display: none !important;
}
.h-visible {
display: block !important;
}
.h-hidden-xxs {
@media only screen and (max-width: $bp-xs-min - 1) {
display: none !important;
}
}
.h-hidden-xs {
@media only screen and (max-width: $bp-sm-min - 1) {
display: none !important;
}
}
.h-hidden-sm {
@media only screen and (min-width: $bp-sm-min) and (max-width: $bp-md-min - 1) {
display: none !important;
}
}
.h-hidden-md {
@media only screen and (min-width: $bp-md-min) and (max-width: $bp-lg-min - 1) {
display: none !important;
}
}
.h-hidden-lg {
@media only screen and (min-width: $bp-lg-min) {
display: none !important;
}
}
.h-text-left {
text-align: left;
}
.h-text-center {
text-align: center;
}
.h-text-right {
text-align: right;
}
.h-block {
display: block;
}
.h-table {
max-width: 100vw;
overflow: auto;
margin-right: $container-padding * -1;
margin-left: $container-padding * -1;
padding-left: 20px;
display: flex;
&:after {
content: '';
display: block;
width: 20px;
flex: 0 0 20px;
}
@include table-styles;
}
.h-d-flex {
display: flex;
}
.h-justify-content-between {
justify-content: space-between;
}
.h-invisible {
opacity: 0 !important;
visibility: hidden !important;
}
import 'form-serializer';
import 'wicg-inert';
import Component from '../component/component';
import './helpers.scss';
export { throttle, debounce } from 'throttle-debounce';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
interface IBreakPoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
static breakPoints: IBreakPoints = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1400,
};
static get isSmallScreen(): boolean {
return window.matchMedia(`(max-width: ${Helpers.breakPoints.md - 1}px)`).matches;
}
static get isMobileDevice(): boolean {
return ((/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4))) ? true : false);
}
static enablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.removeAttribute('inert');
}
}
static disablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.setAttribute('inert', 'true');
}
}
static scrollTo(event: JQuery.TriggeredEvent): void {
const selector: string = $(event.currentTarget).attr('href');
const target: JQuery = $(selector);
if (target.length > 0) {
event.preventDefault();
Helpers.scrollToTarget(target);
}
}
static scrollToTarget(target: JQuery, offsetTop: number = 0): void {
$('html, body').animate({
scrollTop: target.offset().top - offsetTop - (window.gotoAndPlay.headerOffset ? window.gotoAndPlay.headerOffset : 0),
}, 500);
}
static isOnScreen(target: JQuery, partial: boolean = true): boolean {
const win: JQuery<Window> = $(window);
const viewTop: number = win.scrollTop();
const viewBottom: number = viewTop + win.height();
const top: number = target.offset().top;
const bottom: number = top + target.height();
const compareTop: number = partial === true ? bottom : top;
const compareBottom: number = partial === true ? top : bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
}
static disableScroll(): void {
if (!Helpers.isScrollDisabled()) {
const curScroll: number = $(window).scrollTop();
$('body').addClass('is-scroll-disabled');
$('#page').css('top', -curScroll);
$(window).scrollTop(0);
}
}
static enableScroll(): void {
const bodyScroll: number = parseInt($('#page').css('top'), 10);
$('body').removeClass('is-scroll-disabled');
if (bodyScroll) {
$(window).scrollTop(-bodyScroll);
$('#page').css('top', 0);
}
}
static isScrollDisabled(): boolean {
return $('body').hasClass('is-scroll-disabled');
}
static isURL(str: string): boolean {
const regexp: RegExp = /^https?:\/\//i;
return regexp.test(str);
}
static toFixed(n: number, prec: number): number {
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
const k: number = Math.pow(10, prec);
return Math.round(n * k) / k;
}
static formatNumber(num: number, decimals: number = 2, decPoint: string = '.', thousandsSep: string = ''): string {
const n: number = !isFinite(+num) ? 0 : +num;
const prec: number = !isFinite(+decimals) ? 0 : Math.abs(decimals);
const sep: string = thousandsSep === null ? ' ' : thousandsSep;
const dec: string = decPoint === null ? ',' : decPoint;
const s: string[] = (prec ? Helpers.toFixed(n, prec) : Math.round(n)).toString().split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
static serializeObject(formElement: JQuery): Record<string, unknown> {
const formArray: Record<string, unknown> = formElement.serializeObject() as Record<string, unknown>;
formElement.find('[type=checkbox]:not(:checked)').each((index: number, element: HTMLElement): void => {
formArray[$(element).attr('name')] = '';
});
return formArray;
}
static parseFloat(val: string): number {
const num: number = parseFloat(val);
if (typeof num === 'number' && !isNaN(num)) {
return num;
} else {
return 0;
}
}
static trackEvent(params: IGaEventParams): void {
if (typeof ga !== 'undefined') {
ga('send', {
eventAction: params.action,
eventCategory: params.category,
eventLabel: params.label,
eventValue: params.value,
hitType: 'event',
});
}
if (typeof gtag !== 'undefined') {
gtag('event', params.action, {
// eslint-disable-next-line @typescript-eslint/naming-convention
event_category: params.category,
// eslint-disable-next-line @typescript-eslint/naming-convention
event_label: params.label,
value: params.value,
});
}
}
static trackPageChange(path: string): void {
if (typeof ga !== 'undefined') {
ga('set', 'page', path);
ga('send', 'pageview');
}
if (typeof gtag !== 'undefined') {
gtag('event', 'screen_view', {
// eslint-disable-next-line @typescript-eslint/naming-convention
screen_name: path,
});
}
}
static convertToInt(value: string | number | undefined): number {
const numeric: number = parseInt('' + value, 10);
return isNaN(numeric) ? 0 : numeric;
}
static init(): void {
// setup defaults variables
Object.keys(Helpers.defaults).forEach((key: string): void => {
if (window.gotoAndPlay[key] === undefined) {
window.gotoAndPlay[key] = Helpers.defaults[key];
}
});
// run after document ready
$((): void => {
// init components
if (window.gotoAndPlay && Object.prototype.hasOwnProperty.call(window.gotoAndPlay, 'components')) {
Object.keys(window.gotoAndPlay.components).forEach((name: string): void => {
const component: unknown = window.gotoAndPlay.components[name];
if (Component.is(component)) {
component.enhance();
}
});
$(document).trigger('enhance');
}
// re-init components after gravity form post render
$(document).on('gform_post_render', (event: JQuery.TriggeredEvent): void => {
$(event.currentTarget).trigger('enhance');
});
// other field logic for gravity
$(document).on('change', '.gchoice input[type="radio"]', (event: JQuery.TriggeredEvent): void => {
const input: JQuery = $(event.currentTarget).parents('.choice-group').find('[value="gf_other_choice"]');
const textField: JQuery = input.parents('.gchoice').find('input[type="text"]');
const element: JQuery = $('[name="' + input.attr('name') + '"]:checked');
if (element.val() === input.val()) {
textField.removeAttr('disabled');
textField.parents('.textfield').removeClass('is-disabled');
textField.trigger('focus');
} else {
textField.attr('disabled', 'disabled');
textField.parents('.textfield').addClass('is-disabled');
}
});
// track ga events
$(document).on('click', '[data-ga-action]', (event: JQuery.TriggeredEvent): void => {
const target: JQuery = $(event.currentTarget);
const value: string | undefined = target.data('gaValue');
Helpers.trackEvent({
action: '' + target.data('gaAction'),
category: '' + target.data('gaCategory'),
label: '' + target.data('gaLabel'),
value: value !== '' && value !== undefined ? Helpers.convertToInt(value) : undefined,
});
});
// add resizing class to body
let resizeTimeout: number;
$(window).on('resize', () => {
$('body').addClass('is-resizing');
clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(() => {
$('body').removeClass('is-resizing');
}, 150);
});
});
// personal touch by gotoAndPlay team
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line no-console
console.log('%c \n \u221e\u221e\u221e\u221e \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e %cHi there! %c\n \u221e\u221e\u221e \u221e\u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe hope you\'re enjoying our work!%c\n\u221e\u221e \u221e\u221e\u221e\u221e \u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe did our best to bring you this experience!%c \n \u221e\u221e\u221e \u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e\u221e\u221e %cMade with ♥ by gotoAndPlay%c \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e \u221e\u221e\u221e \n \u221e\u221e\u221e\u221e \u221e\u221e\u221e', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;');
}
}
}
Helpers.init();
Float an element to the left.
<div class="h-pull-left ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-pull-left"
}
body {
overflow-y: scroll;
background: $L-background-light;
}
#page { // stylelint-disable selector-max-id
body.is-scroll-disabled & {
overflow-y: hidden;
position: fixed;
width: 100%;
}
}
.h-container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $container-padding;
position: relative;
@include bp(md-min) {
padding: 0 $container-padding-md;
}
}
@media only screen and (max-width: 767.99px) {
.h-cancel-container {
margin: 0 (-$container-padding);
width: calc(100% + 2 * $container-padding);
}
}
.h-visibility-hidden {
visibility: hidden;
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.h-visually-hidden {
@include visually-hidden();
}
.h-hidden {
display: none !important;
}
.h-visible {
display: block !important;
}
.h-hidden-xxs {
@media only screen and (max-width: $bp-xs-min - 1) {
display: none !important;
}
}
.h-hidden-xs {
@media only screen and (max-width: $bp-sm-min - 1) {
display: none !important;
}
}
.h-hidden-sm {
@media only screen and (min-width: $bp-sm-min) and (max-width: $bp-md-min - 1) {
display: none !important;
}
}
.h-hidden-md {
@media only screen and (min-width: $bp-md-min) and (max-width: $bp-lg-min - 1) {
display: none !important;
}
}
.h-hidden-lg {
@media only screen and (min-width: $bp-lg-min) {
display: none !important;
}
}
.h-text-left {
text-align: left;
}
.h-text-center {
text-align: center;
}
.h-text-right {
text-align: right;
}
.h-block {
display: block;
}
.h-table {
max-width: 100vw;
overflow: auto;
margin-right: $container-padding * -1;
margin-left: $container-padding * -1;
padding-left: 20px;
display: flex;
&:after {
content: '';
display: block;
width: 20px;
flex: 0 0 20px;
}
@include table-styles;
}
.h-d-flex {
display: flex;
}
.h-justify-content-between {
justify-content: space-between;
}
.h-invisible {
opacity: 0 !important;
visibility: hidden !important;
}
import 'form-serializer';
import 'wicg-inert';
import Component from '../component/component';
import './helpers.scss';
export { throttle, debounce } from 'throttle-debounce';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
interface IBreakPoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
static breakPoints: IBreakPoints = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1400,
};
static get isSmallScreen(): boolean {
return window.matchMedia(`(max-width: ${Helpers.breakPoints.md - 1}px)`).matches;
}
static get isMobileDevice(): boolean {
return ((/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4))) ? true : false);
}
static enablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.removeAttribute('inert');
}
}
static disablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.setAttribute('inert', 'true');
}
}
static scrollTo(event: JQuery.TriggeredEvent): void {
const selector: string = $(event.currentTarget).attr('href');
const target: JQuery = $(selector);
if (target.length > 0) {
event.preventDefault();
Helpers.scrollToTarget(target);
}
}
static scrollToTarget(target: JQuery, offsetTop: number = 0): void {
$('html, body').animate({
scrollTop: target.offset().top - offsetTop - (window.gotoAndPlay.headerOffset ? window.gotoAndPlay.headerOffset : 0),
}, 500);
}
static isOnScreen(target: JQuery, partial: boolean = true): boolean {
const win: JQuery<Window> = $(window);
const viewTop: number = win.scrollTop();
const viewBottom: number = viewTop + win.height();
const top: number = target.offset().top;
const bottom: number = top + target.height();
const compareTop: number = partial === true ? bottom : top;
const compareBottom: number = partial === true ? top : bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
}
static disableScroll(): void {
if (!Helpers.isScrollDisabled()) {
const curScroll: number = $(window).scrollTop();
$('body').addClass('is-scroll-disabled');
$('#page').css('top', -curScroll);
$(window).scrollTop(0);
}
}
static enableScroll(): void {
const bodyScroll: number = parseInt($('#page').css('top'), 10);
$('body').removeClass('is-scroll-disabled');
if (bodyScroll) {
$(window).scrollTop(-bodyScroll);
$('#page').css('top', 0);
}
}
static isScrollDisabled(): boolean {
return $('body').hasClass('is-scroll-disabled');
}
static isURL(str: string): boolean {
const regexp: RegExp = /^https?:\/\//i;
return regexp.test(str);
}
static toFixed(n: number, prec: number): number {
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
const k: number = Math.pow(10, prec);
return Math.round(n * k) / k;
}
static formatNumber(num: number, decimals: number = 2, decPoint: string = '.', thousandsSep: string = ''): string {
const n: number = !isFinite(+num) ? 0 : +num;
const prec: number = !isFinite(+decimals) ? 0 : Math.abs(decimals);
const sep: string = thousandsSep === null ? ' ' : thousandsSep;
const dec: string = decPoint === null ? ',' : decPoint;
const s: string[] = (prec ? Helpers.toFixed(n, prec) : Math.round(n)).toString().split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
static serializeObject(formElement: JQuery): Record<string, unknown> {
const formArray: Record<string, unknown> = formElement.serializeObject() as Record<string, unknown>;
formElement.find('[type=checkbox]:not(:checked)').each((index: number, element: HTMLElement): void => {
formArray[$(element).attr('name')] = '';
});
return formArray;
}
static parseFloat(val: string): number {
const num: number = parseFloat(val);
if (typeof num === 'number' && !isNaN(num)) {
return num;
} else {
return 0;
}
}
static trackEvent(params: IGaEventParams): void {
if (typeof ga !== 'undefined') {
ga('send', {
eventAction: params.action,
eventCategory: params.category,
eventLabel: params.label,
eventValue: params.value,
hitType: 'event',
});
}
if (typeof gtag !== 'undefined') {
gtag('event', params.action, {
// eslint-disable-next-line @typescript-eslint/naming-convention
event_category: params.category,
// eslint-disable-next-line @typescript-eslint/naming-convention
event_label: params.label,
value: params.value,
});
}
}
static trackPageChange(path: string): void {
if (typeof ga !== 'undefined') {
ga('set', 'page', path);
ga('send', 'pageview');
}
if (typeof gtag !== 'undefined') {
gtag('event', 'screen_view', {
// eslint-disable-next-line @typescript-eslint/naming-convention
screen_name: path,
});
}
}
static convertToInt(value: string | number | undefined): number {
const numeric: number = parseInt('' + value, 10);
return isNaN(numeric) ? 0 : numeric;
}
static init(): void {
// setup defaults variables
Object.keys(Helpers.defaults).forEach((key: string): void => {
if (window.gotoAndPlay[key] === undefined) {
window.gotoAndPlay[key] = Helpers.defaults[key];
}
});
// run after document ready
$((): void => {
// init components
if (window.gotoAndPlay && Object.prototype.hasOwnProperty.call(window.gotoAndPlay, 'components')) {
Object.keys(window.gotoAndPlay.components).forEach((name: string): void => {
const component: unknown = window.gotoAndPlay.components[name];
if (Component.is(component)) {
component.enhance();
}
});
$(document).trigger('enhance');
}
// re-init components after gravity form post render
$(document).on('gform_post_render', (event: JQuery.TriggeredEvent): void => {
$(event.currentTarget).trigger('enhance');
});
// other field logic for gravity
$(document).on('change', '.gchoice input[type="radio"]', (event: JQuery.TriggeredEvent): void => {
const input: JQuery = $(event.currentTarget).parents('.choice-group').find('[value="gf_other_choice"]');
const textField: JQuery = input.parents('.gchoice').find('input[type="text"]');
const element: JQuery = $('[name="' + input.attr('name') + '"]:checked');
if (element.val() === input.val()) {
textField.removeAttr('disabled');
textField.parents('.textfield').removeClass('is-disabled');
textField.trigger('focus');
} else {
textField.attr('disabled', 'disabled');
textField.parents('.textfield').addClass('is-disabled');
}
});
// track ga events
$(document).on('click', '[data-ga-action]', (event: JQuery.TriggeredEvent): void => {
const target: JQuery = $(event.currentTarget);
const value: string | undefined = target.data('gaValue');
Helpers.trackEvent({
action: '' + target.data('gaAction'),
category: '' + target.data('gaCategory'),
label: '' + target.data('gaLabel'),
value: value !== '' && value !== undefined ? Helpers.convertToInt(value) : undefined,
});
});
// add resizing class to body
let resizeTimeout: number;
$(window).on('resize', () => {
$('body').addClass('is-resizing');
clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(() => {
$('body').removeClass('is-resizing');
}, 150);
});
});
// personal touch by gotoAndPlay team
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line no-console
console.log('%c \n \u221e\u221e\u221e\u221e \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e %cHi there! %c\n \u221e\u221e\u221e \u221e\u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe hope you\'re enjoying our work!%c\n\u221e\u221e \u221e\u221e\u221e\u221e \u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe did our best to bring you this experience!%c \n \u221e\u221e\u221e \u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e\u221e\u221e %cMade with ♥ by gotoAndPlay%c \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e \u221e\u221e\u221e \n \u221e\u221e\u221e\u221e \u221e\u221e\u221e', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;');
}
}
}
Helpers.init();
Float an element to the right.
<div class="h-pull-right ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-pull-right"
}
body {
overflow-y: scroll;
background: $L-background-light;
}
#page { // stylelint-disable selector-max-id
body.is-scroll-disabled & {
overflow-y: hidden;
position: fixed;
width: 100%;
}
}
.h-container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $container-padding;
position: relative;
@include bp(md-min) {
padding: 0 $container-padding-md;
}
}
@media only screen and (max-width: 767.99px) {
.h-cancel-container {
margin: 0 (-$container-padding);
width: calc(100% + 2 * $container-padding);
}
}
.h-visibility-hidden {
visibility: hidden;
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.h-visually-hidden {
@include visually-hidden();
}
.h-hidden {
display: none !important;
}
.h-visible {
display: block !important;
}
.h-hidden-xxs {
@media only screen and (max-width: $bp-xs-min - 1) {
display: none !important;
}
}
.h-hidden-xs {
@media only screen and (max-width: $bp-sm-min - 1) {
display: none !important;
}
}
.h-hidden-sm {
@media only screen and (min-width: $bp-sm-min) and (max-width: $bp-md-min - 1) {
display: none !important;
}
}
.h-hidden-md {
@media only screen and (min-width: $bp-md-min) and (max-width: $bp-lg-min - 1) {
display: none !important;
}
}
.h-hidden-lg {
@media only screen and (min-width: $bp-lg-min) {
display: none !important;
}
}
.h-text-left {
text-align: left;
}
.h-text-center {
text-align: center;
}
.h-text-right {
text-align: right;
}
.h-block {
display: block;
}
.h-table {
max-width: 100vw;
overflow: auto;
margin-right: $container-padding * -1;
margin-left: $container-padding * -1;
padding-left: 20px;
display: flex;
&:after {
content: '';
display: block;
width: 20px;
flex: 0 0 20px;
}
@include table-styles;
}
.h-d-flex {
display: flex;
}
.h-justify-content-between {
justify-content: space-between;
}
.h-invisible {
opacity: 0 !important;
visibility: hidden !important;
}
import 'form-serializer';
import 'wicg-inert';
import Component from '../component/component';
import './helpers.scss';
export { throttle, debounce } from 'throttle-debounce';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
interface IBreakPoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
static breakPoints: IBreakPoints = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1400,
};
static get isSmallScreen(): boolean {
return window.matchMedia(`(max-width: ${Helpers.breakPoints.md - 1}px)`).matches;
}
static get isMobileDevice(): boolean {
return ((/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4))) ? true : false);
}
static enablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.removeAttribute('inert');
}
}
static disablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.setAttribute('inert', 'true');
}
}
static scrollTo(event: JQuery.TriggeredEvent): void {
const selector: string = $(event.currentTarget).attr('href');
const target: JQuery = $(selector);
if (target.length > 0) {
event.preventDefault();
Helpers.scrollToTarget(target);
}
}
static scrollToTarget(target: JQuery, offsetTop: number = 0): void {
$('html, body').animate({
scrollTop: target.offset().top - offsetTop - (window.gotoAndPlay.headerOffset ? window.gotoAndPlay.headerOffset : 0),
}, 500);
}
static isOnScreen(target: JQuery, partial: boolean = true): boolean {
const win: JQuery<Window> = $(window);
const viewTop: number = win.scrollTop();
const viewBottom: number = viewTop + win.height();
const top: number = target.offset().top;
const bottom: number = top + target.height();
const compareTop: number = partial === true ? bottom : top;
const compareBottom: number = partial === true ? top : bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
}
static disableScroll(): void {
if (!Helpers.isScrollDisabled()) {
const curScroll: number = $(window).scrollTop();
$('body').addClass('is-scroll-disabled');
$('#page').css('top', -curScroll);
$(window).scrollTop(0);
}
}
static enableScroll(): void {
const bodyScroll: number = parseInt($('#page').css('top'), 10);
$('body').removeClass('is-scroll-disabled');
if (bodyScroll) {
$(window).scrollTop(-bodyScroll);
$('#page').css('top', 0);
}
}
static isScrollDisabled(): boolean {
return $('body').hasClass('is-scroll-disabled');
}
static isURL(str: string): boolean {
const regexp: RegExp = /^https?:\/\//i;
return regexp.test(str);
}
static toFixed(n: number, prec: number): number {
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
const k: number = Math.pow(10, prec);
return Math.round(n * k) / k;
}
static formatNumber(num: number, decimals: number = 2, decPoint: string = '.', thousandsSep: string = ''): string {
const n: number = !isFinite(+num) ? 0 : +num;
const prec: number = !isFinite(+decimals) ? 0 : Math.abs(decimals);
const sep: string = thousandsSep === null ? ' ' : thousandsSep;
const dec: string = decPoint === null ? ',' : decPoint;
const s: string[] = (prec ? Helpers.toFixed(n, prec) : Math.round(n)).toString().split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
static serializeObject(formElement: JQuery): Record<string, unknown> {
const formArray: Record<string, unknown> = formElement.serializeObject() as Record<string, unknown>;
formElement.find('[type=checkbox]:not(:checked)').each((index: number, element: HTMLElement): void => {
formArray[$(element).attr('name')] = '';
});
return formArray;
}
static parseFloat(val: string): number {
const num: number = parseFloat(val);
if (typeof num === 'number' && !isNaN(num)) {
return num;
} else {
return 0;
}
}
static trackEvent(params: IGaEventParams): void {
if (typeof ga !== 'undefined') {
ga('send', {
eventAction: params.action,
eventCategory: params.category,
eventLabel: params.label,
eventValue: params.value,
hitType: 'event',
});
}
if (typeof gtag !== 'undefined') {
gtag('event', params.action, {
// eslint-disable-next-line @typescript-eslint/naming-convention
event_category: params.category,
// eslint-disable-next-line @typescript-eslint/naming-convention
event_label: params.label,
value: params.value,
});
}
}
static trackPageChange(path: string): void {
if (typeof ga !== 'undefined') {
ga('set', 'page', path);
ga('send', 'pageview');
}
if (typeof gtag !== 'undefined') {
gtag('event', 'screen_view', {
// eslint-disable-next-line @typescript-eslint/naming-convention
screen_name: path,
});
}
}
static convertToInt(value: string | number | undefined): number {
const numeric: number = parseInt('' + value, 10);
return isNaN(numeric) ? 0 : numeric;
}
static init(): void {
// setup defaults variables
Object.keys(Helpers.defaults).forEach((key: string): void => {
if (window.gotoAndPlay[key] === undefined) {
window.gotoAndPlay[key] = Helpers.defaults[key];
}
});
// run after document ready
$((): void => {
// init components
if (window.gotoAndPlay && Object.prototype.hasOwnProperty.call(window.gotoAndPlay, 'components')) {
Object.keys(window.gotoAndPlay.components).forEach((name: string): void => {
const component: unknown = window.gotoAndPlay.components[name];
if (Component.is(component)) {
component.enhance();
}
});
$(document).trigger('enhance');
}
// re-init components after gravity form post render
$(document).on('gform_post_render', (event: JQuery.TriggeredEvent): void => {
$(event.currentTarget).trigger('enhance');
});
// other field logic for gravity
$(document).on('change', '.gchoice input[type="radio"]', (event: JQuery.TriggeredEvent): void => {
const input: JQuery = $(event.currentTarget).parents('.choice-group').find('[value="gf_other_choice"]');
const textField: JQuery = input.parents('.gchoice').find('input[type="text"]');
const element: JQuery = $('[name="' + input.attr('name') + '"]:checked');
if (element.val() === input.val()) {
textField.removeAttr('disabled');
textField.parents('.textfield').removeClass('is-disabled');
textField.trigger('focus');
} else {
textField.attr('disabled', 'disabled');
textField.parents('.textfield').addClass('is-disabled');
}
});
// track ga events
$(document).on('click', '[data-ga-action]', (event: JQuery.TriggeredEvent): void => {
const target: JQuery = $(event.currentTarget);
const value: string | undefined = target.data('gaValue');
Helpers.trackEvent({
action: '' + target.data('gaAction'),
category: '' + target.data('gaCategory'),
label: '' + target.data('gaLabel'),
value: value !== '' && value !== undefined ? Helpers.convertToInt(value) : undefined,
});
});
// add resizing class to body
let resizeTimeout: number;
$(window).on('resize', () => {
$('body').addClass('is-resizing');
clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(() => {
$('body').removeClass('is-resizing');
}, 150);
});
});
// personal touch by gotoAndPlay team
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line no-console
console.log('%c \n \u221e\u221e\u221e\u221e \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e %cHi there! %c\n \u221e\u221e\u221e \u221e\u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe hope you\'re enjoying our work!%c\n\u221e\u221e \u221e\u221e\u221e\u221e \u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe did our best to bring you this experience!%c \n \u221e\u221e\u221e \u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e\u221e\u221e %cMade with ♥ by gotoAndPlay%c \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e \u221e\u221e\u221e \n \u221e\u221e\u221e\u221e \u221e\u221e\u221e', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;');
}
}
}
Helpers.init();
Hides content visually, but keeps it accessible to screen readers.
Show an element that is initially hidden.
<div class="h-visible ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-visible"
}
body {
overflow-y: scroll;
background: $L-background-light;
}
#page { // stylelint-disable selector-max-id
body.is-scroll-disabled & {
overflow-y: hidden;
position: fixed;
width: 100%;
}
}
.h-container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $container-padding;
position: relative;
@include bp(md-min) {
padding: 0 $container-padding-md;
}
}
@media only screen and (max-width: 767.99px) {
.h-cancel-container {
margin: 0 (-$container-padding);
width: calc(100% + 2 * $container-padding);
}
}
.h-visibility-hidden {
visibility: hidden;
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.h-visually-hidden {
@include visually-hidden();
}
.h-hidden {
display: none !important;
}
.h-visible {
display: block !important;
}
.h-hidden-xxs {
@media only screen and (max-width: $bp-xs-min - 1) {
display: none !important;
}
}
.h-hidden-xs {
@media only screen and (max-width: $bp-sm-min - 1) {
display: none !important;
}
}
.h-hidden-sm {
@media only screen and (min-width: $bp-sm-min) and (max-width: $bp-md-min - 1) {
display: none !important;
}
}
.h-hidden-md {
@media only screen and (min-width: $bp-md-min) and (max-width: $bp-lg-min - 1) {
display: none !important;
}
}
.h-hidden-lg {
@media only screen and (min-width: $bp-lg-min) {
display: none !important;
}
}
.h-text-left {
text-align: left;
}
.h-text-center {
text-align: center;
}
.h-text-right {
text-align: right;
}
.h-block {
display: block;
}
.h-table {
max-width: 100vw;
overflow: auto;
margin-right: $container-padding * -1;
margin-left: $container-padding * -1;
padding-left: 20px;
display: flex;
&:after {
content: '';
display: block;
width: 20px;
flex: 0 0 20px;
}
@include table-styles;
}
.h-d-flex {
display: flex;
}
.h-justify-content-between {
justify-content: space-between;
}
.h-invisible {
opacity: 0 !important;
visibility: hidden !important;
}
import 'form-serializer';
import 'wicg-inert';
import Component from '../component/component';
import './helpers.scss';
export { throttle, debounce } from 'throttle-debounce';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
interface IBreakPoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
static breakPoints: IBreakPoints = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1400,
};
static get isSmallScreen(): boolean {
return window.matchMedia(`(max-width: ${Helpers.breakPoints.md - 1}px)`).matches;
}
static get isMobileDevice(): boolean {
return ((/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4))) ? true : false);
}
static enablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.removeAttribute('inert');
}
}
static disablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.setAttribute('inert', 'true');
}
}
static scrollTo(event: JQuery.TriggeredEvent): void {
const selector: string = $(event.currentTarget).attr('href');
const target: JQuery = $(selector);
if (target.length > 0) {
event.preventDefault();
Helpers.scrollToTarget(target);
}
}
static scrollToTarget(target: JQuery, offsetTop: number = 0): void {
$('html, body').animate({
scrollTop: target.offset().top - offsetTop - (window.gotoAndPlay.headerOffset ? window.gotoAndPlay.headerOffset : 0),
}, 500);
}
static isOnScreen(target: JQuery, partial: boolean = true): boolean {
const win: JQuery<Window> = $(window);
const viewTop: number = win.scrollTop();
const viewBottom: number = viewTop + win.height();
const top: number = target.offset().top;
const bottom: number = top + target.height();
const compareTop: number = partial === true ? bottom : top;
const compareBottom: number = partial === true ? top : bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
}
static disableScroll(): void {
if (!Helpers.isScrollDisabled()) {
const curScroll: number = $(window).scrollTop();
$('body').addClass('is-scroll-disabled');
$('#page').css('top', -curScroll);
$(window).scrollTop(0);
}
}
static enableScroll(): void {
const bodyScroll: number = parseInt($('#page').css('top'), 10);
$('body').removeClass('is-scroll-disabled');
if (bodyScroll) {
$(window).scrollTop(-bodyScroll);
$('#page').css('top', 0);
}
}
static isScrollDisabled(): boolean {
return $('body').hasClass('is-scroll-disabled');
}
static isURL(str: string): boolean {
const regexp: RegExp = /^https?:\/\//i;
return regexp.test(str);
}
static toFixed(n: number, prec: number): number {
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
const k: number = Math.pow(10, prec);
return Math.round(n * k) / k;
}
static formatNumber(num: number, decimals: number = 2, decPoint: string = '.', thousandsSep: string = ''): string {
const n: number = !isFinite(+num) ? 0 : +num;
const prec: number = !isFinite(+decimals) ? 0 : Math.abs(decimals);
const sep: string = thousandsSep === null ? ' ' : thousandsSep;
const dec: string = decPoint === null ? ',' : decPoint;
const s: string[] = (prec ? Helpers.toFixed(n, prec) : Math.round(n)).toString().split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
static serializeObject(formElement: JQuery): Record<string, unknown> {
const formArray: Record<string, unknown> = formElement.serializeObject() as Record<string, unknown>;
formElement.find('[type=checkbox]:not(:checked)').each((index: number, element: HTMLElement): void => {
formArray[$(element).attr('name')] = '';
});
return formArray;
}
static parseFloat(val: string): number {
const num: number = parseFloat(val);
if (typeof num === 'number' && !isNaN(num)) {
return num;
} else {
return 0;
}
}
static trackEvent(params: IGaEventParams): void {
if (typeof ga !== 'undefined') {
ga('send', {
eventAction: params.action,
eventCategory: params.category,
eventLabel: params.label,
eventValue: params.value,
hitType: 'event',
});
}
if (typeof gtag !== 'undefined') {
gtag('event', params.action, {
// eslint-disable-next-line @typescript-eslint/naming-convention
event_category: params.category,
// eslint-disable-next-line @typescript-eslint/naming-convention
event_label: params.label,
value: params.value,
});
}
}
static trackPageChange(path: string): void {
if (typeof ga !== 'undefined') {
ga('set', 'page', path);
ga('send', 'pageview');
}
if (typeof gtag !== 'undefined') {
gtag('event', 'screen_view', {
// eslint-disable-next-line @typescript-eslint/naming-convention
screen_name: path,
});
}
}
static convertToInt(value: string | number | undefined): number {
const numeric: number = parseInt('' + value, 10);
return isNaN(numeric) ? 0 : numeric;
}
static init(): void {
// setup defaults variables
Object.keys(Helpers.defaults).forEach((key: string): void => {
if (window.gotoAndPlay[key] === undefined) {
window.gotoAndPlay[key] = Helpers.defaults[key];
}
});
// run after document ready
$((): void => {
// init components
if (window.gotoAndPlay && Object.prototype.hasOwnProperty.call(window.gotoAndPlay, 'components')) {
Object.keys(window.gotoAndPlay.components).forEach((name: string): void => {
const component: unknown = window.gotoAndPlay.components[name];
if (Component.is(component)) {
component.enhance();
}
});
$(document).trigger('enhance');
}
// re-init components after gravity form post render
$(document).on('gform_post_render', (event: JQuery.TriggeredEvent): void => {
$(event.currentTarget).trigger('enhance');
});
// other field logic for gravity
$(document).on('change', '.gchoice input[type="radio"]', (event: JQuery.TriggeredEvent): void => {
const input: JQuery = $(event.currentTarget).parents('.choice-group').find('[value="gf_other_choice"]');
const textField: JQuery = input.parents('.gchoice').find('input[type="text"]');
const element: JQuery = $('[name="' + input.attr('name') + '"]:checked');
if (element.val() === input.val()) {
textField.removeAttr('disabled');
textField.parents('.textfield').removeClass('is-disabled');
textField.trigger('focus');
} else {
textField.attr('disabled', 'disabled');
textField.parents('.textfield').addClass('is-disabled');
}
});
// track ga events
$(document).on('click', '[data-ga-action]', (event: JQuery.TriggeredEvent): void => {
const target: JQuery = $(event.currentTarget);
const value: string | undefined = target.data('gaValue');
Helpers.trackEvent({
action: '' + target.data('gaAction'),
category: '' + target.data('gaCategory'),
label: '' + target.data('gaLabel'),
value: value !== '' && value !== undefined ? Helpers.convertToInt(value) : undefined,
});
});
// add resizing class to body
let resizeTimeout: number;
$(window).on('resize', () => {
$('body').addClass('is-resizing');
clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(() => {
$('body').removeClass('is-resizing');
}, 150);
});
});
// personal touch by gotoAndPlay team
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line no-console
console.log('%c \n \u221e\u221e\u221e\u221e \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e %cHi there! %c\n \u221e\u221e\u221e \u221e\u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe hope you\'re enjoying our work!%c\n\u221e\u221e \u221e\u221e\u221e\u221e \u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe did our best to bring you this experience!%c \n \u221e\u221e\u221e \u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e\u221e\u221e %cMade with ♥ by gotoAndPlay%c \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e \u221e\u221e\u221e \n \u221e\u221e\u221e\u221e \u221e\u221e\u221e', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;');
}
}
}
Helpers.init();
Aligns text content to left.
<div class="h-text-left ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-text-left"
}
body {
overflow-y: scroll;
background: $L-background-light;
}
#page { // stylelint-disable selector-max-id
body.is-scroll-disabled & {
overflow-y: hidden;
position: fixed;
width: 100%;
}
}
.h-container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $container-padding;
position: relative;
@include bp(md-min) {
padding: 0 $container-padding-md;
}
}
@media only screen and (max-width: 767.99px) {
.h-cancel-container {
margin: 0 (-$container-padding);
width: calc(100% + 2 * $container-padding);
}
}
.h-visibility-hidden {
visibility: hidden;
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.h-visually-hidden {
@include visually-hidden();
}
.h-hidden {
display: none !important;
}
.h-visible {
display: block !important;
}
.h-hidden-xxs {
@media only screen and (max-width: $bp-xs-min - 1) {
display: none !important;
}
}
.h-hidden-xs {
@media only screen and (max-width: $bp-sm-min - 1) {
display: none !important;
}
}
.h-hidden-sm {
@media only screen and (min-width: $bp-sm-min) and (max-width: $bp-md-min - 1) {
display: none !important;
}
}
.h-hidden-md {
@media only screen and (min-width: $bp-md-min) and (max-width: $bp-lg-min - 1) {
display: none !important;
}
}
.h-hidden-lg {
@media only screen and (min-width: $bp-lg-min) {
display: none !important;
}
}
.h-text-left {
text-align: left;
}
.h-text-center {
text-align: center;
}
.h-text-right {
text-align: right;
}
.h-block {
display: block;
}
.h-table {
max-width: 100vw;
overflow: auto;
margin-right: $container-padding * -1;
margin-left: $container-padding * -1;
padding-left: 20px;
display: flex;
&:after {
content: '';
display: block;
width: 20px;
flex: 0 0 20px;
}
@include table-styles;
}
.h-d-flex {
display: flex;
}
.h-justify-content-between {
justify-content: space-between;
}
.h-invisible {
opacity: 0 !important;
visibility: hidden !important;
}
import 'form-serializer';
import 'wicg-inert';
import Component from '../component/component';
import './helpers.scss';
export { throttle, debounce } from 'throttle-debounce';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
interface IBreakPoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
static breakPoints: IBreakPoints = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1400,
};
static get isSmallScreen(): boolean {
return window.matchMedia(`(max-width: ${Helpers.breakPoints.md - 1}px)`).matches;
}
static get isMobileDevice(): boolean {
return ((/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4))) ? true : false);
}
static enablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.removeAttribute('inert');
}
}
static disablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.setAttribute('inert', 'true');
}
}
static scrollTo(event: JQuery.TriggeredEvent): void {
const selector: string = $(event.currentTarget).attr('href');
const target: JQuery = $(selector);
if (target.length > 0) {
event.preventDefault();
Helpers.scrollToTarget(target);
}
}
static scrollToTarget(target: JQuery, offsetTop: number = 0): void {
$('html, body').animate({
scrollTop: target.offset().top - offsetTop - (window.gotoAndPlay.headerOffset ? window.gotoAndPlay.headerOffset : 0),
}, 500);
}
static isOnScreen(target: JQuery, partial: boolean = true): boolean {
const win: JQuery<Window> = $(window);
const viewTop: number = win.scrollTop();
const viewBottom: number = viewTop + win.height();
const top: number = target.offset().top;
const bottom: number = top + target.height();
const compareTop: number = partial === true ? bottom : top;
const compareBottom: number = partial === true ? top : bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
}
static disableScroll(): void {
if (!Helpers.isScrollDisabled()) {
const curScroll: number = $(window).scrollTop();
$('body').addClass('is-scroll-disabled');
$('#page').css('top', -curScroll);
$(window).scrollTop(0);
}
}
static enableScroll(): void {
const bodyScroll: number = parseInt($('#page').css('top'), 10);
$('body').removeClass('is-scroll-disabled');
if (bodyScroll) {
$(window).scrollTop(-bodyScroll);
$('#page').css('top', 0);
}
}
static isScrollDisabled(): boolean {
return $('body').hasClass('is-scroll-disabled');
}
static isURL(str: string): boolean {
const regexp: RegExp = /^https?:\/\//i;
return regexp.test(str);
}
static toFixed(n: number, prec: number): number {
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
const k: number = Math.pow(10, prec);
return Math.round(n * k) / k;
}
static formatNumber(num: number, decimals: number = 2, decPoint: string = '.', thousandsSep: string = ''): string {
const n: number = !isFinite(+num) ? 0 : +num;
const prec: number = !isFinite(+decimals) ? 0 : Math.abs(decimals);
const sep: string = thousandsSep === null ? ' ' : thousandsSep;
const dec: string = decPoint === null ? ',' : decPoint;
const s: string[] = (prec ? Helpers.toFixed(n, prec) : Math.round(n)).toString().split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
static serializeObject(formElement: JQuery): Record<string, unknown> {
const formArray: Record<string, unknown> = formElement.serializeObject() as Record<string, unknown>;
formElement.find('[type=checkbox]:not(:checked)').each((index: number, element: HTMLElement): void => {
formArray[$(element).attr('name')] = '';
});
return formArray;
}
static parseFloat(val: string): number {
const num: number = parseFloat(val);
if (typeof num === 'number' && !isNaN(num)) {
return num;
} else {
return 0;
}
}
static trackEvent(params: IGaEventParams): void {
if (typeof ga !== 'undefined') {
ga('send', {
eventAction: params.action,
eventCategory: params.category,
eventLabel: params.label,
eventValue: params.value,
hitType: 'event',
});
}
if (typeof gtag !== 'undefined') {
gtag('event', params.action, {
// eslint-disable-next-line @typescript-eslint/naming-convention
event_category: params.category,
// eslint-disable-next-line @typescript-eslint/naming-convention
event_label: params.label,
value: params.value,
});
}
}
static trackPageChange(path: string): void {
if (typeof ga !== 'undefined') {
ga('set', 'page', path);
ga('send', 'pageview');
}
if (typeof gtag !== 'undefined') {
gtag('event', 'screen_view', {
// eslint-disable-next-line @typescript-eslint/naming-convention
screen_name: path,
});
}
}
static convertToInt(value: string | number | undefined): number {
const numeric: number = parseInt('' + value, 10);
return isNaN(numeric) ? 0 : numeric;
}
static init(): void {
// setup defaults variables
Object.keys(Helpers.defaults).forEach((key: string): void => {
if (window.gotoAndPlay[key] === undefined) {
window.gotoAndPlay[key] = Helpers.defaults[key];
}
});
// run after document ready
$((): void => {
// init components
if (window.gotoAndPlay && Object.prototype.hasOwnProperty.call(window.gotoAndPlay, 'components')) {
Object.keys(window.gotoAndPlay.components).forEach((name: string): void => {
const component: unknown = window.gotoAndPlay.components[name];
if (Component.is(component)) {
component.enhance();
}
});
$(document).trigger('enhance');
}
// re-init components after gravity form post render
$(document).on('gform_post_render', (event: JQuery.TriggeredEvent): void => {
$(event.currentTarget).trigger('enhance');
});
// other field logic for gravity
$(document).on('change', '.gchoice input[type="radio"]', (event: JQuery.TriggeredEvent): void => {
const input: JQuery = $(event.currentTarget).parents('.choice-group').find('[value="gf_other_choice"]');
const textField: JQuery = input.parents('.gchoice').find('input[type="text"]');
const element: JQuery = $('[name="' + input.attr('name') + '"]:checked');
if (element.val() === input.val()) {
textField.removeAttr('disabled');
textField.parents('.textfield').removeClass('is-disabled');
textField.trigger('focus');
} else {
textField.attr('disabled', 'disabled');
textField.parents('.textfield').addClass('is-disabled');
}
});
// track ga events
$(document).on('click', '[data-ga-action]', (event: JQuery.TriggeredEvent): void => {
const target: JQuery = $(event.currentTarget);
const value: string | undefined = target.data('gaValue');
Helpers.trackEvent({
action: '' + target.data('gaAction'),
category: '' + target.data('gaCategory'),
label: '' + target.data('gaLabel'),
value: value !== '' && value !== undefined ? Helpers.convertToInt(value) : undefined,
});
});
// add resizing class to body
let resizeTimeout: number;
$(window).on('resize', () => {
$('body').addClass('is-resizing');
clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(() => {
$('body').removeClass('is-resizing');
}, 150);
});
});
// personal touch by gotoAndPlay team
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line no-console
console.log('%c \n \u221e\u221e\u221e\u221e \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e %cHi there! %c\n \u221e\u221e\u221e \u221e\u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe hope you\'re enjoying our work!%c\n\u221e\u221e \u221e\u221e\u221e\u221e \u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe did our best to bring you this experience!%c \n \u221e\u221e\u221e \u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e\u221e\u221e %cMade with ♥ by gotoAndPlay%c \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e \u221e\u221e\u221e \n \u221e\u221e\u221e\u221e \u221e\u221e\u221e', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;');
}
}
}
Helpers.init();
Aligns text content to center.
<div class="h-text-center ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-text-center"
}
body {
overflow-y: scroll;
background: $L-background-light;
}
#page { // stylelint-disable selector-max-id
body.is-scroll-disabled & {
overflow-y: hidden;
position: fixed;
width: 100%;
}
}
.h-container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $container-padding;
position: relative;
@include bp(md-min) {
padding: 0 $container-padding-md;
}
}
@media only screen and (max-width: 767.99px) {
.h-cancel-container {
margin: 0 (-$container-padding);
width: calc(100% + 2 * $container-padding);
}
}
.h-visibility-hidden {
visibility: hidden;
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.h-visually-hidden {
@include visually-hidden();
}
.h-hidden {
display: none !important;
}
.h-visible {
display: block !important;
}
.h-hidden-xxs {
@media only screen and (max-width: $bp-xs-min - 1) {
display: none !important;
}
}
.h-hidden-xs {
@media only screen and (max-width: $bp-sm-min - 1) {
display: none !important;
}
}
.h-hidden-sm {
@media only screen and (min-width: $bp-sm-min) and (max-width: $bp-md-min - 1) {
display: none !important;
}
}
.h-hidden-md {
@media only screen and (min-width: $bp-md-min) and (max-width: $bp-lg-min - 1) {
display: none !important;
}
}
.h-hidden-lg {
@media only screen and (min-width: $bp-lg-min) {
display: none !important;
}
}
.h-text-left {
text-align: left;
}
.h-text-center {
text-align: center;
}
.h-text-right {
text-align: right;
}
.h-block {
display: block;
}
.h-table {
max-width: 100vw;
overflow: auto;
margin-right: $container-padding * -1;
margin-left: $container-padding * -1;
padding-left: 20px;
display: flex;
&:after {
content: '';
display: block;
width: 20px;
flex: 0 0 20px;
}
@include table-styles;
}
.h-d-flex {
display: flex;
}
.h-justify-content-between {
justify-content: space-between;
}
.h-invisible {
opacity: 0 !important;
visibility: hidden !important;
}
import 'form-serializer';
import 'wicg-inert';
import Component from '../component/component';
import './helpers.scss';
export { throttle, debounce } from 'throttle-debounce';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
interface IBreakPoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
static breakPoints: IBreakPoints = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1400,
};
static get isSmallScreen(): boolean {
return window.matchMedia(`(max-width: ${Helpers.breakPoints.md - 1}px)`).matches;
}
static get isMobileDevice(): boolean {
return ((/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4))) ? true : false);
}
static enablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.removeAttribute('inert');
}
}
static disablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.setAttribute('inert', 'true');
}
}
static scrollTo(event: JQuery.TriggeredEvent): void {
const selector: string = $(event.currentTarget).attr('href');
const target: JQuery = $(selector);
if (target.length > 0) {
event.preventDefault();
Helpers.scrollToTarget(target);
}
}
static scrollToTarget(target: JQuery, offsetTop: number = 0): void {
$('html, body').animate({
scrollTop: target.offset().top - offsetTop - (window.gotoAndPlay.headerOffset ? window.gotoAndPlay.headerOffset : 0),
}, 500);
}
static isOnScreen(target: JQuery, partial: boolean = true): boolean {
const win: JQuery<Window> = $(window);
const viewTop: number = win.scrollTop();
const viewBottom: number = viewTop + win.height();
const top: number = target.offset().top;
const bottom: number = top + target.height();
const compareTop: number = partial === true ? bottom : top;
const compareBottom: number = partial === true ? top : bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
}
static disableScroll(): void {
if (!Helpers.isScrollDisabled()) {
const curScroll: number = $(window).scrollTop();
$('body').addClass('is-scroll-disabled');
$('#page').css('top', -curScroll);
$(window).scrollTop(0);
}
}
static enableScroll(): void {
const bodyScroll: number = parseInt($('#page').css('top'), 10);
$('body').removeClass('is-scroll-disabled');
if (bodyScroll) {
$(window).scrollTop(-bodyScroll);
$('#page').css('top', 0);
}
}
static isScrollDisabled(): boolean {
return $('body').hasClass('is-scroll-disabled');
}
static isURL(str: string): boolean {
const regexp: RegExp = /^https?:\/\//i;
return regexp.test(str);
}
static toFixed(n: number, prec: number): number {
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
const k: number = Math.pow(10, prec);
return Math.round(n * k) / k;
}
static formatNumber(num: number, decimals: number = 2, decPoint: string = '.', thousandsSep: string = ''): string {
const n: number = !isFinite(+num) ? 0 : +num;
const prec: number = !isFinite(+decimals) ? 0 : Math.abs(decimals);
const sep: string = thousandsSep === null ? ' ' : thousandsSep;
const dec: string = decPoint === null ? ',' : decPoint;
const s: string[] = (prec ? Helpers.toFixed(n, prec) : Math.round(n)).toString().split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
static serializeObject(formElement: JQuery): Record<string, unknown> {
const formArray: Record<string, unknown> = formElement.serializeObject() as Record<string, unknown>;
formElement.find('[type=checkbox]:not(:checked)').each((index: number, element: HTMLElement): void => {
formArray[$(element).attr('name')] = '';
});
return formArray;
}
static parseFloat(val: string): number {
const num: number = parseFloat(val);
if (typeof num === 'number' && !isNaN(num)) {
return num;
} else {
return 0;
}
}
static trackEvent(params: IGaEventParams): void {
if (typeof ga !== 'undefined') {
ga('send', {
eventAction: params.action,
eventCategory: params.category,
eventLabel: params.label,
eventValue: params.value,
hitType: 'event',
});
}
if (typeof gtag !== 'undefined') {
gtag('event', params.action, {
// eslint-disable-next-line @typescript-eslint/naming-convention
event_category: params.category,
// eslint-disable-next-line @typescript-eslint/naming-convention
event_label: params.label,
value: params.value,
});
}
}
static trackPageChange(path: string): void {
if (typeof ga !== 'undefined') {
ga('set', 'page', path);
ga('send', 'pageview');
}
if (typeof gtag !== 'undefined') {
gtag('event', 'screen_view', {
// eslint-disable-next-line @typescript-eslint/naming-convention
screen_name: path,
});
}
}
static convertToInt(value: string | number | undefined): number {
const numeric: number = parseInt('' + value, 10);
return isNaN(numeric) ? 0 : numeric;
}
static init(): void {
// setup defaults variables
Object.keys(Helpers.defaults).forEach((key: string): void => {
if (window.gotoAndPlay[key] === undefined) {
window.gotoAndPlay[key] = Helpers.defaults[key];
}
});
// run after document ready
$((): void => {
// init components
if (window.gotoAndPlay && Object.prototype.hasOwnProperty.call(window.gotoAndPlay, 'components')) {
Object.keys(window.gotoAndPlay.components).forEach((name: string): void => {
const component: unknown = window.gotoAndPlay.components[name];
if (Component.is(component)) {
component.enhance();
}
});
$(document).trigger('enhance');
}
// re-init components after gravity form post render
$(document).on('gform_post_render', (event: JQuery.TriggeredEvent): void => {
$(event.currentTarget).trigger('enhance');
});
// other field logic for gravity
$(document).on('change', '.gchoice input[type="radio"]', (event: JQuery.TriggeredEvent): void => {
const input: JQuery = $(event.currentTarget).parents('.choice-group').find('[value="gf_other_choice"]');
const textField: JQuery = input.parents('.gchoice').find('input[type="text"]');
const element: JQuery = $('[name="' + input.attr('name') + '"]:checked');
if (element.val() === input.val()) {
textField.removeAttr('disabled');
textField.parents('.textfield').removeClass('is-disabled');
textField.trigger('focus');
} else {
textField.attr('disabled', 'disabled');
textField.parents('.textfield').addClass('is-disabled');
}
});
// track ga events
$(document).on('click', '[data-ga-action]', (event: JQuery.TriggeredEvent): void => {
const target: JQuery = $(event.currentTarget);
const value: string | undefined = target.data('gaValue');
Helpers.trackEvent({
action: '' + target.data('gaAction'),
category: '' + target.data('gaCategory'),
label: '' + target.data('gaLabel'),
value: value !== '' && value !== undefined ? Helpers.convertToInt(value) : undefined,
});
});
// add resizing class to body
let resizeTimeout: number;
$(window).on('resize', () => {
$('body').addClass('is-resizing');
clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(() => {
$('body').removeClass('is-resizing');
}, 150);
});
});
// personal touch by gotoAndPlay team
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line no-console
console.log('%c \n \u221e\u221e\u221e\u221e \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e %cHi there! %c\n \u221e\u221e\u221e \u221e\u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe hope you\'re enjoying our work!%c\n\u221e\u221e \u221e\u221e\u221e\u221e \u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe did our best to bring you this experience!%c \n \u221e\u221e\u221e \u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e\u221e\u221e %cMade with ♥ by gotoAndPlay%c \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e \u221e\u221e\u221e \n \u221e\u221e\u221e\u221e \u221e\u221e\u221e', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;');
}
}
}
Helpers.init();
Aligns text content to right.
<div class="h-text-right ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-text-right"
}
body {
overflow-y: scroll;
background: $L-background-light;
}
#page { // stylelint-disable selector-max-id
body.is-scroll-disabled & {
overflow-y: hidden;
position: fixed;
width: 100%;
}
}
.h-container {
width: 100%;
max-width: $container-max-width;
margin: 0 auto;
padding: 0 $container-padding;
position: relative;
@include bp(md-min) {
padding: 0 $container-padding-md;
}
}
@media only screen and (max-width: 767.99px) {
.h-cancel-container {
margin: 0 (-$container-padding);
width: calc(100% + 2 * $container-padding);
}
}
.h-visibility-hidden {
visibility: hidden;
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.h-visually-hidden {
@include visually-hidden();
}
.h-hidden {
display: none !important;
}
.h-visible {
display: block !important;
}
.h-hidden-xxs {
@media only screen and (max-width: $bp-xs-min - 1) {
display: none !important;
}
}
.h-hidden-xs {
@media only screen and (max-width: $bp-sm-min - 1) {
display: none !important;
}
}
.h-hidden-sm {
@media only screen and (min-width: $bp-sm-min) and (max-width: $bp-md-min - 1) {
display: none !important;
}
}
.h-hidden-md {
@media only screen and (min-width: $bp-md-min) and (max-width: $bp-lg-min - 1) {
display: none !important;
}
}
.h-hidden-lg {
@media only screen and (min-width: $bp-lg-min) {
display: none !important;
}
}
.h-text-left {
text-align: left;
}
.h-text-center {
text-align: center;
}
.h-text-right {
text-align: right;
}
.h-block {
display: block;
}
.h-table {
max-width: 100vw;
overflow: auto;
margin-right: $container-padding * -1;
margin-left: $container-padding * -1;
padding-left: 20px;
display: flex;
&:after {
content: '';
display: block;
width: 20px;
flex: 0 0 20px;
}
@include table-styles;
}
.h-d-flex {
display: flex;
}
.h-justify-content-between {
justify-content: space-between;
}
.h-invisible {
opacity: 0 !important;
visibility: hidden !important;
}
import 'form-serializer';
import 'wicg-inert';
import Component from '../component/component';
import './helpers.scss';
export { throttle, debounce } from 'throttle-debounce';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
interface IBreakPoints {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
static breakPoints: IBreakPoints = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1400,
};
static get isSmallScreen(): boolean {
return window.matchMedia(`(max-width: ${Helpers.breakPoints.md - 1}px)`).matches;
}
static get isMobileDevice(): boolean {
return ((/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4))) ? true : false);
}
static enablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.removeAttribute('inert');
}
}
static disablePageInteractions(): void {
const page: HTMLElement = document.getElementById('page');
if (page) {
page.setAttribute('inert', 'true');
}
}
static scrollTo(event: JQuery.TriggeredEvent): void {
const selector: string = $(event.currentTarget).attr('href');
const target: JQuery = $(selector);
if (target.length > 0) {
event.preventDefault();
Helpers.scrollToTarget(target);
}
}
static scrollToTarget(target: JQuery, offsetTop: number = 0): void {
$('html, body').animate({
scrollTop: target.offset().top - offsetTop - (window.gotoAndPlay.headerOffset ? window.gotoAndPlay.headerOffset : 0),
}, 500);
}
static isOnScreen(target: JQuery, partial: boolean = true): boolean {
const win: JQuery<Window> = $(window);
const viewTop: number = win.scrollTop();
const viewBottom: number = viewTop + win.height();
const top: number = target.offset().top;
const bottom: number = top + target.height();
const compareTop: number = partial === true ? bottom : top;
const compareBottom: number = partial === true ? top : bottom;
return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
}
static disableScroll(): void {
if (!Helpers.isScrollDisabled()) {
const curScroll: number = $(window).scrollTop();
$('body').addClass('is-scroll-disabled');
$('#page').css('top', -curScroll);
$(window).scrollTop(0);
}
}
static enableScroll(): void {
const bodyScroll: number = parseInt($('#page').css('top'), 10);
$('body').removeClass('is-scroll-disabled');
if (bodyScroll) {
$(window).scrollTop(-bodyScroll);
$('#page').css('top', 0);
}
}
static isScrollDisabled(): boolean {
return $('body').hasClass('is-scroll-disabled');
}
static isURL(str: string): boolean {
const regexp: RegExp = /^https?:\/\//i;
return regexp.test(str);
}
static toFixed(n: number, prec: number): number {
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
const k: number = Math.pow(10, prec);
return Math.round(n * k) / k;
}
static formatNumber(num: number, decimals: number = 2, decPoint: string = '.', thousandsSep: string = ''): string {
const n: number = !isFinite(+num) ? 0 : +num;
const prec: number = !isFinite(+decimals) ? 0 : Math.abs(decimals);
const sep: string = thousandsSep === null ? ' ' : thousandsSep;
const dec: string = decPoint === null ? ',' : decPoint;
const s: string[] = (prec ? Helpers.toFixed(n, prec) : Math.round(n)).toString().split('.');
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || '';
s[1] += new Array(prec - s[1].length + 1).join('0');
}
return s.join(dec);
}
static serializeObject(formElement: JQuery): Record<string, unknown> {
const formArray: Record<string, unknown> = formElement.serializeObject() as Record<string, unknown>;
formElement.find('[type=checkbox]:not(:checked)').each((index: number, element: HTMLElement): void => {
formArray[$(element).attr('name')] = '';
});
return formArray;
}
static parseFloat(val: string): number {
const num: number = parseFloat(val);
if (typeof num === 'number' && !isNaN(num)) {
return num;
} else {
return 0;
}
}
static trackEvent(params: IGaEventParams): void {
if (typeof ga !== 'undefined') {
ga('send', {
eventAction: params.action,
eventCategory: params.category,
eventLabel: params.label,
eventValue: params.value,
hitType: 'event',
});
}
if (typeof gtag !== 'undefined') {
gtag('event', params.action, {
// eslint-disable-next-line @typescript-eslint/naming-convention
event_category: params.category,
// eslint-disable-next-line @typescript-eslint/naming-convention
event_label: params.label,
value: params.value,
});
}
}
static trackPageChange(path: string): void {
if (typeof ga !== 'undefined') {
ga('set', 'page', path);
ga('send', 'pageview');
}
if (typeof gtag !== 'undefined') {
gtag('event', 'screen_view', {
// eslint-disable-next-line @typescript-eslint/naming-convention
screen_name: path,
});
}
}
static convertToInt(value: string | number | undefined): number {
const numeric: number = parseInt('' + value, 10);
return isNaN(numeric) ? 0 : numeric;
}
static init(): void {
// setup defaults variables
Object.keys(Helpers.defaults).forEach((key: string): void => {
if (window.gotoAndPlay[key] === undefined) {
window.gotoAndPlay[key] = Helpers.defaults[key];
}
});
// run after document ready
$((): void => {
// init components
if (window.gotoAndPlay && Object.prototype.hasOwnProperty.call(window.gotoAndPlay, 'components')) {
Object.keys(window.gotoAndPlay.components).forEach((name: string): void => {
const component: unknown = window.gotoAndPlay.components[name];
if (Component.is(component)) {
component.enhance();
}
});
$(document).trigger('enhance');
}
// re-init components after gravity form post render
$(document).on('gform_post_render', (event: JQuery.TriggeredEvent): void => {
$(event.currentTarget).trigger('enhance');
});
// other field logic for gravity
$(document).on('change', '.gchoice input[type="radio"]', (event: JQuery.TriggeredEvent): void => {
const input: JQuery = $(event.currentTarget).parents('.choice-group').find('[value="gf_other_choice"]');
const textField: JQuery = input.parents('.gchoice').find('input[type="text"]');
const element: JQuery = $('[name="' + input.attr('name') + '"]:checked');
if (element.val() === input.val()) {
textField.removeAttr('disabled');
textField.parents('.textfield').removeClass('is-disabled');
textField.trigger('focus');
} else {
textField.attr('disabled', 'disabled');
textField.parents('.textfield').addClass('is-disabled');
}
});
// track ga events
$(document).on('click', '[data-ga-action]', (event: JQuery.TriggeredEvent): void => {
const target: JQuery = $(event.currentTarget);
const value: string | undefined = target.data('gaValue');
Helpers.trackEvent({
action: '' + target.data('gaAction'),
category: '' + target.data('gaCategory'),
label: '' + target.data('gaLabel'),
value: value !== '' && value !== undefined ? Helpers.convertToInt(value) : undefined,
});
});
// add resizing class to body
let resizeTimeout: number;
$(window).on('resize', () => {
$('body').addClass('is-resizing');
clearTimeout(resizeTimeout);
resizeTimeout = window.setTimeout(() => {
$('body').removeClass('is-resizing');
}, 150);
});
});
// personal touch by gotoAndPlay team
if (process.env.NODE_ENV === 'production') {
// eslint-disable-next-line no-console
console.log('%c \n \u221e\u221e\u221e\u221e \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e %cHi there! %c\n \u221e\u221e\u221e \u221e\u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe hope you\'re enjoying our work!%c\n\u221e\u221e \u221e\u221e\u221e\u221e \u221e\u221e\n\u221e\u221e\u221e \u221e\u221e \u221e\u221e\u221e %cWe did our best to bring you this experience!%c \n \u221e\u221e\u221e \u221e\u221e\u221e\n \u221e\u221e\u221e \u221e\u221e\u221e\u221e\u221e %cMade with ♥ by gotoAndPlay%c \n \u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e\u221e \u221e\u221e\u221e \n \u221e\u221e\u221e\u221e \u221e\u221e\u221e', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;', 'color: #353535;', 'color: #1abc9c;');
}
}
}
Helpers.init();