UNPKG

flowplayer-vast

Version:
1,480 lines (1,299 loc) 61.9 kB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,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. var objectCreate = Object.create || objectCreatePolyfill var objectKeys = Object.keys || objectKeysPolyfill var bind = Function.prototype.bind || functionBindPolyfill function EventEmitter() { if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) { this._events = objectCreate(null); this._eventsCount = 0; } 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. var defaultMaxListeners = 10; var hasDefineProperty; try { var o = {}; if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 }); hasDefineProperty = o.x === 0; } catch (err) { hasDefineProperty = false } if (hasDefineProperty) { Object.defineProperty(EventEmitter, 'defaultMaxListeners', { enumerable: true, get: function() { return defaultMaxListeners; }, set: function(arg) { // check whether the input is a positive number (whose value is zero or // greater and not a NaN). if (typeof arg !== 'number' || arg < 0 || arg !== arg) throw new TypeError('"defaultMaxListeners" must be a positive number'); defaultMaxListeners = arg; } }); } else { EventEmitter.defaultMaxListeners = defaultMaxListeners; } // 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 setMaxListeners(n) { if (typeof n !== 'number' || n < 0 || isNaN(n)) throw new TypeError('"n" argument must be a positive number'); this._maxListeners = n; return this; }; function $getMaxListeners(that) { if (that._maxListeners === undefined) return EventEmitter.defaultMaxListeners; return that._maxListeners; } EventEmitter.prototype.getMaxListeners = function getMaxListeners() { return $getMaxListeners(this); }; // These standalone emit* functions are used to optimize calling of event // handlers for fast cases because emit() itself often has a variable number of // arguments and can be deoptimized because of that. These functions always have // the same number of arguments and thus do not get deoptimized, so the code // inside them can execute faster. function emitNone(handler, isFn, self) { if (isFn) handler.call(self); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self); } } function emitOne(handler, isFn, self, arg1) { if (isFn) handler.call(self, arg1); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1); } } function emitTwo(handler, isFn, self, arg1, arg2) { if (isFn) handler.call(self, arg1, arg2); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1, arg2); } } function emitThree(handler, isFn, self, arg1, arg2, arg3) { if (isFn) handler.call(self, arg1, arg2, arg3); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1, arg2, arg3); } } function emitMany(handler, isFn, self, args) { if (isFn) handler.apply(self, args); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].apply(self, args); } } EventEmitter.prototype.emit = function emit(type) { var er, handler, len, args, i, events; var doError = (type === 'error'); events = this._events; if (events) doError = (doError && events.error == null); else if (!doError) return false; // If there is no 'error' event listener then throw. if (doError) { if (arguments.length > 1) er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Unhandled "error" event. (' + er + ')'); err.context = er; throw err; } return false; } handler = events[type]; if (!handler) return false; var isFn = typeof handler === 'function'; len = arguments.length; switch (len) { // fast cases case 1: emitNone(handler, isFn, this); break; case 2: emitOne(handler, isFn, this, arguments[1]); break; case 3: emitTwo(handler, isFn, this, arguments[1], arguments[2]); break; case 4: emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); break; // slower default: args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; emitMany(handler, isFn, this, args); } return true; }; function _addListener(target, type, listener, prepend) { var m; var events; var existing; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = target._events; if (!events) { events = target._events = objectCreate(null); target._eventsCount = 0; } else { // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (events.newListener) { target.emit('newListener', type, listener.listener ? listener.listener : listener); // Re-assign `events` because a newListener handler could have caused the // this._events to be assigned to a new object events = target._events; } existing = events[type]; } if (!existing) { // Optimize the case of one listener. Don't need the extra array object. existing = events[type] = listener; ++target._eventsCount; } else { if (typeof existing === 'function') { // Adding the second element, need to change to array. existing = events[type] = prepend ? [listener, existing] : [existing, listener]; } else { // If we've already got an array, just append. if (prepend) { existing.unshift(listener); } else { existing.push(listener); } } // Check for listener leak if (!existing.warned) { m = $getMaxListeners(target); if (m && m > 0 && existing.length > m) { existing.warned = true; var w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' "' + String(type) + '" listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit.'); w.name = 'MaxListenersExceededWarning'; w.emitter = target; w.type = type; w.count = existing.length; if (typeof console === 'object' && console.warn) { console.warn('%s: %s', w.name, w.message); } } } } return target; } EventEmitter.prototype.addListener = function addListener(type, listener) { return _addListener(this, type, listener, false); }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.prependListener = function prependListener(type, listener) { return _addListener(this, type, listener, true); }; function onceWrapper() { if (!this.fired) { this.target.removeListener(this.type, this.wrapFn); this.fired = true; switch (arguments.length) { case 0: return this.listener.call(this.target); case 1: return this.listener.call(this.target, arguments[0]); case 2: return this.listener.call(this.target, arguments[0], arguments[1]); case 3: return this.listener.call(this.target, arguments[0], arguments[1], arguments[2]); default: var args = new Array(arguments.length); for (var i = 0; i < args.length; ++i) args[i] = arguments[i]; this.listener.apply(this.target, args); } } } function _onceWrap(target, type, listener) { var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; var wrapped = bind.call(onceWrapper, state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; } EventEmitter.prototype.once = function once(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); this.on(type, _onceWrap(this, type, listener)); return this; }; EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); this.prependListener(type, _onceWrap(this, type, listener)); return this; }; // Emits a 'removeListener' event if and only if the listener was removed. EventEmitter.prototype.removeListener = function removeListener(type, listener) { var list, events, position, i, originalListener; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = this._events; if (!events) return this; list = events[type]; if (!list) return this; if (list === listener || list.listener === listener) { if (--this._eventsCount === 0) this._events = objectCreate(null); else { delete events[type]; if (events.removeListener) this.emit('removeListener', type, list.listener || listener); } } else if (typeof list !== 'function') { position = -1; for (i = list.length - 1; i >= 0; i--) { if (list[i] === listener || list[i].listener === listener) { originalListener = list[i].listener; position = i; break; } } if (position < 0) return this; if (position === 0) list.shift(); else spliceOne(list, position); if (list.length === 1) events[type] = list[0]; if (events.removeListener) this.emit('removeListener', type, originalListener || listener); } return this; }; EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { var listeners, events, i; events = this._events; if (!events) return this; // not listening for removeListener, no need to emit if (!events.removeListener) { if (arguments.length === 0) { this._events = objectCreate(null); this._eventsCount = 0; } else if (events[type]) { if (--this._eventsCount === 0) this._events = objectCreate(null); else delete events[type]; } return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { var keys = objectKeys(events); var key; for (i = 0; i < keys.length; ++i) { key = keys[i]; if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = objectCreate(null); this._eventsCount = 0; return this; } listeners = events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else if (listeners) { // LIFO order for (i = listeners.length - 1; i >= 0; i--) { this.removeListener(type, listeners[i]); } } return this; }; function _listeners(target, type, unwrap) { var events = target._events; if (!events) return []; var evlistener = events[type]; if (!evlistener) return []; if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener]; return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); } EventEmitter.prototype.listeners = function listeners(type) { return _listeners(this, type, true); }; EventEmitter.prototype.rawListeners = function rawListeners(type) { return _listeners(this, type, false); }; EventEmitter.listenerCount = function(emitter, type) { if (typeof emitter.listenerCount === 'function') { return emitter.listenerCount(type); } else { return listenerCount.call(emitter, type); } }; EventEmitter.prototype.listenerCount = listenerCount; function listenerCount(type) { var events = this._events; if (events) { var evlistener = events[type]; if (typeof evlistener === 'function') { return 1; } else if (evlistener) { return evlistener.length; } } return 0; } EventEmitter.prototype.eventNames = function eventNames() { return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; }; // About 1.5x faster than the two-arg version of Array#splice(). function spliceOne(list, index) { for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) list[i] = list[k]; list.pop(); } function arrayClone(arr, n) { var copy = new Array(n); for (var i = 0; i < n; ++i) copy[i] = arr[i]; return copy; } function unwrapListeners(arr) { var ret = new Array(arr.length); for (var i = 0; i < ret.length; ++i) { ret[i] = arr[i].listener || arr[i]; } return ret; } function objectCreatePolyfill(proto) { var F = function() {}; F.prototype = proto; return new F; } function objectKeysPolyfill(obj) { var keys = []; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } return k; } function functionBindPolyfill(context) { var fn = this; return function () { return fn.apply(context, arguments); }; } },{}],2:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { var VASTAd; VASTAd = (function() { function VASTAd() { this.id = null; this.errorURLTemplates = []; this.impressionURLTemplates = []; this.creatives = []; } return VASTAd; })(); module.exports = VASTAd; }).call(this); },{}],3:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { var VASTClient, VASTParser, VASTUtil; VASTParser = require('./parser'); VASTUtil = require('./util'); VASTClient = (function() { function VASTClient() {} VASTClient.cappingFreeLunch = 0; VASTClient.cappingMinimumTimeInterval = 0; VASTClient.options = { withCredentials: false, timeout: 0 }; VASTClient.get = function(url, opts, cb) { var extend, now, options; now = +new Date(); extend = exports.extend = function(object, properties) { var key, val; for (key in properties) { val = properties[key]; object[key] = val; } return object; }; if (!cb) { if (typeof opts === 'function') { cb = opts; } options = {}; } options = extend(this.options, opts); 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, options, (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; }).call(this); },{"./parser":8,"./util":14}],4:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { var VASTCompanionAd; VASTCompanionAd = (function() { function VASTCompanionAd() { this.id = null; this.width = 0; this.height = 0; this.type = null; this.staticResource = null; this.htmlResource = null; this.iframeResource = null; this.companionClickThroughURLTemplate = null; this.trackingEvents = {}; } return VASTCompanionAd; })(); module.exports = VASTCompanionAd; }).call(this); },{}],5:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { 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 = []; this.videoCustomClickURLTemplates = []; this.adParameters = null; } 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 }; }).call(this); },{}],6:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { module.exports = { client: require('./client'), tracker: require('./tracker'), parser: require('./parser'), util: require('./util') }; }).call(this); },{"./client":3,"./parser":8,"./tracker":10,"./util":14}],7:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { var VASTMediaFile; VASTMediaFile = (function() { function VASTMediaFile() { this.id = null; 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; this.scalable = null; this.maintainAspectRatio = null; } return VASTMediaFile; })(); module.exports = VASTMediaFile; }).call(this); },{}],8:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { 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 = require('./urlhandler'); VASTResponse = require('./response'); VASTAd = require('./ad'); VASTUtil = require('./util'); VASTCreativeLinear = require('./creative').VASTCreativeLinear; VASTCreativeCompanion = require('./creative').VASTCreativeCompanion; VASTMediaFile = require('./mediafile'); VASTCompanionAd = require('./companionad'); EventEmitter = require('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, options, cb) { if (!cb) { if (typeof options === 'function') { cb = options; } options = {}; } return this._parse(url, null, options, 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, options, cb) { var filter, _i, _len; if (!cb) { if (typeof options === 'function') { cb = options; } options = {}; } 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, options, (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, protocol, _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('//') === 0) { protocol = location.protocol; ad.nextWrapperURL = "" + protocol + ad.nextWrapperURL; } else if (ad.nextWrapperURL.indexOf('://') === -1) { baseURL = url.slice(0, url.lastIndexOf('/')); ad.nextWrapperURL = "" + baseURL + "/" + ad.nextWrapperURL; } return _this._parse(ad.nextWrapperURL, parentURLs, options, 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]; adTypeElement.id = adElement.getAttribute("id"); 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); } else { wrapperURLElement = this.childByName(wrapperElement, "VASTAdTagURL"); if (wrapperURLElement != null) { ad.nextWrapperURL = this.parseNodeText(this.childByName(wrapperURLElement, "URL")); } } 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(); ad.id = inLineElement.id; _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 adParamsElement, clickTrackingElement, creative, customClickElement, eventName, maintainAspectRatio, mediaFile, mediaFileElement, mediaFilesElement, offset, percent, scalable, skipOffset, trackingElement, trackingEventsElement, trackingURLTemplate, videoClicksElement, _base, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; 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(videoClicksElement, "CustomClick"); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { customClickElement = _ref1[_j]; creative.videoCustomClickURLTemplates.push(this.parseNodeText(customClickElement)); } } adParamsElement = this.childByName(creativeElement, "AdParameters"); if (adParamsElement != null) { creative.adParameters = this.parseNodeText(adParamsElement); } _ref2 = this.childsByName(creativeElement, "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 (eventName === "progress") { offset = trackingElement.getAttribute("offset"); if (!offset) { continue; } if (offset.charAt(offset.length - 1) === '%') { eventName = "progress-" + offset; } else { eventName = "progress-" + (Math.round(this.parseDuration(offset))); } } if ((_base = creative.trackingEvents)[eventName] == null) { _base[eventName] = []; } creative.trackingEvents[eventName].push(trackingURLTemplate); } } } _ref4 = this.childsByName(creativeElement, "MediaFiles"); for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) { mediaFilesElement = _ref4[_m]; _ref5 = this.childsByName(mediaFilesElement, "MediaFile"); for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) { mediaFileElement = _ref5[_n]; mediaFile = new VASTMediaFile(); mediaFile.id = mediaFileElement.getAttribute("id"); 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); scalable = mediaFileElement.getAttribute("scalable"); if (scalable && typeof scalable === "string") { scalable = scalable.toLowerCase(); if (scalable === "true") { mediaFile.scalable = true; } else if (scalable === "false") { mediaFile.scalable = false; } } maintainAspectRatio = mediaFileElement.getAttribute("maintainAspectRatio"); if (maintainAspectRatio && typeof maintainAspectRatio === "string") { maintainAspectRatio = maintainAspectRatio.toLowerCase(); if (maintainAspectRatio === "true") { mediaFile.maintainAspectRatio = true; } else if (maintainAspectRatio === "false") { mediaFile.maintainAspectRatio = false; } } creative.mediaFiles.push(mediaFile); } } return creative; }; VASTParser.parseCompanionAd = function(creativeElement) { var companionAd, companionResource, creative, eventName, htmlElement, iframeElement, staticElement, trackingElement, trackingEventsElement, trackingURLTemplate, _base, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; 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, "HTMLResource"); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { htmlElement = _ref1[_j]; companionAd.type = htmlElement.getAttribute("creativeType") || 'text/html'; companionAd.htmlResource = this.parseNodeText(htmlElement); } _ref2 = this.childsByName(companionResource, "IFrameResource"); for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { iframeElement = _ref2[_k]; companionAd.type = iframeElement.getAttribute("creativeType") || 0; companionAd.iframeResource = this.parseNodeText(iframeElement); } _ref3 = this.childsByName(companionResource, "StaticResource"); for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { staticElement = _ref3[_l]; companionAd.type = staticElement.getAttribute("creativeType") || 0; companionAd.staticResource = this.parseNodeText(staticElement); } _ref4 = this.childsByName(companionResource, "TrackingEvents"); for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) { trackingEventsElement = _ref4[_m]; _ref5 = this.childsByName(trackingEventsElement, "Tracking"); for (_n = 0, _len5 = _ref5.length; _n < _len5; _n++) { trackingElement = _ref5[_n]; 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 || '').trim(); }; return VASTParser; })(); module.exports = VASTParser; }).call(this); },{"./ad":2,"./companionad":4,"./creative":5,"./mediafile":7,"./response":9,"./urlhandler":11,"./util":14,"events":1}],9:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { var VASTResponse; VASTResponse = (function() { function VASTResponse() { this.ads = []; this.errorURLTemplates = []; } return VASTResponse; })(); module.exports = VASTResponse; }).call(this); },{}],10:[function(require,module,exports){ // Generated by CoffeeScript 1.7.1 (function() { 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 = require('./client'); VASTUtil = require('./util'); VASTCreativeLinear = require('./creative').VASTCreativeLinear; EventEmitter = require('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 = this.creative.trackingEvents; for (eventName in _ref) { events = _ref[eventName]; this.trackingEvents[eventName] = events.slice(0); } if (this.creative instanceof VASTCreativeLinear) { this.setDuration(this.creative.duration); this.skipDelay = this.creative.skipDelay; this.linear = true; this.clickThroughURLTemplate = this.creative.videoClickThroughURLTemplate; this.clickTrackingURLTemplates = this.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 + "%"); events.push("progress-" + (Math.round(progress))); _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 ? "mute" : "unmute"); } 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.close = function() { return this.track(this.linear ? "closeLinear" : "close"); }; VASTTracker.prototype.stop = function() {}; 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.l