(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: true,
          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'];
  });