Skip to content

Commit

Permalink
Merge pull request #56 from ordyakov/createClickControl
Browse files Browse the repository at this point in the history
feat: allow to use custom click element
  • Loading branch information
andrepolischuk authored Sep 30, 2022
2 parents c467a78 + 8f26118 commit f864ada
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/adUnit/VastAdUnit.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class VastAdUnit extends VideoAdUnit {
* Defaults to `window.console`
* @param {Object} [options.hooks] - Optional map with hooks to configure the behaviour of the ad.
* @param {Function} [options.hooks.createSkipControl] - If provided it will be called to generate the skip control. Must return a clickable [HTMLElement](https://developer.mozilla.org/es/docs/Web/API/HTMLElement) that is detached from the DOM.
* @param {Function} [options.hooks.createClickControl] - If provided it will be called to generate the click control. Must return a clickable [HTMLElement](https://developer.mozilla.org/es/docs/Web/API/HTMLElement) that is detached from the DOM.
* @param {Function} [options.hooks.getMediaFile] - If provided it will be called to get a {@link MediaFile} by size of the current video element.
* @param {boolean} [options.viewability] - if true it will pause the ad whenever is not visible for the viewer.
* Defaults to `false`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,21 @@ test('onClickThrough must remove the anchor on disconnect', () => {

expect(element.querySelector('a.mol-vast-clickthrough')).toEqual(null);
});

test('onClickThrough must use custom click element', () => {
const {element, videoElement} = videoAdContainer;
const customClickElement = document.createElement('span');

element.appendChild(customClickElement);

const createClickControl = () => customClickElement;

onClickThrough(videoAdContainer, callback, {createClickControl});

videoElement.paused = false;
customClickElement.click();

expect(element.querySelector('a.mol-vast-clickthrough')).toBeNull();
expect(callback).toHaveBeenCalledTimes(1);
expect(callback).toHaveBeenCalledWith(clickThrough);
});
25 changes: 19 additions & 6 deletions src/adUnit/helpers/metrics/handlers/onClickThrough.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import {linearEvents} from '../../../../tracker';

const {clickThrough} = linearEvents;

const onClickThrough = ({videoElement, element}, callback, {clickThroughUrl, pauseOnAdClick = true} = {}) => {
const placeholder = element || videoElement.parentNode;
const createDefaultClickControl = () => {
const anchor = document.createElement('A');

anchor.classList.add('mol-vast-clickthrough');
Expand All @@ -14,7 +13,19 @@ const onClickThrough = ({videoElement, element}, callback, {clickThroughUrl, pau
anchor.style.left = 0;
anchor.style.top = 0;

if (clickThroughUrl) {
return anchor;
};

const onClickThrough = ({videoElement, element}, callback, {clickThroughUrl, pauseOnAdClick = true, createClickControl = createDefaultClickControl} = {}) => {
const placeholder = element || videoElement.parentNode;
const anchor = createClickControl();
const isVirtual = !document.body.contains(anchor);

if (isVirtual) {
placeholder.appendChild(anchor);
}

if (clickThroughUrl && anchor.tagName === 'A') {
anchor.href = clickThroughUrl;
anchor.target = '_blank';
}
Expand All @@ -39,9 +50,11 @@ const onClickThrough = ({videoElement, element}, callback, {clickThroughUrl, pau
}
};

placeholder.appendChild(anchor);

return () => placeholder.removeChild(anchor);
return () => {
if (isVirtual) {
placeholder.removeChild(anchor);
}
};
};

export default onClickThrough;
1 change: 1 addition & 0 deletions src/runner/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import startVideoAd from './helpers/startVideoAd';
* @param {TrackerFn} [options.tracker] - If provided it will be used to track the VAST events instead of the default {@link pixelTracker}.
* @param {Object} [options.hooks] - Optional map with hooks to configure the behaviour of the ad.
* @param {Function} [options.hooks.createSkipControl] - If provided it will be called to generate the skip control. Must return a clickable [HTMLElement](https://developer.mozilla.org/es/docs/Web/API/HTMLElement) that is detached from the DOM.
* @param {Function} [options.hooks.createClickControl] - If provided it will be called to generate the click control. Must return a clickable [HTMLElement](https://developer.mozilla.org/es/docs/Web/API/HTMLElement) that is detached from the DOM.
* @param {Function} [options.hooks.getMediaFile] - If provided it will be called to get a {@link MediaFile} by size of the current video element.
* @returns {Promise.<VastAdUnit|VpaidAdUnit>} - The video ad unit.
*/
Expand Down
1 change: 1 addition & 0 deletions src/runner/runWaterfall.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ const waterfall = async (fetchVastChain, placeholder, options, isCanceled) => {
* Defaults to `true`.
* @param {Object} [options.hooks] - Optional map with hooks to configure the behaviour of the ad.
* @param {Function} [options.hooks.createSkipControl] - If provided it will be called to generate the skip control. Must return a clickable [HTMLElement](https://developer.mozilla.org/es/docs/Web/API/HTMLElement) that is detached from the DOM.
* @param {Function} [options.hooks.createClickControl] - If provided it will be called to generate the click control. Must return a clickable [HTMLElement](https://developer.mozilla.org/es/docs/Web/API/HTMLElement) that is detached from the DOM.
* @param {Function} [options.hooks.getMediaFile] - If provided it will be called to get a {@link MediaFile} by size of the current video element.
* @param {Function} [options.hooks.validateVastResponse] - If provided it will be called passing the current {@link VastChain} for each valid vast response. Must throw if there is a problem with the vast response. If the Error instance has an `code` number then it will be tracked using the error macros in the Vast response. It will also call {@link runWaterfall~onError} with the thrown error.
* @param {Function} [options.hooks.transformVastResponse] - If provided it will be called with the current {@link VastChain} before building the adUnit allowing the modification of the vastResponse if needed.
Expand Down

0 comments on commit f864ada

Please sign in to comment.