Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name X.com Media Filter
- // @namespace http://tampermonkey.net/
- // @version 1.0
- // @description Filter X.com media tab to show only images or only videos
- // @author You
- // @match https://x.com/*/media
- // @match https://twitter.com/*/media
- // @grant none
- // ==/UserScript==
- (function() {
- 'use strict';
- // Create filter buttons
- function createFilterButtons() {
- const filterContainer = document.createElement('div');
- filterContainer.id = 'media-filter-controls';
- filterContainer.style.cssText = `
- position: fixed;
- top: 20px;
- right: 20px;
- z-index: 9999;
- background: rgba(0, 0, 0, 0.8);
- border-radius: 12px;
- padding: 12px;
- display: flex;
- gap: 8px;
- backdrop-filter: blur(10px);
- `;
- const buttonStyle = `
- padding: 8px 16px;
- border: none;
- border-radius: 8px;
- background: #1d9bf0;
- color: white;
- cursor: pointer;
- font-size: 14px;
- font-weight: 600;
- transition: all 0.2s;
- `;
- const activeButtonStyle = `
- background: #1a8cd8;
- transform: scale(0.95);
- `;
- // All button
- const allBtn = document.createElement('button');
- allBtn.textContent = 'All';
- allBtn.style.cssText = buttonStyle;
- allBtn.onclick = () => filterMedia('all');
- // Images only button
- const imagesBtn = document.createElement('button');
- imagesBtn.textContent = 'Images';
- imagesBtn.style.cssText = buttonStyle;
- imagesBtn.onclick = () => filterMedia('images');
- // Videos only button
- const videosBtn = document.createElement('button');
- videosBtn.textContent = 'Videos';
- videosBtn.style.cssText = buttonStyle;
- videosBtn.onclick = () => filterMedia('videos');
- filterContainer.appendChild(allBtn);
- filterContainer.appendChild(imagesBtn);
- filterContainer.appendChild(videosBtn);
- document.body.appendChild(filterContainer);
- return { allBtn, imagesBtn, videosBtn };
- }
- // Filter media based on type
- function filterMedia(type) {
- // Update button states
- const buttons = document.querySelectorAll('#media-filter-controls button');
- buttons.forEach(btn => {
- btn.style.background = '#1d9bf0';
- btn.style.transform = 'none';
- });
- const activeBtn = document.querySelector(`#media-filter-controls button:nth-child(${
- type === 'all' ? '1' : type === 'images' ? '2' : '3'
- })`);
- if (activeBtn) {
- activeBtn.style.background = '#1a8cd8';
- activeBtn.style.transform = 'scale(0.95)';
- }
- // Find all media items - multiple selectors for different X.com layouts
- const mediaSelectors = [
- '[data-testid="cellInnerDiv"]',
- '[role="gridcell"]',
- 'div[style*="padding-bottom"]', // Common for media grid items
- 'a[href*="/photo/"]',
- 'a[href*="/video/"]'
- ];
- let mediaItems = [];
- for (const selector of mediaSelectors) {
- const items = document.querySelectorAll(selector);
- if (items.length > 0) {
- mediaItems = Array.from(items);
- break;
- }
- }
- // If no items found with standard selectors, try broader approach
- if (mediaItems.length === 0) {
- // Look for containers that likely contain media
- const possibleContainers = document.querySelectorAll('div[style*="padding-bottom"], div[data-testid], a[href*="/status/"]');
- mediaItems = Array.from(possibleContainers).filter(item => {
- return item.querySelector('img, video') ||
- item.innerHTML.includes('video') ||
- item.innerHTML.includes('photo');
- });
- }
- mediaItems.forEach(item => {
- const isVideo = isVideoItem(item);
- const isImage = isImageItem(item);
- switch(type) {
- case 'all':
- item.style.display = '';
- break;
- case 'images':
- item.style.display = isImage && !isVideo ? '' : 'none';
- break;
- case 'videos':
- item.style.display = isVideo ? '' : 'none';
- break;
- }
- });
- console.log(`Filtered ${mediaItems.length} items for type: ${type}`);
- }
- // Check if item contains video
- function isVideoItem(item) {
- // Multiple ways to detect videos
- return item.querySelector('video') ||
- item.querySelector('[data-testid*="video"]') ||
- item.querySelector('.PlayableMedia-player') ||
- item.innerHTML.includes('video') ||
- item.href?.includes('/video/') ||
- item.querySelector('svg[aria-label*="Play"]') ||
- item.querySelector('[aria-label*="video"]') ||
- item.querySelector('[role="button"][aria-label*="Play"]');
- }
- // Check if item contains image
- function isImageItem(item) {
- // Multiple ways to detect images
- return item.querySelector('img:not([alt*="avatar"]):not([alt*="profile"])') ||
- item.href?.includes('/photo/') ||
- item.querySelector('[data-testid*="image"]') ||
- item.querySelector('[aria-label*="image"]');
- }
- // Initialize when page loads
- function init() {
- // Wait for page to load
- setTimeout(() => {
- if (window.location.pathname.includes('/media')) {
- const buttons = createFilterButtons();
- console.log('X.com Media Filter initialized');
- // Re-run filter when new content loads (infinite scroll)
- const observer = new MutationObserver(() => {
- // Debounce to avoid excessive calls
- clearTimeout(window.mediaFilterTimeout);
- window.mediaFilterTimeout = setTimeout(() => {
- const activeFilter = getActiveFilter();
- if (activeFilter !== 'all') {
- filterMedia(activeFilter);
- }
- }, 500);
- });
- observer.observe(document.body, {
- childList: true,
- subtree: true
- });
- }
- }, 2000);
- }
- // Get currently active filter
- function getActiveFilter() {
- const buttons = document.querySelectorAll('#media-filter-controls button');
- for (let i = 0; i < buttons.length; i++) {
- if (buttons[i].style.background === 'rgb(26, 140, 216)') {
- return ['all', 'images', 'videos'][i];
- }
- }
- return 'all';
- }
- // Handle navigation changes (SPA)
- let currentUrl = window.location.href;
- const checkUrlChange = () => {
- if (window.location.href !== currentUrl) {
- currentUrl = window.location.href;
- // Remove old controls
- const oldControls = document.getElementById('media-filter-controls');
- if (oldControls) oldControls.remove();
- // Reinitialize if on media page
- init();
- }
- };
- // Check for URL changes every second
- setInterval(checkUrlChange, 1000);
- // Initial load
- init();
- })();
Add Comment
Please, Sign In to add comment