mondworker / Spiegel Online Video Ad remover

// ==UserScript==
// @name        Spiegel Online Video Ad remover
// @description Entfernt die Videowerbung vor einem Clip auf Spiegel-Online
// @include     http*
// @grant       none
// @version     2.08
// @namespace https://greasyfork.org/users/16149
// ==/UserScript==
var scriptCode = new Array();
scriptCode.push('function spStartVideo6(wrapperElemId, videoId, videoFilename, poster, prerollGateway, postrollGateway, allowAds, credit, displaycat, videocat, server, trackingsize, autoplay, onAdStart, onAdEnd, onVideoEnd, onFinalEnd, embedWidth, embedHeight) {	spStartVideo({		wrapperElemId:		wrapperElemId,		videoId: videoId,		videoFilename:		videoFilename,		poster: 	poster,		prerollGateway:		"",		postrollGateway:	"",		allowAds: false,		credit: 	credit,		displaycat: displaycat,		videocat: videocat,		server: 	server,		trackingsize:		trackingsize,		autoplay: autoplay,		callbacks: { /* spStartVideo6 sets callback functions by name inside string - convert them to real JS functions*/ onAdStart: window[onAdStart], onAdEnd: window[onAdEnd], onVideoEnd: window[onVideoEnd], onFinalEnd: window[onFinalEnd]		},		embedWidth: embedWidth,		embedHeight:		embedHeight	});} function spStartVideo(config) {	/*alert("startVideoGM");*//* set config param defaults */	var defaults = {		prerollGateway:		\'\',		postrollGateway:	\'\',		overlayGateway:		\'\',		overlayStartAt:		7,		allowAds:			false,		autoplay:			true,		callbacks: 			{},		embedWidth:			640,		embedHeight:		360	};	config = $.extend({}, defaults, config);	/* special hash param switches to affect ads & statistics */	var hashParams = (typeof spGetHashParams === \'function\' ? spGetHashParams() : []);	/* extra ref parameter for statistics */	var refParam = hashParams.ref !== null ? hashParams.ref : \'\';	/* deactivating ads, also possible through ADI */	if (true) {		config.prerollGateway	= "";		config.postrollGateway	= "";		config.overlayGateway	= "";		config.allowAds = false;		config.callbacks = {};	}		/* get ABD (ad-block detection) status - if function is not defined we\'re likely in an Iframe, so let\'s use the SPON interface in that case */	var abd = false; /*(!window.spGetAbdStatus && spInterface) ? spInterface(\'getAbdStatus\') : spGetAbdStatus();*/	var wrapperElem = $(\'#\' + config.wrapperElemId);	var html5PlayerWrapperId = wrapperElem.find(\'.videoplayer-placeholder\').attr(\'id\');	if (!html5PlayerWrapperId) {		/* assign an ID to player wrapper element, because JW player needs an ID for setup */		var playerIdCount = 1;		/* make sure the ID doesn\'t exist yet */		while ($(\'#spVideoplayer-\' + playerIdCount).length)			playerIdCount++;		html5PlayerWrapperId = \'spVideoplayer-\' + playerIdCount;		wrapperElem.find(\'.videoplayer-placeholder\').attr(\'id\', html5PlayerWrapperId);	}	if ((spUA.isIDevice() || spUA.isAndroid()) && parseInt(config.videoId) < 58671) {		/* this video is limited to desktop */		wrapperElem.find(\'.video-player-error\')			.html(unescape(\'Dieses Video steht f%FCr iOS- %26 Android-Ger%E4te nicht zur Verf%FCgung.\'))  /* work around encoding-problems with umlauts... */			.show();	} else if (!document.createElement(\'video\').canPlayType && !isValidPluginVersion()) {		/* no HTML5 video possible & Flash version not sufficient for fallback play */		var fpversion = swfobject.getFlashPlayerVersion();		wrapperElem.find(\'.video-player-error\')			.html(unescape(\'Dieses Video ben%F6tigt mindestens Version \') + sp_webcfg_global.flash.pluginversion.major + \'.\' + sp_webcfg_global.flash.pluginversion.minor + \' des Flash-Plugins. Gefundene Version: \' + fpversion.major + \'.\' + fpversion.minor + \'.\' + fpversion.release + \' \' + spnetENV_NOFLASHPLAYER_LINK)			.show();	} else {		/* make sure a filname is provided (note: JW Player can only play videofiles directly, no video ID HTML redirect possible) */		if (config.videoFilename === null || config.videoFilename === \'\') return;		/* set generic player options */		jwplayer.key = spnetENV_JWPLAYER_KEY;		var jwplayerOptions = {			flashplayer:	\'/static/flash/flashvideo/jwplayer7.flash.swf\',			primary:		\'flash\',			image:			config.poster,			width:			config.embedWidth,			height:			config.embedHeight,			autostart:		config.autoplay,			ga:				{},    /* enable Google Analytics, uses the GA JS already on the page */			skin: {				name:			\'spon\'			}		};		/* read cookie for HQ/SQ */		var qualityCookieName = \'sponVideoplayerQuality\';		var playerQuality = \'hq\';		if ($.cookie(qualityCookieName))			playerQuality = $.cookie(qualityCookieName);		else			$.cookie(qualityCookieName, playerQuality, { expires: 365, path: \'/\' });		/* set video sources */		if (typeof config.videoFilename == \'object\') {			jwplayerOptions.sources = [];			/* check all quality levels that we\'re expecting */			$.each([\'sq\', \'hq\'], function(i, quality) {				if (config.videoFilename[quality] !== \'\') {					var sourceInfo = {file: config.server + config.videoFilename[quality]};					/* set this quality as default if quality read from cookie matches */					if (playerQuality == quality)						sourceInfo[\'default\'] = true;					jwplayerOptions.sources.push(sourceInfo);				}			});		} else {			/* legacy: videoFilename is a single string */			jwplayerOptions.file = config.server + config.videoFilename;		}				/* instantiate player */		var jwplayerInstance = jwplayer(html5PlayerWrapperId).setup(jwplayerOptions);		jwplayerInstance.on(\'ready\', function() {			var playerElem = $(\'#\' + this.id);			/* store player instance from JW Player setup for future reference (i.e. removing player) */			playerElem.data(\'playerInstance\', jwplayerInstance);			/* detect if we\'re on a touch device */			var touchabilityClass = \'jw-\'+(\'ontouchstart\' in document.createElement(\'div\') ? \'\' : \'un\')+\'touchable\';			playerElem.addClass(touchabilityClass);			/* detect if we\'re inside an iframe */			var isInIframe = window.parent != window.self;			/* get video data */			var videoData = playerElem.parents(\'.video-elements\').data();			/* move duration display over to left group */			playerElem.find(\'.jw-text-duration\').detach().appendTo(playerElem.find(\'.jw-controlbar-left-group\'));			/* hover handler for icons, cause JW Player has a bug when keeping controls open (won\'t happen on hover for dock icons) */			playerElem.on(\'mouseenter\', \'.jw-icon\', function() {				playerElem.addClass(\'jw-flag-icon-hover\');			});			playerElem.on(\'mouseleave\', \'.jw-icon\', function() {				playerElem.removeClass(\'jw-flag-icon-hover\');			});			/* add left dock with info button & addtional text */			playerElem.find(\'.jw-dock\').append(\'<div class="jw-dock-left jw-reset"></div>\');			playerElem.find(\'.jw-dock-left\').append(\'<div class="jw-icon jw-icon-info jw-button-color"></div>\');			var infoWindow = \'<div class="jw-infowindow">\'+								\'<a class="jw-spon-logo" href="/"\'+(isInIframe ? \' target="_blank"\' : \'\')+\'><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA8CAIAAABZ6yszAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABAdJREFUeNrsmL9PU1EUxymKAw7UwcVE2sWFaOgfYEKdxaSDiyxtR3WgmzK13WDr5ki7wKADiTpbEpx0aKOyuLSaOOhga6IhYcBPe/R4Oe+9UgqJNLnfvDTv3nt+3O/5ce+D2NOJ+MQ4Y3JizOEJeAKegCfgCXgCnoAn4Al4Av8P5834SuZ2PHVDhx8rT/Y73bnSYyPGJEu8uEvt6kYitxT08av1qVXdmIrPXCvc18lO492XrZfGgovd0moytzSdnJXht/oOT4gcf9Do8yb34OAwcMP8QRjYk1mqpxdDJb/Wd5DElJnHXZRxwBKKOvxQWnW3qs+hEpL4tWubu+U1fnmfmb/eY7/9er/7oxfL9mfeu833PeHsvV6cymt/wl/bJNLukHeE1biYYlLnxZ1REb+aUjzKBsLDH9oDhJb08asz2+lF4idLvDcKK26iVesnBJwh70GvTJp5o+L6FZuD6ifYA26Nbt+6c8IOI4Q4pmGGnB/BbwiBhVfP3eGz2CV9p6sup29eiM8caVeNkH2SpvOoRy1FzR+bwABMJ67yyPvb/MMzd4xGhepf6mubUqNkX7oiCpRBaNUySUo5OueKj4ZUccGuxEh4Ey/UX9w9+B51MANaSvpp8O4VmMIgZoePKFtEhSeqMk1Yx/4mPnSRuRfHkBfK8BdZ1Hyo06BfsxR+kTULK3JhKU6xU40pHDWd+2RkxMz/Ri8mZ/XzQzuVr6Opv0cn161cLmcEsXH/5+7Y41zUQjqdTiaTvbu90zFL8Xh8b2/vVNyPYMqoTAaXK5VKo9HIZDJw2NraarVavKtAKpWq1+uIGbaocD4UCgUZQpsh6q4Yq71P9E4HAZlBIJfLmT1Uq1XEMBjvA5ne13urhV90WR3EDzUjgQP0S6WS7lWtGzF86BB5xELtqynAnhALcjBR0w3gVGIUngGEkDDm4FOr1YrFolRU74Oi3Z6fnzd5aPVxZAEEC7Lb7a6vr7vbFWtBSVGnQCIJsHWTdIHoKDGs5/N5OBhbowGzzWaTMFGcJ/2YSyQSobzJu1S/mxZ+iZxLbDRIS9T7kF6KOlQoEKqA8LlFOHksT6a0yuVyNps9oquGsywlBIeoPGgTm0K1fw9ooUflwfQM8nAQ6yfhgAXJAzUcykFcBA/AQwRoViKBhAm2hCe0PaR+aHFjdwQQIK2l4QvBnkKSR3c3vDNPtWjuggcozJeXlwd41bNvQIaVAzKcEAOaflAYSJ8ciLjElpzubtPIZaQ3kdsSGjkYygHPJLr86jEgd4jQkI5k1bBCzL3syL9olfowGYiF0kBHClEqz429FigWg5UmZZbsw1QwQFeyhyLqOgzeIRJHsW+CJbr+I9DDw8PDw8PDw8PDY/zxW4ABADOl37fKzRkIAAAAAElFTkSuQmCC"/></a>\'+								\'<div class="jw-info-title">\'+videoData.videoTitle+\'</div>\'+								\'<div class="jw-info-text">\';			if (videoData.videoTeaser && videoData.videoTeaser !== \'\')				infoWindow +=		\'<p>\'+videoData.videoTeaser+\'</p>\';			if (videoData.videoArticleUrl && videoData.videoArticleUrl !== \'\')				infoWindow +=		\'<a href="\'+videoData.videoArticleUrl+\'">Zum Artikel</a>\';			infoWindow +=			\'<span class="jw-info-date">\'+videoData.videoDate+\'</span>\'+								\'</div>\'+							\'</div>\';			playerElem.find(\'.jw-dock-left\').append(infoWindow);			/* click handler for info window */			playerElem.on(\'click touchstart\', \'.jw-icon-info\', function() {				$(this).add(playerElem.find(\'.jw-infowindow\')).toggleClass(\'jw-open\');				playerElem.toggleClass(\'jw-flag-infowindow-open\');			});			/* add separate area for right dock */			playerElem.find(\'.jw-dock\').append(\'<div class="jw-dock-right jw-reset"></div>\');			/* add share buttons */			playerElem.find(\'.jw-dock-right\').append(\'<div class="jw-icon jw-icon-share jw-button-color"></div>\');			playerElem.find(\'.jw-dock-right\').append(\'<div class="jw-shares"></div>\');			playerElem.find(\'.jw-shares\').append(\'<div class="jw-icon jw-icon-share-facebook jw-button-color"></div>\');			playerElem.find(\'.jw-shares\').append(\'<div class="jw-icon jw-icon-share-twitter jw-button-color"></div>\');			playerElem.find(\'.jw-shares\').append(\'<div class="jw-icon jw-icon-share-googleplus jw-button-color"></div>\');			playerElem.find(\'.jw-shares\').append(\'<div class="jw-icon jw-icon-share-mail jw-button-color"></div>\');			playerElem.find(\'.jw-shares\').append(\'<div class="jw-icon jw-icon-share-link jw-button-color"></div>\');			/* copy share buttons to endscreen */			playerElem.parent().find(\'.video-end-screen .sharebuttons-placeholder\').replaceWith(				$(\'<div class="jw-skin-spon \' + touchabilityClass + \'"><div class="jw-dock"></div></div>\')			);			playerElem.parent().find(\'.video-end-screen .jw-dock\').append(playerElem.find(\'.jw-dock-right\').clone());			playerElem.parent().find(\'.video-end-screen .jw-icon-share, .video-end-screen .jw-shares\').addClass(\'jw-open\');			/* click handlers for share buttons */			playerElem.on(\'click touchstart\', \'.jw-icon-share\', function() {				$(this).add(playerElem.find(\'.jw-shares\')).toggleClass(\'jw-open\');			});			/* handler for actual shares has to be one element up, so that share buttons in endscreen are detected as well */			playerElem.parent().on(\'click touchstart\', \'.jw-shares .jw-icon\', function() {				/* social media shares just open their respective share URLs inside new popup */				if ($(this).hasClass(\'jw-icon-share-facebook\'))					window.open(\'https://www.facebook.com/sharer/sharer.php?u=\'+videoData.videoSocialUrl+\'&display=popup&ref=plugin&src=share_button\', \'spon-share\', \'top=150,left=200,toolbar=0,status=0,width=670,height=335\');				if ($(this).hasClass(\'jw-icon-share-twitter\'))					window.open(\'https://twitter.com/intent/tweet?original_referer=\'+videoData.videoSocialUrl+\'&ref_src=twsrc%5Etfw&text=\'+videoData.videoTitle+\'&tw_p=tweetbutton&url=\'+videoData.videoShortUrl+\'&via=SPIEGELONLINE\', \'spon-share\', \'top=150,left=200,toolbar=0,status=0,width=550,height=420\');				if ($(this).hasClass(\'jw-icon-share-googleplus\'))					window.open(\'https://plus.google.com/share?url=\'+videoData.videoSocialUrl+\'&hl=\'+videoData.videoLanguage, \'spon-share\', \'top=150,left=200,toolbar=0,status=0,width=550,height=420\');				/* mail & embed/URL shares may have to use parent methods if inside iframe (inline player or framework player inside iframe) */				if ($(this).hasClass(\'jw-icon-share-mail\'))					if ($(\'#video-inline-player\').length || ($(this).parents(\'.videoplayer-framework\').length && isInIframe))						parent.spOpenSendForm(\'de\', \'video\', null, {videoId: config.videoId});					else						spOpenSendForm(\'de\', \'video\');				if ($(this).hasClass(\'jw-icon-share-link\')) {					if ($(\'#video-inline-player\').length || ($(this).parents(\'.videoplayer-framework\').length && isInIframe))						parent.spOpenEmbedForm(config.videoId, videoData.videoEmbeddable);					else						spOpenEmbedForm(config.videoId, videoData.videoEmbeddable);				}			});			/* flags to make sure that tracking is happening only once */			playerElem.data({				startTracked:	false,				endTracked:		false			});		});		/* define function for Netmind tracking (depends on whether we\'re in an Iframe or on a normal page) */		var doNmTracking = function(trackingParams) {			/* modify default tracking params by the ones passed to this function */			trackingParams = $.extend({				\'sp.atyp\':				33,				\'sp.videocredit\':		config.credit,				\'sp.df\':				config.trackingsize,				\'sp.videodisplaycatid\':	config.displaycat,				\'sp.videocatid\':		config.videocat,				\'sp.aid\':				config.videoId,				\'sp.channel\':			781			}, trackingParams);			if (!window.spNmAjax && spInterface)				spInterface(\'reCountPage\', {newParamsOnly: true, params: trackingParams});			else				spNmAjax(trackingParams);		};		var doTrackEnd = function() {			doNmTracking({				\'sp.site\':	1001,				\'sp.event\':	\'end\'			});			if (typeof config.callbacks.onVideoEnd === \'function\')				config.callbacks.onVideoEnd();		};		/* callback for start of video */		jwplayerInstance.on(\'play\', function() {			var playerElem = $(\'#\' + this.id);			/* move HD button over to dock, each time a new video plays - because JW Player puts it back into the controlbar on each new video */			playerElem.find(\'.jw-icon-hd\').detach().prependTo(playerElem.find(\'.jw-dock-right\'));			/* only track once! onPlay fires every time the player state switches to PLAYING (= also when unpausing the video) */			/* onPlay does NOT fire on preroll - howevery this is desired, cause we want to track the actual content video */			if (!playerElem.data(\'startTracked\')) {				playerElem.data(\'startTracked\', true);				doNmTracking({					\'ref\':		refParam,					\'sp.site\':	1,					\'sp.abd\':	abd				});				/* also track usage of SQ quality */				if (playerQuality == \'sq\') {					doNmTracking({						\'sp.site\':			1001,						\'sp.videoquality\':	\'sq\'					});				}			}		});		/* callback for end of video (fires AFTER end of postroll, if there is one!) */		jwplayerInstance.on(\'complete\', function() {			var playerElem = $(\'#\' + this.id);			/* if video end hasn\'t been tracked before (= if there is no postroll), track it now */			if (!playerElem.data(\'endTracked\'))				doTrackEnd();			if (typeof config.callbacks.onFinalEnd === \'function\')				config.callbacks.onFinalEnd();		});		jwplayerInstance.on(\'adImpression\', function(e) {			var playerElem = $(\'#\' + this.id);						/* always hide the dock & shares */			playerElem.find(\'.jw-icon-share, .jw-shares\').removeClass(\'jw-open-forced\');			playerElem.find(\'.jw-dock, .jw-controlbar\').removeAttr(\'style\');			/* if we\'re at postroll start: track main content video end, because onComplete fires after postroll */			if (e.adposition == \'post\') {				/* if endscreen is present, hide share buttons cause they don\'t really make sense after a postroll */				wrapperElem.find(\'.video-end-screen\').addClass(\'jw-after-postroll\');				/* make sure we don\'t track the video-end again on completion of postroll (which is when the JW Player "onComplete" fires) */				playerElem.data(\'endTracked\', true);				doTrackEnd();			}			if (typeof config.callbacks.onAdStart === \'function\')				config.callbacks.onAdStart();		});		jwplayerInstance.on(\'adComplete\', function() {			if (typeof config.callbacks.onAdEnd === \'function\')				config.callbacks.onAdEnd();		});		jwplayerInstance.on(\'time\', function(player) {			var playerElem = $(\'#\' + this.id);			/* force display of controls, dock & shares when in last part of video */			if (player.position > player.duration - 3) {				playerElem.find(\'.jw-icon-share, .jw-shares\').addClass(\'jw-open-forced\');				playerElem.find(\'.jw-dock, .jw-controlbar\').show();			} else {				playerElem.find(\'.jw-icon-share, .jw-shares\').removeClass(\'jw-open-forced\');				playerElem.find(\'.jw-dock, .jw-controlbar\').removeAttr(\'style\');			}		});		jwplayerInstance.on(\'levelsChanged\', function(e) {			/* track a change in quality when HQ/SQ is clicked */			var playerQuality = e.currentQuality == 1 ? \'hq\' : \'sq\';			$.cookie(qualityCookieName, playerQuality, { expires: 365, path: \'/\' });			/* when switching to SQ we have to track explicitly, because the JW "onPlay" 1st tracking point was already fired */			if (playerQuality == \'sq\') {				doNmTracking({					\'sp.site\': 1001,					\'sp.videoquality\': \'sq\'				});			}		});		/* callback for errors, to display user-friendly info */		jwplayerInstance.on(\'error setupError\', function(e) {			$(\'#\' + this.id).hide();			var hasGeoBlocking = $(\'.video-player\').hasClass(\'video-player-geoblocking\');			var errorText = hasGeoBlocking				? unescape(\'Dieses Video ist leider an Ihrem Standort nicht verf%FCgbar.\')				: unescape(\'Leider steht f%FCr dieses Video keine auf Ihrem Ger%E4t abspielbare Datei zur Verf%FCgung.\');			wrapperElem.find(\'.video-player-error\')				.html(errorText)				.show();		});		/* click handler for video end screen "replay" button (handler on parent, watching for end screen selector, */		/* cause in case of video component player, where end screen is loaded asynchronously) */		wrapperElem.on(\'click touchstart\', \'.video-end-screen .watch-video-again\', function(e) {			e.preventDefault();			spToggleEndScreen(config.wrapperElemId);			spRestartVideo(config.wrapperElemId);		});	}}');
// now, we put the script in a new script element in the DOM
var script = document.createElement('script'); // create the script element
script.innerHTML = scriptCode.join('\n'); // add the script code to it
scriptCode.length = 0; // recover the memory we used to build the script
// this is sort of hard to read, because it's doing 2 things:
// 1. finds the first <head> tag on the page
// 2. adds the new script just before the </head> tag
document.getElementsByTagName('head') [0].appendChild(script);