diff --git a/types/vast-client/index.d.ts b/types/vast-client/index.d.ts new file mode 100644 index 0000000000..8ef25fa00b --- /dev/null +++ b/types/vast-client/index.d.ts @@ -0,0 +1,336 @@ +// Type definitions for vast-client 1.7 +// Project: https://github.com/dailymotion/vast-client-js#readme +// Definitions by: John G. Gainfort, Jr. +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +export as namespace DMVAST; +export = DMVAST; + +declare namespace DMVAST { + const client: VastClient; + const parser: VastParser; + + class tracker { + /** + * The VAST tracker constructor will process the tracking URLs of the selected ad/creative and returns an instance of VASTTracker. + * You can create an instance with new DMVAST.tracker( ad , creative ). + * + * Object ad – Reference to the element of the selected mediaFile + * Object creative – Reference to the element of the selected mediaFile + * Object variationd - An optional reference to the selected / element for non-linear ads + */ + constructor(ad: DMVAST.VastAd, creative: DMVAST.VastCreativeLinear, companion?: DMVAST.VastCreativeCompanion); + /** + * Add a listener function for the specified event. + * + * eventName – Name of the event to attach the listener to. See events below for all details. + * listener – Method to be called when the event is emitted. + */ + on(eventName: string, listener: (data?: any) => void): void; + /** + * Remove a listener function for the specified event. + * + * eventName – Name of the event. + * listener – Method to remove. Will remove all listeners for the given event if no specific callback is passed. + */ + off(eventName: string, listener?: () => void): void; + /** + * Remove all listener functions for the specified event. + * + * eventName – Name of the event. + */ + removeAllListeners(eventName: string): void; + /** + * Update the current time value. This is required for tracking time related events such as start, firstQuartile, midpoint, thirdQuartile or rewind. + * + * progess – Current playback time in seconds. + */ + setProgress(progress: number): void; + /** + * Update the mute state and call the mute/unmute tracking URLs. Emit a mute or unmute event. + * + * muted – Indicate if the video is muted or not. + */ + setMuted(muted: boolean): void; + /** + * Update the pause state and call the resume/pause tracking URLs. Emit a resume or pause event. + * + * paused – Indicate if the video is paused or not. + */ + setPaused(paused: boolean): void; + /** + * Update the fullscreen state and call the fullscreen tracking URLs. Emit a fullscreen or exitFullscreen event. + * + * fullscreen – Indicate the fullscreen mode. + */ + setFullscreen(fullscreen: boolean): void; + /** + * Update the expand state and call the expand/collapse tracking URLs. Emit a expand or collapse event + * + * Boolean expanded – Indicate if the video is expanded or no + */ + setExpand(expanded: boolean): void; + /** + * Must be called if you want to overwrite the Skipoffset value. This will init the skip countdown duration. + * Then, every time you call setProgress(), it will decrease the countdown and emit a skip-countdown event with the remaining time. + * Do not call this method if you want to keep the original Skipoffset value. + * + * duration – The time in seconds until the skip button is displayed. + */ + setSkipDelay(duration: number): void; + /** + * Report the impression URI. Can only be called once. Will report the following URI: + * + * - All URI from the and tracking elements. + * - The creativeView URI from the events + * + * Once done, a creativeView event is emitted. + */ + load(): void; + /** + * Send a request to the URI provided by the VAST element. If an [ERRORCODE] macro is included, it will be substitute with code. + * + * code – Replaces [ERRORCODE] macro. [ERRORCODE] values are liste in the VAST specification. + */ + errorWithCode(code: string): void; + /** + * Must be called when the user watched the linear creative until its end. Call the complete tracking URLs. Emit a complete events when done. + */ + complete(): void; + /** + * Must be called when the player or the window is closed during the ad. Call the closeLinear (in VAST 3.0) and close tracking URLs. Emit a closeLinear or a close event when done. + */ + close(): void; + /** + * Must be called when the skip button is clicked. Call the skip tracking URLs. Emit a skip event when done. + */ + skip(): void; + /** + * Must be called when the user clicks on the creative. Call the tracking URLs. Emit a clickthrough event with the resolved clickThrough URL when done. + */ + click(): void; + } + + interface VastClient { + /** + * Used for ignoring the first n calls. Automatically reset 1 hour after the 1st ignored call. Free Lunch capping is disable if sets to 0. + * Default: 0 + */ + cappingFreeLunch: number; + /** + * Used for ignoring calls that happen n ms after the previous call. Minimum time interval is disabled if sets to 0. + * Default: 0 + */ + cappingMinimumTimeInterval: number; + /** + * Fetch a URL and parse the response into a valid VAST object. + * + * String url – Contains the URL for fetching the VAST XML document. + * Object options – An optional set of key/value to configure the Ajax request: + * String response – A VAST XML document. When response is provided, no Ajax request is made and thus the url parameter is ignored + * Object urlhandler – A URL handler module, used to fetch the VAST document instead of the default ones. + * Boolean withCredentials – A boolean to enable the withCredentials options for the XHR and FLASH URLHandlers. + * Number wrapperLimit – A number of available Wrapper responses that can be received with no InLine response. + * Function done – Method to be called once the VAST document is parsed. The VAST JS object is passed as the 1st parameter. If null, an error is provided as a 2nd parameter. + */ + get(url: string, done: (response: DMVAST.VastResponse, error: Error) => void): void; + get(url: string, options: DMVAST.VastRequestOptions, done: (response: DMVAST.VastResponse, error: Error) => void): void; + } + + interface VastParser { + /** + * Add the replace function at the end of the URLTemplateFilters array. + * All functions in URLTemplateFilters will be called with the VAST URL as parameter before fetching the VAST URL document. + */ + addURLTemplateFilter(cb: (vastUrl: string) => string): void; + /** + * Reset URLTemplateFilters to empty, previous replace function set with addURLTemplateFilter() are no longer called. + */ + clearUrlTemplateFilters(): void; + /** + * Returns how many replace function are set (ie: URLTemplateFilters length) + */ + countURLTemplateFilters(): number; + /** + * Parse an VAST xml, resolve any wrappers and execute callback function done + * + * String XMLDocument – A VAST XML document. + * Object options – An optional set of key/value to configure the Ajax request: + * Object urlhandler – A URL handler module, used to fetch VASTAdTagURI URL. If defined, will be used instead of the default ones. + * Boolean withCredentials – A boolean to enable the withCredentials options for the XHR and FLASH URLHandlers. + * Number wrapperLimit – A number of available Wrapper responses that can be received with no InLine response. + * Function done – Method to be called once the VAST document is parsed. When at least 1 valid has been found, the 1st parameter will be an array of VASTAd instances. + * Hoverwise, in case of no ads, it will be null, and an error as a 2nd parameter is provided. + */ + load(xml: string, done: (response: DMVAST.VastResponse, error: Error) => void): void; + load(xml: string, options: DMVAST.VastRequestOptions, done: (response: DMVAST.VastResponse, error: Error) => void): void; + /** + * Add the listener function for the event named eventName. eventName value can be : + * + * String VAST-error – emitted when the parser encountered a VAST error (ie: no ads, warapper timeout...). + * The VAST error code is passed to the listener function as a parameter. + */ + on(eventName: string, listener: (error: DMVAST.VastError) => void): void; + /** + * Add a one time listener function for the event named eventName. + */ + once(eventName: string, listener: (data?: any) => void): void; + /** + * Fetch a URL and parse the response into a valid VAST object. + * + * String url – The VAST XML document URL to fetch. + * Object options – An optional set of key/value to configure the Ajax request: + * Object urlhandler – A URL handler module, used to fetch the VAST document instead of the default ones. + * Boolean withCredentials – A boolean to enable the withCredentials options for the XHR and FLASH URLHandlers. + * Number wrapperLimit – A number of available Wrapper responses that can be received with no InLine response. + * Function done – Method to be called once the VAST document is parsed. When at least 1 valid has been found, the 1st parameter will be an array of VASTAd instances. + * Hoverwise, in case of no ads, it will be null, and an error as a 2nd parameter is provided. + */ + parse(url: string, done: (response: DMVAST.VastResponse, error: Error) => void): void; + parse(url: string, options: DMVAST.VastRequestOptions, done: (response: DMVAST.VastResponse, error: Error) => void): void; + /** + * Remove the specified listener for the event named eventName. + */ + off(eventName: string, listener: (error: DMVAST.VastError) => void): void; + /** + * Remove replace function from URLTemplateFilters array. + * Replace function won't be called on the next VAST URL encountred by the parser. + */ + removeURLTemplateFilter(cb: (vastUrl: string) => string): void; + } + + interface VastRequestOptions { + /** + * A VAST XML document. When response is provided, no Ajax request is made and thus the url parameter is ignored. + */ + response?: string; + /**a + * A URL handler module, used to fetch the VAST document instead of the default ones. + */ + urlhandler?: any; + /** + * A boolean to enable the withCredentials options for the XHR and FLASH URLHandlers. + */ + withCredentials?: boolean; + /** + * A number of available Wrapper responses that can be received with no InLine response. + */ + wrapperLimit?: number; + } + + interface VastResponse { + ads: VastAd[]; + errorURLTemplates: string[]; + } + + interface VastError { + /** + * Whenever an error occurs during the VAST parsing, the parser will call on his own all related tracking error URLs. Reported errors are: + * no_ad: The VAST document is empty + * VAST error 101: VAST schema validation error. + * VAST error 301: Timeout of VAST URI provided in Wrapper element. + * VAST error 302: Wrapper limit reached. + * VAST error 303: No VAST response after one or more Wrappers. + */ + ERRORCODE: string; + } + + interface VastAd { + advertiser: any; + creatives: VastCreativeLinear | VastCreativeCompanion[]; + description: string; + errorURLTemplates: string[]; + extensions: VastAdExtension[]; + id: string; + impressionURLTemplates: string[]; + pricing: any; + sequence: string; + survey: any; + system: VastSystem; + title: string; + hasHLS: boolean; + } + + interface VastAdExtension { + attributes: VastAdAttributes; + children: VastAdExtensionChild[]; + } + + interface VastAdAttributes { + type: string; + } + + interface VastAdExtensionChild { + attributes: VastAdChildAttributes; + name: string; + value: string; + } + + interface VastAdChildAttributes { + name: string; + } + + interface VastCreativeLinear { + adParameters: any; + duration: number; + icons: string[]; + mediaFiles: VastMediaFile[]; + skipDelay: boolean; + trackingEvents: VastTrackingEvents; + type: string; + videoClickThroughURLTemplate: string; + videoClickTrackingURLTemplates: string[]; + videoCustomClickURLTempaltes: string[]; + } + + interface VastCreativeCompanion { + type: string; + variations: VastCompanionAd[]; + } + + interface VastCompanionAd { + companionClickThroughURLTemplate: string; + companionClickTrackingURLTemplate: string; + companionClickTrackingURLTemplates: string[]; + height: string; + htmlResource: string; + id: string; + iframeResource: string; + staticResource: string; + trackingEvents: VastCompanionTrackingEvents; + type: string; + width: string; + } + + interface VastCompanionTrackingEvents { + creativeView: string[]; + } + + interface VastMediaFile { + apiFramework: any; + bitrate: number; + codec: string; + deliveryType: string; + fileURL: string; + height: number; + id: string; + maintainAspectRatio: boolean; + maxBitrate: number; + mimeType: string; + minBitrate: number; + scalable: any; + width: number; + } + + interface VastTrackingEvents { + complete: string[]; + firstQuartile: string[]; + midpoint: string[]; + thirdQuartile: string[]; + } + + interface VastSystem { + value: string; + version: string; + } +} diff --git a/types/vast-client/tsconfig.json b/types/vast-client/tsconfig.json new file mode 100644 index 0000000000..5ab6b994a8 --- /dev/null +++ b/types/vast-client/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "vast-client-tests.ts" + ] +} diff --git a/types/vast-client/tslint.json b/types/vast-client/tslint.json new file mode 100644 index 0000000000..d88586e5bd --- /dev/null +++ b/types/vast-client/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "dtslint/dt.json" +} diff --git a/types/vast-client/vast-client-tests.ts b/types/vast-client/vast-client-tests.ts new file mode 100644 index 0000000000..eed1416c7a --- /dev/null +++ b/types/vast-client/vast-client-tests.ts @@ -0,0 +1,230 @@ +import * as DMVAST from 'vast-client'; + +const VASTUrl = 'http://example.dailymotion.com/vast.xml'; +function cb(response: DMVAST.VastResponse, error: Error): void { + if (error) return; + // process the VAST response + const ads: DMVAST.VastAd[] = response.ads; +} + +// CLIENT + +// Ignore the first 2 calls +DMVAST.client.cappingFreeLunch = 2; + +// Those following DMVAST.client.get calls won't be done +DMVAST.client.get(VASTUrl, cb); +DMVAST.client.get(VASTUrl, cb); + +// VASTUrl will be called +DMVAST.client.get(VASTUrl, cb); + +// Ignore any call made 5 minutes or less after one. +DMVAST.client.cappingMinimumTimeInterval = 5 * 60 * 1000; + +// Work +DMVAST.client.get(VASTUrl, cb); + +// ... +// 2 minutes later + +// Ignored +DMVAST.client.get(VASTUrl, cb); + +// ... +// 4 minutes later + +// Work +DMVAST.client.get(VASTUrl, cb); + +// PARSER + +DMVAST.parser.addURLTemplateFilter((vastUrl: string): string => { + return vastUrl.replace('[DOMAIN]', 'mywebsite.com'); +}); + +const count = DMVAST.parser.countURLTemplateFilters(); + +DMVAST.parser.clearUrlTemplateFilters(); + +const xml = 'some xml'; +const options = { + withCredentials: true, + wrapperLimit: 5 +}; + +DMVAST.parser.load(xml, options, cb); + +const url = 'http://example.dailymotion.com/vast.xml'; + +DMVAST.parser.parse(url, options, cb); + +const replaceDomain = (url: string): string => { + return url.replace('[DOMAIN]', 'mywebsite.com'); +}; + +DMVAST.parser.addURLTemplateFilter(replaceDomain); +DMVAST.parser.removeURLTemplateFilter(replaceDomain); + +// TRACKER + +// Create a VAST Tracker instance for a linear ad +const vastTracker = new DMVAST.tracker({} as DMVAST.VastAd, {} as DMVAST.VastCreativeLinear); + +// Create a VAST Tracker instance for a companion ad +// const vastTracker = new DMVAST.tracker({} as DMVAST.VastAd, {} as DMVAST.VastCreativeLinear, {} as DMVAST.VastCreativeCompanion); + +const onSkip = () => { + console.log('Ad unit skipped'); +}; + +// Log a message when event 'skip' is emitted +vastTracker.on('skip', onSkip); +// Stop logging message +vastTracker.off('skip', onSkip); + +const player: HTMLVideoElement = document.getElementById('playerId'); + +// Bind a timeupdate listener to the player +player.addEventListener('timeupdate', (e) => { + vastTracker.setProgress(( e.target).currentTime); +}); + +vastTracker.on('firstQuartile', () => { + // firstQuartile tracking URLs have been called +}); + +// Bind a volumechange listener to the player +player.addEventListener('volumechange', (e) => { + vastTracker.setMuted(( e.target).muted); +}); + +vastTracker.on('mute', () => { + // mute tracking URLs have been called +}); + +vastTracker.on('unmute', () => { + // unmute tracking URLs have been called +}); + +// Bind play/pause listeners to the player +player.addEventListener('play', () => { vastTracker.setPaused(false); }); +player.addEventListener('pause', () => { vastTracker.setPaused(true); }); + +vastTracker.on('resume', () => { + // resume tracking URLs have been called +}); + +vastTracker.on('pause', () => { + // pause tracking URLs have been called +}); + +// Bind fullscreenchange listener to the player +// Note that the fullscreen API is still vendor-prefixed in browsers +player.addEventListener('fullscreenchange', (e) => { + const isFullscreen = !!document.fullscreenElement; + vastTracker.setFullscreen(isFullscreen); +}); + +vastTracker.on('fullscreen', () => { + // fullscreen tracking URLs have been called +}); + +vastTracker.on('exitFullscreen', () => { + // exitFullscreen tracking URLs have been called +}); + +// Sample function for a button that increase/decrease player size +let playerExpanded = false; + +const expandButton = document.getElementById('buttonId'); + +function increasePlayerSize(): void { + // do nothing +} + +function decreasePlayerSize(): void { + // do nothing +} + +expandButton.addEventListener('click', (e) => { + playerExpanded = !playerExpanded; + if (playerExpanded) { + increasePlayerSize(); + } else { + decreasePlayerSize(); + } + vastTracker.setExpand(playerExpanded); +}); + +vastTracker.on('expand', () => { + // expand tracking URLs have been called +}); + +vastTracker.on('collapse', () => { + // collapse tracking URLs have been called +}); + +// Overwrite linear Skipoffset value – 5s countdown +vastTracker.setSkipDelay(5); + +// Bind canplay listener to the player +player.addEventListener('canplay', () => { + vastTracker.load(); +}); + +vastTracker.on('creativeView', () => { + // impression tracking URLs have been called +}); + +const MEDIAFILE_PLAYBACK_ERROR = '405'; + +// Bind error listener to the player +player.addEventListener('error', () => { + vastTracker.errorWithCode(MEDIAFILE_PLAYBACK_ERROR); +}); + +// Bind ended listener to the player +player.addEventListener('ended', () => { + vastTracker.complete(); +}); + +vastTracker.on('complete', () => { + // complete tracking URLs have been called +}); + +// When user exits the page +window.onbeforeunload = () => { + vastTracker.close(); +}; + +// use for VAST 3.0 linear ads +vastTracker.on('closeLinear', () => { + // ... +}); + +// Use for VAST 2.0 linear ads or companion ads +vastTracker.on('close', () => { + // ... +}); + +// Bind click listener to the skip button +const skipButton = document.getElementById('buttonId'); + +skipButton.addEventListener('click', () => { + vastTracker.skip(); +}); + +vastTracker.on('skip', () => { + // skip tracking URLs have been called +}); + +// Bind click listener to the player +player.addEventListener('click', () => { + vastTracker.click(); +}); + +vastTracker.on('clickthrough', (url: string) => { + // Open the resolved clickThrough url + document.location.href = url; +});