PageSourceSearch

https://www.whatismyscreenresolution.org/assets/js/screentest.js?v=589349

js whatismyscreenresolution.org collected 2026-10-04 05:34:25 UTC 9,637 bytes, 187 lines download raw bytes

1/* Fullscreen screen tests — dead pixel and colour.
2   One engine, driven by the slide set declared on the page container. */
3(function () {
4  'use strict';
5
6  var stage = document.getElementById('test-stage');
7  if (!stage) return;
8
9  var mode = stage.dataset.mode || 'pixel';
10
11  var SETS = {
12    pixel: [
13      { css: '#000000', name: 'Black',   hint: 'Bright dots here are stuck or hot pixels.' },
14      { css: '#ffffff', name: 'White',   hint: 'Dark dots here are dead pixels or dust.' },
15      { css: '#ff0000', name: 'Red',     hint: 'A pixel missing red shows as cyan-ish.' },
16      { css: '#00ff00', name: 'Green',   hint: 'Green drives most of perceived brightness.' },
17      { css: '#0000ff', name: 'Blue',    hint: 'Blue faults are the hardest to spot — look closely.' },
18      { css: '#00ffff', name: 'Cyan',    hint: 'Green + blue only.' },
19      { css: '#ff00ff', name: 'Magenta', hint: 'Red + blue only.' },
20      { css: '#ffff00', name: 'Yellow',  hint: 'Red + green only.' },
21      { css: '#808080', name: 'Grey 50%', hint: 'Uneven patches here mean poor uniformity.' }
22    ],
23    colour: [
24      { css: 'linear-gradient(90deg,#000,#fff)', name: 'Greyscale ramp', hint: 'Look for banding — steps instead of a smooth fade.' },
25      { css: 'linear-gradient(90deg,#000,#f00)', name: 'Red ramp',   hint: 'Should fade evenly with no blotches.' },
26      { css: 'linear-gradient(90deg,#000,#0f0)', name: 'Green ramp', hint: 'Should fade evenly with no blotches.' },
27      { css: 'linear-gradient(90deg,#000,#00f)', name: 'Blue ramp',  hint: 'Blue banding is the most common.' },
28      { css: 'linear-gradient(90deg,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)', name: 'Hue sweep', hint: 'Every hue should be distinct, none crushed.' },
29      { css: '#ffffff', name: 'White field', hint: 'Check for tint, clouding or brighter edges.' },
30      { css: '#808080', name: 'Grey field',  hint: 'The honest test of panel uniformity.' },
31      { css: '#000000', name: 'Black field', hint: 'Check backlight bleed at the corners.' }
32    ],
33    burnin: [
34      { css: '#ffffff', name: 'Full white', hint: 'A faint ghost of a previous image shows most clearly here.' },
35      { css: '#808080', name: 'Grey 50%',   hint: 'The most revealing field for image retention.' },
36      { css: '#ff0000', name: 'Red',        hint: 'Retention often shows in one channel before the others.' },
37      { css: '#00ff00', name: 'Green',      hint: 'Green wears fastest on OLED — check for dull patches.' },
38      { css: '#0000ff', name: 'Blue',       hint: 'Blue subpixels age quickest of all.' },
39      { css: '#000000', name: 'Black',      hint: 'Look for uneven glow or lingering shapes.' }
40    ],
41    full: [
42      { css: '#ffffff', name: 'White',        hint: 'Step 1 of 10 — dark dots are dead pixels or dust.' },
43      { css: '#000000', name: 'Black',        hint: 'Step 2 — bright dots are stuck pixels; glow at the edges is backlight bleed.' },
44      { css: '#ff0000', name: 'Red',          hint: 'Step 3 — checking the red subpixels.' },
45      { css: '#00ff00', name: 'Green',        hint: 'Step 4 — green carries most of the perceived brightness.' },
46      { css: '#0000ff', name: 'Blue',         hint: 'Step 5 — blue faults are the hardest to spot.' },
47      { css: '#808080', name: 'Grey 50%',     hint: 'Step 6 — the most revealing field for uniformity and retention.' },
48      { css: 'linear-gradient(90deg,#000,#fff)', name: 'Greyscale ramp', hint: 'Step 7 — look for banding: steps instead of a smooth fade.' },
49      { css: 'linear-gradient(90deg,#000,#00f)', name: 'Blue ramp',      hint: 'Step 8 — blue bands most easily of the three channels.' },
50      { css: 'linear-gradient(90deg,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)', name: 'Hue sweep', hint: 'Step 9 — every hue should be distinct.' },
51      { css: '#050505', name: 'Near black',   hint: 'Step 10 — lift the black slightly to expose clouding.' }
52    ],
53    bleed: [
54      { css: '#000000', name: 'Pure black', hint: 'Light leaking at the edges or corners is backlight bleed.' },
55      { css: '#050505', name: 'Near black', hint: 'Slightly lifted black makes clouding easier to see.' },
56      { css: '#101010', name: 'Very dark grey', hint: 'Uneven patches here are clouding rather than bleed.' },
57      { css: '#000000', name: 'Pure black again', hint: 'Move your head: bleed stays put, reflections move.' }
58    ]
59  };
60
61  var slides = SETS[mode] || SETS.pixel;
62  var i = 0;
63
64  var surface = document.getElementById('test-surface');
65  var nameEl  = document.getElementById('test-name');
66  var hintEl  = document.getElementById('test-hint');
67  var posEl   = document.getElementById('test-pos');
68  var hud     = document.getElementById('test-hud');
69
70  function paint() {
71    var s = slides[i];
72    var isGradient = s.css.indexOf('gradient') !== -1;
73    surface.style.background = s.css;
74    // Keep the HUD readable whatever is behind it.
75    surface.classList.toggle('on-light', !isGradient && isLight(s.css));
76    if (nameEl) nameEl.textContent = s.name;
77    if (hintEl) hintEl.textContent = s.hint;
78    if (posEl)  posEl.textContent = (i + 1) + ' / ' + slides.length;
79  }
80
81  function isLight(hex) {
82    if (hex.charAt(0) !== '#') return false;
83    var n = parseInt(hex.slice(1), 16);
84    var r = (n >> 16) & 255, g = (n >> 8) & 255, b = n & 255;
85    return (0.2126 * r + 0.7152 * g + 0.0722 * b) > 140;
86  }
87
88  function go(d) { i = (i + d + slides.length) % slides.length; paint(); }
89
90  // ── burn-in fixer ───────────────────────────────────────────────
91  // Rapidly cycling colours exercises every subpixel, which can shift mild
92  // image retention. It cannot repair a truly burned-in OLED.
93  var fixer = null;
94  var FIX_COLOURS = ['#ff0000', '#00ff00', '#0000ff', '#ffffff', '#000000'];
95  function startFixer() {
96    if (fixer) return;
97    var n = 0;   // local counter; must not shadow the slide index
98    var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
99    var every = reduce ? 400 : 90;
100    fixer = setInterval(function () {
101      surface.style.background = FIX_COLOURS[n++ % FIX_COLOURS.length];
102    }, every);
103    if (nameEl) nameEl.textContent = 'Fixer running';
104    if (hintEl) hintEl.textContent = 'Leave this running for 10-30 minutes. Press Esc to stop.';
105  }
106  function stopFixer() {
107    if (!fixer) return;
108    clearInterval(fixer); fixer = null; paint();
109  }
110  var fixBtn = document.getElementById('test-fixer');
111  if (fixBtn) fixBtn.addEventListener('click', function (ev) {
112    ev.stopPropagation();
113    if (fixer) { stopFixer(); fixBtn.textContent = 'Run burn-in fixer'; }
114    else { enter(); startFixer(); fixBtn.textContent = 'Stop fixer'; }
115  });
116
117  // ── fullscreen ──────────────────────────────────────────────────
118  function enter() {
119    var el = stage;
120    var fn = el.requestFullscreen || el.webkitRequestFullscreen || el.msRequestFullscreen;
121    if (fn) { try { fn.call(el); } catch (e) {} }
122    stage.classList.add('running');
123    document.body.classList.add('test-running');
124    paint();
125  }
126  function exit() {
127    stopFixer();
128    if (document.fullscreenElement || document.webkitFullscreenElement) {
129      var fn = document.exitFullscreen || document.webkitExitFullscreen;
130      if (fn) { try { fn.call(document); } catch (e) {} }
131    }
132    stage.classList.remove('running');
133    document.body.classList.remove('test-running');
134  }
135
136  var startBtn = document.getElementById('test-start');
137  if (startBtn) startBtn.addEventListener('click', enter);
138
139  var exitBtn = document.getElementById('test-exit');
140  if (exitBtn) exitBtn.addEventListener('click', function (ev) { ev.stopPropagation(); exit(); });
141
142  document.querySelectorAll('[data-test-nav]').forEach(function (b) {
143    b.addEventListener('click', function (ev) {
144      ev.stopPropagation();
145      go(b.dataset.testNav === 'prev' ? -1 : 1);
146    });
147  });
148
149  // Click / tap anywhere advances — the whole point is not hunting for a button.
150  if (surface) {
151    surface.addEventListener('click', function () { if (stage.classList.contains('running') && !fixer) go(1); });
152  }
153
154  document.addEventListener('keydown', function (ev) {
155    if (!stage.classList.contains('running')) return;
156    if (ev.key === 'ArrowRight' || ev.key === ' ' || ev.key === 'Enter') { ev.preventDefault(); go(1); }
157    else if (ev.key === 'ArrowLeft') { ev.preventDefault(); go(-1); }
158    else if (ev.key === 'Escape') exit();
159    else if (ev.key === 'h' || ev.key === 'H') hud && hud.classList.toggle('hidden');
160  });
161
162  ['fullscreenchange', 'webkitfullscreenchange'].forEach(function (evt) {
163    document.addEventListener(evt, function () {
164      if (!document.fullscreenElement && !document.webkitFullscreenElement) {
165        stage.classList.remove('running');
166        document.body.classList.remove('test-running');
167      }
168    });
169  });
170
171  // Build the swatch strip on the intro card so the page is not empty before you start.
172  var strip = document.getElementById('test-strip');
173  if (strip) {
174    strip.innerHTML = slides.map(function (s, n) {
175      return '<button type="button" class="sw" data-i="' + n + '" title="' + s.name +
176             '" style="background:' + s.css + '"><span>' + s.name + '</span></button>';
177    }).join('');
178    strip.addEventListener('click', function (ev) {
179      var b = ev.target.closest('.sw');
180      if (!b) return;
181      i = parseInt(b.dataset.i, 10) || 0;
182      enter();
183    });
184  }
185
186  paint();
187})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.