Last active
February 13, 2018 14:16
-
-
Save darcher-/1a6e9861913ff830449373dd2f5bb5d9 to your computer and use it in GitHub Desktop.
Panel and Landing page javascript includes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* classList Polyfill: https://gist.github.com/k-gun/c2ea7c49edf7b757fe9561ba37cb19ca */ ; | |
(function() { | |
var trim = function(s) { | |
return s.replace(/^\s+|\s+$/g, ''); | |
}, | |
regExp = function(name) { | |
return new RegExp('(^|\\s+)' + name + '(\\s+|$)'); | |
}, | |
forEach = function(list, fn, scope) { | |
for (var i = 0; i < list.length; i++) { | |
fn.call(scope, list[i]); | |
} | |
}; | |
function ClassList(element) { | |
this.element = element; | |
} | |
ClassList.prototype = { | |
add: function() { | |
forEach(arguments, function(name) { | |
if (!this.contains(name)) { | |
this.element.className = trim(this.element.className + ' ' + name); | |
} | |
}, this); | |
}, | |
remove: function() { | |
forEach(arguments, function(name) { | |
this.element.className = trim(this.element.className.replace(regExp(name), ' ')); | |
}, this); | |
}, | |
toggle: function(name) { | |
return this.contains(name) ? (this.remove(name), false) : (this.add(name), true); | |
}, | |
contains: function(name) { | |
return regExp(name).test(this.element.className); | |
}, | |
item: function(i) { | |
return this.element.className.split(/\s+/)[i] || null; | |
}, | |
replace: function(oldName, newName) { | |
this.remove(oldName), this.add(newName); | |
} | |
}; | |
if (!('classList' in Element.prototype)) { | |
Object.defineProperty(Element.prototype, 'classList', { | |
get: function() { | |
return new ClassList(this); | |
} | |
}); | |
} | |
if (window.DOMTokenList && !DOMTokenList.prototype.replace) { | |
DOMTokenList.prototype.replace = ClassList.prototype.replace; | |
} | |
})(); | |
/* clear console errors */ | |
console.clear(); | |
/* Anonymous, self-executing Function */ | |
/* | |
if you're using jQuery: | |
(function($, Z, undefined){ | |
*/ | |
(function(Z, undefined) { | |
/* global variables & private punctions */ | |
var d = document, | |
/*! these are the 3 required elements to run these functions */ | |
// update below to "z_wrapper" as needed. | |
wrapper = d.getElementById('zWrapper'), | |
// the following is a dynamically generated ID and should NOT change. | |
form = d.getElementById('zFormId'), | |
copyright = d.getElementById('zCopyrightYear'), | |
viewportMeta = d.querySelectorAll('meta[name=viewport]')[0], | |
required = d.querySelectorAll('[required="required"]'), | |
loopFn = function(collection, callback, scope) { | |
/* loop arrays/objects/collections/elements/etc. use like forEach() or $.each() */ | |
if (Object.prototype.toString.call(collection) === '[object Object]') { | |
for (var property in collection) { | |
if (Object.prototype.hasOwnProperty.call(collection, property)) { | |
callback.call(scope, collection[property], property, collection); | |
} | |
} | |
} else { | |
for (var index = 0; index < collection.length; index++) { | |
callback.call(scope, collection[index], index, collection); | |
} | |
} | |
}, | |
debounce = function(func, wait, immediate) { | |
/* wait for event to finish before execution---prevents event bubbling */ | |
var timeout; | |
return function() { | |
var context = this, | |
args = arguments; | |
clearTimeout(timeout); | |
timeout = setTimeout(function() { | |
timeout = null; | |
if (!immediate) { | |
func.apply(context, args); | |
} | |
}, wait); | |
if (immediate && !timeout) { | |
func.apply(context, args); | |
} | |
}; | |
}, | |
resizeWaitFn = debounce(function() { | |
/* set in own variable to run on resize/load within Z.landingFn()*/ | |
Z.wrapWidth(wrapper); | |
}, 66), | |
createMetaFn = function() { | |
/* create viewport meta tag to be used */ | |
var meta = d.createElement('meta'); | |
meta.name = "viewport"; | |
meta.content = "width=device-width, initial-scale=1, shrink-to-fit=no"; | |
d.head.appendChild(meta); | |
}, | |
elNodeExistsFn = function(nodeList, Fn) { | |
/* ensure element node exists, use when using d.querySelectorAll() */ | |
if (nodeList.length) { | |
return Fn; | |
} | |
}, | |
elExistsFn = function(el, Fn) { | |
/* ensure element exists, use when using d.querySelector() */ | |
if (el) { | |
return Fn; | |
} | |
}, | |
elReplaceFn = function(el, Fn) { | |
/* ensure element exists */ | |
if (el) { | |
el.parentNode.removeChild(el); | |
return Fn; | |
} else { | |
return Fn; | |
} | |
}; | |
/*! Public Functions */ | |
Z.wrapWidth = function(el) { | |
/* update class on wrapper based on wrapper element size, panels require this as they aren't dependend on window widths in most cases */ | |
var elWidth = el.offsetWidth; | |
el.classList.toggle('zxl', elWidth > 1200); | |
el.classList.toggle('zlg', elWidth > 992);// && (elWidth < 1199)); | |
el.classList.toggle('zmd', elWidth > 768);// && (elWidth < 991)); | |
el.classList.toggle('zsm', elWidth > 544);// && (elWidth < 767)); | |
el.classList.toggle('zxs', elWidth < 543); | |
/* this is more for debugging, but adds data attribute to show width */ | |
el.setAttribute('data-px-width', elWidth); | |
}; | |
Z.copyrightYearFn = function(c) { | |
// get and insert current year | |
var a = new Date(), | |
b = a.getFullYear(); | |
c.innerHTML = b; | |
}; | |
Z.metaViewportUpdate = function(el) { | |
/* override viewport meta if present, inject if not present */ | |
elReplaceFn(el, createMetaFn()); | |
}; | |
Z.chromeFormReset = function(el) { | |
// check for Chrome Browser | |
if (/Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor)) { | |
// if Chrome clear form fields to avoid chrome bug | |
setTimeout(function() { | |
el.reset(); | |
}, 250); | |
} | |
}; | |
Z.fullfilledFormFn = function(el) { | |
/* form validation: allow html5 validation, prevent empty fields */ | |
var button = form.querySelector('button'), | |
// store onclick value to add back after form validates | |
clickAction = button.getAttribute('onclick'), | |
cleanseBtnFn = function(btn) { | |
// remove onclick so html5 validation can trigger | |
btn.removeAttribute('onclick'); | |
}; | |
// prevent button cleansing if no required fields | |
if (required.length) { | |
// cleanse button if required found | |
cleanseBtnFn(button); | |
} | |
loopFn(required, function(index) { | |
/*! | |
this works on initial load only in chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=669724 | |
- chromeFormReset() function is to circumvent this bug in chrome, it removes shadow values by form reset. | |
*/ | |
if ((!index.value || !index.checkValidity()) || index.value === 'undefined') { | |
// set as invalid | |
index.setAttribute('aria-invalid', 'true'); | |
// add parent class to toggle displayed validation (use CSS to add styling) | |
index.parentNode.classList.add('invalid'); | |
} else { | |
// set as valid | |
index.setAttribute('aria-invalid', 'false'); | |
// add parent class to toggle displayed validation (use CSS to add styling) | |
index.parentNode.classList.add('valid'); | |
} | |
index.addEventListener('input', function() { | |
// replace aria-states on input | |
if ((!this.value || !this.checkValidity()) || this.value === 'undefined') { | |
// set as invalid | |
this.setAttribute('aria-invalid', 'true'); | |
// replace parent class to toggle displayed validation (use CSS to add styling) | |
this.parentNode.classList.replace('valid', 'invalid'); | |
} else { | |
// set as valid | |
this.setAttribute('aria-invalid', 'false'); | |
// replace parent class to toggle displayed validation (use CSS to add styling) | |
this.parentNode.classList.replace('invalid', 'valid'); | |
} | |
// find valid inputs via aria-state | |
var valid = d.querySelectorAll('[aria-invalid="false"]'); | |
// if valid amount is same as required amount add submit function back. | |
if (valid.length === required.length) { | |
button.setAttribute('onclick', clickAction); | |
} else { | |
// if returns to invalid, remove onClick from button again | |
cleanseBtnFn(button); | |
} | |
}); | |
}); | |
}; | |
Z.cleanFn = function(node) { | |
/* clean whitespace and empty elements in DOM */ | |
for (var n = 0; n < node.childNodes.length; n++) { | |
var child = node.childNodes[n]; | |
if (child.nodeType === 8 || (child.nodeType === 3 && !/\S/.test(child.nodeValue))) { | |
node.removeChild(child); | |
n--; | |
} else if (child.nodeType === 1) { | |
Z.cleanFn(child); | |
} | |
} | |
}; | |
Z.includesFn = function() { | |
/*! houses all private/public functions into one call */ | |
elExistsFn(form, this.chromeFormReset(form)); | |
elExistsFn(form, this.fullfilledFormFn(form)); | |
elExistsFn(copyright, this.copyrightYearFn(copyright)); | |
// check onload and resize | |
elExistsFn(wrapper, resizeWaitFn()); | |
window.addEventListener("resize", resizeWaitFn, false); | |
this.metaViewportUpdate(viewportMeta); | |
this.cleanFn(d); | |
}; | |
/* | |
if you're using jQuery: | |
}(jQuery, window.Z = window.Z || {})); | |
*/ | |
}(window.Z = window.Z || {})); | |
/* use below to init: Or only call functions that are needed, via Z.cleanFn(document) or any of the other public functions, etc.*/ | |
//addZiftLoadEvent(function() { Z.includesFn(); }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hosted at: //s3.amazonaws.com/static.ziftsolutions.com/codebase/js/zIncludes.js