Outstream Advertising

Trigger an in-read ad to autoplay once it comes into view and collapse the video player after ad completion.

License: Enterprise
Player Version:
Author: JW Player | GitHub
This demo includes:
  • on('complete')
  • on('adComplete')
  • on('adError')
  • remove()

Outstream Advertising

This demo resembles a long blog post with an inline video ad. Scroll down to see the demo and JavaScript code.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui ex, suscipit eu ultrices et, congue nec quam. Sed ultricies bibendum quam at sollicitudin. Mauris ut dapibus sapien. Sed turpis mauris, cursus in enim ut, sodales tempus tortor. Donec varius aliquam massa. Donec fermentum pellentesque molestie. Integer varius porta vehicula. Etiam volutpat nibh et nisl malesuada, vel auctor tellus commodo. Aliquam quis pharetra diam. Aliquam efficitur molestie viverra. Curabitur eu vulputate odio. Praesent sollicitudin tincidunt rhoncus. Phasellus nunc metus, blandit quis arcu at, feugiat viverra lorem. Phasellus sollicitudin augue at tincidunt ullamcorper. Quisque non ipsum augue.

Donec eget urna sit amet tellus varius efficitur ac sodales lorem. Nullam id elit eros. Etiam finibus nunc vel ante condimentum, eu ullamcorper lorem commodo. Maecenas pretium, nulla id iaculis convallis, lectus dui feugiat arcu, sit amet placerat augue turpis quis ante. Sed sit amet ornare dui. Ut maximus suscipit dictum. Fusce vitae justo tortor. Cras ac vestibulum augue, sed tristique felis. Nam tincidunt sapien velit, dignissim tempus justo laoreet in.

Advertisement

Vivamus eleifend congue lectus, quis ullamcorper tortor accumsan non. Duis vitae mattis tortor. Nulla vitae odio enim. Praesent eu orci at elit venenatis luctus. Praesent at luctus mauris. Maecenas accumsan posuere varius. Suspendisse id vehicula mauris. Vestibulum id neque vitae dui lobortis eleifend non sed erat. Nunc posuere augue nec turpis ornare facilisis. Vivamus lectus justo, commodo sed molestie consequat, dictum sed est. Maecenas semper velit placerat ex finibus rhoncus. Duis nisi justo, pharetra ac ipsum ac, gravida venenatis risus. Praesent eu est ultrices, lobortis felis quis, volutpat augue. Mauris non varius lacus. Etiam pulvinar ornare lectus et tristique.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui ex, suscipit eu ultrices et, congue nec quam. Sed ultricies bibendum quam at sollicitudin. Mauris ut dapibus sapien. Sed turpis mauris, cursus in enim ut, sodales tempus tortor. Donec varius aliquam massa. Donec fermentum pellentesque molestie. Integer varius porta vehicula. Etiam volutpat nibh et nisl malesuada, vel auctor tellus commodo. Aliquam quis pharetra diam. Aliquam efficitur molestie viverra. Curabitur eu vulputate odio. Praesent sollicitudin tincidunt rhoncus. Phasellus nunc metus, blandit quis arcu at, feugiat viverra lorem. Phasellus sollicitudin augue at tincidunt ullamcorper. Quisque non ipsum augue.

Donec eget urna sit amet tellus varius efficitur ac sodales lorem. Nullam id elit eros. Etiam finibus nunc vel ante condimentum, eu ullamcorper lorem commodo. Maecenas pretium, nulla id iaculis convallis, lectus dui feugiat arcu, sit amet placerat augue turpis quis ante. Sed sit amet ornare dui. Ut maximus suscipit dictum. Fusce vitae justo tortor. Cras ac vestibulum augue, sed tristique felis. Nam tincidunt sapien velit, dignissim tempus justo laoreet in.

<script type="text/javascript">

// math functions related to scroll and offset positions relative to player
var getScrollTop = function() {
	var documentEl = document.documentElement;
	return (window.pageYOffset || documentEl.scrollTop) - (documentEl.clientTop || 0);
};
var getElementOffsetTop = function(el) {
	var bodyRect = document.body.getBoundingClientRect(),
		elRect = el.getBoundingClientRect();
	return elRect.top - bodyRect.top;
};
var	getAdInView = function() {
	var scrollBoundary = playerOffsetTop + (playerHeight / 2),
		scrollTop = getScrollTop();
	return (window.innerHeight + scrollTop) > scrollBoundary && scrollTop < scrollBoundary;
};

// cross-browser event binding method
var setEventListener = function(el, ev, fn) {
	var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent',
		eventName = window.addEventListener ? ev : 'on' + ev;
	el[eventMethod](eventName, fn, false);
};

// get element margin top and bottom totat height
var getMarginHeight = function(el) {
	if (document.all) {
		return parseInt(el.currentStyle.marginTop, 10) + parseInt(el.currentStyle.marginBottom, 10);
	} else {
		return parseInt(document.defaultView.getComputedStyle(el, '').getPropertyValue('margin-top')) + parseInt(document.defaultView.getComputedStyle(el, '').getPropertyValue('margin-bottom'));
	}
};

// check if ad is in view, ad visible class when necessary (but only the first time it's in view)
var setAdDisplayState = function() {
	if (getAdInView()) {
		if (!new RegExp('(^| )jw-ad-visible( |$)', 'gi').test(adEl.className)) {
			adEl.className += (adEl.className ? ' ' : '') + 'jw-ad-visible';
			adEl.style.maxHeight = adLabelEl.offsetHeight + getMarginHeight(adLabelEl) + adMediaContainerEl.offsetHeight + getMarginHeight(adMediaContainerEl) + 'px';
		}
		if (playerInstance.getState() === 'idle' || playerInstance.getState() === 'paused') {
			setTimeout(function() {
				playerInstance.play();
			}, 0);
		}
	} else {
		if (playerInstance.getState() === 'playing') {
			setTimeout(function() {
				playerInstance.pause();
			}, 0);
		}
	}
};

// player elements and utility vars
var playerInstance = jwplayer('player'),
	adEl = document.querySelector('.jw-ad'),
	adLabelEl = document.querySelector('.jw-ad-label'),
  adMediaContainerEl = document.querySelector('.jw-ad-media-container'),
  playerHeight,
  playerOffsetTop = getElementOffsetTop(adEl),
	isScrollTimeout = false; // namespace for whether or not we are waiting for setTimeout() to finish

// player setup
playerInstance.setup({
  file: 'http://content.jwplatform.com/videos/mX3zaT5H-Zq6530MP.mp4',
  advertising: {
    client: 'vast',
    tag: 'https://playertest.longtailvideo.com/vast-30s-ad.xml'
  }
});

playerInstance.on('ready', function() {

	// get player container height
	playerHeight = adMediaContainerEl.offsetHeight;

	// mute by default
	playerInstance.setMute(true);

	// unmute/mute player on adMediaContainerEl mouse enter/leave
	setEventListener(adMediaContainerEl, 'mouseenter', function() {
		playerInstance.setMute(false);
	});

	setEventListener(adMediaContainerEl, 'mouseleave', function() {
		playerInstance.setMute(true);
	});

	// handle ad display state on page load
	setTimeout(setAdDisplayState(), 1000);

  // attach scroll event listener to window
  setEventListener(window, 'scroll', function() {
		// skip if we're waiting on a scroll update timeout to finish
		if (isScrollTimeout) return;
		// flag that a new timeout will begin
		isScrollTimeout = true;
		// otherwise, execute scroll event handler
		setAdDisplayState();
		// set new timeout
		setTimeout(function() {
			// reset timeout flag to false (no longer waiting)
			isScrollTimeout = false;
		}, 100);
  });
});

// handle when ad is complete or encounters error
playerInstance.on('complete adComplete adError', function() {
	adEl.style.maxHeight = '0px';
  setTimeout(function() {
    playerInstance.remove();
    adMediaContainerEl.parentNode.removeChild(adMediaContainerEl);
  }, 500 /* should be the same duration as css transition */);
});

</script>
Please Note: This player implementation is a Proof of Concept only provided to show the possibilities of the JW Player and Platform and should not be taken as an offer to create, edit or maintain custom integration or development.