Size
4.0 KB
Version
1.0.1
Created
Jan 22, 2026
Updated
12 days ago
1// ==UserScript==
2// @name UpToDate Animal Timer
3// @description 2-minute countdown timer with running animals
4// @version 1.0.1
5// @match https://*.uptodate.com/*
6// @icon https://www.uptodate.com/app/utd-menu/utd-icon-redesign.png
7// @grant GM.getValue
8// @grant GM.setValue
9// ==/UserScript==
10(function() {
11 'use strict';
12
13 // Animal sequence
14 const animals = ['🦓 Zebra', '🦁 Lion', '🦛 Hippo', '🦒 Giraffe'];
15 let currentAnimalIndex = 0;
16
17 // Create timer container
18 function createTimer() {
19 const timerContainer = document.createElement('div');
20 timerContainer.id = 'animal-timer-container';
21 timerContainer.style.cssText = `
22 position: fixed;
23 top: 20px;
24 right: 20px;
25 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
26 color: white;
27 padding: 20px 30px;
28 border-radius: 15px;
29 font-family: Arial, sans-serif;
30 font-size: 32px;
31 font-weight: bold;
32 z-index: 10000;
33 box-shadow: 0 8px 20px rgba(0,0,0,0.3);
34 min-width: 200px;
35 text-align: center;
36 `;
37
38 const timeDisplay = document.createElement('div');
39 timeDisplay.id = 'time-display';
40 timeDisplay.textContent = '02:00';
41
42 timerContainer.appendChild(timeDisplay);
43 document.body.appendChild(timerContainer);
44
45 return timeDisplay;
46 }
47
48 // Create running animal animation
49 function showRunningAnimal() {
50 const animalName = animals[currentAnimalIndex];
51 console.log('Showing animal:', animalName);
52
53 const animalElement = document.createElement('div');
54 animalElement.style.cssText = `
55 position: fixed;
56 bottom: 100px;
57 left: -200px;
58 font-size: 80px;
59 z-index: 10001;
60 animation: runAcrossScreen 4s linear;
61 `;
62 animalElement.textContent = animalName;
63
64 // Add animation keyframes
65 if (!document.getElementById('animal-animation-style')) {
66 const style = document.createElement('style');
67 style.id = 'animal-animation-style';
68 style.textContent = `
69 @keyframes runAcrossScreen {
70 0% {
71 left: -200px;
72 }
73 100% {
74 left: 100%;
75 }
76 }
77 `;
78 document.head.appendChild(style);
79 }
80
81 document.body.appendChild(animalElement);
82
83 // Remove animal after animation
84 setTimeout(() => {
85 animalElement.remove();
86 }, 4000);
87
88 // Move to next animal in sequence
89 currentAnimalIndex = (currentAnimalIndex + 1) % animals.length;
90 }
91
92 // Start timer
93 async function startTimer() {
94 const timeDisplay = createTimer();
95
96 // Get saved animal index
97 const savedIndex = await GM.getValue('currentAnimalIndex', 0);
98 currentAnimalIndex = savedIndex;
99
100 let totalSeconds = 120; // 2 minutes
101
102 const interval = setInterval(async () => {
103 totalSeconds--;
104
105 const minutes = Math.floor(totalSeconds / 60);
106 const seconds = totalSeconds % 60;
107 timeDisplay.textContent = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
108
109 if (totalSeconds <= 0) {
110 // Show animal
111 showRunningAnimal();
112
113 // Save current animal index
114 await GM.setValue('currentAnimalIndex', currentAnimalIndex);
115
116 // Reset timer
117 totalSeconds = 120;
118 console.log('Timer reset! Next animal will be:', animals[currentAnimalIndex]);
119 }
120 }, 1000);
121 }
122
123 // Initialize when page loads
124 if (document.body) {
125 startTimer();
126 } else {
127 window.addEventListener('DOMContentLoaded', startTimer);
128 }
129
130})();