<!DOCTYPE html>
<html>
  <head>
    <link href="http://api.140proof.com/video-js/video-js.min.css?1420673850" media="screen" rel="stylesheet" type="text/css" />

    <!-- <script type="text/javascript" src="videojs.ads.js"></script> --> <!-- latest master -->
    <!-- <script type="text/javascript" src="vast-client.js"></script> --> <!-- latest master -->

    <script src="http://vjs.zencdn.net/4.4.3/video.js"></script>         <!-- only "works" with 4.4.x, anything more recent doesn't play *any* video -->
    <script type="text/javascript" src="videojs.ads-0.4.0.js"></script>  <!-- commit 35bb73023383ff5863c7ae7fa26e78ba336be546, 9/27 -->
    <script type="text/javascript" src="vast-client-1.3.0.js"></script>  <!-- commit 3c6dbaac66f245a7bbbb64c13a44d661927c36db, 10/22 -->
    <script type="text/javascript" src="videojs.vast.js"></script>       <!-- latest vpaid-squashed (10/28) -->
  </head>
  
  <body>
  
    <video id='pv'
            class='video-js vjs-big-play-centered vjs-default-skin'
            controls='controls'
            data-setup="{}"
            height='240'
            poster='https://ads-production.s3.amazonaws.com/videos/466/original_Screen_Shot_2014-09-16_at_10.58.02_AM.png?1410890364' 
            preload='auto' 
            width='320'>
    
      <source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
    </video>
    
    <!-- http://www.iab.net/guidelines/508676/digitalvideo/vast/vast_xml_samples -->
    
    <script>
      var player = videojs('pv');
      player.ads();
      // player.vast({ url : 'vast2VPAIDLinear.xml'}); // http://demo.tremorvideo.com/proddev/vast/vast2VPAIDLinear.xml, local here because CORS
      player.vast({ url : 'VPAID-Brightcove.xml'}); // http://support.brightcove.com/en/video-cloud/docs/developing-vpaid-swfs
    </script>

  </body>
</html>
// Code goes here

/* Styles go here */

/**
 * Basic Ad support plugin for video.js.
 *
 * Common code to support ad integrations.
 */
(function(window, document, vjs, undefined) {
"use strict";

var

  /**
   * Copies properties from one or more objects onto an original.
   */
  extend = function(obj /*, arg1, arg2, ... */) {
    var arg, i, k;
    for (i=1; i<arguments.length; i++) {
      arg = arguments[i];
      for (k in arg) {
        if (arg.hasOwnProperty(k)) {
          obj[k] = arg[k];
        }
      }
    }
    return obj;
  },

  /**
   * Add a handler for multiple listeners to an object that supports addEventListener() or on().
   *
   * @param {object} obj The object to which the handler will be assigned.
   * @param {mixed} events A string, array of strings, or hash of string/callback pairs.
   * @param {function} callback Invoked when specified events occur, if events param is not a hash.
   *
   * @return {object} obj The object passed in.
   */
  on = function(obj, events, handler) {

    var

      type = Object.prototype.toString.call(events),

      register = function(obj, event, handler) {
        if (obj.addEventListener) {
          obj.addEventListener(event, handler);
        } else if (obj.on) {
          obj.on(event, handler);
        } else if (obj.attachEvent) {
          obj.attachEvent('on' + event, handler);
        } else {
          throw new Error('object has no mechanism for adding event listeners');
        }
      },

      i,
      ii;

    switch (type) {
      case '[object String]':
        register(obj, events, handler);
        break;
      case '[object Array]':
        for (i = 0, ii = events.length; i<ii; i++) {
          register(obj, events[i], handler);
        }
        break;
      case '[object Object]':
        for (i in events) {
          if (events.hasOwnProperty(i)) {
            register(obj, i, events[i]);
          }
        }
        break;
      default:
        throw new Error('Unrecognized events parameter type: ' + type);
    }

    return obj;

  },

  /**
   * Runs the callback at the next available opportunity.
   * @see https://developer.mozilla.org/en-US/docs/Web/API/window.setImmediate
   */
  setImmediate = function(callback) {
    return (
      window.setImmediate ||
      window.requestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.setTimeout
    )(callback, 0);
  },

  /**
   * Clears a callback previously registered with `setImmediate`.
   * @param {id} id The identifier of the callback to abort
   */
  clearImmediate = function(id) {
    return (window.clearImmediate ||
            window.cancelAnimationFrame ||
            window.webkitCancelAnimationFrame ||
            window.mozCancelAnimationFrame ||
            window.clearTimeout)(id);
  },

  /**
   * If ads are not playing, pauses the player at the next available
   * opportunity. Has no effect if ads have started. This function is necessary
   * because pausing a video element while processing a `play` event on iOS can
   * cause the video element to continuously toggle between playing and paused
   * states.
   *
   * @param {object} player The video player
   */
  cancelContentPlay = function(player) {
    if (player.ads.cancelPlayTimeout) {
      // another cancellation is already in flight, so do nothing
      return;
    }

    player.ads.cancelPlayTimeout = setImmediate(function() {

      // deregister the cancel timeout so subsequent cancels are scheduled
      player.ads.cancelPlayTimeout = null;

      if (!player.paused()) {
        player.pause();
      }
    });
  },

  /**
   * Returns an object that captures the portions of player state relevant to
   * video playback. The result of this function can be passed to
   * restorePlayerSnapshot with a player to return the player to the state it
   * was in when this function was invoked.
   * @param {object} player The videojs player object
   */
  getPlayerSnapshot = function(player) {
    var
      tech = player.el().querySelector('.vjs-tech'),
      snapshot = {
        src: player.currentSrc(),
        currentTime: player.currentTime(),
        type: player.currentType()
      };

    if (tech) {
      snapshot.nativePoster = tech.poster;
      snapshot.style = tech.getAttribute('style');
    }

    return snapshot;
  },

  removeClass = function(element, className) {
    var
      classes = element.className.split(/\s+/),
      i = classes.length,
      newClasses = [];
    while (i--) {
      if (classes[i] !== className) {
        newClasses.push(classes[i]);
      }
    }
    element.className = newClasses.join(' ');
  },

  /**
   * Attempts to modify the specified player so that its state is equivalent to
   * the state of the snapshot.
   * @param {object} snapshot - the player state to apply
   */
  restorePlayerSnapshot = function(player, snapshot) {
    var
      // the playback tech
      tech = player.el().querySelector('.vjs-tech'),

      // the number of remaining attempts to restore the snapshot
      attempts = 20,

      // finish restoring the playback state
      resume = function() {
        player.currentTime(snapshot.currentTime);
        //If this wasn't a postroll resume
        if (!player.ended()) {
          player.play();
        }
      },

      // determine if the video element has loaded enough of the snapshot source
      // to be ready to apply the rest of the state
      tryToResume = function() {
        if (tech.seekable === undefined) {
          // if the tech doesn't expose the seekable time ranges, try to
          // resume playback immediately
          resume();
          return;
        }
        if (tech.seekable.length > 0) {
          // if some period of the video is seekable, resume playback
          resume();
          return;
        }

        // delay a bit and then check again unless we're out of attempts
        if (attempts--) {
          setTimeout(tryToResume, 50);
        }
      },

      // whether the video element has been modified since the
      // snapshot was taken
      srcChanged;

    if (snapshot.nativePoster) {
      tech.poster = snapshot.nativePoster;
    }
    
    if ('style' in snapshot) {
      // overwrite all css style properties to restore state precisely
      tech.setAttribute('style', snapshot.style || '');
    }

    // Determine whether the player needs to be restored to its state
    // before ad playback began. With a custom ad display or burned-in
    // ads, the content player state hasn't been modified and so no
    // restoration is required

    if (player.src()) {
      // the player was in src attribute mode before the ad and the
      // src attribute has not been modified, no restoration is required
      // to resume playback
      srcChanged = player.src() !== snapshot.src;
    } else {
      // the player was configured through source element children
      // and the currentSrc hasn't changed, no restoration is required
      // to resume playback
      srcChanged = player.currentSrc() !== snapshot.src;
    }

    if (srcChanged) {
      // if the src changed for ad playback, reset it
      player.src({ src: snapshot.src, type: snapshot.type });
      // safari requires a call to `load` to pick up a changed source
      player.load();
      // and then resume from the snapshots time once the original src has loaded
      player.one('loadedmetadata', tryToResume);
    } else if (!player.ended()) {
      // the src didn't change and this wasn't a postroll
      // just resume playback at the current time.
      player.play();
    }
  },

  /**
   * Remove the poster attribute from the video element tech, if present. When
   * reusing a video element for multiple videos, the poster image will briefly
   * reappear while the new source loads. Removing the attribute ahead of time
   * prevents the poster from showing up between videos.
   * @param {object} player The videojs player object
   */
  removeNativePoster = function(player) {
    var tech = player.el().querySelector('.vjs-tech');
    if (tech) {
      tech.removeAttribute('poster');
    }
  },

  // ---------------------------------------------------------------------------
  // Ad Framework
  // ---------------------------------------------------------------------------

  // default framework settings
  defaults = {
    // maximum amount of time in ms to wait to receive `adsready` from the ad
    // implementation after play has been requested. Ad implementations are
    // expected to load any dynamic libraries and make any requests to determine
    // ad policies for a video during this time.
    timeout: 5000,

    // maximum amount of time in ms to wait for the ad implementation to start
    // linear ad mode after `readyforpreroll` has fired. This is in addition to
    // the standard timeout.
    prerollTimeout: 100,

    // when truthy, instructs the plugin to output additional information about
    // plugin state to the video.js log. On most devices, the video.js log is
    // the same as the developer console.
    debug: false
  },

  adFramework = function(options) {
    var
      player = this,

      // merge options and defaults
      settings = extend({}, defaults, options || {}),

      fsmHandler;

    // replace the ad initializer with the ad namespace
    player.ads = {
      state: 'content-set',

      startLinearAdMode: function() {
        player.trigger('adstart');
      },

      endLinearAdMode: function() {
        player.trigger('adend');
      }
    };

    fsmHandler = function(event) {

      // Ad Playback State Machine
      var
        fsm = {
          'content-set': {
            events: {
              'adscanceled': function() {
                this.state = 'content-playback';
              },
              'adsready': function() {
                this.state = 'ads-ready';
              },
              'play': function() {
                this.state = 'ads-ready?';
                cancelContentPlay(player);

                // remove the poster so it doesn't flash between videos
                removeNativePoster(player);
              }
            }
          },
          'ads-ready': {
            events: {
              'play': function() {
                this.state = 'preroll?';
                cancelContentPlay(player);
              }
            }
          },
          'preroll?': {
            enter: function() {
              // change class to show that we're waiting on ads
              player.el().className += ' vjs-ad-loading';

              // schedule an adtimeout event to fire if we waited too long
              player.ads.timeout = window.setTimeout(function() {
                player.trigger('adtimeout');
              }, settings.prerollTimeout);

              // signal to ad plugin that it's their opportunity to play a preroll
              player.trigger('readyforpreroll');

            },
            leave: function() {
              window.clearTimeout(player.ads.timeout);

              clearImmediate(player.ads.cancelPlayTimeout);
              player.ads.cancelPlayTimeout = null;

              removeClass(player.el(), 'vjs-ad-loading');
            },
            events: {
              'play': function() {
                cancelContentPlay(player);
              },
              'adstart': function() {
                this.state = 'ad-playback';
                player.el().className += ' vjs-ad-playing';
              },
              'adtimeout': function() {
                this.state = 'content-playback';
                player.play();
              }
            }
          },
          'ads-ready?': {
            enter: function() {
              player.el().className += ' vjs-ad-loading';
              player.ads.timeout = window.setTimeout(function() {
                player.trigger('adtimeout');
              }, settings.timeout);
            },
            leave: function() {
              window.clearTimeout(player.ads.timeout);
              removeClass(player.el(), 'vjs-ad-loading');
            },
            events: {
              'play': function() {
                cancelContentPlay(player);
              },
              'adscanceled': function() {
                this.state = 'content-playback';

                clearImmediate(player.ads.cancelPlayTimeout);
                player.ads.cancelPlayTimeout = null;
                player.play();
              },
              'adsready': function() {
                this.state = 'preroll?';
              },
              'adtimeout': function() {
                this.state = 'ad-timeout-playback';
              }
            }
          },
          'ad-timeout-playback': {
            events: {
              'adsready': function() {
                if (player.paused()) {
                  this.state = 'ads-ready';
                } else {
                  this.state = 'preroll?';
                }
              },
              'contentupdate': function() {
                if (player.paused()) {
                  this.state = 'content-set';
                } else {
                  this.state = 'ads-ready?';
                }
              }
            }
          },
          'ad-playback': {
            enter: function() {
              // capture current player state snapshot (playing, currentTime, src)
              this.snapshot = getPlayerSnapshot(player);

              // remove the poster so it doesn't flash between videos
              removeNativePoster(player);
            },
            leave: function() {
              removeClass(player.el(), 'vjs-ad-playing');
              restorePlayerSnapshot(player, this.snapshot);
            },
            events: {
              'adend': function() {
                this.state = 'content-playback';
              }
            }
          },
          'content-playback': {
            events: {
              'adstart': function() {
                this.state = 'ad-playback';
                player.el().className += ' vjs-ad-playing';

                // remove the poster so it doesn't flash between videos
                removeNativePoster(player);
              },
              'contentupdate': function() {
                if (player.paused()) {
                  this.state = 'content-set';
                } else {
                  this.state = 'ads-ready?';
                }
              }
            }
          }
        };

      (function(state) {

        var noop = function() {};

        // process the current event with a noop default handler
        (fsm[state].events[event.type] || noop).apply(player.ads);

        // execute leave/enter callbacks if present
        if (state !== player.ads.state) {
          (fsm[state].leave || noop).apply(player.ads);
          (fsm[player.ads.state].enter || noop).apply(player.ads);

          if (settings.debug) {
            videojs.log('ads', state + ' -> ' + player.ads.state);
          }
        }

      })(player.ads.state);

    };

    // register for the events we're interested in
    on(player, vjs.Html5.Events.concat([
      // events emitted by ad plugin
      'adtimeout',
      'contentupdate',
      // events emitted by third party ad implementors
      'adsready',
      'adscanceled',
      'adstart',  // startLinearAdMode()
      'adend'     // endLinearAdMode()
    ]), fsmHandler);
    
    // keep track of the current content source
    // if you want to change the src of the video without triggering
    // the ad workflow to restart, you can update this variable before
    // modifying the player's source
    player.ads.contentSrc = player.currentSrc();
    
    // implement 'contentupdate' event.
    (function(){
      var
        // check if a new src has been set, if so, trigger contentupdate
        checkSrc = function() {
          var src;
          if (player.ads.state !== 'ad-playback') {
            src = player.currentSrc();
            if (src !== player.ads.contentSrc) {
              player.trigger({
                type: 'contentupdate',
                oldValue: player.ads.contentSrc,
                newValue: src
              });
              player.ads.contentSrc = src;
            }
          }
        };
      // loadstart reliably indicates a new src has been set
      player.on('loadstart', checkSrc);
      // check immediately in case we missed the loadstart
      setImmediate(checkSrc);
    })();

    // kick off the fsm
    if (!player.paused()) {
      // simulate a play event if we're autoplaying
      fsmHandler({type:'play'});
    }

  };

  // register the ad plugin framework
  vjs.plugin('ads', adFramework);

})(window, document, videojs);
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.DMVAST=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

function EventEmitter() {
  this._events = this._events || {};
  this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;

// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;

EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;

// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;

// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
  if (!isNumber(n) || n < 0 || isNaN(n))
    throw TypeError('n must be a positive number');
  this._maxListeners = n;
  return this;
};

EventEmitter.prototype.emit = function(type) {
  var er, handler, len, args, i, listeners;

  if (!this._events)
    this._events = {};

  // If there is no 'error' event listener then throw.
  if (type === 'error') {
    if (!this._events.error ||
        (isObject(this._events.error) && !this._events.error.length)) {
      er = arguments[1];
      if (er instanceof Error) {
        throw er; // Unhandled 'error' event
      } else {
        throw TypeError('Uncaught, unspecified "error" event.');
      }
      return false;
    }
  }

  handler = this._events[type];

  if (isUndefined(handler))
    return false;

  if (isFunction(handler)) {
    switch (arguments.length) {
      // fast cases
      case 1:
        handler.call(this);
        break;
      case 2:
        handler.call(this, arguments[1]);
        break;
      case 3:
        handler.call(this, arguments[1], arguments[2]);
        break;
      // slower
      default:
        len = arguments.length;
        args = new Array(len - 1);
        for (i = 1; i < len; i++)
          args[i - 1] = arguments[i];
        handler.apply(this, args);
    }
  } else if (isObject(handler)) {
    len = arguments.length;
    args = new Array(len - 1);
    for (i = 1; i < len; i++)
      args[i - 1] = arguments[i];

    listeners = handler.slice();
    len = listeners.length;
    for (i = 0; i < len; i++)
      listeners[i].apply(this, args);
  }

  return true;
};

EventEmitter.prototype.addListener = function(type, listener) {
  var m;

  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  if (!this._events)
    this._events = {};

  // To avoid recursion in the case that type === "newListener"! Before
  // adding it to the listeners, first emit "newListener".
  if (this._events.newListener)
    this.emit('newListener', type,
              isFunction(listener.listener) ?
              listener.listener : listener);

  if (!this._events[type])
    // Optimize the case of one listener. Don't need the extra array object.
    this._events[type] = listener;
  else if (isObject(this._events[type]))
    // If we've already got an array, just append.
    this._events[type].push(listener);
  else
    // Adding the second element, need to change to array.
    this._events[type] = [this._events[type], listener];

  // Check for listener leak
  if (isObject(this._events[type]) && !this._events[type].warned) {
    var m;
    if (!isUndefined(this._maxListeners)) {
      m = this._maxListeners;
    } else {
      m = EventEmitter.defaultMaxListeners;
    }

    if (m && m > 0 && this._events[type].length > m) {
      this._events[type].warned = true;
      console.error('(node) warning: possible EventEmitter memory ' +
                    'leak detected. %d listeners added. ' +
                    'Use emitter.setMaxListeners() to increase limit.',
                    this._events[type].length);
      if (typeof console.trace === 'function') {
        // not supported in IE 10
        console.trace();
      }
    }
  }

  return this;
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

EventEmitter.prototype.once = function(type, listener) {
  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  var fired = false;

  function g() {
    this.removeListener(type, g);

    if (!fired) {
      fired = true;
      listener.apply(this, arguments);
    }
  }

  g.listener = listener;
  this.on(type, g);

  return this;
};

// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
  var list, position, length, i;

  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  if (!this._events || !this._events[type])
    return this;

  list = this._events[type];
  length = list.length;
  position = -1;

  if (list === listener ||
      (isFunction(list.listener) && list.listener === listener)) {
    delete this._events[type];
    if (this._events.removeListener)
      this.emit('removeListener', type, listener);

  } else if (isObject(list)) {
    for (i = length; i-- > 0;) {
      if (list[i] === listener ||
          (list[i].listener && list[i].listener === listener)) {
        position = i;
        break;
      }
    }

    if (position < 0)
      return this;

    if (list.length === 1) {
      list.length = 0;
      delete this._events[type];
    } else {
      list.splice(position, 1);
    }

    if (this._events.removeListener)
      this.emit('removeListener', type, listener);
  }

  return this;
};

EventEmitter.prototype.removeAllListeners = function(type) {
  var key, listeners;

  if (!this._events)
    return this;

  // not listening for removeListener, no need to emit
  if (!this._events.removeListener) {
    if (arguments.length === 0)
      this._events = {};
    else if (this._events[type])
      delete this._events[type];
    return this;
  }

  // emit removeListener for all listeners on all events
  if (arguments.length === 0) {
    for (key in this._events) {
      if (key === 'removeListener') continue;
      this.removeAllListeners(key);
    }
    this.removeAllListeners('removeListener');
    this._events = {};
    return this;
  }

  listeners = this._events[type];

  if (isFunction(listeners)) {
    this.removeListener(type, listeners);
  } else {
    // LIFO order
    while (listeners.length)
      this.removeListener(type, listeners[listeners.length - 1]);
  }
  delete this._events[type];

  return this;
};

EventEmitter.prototype.listeners = function(type) {
  var ret;
  if (!this._events || !this._events[type])
    ret = [];
  else if (isFunction(this._events[type]))
    ret = [this._events[type]];
  else
    ret = this._events[type].slice();
  return ret;
};

EventEmitter.listenerCount = function(emitter, type) {
  var ret;
  if (!emitter._events || !emitter._events[type])
    ret = 0;
  else if (isFunction(emitter._events[type]))
    ret = 1;
  else
    ret = emitter._events[type].length;
  return ret;
};

function isFunction(arg) {
  return typeof arg === 'function';
}

function isNumber(arg) {
  return typeof arg === 'number';
}

function isObject(arg) {
  return typeof arg === 'object' && arg !== null;
}

function isUndefined(arg) {
  return arg === void 0;
}

},{}],2:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTAd;

VASTAd = (function() {
  function VASTAd() {
    this.errorURLTemplates = [];
    this.impressionURLTemplates = [];
    this.creatives = [];
  }

  return VASTAd;

})();

module.exports = VASTAd;

},{}],3:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTClient, VASTParser, VASTUtil;

VASTParser = _dereq_('./parser.coffee');

VASTUtil = _dereq_('./util.coffee');

VASTClient = (function() {
  function VASTClient() {}

  VASTClient.cappingFreeLunch = 0;

  VASTClient.cappingMinimumTimeInterval = 0;

  VASTClient.timeout = 0;

  VASTClient.get = function(url, cb) {
    var now;
    now = +new Date();
    if (this.totalCallsTimeout < now) {
      this.totalCalls = 1;
      this.totalCallsTimeout = now + (60 * 60 * 1000);
    } else {
      this.totalCalls++;
    }
    if (this.cappingFreeLunch >= this.totalCalls) {
      cb(null);
      return;
    }
    if (now - this.lastSuccessfullAd < this.cappingMinimumTimeInterval) {
      cb(null);
      return;
    }
    return VASTParser.parse(url, (function(_this) {
      return function(response) {
        return cb(response);
      };
    })(this));
  };

  (function() {
    var defineProperty, storage;
    storage = VASTUtil.storage;
    defineProperty = Object.defineProperty;
    ['lastSuccessfullAd', 'totalCalls', 'totalCallsTimeout'].forEach(function(property) {
      defineProperty(VASTClient, property, {
        get: function() {
          return storage.getItem(property);
        },
        set: function(value) {
          return storage.setItem(property, value);
        },
        configurable: false,
        enumerable: true
      });
    });
    if (VASTClient.totalCalls == null) {
      VASTClient.totalCalls = 0;
    }
    if (VASTClient.totalCallsTimeout == null) {
      VASTClient.totalCallsTimeout = 0;
    }
  })();

  return VASTClient;

})();

module.exports = VASTClient;

},{"./parser.coffee":8,"./util.coffee":14}],4:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTCompanionAd;

VASTCompanionAd = (function() {
  function VASTCompanionAd() {
    this.id = null;
    this.width = 0;
    this.height = 0;
    this.type = null;
    this.staticResource = null;
    this.companionClickThroughURLTemplate = null;
    this.trackingEvents = {};
  }

  return VASTCompanionAd;

})();

module.exports = VASTCompanionAd;

},{}],5:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTCreative, VASTCreativeCompanion, VASTCreativeLinear, VASTCreativeNonLinear,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

VASTCreative = (function() {
  function VASTCreative() {
    this.trackingEvents = {};
  }

  return VASTCreative;

})();

VASTCreativeLinear = (function(_super) {
  __extends(VASTCreativeLinear, _super);

  function VASTCreativeLinear() {
    VASTCreativeLinear.__super__.constructor.apply(this, arguments);
    this.type = "linear";
    this.duration = 0;
    this.skipDelay = null;
    this.mediaFiles = [];
    this.videoClickThroughURLTemplate = null;
    this.videoClickTrackingURLTemplates = [];
  }

  return VASTCreativeLinear;

})(VASTCreative);

VASTCreativeNonLinear = (function(_super) {
  __extends(VASTCreativeNonLinear, _super);

  function VASTCreativeNonLinear() {
    return VASTCreativeNonLinear.__super__.constructor.apply(this, arguments);
  }

  return VASTCreativeNonLinear;

})(VASTCreative);

VASTCreativeCompanion = (function(_super) {
  __extends(VASTCreativeCompanion, _super);

  function VASTCreativeCompanion() {
    this.type = "companion";
    this.variations = [];
    this.videoClickTrackingURLTemplates = [];
  }

  return VASTCreativeCompanion;

})(VASTCreative);

module.exports = {
  VASTCreativeLinear: VASTCreativeLinear,
  VASTCreativeNonLinear: VASTCreativeNonLinear,
  VASTCreativeCompanion: VASTCreativeCompanion
};

},{}],6:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
module.exports = {
  client: _dereq_('./client.coffee'),
  tracker: _dereq_('./tracker.coffee'),
  parser: _dereq_('./parser.coffee'),
  util: _dereq_('./util.coffee')
};

},{"./client.coffee":3,"./parser.coffee":8,"./tracker.coffee":10,"./util.coffee":14}],7:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTMediaFile;

VASTMediaFile = (function() {
  function VASTMediaFile() {
    this.fileURL = null;
    this.deliveryType = "progressive";
    this.mimeType = null;
    this.codec = null;
    this.bitrate = 0;
    this.minBitrate = 0;
    this.maxBitrate = 0;
    this.width = 0;
    this.height = 0;
    this.apiFramework = null;
  }

  return VASTMediaFile;

})();

module.exports = VASTMediaFile;

},{}],8:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var EventEmitter, URLHandler, VASTAd, VASTCompanionAd, VASTCreativeCompanion, VASTCreativeLinear, VASTMediaFile, VASTParser, VASTResponse, VASTUtil,
  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

URLHandler = _dereq_('./urlhandler.coffee');

VASTResponse = _dereq_('./response.coffee');

VASTAd = _dereq_('./ad.coffee');

VASTUtil = _dereq_('./util.coffee');

VASTCreativeLinear = _dereq_('./creative.coffee').VASTCreativeLinear;

VASTCreativeCompanion = _dereq_('./creative.coffee').VASTCreativeCompanion;

VASTMediaFile = _dereq_('./mediafile.coffee');

VASTCompanionAd = _dereq_('./companionad.coffee');

EventEmitter = _dereq_('events').EventEmitter;

VASTParser = (function() {
  var URLTemplateFilters;

  function VASTParser() {}

  URLTemplateFilters = [];

  VASTParser.addURLTemplateFilter = function(func) {
    if (typeof func === 'function') {
      URLTemplateFilters.push(func);
    }
  };

  VASTParser.removeURLTemplateFilter = function() {
    return URLTemplateFilters.pop();
  };

  VASTParser.countURLTemplateFilters = function() {
    return URLTemplateFilters.length;
  };

  VASTParser.clearUrlTemplateFilters = function() {
    return URLTemplateFilters = [];
  };

  VASTParser.parse = function(url, cb) {
    return this._parse(url, null, function(err, response) {
      return cb(response);
    });
  };

  VASTParser.vent = new EventEmitter();

  VASTParser.track = function(templates, errorCode) {
    this.vent.emit('VAST-error', errorCode);
    return VASTUtil.track(templates, errorCode);
  };

  VASTParser.on = function(eventName, cb) {
    return this.vent.on(eventName, cb);
  };

  VASTParser.once = function(eventName, cb) {
    return this.vent.once(eventName, cb);
  };

  VASTParser._parse = function(url, parentURLs, cb) {
    var filter, _i, _len;
    for (_i = 0, _len = URLTemplateFilters.length; _i < _len; _i++) {
      filter = URLTemplateFilters[_i];
      url = filter(url);
    }
    if (parentURLs == null) {
      parentURLs = [];
    }
    parentURLs.push(url);
    return URLHandler.get(url, (function(_this) {
      return function(err, xml) {
        var ad, complete, loopIndex, node, response, _j, _k, _len1, _len2, _ref, _ref1;
        if (err != null) {
          return cb(err);
        }
        response = new VASTResponse();
        if (!(((xml != null ? xml.documentElement : void 0) != null) && xml.documentElement.nodeName === "VAST")) {
          return cb();
        }
        _ref = xml.documentElement.childNodes;
        for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
          node = _ref[_j];
          if (node.nodeName === 'Error') {
            response.errorURLTemplates.push(_this.parseNodeText(node));
          }
        }
        _ref1 = xml.documentElement.childNodes;
        for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
          node = _ref1[_k];
          if (node.nodeName === 'Ad') {
            ad = _this.parseAdElement(node);
            if (ad != null) {
              response.ads.push(ad);
            } else {
              _this.track(response.errorURLTemplates, {
                ERRORCODE: 101
              });
            }
          }
        }
        complete = function(errorAlreadyRaised) {
          var _l, _len3, _ref2;
          if (errorAlreadyRaised == null) {
            errorAlreadyRaised = false;
          }
          if (!response) {
            return;
          }
          _ref2 = response.ads;
          for (_l = 0, _len3 = _ref2.length; _l < _len3; _l++) {
            ad = _ref2[_l];
            if (ad.nextWrapperURL != null) {
              return;
            }
          }
          if (response.ads.length === 0) {
            if (!errorAlreadyRaised) {
              _this.track(response.errorURLTemplates, {
                ERRORCODE: 303
              });
            }
            response = null;
          }
          return cb(null, response);
        };
        loopIndex = response.ads.length;
        while (loopIndex--) {
          ad = response.ads[loopIndex];
          if (ad.nextWrapperURL == null) {
            continue;
          }
          (function(ad) {
            var baseURL, _ref2;
            if (parentURLs.length >= 10 || (_ref2 = ad.nextWrapperURL, __indexOf.call(parentURLs, _ref2) >= 0)) {
              _this.track(ad.errorURLTemplates, {
                ERRORCODE: 302
              });
              response.ads.splice(response.ads.indexOf(ad), 1);
              complete();
              return;
            }
            if (ad.nextWrapperURL.indexOf('://') === -1) {
              baseURL = url.slice(0, url.lastIndexOf('/'));
              ad.nextWrapperURL = "" + baseURL + "/" + ad.nextWrapperURL;
            }
            return _this._parse(ad.nextWrapperURL, parentURLs, function(err, wrappedResponse) {
              var creative, errorAlreadyRaised, eventName, index, wrappedAd, _base, _l, _len3, _len4, _len5, _len6, _m, _n, _o, _ref3, _ref4, _ref5, _ref6;
              errorAlreadyRaised = false;
              if (err != null) {
                _this.track(ad.errorURLTemplates, {
                  ERRORCODE: 301
                });
                response.ads.splice(response.ads.indexOf(ad), 1);
                errorAlreadyRaised = true;
              } else if (wrappedResponse == null) {
                _this.track(ad.errorURLTemplates, {
                  ERRORCODE: 303
                });
                response.ads.splice(response.ads.indexOf(ad), 1);
                errorAlreadyRaised = true;
              } else {
                response.errorURLTemplates = response.errorURLTemplates.concat(wrappedResponse.errorURLTemplates);
                index = response.ads.indexOf(ad);
                response.ads.splice(index, 1);
                _ref3 = wrappedResponse.ads;
                for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
                  wrappedAd = _ref3[_l];
                  wrappedAd.errorURLTemplates = ad.errorURLTemplates.concat(wrappedAd.errorURLTemplates);
                  wrappedAd.impressionURLTemplates = ad.impressionURLTemplates.concat(wrappedAd.impressionURLTemplates);
                  if (ad.trackingEvents != null) {
                    _ref4 = wrappedAd.creatives;
                    for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) {
                      creative = _ref4[_m];
                      if (creative.type === 'linear') {
                        _ref5 = Object.keys(ad.trackingEvents);
                        for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) {
                          eventName = _ref5[_n];
                          (_base = creative.trackingEvents)[eventName] || (_base[eventName] = []);
                          creative.trackingEvents[eventName] = creative.trackingEvents[eventName].concat(ad.trackingEvents[eventName]);
                        }
                      }
                    }
                  }
                  if (ad.videoClickTrackingURLTemplates != null) {
                    _ref6 = wrappedAd.creatives;
                    for (_o = 0, _len6 = _ref6.length; _o < _len6; _o++) {
                      creative = _ref6[_o];
                      if (creative.type === 'linear') {
                        creative.videoClickTrackingURLTemplates = creative.videoClickTrackingURLTemplates.concat(ad.videoClickTrackingURLTemplates);
                      }
                    }
                  }
                  response.ads.splice(index, 0, wrappedAd);
                }
              }
              delete ad.nextWrapperURL;
              return complete(errorAlreadyRaised);
            });
          })(ad);
        }
        return complete();
      };
    })(this));
  };

  VASTParser.childByName = function(node, name) {
    var child, _i, _len, _ref;
    _ref = node.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      child = _ref[_i];
      if (child.nodeName === name) {
        return child;
      }
    }
  };

  VASTParser.childsByName = function(node, name) {
    var child, childs, _i, _len, _ref;
    childs = [];
    _ref = node.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      child = _ref[_i];
      if (child.nodeName === name) {
        childs.push(child);
      }
    }
    return childs;
  };

  VASTParser.parseAdElement = function(adElement) {
    var adTypeElement, _i, _len, _ref;
    _ref = adElement.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      adTypeElement = _ref[_i];
      if (adTypeElement.nodeName === "Wrapper") {
        return this.parseWrapperElement(adTypeElement);
      } else if (adTypeElement.nodeName === "InLine") {
        return this.parseInLineElement(adTypeElement);
      }
    }
  };

  VASTParser.parseWrapperElement = function(wrapperElement) {
    var ad, creative, wrapperCreativeElement, wrapperURLElement, _i, _len, _ref;
    ad = this.parseInLineElement(wrapperElement);
    wrapperURLElement = this.childByName(wrapperElement, "VASTAdTagURI");
    if (wrapperURLElement != null) {
      ad.nextWrapperURL = this.parseNodeText(wrapperURLElement);
    }
    wrapperCreativeElement = null;
    _ref = ad.creatives;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      creative = _ref[_i];
      if (creative.type === 'linear') {
        wrapperCreativeElement = creative;
        break;
      }
    }
    if (wrapperCreativeElement != null) {
      if (wrapperCreativeElement.trackingEvents != null) {
        ad.trackingEvents = wrapperCreativeElement.trackingEvents;
      }
      if (wrapperCreativeElement.videoClickTrackingURLTemplates != null) {
        ad.videoClickTrackingURLTemplates = wrapperCreativeElement.videoClickTrackingURLTemplates;
      }
    }
    if (ad.nextWrapperURL != null) {
      return ad;
    }
  };

  VASTParser.parseInLineElement = function(inLineElement) {
    var ad, creative, creativeElement, creativeTypeElement, node, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
    ad = new VASTAd();
    _ref = inLineElement.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.nodeName) {
        case "Error":
          ad.errorURLTemplates.push(this.parseNodeText(node));
          break;
        case "Impression":
          ad.impressionURLTemplates.push(this.parseNodeText(node));
          break;
        case "Creatives":
          _ref1 = this.childsByName(node, "Creative");
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
            creativeElement = _ref1[_j];
            _ref2 = creativeElement.childNodes;
            for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
              creativeTypeElement = _ref2[_k];
              switch (creativeTypeElement.nodeName) {
                case "Linear":
                  creative = this.parseCreativeLinearElement(creativeTypeElement);
                  if (creative) {
                    ad.creatives.push(creative);
                  }
                  break;
                case "CompanionAds":
                  creative = this.parseCompanionAd(creativeTypeElement);
                  if (creative) {
                    ad.creatives.push(creative);
                  }
              }
            }
          }
      }
    }
    return ad;
  };

  VASTParser.parseCreativeLinearElement = function(creativeElement) {
    var clickTrackingElement, creative, eventName, mediaFile, mediaFileElement, mediaFilesElement, percent, skipOffset, trackingElement, trackingEventsElement, trackingURLTemplate, videoClicksElement, _base, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4;
    creative = new VASTCreativeLinear();
    creative.duration = this.parseDuration(this.parseNodeText(this.childByName(creativeElement, "Duration")));
    if (creative.duration === -1 && creativeElement.parentNode.parentNode.parentNode.nodeName !== 'Wrapper') {
      return null;
    }
    skipOffset = creativeElement.getAttribute("skipoffset");
    if (skipOffset == null) {
      creative.skipDelay = null;
    } else if (skipOffset.charAt(skipOffset.length - 1) === "%") {
      percent = parseInt(skipOffset, 10);
      creative.skipDelay = creative.duration * (percent / 100);
    } else {
      creative.skipDelay = this.parseDuration(skipOffset);
    }
    videoClicksElement = this.childByName(creativeElement, "VideoClicks");
    if (videoClicksElement != null) {
      creative.videoClickThroughURLTemplate = this.parseNodeText(this.childByName(videoClicksElement, "ClickThrough"));
      _ref = this.childsByName(videoClicksElement, "ClickTracking");
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        clickTrackingElement = _ref[_i];
        creative.videoClickTrackingURLTemplates.push(this.parseNodeText(clickTrackingElement));
      }
    }
    _ref1 = this.childsByName(creativeElement, "TrackingEvents");
    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
      trackingEventsElement = _ref1[_j];
      _ref2 = this.childsByName(trackingEventsElement, "Tracking");
      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
        trackingElement = _ref2[_k];
        eventName = trackingElement.getAttribute("event");
        trackingURLTemplate = this.parseNodeText(trackingElement);
        if ((eventName != null) && (trackingURLTemplate != null)) {
          if ((_base = creative.trackingEvents)[eventName] == null) {
            _base[eventName] = [];
          }
          creative.trackingEvents[eventName].push(trackingURLTemplate);
        }
      }
    }
    _ref3 = this.childsByName(creativeElement, "MediaFiles");
    for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
      mediaFilesElement = _ref3[_l];
      _ref4 = this.childsByName(mediaFilesElement, "MediaFile");
      for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) {
        mediaFileElement = _ref4[_m];
        mediaFile = new VASTMediaFile();
        mediaFile.fileURL = this.parseNodeText(mediaFileElement);
        mediaFile.deliveryType = mediaFileElement.getAttribute("delivery");
        mediaFile.codec = mediaFileElement.getAttribute("codec");
        mediaFile.mimeType = mediaFileElement.getAttribute("type");
        mediaFile.apiFramework = mediaFileElement.getAttribute("apiFramework");
        mediaFile.bitrate = parseInt(mediaFileElement.getAttribute("bitrate") || 0);
        mediaFile.minBitrate = parseInt(mediaFileElement.getAttribute("minBitrate") || 0);
        mediaFile.maxBitrate = parseInt(mediaFileElement.getAttribute("maxBitrate") || 0);
        mediaFile.width = parseInt(mediaFileElement.getAttribute("width") || 0);
        mediaFile.height = parseInt(mediaFileElement.getAttribute("height") || 0);
        creative.mediaFiles.push(mediaFile);
      }
    }
    return creative;
  };

  VASTParser.parseCompanionAd = function(creativeElement) {
    var companionAd, companionResource, creative, eventName, staticElement, trackingElement, trackingEventsElement, trackingURLTemplate, _base, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
    creative = new VASTCreativeCompanion();
    _ref = this.childsByName(creativeElement, "Companion");
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      companionResource = _ref[_i];
      companionAd = new VASTCompanionAd();
      companionAd.id = companionResource.getAttribute("id") || null;
      companionAd.width = companionResource.getAttribute("width");
      companionAd.height = companionResource.getAttribute("height");
      _ref1 = this.childsByName(companionResource, "StaticResource");
      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
        staticElement = _ref1[_j];
        companionAd.type = staticElement.getAttribute("creativeType") || 0;
        companionAd.staticResource = this.parseNodeText(staticElement);
      }
      _ref2 = this.childsByName(companionResource, "TrackingEvents");
      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
        trackingEventsElement = _ref2[_k];
        _ref3 = this.childsByName(trackingEventsElement, "Tracking");
        for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
          trackingElement = _ref3[_l];
          eventName = trackingElement.getAttribute("event");
          trackingURLTemplate = this.parseNodeText(trackingElement);
          if ((eventName != null) && (trackingURLTemplate != null)) {
            if ((_base = companionAd.trackingEvents)[eventName] == null) {
              _base[eventName] = [];
            }
            companionAd.trackingEvents[eventName].push(trackingURLTemplate);
          }
        }
      }
      companionAd.companionClickThroughURLTemplate = this.parseNodeText(this.childByName(companionResource, "CompanionClickThrough"));
      creative.variations.push(companionAd);
    }
    return creative;
  };

  VASTParser.parseDuration = function(durationString) {
    var durationComponents, hours, minutes, seconds, secondsAndMS;
    if (!(durationString != null)) {
      return -1;
    }
    durationComponents = durationString.split(":");
    if (durationComponents.length !== 3) {
      return -1;
    }
    secondsAndMS = durationComponents[2].split(".");
    seconds = parseInt(secondsAndMS[0]);
    if (secondsAndMS.length === 2) {
      seconds += parseFloat("0." + secondsAndMS[1]);
    }
    minutes = parseInt(durationComponents[1] * 60);
    hours = parseInt(durationComponents[0] * 60 * 60);
    if (isNaN(hours || isNaN(minutes || isNaN(seconds || minutes > 60 * 60 || seconds > 60)))) {
      return -1;
    }
    return hours + minutes + seconds;
  };

  VASTParser.parseNodeText = function(node) {
    return node && (node.textContent || node.text);
  };

  return VASTParser;

})();

module.exports = VASTParser;

},{"./ad.coffee":2,"./companionad.coffee":4,"./creative.coffee":5,"./mediafile.coffee":7,"./response.coffee":9,"./urlhandler.coffee":11,"./util.coffee":14,"events":1}],9:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTResponse;

VASTResponse = (function() {
  function VASTResponse() {
    this.ads = [];
    this.errorURLTemplates = [];
  }

  return VASTResponse;

})();

module.exports = VASTResponse;

},{}],10:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var EventEmitter, VASTClient, VASTCreativeLinear, VASTTracker, VASTUtil,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

VASTClient = _dereq_('./client.coffee');

VASTUtil = _dereq_('./util.coffee');

VASTCreativeLinear = _dereq_('./creative.coffee').VASTCreativeLinear;

EventEmitter = _dereq_('events').EventEmitter;

VASTTracker = (function(_super) {
  __extends(VASTTracker, _super);

  function VASTTracker(ad, creative) {
    var eventName, events, _ref;
    this.ad = ad;
    this.creative = creative;
    this.muted = false;
    this.impressed = false;
    this.skipable = false;
    this.skipDelayDefault = -1;
    this.trackingEvents = {};
    this.emitAlwaysEvents = ['creativeView', 'start', 'firstQuartile', 'midpoint', 'thirdQuartile', 'complete', 'resume', 'pause', 'rewind', 'skip', 'closeLinear', 'close'];
    _ref = creative.trackingEvents;
    for (eventName in _ref) {
      events = _ref[eventName];
      this.trackingEvents[eventName] = events.slice(0);
    }
    if (creative instanceof VASTCreativeLinear) {
      this.setDuration(creative.duration);
      this.skipDelay = creative.skipDelay;
      this.linear = true;
      this.clickThroughURLTemplate = creative.videoClickThroughURLTemplate;
      this.clickTrackingURLTemplates = creative.videoClickTrackingURLTemplates;
    } else {
      this.skipDelay = -1;
      this.linear = false;
    }
    this.on('start', function() {
      VASTClient.lastSuccessfullAd = +new Date();
    });
  }

  VASTTracker.prototype.setDuration = function(duration) {
    this.assetDuration = duration;
    return this.quartiles = {
      'firstQuartile': Math.round(25 * this.assetDuration) / 100,
      'midpoint': Math.round(50 * this.assetDuration) / 100,
      'thirdQuartile': Math.round(75 * this.assetDuration) / 100
    };
  };

  VASTTracker.prototype.setProgress = function(progress) {
    var eventName, events, percent, quartile, skipDelay, time, _i, _len, _ref;
    skipDelay = this.skipDelay === null ? this.skipDelayDefault : this.skipDelay;
    if (skipDelay !== -1 && !this.skipable) {
      if (skipDelay > progress) {
        this.emit('skip-countdown', skipDelay - progress);
      } else {
        this.skipable = true;
        this.emit('skip-countdown', 0);
      }
    }
    if (this.linear && this.assetDuration > 0) {
      events = [];
      if (progress > 0) {
        events.push("start");
        percent = Math.round(progress / this.assetDuration * 100);
        events.push("progress-" + percent + "%");
        _ref = this.quartiles;
        for (quartile in _ref) {
          time = _ref[quartile];
          if ((time <= progress && progress <= (time + 1))) {
            events.push(quartile);
          }
        }
      }
      for (_i = 0, _len = events.length; _i < _len; _i++) {
        eventName = events[_i];
        this.track(eventName, true);
      }
      if (progress < this.progress) {
        this.track("rewind");
      }
    }
    return this.progress = progress;
  };

  VASTTracker.prototype.setMuted = function(muted) {
    if (this.muted !== muted) {
      this.track(muted ? "muted" : "unmuted");
    }
    return this.muted = muted;
  };

  VASTTracker.prototype.setPaused = function(paused) {
    if (this.paused !== paused) {
      this.track(paused ? "pause" : "resume");
    }
    return this.paused = paused;
  };

  VASTTracker.prototype.setFullscreen = function(fullscreen) {
    if (this.fullscreen !== fullscreen) {
      this.track(fullscreen ? "fullscreen" : "exitFullscreen");
    }
    return this.fullscreen = fullscreen;
  };

  VASTTracker.prototype.setSkipDelay = function(duration) {
    if (typeof duration === 'number') {
      return this.skipDelay = duration;
    }
  };

  VASTTracker.prototype.load = function() {
    if (!this.impressed) {
      this.impressed = true;
      this.trackURLs(this.ad.impressionURLTemplates);
      return this.track("creativeView");
    }
  };

  VASTTracker.prototype.errorWithCode = function(errorCode) {
    return this.trackURLs(this.ad.errorURLTemplates, {
      ERRORCODE: errorCode
    });
  };

  VASTTracker.prototype.complete = function() {
    return this.track("complete");
  };

  VASTTracker.prototype.stop = function() {
    return this.track(this.linear ? "closeLinear" : "close");
  };

  VASTTracker.prototype.skip = function() {
    this.track("skip");
    return this.trackingEvents = [];
  };

  VASTTracker.prototype.click = function() {
    var clickThroughURL, variables, _ref;
    if ((_ref = this.clickTrackingURLTemplates) != null ? _ref.length : void 0) {
      this.trackURLs(this.clickTrackingURLTemplates);
    }
    if (this.clickThroughURLTemplate != null) {
      if (this.linear) {
        variables = {
          CONTENTPLAYHEAD: this.progressFormated()
        };
      }
      clickThroughURL = VASTUtil.resolveURLTemplates([this.clickThroughURLTemplate], variables)[0];
      return this.emit("clickthrough", clickThroughURL);
    }
  };

  VASTTracker.prototype.track = function(eventName, once) {
    var idx, trackingURLTemplates;
    if (once == null) {
      once = false;
    }
    if (eventName === 'closeLinear' && ((this.trackingEvents[eventName] == null) && (this.trackingEvents['close'] != null))) {
      eventName = 'close';
    }
    trackingURLTemplates = this.trackingEvents[eventName];
    idx = this.emitAlwaysEvents.indexOf(eventName);
    if (trackingURLTemplates != null) {
      this.emit(eventName, '');
      this.trackURLs(trackingURLTemplates);
    } else if (idx !== -1) {
      this.emit(eventName, '');
    }
    if (once === true) {
      delete this.trackingEvents[eventName];
      if (idx > -1) {
        this.emitAlwaysEvents.splice(idx, 1);
      }
    }
  };

  VASTTracker.prototype.trackURLs = function(URLTemplates, variables) {
    if (variables == null) {
      variables = {};
    }
    if (this.linear) {
      variables["CONTENTPLAYHEAD"] = this.progressFormated();
    }
    return VASTUtil.track(URLTemplates, variables);
  };

  VASTTracker.prototype.progressFormated = function() {
    var h, m, ms, s, seconds;
    seconds = parseInt(this.progress);
    h = seconds / (60 * 60);
    if (h.length < 2) {
      h = "0" + h;
    }
    m = seconds / 60 % 60;
    if (m.length < 2) {
      m = "0" + m;
    }
    s = seconds % 60;
    if (s.length < 2) {
      s = "0" + m;
    }
    ms = parseInt((this.progress - seconds) * 100);
    return "" + h + ":" + m + ":" + s + "." + ms;
  };

  return VASTTracker;

})(EventEmitter);

module.exports = VASTTracker;

},{"./client.coffee":3,"./creative.coffee":5,"./util.coffee":14,"events":1}],11:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var URLHandler, flash, xhr;

xhr = _dereq_('./urlhandlers/xmlhttprequest.coffee');

flash = _dereq_('./urlhandlers/flash.coffee');

URLHandler = (function() {
  function URLHandler() {}

  URLHandler.get = function(url, cb) {
    if (typeof window === "undefined" || window === null) {
      return _dereq_('./urlhandlers/' + 'node.coffee').get(url, cb);
    } else if (xhr.supported()) {
      return xhr.get(url, cb);
    } else if (flash.supported()) {
      return flash.get(url, cb);
    } else {
      return cb();
    }
  };

  return URLHandler;

})();

module.exports = URLHandler;

},{"./urlhandlers/flash.coffee":12,"./urlhandlers/xmlhttprequest.coffee":13}],12:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var FlashURLHandler;

FlashURLHandler = (function() {
  function FlashURLHandler() {}

  FlashURLHandler.xdr = function() {
    var xdr;
    if (window.XDomainRequest) {
      xdr = new XDomainRequest();
    }
    return xdr;
  };

  FlashURLHandler.supported = function() {
    return !!this.xdr();
  };

  FlashURLHandler.get = function(url, cb) {
    var xdr, xmlDocument;
    if (xmlDocument = typeof window.ActiveXObject === "function" ? new window.ActiveXObject("Microsoft.XMLDOM") : void 0) {
      xmlDocument.async = false;
    } else {
      return cb();
    }
    xdr = this.xdr();
    xdr.open('GET', url);
    xdr.send();
    return xdr.onload = function() {
      xmlDocument.loadXML(xdr.responseText);
      return cb(null, xmlDocument);
    };
  };

  return FlashURLHandler;

})();

module.exports = FlashURLHandler;

},{}],13:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var XHRURLHandler;

XHRURLHandler = (function() {
  function XHRURLHandler() {}

  XHRURLHandler.xhr = function() {
    var xhr;
    xhr = new window.XMLHttpRequest();
    if ('withCredentials' in xhr) {
      return xhr;
    }
  };

  XHRURLHandler.supported = function() {
    return !!this.xhr();
  };

  XHRURLHandler.get = function(url, cb) {
    var xhr;
    try {
      xhr = this.xhr();
      xhr.open('GET', url);
      xhr.send();
      return xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
          return cb(null, xhr.responseXML);
        }
      };
    } catch (_error) {
      return cb();
    }
  };

  return XHRURLHandler;

})();

module.exports = XHRURLHandler;

},{}],14:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTUtil;

VASTUtil = (function() {
  function VASTUtil() {}

  VASTUtil.track = function(URLTemplates, variables) {
    var URL, URLs, i, _i, _len, _results;
    URLs = this.resolveURLTemplates(URLTemplates, variables);
    _results = [];
    for (_i = 0, _len = URLs.length; _i < _len; _i++) {
      URL = URLs[_i];
      if (typeof window !== "undefined" && window !== null) {
        i = new Image();
        _results.push(i.src = URL);
      } else {

      }
    }
    return _results;
  };

  VASTUtil.resolveURLTemplates = function(URLTemplates, variables) {
    var URLTemplate, URLs, key, macro1, macro2, resolveURL, value, _i, _len;
    URLs = [];
    if (variables == null) {
      variables = {};
    }
    if (!("CACHEBUSTING" in variables)) {
      variables["CACHEBUSTING"] = Math.round(Math.random() * 1.0e+10);
    }
    variables["random"] = variables["CACHEBUSTING"];
    for (_i = 0, _len = URLTemplates.length; _i < _len; _i++) {
      URLTemplate = URLTemplates[_i];
      resolveURL = URLTemplate;
      if (!resolveURL) {
        continue;
      }
      for (key in variables) {
        value = variables[key];
        macro1 = "[" + key + "]";
        macro2 = "%%" + key + "%%";
        resolveURL = resolveURL.replace(macro1, value);
        resolveURL = resolveURL.replace(macro2, value);
      }
      URLs.push(resolveURL);
    }
    return URLs;
  };

  VASTUtil.storage = (function() {
    var data, isDisabled, storage, storageError;
    try {
      storage = typeof window !== "undefined" && window !== null ? window.localStorage || window.sessionStorage : null;
    } catch (_error) {
      storageError = _error;
      storage = null;
    }
    isDisabled = function(store) {
      var e, testValue;
      try {
        testValue = '__VASTUtil__';
        store.setItem(testValue, testValue);
        if (store.getItem(testValue) !== testValue) {
          return true;
        }
      } catch (_error) {
        e = _error;
        return true;
      }
      return false;
    };
    if ((storage == null) || isDisabled(storage)) {
      data = {};
      storage = {
        length: 0,
        getItem: function(key) {
          return data[key];
        },
        setItem: function(key, value) {
          data[key] = value;
          this.length = Object.keys(data).length;
        },
        removeItem: function(key) {
          delete data[key];
          this.length = Object.keys(data).length;
        },
        clear: function() {
          data = {};
          this.length = 0;
        }
      };
    }
    return storage;
  })();

  return VASTUtil;

})();

module.exports = VASTUtil;

},{}]},{},[6])
(6)
});
(function(vjs, vast, undefined) {
"use strict";
  var
  extend = function(obj) {
    var arg, i, k;
    for (i = 1; i < arguments.length; i++) {
      arg = arguments[i];
      for (k in arg) {
        if (arg.hasOwnProperty(k)) {
          obj[k] = arg[k];
        }
      }
    }
    return obj;
  },

  defaults = {
    skip: 5, // negative disables. Ignored for VPAID as VPAID asset controls it itself
    bitrate: 1000, //advised bitrate for VPAID ads
    viewMode: 'normal', //view mode for VPAID ads. Possible values: normal, thumbnail, fullscreen
    vpaidElement: undefined //html element used for vpaid ads
  },

  vastPlugin = function(options) {
    var player = this;
    var settings = extend({}, defaults, options || {});
    var vpaidObj, vpaidListeners = {}, vpaidIFrame = null, vpaidPlayer = null, vpaidTrackInterval = -1, vpaidSeeker;

    if (player.ads === undefined) {
        console.log("VAST requires videojs-contrib-ads");
        return;
    }

    // If we don't have a VAST url, just bail out.
    if(settings.url === undefined) {
      player.trigger('adtimeout');
      return;
    }

    //preserve support for older video.js versions
    function localize(text) {
      if (player.localize) {
        return player.localize(text);
      } else {
        return text;
      }
    }

    // videojs-ads triggers this when src changes
    player.on('contentupdate', function(){
      player.vast.getContent(settings.url);
    });

    player.on('readyforpreroll', function() {
      //in case we have something simple to show
      if (player.vast.sources) {
        player.vast.preroll();
      } else {
        player.vast.prerollVPAID();
      }
    });

    player.vast.getContent = function(url) {
      vast.client.get(url, function(response) {
        if (response) {
                 debugger;
           for (var adIdx = 0; adIdx < response.ads.length; adIdx++) {
            var ad = response.ads[adIdx];
            player.vast.companion = undefined;
            var foundCreative = false, foundCompanion = false, foundVPAID = false;
            for (var creaIdx = 0; creaIdx < ad.creatives.length; creaIdx++) {
              var creative = ad.creatives[creaIdx];
              if (creative.type === "linear" && !foundCreative) {

                if (creative.mediaFiles.length) {

                  player.vastTracker = new vast.tracker(ad, creative);
                  var vpaidTech = player.vast.findOptimalVPAIDTech(creative.mediaFiles);
                  if (vpaidTech) {
                    foundVPAID = true;
                    player.vast.initVPAID(vpaidTech, function() {
                      player.vast.createVPAIDControls();
                      player.trigger('adsready');
                    });
                  } else {

                    player.vast.sources = player.vast.createSourceObjects(creative.mediaFiles);
                    if (!player.vast.sources.length) {
                      player.trigger('adtimeout');
                      return;
                    }

                    player.vast.initSimpleVAST(ad);
                  }

                  foundCreative = true;
                }

              } else if (creative.type === "companion" && !foundCompanion) {
                //TODO is it ever used?
                player.vast.companion = creative;

                foundCompanion = true;

              }
            }

            if (player.vastTracker) {
              //vpaid will trigger adsready in async manner when all assets are loaded
              if (!foundVPAID) {
                player.trigger("adsready");
              }
              break;
            } else {
              // Inform ad server we can't find suitable media file for this ad
              vast.util.track(ad.errorURLTemplates, {ERRORCODE: 403});
            }
          }
        }

        if (!player.vastTracker) {
          // No pre-roll, start video
          player.trigger('adtimeout');
        }
      });
    };

    player.vast.createSkipButton = function() {
      var skipButton = document.createElement("div");
      skipButton.className = "vast-skip-button";
      if (settings.skip < 0) {
        skipButton.style.display = "none";
      }
      player.vast.skipButton = skipButton;
      player.el().appendChild(skipButton);

      skipButton.onclick = function (e) {
        if ((' ' + player.vast.skipButton.className + ' ').indexOf(' enabled ') >= 0) {
          if (vpaidObj) {
            vpaidObj.skipAd();
            //will tear down after event AdSkipped is triggered
          } else {
            player.vastTracker.skip();
            player.vast.tearDown();
          }
        }
        if (Event.prototype.stopPropagation !== undefined) {
          e.stopPropagation();
        } else {
          return false;
        }
      };
    };

    player.vast.getClickThrough = function () {
      var clickthrough;
      if (player.vastTracker.clickThroughURLTemplate) {
        clickthrough = vast.util.resolveURLTemplates(
          [player.vastTracker.clickThroughURLTemplate],
          {
            CACHEBUSTER: Math.round(Math.random() * 1.0e+10),
            CONTENTPLAYHEAD: player.vastTracker.progressFormated()
          }
        )[0];
      }
      return clickthrough;
    };

    player.vast.preroll = function() {
      player.ads.startLinearAdMode();
      player.vast.showControls = player.controls();
      if (player.vast.showControls ) {
        player.controls(false);
      }
      player.autoplay(true);
      // play your linear ad content
      var adSources = player.vast.sources;
      player.src(adSources);

      var clickthrough = player.vast.getClickThrough();
      var blocker = document.createElement("a");
      blocker.className = "vast-blocker";
      blocker.href = clickthrough || "#";
      blocker.target = "_blank";
      blocker.onclick = function() {
        if (player.paused()) {
          player.play();
          return false;
        }
        var clicktrackers = player.vastTracker.clickTrackingURLTemplate;
        if (clicktrackers) {
          player.vastTracker.trackURLs([clicktrackers]);
        }
        player.trigger("adclick");
      };
      player.vast.blocker = blocker;
      player.el().insertBefore(blocker, player.controlBar.el());

      player.vast.createSkipButton();
      player.on("timeupdate", player.vast.timeupdate);
      player.one("ended", player.vast.tearDown);
    };

    player.vast.prerollVPAID = function() {
      player.ads.startLinearAdMode();
      player.vast.showControls = player.controls();
      if (player.vast.showControls ) {
        player.controls(false);
      }
      vpaidObj.startAd();
      vpaidTrackInterval = setInterval(player.vast.updateSeeker, 500);
      //player might be playing if video tags are different
      player.pause();
    };

    player.vast.tearDown = function() {
      if (player.vast.skipButton) {
        player.vast.skipButton.parentNode.removeChild(player.vast.skipButton);
        player.vast.skipButton = undefined;
      }
      if (player.vast.blocker) {
        player.vast.blocker.parentNode.removeChild(player.vast.blocker);
        player.vast.blocker = undefined;
      }
      player.off('timeupdate', player.vast.timeupdate);
      player.off('ended', player.vast.tearDown);
      if (player.vast.showControls ) {
        player.controls(true);
      }

      if (vpaidObj) {
        for (var event in vpaidListeners) {
          if (!vpaidListeners.hasOwnProperty(event)) {
            continue;
          }
          var listeners = vpaidListeners[event];
          for (var i = 0; i < listeners.length; i++) {
            vpaidObj.unsubscribe(listeners[i], event);
          }
        }
        if (vpaidIFrame) {
          vpaidIFrame.parentNode.removeChild(vpaidIFrame);
        }
        vpaidObj = null;
        vpaidIFrame = null;
        vpaidListeners = {};
        player.vast.removeVPAIDControls();
      }
      if (vpaidTrackInterval != -1) {
        clearInterval(vpaidTrackInterval);
        vpaidTrackInterval = -1;
      }
      if (vpaidPlayer) {
        vpaidPlayer.parentNode.removeChild(vpaidPlayer);
      }

      //complete in async manner. Sometimes when shutdown too soon, video does not start playback
      setTimeout(function() {
        player.ads.endLinearAdMode();
      }, 0);
    };

    player.vast.enableSkipButton = function () {
      if ((' ' + player.vast.skipButton.className + ' ').indexOf(' enabled ') === -1) {
        player.vast.skipButton.className += " enabled";
        player.vast.skipButton.innerHTML = localize("Skip");
      }
    };

    player.vast.timeupdate = function(e) {
      player.loadingSpinner.el().style.display = "none";
      var timeLeft = Math.ceil(settings.skip - player.currentTime());
      if(timeLeft > 0) {
        var translation = localize('Skip in %num%...');
        player.vast.skipButton.innerHTML = translation.replace('%num%', timeLeft);
      } else {
        player.vast.enableSkipButton();
      }
    };
    player.vast.createSourceObjects = function (media_files) {
      var sourcesByFormat = {}, i, j, tech;
      var techOrder = player.options().techOrder;
      for (i = 0, j = techOrder.length; i < j; i++) {
        var techName = techOrder[i].charAt(0).toUpperCase() + techOrder[i].slice(1);
        tech = window.videojs[techName];

        // Check if the current tech is defined before continuing
        if (!tech) {
          continue;
        }

        // Check if the browser supports this technology
        if (tech.isSupported()) {
          // Loop through each source object
          for (var a = 0, b = media_files.length; a < b; a++) {
            var media_file = media_files[a];
            var source = {type:media_file.mimeType, src:media_file.fileURL};
            // Check if source can be played with this technology
            if (tech.canPlaySource(source)) {
              if (sourcesByFormat[techOrder[i]] === undefined) {
                sourcesByFormat[techOrder[i]] = [];
              }
              sourcesByFormat[techOrder[i]].push({
                type:media_file.mimeType,
                src: media_file.fileURL,
                width: media_file.width,
                height: media_file.height
              });
            }
          }
        }
      }
      // Create sources in preferred format order
      var sources = [];
      for (j = 0; j < techOrder.length; j++) {
        tech = techOrder[j];
        if (sourcesByFormat[tech] !== undefined) {
          for (i = 0; i < sourcesByFormat[tech].length; i++) {
            sources.push(sourcesByFormat[tech][i]);
          }
        }
      }
      return sources;
    };

    //Find optimal available VPAID tech. Best match is javascript, otherwise last found will be returned
    player.vast.findOptimalVPAIDTech = function(mediaFiles) {
      var foundTech = null;
      for (var i = 0; i < mediaFiles.length; i++) {
        var mediaFile = mediaFiles[i];
        if (mediaFile.apiFramework != "VPAID") {
          continue;
        }

        if (mediaFile.mimeType == 'application/javascript') {
          //bingo!
          return mediaFile;
        } else {
          foundTech = mediaFile;
        }
      }

      return foundTech;
    };

    player.vast.loadVPAIDResource = function(mediaFile, callback) {
      if (mediaFile.mimeType != "application/javascript") {
        throw new Error("Loading not javascript vpaid ads is not supported");
      }

      vpaidIFrame = document.createElement('iframe');
      vpaidIFrame.style.display = 'none';
      vpaidIFrame.onload = function() {
        var iframeDoc = vpaidIFrame.contentDocument;
        //Credos http://stackoverflow.com/a/950146/51966
        // Adding the script tag to the head as suggested before
        var head = iframeDoc.getElementsByTagName('head')[0];
        var script = iframeDoc.createElement('script');
        script.type = 'text/javascript';
        script.src = mediaFile.fileURL;

        // Then bind the event to the callback function.
        // There are several events for cross browser compatibility.
        script.onreadystatechange = script.onload = function() {
          if (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") {
            if (vpaidIFrame.contentWindow.getVPAIDAd === undefined) {
              console.log("Unable to load script or script do not have getVPAIDAd method");
              return;
            }

            callback(vpaidIFrame.contentWindow.getVPAIDAd());
          }
        };

        head.appendChild(script);
      };

      document.body.appendChild(vpaidIFrame);
    };

    player.vast.initSimpleVAST = function(ad) {
      var errorOccurred = false,
        canplayFn = function() {
          this.vastTracker.load();
        },
        timeupdateFn = function() {
          if (isNaN(this.vastTracker.assetDuration)) {
            this.vastTracker.assetDuration = this.duration();
          }
          this.vastTracker.setProgress(this.currentTime());
        },
        playFn = function() {
          this.vastTracker.setPaused(false);
        },
        pauseFn = function() {
          this.vastTracker.setPaused(true);
        },
        errorFn = function() {
          // Inform ad server we couldn't play the media file for this ad
          vast.util.track(ad.errorURLTemplates, {ERRORCODE: 405});
          errorOccurred = true;
          player.trigger('ended');
        };

      player.on('canplay', canplayFn);
      player.on('timeupdate', timeupdateFn);
      player.on('play', playFn);
      player.on('pause', pauseFn);
      player.on('error', errorFn);

      player.one('ended', function() {
        player.off('canplay', canplayFn);
        player.off('timeupdate', timeupdateFn);
        player.off('play', playFn);
        player.off('pause', pauseFn);
        player.off('error', errorFn);
        if (!errorOccurred) {
          this.vastTracker.complete();
        }
      });
    };

    player.vast.initVPAID = function(vpaidTech, cb) {
      player.vast.loadVPAIDResource(vpaidTech, function(vpaid) {
        vpaidObj = vpaid;
        if (vpaid.handshakeVersion('2.0') != '2.0') {
          throw new Error("Versions different to 2.0 are not supported");
        }

        var root = player.el();
        var pref = {
          videoSlotCanAutoPlay: true,
          slot: root
        };
        if (/iphone|ipad|android/gi.test(navigator.userAgent)) {
          pref.videoSlot = player.el().querySelector('.vjs-tech');
          if (pref.videoSlot.tagName != 'video') { //might be using non-default source, fallback to custom video slot
            pref.videoSlot = undefined;
          }
        }

        if (!pref.videoSlot) {
          vpaidPlayer = document.createElement('video');

          vpaidPlayer.className = 'vast-blocker';
          root.appendChild(vpaidPlayer);
          pref.videoSlot = vpaidPlayer;
        }

        player.on('resize', function() {
          vpaid.resizeAd(player.width(), player.height(), settings.viewMode);
        });
        player.on('fullscreenchange', function() {
          if (player.isFullScreen()) {
            vpaid.resizeAd(0, 0, 'fullscreen');
          } else {
            vpaid.resizeAd(player.width, player.width, settings.viewMode);
          }
        });

        function setTrackerDuration() {
          if (vpaidObj.getAdDuration) {
            var duration = vpaidObj.getAdDuration();
            if (duration > 0) {
              player.vastTracker.setDuration(duration);
            }
          }
        }

        player.vast.onVPAID('AdError', function() {
          player.vast.tearDown();
        });
        player.vast.oneVPAID('AdLoaded', function() {
          if (cb) {
            cb(vpaid);
          }

          setTrackerDuration();
        });
        player.vast.oneVPAID('AdStopped', function() {
          player.vast.tearDown();
        });

        player.vast.onVPAID('AdDurationChange', function() {
          setTrackerDuration();
        });
        player.vast.onVPAID('AdRemainingTimeChange', function() {
          setTrackerDuration();
        });
        player.vast.oneVPAID('AdSkipped', function() {
          player.vastTracker.skip();
          player.vast.tearDown();
        });
        player.vast.oneVPAID('AdStarted', function() {
          player.ads.startLinearAdMode();
          player.vastTracker.load();
        });
        player.vast.onVPAID('AdVolumeChange', function() {
          player.vastTracker.setMuted(vpaidObj.getAdVolume() === 0);
          player.setVolume(vpaidObj.getAdVolume());
        });
        player.vast.onVPAID('AdImpression', function() {
          //TODO
        });
        player.vast.onVPAID('AdVideoStart', function() {
          player.vastTracker.setProgress(0);
        });
        player.vast.onVPAID('AdVideoFirstQuartile', function() {
          var emulatedFirstQuartile = Math.round(25 * vpaidObj.getAdDuration()) / 100;
          player.vastTracker.setProgress(emulatedFirstQuartile);
        });
        player.vast.onVPAID('AdVideoMidpoint', function() {
          var emulatedMidpoint = Math.round(50 * vpaidObj.getAdDuration()) / 100;
          player.vastTracker.setProgress(emulatedMidpoint);
        });
        player.vast.onVPAID('AdVideoThirdQuartile', function() {
          var emulatedThirdQuartile = Math.round(75 * vpaidObj.getAdDuration()) / 100;
          player.vastTracker.setProgress(emulatedThirdQuartile);
        });
        player.vast.onVPAID('AdVideoComplete', function() {
          player.vastTracker.setProgress(vpaidObj.getAdDuration());
        });
        player.vast.onVPAID('AdClickThru', function(url, id, playerHandles) {
          player.vastTracker.click();
          if (playerHandles) {
            if (!url) {
              url = player.vast.getClickThrough();
            }

            //TODO open url
          }
        });
        player.vast.onVPAID('AdUserAcceptInvitation', function() {
          //TODO implement in vast client
          player.vastTracker.acceptInvitation();
        });
        player.vast.onVPAID('AdUserClose', function() {
          player.vastTracker.close();
        });
        player.vast.onVPAID('AdPaused', function() {
          player.vastTracker.setPaused(true);
        });
        player.vast.onVPAID('AdPlaying', function() {
          player.vastTracker.setPaused(false);
        });
        player.vast.onVPAID('AdSkippableStateChange', function() {
          if (vpaidObj.getAdSkippableState()) {
            player.vast.createSkipButton();
            player.vast.enableSkipButton();
          } else if (player.vast.skipButton) {
            player.vast.skipButton.parentNode.removeChild(player.vast.skipButton);
          }
        });
        //TODO add creativeData
        vpaid.initAd(player.width(), player.height(), settings.viewMode, settings.bitrate, {}, pref);
      });
    };

    player.vast.createVPAIDControls = function() {
      vpaidSeeker = document.createElement('div');
      vpaidSeeker.className = 'vast-ad-control';
      vpaidSeeker.innerHTML = '<span class="vast-advertisement">' + localize('Advertisement') + ' <span class="vast-ad-left"></span></span><div class="vast-progress-holder"><div class="vjs-play-progress"></div></div>';
      player.el().appendChild(vpaidSeeker, player.el().childNodes[0]);
    };

    player.vast.removeVPAIDControls = function() {
      if (vpaidSeeker) {
        vpaidSeeker.parentNode.removeChild(vpaidSeeker);
      }
    };

    player.vast.updateSeeker = function() {
      if (!vpaidObj && vpaidTrackInterval != -1) { //might be it was shutdown earlier than first seek could appear. Silently remove itself
        clearInterval(vpaidTrackInterval);
        vpaidTrackInterval = -1;
        return;
      }
      var remaining = vpaidObj.getAdRemainingTime();
      if (remaining < 0) {
        return;
      }
      var total = vpaidObj.getAdDuration();
      if (total < 0) {
        return;
      }
      var progress = vpaidSeeker.querySelector('.vjs-play-progress');
      progress.style.width = ((total - remaining) / total * 100) + '%';

      //taken from videojs-iva
      var remainingMinutes = Math.floor(remaining / 60);
      var remainingSeconds = Math.floor(remaining % 60);
      if (remainingSeconds.toString().length < 2) {
        remainingSeconds = '0' + remainingSeconds;
      }
      var remains = remainingMinutes + ':' + remainingSeconds;
      progress.innerHTML = '<span class="vjs-control-text">' + remains + '</span>';
      vpaidSeeker.querySelector('.vast-ad-left').innerHTML = remains;
    };

    player.vast.onVPAID = function(event, func) {
      if (vpaidListeners[event] === undefined) {
        vpaidListeners[event] = [];
      }
      vpaidListeners[event].push(func);
      vpaidObj.subscribe(func, event);
    };

    player.vast.offVPAID = function(event, func) {
      vpaidObj.unsubscribe(func, event);
      if (vpaidListeners[event]) {
        var listeners = vpaidListeners[event],
          index = -1;
        if (!Array.prototype.indexOf) {
          for (var i = 0; i < listeners.length; i++) {
            if (listeners[i] == func) {
              index = i;
              break;
            }
          }
        } else {
          index = listeners.indexOf(func);
        }

        if (index != -1) {
          listeners.splice(index, 1);
        }
        if (listeners.length === 0) {
          delete vpaidListeners[event];
        }
      }
    };

    player.vast.oneVPAID = function(event, func) {
      var wrapper = function() {
        player.vast.offVPAID(event, wrapper);
        func();
      };
      player.vast.onVPAID(event, wrapper);
    };

    // make an ads request immediately so we're ready when the viewer
    // hits "play"
    if (player.currentSrc()) {
      player.vast.getContent(settings.url);
    }
  };

  vjs.plugin('vast', vastPlugin);
}(window.videojs, window.DMVAST));
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.DMVAST=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

function EventEmitter() {
  this._events = this._events || {};
  this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;

// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;

EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;

// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;

// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
  if (!isNumber(n) || n < 0 || isNaN(n))
    throw TypeError('n must be a positive number');
  this._maxListeners = n;
  return this;
};

EventEmitter.prototype.emit = function(type) {
  var er, handler, len, args, i, listeners;

  if (!this._events)
    this._events = {};

  // If there is no 'error' event listener then throw.
  if (type === 'error') {
    if (!this._events.error ||
        (isObject(this._events.error) && !this._events.error.length)) {
      er = arguments[1];
      if (er instanceof Error) {
        throw er; // Unhandled 'error' event
      } else {
        throw TypeError('Uncaught, unspecified "error" event.');
      }
      return false;
    }
  }

  handler = this._events[type];

  if (isUndefined(handler))
    return false;

  if (isFunction(handler)) {
    switch (arguments.length) {
      // fast cases
      case 1:
        handler.call(this);
        break;
      case 2:
        handler.call(this, arguments[1]);
        break;
      case 3:
        handler.call(this, arguments[1], arguments[2]);
        break;
      // slower
      default:
        len = arguments.length;
        args = new Array(len - 1);
        for (i = 1; i < len; i++)
          args[i - 1] = arguments[i];
        handler.apply(this, args);
    }
  } else if (isObject(handler)) {
    len = arguments.length;
    args = new Array(len - 1);
    for (i = 1; i < len; i++)
      args[i - 1] = arguments[i];

    listeners = handler.slice();
    len = listeners.length;
    for (i = 0; i < len; i++)
      listeners[i].apply(this, args);
  }

  return true;
};

EventEmitter.prototype.addListener = function(type, listener) {
  var m;

  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  if (!this._events)
    this._events = {};

  // To avoid recursion in the case that type === "newListener"! Before
  // adding it to the listeners, first emit "newListener".
  if (this._events.newListener)
    this.emit('newListener', type,
              isFunction(listener.listener) ?
              listener.listener : listener);

  if (!this._events[type])
    // Optimize the case of one listener. Don't need the extra array object.
    this._events[type] = listener;
  else if (isObject(this._events[type]))
    // If we've already got an array, just append.
    this._events[type].push(listener);
  else
    // Adding the second element, need to change to array.
    this._events[type] = [this._events[type], listener];

  // Check for listener leak
  if (isObject(this._events[type]) && !this._events[type].warned) {
    var m;
    if (!isUndefined(this._maxListeners)) {
      m = this._maxListeners;
    } else {
      m = EventEmitter.defaultMaxListeners;
    }

    if (m && m > 0 && this._events[type].length > m) {
      this._events[type].warned = true;
      console.error('(node) warning: possible EventEmitter memory ' +
                    'leak detected. %d listeners added. ' +
                    'Use emitter.setMaxListeners() to increase limit.',
                    this._events[type].length);
      if (typeof console.trace === 'function') {
        // not supported in IE 10
        console.trace();
      }
    }
  }

  return this;
};

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

EventEmitter.prototype.once = function(type, listener) {
  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  var fired = false;

  function g() {
    this.removeListener(type, g);

    if (!fired) {
      fired = true;
      listener.apply(this, arguments);
    }
  }

  g.listener = listener;
  this.on(type, g);

  return this;
};

// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
  var list, position, length, i;

  if (!isFunction(listener))
    throw TypeError('listener must be a function');

  if (!this._events || !this._events[type])
    return this;

  list = this._events[type];
  length = list.length;
  position = -1;

  if (list === listener ||
      (isFunction(list.listener) && list.listener === listener)) {
    delete this._events[type];
    if (this._events.removeListener)
      this.emit('removeListener', type, listener);

  } else if (isObject(list)) {
    for (i = length; i-- > 0;) {
      if (list[i] === listener ||
          (list[i].listener && list[i].listener === listener)) {
        position = i;
        break;
      }
    }

    if (position < 0)
      return this;

    if (list.length === 1) {
      list.length = 0;
      delete this._events[type];
    } else {
      list.splice(position, 1);
    }

    if (this._events.removeListener)
      this.emit('removeListener', type, listener);
  }

  return this;
};

EventEmitter.prototype.removeAllListeners = function(type) {
  var key, listeners;

  if (!this._events)
    return this;

  // not listening for removeListener, no need to emit
  if (!this._events.removeListener) {
    if (arguments.length === 0)
      this._events = {};
    else if (this._events[type])
      delete this._events[type];
    return this;
  }

  // emit removeListener for all listeners on all events
  if (arguments.length === 0) {
    for (key in this._events) {
      if (key === 'removeListener') continue;
      this.removeAllListeners(key);
    }
    this.removeAllListeners('removeListener');
    this._events = {};
    return this;
  }

  listeners = this._events[type];

  if (isFunction(listeners)) {
    this.removeListener(type, listeners);
  } else {
    // LIFO order
    while (listeners.length)
      this.removeListener(type, listeners[listeners.length - 1]);
  }
  delete this._events[type];

  return this;
};

EventEmitter.prototype.listeners = function(type) {
  var ret;
  if (!this._events || !this._events[type])
    ret = [];
  else if (isFunction(this._events[type]))
    ret = [this._events[type]];
  else
    ret = this._events[type].slice();
  return ret;
};

EventEmitter.listenerCount = function(emitter, type) {
  var ret;
  if (!emitter._events || !emitter._events[type])
    ret = 0;
  else if (isFunction(emitter._events[type]))
    ret = 1;
  else
    ret = emitter._events[type].length;
  return ret;
};

function isFunction(arg) {
  return typeof arg === 'function';
}

function isNumber(arg) {
  return typeof arg === 'number';
}

function isObject(arg) {
  return typeof arg === 'object' && arg !== null;
}

function isUndefined(arg) {
  return arg === void 0;
}

},{}],2:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTAd;

VASTAd = (function() {
  function VASTAd() {
    this.errorURLTemplates = [];
    this.impressionURLTemplates = [];
    this.creatives = [];
  }

  return VASTAd;

})();

module.exports = VASTAd;

},{}],3:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTClient, VASTParser, VASTUtil;

VASTParser = _dereq_('./parser.coffee');

VASTUtil = _dereq_('./util.coffee');

VASTClient = (function() {
  function VASTClient() {}

  VASTClient.cappingFreeLunch = 0;

  VASTClient.cappingMinimumTimeInterval = 0;

  VASTClient.timeout = 0;

  VASTClient.get = function(url, cb) {
    var now;
    now = +new Date();
    if (this.totalCallsTimeout < now) {
      this.totalCalls = 1;
      this.totalCallsTimeout = now + (60 * 60 * 1000);
    } else {
      this.totalCalls++;
    }
    if (this.cappingFreeLunch >= this.totalCalls) {
      cb(null);
      return;
    }
    if (now - this.lastSuccessfullAd < this.cappingMinimumTimeInterval) {
      cb(null);
      return;
    }
    return VASTParser.parse(url, (function(_this) {
      return function(response) {
        return cb(response);
      };
    })(this));
  };

  (function() {
    var defineProperty, storage;
    storage = VASTUtil.storage;
    defineProperty = Object.defineProperty;
    ['lastSuccessfullAd', 'totalCalls', 'totalCallsTimeout'].forEach(function(property) {
      defineProperty(VASTClient, property, {
        get: function() {
          return storage.getItem(property);
        },
        set: function(value) {
          return storage.setItem(property, value);
        },
        configurable: false,
        enumerable: true
      });
    });
    if (VASTClient.totalCalls == null) {
      VASTClient.totalCalls = 0;
    }
    if (VASTClient.totalCallsTimeout == null) {
      VASTClient.totalCallsTimeout = 0;
    }
  })();

  return VASTClient;

})();

module.exports = VASTClient;

},{"./parser.coffee":8,"./util.coffee":14}],4:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTCompanionAd;

VASTCompanionAd = (function() {
  function VASTCompanionAd() {
    this.id = null;
    this.width = 0;
    this.height = 0;
    this.type = null;
    this.staticResource = null;
    this.companionClickThroughURLTemplate = null;
    this.trackingEvents = {};
  }

  return VASTCompanionAd;

})();

module.exports = VASTCompanionAd;

},{}],5:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTCreative, VASTCreativeCompanion, VASTCreativeLinear, VASTCreativeNonLinear,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

VASTCreative = (function() {
  function VASTCreative() {
    this.trackingEvents = {};
  }

  return VASTCreative;

})();

VASTCreativeLinear = (function(_super) {
  __extends(VASTCreativeLinear, _super);

  function VASTCreativeLinear() {
    VASTCreativeLinear.__super__.constructor.apply(this, arguments);
    this.type = "linear";
    this.duration = 0;
    this.skipDelay = null;
    this.mediaFiles = [];
    this.videoClickThroughURLTemplate = null;
    this.videoClickTrackingURLTemplates = [];
  }

  return VASTCreativeLinear;

})(VASTCreative);

VASTCreativeNonLinear = (function(_super) {
  __extends(VASTCreativeNonLinear, _super);

  function VASTCreativeNonLinear() {
    return VASTCreativeNonLinear.__super__.constructor.apply(this, arguments);
  }

  return VASTCreativeNonLinear;

})(VASTCreative);

VASTCreativeCompanion = (function(_super) {
  __extends(VASTCreativeCompanion, _super);

  function VASTCreativeCompanion() {
    this.type = "companion";
    this.variations = [];
    this.videoClickTrackingURLTemplates = [];
  }

  return VASTCreativeCompanion;

})(VASTCreative);

module.exports = {
  VASTCreativeLinear: VASTCreativeLinear,
  VASTCreativeNonLinear: VASTCreativeNonLinear,
  VASTCreativeCompanion: VASTCreativeCompanion
};

},{}],6:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
module.exports = {
  client: _dereq_('./client.coffee'),
  tracker: _dereq_('./tracker.coffee'),
  parser: _dereq_('./parser.coffee'),
  util: _dereq_('./util.coffee')
};

},{"./client.coffee":3,"./parser.coffee":8,"./tracker.coffee":10,"./util.coffee":14}],7:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTMediaFile;

VASTMediaFile = (function() {
  function VASTMediaFile() {
    this.fileURL = null;
    this.deliveryType = "progressive";
    this.mimeType = null;
    this.codec = null;
    this.bitrate = 0;
    this.minBitrate = 0;
    this.maxBitrate = 0;
    this.width = 0;
    this.height = 0;
    this.apiFramework = null;
  }

  return VASTMediaFile;

})();

module.exports = VASTMediaFile;

},{}],8:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var URLHandler, VASTAd, VASTCompanionAd, VASTCreativeCompanion, VASTCreativeLinear, VASTMediaFile, VASTParser, VASTResponse, VASTUtil,
  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

URLHandler = _dereq_('./urlhandler.coffee');

VASTResponse = _dereq_('./response.coffee');

VASTAd = _dereq_('./ad.coffee');

VASTUtil = _dereq_('./util.coffee');

VASTCreativeLinear = _dereq_('./creative.coffee').VASTCreativeLinear;

VASTCreativeCompanion = _dereq_('./creative.coffee').VASTCreativeCompanion;

VASTMediaFile = _dereq_('./mediafile.coffee');

VASTCompanionAd = _dereq_('./companionad.coffee');

VASTParser = (function() {
  var URLTemplateFilters;

  function VASTParser() {}

  URLTemplateFilters = [];

  VASTParser.addURLTemplateFilter = function(func) {
    if (typeof func === 'function') {
      URLTemplateFilters.push(func);
    }
  };

  VASTParser.removeURLTemplateFilter = function() {
    return URLTemplateFilters.pop();
  };

  VASTParser.countURLTemplateFilters = function() {
    return URLTemplateFilters.length;
  };

  VASTParser.clearUrlTemplateFilters = function() {
    return URLTemplateFilters = [];
  };

  VASTParser.parse = function(url, cb) {
    return this._parse(url, null, function(err, response) {
      return cb(response);
    });
  };

  VASTParser._parse = function(url, parentURLs, cb) {
    var filter, _i, _len;
    for (_i = 0, _len = URLTemplateFilters.length; _i < _len; _i++) {
      filter = URLTemplateFilters[_i];
      url = filter(url);
    }
    if (parentURLs == null) {
      parentURLs = [];
    }
    parentURLs.push(url);
    return URLHandler.get(url, (function(_this) {
      return function(err, xml) {
        var ad, complete, loopIndex, node, response, _j, _k, _len1, _len2, _ref, _ref1;
        if (err != null) {
          return cb(err);
        }
        response = new VASTResponse();
        if (!(((xml != null ? xml.documentElement : void 0) != null) && xml.documentElement.nodeName === "VAST")) {
          return cb();
        }
        _ref = xml.documentElement.childNodes;
        for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
          node = _ref[_j];
          if (node.nodeName === 'Error') {
            response.errorURLTemplates.push(_this.parseNodeText(node));
          }
        }
        _ref1 = xml.documentElement.childNodes;
        for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
          node = _ref1[_k];
          if (node.nodeName === 'Ad') {
            ad = _this.parseAdElement(node);
            if (ad != null) {
              response.ads.push(ad);
            } else {
              VASTUtil.track(response.errorURLTemplates, {
                ERRORCODE: 101
              });
            }
          }
        }
        complete = function() {
          var _l, _len3, _ref2;
          if (!response) {
            return;
          }
          _ref2 = response.ads;
          for (_l = 0, _len3 = _ref2.length; _l < _len3; _l++) {
            ad = _ref2[_l];
            if (ad.nextWrapperURL != null) {
              return;
            }
          }
          if (response.ads.length === 0) {
            VASTUtil.track(response.errorURLTemplates, {
              ERRORCODE: 303
            });
            response = null;
          }
          return cb(null, response);
        };
        loopIndex = response.ads.length;
        while (loopIndex--) {
          ad = response.ads[loopIndex];
          if (ad.nextWrapperURL == null) {
            continue;
          }
          (function(ad) {
            var baseURL, _ref2;
            if (parentURLs.length >= 10 || (_ref2 = ad.nextWrapperURL, __indexOf.call(parentURLs, _ref2) >= 0)) {
              VASTUtil.track(ad.errorURLTemplates, {
                ERRORCODE: 302
              });
              response.ads.splice(response.ads.indexOf(ad), 1);
              complete();
              return;
            }
            if (ad.nextWrapperURL.indexOf('://') === -1) {
              baseURL = url.slice(0, url.lastIndexOf('/'));
              ad.nextWrapperURL = "" + baseURL + "/" + ad.nextWrapperURL;
            }
            return _this._parse(ad.nextWrapperURL, parentURLs, function(err, wrappedResponse) {
              var creative, eventName, index, wrappedAd, _base, _l, _len3, _len4, _len5, _len6, _m, _n, _o, _ref3, _ref4, _ref5, _ref6;
              if (err != null) {
                VASTUtil.track(ad.errorURLTemplates, {
                  ERRORCODE: 301
                });
                response.ads.splice(response.ads.indexOf(ad), 1);
              } else if (wrappedResponse == null) {
                VASTUtil.track(ad.errorURLTemplates, {
                  ERRORCODE: 303
                });
                response.ads.splice(response.ads.indexOf(ad), 1);
              } else {
                response.errorURLTemplates = response.errorURLTemplates.concat(wrappedResponse.errorURLTemplates);
                index = response.ads.indexOf(ad);
                response.ads.splice(index, 1);
                _ref3 = wrappedResponse.ads;
                for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
                  wrappedAd = _ref3[_l];
                  wrappedAd.errorURLTemplates = ad.errorURLTemplates.concat(wrappedAd.errorURLTemplates);
                  wrappedAd.impressionURLTemplates = ad.impressionURLTemplates.concat(wrappedAd.impressionURLTemplates);
                  if (ad.trackingEvents != null) {
                    _ref4 = wrappedAd.creatives;
                    for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) {
                      creative = _ref4[_m];
                      if (creative.type === 'linear') {
                        _ref5 = Object.keys(ad.trackingEvents);
                        for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) {
                          eventName = _ref5[_n];
                          (_base = creative.trackingEvents)[eventName] || (_base[eventName] = []);
                          creative.trackingEvents[eventName] = creative.trackingEvents[eventName].concat(ad.trackingEvents[eventName]);
                        }
                      }
                    }
                  }
                  if (ad.videoClickTrackingURLTemplates != null) {
                    _ref6 = wrappedAd.creatives;
                    for (_o = 0, _len6 = _ref6.length; _o < _len6; _o++) {
                      creative = _ref6[_o];
                      if (creative.type === 'linear') {
                        creative.videoClickTrackingURLTemplates = creative.videoClickTrackingURLTemplates.concat(ad.videoClickTrackingURLTemplates);
                      }
                    }
                  }
                  response.ads.splice(index, 0, wrappedAd);
                }
              }
              delete ad.nextWrapperURL;
              return complete();
            });
          })(ad);
        }
        return complete();
      };
    })(this));
  };

  VASTParser.childByName = function(node, name) {
    var child, _i, _len, _ref;
    _ref = node.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      child = _ref[_i];
      if (child.nodeName === name) {
        return child;
      }
    }
  };

  VASTParser.childsByName = function(node, name) {
    var child, childs, _i, _len, _ref;
    childs = [];
    _ref = node.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      child = _ref[_i];
      if (child.nodeName === name) {
        childs.push(child);
      }
    }
    return childs;
  };

  VASTParser.parseAdElement = function(adElement) {
    var adTypeElement, _i, _len, _ref;
    _ref = adElement.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      adTypeElement = _ref[_i];
      if (adTypeElement.nodeName === "Wrapper") {
        return this.parseWrapperElement(adTypeElement);
      } else if (adTypeElement.nodeName === "InLine") {
        return this.parseInLineElement(adTypeElement);
      }
    }
  };

  VASTParser.parseWrapperElement = function(wrapperElement) {
    var ad, creative, wrapperCreativeElement, wrapperURLElement, _i, _len, _ref;
    ad = this.parseInLineElement(wrapperElement);
    wrapperURLElement = this.childByName(wrapperElement, "VASTAdTagURI");
    if (wrapperURLElement != null) {
      ad.nextWrapperURL = this.parseNodeText(wrapperURLElement);
    }
    wrapperCreativeElement = null;
    _ref = ad.creatives;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      creative = _ref[_i];
      if (creative.type === 'linear') {
        wrapperCreativeElement = creative;
        break;
      }
    }
    if (wrapperCreativeElement != null) {
      if (wrapperCreativeElement.trackingEvents != null) {
        ad.trackingEvents = wrapperCreativeElement.trackingEvents;
      }
      if (wrapperCreativeElement.videoClickTrackingURLTemplates != null) {
        ad.videoClickTrackingURLTemplates = wrapperCreativeElement.videoClickTrackingURLTemplates;
      }
    }
    if (ad.nextWrapperURL != null) {
      return ad;
    }
  };

  VASTParser.parseInLineElement = function(inLineElement) {
    var ad, creative, creativeElement, creativeTypeElement, node, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
    ad = new VASTAd();
    _ref = inLineElement.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      switch (node.nodeName) {
        case "Error":
          ad.errorURLTemplates.push(this.parseNodeText(node));
          break;
        case "Impression":
          ad.impressionURLTemplates.push(this.parseNodeText(node));
          break;
        case "Creatives":
          _ref1 = this.childsByName(node, "Creative");
          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
            creativeElement = _ref1[_j];
            _ref2 = creativeElement.childNodes;
            for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
              creativeTypeElement = _ref2[_k];
              switch (creativeTypeElement.nodeName) {
                case "Linear":
                  creative = this.parseCreativeLinearElement(creativeTypeElement);
                  if (creative) {
                    ad.creatives.push(creative);
                  }
                  break;
                case "CompanionAds":
                  creative = this.parseCompanionAd(creativeTypeElement);
                  if (creative) {
                    ad.creatives.push(creative);
                  }
              }
            }
          }
      }
    }
    return ad;
  };

  VASTParser.parseCreativeLinearElement = function(creativeElement) {
    var clickTrackingElement, creative, eventName, mediaFile, mediaFileElement, mediaFilesElement, percent, skipOffset, trackingElement, trackingEventsElement, trackingURLTemplate, videoClicksElement, _base, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4;
    creative = new VASTCreativeLinear();
    creative.duration = this.parseDuration(this.parseNodeText(this.childByName(creativeElement, "Duration")));
    if (creative.duration === -1 && creativeElement.parentNode.parentNode.parentNode.nodeName !== 'Wrapper') {
      return null;
    }
    skipOffset = creativeElement.getAttribute("skipoffset");
    if (skipOffset == null) {
      creative.skipDelay = null;
    } else if (skipOffset.charAt(skipOffset.length - 1) === "%") {
      percent = parseInt(skipOffset, 10);
      creative.skipDelay = creative.duration * (percent / 100);
    } else {
      creative.skipDelay = this.parseDuration(skipOffset);
    }
    videoClicksElement = this.childByName(creativeElement, "VideoClicks");
    if (videoClicksElement != null) {
      creative.videoClickThroughURLTemplate = this.parseNodeText(this.childByName(videoClicksElement, "ClickThrough"));
      _ref = this.childsByName(videoClicksElement, "ClickTracking");
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        clickTrackingElement = _ref[_i];
        creative.videoClickTrackingURLTemplates.push(this.parseNodeText(clickTrackingElement));
      }
    }
    _ref1 = this.childsByName(creativeElement, "TrackingEvents");
    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
      trackingEventsElement = _ref1[_j];
      _ref2 = this.childsByName(trackingEventsElement, "Tracking");
      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
        trackingElement = _ref2[_k];
        eventName = trackingElement.getAttribute("event");
        trackingURLTemplate = this.parseNodeText(trackingElement);
        if ((eventName != null) && (trackingURLTemplate != null)) {
          if ((_base = creative.trackingEvents)[eventName] == null) {
            _base[eventName] = [];
          }
          creative.trackingEvents[eventName].push(trackingURLTemplate);
        }
      }
    }
    _ref3 = this.childsByName(creativeElement, "MediaFiles");
    for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
      mediaFilesElement = _ref3[_l];
      _ref4 = this.childsByName(mediaFilesElement, "MediaFile");
      for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) {
        mediaFileElement = _ref4[_m];
        mediaFile = new VASTMediaFile();
        mediaFile.fileURL = this.parseNodeText(mediaFileElement);
        mediaFile.deliveryType = mediaFileElement.getAttribute("delivery");
        mediaFile.codec = mediaFileElement.getAttribute("codec");
        mediaFile.mimeType = mediaFileElement.getAttribute("type");
        mediaFile.apiFramework = mediaFileElement.getAttribute("apiFramework");
        mediaFile.bitrate = parseInt(mediaFileElement.getAttribute("bitrate") || 0);
        mediaFile.minBitrate = parseInt(mediaFileElement.getAttribute("minBitrate") || 0);
        mediaFile.maxBitrate = parseInt(mediaFileElement.getAttribute("maxBitrate") || 0);
        mediaFile.width = parseInt(mediaFileElement.getAttribute("width") || 0);
        mediaFile.height = parseInt(mediaFileElement.getAttribute("height") || 0);
        creative.mediaFiles.push(mediaFile);
      }
    }
    return creative;
  };

  VASTParser.parseCompanionAd = function(creativeElement) {
    var companionAd, companionResource, creative, eventName, staticElement, trackingElement, trackingEventsElement, trackingURLTemplate, _base, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
    creative = new VASTCreativeCompanion();
    _ref = this.childsByName(creativeElement, "Companion");
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      companionResource = _ref[_i];
      companionAd = new VASTCompanionAd();
      companionAd.id = companionResource.getAttribute("id") || null;
      companionAd.width = companionResource.getAttribute("width");
      companionAd.height = companionResource.getAttribute("height");
      _ref1 = this.childsByName(companionResource, "StaticResource");
      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
        staticElement = _ref1[_j];
        companionAd.type = staticElement.getAttribute("creativeType") || 0;
        companionAd.staticResource = this.parseNodeText(staticElement);
      }
      _ref2 = this.childsByName(companionResource, "TrackingEvents");
      for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
        trackingEventsElement = _ref2[_k];
        _ref3 = this.childsByName(trackingEventsElement, "Tracking");
        for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
          trackingElement = _ref3[_l];
          eventName = trackingElement.getAttribute("event");
          trackingURLTemplate = this.parseNodeText(trackingElement);
          if ((eventName != null) && (trackingURLTemplate != null)) {
            if ((_base = companionAd.trackingEvents)[eventName] == null) {
              _base[eventName] = [];
            }
            companionAd.trackingEvents[eventName].push(trackingURLTemplate);
          }
        }
      }
      companionAd.companionClickThroughURLTemplate = this.parseNodeText(this.childByName(companionResource, "CompanionClickThrough"));
      creative.variations.push(companionAd);
    }
    return creative;
  };

  VASTParser.parseDuration = function(durationString) {
    var durationComponents, hours, minutes, seconds, secondsAndMS;
    if (!(durationString != null)) {
      return -1;
    }
    durationComponents = durationString.split(":");
    if (durationComponents.length !== 3) {
      return -1;
    }
    secondsAndMS = durationComponents[2].split(".");
    seconds = parseInt(secondsAndMS[0]);
    if (secondsAndMS.length === 2) {
      seconds += parseFloat("0." + secondsAndMS[1]);
    }
    minutes = parseInt(durationComponents[1] * 60);
    hours = parseInt(durationComponents[0] * 60 * 60);
    if (isNaN(hours || isNaN(minutes || isNaN(seconds || minutes > 60 * 60 || seconds > 60)))) {
      return -1;
    }
    return hours + minutes + seconds;
  };

  VASTParser.parseNodeText = function(node) {
    return node && (node.textContent || node.text);
  };

  return VASTParser;

})();

module.exports = VASTParser;

},{"./ad.coffee":2,"./companionad.coffee":4,"./creative.coffee":5,"./mediafile.coffee":7,"./response.coffee":9,"./urlhandler.coffee":11,"./util.coffee":14}],9:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTResponse;

VASTResponse = (function() {
  function VASTResponse() {
    this.ads = [];
    this.errorURLTemplates = [];
  }

  return VASTResponse;

})();

module.exports = VASTResponse;

},{}],10:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var EventEmitter, VASTClient, VASTCreativeLinear, VASTTracker, VASTUtil,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

VASTClient = _dereq_('./client.coffee');

VASTUtil = _dereq_('./util.coffee');

VASTCreativeLinear = _dereq_('./creative.coffee').VASTCreativeLinear;

EventEmitter = _dereq_('events').EventEmitter;

VASTTracker = (function(_super) {
  __extends(VASTTracker, _super);

  function VASTTracker(ad, creative) {
    var eventName, events, _ref;
    this.ad = ad;
    this.creative = creative;
    this.muted = false;
    this.impressed = false;
    this.skipable = false;
    this.skipDelayDefault = -1;
    this.trackingEvents = {};
    this.emitAlwaysEvents = ['creativeView', 'start', 'firstQuartile', 'midpoint', 'thirdQuartile', 'complete', 'resume', 'pause', 'rewind', 'skip', 'closeLinear', 'close'];
    _ref = creative.trackingEvents;
    for (eventName in _ref) {
      events = _ref[eventName];
      this.trackingEvents[eventName] = events.slice(0);
    }
    if (creative instanceof VASTCreativeLinear) {
      this.setDuration(creative.duration);
      this.skipDelay = creative.skipDelay;
      this.linear = true;
      this.clickThroughURLTemplate = creative.videoClickThroughURLTemplate;
      this.clickTrackingURLTemplates = creative.videoClickTrackingURLTemplates;
    } else {
      this.skipDelay = -1;
      this.linear = false;
    }
    this.on('start', function() {
      VASTClient.lastSuccessfullAd = +new Date();
    });
  }

  VASTTracker.prototype.setDuration = function(duration) {
    this.assetDuration = duration;
    return this.quartiles = {
      'firstQuartile': Math.round(25 * this.assetDuration) / 100,
      'midpoint': Math.round(50 * this.assetDuration) / 100,
      'thirdQuartile': Math.round(75 * this.assetDuration) / 100
    };
  };

  VASTTracker.prototype.setProgress = function(progress) {
    var eventName, events, percent, quartile, skipDelay, time, _i, _len, _ref;
    skipDelay = this.skipDelay === null ? this.skipDelayDefault : this.skipDelay;
    if (skipDelay !== -1 && !this.skipable) {
      if (skipDelay > progress) {
        this.emit('skip-countdown', skipDelay - progress);
      } else {
        this.skipable = true;
        this.emit('skip-countdown', 0);
      }
    }
    if (this.linear && this.assetDuration > 0) {
      events = [];
      if (progress > 0) {
        events.push("start");
        percent = Math.round(progress / this.assetDuration * 100);
        events.push("progress-" + percent + "%");
        _ref = this.quartiles;
        for (quartile in _ref) {
          time = _ref[quartile];
          if ((time <= progress && progress <= (time + 1))) {
            events.push(quartile);
          }
        }
      }
      for (_i = 0, _len = events.length; _i < _len; _i++) {
        eventName = events[_i];
        this.track(eventName, true);
      }
      if (progress < this.progress) {
        this.track("rewind");
      }
    }
    return this.progress = progress;
  };

  VASTTracker.prototype.setMuted = function(muted) {
    if (this.muted !== muted) {
      this.track(muted ? "muted" : "unmuted");
    }
    return this.muted = muted;
  };

  VASTTracker.prototype.setPaused = function(paused) {
    if (this.paused !== paused) {
      this.track(paused ? "pause" : "resume");
    }
    return this.paused = paused;
  };

  VASTTracker.prototype.setFullscreen = function(fullscreen) {
    if (this.fullscreen !== fullscreen) {
      this.track(fullscreen ? "fullscreen" : "exitFullscreen");
    }
    return this.fullscreen = fullscreen;
  };

  VASTTracker.prototype.setSkipDelay = function(duration) {
    if (typeof duration === 'number') {
      return this.skipDelay = duration;
    }
  };

  VASTTracker.prototype.load = function() {
    if (!this.impressed) {
      this.impressed = true;
      this.trackURLs(this.ad.impressionURLTemplates);
      return this.track("creativeView");
    }
  };

  VASTTracker.prototype.errorWithCode = function(errorCode) {
    return this.trackURLs(this.ad.errorURLTemplates, {
      ERRORCODE: errorCode
    });
  };

  VASTTracker.prototype.complete = function() {
    return this.track("complete");
  };

  VASTTracker.prototype.stop = function() {
    return this.track(this.linear ? "closeLinear" : "close");
  };

  VASTTracker.prototype.skip = function() {
    this.track("skip");
    return this.trackingEvents = [];
  };

  VASTTracker.prototype.click = function() {
    var clickThroughURL, variables, _ref;
    if ((_ref = this.clickTrackingURLTemplates) != null ? _ref.length : void 0) {
      this.trackURLs(this.clickTrackingURLTemplates);
    }
    if (this.clickThroughURLTemplate != null) {
      if (this.linear) {
        variables = {
          CONTENTPLAYHEAD: this.progressFormated()
        };
      }
      clickThroughURL = VASTUtil.resolveURLTemplates([this.clickThroughURLTemplate], variables)[0];
      return this.emit("clickthrough", clickThroughURL);
    }
  };

  VASTTracker.prototype.track = function(eventName, once) {
    var idx, trackingURLTemplates;
    if (once == null) {
      once = false;
    }
    if (eventName === 'closeLinear' && ((this.trackingEvents[eventName] == null) && (this.trackingEvents['close'] != null))) {
      eventName = 'close';
    }
    trackingURLTemplates = this.trackingEvents[eventName];
    idx = this.emitAlwaysEvents.indexOf(eventName);
    if (trackingURLTemplates != null) {
      this.emit(eventName, '');
      this.trackURLs(trackingURLTemplates);
    } else if (idx !== -1) {
      this.emit(eventName, '');
    }
    if (once === true) {
      delete this.trackingEvents[eventName];
      if (idx > -1) {
        this.emitAlwaysEvents.splice(idx, 1);
      }
    }
  };

  VASTTracker.prototype.trackURLs = function(URLTemplates, variables) {
    if (variables == null) {
      variables = {};
    }
    if (this.linear) {
      variables["CONTENTPLAYHEAD"] = this.progressFormated();
    }
    return VASTUtil.track(URLTemplates, variables);
  };

  VASTTracker.prototype.progressFormated = function() {
    var h, m, ms, s, seconds;
    seconds = parseInt(this.progress);
    h = seconds / (60 * 60);
    if (h.length < 2) {
      h = "0" + h;
    }
    m = seconds / 60 % 60;
    if (m.length < 2) {
      m = "0" + m;
    }
    s = seconds % 60;
    if (s.length < 2) {
      s = "0" + m;
    }
    ms = parseInt((this.progress - seconds) * 100);
    return "" + h + ":" + m + ":" + s + "." + ms;
  };

  return VASTTracker;

})(EventEmitter);

module.exports = VASTTracker;

},{"./client.coffee":3,"./creative.coffee":5,"./util.coffee":14,"events":1}],11:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var URLHandler, flash, xhr;

xhr = _dereq_('./urlhandlers/xmlhttprequest.coffee');

flash = _dereq_('./urlhandlers/flash.coffee');

URLHandler = (function() {
  function URLHandler() {}

  URLHandler.get = function(url, cb) {
    if (typeof window === "undefined" || window === null) {
      return _dereq_('./urlhandlers/' + 'node.coffee').get(url, cb);
    } else if (xhr.supported()) {
      return xhr.get(url, cb);
    } else if (flash.supported()) {
      return flash.get(url, cb);
    } else {
      return cb();
    }
  };

  return URLHandler;

})();

module.exports = URLHandler;

},{"./urlhandlers/flash.coffee":12,"./urlhandlers/xmlhttprequest.coffee":13}],12:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var FlashURLHandler;

FlashURLHandler = (function() {
  function FlashURLHandler() {}

  FlashURLHandler.xdr = function() {
    var xdr;
    if (window.XDomainRequest) {
      xdr = new XDomainRequest();
    }
    return xdr;
  };

  FlashURLHandler.supported = function() {
    return !!this.xdr();
  };

  FlashURLHandler.get = function(url, cb) {
    var xdr, xmlDocument;
    if (xmlDocument = typeof window.ActiveXObject === "function" ? new window.ActiveXObject("Microsoft.XMLDOM") : void 0) {
      xmlDocument.async = false;
    } else {
      return cb();
    }
    xdr = this.xdr();
    xdr.open('GET', url);
    xdr.send();
    return xdr.onload = function() {
      xmlDocument.loadXML(xdr.responseText);
      return cb(null, xmlDocument);
    };
  };

  return FlashURLHandler;

})();

module.exports = FlashURLHandler;

},{}],13:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var XHRURLHandler;

XHRURLHandler = (function() {
  function XHRURLHandler() {}

  XHRURLHandler.xhr = function() {
    var xhr;
    xhr = new window.XMLHttpRequest();
    if ('withCredentials' in xhr) {
      return xhr;
    }
  };

  XHRURLHandler.supported = function() {
    return !!this.xhr();
  };

  XHRURLHandler.get = function(url, cb) {
    var xhr;
    xhr = this.xhr();
    xhr.open('GET', url);
    xhr.send();
    return xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        return cb(null, xhr.responseXML);
      }
    };
  };

  return XHRURLHandler;

})();

module.exports = XHRURLHandler;

},{}],14:[function(_dereq_,module,exports){
// Generated by CoffeeScript 1.7.1
var VASTUtil;

VASTUtil = (function() {
  function VASTUtil() {}

  VASTUtil.track = function(URLTemplates, variables) {
    var URL, URLs, i, _i, _len, _results;
    URLs = this.resolveURLTemplates(URLTemplates, variables);
    _results = [];
    for (_i = 0, _len = URLs.length; _i < _len; _i++) {
      URL = URLs[_i];
      if (typeof window !== "undefined" && window !== null) {
        i = new Image();
        _results.push(i.src = URL);
      } else {

      }
    }
    return _results;
  };

  VASTUtil.resolveURLTemplates = function(URLTemplates, variables) {
    var URLTemplate, URLs, key, macro1, macro2, resolveURL, value, _i, _len;
    URLs = [];
    if (variables == null) {
      variables = {};
    }
    if (!("CACHEBUSTING" in variables)) {
      variables["CACHEBUSTING"] = Math.round(Math.random() * 1.0e+10);
    }
    variables["random"] = variables["CACHEBUSTING"];
    for (_i = 0, _len = URLTemplates.length; _i < _len; _i++) {
      URLTemplate = URLTemplates[_i];
      resolveURL = URLTemplate;
      if (!resolveURL) {
        continue;
      }
      for (key in variables) {
        value = variables[key];
        macro1 = "[" + key + "]";
        macro2 = "%%" + key + "%%";
        resolveURL = resolveURL.replace(macro1, value);
        resolveURL = resolveURL.replace(macro2, value);
      }
      URLs.push(resolveURL);
    }
    return URLs;
  };

  VASTUtil.storage = (function() {
    var data, isDisabled, storage, storageError;
    try {
      storage = typeof window !== "undefined" && window !== null ? window.localStorage || window.sessionStorage : null;
    } catch (_error) {
      storageError = _error;
      storage = null;
    }
    isDisabled = function(store) {
      var e, testValue;
      try {
        testValue = '__VASTUtil__';
        store.setItem(testValue, testValue);
        if (store.getItem(testValue) !== testValue) {
          return true;
        }
      } catch (_error) {
        e = _error;
        return true;
      }
      return false;
    };
    if ((storage == null) || isDisabled(storage)) {
      data = {};
      storage = {
        length: 0,
        getItem: function(key) {
          return data[key];
        },
        setItem: function(key, value) {
          data[key] = value;
          this.length = Object.keys(data).length;
        },
        removeItem: function(key) {
          delete data[key];
          this.length = Object.keys(data).length;
        },
        clear: function() {
          data = {};
          this.length = 0;
        }
      };
    }
    return storage;
  })();

  return VASTUtil;

})();

module.exports = VASTUtil;

},{}]},{},[6])
(6)
});
/**
 * Basic Ad support plugin for video.js.
 *
 * Common code to support ad integrations.
 */
(function(window, document, vjs, undefined) {
"use strict";

var

  /**
   * Copies properties from one or more objects onto an original.
   */
  extend = function(obj /*, arg1, arg2, ... */) {
    var arg, i, k;
    for (i=1; i<arguments.length; i++) {
      arg = arguments[i];
      for (k in arg) {
        if (arg.hasOwnProperty(k)) {
          obj[k] = arg[k];
        }
      }
    }
    return obj;
  },

  /**
   * Add a handler for multiple listeners to an object that supports addEventListener() or on().
   *
   * @param {object} obj The object to which the handler will be assigned.
   * @param {mixed} events A string, array of strings, or hash of string/callback pairs.
   * @param {function} callback Invoked when specified events occur, if events param is not a hash.
   *
   * @return {object} obj The object passed in.
   */
  on = function(obj, events, handler) {

    var

      type = Object.prototype.toString.call(events),

      register = function(obj, event, handler) {
        if (obj.addEventListener) {
          obj.addEventListener(event, handler);
        } else if (obj.on) {
          obj.on(event, handler);
        } else if (obj.attachEvent) {
          obj.attachEvent('on' + event, handler);
        } else {
          throw new Error('object has no mechanism for adding event listeners');
        }
      },

      i,
      ii;

    switch (type) {
      case '[object String]':
        register(obj, events, handler);
        break;
      case '[object Array]':
        for (i = 0, ii = events.length; i<ii; i++) {
          register(obj, events[i], handler);
        }
        break;
      case '[object Object]':
        for (i in events) {
          if (events.hasOwnProperty(i)) {
            register(obj, i, events[i]);
          }
        }
        break;
      default:
        throw new Error('Unrecognized events parameter type: ' + type);
    }

    return obj;

  },

  /**
   * Runs the callback at the next available opportunity.
   * @see https://developer.mozilla.org/en-US/docs/Web/API/window.setImmediate
   */
  setImmediate = function(callback) {
    return (
      window.setImmediate ||
      window.requestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.setTimeout
    )(callback, 0);
  },

  /**
   * Clears a callback previously registered with `setImmediate`.
   * @param {id} id The identifier of the callback to abort
   */
  clearImmediate = function(id) {
    return (window.clearImmediate ||
            window.cancelAnimationFrame ||
            window.webkitCancelAnimationFrame ||
            window.mozCancelAnimationFrame ||
            window.clearTimeout)(id);
  },

  /**
   * If ads are not playing, pauses the player at the next available
   * opportunity. Has no effect if ads have started. This function is necessary
   * because pausing a video element while processing a `play` event on iOS can
   * cause the video element to continuously toggle between playing and paused
   * states.
   *
   * @param {object} player The video player
   */
  cancelContentPlay = function(player) {
    if (player.ads.cancelPlayTimeout) {
      // another cancellation is already in flight, so do nothing
      return;
    }

    player.ads.cancelPlayTimeout = setImmediate(function() {

      // deregister the cancel timeout so subsequent cancels are scheduled
      player.ads.cancelPlayTimeout = null;

      if (!player.paused()) {
        player.pause();
      }
    });
  },

  /**
   * Returns an object that captures the portions of player state relevant to
   * video playback. The result of this function can be passed to
   * restorePlayerSnapshot with a player to return the player to the state it
   * was in when this function was invoked.
   * @param {object} player The videojs player object
   */
  getPlayerSnapshot = function(player) {
    var
      tech = player.el().querySelector('.vjs-tech'),
      snapshot = {
        src: player.currentSrc(),
        currentTime: player.currentTime(),
        type: player.currentType()
      };

    if (tech) {
      snapshot.nativePoster = tech.poster;
    }

    return snapshot;
  },

  removeClass = function(element, className) {
    var
      classes = element.className.split(/\s+/),
      i = classes.length,
      newClasses = [];
    while (i--) {
      if (classes[i] !== className) {
        newClasses.push(classes[i]);
      }
    }
    element.className = newClasses.join(' ');
  },

  /**
   * Attempts to modify the specified player so that its state is equivalent to
   * the state of the snapshot.
   * @param {object} snapshot - the player state to apply
   */
  restorePlayerSnapshot = function(player, snapshot) {
    var
      // the playback tech
      tech = player.el().querySelector('.vjs-tech'),

      // the number of remaining attempts to restore the snapshot
      attempts = 20,

      // finish restoring the playback state
      resume = function() {
        player.currentTime(snapshot.currentTime);
        //If this wasn't a postroll resume
        if (!player.ended()) {
          player.play();
        }
      },

      // determine if the video element has loaded enough of the snapshot source
      // to be ready to apply the rest of the state
      tryToResume = function() {
        if (tech.seekable === undefined) {
          // if the tech doesn't expose the seekable time ranges, try to
          // resume playback immediately
          resume();
          return;
        }
        if (tech.seekable.length > 0) {
          // if some period of the video is seekable, resume playback
          resume();
          return;
        }

        // delay a bit and then check again unless we're out of attempts
        if (attempts--) {
          setTimeout(tryToResume, 50);
        }
      },

      // whether the video element has been modified since the
      // snapshot was taken
      srcChanged;

    if (snapshot.nativePoster) {
      tech.poster = snapshot.nativePoster;
    }

    // Determine whether the player needs to be restored to its state
    // before ad playback began. With a custom ad display or burned-in
    // ads, the content player state hasn't been modified and so no
    // restoration is required

    if (player.src()) {
      // the player was in src attribute mode before the ad and the
      // src attribute has not been modified, no restoration is required
      // to resume playback
      srcChanged = player.src() !== snapshot.src;
    } else {
      // the player was configured through source element children
      // and the currentSrc hasn't changed, no restoration is required
      // to resume playback
      srcChanged = player.currentSrc() !== snapshot.src;
    }

    if (srcChanged) {
      // if the src changed for ad playback, reset it
      player.src({ src: snapshot.src, type: snapshot.type });
      // safari requires a call to `load` to pick up a changed source
      player.load();
      // and then resume from the snapshots time once the original src has loaded
      player.one('loadedmetadata', tryToResume);
    } else if (!player.ended()) {
      // the src didn't change and this wasn't a postroll
      // just resume playback at the current time.
      player.play();
    }
  },

  /**
   * Remove the poster attribute from the video element tech, if present. When
   * reusing a video element for multiple videos, the poster image will briefly
   * reappear while the new source loads. Removing the attribute ahead of time
   * prevents the poster from showing up between videos.
   * @param {object} player The videojs player object
   */
  removeNativePoster = function(player) {
    var tech = player.el().querySelector('.vjs-tech');
    if (tech) {
      tech.removeAttribute('poster');
    }
  },

  // ---------------------------------------------------------------------------
  // Ad Framework
  // ---------------------------------------------------------------------------

  // default framework settings
  defaults = {
    // maximum amount of time in ms to wait to receive `adsready` from the ad
    // implementation after play has been requested. Ad implementations are
    // expected to load any dynamic libraries and make any requests to determine
    // ad policies for a video during this time.
    timeout: 5000,

    // maximum amount of time in ms to wait for the ad implementation to start
    // linear ad mode after `readyforpreroll` has fired. This is in addition to
    // the standard timeout.
    prerollTimeout: 100,

    // when truthy, instructs the plugin to output additional information about
    // plugin state to the video.js log. On most devices, the video.js log is
    // the same as the developer console.
    debug: false
  },

  adFramework = function(options) {
    var
      player = this,

      // merge options and defaults
      settings = extend({}, defaults, options || {}),

      fsmHandler;

    // replace the ad initializer with the ad namespace
    player.ads = {
      state: 'content-set',

      startLinearAdMode: function() {
        player.trigger('adstart');
      },

      endLinearAdMode: function() {
        player.trigger('adend');
      }
    };

    fsmHandler = function(event) {

      // Ad Playback State Machine
      var
        fsm = {
          'content-set': {
            events: {
              'adsready': function() {
                this.state = 'ads-ready';
              },
              'play': function() {
                this.state = 'ads-ready?';
                cancelContentPlay(player);

                // remove the poster so it doesn't flash between videos
                removeNativePoster(player);
              }
            }
          },
          'ads-ready': {
            events: {
              'play': function() {
                this.state = 'preroll?';
                cancelContentPlay(player);
              }
            }
          },
          'preroll?': {
            enter: function() {
              // change class to show that we're waiting on ads
              player.el().className += ' vjs-ad-loading';

              // schedule an adtimeout event to fire if we waited too long
              player.ads.timeout = window.setTimeout(function() {
                player.trigger('adtimeout');
              }, settings.prerollTimeout);

              // signal to ad plugin that it's their opportunity to play a preroll
              player.trigger('readyforpreroll');

            },
            leave: function() {
              window.clearTimeout(player.ads.timeout);

              clearImmediate(player.ads.cancelPlayTimeout);
              player.ads.cancelPlayTimeout = null;

              removeClass(player.el(), 'vjs-ad-loading');
            },
            events: {
              'play': function() {
                cancelContentPlay(player);
              },
              'adstart': function() {
                this.state = 'ad-playback';
                player.el().className += ' vjs-ad-playing';
              },
              'adtimeout': function() {
                this.state = 'content-playback';
                player.play();
              }
            }
          },
          'ads-ready?': {
            enter: function() {
              player.el().className += ' vjs-ad-loading';
              player.ads.timeout = window.setTimeout(function() {
                player.trigger('adtimeout');
              }, settings.timeout);
            },
            leave: function() {
              window.clearTimeout(player.ads.timeout);
              removeClass(player.el(), 'vjs-ad-loading');
            },
            events: {
              'play': function() {
                cancelContentPlay(player);
              },
              'adsready': function() {
                this.state = 'preroll?';
              },
              'adtimeout': function() {
                this.state = 'ad-timeout-playback';
              }
            }
          },
          'ad-timeout-playback': {
            events: {
              'adsready': function() {
                if (player.paused()) {
                  this.state = 'ads-ready';
                } else {
                  this.state = 'preroll?';
                }
              },
              'contentupdate': function() {
                if (player.paused()) {
                  this.state = 'content-set';
                } else {
                  this.state = 'ads-ready?';
                }
              }
            }
          },
          'ad-playback': {
            enter: function() {
              // capture current player state snapshot (playing, currentTime, src)
              this.snapshot = getPlayerSnapshot(player);

              // remove the poster so it doesn't flash between videos
              removeNativePoster(player);
            },
            leave: function() {
              removeClass(player.el(), 'vjs-ad-playing');
              restorePlayerSnapshot(player, this.snapshot);
            },
            events: {
              'adend': function() {
                this.state = 'content-playback';
              }
            }
          },
          'content-playback': {
            events: {
              'adstart': function() {
                this.state = 'ad-playback';
                player.el().className += ' vjs-ad-playing';

                // remove the poster so it doesn't flash between videos
                removeNativePoster(player);
              },
              'contentupdate': function() {
                if (player.paused()) {
                  this.state = 'content-set';
                } else {
                  this.state = 'ads-ready?';
                }
              }
            }
          }
        };

      (function(state) {

        var noop = function() {};

        // process the current event with a noop default handler
        (fsm[state].events[event.type] || noop).apply(player.ads);

        // execute leave/enter callbacks if present
        if (state !== player.ads.state) {
          (fsm[state].leave || noop).apply(player.ads);
          (fsm[player.ads.state].enter || noop).apply(player.ads);

          if (settings.debug) {
            videojs.log('ads', state + ' -> ' + player.ads.state);
          }
        }

      })(player.ads.state);

    };

    // register for the events we're interested in
    on(player, vjs.Html5.Events.concat([
      // events emitted by ad plugin
      'adtimeout',
      'contentupdate',
      // events emitted by third party ad implementors
      'adsready',
      'adstart',  // startLinearAdMode()
      'adend'     // endLinearAdMode()
    ]), fsmHandler);
    
    // keep track of the current content source
    // if you want to change the src of the video without triggering
    // the ad workflow to restart, you can update this variable before
    // modifying the player's source
    player.ads.contentSrc = player.currentSrc();
    
    // implement 'contentupdate' event.
    (function(){
      var
        // check if a new src has been set, if so, trigger contentupdate
        checkSrc = function() {
          var src;
          if (player.ads.state !== 'ad-playback') {
            src = player.currentSrc();
            if (src !== player.ads.contentSrc) {
              player.trigger({
                type: 'contentupdate',
                oldValue: player.ads.contentSrc,
                newValue: src
              });
              player.ads.contentSrc = src;
            }
          }
        };
      // loadstart reliably indicates a new src has been set
      player.on('loadstart', checkSrc);
      // check immediately in case we missed the loadstart
      setImmediate(checkSrc);
    })();

    // kick off the fsm
    if (!player.paused()) {
      // simulate a play event if we're autoplaying
      fsmHandler({type:'play'});
    }

  };

  // register the ad plugin framework
  vjs.plugin('ads', adFramework);

})(window, document, videojs);
<VAST version="2.0">
<Ad id="preroll-1">
<InLine>
<AdSystem>2.0</AdSystem>
<AdTitle>5773100</AdTitle>
<Creatives>
<Creative>
<Linear>
<Duration>00:00:01</Duration>
<MediaFiles>
<MediaFile height="270" width="370" type="application/x-shockwave-flash">
<![CDATA[
http://static.scanscout.com/ads/vpaidad3.swf?adData=http%3A//app.scanscout.com/ssframework/adStreamJSController.xml%3Fa%3Dgetadscheduleforcontent%26PI%3D567%26scheduleVersion%3Dnull%26HI%3D567|preroll|7496075541100999745%26AI%3D0
]]>
</MediaFile>
</MediaFiles>
</Linear>
</Creative>
<Creative>
<CompanionAds>
<Companion height="250" width="300" id="573242">
<HTMLResource>
<![CDATA[
<A onClick="var i= new Image(1,1); i.src='http://app.scanscout.com/ssframework/log/log.png?a=logitemaction&RI=573242&CbC=1&CbF=true&EC=0&RC=0&SmC=2&CbM=1.0E-5&VI=44cfc3b2382300cb751ba129fe51f46a&admode=preroll&PRI=7496075541100999745&RprC=5&ADsn=20&VcaI=192,197&RrC=1&VgI=44cfc3b2382300cb751ba129fe51f46a&AVI=142&Ust=ma&Uctry=us&CI=1247549&AC=4&PI=567&Udma=506&ADI=5773100&VclF=true';" HREF="http://vaseline.com" target="_blank"> <IMG SRC="http://media.scanscout.com/ads/vaseline300x250Companion.jpg" BORDER=0 WIDTH=300 HEIGHT=250 ALT="Click Here"> </A> <img src="http://app.scanscout.com/ssframework/log/log.png?a=logitemaction&RI=573242&CbC=1&CbF=true&EC=1&RC=0&SmC=2&CbM=1.0E-5&VI=44cfc3b2382300cb751ba129fe51f46a&admode=preroll&PRI=7496075541100999745&RprC=5&ADsn=20&VcaI=192,197&RrC=1&VgI=44cfc3b2382300cb751ba129fe51f46a&AVI=142&Ust=ma&Uctry=us&CI=1247549&AC=4&PI=567&Udma=506&ADI=5773100&VclF=true" height="1" width="1">
]]>
</HTMLResource>
</Companion>
</CompanionAds>
</Creative>
</Creatives>
</InLine>
</Ad>
</VAST>
<?xml version="1.0" encoding="UTF-8"?>
<VAST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="vast_2.0.1-creativeView.xsd"
 version="2.0">

  <Ad id="overlay-1">
    <InLine>
      <AdSystem>2.0</AdSystem>
      <AdTitle>VPAID Example</AdTitle>
      <!--  <Impression><![CDATA[http://impression_url_goes_here]]</Impression> -->
      <Creatives>
        <Creative>
          <NonLinearAds>
            <NonLinear apiFramework="VPAID" id="overlay-1"  width="480" height="200" >
              <StaticResource creativeType="application/x-shockwave-flash">
              <![CDATA[http://admin.brightcove.com/vpaid/Example.swf]]></StaticResource>
            </NonLinear>
          </NonLinearAds>
        </Creative>
      </Creatives>
    </InLine>
  </Ad>
</VAST>