(function (global, factory) { if (typeof define === "function" && define.amd) { define(['module', 'exports'], factory); } else if (typeof exports !== "undefined") { factory(module, exports); } else { var mod = { exports: {} }; factory(mod, mod.exports); global.wow = mod.exports; } })(this, function (module, exports) { 'use strict'; object.defineproperty(exports, "__esmodule", { value: true }); var _class, _temp; function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } } 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 isin(needle, haystack) { return haystack.indexof(needle) >= 0; } function extend(custom, defaults) { for (var key in defaults) { if (custom[key] == null) { var value = defaults[key]; custom[key] = value; } } return custom; } function ismobile(agent) { return (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(agent) ); } function createevent(event) { var bubble = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; var cancel = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; var detail = arguments.length <= 3 || arguments[3] === undefined ? null : arguments[3]; var customevent = void 0; if (document.createevent != null) { // w3c dom customevent = document.createevent('customevent'); customevent.initcustomevent(event, bubble, cancel, detail); } else if (document.createeventobject != null) { // ie dom < 9 customevent = document.createeventobject(); customevent.eventtype = event; } else { customevent.eventname = event; } return customevent; } function emitevent(elem, event) { if (elem.dispatchevent != null) { // w3c dom elem.dispatchevent(event); } else if (event in (elem != null)) { elem[event](); } else if ('on' + event in (elem != null)) { elem['on' + event](); } } function addevent(elem, event, fn) { if (elem.addeventlistener != null) { // w3c dom elem.addeventlistener(event, fn, false); } else if (elem.attachevent != null) { // ie dom elem.attachevent('on' + event, fn); } else { // fallback elem[event] = fn; } } function removeevent(elem, event, fn) { if (elem.removeeventlistener != null) { // w3c dom elem.removeeventlistener(event, fn, false); } else if (elem.detachevent != null) { // ie dom elem.detachevent('on' + event, fn); } else { // fallback delete elem[event]; } } function getinnerheight() { if ('innerheight' in window) { return window.innerheight; } return document.documentelement.clientheight; } // minimalistic weakmap shim, just in case. var weakmap = window.weakmap || window.mozweakmap || function () { function weakmap() { _classcallcheck(this, weakmap); this.keys = []; this.values = []; } _createclass(weakmap, [{ key: 'get', value: function get(key) { for (var i = 0; i < this.keys.length; i++) { var item = this.keys[i]; if (item === key) { return this.values[i]; } } return undefined; } }, { key: 'set', value: function set(key, value) { for (var i = 0; i < this.keys.length; i++) { var item = this.keys[i]; if (item === key) { this.values[i] = value; return this; } } this.keys.push(key); this.values.push(value); return this; } }]); return weakmap; }(); // dummy mutationobserver, to avoid raising exceptions. var mutationobserver = window.mutationobserver || window.webkitmutationobserver || window.mozmutationobserver || (_temp = _class = function () { function mutationobserver() { _classcallcheck(this, mutationobserver); if (typeof console !== 'undefined' && console !== null) { console.warn('mutationobserver is not supported by your browser.'); console.warn('wow.js cannot detect dom mutations, please call .sync() after loading new content.'); } } _createclass(mutationobserver, [{ key: 'observe', value: function observe() {} }]); return mutationobserver; }(), _class.notsupported = true, _temp); // getcomputedstyle shim, from http://stackoverflow.com/a/21797294 var getcomputedstyle = window.getcomputedstyle || function getcomputedstyle(el) { var getcomputedstylerx = /(\-([a-z]){1})/g; return { getpropertyvalue: function getpropertyvalue(prop) { if (prop === 'float') { prop = 'stylefloat'; } if (getcomputedstylerx.test(prop)) { prop.replace(getcomputedstylerx, function (_, _char) { return _char.touppercase(); }); } var currentstyle = el.currentstyle; return (currentstyle != null ? currentstyle[prop] : void 0) || null; } }; }; var wow = function () { function wow() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; _classcallcheck(this, wow); this.defaults = { boxclass: 'wow', animateclass: 'animated', offset: 0, mobile: false, live: true, callback: null, scrollcontainer: null, resetanimation: true }; this.animate = function animatefactory() { if ('requestanimationframe' in window) { return function (callback) { return window.requestanimationframe(callback); }; } return function (callback) { return callback(); }; }(); this.vendors = ['moz', 'webkit']; this.start = this.start.bind(this); this.resetanimation = this.resetanimation.bind(this); this.scrollhandler = this.scrollhandler.bind(this); this.scrollcallback = this.scrollcallback.bind(this); this.scrolled = true; this.config = extend(options, this.defaults); if (options.scrollcontainer != null) { this.config.scrollcontainer = document.queryselector(options.scrollcontainer); } // map of elements to animation names: this.animationnamecache = new weakmap(); this.wowevent = createevent(this.config.boxclass); } _createclass(wow, [{ key: 'init', value: function init() { this.element = window.document.documentelement; if (isin(document.readystate, ['interactive', 'complete'])) { this.start(); } else { addevent(document, 'domcontentloaded', this.start); } this.finished = []; } }, { key: 'start', value: function start() { var _this = this; this.stopped = false; this.boxes = [].slice.call(this.element.queryselectorall('.' + this.config.boxclass)); this.all = this.boxes.slice(0); if (this.boxes.length) { if (this.disabled()) { this.resetstyle(); } else { for (var i = 0; i < this.boxes.length; i++) { var box = this.boxes[i]; this.applystyle(box, true); } } } if (!this.disabled()) { addevent(this.config.scrollcontainer || window, 'scroll', this.scrollhandler); addevent(window, 'resize', this.scrollhandler); this.interval = setinterval(this.scrollcallback, 50); } if (this.config.live) { var mut = new mutationobserver(function (records) { for (var j = 0; j < records.length; j++) { var record = records[j]; for (var k = 0; k < record.addednodes.length; k++) { var node = record.addednodes[k]; _this.dosync(node); } } return undefined; }); mut.observe(document.body, { childlist: true, subtree: true }); } } }, { key: 'stop', value: function stop() { this.stopped = true; removeevent(this.config.scrollcontainer || window, 'scroll', this.scrollhandler); removeevent(window, 'resize', this.scrollhandler); if (this.interval != null) { clearinterval(this.interval); } } }, { key: 'sync', value: function sync() { if (mutationobserver.notsupported) { this.dosync(this.element); } } }, { key: 'dosync', value: function dosync(element) { if (typeof element === 'undefined' || element === null) { element = this.element; } if (element.nodetype !== 1) { return; } element = element.parentnode || element; var iterable = element.queryselectorall('.' + this.config.boxclass); for (var i = 0; i < iterable.length; i++) { var box = iterable[i]; if (!isin(box, this.all)) { this.boxes.push(box); this.all.push(box); if (this.stopped || this.disabled()) { this.resetstyle(); } else { this.applystyle(box, true); } this.scrolled = true; } } } }, { key: 'show', value: function show(box) { this.applystyle(box); box.classname = box.classname + ' ' + this.config.animateclass; if (this.config.callback != null) { this.config.callback(box); } emitevent(box, this.wowevent); if (this.config.resetanimation) { addevent(box, 'animationend', this.resetanimation); addevent(box, 'oanimationend', this.resetanimation); addevent(box, 'webkitanimationend', this.resetanimation); addevent(box, 'msanimationend', this.resetanimation); } return box; } }, { key: 'applystyle', value: function applystyle(box, hidden) { var _this2 = this; var duration = box.getattribute('data-wow-duration'); var delay = box.getattribute('data-wow-delay'); var iteration = box.getattribute('data-wow-iteration'); return this.animate(function () { return _this2.customstyle(box, hidden, duration, delay, iteration); }); } }, { key: 'resetstyle', value: function resetstyle() { for (var i = 0; i < this.boxes.length; i++) { var box = this.boxes[i]; box.style.visibility = 'visible'; } return undefined; } }, { key: 'resetanimation', value: function resetanimation(event) { if (event.type.tolowercase().indexof('animationend') >= 0) { var target = event.target || event.srcelement; target.classname = target.classname.replace(this.config.animateclass, '').trim(); } } }, { key: 'customstyle', value: function customstyle(box, hidden, duration, delay, iteration) { if (hidden) { this.cacheanimationname(box); } box.style.visibility = hidden ? 'hidden' : 'visible'; if (duration) { this.vendorset(box.style, { animationduration: duration }); } if (delay) { this.vendorset(box.style, { animationdelay: delay }); } if (iteration) { this.vendorset(box.style, { animationiterationcount: iteration }); } this.vendorset(box.style, { animationname: hidden ? 'none' : this.cachedanimationname(box) }); return box; } }, { key: 'vendorset', value: function vendorset(elem, properties) { for (var name in properties) { if (properties.hasownproperty(name)) { var value = properties[name]; elem['' + name] = value; for (var i = 0; i < this.vendors.length; i++) { var vendor = this.vendors[i]; elem['' + vendor + name.charat(0).touppercase() + name.substr(1)] = value; } } } } }, { key: 'vendorcss', value: function vendorcss(elem, property) { var style = getcomputedstyle(elem); var result = style.getpropertycssvalue(property); for (var i = 0; i < this.vendors.length; i++) { var vendor = this.vendors[i]; result = result || style.getpropertycssvalue('-' + vendor + '-' + property); } return result; } }, { key: 'animationname', value: function animationname(box) { var aname = void 0; try { aname = this.vendorcss(box, 'animation-name').csstext; } catch (error) { // opera, fall back to plain property value aname = getcomputedstyle(box).getpropertyvalue('animation-name'); } if (aname === 'none') { return ''; // svg/firefox, unable to get animation name? } return aname; } }, { key: 'cacheanimationname', value: function cacheanimationname(box) { // https://bugzilla.mozilla.org/show_bug.cgi?id=921834 // box.dataset is not supported for svg elements in firefox return this.animationnamecache.set(box, this.animationname(box)); } }, { key: 'cachedanimationname', value: function cachedanimationname(box) { return this.animationnamecache.get(box); } }, { key: 'scrollhandler', value: function scrollhandler() { this.scrolled = true; } }, { key: 'scrollcallback', value: function scrollcallback() { if (this.scrolled) { this.scrolled = false; var results = []; for (var i = 0; i < this.boxes.length; i++) { var box = this.boxes[i]; if (box) { if (this.isvisible(box)) { this.show(box); continue; } results.push(box); } } this.boxes = results; if (!this.boxes.length && !this.config.live) { this.stop(); } } } }, { key: 'offsettop', value: function offsettop(element) { // svg elements don't have an offsettop in firefox. // this will use their nearest parent that has an offsettop. // also, using ('offsettop' of element) causes an exception in firefox. while (element.offsettop === undefined) { element = element.parentnode; } var top = element.offsettop; while (element.offsetparent) { element = element.offsetparent; top += element.offsettop; } return top; } }, { key: 'isvisible', value: function isvisible(box) { var offset = box.getattribute('data-wow-offset') || this.config.offset; var viewtop = this.config.scrollcontainer && this.config.scrollcontainer.scrolltop || window.pageyoffset; var viewbottom = viewtop + math.min(this.element.clientheight, getinnerheight()) - offset; var top = this.offsettop(box); var bottom = top + box.clientheight; return top <= viewbottom && bottom >= viewtop; } }, { key: 'disabled', value: function disabled() { return !this.config.mobile && ismobile(navigator.useragent); } }]); return wow; }(); exports.default = wow; module.exports = exports['default']; });