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;
}
#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;
@include bp(sm-min) {
padding: 0 $container-padding-sm;
}
@include bp(xxl-min) {
padding: 0 $container-padding-xxl;
}
}
.h-clearfix {
&:after {
content: '';
display: table;
clear: both;
}
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.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-visually-hidden {
@include visually-hidden;
}
import 'form-serializer';
import Component from '../component/component';
import './helpers.scss';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
globalAnimationsEnabled: false,
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
mousePos: {x: 0, y: 0},
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
/* eslint-disable */ // this lets the breakpoints stay in numerical order, not alphabetical
static bp: { [key: string]: number } = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1440,
xxl: 1920,
};
/* eslint-enable */
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 (!$('body').hasClass('is-scroll-disabled')) {
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 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((): void => {
formArray[$(this).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 get isIE(): boolean | number {
const ua: string = window.navigator.userAgent;
const msie: number = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
const trident: number = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
const rv: number = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
const edge: number = ua.indexOf('Edge/');
if (edge > 0) {
// Edge (IE 12+) => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
static detectScroll(): void {
if ($(window).scrollTop() > 0) {
$('body').addClass('is-scrolled');
} else {
$('body').removeClass('is-scrolled');
}
}
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 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');
});
// 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,
});
});
$(window).on('mousemove', (event: JQuery.MouseMoveEvent) => {
let posx: number = 0;
let posy: number = 0;
if (event.pageX || event.pageY) {
posx = event.pageX;
posy = event.pageY;
} else if (event.clientX || event.clientY) {
posx = event.clientX + $('body')[0].scrollLeft + document.documentElement.scrollLeft;
posy = event.clientY + $('body')[0].scrollTop + document.documentElement.scrollTop;
}
window.gotoAndPlay.mousePos = { x: posx, y: posy };
});
Helpers.detectScroll();
$(window).on('scroll', () => {
Helpers.detectScroll();
});
});
// 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();
Clear floats of child elements.
<div class="h-clearfix ">Helper example</div>
<div class="{{ class }} ">Helper example</div>
{
"language": "en-US",
"class": "h-clearfix"
}
body {
overflow-y: scroll;
}
#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;
@include bp(sm-min) {
padding: 0 $container-padding-sm;
}
@include bp(xxl-min) {
padding: 0 $container-padding-xxl;
}
}
.h-clearfix {
&:after {
content: '';
display: table;
clear: both;
}
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.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-visually-hidden {
@include visually-hidden;
}
import 'form-serializer';
import Component from '../component/component';
import './helpers.scss';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
globalAnimationsEnabled: false,
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
mousePos: {x: 0, y: 0},
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
/* eslint-disable */ // this lets the breakpoints stay in numerical order, not alphabetical
static bp: { [key: string]: number } = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1440,
xxl: 1920,
};
/* eslint-enable */
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 (!$('body').hasClass('is-scroll-disabled')) {
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 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((): void => {
formArray[$(this).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 get isIE(): boolean | number {
const ua: string = window.navigator.userAgent;
const msie: number = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
const trident: number = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
const rv: number = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
const edge: number = ua.indexOf('Edge/');
if (edge > 0) {
// Edge (IE 12+) => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
static detectScroll(): void {
if ($(window).scrollTop() > 0) {
$('body').addClass('is-scrolled');
} else {
$('body').removeClass('is-scrolled');
}
}
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 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');
});
// 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,
});
});
$(window).on('mousemove', (event: JQuery.MouseMoveEvent) => {
let posx: number = 0;
let posy: number = 0;
if (event.pageX || event.pageY) {
posx = event.pageX;
posy = event.pageY;
} else if (event.clientX || event.clientY) {
posx = event.clientX + $('body')[0].scrollLeft + document.documentElement.scrollLeft;
posy = event.clientY + $('body')[0].scrollTop + document.documentElement.scrollTop;
}
window.gotoAndPlay.mousePos = { x: posx, y: posy };
});
Helpers.detectScroll();
$(window).on('scroll', () => {
Helpers.detectScroll();
});
});
// 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;
}
#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;
@include bp(sm-min) {
padding: 0 $container-padding-sm;
}
@include bp(xxl-min) {
padding: 0 $container-padding-xxl;
}
}
.h-clearfix {
&:after {
content: '';
display: table;
clear: both;
}
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.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-visually-hidden {
@include visually-hidden;
}
import 'form-serializer';
import Component from '../component/component';
import './helpers.scss';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
globalAnimationsEnabled: false,
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
mousePos: {x: 0, y: 0},
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
/* eslint-disable */ // this lets the breakpoints stay in numerical order, not alphabetical
static bp: { [key: string]: number } = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1440,
xxl: 1920,
};
/* eslint-enable */
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 (!$('body').hasClass('is-scroll-disabled')) {
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 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((): void => {
formArray[$(this).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 get isIE(): boolean | number {
const ua: string = window.navigator.userAgent;
const msie: number = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
const trident: number = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
const rv: number = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
const edge: number = ua.indexOf('Edge/');
if (edge > 0) {
// Edge (IE 12+) => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
static detectScroll(): void {
if ($(window).scrollTop() > 0) {
$('body').addClass('is-scrolled');
} else {
$('body').removeClass('is-scrolled');
}
}
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 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');
});
// 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,
});
});
$(window).on('mousemove', (event: JQuery.MouseMoveEvent) => {
let posx: number = 0;
let posy: number = 0;
if (event.pageX || event.pageY) {
posx = event.pageX;
posy = event.pageY;
} else if (event.clientX || event.clientY) {
posx = event.clientX + $('body')[0].scrollLeft + document.documentElement.scrollLeft;
posy = event.clientY + $('body')[0].scrollTop + document.documentElement.scrollTop;
}
window.gotoAndPlay.mousePos = { x: posx, y: posy };
});
Helpers.detectScroll();
$(window).on('scroll', () => {
Helpers.detectScroll();
});
});
// 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;
}
#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;
@include bp(sm-min) {
padding: 0 $container-padding-sm;
}
@include bp(xxl-min) {
padding: 0 $container-padding-xxl;
}
}
.h-clearfix {
&:after {
content: '';
display: table;
clear: both;
}
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.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-visually-hidden {
@include visually-hidden;
}
import 'form-serializer';
import Component from '../component/component';
import './helpers.scss';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
globalAnimationsEnabled: false,
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
mousePos: {x: 0, y: 0},
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
/* eslint-disable */ // this lets the breakpoints stay in numerical order, not alphabetical
static bp: { [key: string]: number } = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1440,
xxl: 1920,
};
/* eslint-enable */
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 (!$('body').hasClass('is-scroll-disabled')) {
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 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((): void => {
formArray[$(this).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 get isIE(): boolean | number {
const ua: string = window.navigator.userAgent;
const msie: number = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
const trident: number = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
const rv: number = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
const edge: number = ua.indexOf('Edge/');
if (edge > 0) {
// Edge (IE 12+) => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
static detectScroll(): void {
if ($(window).scrollTop() > 0) {
$('body').addClass('is-scrolled');
} else {
$('body').removeClass('is-scrolled');
}
}
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 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');
});
// 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,
});
});
$(window).on('mousemove', (event: JQuery.MouseMoveEvent) => {
let posx: number = 0;
let posy: number = 0;
if (event.pageX || event.pageY) {
posx = event.pageX;
posy = event.pageY;
} else if (event.clientX || event.clientY) {
posx = event.clientX + $('body')[0].scrollLeft + document.documentElement.scrollLeft;
posy = event.clientY + $('body')[0].scrollTop + document.documentElement.scrollTop;
}
window.gotoAndPlay.mousePos = { x: posx, y: posy };
});
Helpers.detectScroll();
$(window).on('scroll', () => {
Helpers.detectScroll();
});
});
// 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();
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;
}
#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;
@include bp(sm-min) {
padding: 0 $container-padding-sm;
}
@include bp(xxl-min) {
padding: 0 $container-padding-xxl;
}
}
.h-clearfix {
&:after {
content: '';
display: table;
clear: both;
}
}
.h-pull-left {
float: left;
}
.h-pull-right {
float: right;
}
.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-visually-hidden {
@include visually-hidden;
}
import 'form-serializer';
import Component from '../component/component';
import './helpers.scss';
export interface IGaEventParams {
category: string;
action: string;
label?: string;
value?: number;
}
export default class Helpers {
static defaults: IGotoAndPlay = {
ajax: {
isEnabled: false,
keptBodyClasses: [],
templateName: '',
},
ajaxPath: '',
assetsPath: '',
components: {},
cookieDomain: '',
cookiePath: '',
globalAnimationsEnabled: false,
googleMapsApiKey: null,
headerOffset: 0,
loggedIn: false,
mousePos: {x: 0, y: 0},
nonce: '',
notifications: [],
sitePath: '',
svgPath: '',
templatePath: '',
version: '',
};
/* eslint-disable */ // this lets the breakpoints stay in numerical order, not alphabetical
static bp: { [key: string]: number } = {
xs: 375,
sm: 680,
md: 1000,
lg: 1200,
xl: 1440,
xxl: 1920,
};
/* eslint-enable */
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 (!$('body').hasClass('is-scroll-disabled')) {
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 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((): void => {
formArray[$(this).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 get isIE(): boolean | number {
const ua: string = window.navigator.userAgent;
const msie: number = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}
const trident: number = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
const rv: number = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
}
const edge: number = ua.indexOf('Edge/');
if (edge > 0) {
// Edge (IE 12+) => return version number
return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
}
// other browser
return false;
}
static detectScroll(): void {
if ($(window).scrollTop() > 0) {
$('body').addClass('is-scrolled');
} else {
$('body').removeClass('is-scrolled');
}
}
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 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');
});
// 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,
});
});
$(window).on('mousemove', (event: JQuery.MouseMoveEvent) => {
let posx: number = 0;
let posy: number = 0;
if (event.pageX || event.pageY) {
posx = event.pageX;
posy = event.pageY;
} else if (event.clientX || event.clientY) {
posx = event.clientX + $('body')[0].scrollLeft + document.documentElement.scrollLeft;
posy = event.clientY + $('body')[0].scrollTop + document.documentElement.scrollTop;
}
window.gotoAndPlay.mousePos = { x: posx, y: posy };
});
Helpers.detectScroll();
$(window).on('scroll', () => {
Helpers.detectScroll();
});
});
// 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();