Shows the YouTube upload date & view count at the top of the page to save scrolling every time.
// ==UserScript==
// @name YouTube Date & View Count at Top
// @namespace http://tampermonkey.net/
// @license MIT
// @version 2.9
// @description Shows the YouTube upload date & view count at the top of the page to save scrolling every time.
// @match https://www.youtube.com/watch*
// @grant none
// ==/UserScript==
(function () {
'use strict';
let lastVideoId = '';
let lastInfoText = '';
function getVideoId() {
const params = new URLSearchParams(window.location.search);
return params.get('v');
}
function waitForUpdatedInfo(videoId) {
console.log('[DBG] Waiting for updated info for videoId:', videoId);
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
clearInterval(checkInterval);
console.warn('[WARN] Timeout: #info element not found after 10 seconds for videoId:', videoId);
reject(new Error('Timeout waiting for #info'));
}, 10000); // 10 seconds timeout
const checkInterval = setInterval(() => {
const infoEl = document.querySelector('#info-container #info');
if (!infoEl) return;
const text = infoEl.textContent.trim();
if (text && text !== lastInfoText) {
console.log('[DBG] Fresh info text:', text);
clearInterval(checkInterval);
clearTimeout(timeout);
resolve(infoEl);
}
}, 500); // poll every 500ms until info appears
});
}
async function insertInfoBox() {
const videoId = getVideoId();
if (!videoId || videoId === lastVideoId) return;
console.log('[DBG] Detected new videoId:', videoId);
lastVideoId = videoId;
try {
const infoEl = await waitForUpdatedInfo(videoId);
lastInfoText = infoEl.textContent.trim();
// Extract only the first two spans (views + date)
const spans = infoEl.querySelectorAll('span');
let viewText = spans[0]?.textContent.trim() || '';
let dateText = spans[2]?.textContent.trim() || '';
console.log('[DBG] Extracted short form:', { viewText, dateText });
// Get long-form tooltip data (exact count & upload date)
let tooltipText = '';
const tooltipEl = document.querySelector(
'tp-yt-paper-tooltip.style-scope.ytd-watch-info-text #tooltip'
);
if (tooltipEl && tooltipEl.textContent.trim()) {
const fullTooltip = tooltipEl.textContent.trim();
console.log('[DBG] Full tooltip text:', fullTooltip);
// Split by • and take only first two parts (views + date)
const parts = fullTooltip.split('•').map(part => part.trim());
if (parts.length >= 2) {
tooltipText = `${parts[0]} • ${parts[1]}`;
} else {
tooltipText = fullTooltip; // fallback
}
console.log('[DBG] Trimmed tooltip text:', tooltipText);
} else {
console.warn('[DBG] Tooltip element not found, falling back.');
tooltipText = `${viewText} • ${dateText}`;
}
const logoContainer = document.querySelector('ytd-masthead #start');
const mastheadContainer = document.querySelector('ytd-masthead #container');
if (!logoContainer || !mastheadContainer) {
console.warn('[DBG] Could not find masthead or logo container');
return;
}
// Measure logo width for placement
const logoRect = logoContainer.getBoundingClientRect();
const shiftRight = 20; // adjust this value to move further right
// Remove old box
const oldBox = document.getElementById('yt-date-view-overlay');
if (oldBox) oldBox.remove();
// Create wrapper with tooltip
const wrapper = document.createElement('div');
wrapper.id = 'yt-date-view-overlay';
wrapper.style = `
position: absolute;
left: ${logoRect.right + shiftRight}px;
top: 50%;
transform: translateY(-50%);
font-size: 12px;
font-weight: 500;
color: var(--yt-spec-text-primary);
cursor: pointer;
z-index: 1000;
pointer-events: auto;
`;
const infoBox = document.createElement('div');
infoBox.textContent = `${viewText} • ${dateText}`;
wrapper.appendChild(infoBox);
const tooltip = document.createElement('div');
tooltip.textContent = tooltipText || 'No detailed data found';
tooltip.style = `
visibility: hidden;
background-color: #333;
color: #fff;
text-align: center;
border-radius: 4px;
padding: 6px;
position: absolute;
top: 120%;
left: 50%;
transform: translateX(-50%);
opacity: 0;
transition: opacity 0.3s;
white-space: nowrap;
`;
wrapper.appendChild(tooltip);
wrapper.addEventListener('mouseenter', () => {
tooltip.style.visibility = 'visible';
tooltip.style.opacity = '1';
});
wrapper.addEventListener('mouseleave', () => {
tooltip.style.visibility = 'hidden';
tooltip.style.opacity = '0';
});
// Append wrapper
mastheadContainer.appendChild(wrapper);
console.log('[DBG] Added info box with adjusted right shift:', infoBox.textContent);
} catch (err) {
console.error('[ERR] insertInfoBox failed:', err.message);
}
}
function listenForNavigation() {
window.addEventListener('yt-navigate-finish', () => {
console.log('[DBG] Detected YouTube navigation (yt-navigate-finish)');
insertInfoBox();
});
}
listenForNavigation();
insertInfoBox(); // Run once on initial load
})();