text: !(function(root, factory) {
    if (typeof define === 'function' && define.amd) {
      define(['jquery'], factory);
    } else if (typeof exports === 'object') {
      factory(require('jquery'));
    } else {
      factory(root.jQuery);
    }
  })(this, function($) {
  
    'use strict';
  
    /**
     * Name of the plugin
     * @private
     * @const
     * @type {String}
     */
    var PLUGIN_NAME = 'vide';
  
    /**
     * Default settings
     * @private
     * @const
     * @type {Object}
     */
    var DEFAULTS = {
      volume: 1,
      playbackRate: 1,
      muted: true,
      loop: true,
      autoplay: true,
      position: '50% 50%',
      posterType: 'detect',
      resizing: true,
      bgColor: 'transparent',
      className: ''
    };
  
    /**
     * Not implemented error message
     * @private
     * @const
     * @type {String}
     */
    var NOT_IMPLEMENTED_MSG = 'Not implemented';
  
    /**
     * Parse a string with options
     * @private
     * @param {String} str
     * @returns {Object|String}
     */
    function parseOptions(str) {
      var obj = {};
      var delimiterIndex;
      var option;
      var prop;
      var val;
      var arr;
      var len;
      var i;
  
      // Remove spaces around delimiters and split
      arr = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',').split(',');
  
      // Parse a string
      for (i = 0, len = arr.length; i < len; i++) {
        option = arr[i];
  
        // Ignore urls and a string without colon delimiters
        if (
          option.search(/^(http|https|ftp):\/\//) !== -1 ||
          option.search(':') === -1
        ) {
          break;
        }
  
        delimiterIndex = option.indexOf(':');
        prop = option.substring(0, delimiterIndex);
        val = option.substring(delimiterIndex + 1);
  
        // If val is an empty string, make it undefined
        if (!val) {
          val = undefined;
        }
  
        // Convert a string value if it is like a boolean
        if (typeof val === 'string') {
          val = val === 'true' || (val === 'false' ? false : val);
        }
  
        // Convert a string value if it is like a number
        if (typeof val === 'string') {
          val = !isNaN(val) ? +val : val;
        }
  
        obj[prop] = val;
      }
  
      // If nothing is parsed
      if (prop == null && val == null) {
        return str;
      }
  
      return obj;
    }
  
    /**
     * Parse a position option
     * @private
     * @param {String} str
     * @returns {Object}
     */
    function parsePosition(str) {
      str = '' + str;
  
      // Default value is a center
      var args = str.split(/\s+/);
      var x = '50%';
      var y = '50%';
      var len;
      var arg;
      var i;
  
      for (i = 0, len = args.length; i < len; i++) {
        arg = args[i];
  
        // Convert values
        if (arg === 'left') {
          x = '0%';
        } else if (arg === 'right') {
          x = '100%';
        } else if (arg === 'top') {
          y = '0%';
        } else if (arg === 'bottom') {
          y = '100%';
        } else if (arg === 'center') {
          if (i === 0) {
            x = '50%';
          } else {
            y = '50%';
          }
        } else {
          if (i === 0) {
            x = arg;
          } else {
            y = arg;
          }
        }
      }
  
      return { x: x, y: y };
    }
  
    /**
     * Search a poster
     * @private
     * @param {String} path
     * @param {Function} callback
     */
    function findPoster(path, callback) {
      var onLoad = function() {
        callback(this.src);
      };
  
      //$('<img src="' + path + '.gif">').on('load', onLoad);
      //$('<img src="' + path + '.jpg">').on('load', onLoad);
      //$('<img src="' + path + '.jpeg">').on('load', onLoad);
      //$('<img src="' + path + '.png">').on('load', onLoad);
    }
  
    /**
     * Vide constructor
     * @param {HTMLElement} element
     * @param {Object|String} path
     * @param {Object|String} options
     * @constructor
     */
    function Vide(element, path, options) {
      this.$element = $(element);
  
      // Parse path
      if (typeof path === 'string') {
        path = parseOptions(path);
      }
  
      // Parse options
      if (!options) {
        options = {};
      } else if (typeof options === 'string') {
        options = parseOptions(options);
      }
  
      // Remove an extension
      if (typeof path === 'string') {
        path = path.replace(/\.\w*$/, '');
      } else if (typeof path === 'object') {
        for (var i in path) {
          if (path.hasOwnProperty(i)) {
            path[i] = path[i].replace(/\.\w*$/, '');
          }
        }
      }
  
      this.settings = $.extend({}, DEFAULTS, options);
      this.path = path;
  
      // https://github.com/VodkaBears/Vide/issues/110
      try {
        this.init();
      } catch (e) {
        if (e.message !== NOT_IMPLEMENTED_MSG) {
          throw e;
        }
      }
    }
  
    /**
     * Initialization
     * @public
     */
    Vide.prototype.init = function() {
      var vide = this;
      var path = vide.path;
      var poster = path;
      var sources = '';
      var $element = vide.$element;
      var settings = vide.settings;
      var position = parsePosition(settings.position);
      var posterType = settings.posterType;
      var $video;
      var $wrapper;
  
      // Set styles of a video wrapper
      $wrapper = vide.$wrapper = $('<div>')
        .addClass(settings.className)
        .css({
          position: 'absolute',
          'z-index': -1,
          top: 0,
          left: 0,
          bottom: 0,
          right: 0,
          overflow: 'hidden',
          '-webkit-background-size': 'cover',
          '-moz-background-size': 'cover',
          '-o-background-size': 'cover',
          'background-size': 'cover',
          'background-color': settings.bgColor,
          'background-repeat': 'no-repeat',
          'background-position': position.x + ' ' + position.y
        });
  
      // Get a poster path
      if (typeof path === 'object') {
        if (path.poster) {
          poster = path.poster;
        } else {
          if (path.mp4) {
            poster = path.mp4;
          } else if (path.webm) {
            poster = path.webm;
          } else if (path.ogv) {
            poster = path.ogv;
          }
        }
      }
  
      // Set a video poster
      if (posterType === 'detect') {
        findPoster(poster, function(url) {
          $wrapper.css('background-image', 'url(' + url + ')');
        });
      } else if (posterType !== 'none') {
        $wrapper.css('background-image', 'url(' + poster + '.' + posterType + ')');
      }
  
      // If a parent element has a static position, make it relative
      if ($element.css('position') === 'static') {
        $element.css('position', 'relative');
      }
  
      $element.prepend($wrapper);
  
      if (typeof path === 'object') {
        if (path.mp4) {
          sources += '<source src="' + path.mp4 + '.mp4" type="video/mp4">';
        }
  
        if (path.webm) {
          sources += '<source src="' + path.webm + '.webm" type="video/webm">';
        }
  
        if (path.ogv) {
          sources += '<source src="' + path.ogv + '.ogv" type="video/ogg">';
        }
  
        $video = vide.$video = $('<video>' + sources + '</video>');
      } else {
        $video = vide.$video = $('<video>' +
          '<source src="' + path + '.mp4" type="video/mp4">' +
          '<source src="' + path + '.webm" type="video/webm">' +
          '<source src="' + path + '.ogv" type="video/ogg">' +
          '</video>');
      }
  
      // https://github.com/VodkaBears/Vide/issues/110
      try {
        $video
  
          // Set video properties
          .prop({
            autoplay: settings.autoplay,
            loop: settings.loop,
            volume: settings.volume,
            muted: settings.muted,
            defaultMuted: settings.muted,
            playbackRate: settings.playbackRate,
            defaultPlaybackRate: settings.playbackRate
          });
      } catch (e) {
        throw new Error(NOT_IMPLEMENTED_MSG);
      }
  
      // Video alignment
      $video.css({
        margin: 'auto',
        position: 'absolute',
        'z-index': -1,
        top: position.y,
        left: position.x,
        '-webkit-transform': 'translate(-' + position.x + ', -' + position.y + ')',
        '-ms-transform': 'translate(-' + position.x + ', -' + position.y + ')',
        '-moz-transform': 'translate(-' + position.x + ', -' + position.y + ')',
        transform: 'translate(-' + position.x + ', -' + position.y + ')',
  
        // Disable visibility, while loading
        visibility: 'hidden',
        opacity: 0
      })
  
      // Resize a video, when it's loaded
      .one('canplaythrough.' + PLUGIN_NAME, function() {
        vide.resize();
      })
  
      // Make it visible, when it's already playing
      .one('playing.' + PLUGIN_NAME, function() {
        $video.css({
          visibility: 'visible',
          opacity: 1
        });
        $wrapper.css('background-image', 'none');
      });
  
      // Resize event is available only for 'window'
      // Use another code solutions to detect DOM elements resizing
      $element.on('resize.' + PLUGIN_NAME, function() {
        if (settings.resizing) {
          vide.resize();
        }
      });
  
      // Append a video
      $wrapper.append($video);
    };
  
    /**
     * Get a video element
     * @public
     * @returns {HTMLVideoElement}
     */
    Vide.prototype.getVideoObject = function() {
      return this.$video[0];
    };
  
    /**
     * Resize a video background
     * @public
     */
    Vide.prototype.resize = function() {
      if (!this.$video) {
        return;
      }
  
      var $wrapper = this.$wrapper;
      var $video = this.$video;
      var video = $video[0];
  
      // Get a native video size
      var videoHeight = video.videoHeight;
      var videoWidth = video.videoWidth;
  
      // Get a wrapper size
      var wrapperHeight = $wrapper.height();
      var wrapperWidth = $wrapper.width();
  
      if (wrapperWidth / videoWidth > wrapperHeight / videoHeight) {
        $video.css({
  
          // +2 pixels to prevent an empty space after transformation
          width: wrapperWidth + 2,
          height: 'auto'
        });
      } else {
        $video.css({
          width: 'auto',
  
          // +2 pixels to prevent an empty space after transformation
          height: wrapperHeight + 2
        });
      }
    };
  
    /**
     * Destroy a video background
     * @public
     */
    Vide.prototype.destroy = function() {
      delete $[PLUGIN_NAME].lookup[this.index];
      this.$video && this.$video.off(PLUGIN_NAME);
      this.$element.off(PLUGIN_NAME).removeData(PLUGIN_NAME);
      this.$wrapper.remove();
    };
  
    /**
     * Special plugin object for instances.
     * @public
     * @type {Object}
     */
    $[PLUGIN_NAME] = {
      lookup: []
    };
  
    /**
     * Plugin constructor
     * @param {Object|String} path
     * @param {Object|String} options
     * @returns {JQuery}
     * @constructor
     */
    $.fn[PLUGIN_NAME] = function(path, options) {
      var instance;
  
      this.each(function() {
        instance = $.data(this, PLUGIN_NAME);
  
        // Destroy the plugin instance if exists
        instance && instance.destroy();
  
        // Create the plugin instance
        instance = new Vide(this, path, options);
        instance.index = $[PLUGIN_NAME].lookup.push(instance) - 1;
        $.data(this, PLUGIN_NAME, instance);
      });
  
      return this;
    };
  
    $(document).ready(function() {
      var $window = $(window);
  
      // Window resize event listener
      $window.on('resize.' + PLUGIN_NAME, function() {
        for (var len = $[PLUGIN_NAME].lookup.length, i = 0, instance; i < len; i++) {
          instance = $[PLUGIN_NAME].lookup[i];
  
          if (instance && instance.settings.resizing) {
            instance.resize();
          }
        }
      });
  
      // https://github.com/VodkaBears/Vide/issues/68
      $window.on('unload.' + PLUGIN_NAME, function() {
        return false;
      });
  
      // Auto initialization
      // Add 'data-vide-bg' attribute with a path to the video without extension
      // Also you can pass options throw the 'data-vide-options' attribute
      // 'data-vide-options' must be like 'muted: false, volume: 0.5'
      $(document).find('[data-' + PLUGIN_NAME + '-bg]').each(function(i, element) {
        var $element = $(element);
        var options = $element.data(PLUGIN_NAME + '-options');
        var path = $element.data(PLUGIN_NAME + '-bg');
  
        $element[PLUGIN_NAME](path, options);
      });
    });
  
  });
  