Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (function () {
- const selectors = {
- playlists: '.yt-lockup-view-model-wiz__content-image:not(.unplaylisted)',
- badge: '.yt-thumbnail-overlay-badge-view-model-wiz',
- badgeText: '.badge-shape-wiz__text',
- ancestor: '.ytd-rich-item-renderer.lockup',
- title: '.yt-lockup-metadata-view-model-wiz__title',
- subtitle: '.yt-lockup-metadata-view-model-wiz__metadata',
- thumbnail: '.yt-thumbnail-view-model__image img',
- };
- const classNames = {
- unplaylisted: 'unplaylisted',
- unplaylistedCSS: 'unplaylisted-styles',
- thumbnailLoaded: 'yt-core-image--loaded',
- };
- function removeStackedThumbnails () {
- const style = document.createElement('style');
- style.innerHTML = `div[class^='collections-stack'] { display: none; }`;
- style.className = classNames.unplaylistedCSS,
- document.head.appendChild(style);
- }
- function unPlaylist (playListElement) {
- const playlists = document.querySelectorAll(selectors.playlists);
- if (!playListElement && playlists.length === 0) return;
- if (playListElement) {
- updatePlaylist(playListElement);
- } else {
- playlists.forEach(function (playlist) {
- updatePlaylist(playlist);
- });
- }
- }
- function updatePlaylist(playlist) {
- if (!playlist) throw new Error('Error: no playlist passed to this function!');
- const oldUrl = playlist.getAttribute('href'),
- newUrl = oldUrl.split('&')[0],
- badge = playlist.querySelector(selectors.badge),
- ancestor = playlist.closest(selectors.ancestor),
- badgeText = playlist.querySelector(selectors.badgeText).innerText,
- videoTitleLink = playlist.nextElementSibling.querySelector(selectors.title),
- videoTitle = videoTitleLink.lastChild,
- oldVideoTitle = videoTitle.innerText,
- newVideoTitle = oldVideoTitle.replace('Mix - ', ''),
- videoSubtitle = playlist.nextElementSibling.querySelector(selectors.subtitle),
- videoThumbnail = playlist.querySelector(selectors.thumbnail);
- // Remove playlist query param from video links.
- playlist.setAttribute('href', newUrl);
- videoTitleLink.setAttribute('href', newUrl);
- // The script is executed after the playlist's thumbnail's "src" attribute
- // has been populated. However, the class required to actually display it
- // has not been added yet, so we add it here.
- videoThumbnail.classList.add(classNames.thumbnailLoaded);
- // Remove most of the mix-exclusive design (badge and text).
- badge.remove();
- if (videoTitle) videoTitle.innerHTML = newVideoTitle;
- if (videoSubtitle) videoSubtitle.remove();
- playlist.classList.add(classNames.unplaylisted);
- // Remove all event listeners from the video which would send you to the
- // playlist despite the link href not having the playlist query params.
- const newAncestor = ancestor.cloneNode(true);
- ancestor.parentNode.replaceChild(newAncestor, ancestor);
- }
- // Dynamically remove playlists as they appear in the DOM.
- // @note: There may be a better way to do this than listening for the entire
- // <body> element. However I don't feel like doing that rn. :)
- const pageObserver = new MutationObserver(function (mutations) {
- mutations.forEach(function (mutation) {
- mutation.addedNodes.forEach(function (node) {
- if (node.nodeType !== Node.ELEMENT_NODE) return;
- const matchingElements = node.querySelectorAll(selectors.playlists);
- if (matchingElements.length === 0) return;
- matchingElements.forEach(function (elem) {
- // Wait for the image to load before running the unPlaylist function.
- const videoThumbnail = elem.querySelector(selectors.thumbnail);
- const thumbnailObserver = new MutationObserver(function (thumbnailMutations) {
- thumbnailMutations.forEach(function (thumbnailMutation) {
- unPlaylist(elem);
- thumbnailObserver.disconnect();
- });
- });
- thumbnailObserver.observe(videoThumbnail, { attributeFilter: ['src'] });
- });
- });
- });
- });
- pageObserver.observe(document.body, { childList: true, subtree: true });
- removeStackedThumbnails();
- unPlaylist();
- }());
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement