ニコニ広告による動画への装飾を削除
Od
// ==UserScript==
// @name Nico User Ads Hider
// @namespace http://userscripts.org/users/121129
// @description ニコニ広告による動画への装飾を削除
// @match http://www.nicovideo.jp/*
// @match http://search.nicovideo.jp/*
// @version 5
// @grant none
// @run-at document-idle
// ==/UserScript==
;(function() {
'use strict'
var handler = function(handleForEachMutation) {
return function(mutations) {
for (var m of mutations) handleForEachMutation(m)
}
}
var containsAllClass = function(elem, classTokens) {
return classTokens.every(function(t) {
return elem.classList.contains(t)
})
}
var nicovideoObj = function() {
var isUadLevelClassAdded = function(mutation) {
return mutation.attributeName === 'class'
&& mutation.target.className.includes('uadlevel')
}
var restoreIfUadLevelClassAdded = function(mutation) {
if (isUadLevelClassAdded(mutation)) {
mutation.target.className = mutation.oldValue
}
}
var isBalloonShown = function(mutation) {
var e = mutation.target
return mutation.attributeName === 'style'
&& e.style.display !== 'none'
&& containsAllClass(e, ['balloon', 'recent', 'active'])
}
var hideIfBalloonShown = function(mutation) {
if (isBalloonShown(mutation)) mutation.target.style.display = 'none'
}
var isListRankingPage = function() {
var p = location.pathname
return p.startsWith('/ranking/') && p !== '/ranking/'
}
var isVideoCommentsShown = function(elem) {
return elem.hasAttribute('data-video-comments')
&& elem.style.display !== 'none'
}
var hideIfVideoCommentsShown = function(mutation) {
var e = mutation.target
if (isVideoCommentsShown(e)) e.style.display = 'none'
}
var fs = [restoreIfUadLevelClassAdded, hideIfBalloonShown]
if (isListRankingPage()) fs.push(hideIfVideoCommentsShown)
return {
handler: handler(function(mutation) {
for (var f of fs) f(mutation)
}),
options: {
attributes: true,
subtree: true,
attributeOldValue: true,
attributeFilter: ['class', 'style'],
},
}
}
var searchObj = function() {
var isClassMutated = function(mutation) {
return mutation.type === 'attributes'
&& mutation.attributeName === 'class'
}
var removeClassIfContains = function(classToken) {
return function(elem) {
var l = elem.classList
if (l.contains(classToken)) l.remove(classToken)
}
}
var removeGoldAdIfContains = removeClassIfContains('gold-ad')
var removeSilverAdIfContains = removeClassIfContains('silver-ad')
var isTooltipShown = function(mutation) {
return mutation.type === 'childList'
&& mutation.addedNodes.length === 1
&& Boolean(mutation.addedNodes[0].classList)
&& containsAllClass(mutation.addedNodes[0]
, ['tooltip', 'fade', 'top', 'in'])
}
var hideTooltip = function(mutation) {
mutation.addedNodes[0].style.display = 'none'
}
return {
handler: handler(function(mutation) {
if (isClassMutated(mutation)) {
removeGoldAdIfContains(mutation.target)
removeSilverAdIfContains(mutation.target)
} else if (isTooltipShown(mutation)) {
hideTooltip(mutation)
}
}),
options: {
attributes: true,
childList: true,
subtree: true,
attributeFilter: ['class'],
},
}
}
var diffBy = function(location) {
switch (location.hostname) {
case 'www.nicovideo.jp': return nicovideoObj()
case 'search.nicovideo.jp': return searchObj()
default: throw new Error(location.hostname)
}
}
var observe = function(obj) {
new MutationObserver(obj.handler).observe(document.body, obj.options)
}
observe(diffBy(location))
})()