;(function(root, factory) { if (typeof define === 'function' && define.amd) { define([], function() { return (factory()); }); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.whatinput = factory(); } } (this, function() { 'use strict'; /* --------------- variables --------------- */ // array of actively pressed keys var activekeys = []; // cache document.body var body = document.body; // boolean: true if touch buffer timer is running var buffer = false; // the last used input type var currentinput = null; // array of form elements that take keyboard input var forminputs = [ 'input', 'select', 'textarea' ]; // user-set flag to allow typing in form fields to be recorded var formtyping = body.hasattribute('data-whatinput-formtyping'); // mapping of events to input types var inputmap = { 'keydown': 'keyboard', 'mousedown': 'mouse', 'mouseenter': 'mouse', 'touchstart': 'touch', 'pointerdown': 'pointer', 'mspointerdown': 'pointer' }; // array of all used input types var inputtypes = []; // mapping of key codes to common name var keymap = { 9: 'tab', 13: 'enter', 16: 'shift', 27: 'esc', 32: 'space', 37: 'left', 38: 'up', 39: 'right', 40: 'down' }; // map of ie 10 pointer events var pointermap = { 2: 'touch', 3: 'touch', // treat pen like touch 4: 'mouse' }; // touch buffer timer var timer; /* --------------- functions --------------- */ function bufferinput(event) { cleartimeout(timer); setinput(event); buffer = true; timer = settimeout(function() { buffer = false; }, 1000); } function immediateinput(event) { if (!buffer) setinput(event); } function setinput(event) { var eventkey = key(event); var eventtarget = target(event); var value = inputmap[event.type]; if (value === 'pointer') value = pointertype(event); if (currentinput !== value) { if ( // only if the user flag isn't set !formtyping && // only if currentinput has a value currentinput && // only if the input is `keyboard` value === 'keyboard' && // not if the key is `tab` keymap[eventkey] !== 'tab' && // only if the target is one of the elements in `forminputs` forminputs.indexof(eventtarget.nodename.tolowercase()) >= 0 ) { // ignore keyboard typing on form elements } else { currentinput = value; body.setattribute('data-whatinput', currentinput); if (inputtypes.indexof(currentinput) === -1) inputtypes.push(currentinput); } } if (value === 'keyboard') logkeys(eventkey); } function key(event) { return (event.keycode) ? event.keycode : event.which; } function target(event) { return event.target || event.srcelement; } function pointertype(event) { return (typeof event.pointertype === 'number') ? pointermap[event.pointertype] : event.pointertype; } // keyboard logging function logkeys(eventkey) { if (activekeys.indexof(keymap[eventkey]) === -1 && keymap[eventkey]) activekeys.push(keymap[eventkey]); } function unlogkeys(event) { var eventkey = key(event); var arraypos = activekeys.indexof(keymap[eventkey]); if (arraypos !== -1) activekeys.splice(arraypos, 1); } function bindevents() { // pointer/mouse var mouseevent = 'mousedown'; if (window.pointerevent) { mouseevent = 'pointerdown'; } else if (window.mspointerevent) { mouseevent = 'mspointerdown'; } body.addeventlistener(mouseevent, immediateinput); body.addeventlistener('mouseenter', immediateinput); // touch if ('ontouchstart' in window) { body.addeventlistener('touchstart', bufferinput); } // keyboard body.addeventlistener('keydown', immediateinput); document.addeventlistener('keyup', unlogkeys); } /* --------------- init don't start script unless browser cuts the mustard, also passes if polyfills are used --------------- */ if ('addeventlistener' in window && array.prototype.indexof) { bindevents(); } /* --------------- api --------------- */ return { // returns string: the current input type ask: function() { return currentinput; }, // returns array: currently pressed keys keys: function() { return activekeys; }, // returns array: all the detected input types types: function() { return inputtypes; }, // accepts string: manually set the input type set: setinput }; })); !function ($) { "use strict"; var foundation_version = '6.2.2'; // global foundation object // this is attached to the window, or used as a module for amd/browserify var foundation = { version: foundation_version, /** * stores initialized plugins. */ _plugins: {}, /** * stores generated unique ids for plugin instances */ _uuids: [], /** * returns a boolean for rtl support */ rtl: function () { return $('html').attr('dir') === 'rtl'; }, /** * defines a foundation plugin, adding it to the `foundation` namespace and the list of plugins to initialize when reflowing. * @param {object} plugin - the constructor of the plugin. */ plugin: function (plugin, name) { // object key to use when adding to global foundation object // examples: foundation.reveal, foundation.offcanvas var classname = name || functionname(plugin); // object key to use when storing the plugin, also used to create the identifying data attribute for the plugin // examples: data-reveal, data-off-canvas var attrname = hyphenate(classname); // add to the foundation object and the plugins list (for reflowing) this._plugins[attrname] = this[classname] = plugin; }, /** * @function * populates the _uuids array with pointers to each individual plugin instance. * adds the `zfplugin` data-attribute to programmatically created plugins to allow use of $(selector).foundation(method) calls. * also fires the initialization event for each plugin, consolidating repetitive code. * @param {object} plugin - an instance of a plugin, usually `this` in context. * @param {string} name - the name of the plugin, passed as a camelcased string. * @fires plugin#init */ registerplugin: function (plugin, name) { var pluginname = name ? hyphenate(name) : functionname(plugin.constructor).tolowercase(); plugin.uuid = this.getyodigits(6, pluginname); if (!plugin.$element.attr('data-' + pluginname)) { plugin.$element.attr('data-' + pluginname, plugin.uuid); } if (!plugin.$element.data('zfplugin')) { plugin.$element.data('zfplugin', plugin); } /** * fires when the plugin has initialized. * @event plugin#init */ plugin.$element.trigger('init.zf.' + pluginname); this._uuids.push(plugin.uuid); return; }, /** * @function * removes the plugins uuid from the _uuids array. * removes the zfplugin data attribute, as well as the data-plugin-name attribute. * also fires the destroyed event for the plugin, consolidating repetitive code. * @param {object} plugin - an instance of a plugin, usually `this` in context. * @fires plugin#destroyed */ unregisterplugin: function (plugin) { var pluginname = hyphenate(functionname(plugin.$element.data('zfplugin').constructor)); this._uuids.splice(this._uuids.indexof(plugin.uuid), 1); plugin.$element.removeattr('data-' + pluginname).removedata('zfplugin') /** * fires when the plugin has been destroyed. * @event plugin#destroyed */ .trigger('destroyed.zf.' + pluginname); for (var prop in plugin) { plugin[prop] = null; //clean up script to prep for garbage collection. } return; }, /** * @function * causes one or more active plugins to re-initialize, resetting event listeners, recalculating positions, etc. * @param {string} plugins - optional string of an individual plugin key, attained by calling `$(element).data('pluginname')`, or string of a plugin class i.e. `'dropdown'` * @default if no argument is passed, reflow all currently active plugins. */ reinit: function (plugins) { var isjq = plugins instanceof $; try { if (isjq) { plugins.each(function () { $(this).data('zfplugin')._init(); }); } else { var type = typeof plugins, _this = this, fns = { 'object': function (plgs) { plgs.foreach(function (p) { p = hyphenate(p); $('[data-' + p + ']').foundation('_init'); }); }, 'string': function () { plugins = hyphenate(plugins); $('[data-' + plugins + ']').foundation('_init'); }, 'undefined': function () { this['object'](object.keys(_this._plugins)); } }; fns[type](plugins); } } catch (err) { console.error(err); } finally { return plugins; } }, /** * returns a random base-36 uid with namespacing * @function * @param {number} length - number of random base-36 digits desired. increase for more random strings. * @param {string} namespace - name of plugin to be incorporated in uid, optional. * @default {string} '' - if no plugin name is provided, nothing is appended to the uid. * @returns {string} - unique id */ getyodigits: function (length, namespace) { length = length || 6; return math.round(math.pow(36, length + 1) - math.random() * math.pow(36, length)).tostring(36).slice(1) + (namespace ? '-' + namespace : ''); }, /** * initialize plugins on any elements within `elem` (and `elem` itself) that aren't already initialized. * @param {object} elem - jquery object containing the element to check inside. also checks the element itself, unless it's the `document` object. * @param {string|array} plugins - a list of plugins to initialize. leave this out to initialize everything. */ reflow: function (elem, plugins) { // if plugins is undefined, just grab everything if (typeof plugins === 'undefined') { plugins = object.keys(this._plugins); } // if plugins is a string, convert it to an array with one item else if (typeof plugins === 'string') { plugins = [plugins]; } var _this = this; // iterate through each plugin $.each(plugins, function (i, name) { // get the current plugin var plugin = _this._plugins[name]; // localize the search to all elements inside elem, as well as elem itself, unless elem === document var $elem = $(elem).find('[data-' + name + ']').addback('[data-' + name + ']'); // for each plugin found, initialize it $elem.each(function () { var $el = $(this), opts = {}; // don't double-dip on plugins if ($el.data('zfplugin')) { console.warn("tried to initialize " + name + " on an element that already has a foundation plugin."); return; } if ($el.attr('data-options')) { var thing = $el.attr('data-options').split(';').foreach(function (e, i) { var opt = e.split(':').map(function (el) { return el.trim(); }); if (opt[0]) opts[opt[0]] = parsevalue(opt[1]); }); } try { $el.data('zfplugin', new plugin($(this), opts)); } catch (er) { console.error(er); } finally { return; } }); }); }, getfnname: functionname, transitionend: function ($elem) { var transitions = { 'transition': 'transitionend', 'webkittransition': 'webkittransitionend', 'moztransition': 'transitionend', 'otransition': 'otransitionend' }; var elem = document.createelement('div'), end; for (var t in transitions) { if (typeof elem.style[t] !== 'undefined') { end = transitions[t]; } } if (end) { return end; } else { end = settimeout(function () { $elem.triggerhandler('transitionend', [$elem]); }, 1); return 'transitionend'; } } }; foundation.util = { /** * function for applying a debounce effect to a function call. * @function * @param {function} func - function to be called at end of timeout. * @param {number} delay - time in ms to delay the call of `func`. * @returns function */ throttle: function (func, delay) { var timer = null; return function () { var context = this, args = arguments; if (timer === null) { timer = settimeout(function () { func.apply(context, args); timer = null; }, delay); } }; } }; // todo: consider not making this a jquery function // todo: need way to reflow vs. re-initialize /** * the foundation jquery method. * @param {string|array} method - an action to perform on the current jquery object. */ var foundation = function (method) { var type = typeof method, $meta = $('meta.foundation-mq'), $nojs = $('.no-js'); if (!$meta.length) { $('').appendto(document.head); } if ($nojs.length) { $nojs.removeclass('no-js'); } if (type === 'undefined') { //needs to initialize the foundation object, or an individual plugin. foundation.mediaquery._init(); foundation.reflow(this); } else if (type === 'string') { //an individual method to invoke on a plugin or group of plugins var args = array.prototype.slice.call(arguments, 1); //collect all the arguments, if necessary var plugclass = this.data('zfplugin'); //determine the class of plugin if (plugclass !== undefined && plugclass[method] !== undefined) { //make sure both the class and method exist if (this.length === 1) { //if there's only one, call it directly. plugclass[method].apply(plugclass, args); } else { this.each(function (i, el) { //otherwise loop through the jquery collection and invoke the method on each plugclass[method].apply($(el).data('zfplugin'), args); }); } } else { //error for no class or no method throw new referenceerror("we're sorry, '" + method + "' is not an available method for " + (plugclass ? functionname(plugclass) : 'this element') + '.'); } } else { //error for invalid argument type throw new typeerror('we\'re sorry, ' + type + ' is not a valid parameter. you must use a string representing the method you wish to invoke.'); } return this; }; window.foundation = foundation; $.fn.foundation = foundation; // polyfill for requestanimationframe (function () { if (!date.now || !window.date.now) window.date.now = date.now = function () { return new date().gettime(); }; var vendors = ['webkit', 'moz']; for (var i = 0; i < vendors.length && !window.requestanimationframe; ++i) { var vp = vendors[i]; window.requestanimationframe = window[vp + 'requestanimationframe']; window.cancelanimationframe = window[vp + 'cancelanimationframe'] || window[vp + 'cancelrequestanimationframe']; } if (/ip(ad|hone|od).*os 6/.test(window.navigator.useragent) || !window.requestanimationframe || !window.cancelanimationframe) { var lasttime = 0; window.requestanimationframe = function (callback) { var now = date.now(); var nexttime = math.max(lasttime + 16, now); return settimeout(function () { callback(lasttime = nexttime); }, nexttime - now); }; window.cancelanimationframe = cleartimeout; } /** * polyfill for performance.now, required by raf */ if (!window.performance || !window.performance.now) { window.performance = { start: date.now(), now: function () { return date.now() - this.start; } }; } })(); if (!function.prototype.bind) { function.prototype.bind = function (othis) { if (typeof this !== 'function') { // closest thing possible to the ecmascript 5 // internal iscallable function throw new typeerror('function.prototype.bind - what is trying to be bound is not callable'); } var aargs = array.prototype.slice.call(arguments, 1), ftobind = this, fnop = function () {}, fbound = function () { return ftobind.apply(this instanceof fnop ? this : othis, aargs.concat(array.prototype.slice.call(arguments))); }; if (this.prototype) { // native functions don't have a prototype fnop.prototype = this.prototype; } fbound.prototype = new fnop(); return fbound; }; } // polyfill to get the name of a function in ie9 function functionname(fn) { if (function.prototype.name === undefined) { var funcnameregex = /function\s([^(]{1,})\(/; var results = funcnameregex.exec(fn.tostring()); return results && results.length > 1 ? results[1].trim() : ""; } else if (fn.prototype === undefined) { return fn.constructor.name; } else { return fn.prototype.constructor.name; } } function parsevalue(str) { if (/true/.test(str)) return true;else if (/false/.test(str)) return false;else if (!isnan(str * 1)) return parsefloat(str); return str; } // convert pascalcase to kebab-case // thank you: http://stackoverflow.com/a/8955580 function hyphenate(str) { return str.replace(/([a-z])([a-z])/g, '$1-$2').tolowercase(); } }(jquery); 'use strict'; !function ($) { foundation.box = { imnottouchingyou: imnottouchingyou, getdimensions: getdimensions, getoffsets: getoffsets }; /** * compares the dimensions of an element to a container and determines collision events with container. * @function * @param {jquery} element - jquery object to test for collisions. * @param {jquery} parent - jquery object to use as bounding container. * @param {boolean} lronly - set to true to check left and right values only. * @param {boolean} tbonly - set to true to check top and bottom values only. * @default if no parent object passed, detects collisions with `window`. * @returns {boolean} - true if collision free, false if a collision in any direction. */ function imnottouchingyou(element, parent, lronly, tbonly) { var eledims = getdimensions(element), top, bottom, left, right; if (parent) { var pardims = getdimensions(parent); bottom = eledims.offset.top + eledims.height <= pardims.height + pardims.offset.top; top = eledims.offset.top >= pardims.offset.top; left = eledims.offset.left >= pardims.offset.left; right = eledims.offset.left + eledims.width <= pardims.width + pardims.offset.left; } else { bottom = eledims.offset.top + eledims.height <= eledims.windowdims.height + eledims.windowdims.offset.top; top = eledims.offset.top >= eledims.windowdims.offset.top; left = eledims.offset.left >= eledims.windowdims.offset.left; right = eledims.offset.left + eledims.width <= eledims.windowdims.width; } var alldirs = [bottom, top, left, right]; if (lronly) { return left === right === true; } if (tbonly) { return top === bottom === true; } return alldirs.indexof(false) === -1; }; /** * uses native methods to return an object of dimension values. * @function * @param {jquery || html} element - jquery object or dom element for which to get the dimensions. can be any element other that document or window. * @returns {object} - nested object of integer pixel values * todo - if element is window, return only those values. */ function getdimensions(elem, test) { elem = elem.length ? elem[0] : elem; if (elem === window || elem === document) { throw new error("i'm sorry, dave. i'm afraid i can't do that."); } var rect = elem.getboundingclientrect(), parrect = elem.parentnode.getboundingclientrect(), winrect = document.body.getboundingclientrect(), winy = window.pageyoffset, winx = window.pagexoffset; return { width: rect.width, height: rect.height, offset: { top: rect.top + winy, left: rect.left + winx }, parentdims: { width: parrect.width, height: parrect.height, offset: { top: parrect.top + winy, left: parrect.left + winx } }, windowdims: { width: winrect.width, height: winrect.height, offset: { top: winy, left: winx } } }; } /** * returns an object of top and left integer pixel values for dynamically rendered elements, * such as: tooltip, reveal, and dropdown * @function * @param {jquery} element - jquery object for the element being positioned. * @param {jquery} anchor - jquery object for the element's anchor point. * @param {string} position - a string relating to the desired position of the element, relative to it's anchor * @param {number} voffset - integer pixel value of desired vertical separation between anchor and element. * @param {number} hoffset - integer pixel value of desired horizontal separation between anchor and element. * @param {boolean} isoverflow - if a collision event is detected, sets to true to default the element to full width - any desired offset. * todo alter/rewrite to work with `em` values as well/instead of pixels */ function getoffsets(element, anchor, position, voffset, hoffset, isoverflow) { var $eledims = getdimensions(element), $anchordims = anchor ? getdimensions(anchor) : null; switch (position) { case 'top': return { left: foundation.rtl() ? $anchordims.offset.left - $eledims.width + $anchordims.width : $anchordims.offset.left, top: $anchordims.offset.top - ($eledims.height + voffset) }; break; case 'left': return { left: $anchordims.offset.left - ($eledims.width + hoffset), top: $anchordims.offset.top }; break; case 'right': return { left: $anchordims.offset.left + $anchordims.width + hoffset, top: $anchordims.offset.top }; break; case 'center top': return { left: $anchordims.offset.left + $anchordims.width / 2 - $eledims.width / 2, top: $anchordims.offset.top - ($eledims.height + voffset) }; break; case 'center bottom': return { left: isoverflow ? hoffset : $anchordims.offset.left + $anchordims.width / 2 - $eledims.width / 2, top: $anchordims.offset.top + $anchordims.height + voffset }; break; case 'center left': return { left: $anchordims.offset.left - ($eledims.width + hoffset), top: $anchordims.offset.top + $anchordims.height / 2 - $eledims.height / 2 }; break; case 'center right': return { left: $anchordims.offset.left + $anchordims.width + hoffset + 1, top: $anchordims.offset.top + $anchordims.height / 2 - $eledims.height / 2 }; break; case 'center': return { left: $eledims.windowdims.offset.left + $eledims.windowdims.width / 2 - $eledims.width / 2, top: $eledims.windowdims.offset.top + $eledims.windowdims.height / 2 - $eledims.height / 2 }; break; case 'reveal': return { left: ($eledims.windowdims.width - $eledims.width) / 2, top: $eledims.windowdims.offset.top + voffset }; case 'reveal full': return { left: $eledims.windowdims.offset.left, top: $eledims.windowdims.offset.top }; break; case 'left bottom': return { left: $anchordims.offset.left - ($eledims.width + hoffset), top: $anchordims.offset.top + $anchordims.height }; break; case 'right bottom': return { left: $anchordims.offset.left + $anchordims.width + hoffset - $eledims.width, top: $anchordims.offset.top + $anchordims.height }; break; default: return { left: foundation.rtl() ? $anchordims.offset.left - $eledims.width + $anchordims.width : $anchordims.offset.left, top: $anchordims.offset.top + $anchordims.height + voffset }; } } }(jquery); /******************************************* * * * this util was created by marius olbertz * * please thank marius on github /owlbertz * * or the web http://www.mariusolbertz.de/ * * * ******************************************/ 'use strict'; !function ($) { var keycodes = { 9: 'tab', 13: 'enter', 27: 'escape', 32: 'space', 37: 'arrow_left', 38: 'arrow_up', 39: 'arrow_right', 40: 'arrow_down' }; var commands = {}; var keyboard = { keys: getkeycodes(keycodes), /** * parses the (keyboard) event and returns a string that represents its key * can be used like foundation.parsekey(event) === foundation.keys.space * @param {event} event - the event generated by the event handler * @return string key - string that represents the key pressed */ parsekey: function (event) { var key = keycodes[event.which || event.keycode] || string.fromcharcode(event.which).touppercase(); if (event.shiftkey) key = 'shift_' + key; if (event.ctrlkey) key = 'ctrl_' + key; if (event.altkey) key = 'alt_' + key; return key; }, /** * handles the given (keyboard) event * @param {event} event - the event generated by the event handler * @param {string} component - foundation component's name, e.g. slider or reveal * @param {objects} functions - collection of functions that are to be executed */ handlekey: function (event, component, functions) { var commandlist = commands[component], keycode = this.parsekey(event), cmds, command, fn; if (!commandlist) return console.warn('component not defined!'); if (typeof commandlist.ltr === 'undefined') { // this component does not differentiate between ltr and rtl cmds = commandlist; // use plain list } else { // merge ltr and rtl: if document is rtl, rtl overwrites ltr and vice versa if (foundation.rtl()) cmds = $.extend({}, commandlist.ltr, commandlist.rtl);else cmds = $.extend({}, commandlist.rtl, commandlist.ltr); } command = cmds[keycode]; fn = functions[command]; if (fn && typeof fn === 'function') { // execute function if exists var returnvalue = fn.apply(); if (functions.handled || typeof functions.handled === 'function') { // execute function when event was handled functions.handled(returnvalue); } } else { if (functions.unhandled || typeof functions.unhandled === 'function') { // execute function when event was not handled functions.unhandled(); } } }, /** * finds all focusable elements within the given `$element` * @param {jquery} $element - jquery object to search within * @return {jquery} $focusable - all focusable elements within `$element` */ findfocusable: function ($element) { return $element.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').filter(function () { if (!$(this).is(':visible') || $(this).attr('tabindex') < 0) { return false; } //only have visible elements and those that have a tabindex greater or equal 0 return true; }); }, /** * returns the component name name * @param {object} component - foundation component, e.g. slider or reveal * @return string componentname */ register: function (componentname, cmds) { commands[componentname] = cmds; } }; /* * constants for easier comparing. * can be used like foundation.parsekey(event) === foundation.keys.space */ function getkeycodes(kcs) { var k = {}; for (var kc in kcs) { k[kcs[kc]] = kcs[kc]; }return k; } foundation.keyboard = keyboard; }(jquery); 'use strict'; !function ($) { // default set of media queries var defaultqueries = { 'default': 'only screen', landscape: 'only screen and (orientation: landscape)', portrait: 'only screen and (orientation: portrait)', retina: 'only screen and (-webkit-min-device-pixel-ratio: 2),' + 'only screen and (min--moz-device-pixel-ratio: 2),' + 'only screen and (-o-min-device-pixel-ratio: 2/1),' + 'only screen and (min-device-pixel-ratio: 2),' + 'only screen and (min-resolution: 192dpi),' + 'only screen and (min-resolution: 2dppx)' }; var mediaquery = { queries: [], current: '', /** * initializes the media query helper, by extracting the breakpoint list from the css and activating the breakpoint watcher. * @function * @private */ _init: function () { var self = this; var extractedstyles = $('.foundation-mq').css('font-family'); var namedqueries; namedqueries = parsestyletoobject(extractedstyles); for (var key in namedqueries) { if (namedqueries.hasownproperty(key)) { self.queries.push({ name: key, value: 'only screen and (min-width: ' + namedqueries[key] + ')' }); } } this.current = this._getcurrentsize(); this._watcher(); }, /** * checks if the screen is at least as wide as a breakpoint. * @function * @param {string} size - name of the breakpoint to check. * @returns {boolean} `true` if the breakpoint matches, `false` if it's smaller. */ atleast: function (size) { var query = this.get(size); if (query) { return window.matchmedia(query).matches; } return false; }, /** * gets the media query of a breakpoint. * @function * @param {string} size - name of the breakpoint to get. * @returns {string|null} - the media query of the breakpoint, or `null` if the breakpoint doesn't exist. */ get: function (size) { for (var i in this.queries) { if (this.queries.hasownproperty(i)) { var query = this.queries[i]; if (size === query.name) return query.value; } } return null; }, /** * gets the current breakpoint name by testing every breakpoint and returning the last one to match (the biggest one). * @function * @private * @returns {string} name of the current breakpoint. */ _getcurrentsize: function () { var matched; for (var i = 0; i < this.queries.length; i++) { var query = this.queries[i]; if (window.matchmedia(query.value).matches) { matched = query; } } if (typeof matched === 'object') { return matched.name; } else { return matched; } }, /** * activates the breakpoint watcher, which fires an event on the window whenever the breakpoint changes. * @function * @private */ _watcher: function () { var _this = this; $(window).on('resize.zf.mediaquery', function () { var newsize = _this._getcurrentsize(), currentsize = _this.current; if (newsize !== currentsize) { // change the current media query _this.current = newsize; // broadcast the media query change on the window $(window).trigger('changed.zf.mediaquery', [newsize, currentsize]); } }); } }; foundation.mediaquery = mediaquery; // matchmedia() polyfill - test a css media type/query in js. // authors & copyright (c) 2012: scott jehl, paul irish, nicholas zakas, david knight. dual mit/bsd license window.matchmedia || (window.matchmedia = function () { 'use strict'; // for browsers that support matchmedium api such as ie 9 and webkit var stylemedia = window.stylemedia || window.media; // for those that don't support matchmedium if (!stylemedia) { var style = document.createelement('style'), script = document.getelementsbytagname('script')[0], info = null; style.type = 'text/css'; style.id = 'matchmediajs-test'; script.parentnode.insertbefore(style, script); // 'style.currentstyle' is used by ie <= 8 and 'window.getcomputedstyle' for all other browsers info = 'getcomputedstyle' in window && window.getcomputedstyle(style, null) || style.currentstyle; stylemedia = { matchmedium: function (media) { var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }'; // 'style.stylesheet' is used by ie <= 8 and 'style.textcontent' for all other browsers if (style.stylesheet) { style.stylesheet.csstext = text; } else { style.textcontent = text; } // test if media query is true or false return info.width === '1px'; } }; } return function (media) { return { matches: stylemedia.matchmedium(media || 'all'), media: media || 'all' }; }; }()); // thank you: https://github.com/sindresorhus/query-string function parsestyletoobject(str) { var styleobject = {}; if (typeof str !== 'string') { return styleobject; } str = str.trim().slice(1, -1); // browsers re-quote string style values if (!str) { return styleobject; } styleobject = str.split('&').reduce(function (ret, param) { var parts = param.replace(/\+/g, ' ').split('='); var key = parts[0]; var val = parts[1]; key = decodeuricomponent(key); // missing `=` should be `null`: // http://w3.org/tr/2012/wd-url-20120524/#collect-url-parameters val = val === undefined ? null : decodeuricomponent(val); if (!ret.hasownproperty(key)) { ret[key] = val; } else if (array.isarray(ret[key])) { ret[key].push(val); } else { ret[key] = [ret[key], val]; } return ret; }, {}); return styleobject; } foundation.mediaquery = mediaquery; }(jquery); 'use strict'; !function ($) { /** * motion module. * @module foundation.motion */ var initclasses = ['mui-enter', 'mui-leave']; var activeclasses = ['mui-enter-active', 'mui-leave-active']; var motion = { animatein: function (element, animation, cb) { animate(true, element, animation, cb); }, animateout: function (element, animation, cb) { animate(false, element, animation, cb); } }; function move(duration, elem, fn) { var anim, prog, start = null; // console.log('called'); function move(ts) { if (!start) start = window.performance.now(); // console.log(start, ts); prog = ts - start; fn.apply(elem); if (prog < duration) { anim = window.requestanimationframe(move, elem); } else { window.cancelanimationframe(anim); elem.trigger('finished.zf.animate', [elem]).triggerhandler('finished.zf.animate', [elem]); } } anim = window.requestanimationframe(move); } /** * animates an element in or out using a css transition class. * @function * @private * @param {boolean} isin - defines if the animation is in or out. * @param {object} element - jquery or html object to animate. * @param {string} animation - css class to use. * @param {function} cb - callback to run when animation is finished. */ function animate(isin, element, animation, cb) { element = $(element).eq(0); if (!element.length) return; var initclass = isin ? initclasses[0] : initclasses[1]; var activeclass = isin ? activeclasses[0] : activeclasses[1]; // set up the animation reset(); element.addclass(animation).css('transition', 'none'); requestanimationframe(function () { element.addclass(initclass); if (isin) element.show(); }); // start the animation requestanimationframe(function () { element[0].offsetwidth; element.css('transition', '').addclass(activeclass); }); // clean up the animation when it finishes element.one(foundation.transitionend(element), finish); // hides the element (for out animations), resets the element, and runs a callback function finish() { if (!isin) element.hide(); reset(); if (cb) cb.apply(element); } // resets transitions and removes motion-specific classes function reset() { element[0].style.transitionduration = 0; element.removeclass(initclass + ' ' + activeclass + ' ' + animation); } } foundation.move = move; foundation.motion = motion; }(jquery); 'use strict'; !function ($) { var nest = { feather: function (menu) { var type = arguments.length <= 1 || arguments[1] === undefined ? 'zf' : arguments[1]; menu.attr('role', 'menubar'); var items = menu.find('li').attr({ 'role': 'menuitem' }), submenuclass = 'is-' + type + '-submenu', subitemclass = submenuclass + '-item', hassubclass = 'is-' + type + '-submenu-parent'; menu.find('a:first').attr('tabindex', 0); items.each(function () { var $item = $(this), $sub = $item.children('ul'); if ($sub.length) { $item.addclass(hassubclass).attr({ 'aria-haspopup': true, 'aria-expanded': false, 'aria-label': $item.children('a:first').text() }); $sub.addclass('submenu ' + submenuclass).attr({ 'data-submenu': '', 'aria-hidden': true, 'role': 'menu' }); } if ($item.parent('[data-submenu]').length) { $item.addclass('is-submenu-item ' + subitemclass); } }); return; }, burn: function (menu, type) { var items = menu.find('li').removeattr('tabindex'), submenuclass = 'is-' + type + '-submenu', subitemclass = submenuclass + '-item', hassubclass = 'is-' + type + '-submenu-parent'; menu.find('*').removeclass(submenuclass + ' ' + subitemclass + ' ' + hassubclass + ' is-submenu-item submenu is-active').removeattr('data-submenu').css('display', ''); // console.log( menu.find('.' + submenuclass + ', .' + subitemclass + ', .has-submenu, .is-submenu-item, .submenu, [data-submenu]') // .removeclass(submenuclass + ' ' + subitemclass + ' has-submenu is-submenu-item submenu') // .removeattr('data-submenu')); // items.each(function(){ // var $item = $(this), // $sub = $item.children('ul'); // if($item.parent('[data-submenu]').length){ // $item.removeclass('is-submenu-item ' + subitemclass); // } // if($sub.length){ // $item.removeclass('has-submenu'); // $sub.removeclass('submenu ' + submenuclass).removeattr('data-submenu'); // } // }); } }; foundation.nest = nest; }(jquery); 'use strict'; !function ($) { function timer(elem, options, cb) { var _this = this, duration = options.duration, //options is an object for easily adding features later. namespace = object.keys(elem.data())[0] || 'timer', remain = -1, start, timer; this.ispaused = false; this.restart = function () { remain = -1; cleartimeout(timer); this.start(); }; this.start = function () { this.ispaused = false; // if(!elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things. cleartimeout(timer); remain = remain <= 0 ? duration : remain; elem.data('paused', false); start = date.now(); timer = settimeout(function () { if (options.infinite) { _this.restart(); //rerun the timer. } cb(); }, remain); elem.trigger('timerstart.zf.' + namespace); }; this.pause = function () { this.ispaused = true; //if(elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things. cleartimeout(timer); elem.data('paused', true); var end = date.now(); remain = remain - (end - start); elem.trigger('timerpaused.zf.' + namespace); }; } /** * runs a callback function when images are fully loaded. * @param {object} images - image(s) to check if loaded. * @param {func} callback - function to execute when image is fully loaded. */ function onimagesloaded(images, callback) { var self = this, unloaded = images.length; if (unloaded === 0) { callback(); } images.each(function () { if (this.complete) { singleimageloaded(); } else if (typeof this.naturalwidth !== 'undefined' && this.naturalwidth > 0) { singleimageloaded(); } else { $(this).one('load', function () { singleimageloaded(); }); } }); function singleimageloaded() { unloaded--; if (unloaded === 0) { callback(); } } } foundation.timer = timer; foundation.onimagesloaded = onimagesloaded; }(jquery); //************************************************** //**work inspired by multiple jquery swipe plugins** //**done by yohai ararat *************************** //************************************************** (function ($) { $.spotswipe = { version: '1.0.0', enabled: 'ontouchstart' in document.documentelement, preventdefault: false, movethreshold: 75, timethreshold: 200 }; var startposx, startposy, starttime, elapsedtime, ismoving = false; function ontouchend() { // alert(this); this.removeeventlistener('touchmove', ontouchmove); this.removeeventlistener('touchend', ontouchend); ismoving = false; } function ontouchmove(e) { if ($.spotswipe.preventdefault) { e.preventdefault(); } if (ismoving) { var x = e.touches[0].pagex; var y = e.touches[0].pagey; var dx = startposx - x; var dy = startposy - y; var dir; elapsedtime = new date().gettime() - starttime; if (math.abs(dx) >= $.spotswipe.movethreshold && elapsedtime <= $.spotswipe.timethreshold) { dir = dx > 0 ? 'left' : 'right'; } // else if(math.abs(dy) >= $.spotswipe.movethreshold && elapsedtime <= $.spotswipe.timethreshold) { // dir = dy > 0 ? 'down' : 'up'; // } if (dir) { e.preventdefault(); ontouchend.call(this); $(this).trigger('swipe', dir).trigger('swipe' + dir); } } } function ontouchstart(e) { if (e.touches.length == 1) { startposx = e.touches[0].pagex; startposy = e.touches[0].pagey; ismoving = true; starttime = new date().gettime(); this.addeventlistener('touchmove', ontouchmove, false); this.addeventlistener('touchend', ontouchend, false); } } function init() { this.addeventlistener && this.addeventlistener('touchstart', ontouchstart, false); } function teardown() { this.removeeventlistener('touchstart', ontouchstart); } $.event.special.swipe = { setup: init }; $.each(['left', 'up', 'down', 'right'], function () { $.event.special['swipe' + this] = { setup: function () { $(this).on('swipe', $.noop); } }; }); })(jquery); /**************************************************** * method for adding psuedo drag events to elements * ***************************************************/ !function ($) { $.fn.addtouch = function () { this.each(function (i, el) { $(el).bind('touchstart touchmove touchend touchcancel', function () { //we pass the original event object because the jquery event //object is normalized to w3c specs and does not provide the touchlist handletouch(event); }); }); var handletouch = function (event) { var touches = event.changedtouches, first = touches[0], eventtypes = { touchstart: 'mousedown', touchmove: 'mousemove', touchend: 'mouseup' }, type = eventtypes[event.type], simulatedevent; if ('mouseevent' in window && typeof window.mouseevent === 'function') { simulatedevent = new window.mouseevent(type, { 'bubbles': true, 'cancelable': true, 'screenx': first.screenx, 'screeny': first.screeny, 'clientx': first.clientx, 'clienty': first.clienty }); } else { simulatedevent = document.createevent('mouseevent'); simulatedevent.initmouseevent(type, true, true, window, 1, first.screenx, first.screeny, first.clientx, first.clienty, false, false, false, false, 0 /*left*/, null); } first.target.dispatchevent(simulatedevent); }; }; }(jquery); //********************************** //**from the jquery mobile library** //**need to recreate functionality** //**and try to improve if possible** //********************************** /* removing the jquery function **** ************************************ (function( $, window, undefined ) { var $document = $( document ), // supporttouch = $.mobile.support.touch, touchstartevent = 'touchstart'//supporttouch ? "touchstart" : "mousedown", touchstopevent = 'touchend'//supporttouch ? "touchend" : "mouseup", touchmoveevent = 'touchmove'//supporttouch ? "touchmove" : "mousemove"; // setup new event shortcuts $.each( ( "touchstart touchmove touchend " + "swipe swipeleft swiperight" ).split( " " ), function( i, name ) { $.fn[ name ] = function( fn ) { return fn ? this.bind( name, fn ) : this.trigger( name ); }; // jquery < 1.8 if ( $.attrfn ) { $.attrfn[ name ] = true; } }); function triggercustomevent( obj, eventtype, event, bubble ) { var originaltype = event.type; event.type = eventtype; if ( bubble ) { $.event.trigger( event, undefined, obj ); } else { $.event.dispatch.call( obj, event ); } event.type = originaltype; } // also handles taphold // also handles swipeleft, swiperight $.event.special.swipe = { // more than this horizontal displacement, and we will suppress scrolling. scrollsupressionthreshold: 30, // more time than this, and it isn't a swipe. durationthreshold: 1000, // swipe horizontal displacement must be more than this. horizontaldistancethreshold: window.devicepixelratio >= 2 ? 15 : 30, // swipe vertical displacement must be less than this. verticaldistancethreshold: window.devicepixelratio >= 2 ? 15 : 30, getlocation: function ( event ) { var winpagex = window.pagexoffset, winpagey = window.pageyoffset, x = event.clientx, y = event.clienty; if ( event.pagey === 0 && math.floor( y ) > math.floor( event.pagey ) || event.pagex === 0 && math.floor( x ) > math.floor( event.pagex ) ) { // ios4 clientx/clienty have the value that should have been // in pagex/pagey. while pagex/page/ have the value 0 x = x - winpagex; y = y - winpagey; } else if ( y < ( event.pagey - winpagey) || x < ( event.pagex - winpagex ) ) { // some android browsers have totally bogus values for clientx/y // when scrolling/zooming a page. detectable since clientx/clienty // should never be smaller than pagex/pagey minus page scroll x = event.pagex - winpagex; y = event.pagey - winpagey; } return { x: x, y: y }; }, start: function( event ) { var data = event.originalevent.touches ? event.originalevent.touches[ 0 ] : event, location = $.event.special.swipe.getlocation( data ); return { time: ( new date() ).gettime(), coords: [ location.x, location.y ], origin: $( event.target ) }; }, stop: function( event ) { var data = event.originalevent.touches ? event.originalevent.touches[ 0 ] : event, location = $.event.special.swipe.getlocation( data ); return { time: ( new date() ).gettime(), coords: [ location.x, location.y ] }; }, handleswipe: function( start, stop, thisobject, origtarget ) { if ( stop.time - start.time < $.event.special.swipe.durationthreshold && math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontaldistancethreshold && math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticaldistancethreshold ) { var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; triggercustomevent( thisobject, "swipe", $.event( "swipe", { target: origtarget, swipestart: start, swipestop: stop }), true ); triggercustomevent( thisobject, direction,$.event( direction, { target: origtarget, swipestart: start, swipestop: stop } ), true ); return true; } return false; }, // this serves as a flag to ensure that at most one swipe event event is // in work at any given time eventinprogress: false, setup: function() { var events, thisobject = this, $this = $( thisobject ), context = {}; // retrieve the events data for this element and add the swipe context events = $.data( this, "mobile-events" ); if ( !events ) { events = { length: 0 }; $.data( this, "mobile-events", events ); } events.length++; events.swipe = context; context.start = function( event ) { // bail if we're already working on a swipe event if ( $.event.special.swipe.eventinprogress ) { return; } $.event.special.swipe.eventinprogress = true; var stop, start = $.event.special.swipe.start( event ), origtarget = event.target, emitted = false; context.move = function( event ) { if ( !start || event.isdefaultprevented() ) { return; } stop = $.event.special.swipe.stop( event ); if ( !emitted ) { emitted = $.event.special.swipe.handleswipe( start, stop, thisobject, origtarget ); if ( emitted ) { // reset the context to make way for the next swipe event $.event.special.swipe.eventinprogress = false; } } // prevent scrolling if ( math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollsupressionthreshold ) { event.preventdefault(); } }; context.stop = function() { emitted = true; // reset the context to make way for the next swipe event $.event.special.swipe.eventinprogress = false; $document.off( touchmoveevent, context.move ); context.move = null; }; $document.on( touchmoveevent, context.move ) .one( touchstopevent, context.stop ); }; $this.on( touchstartevent, context.start ); }, teardown: function() { var events, context; events = $.data( this, "mobile-events" ); if ( events ) { context = events.swipe; delete events.swipe; events.length--; if ( events.length === 0 ) { $.removedata( this, "mobile-events" ); } } if ( context ) { if ( context.start ) { $( this ).off( touchstartevent, context.start ); } if ( context.move ) { $document.off( touchmoveevent, context.move ); } if ( context.stop ) { $document.off( touchstopevent, context.stop ); } } } }; $.each({ swipeleft: "swipe.left", swiperight: "swipe.right" }, function( event, sourceevent ) { $.event.special[ event ] = { setup: function() { $( this ).bind( sourceevent, $.noop ); }, teardown: function() { $( this ).unbind( sourceevent ); } }; }); })( jquery, this ); */ 'use strict'; !function ($) { var mutationobserver = function () { var prefixes = ['webkit', 'moz', 'o', 'ms', '']; for (var i = 0; i < prefixes.length; i++) { if (prefixes[i] + 'mutationobserver' in window) { return window[prefixes[i] + 'mutationobserver']; } } return false; }(); var triggers = function (el, type) { el.data(type).split(' ').foreach(function (id) { $('#' + id)[type === 'close' ? 'trigger' : 'triggerhandler'](type + '.zf.trigger', [el]); }); }; // elements with [data-open] will reveal a plugin that supports it when clicked. $(document).on('click.zf.trigger', '[data-open]', function () { triggers($(this), 'open'); }); // elements with [data-close] will close a plugin that supports it when clicked. // if used without a value on [data-close], the event will bubble, allowing it to close a parent component. $(document).on('click.zf.trigger', '[data-close]', function () { var id = $(this).data('close'); if (id) { triggers($(this), 'close'); } else { $(this).trigger('close.zf.trigger'); } }); // elements with [data-toggle] will toggle a plugin that supports it when clicked. $(document).on('click.zf.trigger', '[data-toggle]', function () { triggers($(this), 'toggle'); }); // elements with [data-closable] will respond to close.zf.trigger events. $(document).on('close.zf.trigger', '[data-closable]', function (e) { e.stoppropagation(); var animation = $(this).data('closable'); if (animation !== '') { foundation.motion.animateout($(this), animation, function () { $(this).trigger('closed.zf'); }); } else { $(this).fadeout().trigger('closed.zf'); } }); $(document).on('focus.zf.trigger blur.zf.trigger', '[data-toggle-focus]', function () { var id = $(this).data('toggle-focus'); $('#' + id).triggerhandler('toggle.zf.trigger', [$(this)]); }); /** * fires once after all other scripts have loaded * @function * @private */ $(window).load(function () { checklisteners(); }); function checklisteners() { eventslistener(); resizelistener(); scrolllistener(); closemelistener(); } //******** only fires this function once on load, if there's something to watch ******** function closemelistener(pluginname) { var yetiboxes = $('[data-yeti-box]'), plugnames = ['dropdown', 'tooltip', 'reveal']; if (pluginname) { if (typeof pluginname === 'string') { plugnames.push(pluginname); } else if (typeof pluginname === 'object' && typeof pluginname[0] === 'string') { plugnames.concat(pluginname); } else { console.error('plugin names must be strings'); } } if (yetiboxes.length) { var listeners = plugnames.map(function (name) { return 'closeme.zf.' + name; }).join(' '); $(window).off(listeners).on(listeners, function (e, pluginid) { var plugin = e.namespace.split('.')[0]; var plugins = $('[data-' + plugin + ']').not('[data-yeti-box="' + pluginid + '"]'); plugins.each(function () { var _this = $(this); _this.triggerhandler('close.zf.trigger', [_this]); }); }); } } function resizelistener(debounce) { var timer = void 0, $nodes = $('[data-resize]'); if ($nodes.length) { $(window).off('resize.zf.trigger').on('resize.zf.trigger', function (e) { if (timer) { cleartimeout(timer); } timer = settimeout(function () { if (!mutationobserver) { //fallback for ie 9 $nodes.each(function () { $(this).triggerhandler('resizeme.zf.trigger'); }); } //trigger all listening elements and signal a resize event $nodes.attr('data-events', "resize"); }, debounce || 10); //default time to emit resize event }); } } function scrolllistener(debounce) { var timer = void 0, $nodes = $('[data-scroll]'); if ($nodes.length) { $(window).off('scroll.zf.trigger').on('scroll.zf.trigger', function (e) { if (timer) { cleartimeout(timer); } timer = settimeout(function () { if (!mutationobserver) { //fallback for ie 9 $nodes.each(function () { $(this).triggerhandler('scrollme.zf.trigger'); }); } //trigger all listening elements and signal a scroll event $nodes.attr('data-events', "scroll"); }, debounce || 10); //default time to emit scroll event }); } } function eventslistener() { if (!mutationobserver) { return false; } var nodes = document.queryselectorall('[data-resize], [data-scroll], [data-mutate]'); //element callback var listeningelementsmutation = function (mutationrecordslist) { var $target = $(mutationrecordslist[0].target); //trigger the event handler for the element depending on type switch ($target.attr("data-events")) { case "resize": $target.triggerhandler('resizeme.zf.trigger', [$target]); break; case "scroll": $target.triggerhandler('scrollme.zf.trigger', [$target, window.pageyoffset]); break; // case "mutate" : // console.log('mutate', $target); // $target.triggerhandler('mutate.zf.trigger'); // // //make sure we don't get stuck in an infinite loop from sloppy codeing // if ($target.index('[data-mutate]') == $("[data-mutate]").length-1) { // dommutationobserver(); // } // break; default: return false; //nothing } }; if (nodes.length) { //for each element that needs to listen for resizing, scrolling, (or coming soon mutation) add a single observer for (var i = 0; i <= nodes.length - 1; i++) { var elementobserver = new mutationobserver(listeningelementsmutation); elementobserver.observe(nodes[i], { attributes: true, childlist: false, characterdata: false, subtree: false, attributefilter: ["data-events"] }); } } } // ------------------------------------ // [ph] // foundation.checkwatchers = checkwatchers; foundation.ihearyou = checklisteners; // foundation.iseeyou = scrolllistener; // foundation.ifeelyou = closemelistener; }(jquery); // function dommutationobserver(debounce) { // // !!! this is coming soon and needs more work; not active !!! // // var timer, // nodes = document.queryselectorall('[data-mutate]'); // // // if (nodes.length) { // // var mutationobserver = (function () { // // var prefixes = ['webkit', 'moz', 'o', 'ms', '']; // // for (var i=0; i < prefixes.length; i++) { // // if (prefixes[i] + 'mutationobserver' in window) { // // return window[prefixes[i] + 'mutationobserver']; // // } // // } // // return false; // // }()); // // // //for the body, we need to listen for all changes effecting the style and class attributes // var bodyobserver = new mutationobserver(bodymutation); // bodyobserver.observe(document.body, { attributes: true, childlist: true, characterdata: false, subtree:true, attributefilter:["style", "class"]}); // // // //body callback // function bodymutation(mutate) { // //trigger all listening elements and signal a mutation event // if (timer) { cleartimeout(timer); } // // timer = settimeout(function() { // bodyobserver.disconnect(); // $('[data-mutate]').attr('data-events',"mutate"); // }, debounce || 150); // } // } // } 'use strict'; var _createclass = function () { function defineproperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; object.defineproperty(target, descriptor.key, descriptor); } } return function (constructor, protoprops, staticprops) { if (protoprops) defineproperties(constructor.prototype, protoprops); if (staticprops) defineproperties(constructor, staticprops); return constructor; }; }(); function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } } !function ($) { /** * abide module. * @module foundation.abide */ var abide = function () { /** * creates a new instance of abide. * @class * @fires abide#init * @param {object} element - jquery object to add the trigger to. * @param {object} options - overrides to the default plugin settings. */ function abide(element) { var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; _classcallcheck(this, abide); this.$element = element; this.options = $.extend({}, abide.defaults, this.$element.data(), options); this._init(); foundation.registerplugin(this, 'abide'); } /** * initializes the abide plugin and calls functions to get abide functioning on load. * @private */ _createclass(abide, [{ key: '_init', value: function _init() { this.$inputs = this.$element.find('input, textarea, select'); this._events(); } /** * initializes events for abide. * @private */ }, { key: '_events', value: function _events() { var _this2 = this; this.$element.off('.abide').on('reset.zf.abide', function () { _this2.resetform(); }).on('submit.zf.abide', function () { return _this2.validateform(); }); if (this.options.validateon === 'fieldchange') { this.$inputs.off('change.zf.abide').on('change.zf.abide', function (e) { _this2.validateinput($(e.target)); }); } if (this.options.livevalidate) { this.$inputs.off('input.zf.abide').on('input.zf.abide', function (e) { _this2.validateinput($(e.target)); }); } } /** * calls necessary functions to update abide upon dom change * @private */ }, { key: '_reflow', value: function _reflow() { this._init(); } /** * checks whether or not a form element has the required attribute and if it's checked or not * @param {object} element - jquery object to check for required attribute * @returns {boolean} boolean value depends on whether or not attribute is checked or empty */ }, { key: 'requiredcheck', value: function requiredcheck($el) { if (!$el.attr('required')) return true; var isgood = true; switch ($el[0].type) { case 'checkbox': isgood = $el[0].checked; break; case 'select': case 'select-one': case 'select-multiple': var opt = $el.find('option:selected'); if (!opt.length || !opt.val()) isgood = false; break; default: if (!$el.val() || !$el.val().length) isgood = false; } return isgood; } /** * based on $el, get the first element with selector in this order: * 1. the element's direct sibling('s). * 3. the element's parent's children. * * this allows for multiple form errors per input, though if none are found, no form errors will be shown. * * @param {object} $el - jquery object to use as reference to find the form error selector. * @returns {object} jquery object with the selector. */ }, { key: 'findformerror', value: function findformerror($el) { var $error = $el.siblings(this.options.formerrorselector); if (!$error.length) { $error = $el.parent().find(this.options.formerrorselector); } return $error; } /** * get the first element in this order: * 2. the