Skip to content
TORNLIFE More

Online Status to Text for Screen Readers

Started by PurpleFire [2868362] Committee on in Tools & Userscripts.

4 replies · 101 views · thread synced · 3 days ago · View on torn.com
About this thread

Posts archived: 5 / 5 posts (100%) · the total is Torn's reply count + the opening post at the last fetch

Counted by TornLife from the archived posts.

Archived posts
5
Discussion span
→
People posting
3
Likes on archived posts
10
Posts by staff, officers and moderators
3
Authority score
60 / 100
Historical score
41 / 100
Story score
35 / 100
Engagement score
53 / 100

Mentioned in this thread

Swervelord [3637232] ×2

PurpleFire [2868362] Committee Committee

Replace Torn profile status dot with text and announce status for screen readers
 
Mainly for screen reader users, since we have no way of getting the online/offline/idle status of players.
Color blind users might find it helpful since it replaces the colors with text.
No API keys needed.
 
If using a screen reader, the status is announced on page load, online/offline/idle.

The text is also displayed to the left of the player's name and ID at the top of their profile page.
Using NVDA, I use "4" or "H" to navigate to the top of the profile then up arrow to hear the status.
 
Install - Online Status to Text
 
Thanks Swervelord

Mentions: Swervelord [3637232]

PurpleFire [2868362] Committee Committee

I managed to add the ability to change rate and volume of speech output without breaking it XD. Yes, I cheated with Claude.

code // ==UserScript== // @name Online Status to Text // @namespace https://swervelord.dev // @version 1.0.0 // @description Replaces Torn profile online status icons with text and announces the status. // @author swervelord [3637232] // @license MIT // @match https://www.torn.com/profiles.php?XID* // @grant none // ==/UserScript== (function () { 'use strict'; var SPEECH_RATE = 1.3; // 1.0 = normal speed, 2.5 = faster, 0.5 = slower var SPEECH_VOLUME = 0.7; // 1.0 = full volume, 0.7 = quieter const STATUS_CLASSES = [ { className: 'user-status-16-Online', label: 'Online' }, { className: 'user-status-16-Away', label: 'Idle' }, { className: 'user-status-16-Offline', label: 'Offline' }, ]; let lastAnnouncedProfileStatus = ''; function addTextStatusStyles() { if (document.getElementById('online-status-to-text-styles')) { return; } const style.id = 'online-status-to-text-styles'; style.textContent = ` ul.basic-info li[data-online-status-to-text="true"] { background: none !important; background-image: none !important; color: #ffffff !important; display: inline-block !important; float: left !important; font-size: 13px !important; font-weight: 700 !important; height: auto !important; line-height: 16px !important; margin: 0 8px 0 0 !important; min-width: 0 !important; overflow: visible !important; padding: 0 !important; position: static !important; text-indent: 0 !important; text-transform: none !important; white-space: nowrap !important; width: auto !important; } `; document.head.appendChild(style); } function getProfileId(statusIcon) { const match = statusIcon.id && statusIcon.id.match(/profile-(d+)/); return match ? match[1] : location.search; } function getStatus(statusIcon) { return STATUS_CLASSES.find((status) => statusIcon.classList.contains(status.className)); } function speakStatus(label) { if (!('speechSynthesis' in window) || !('SpeechSynthesisUtterance' in window)) { return; } var utterance = new SpeechSynthesisUtterance(label); utterance.rate = SPEECH_RATE; utterance.volume = SPEECH_VOLUME; window.speechSynthesis.cancel(); window.speechSynthesis.speak(utterance); } function replaceStatusIcon(statusIcon) { const status = getStatus(statusIcon); if (!status) { return; } if (statusIcon.textContent.trim() !== status.label) { statusIcon.textContent = status.label; } if (statusIcon.getAttribute('aria-label') !== status.label) { statusIcon.setAttribute('aria-label', status.label); } if (statusIcon.getAttribute('title') !== status.label) { statusIcon.setAttribute('title', status.label); } if (statusIcon.dataset.onlineStatusToText !== 'true') { statusIcon.dataset.onlineStatusToText = 'true'; statusIcon.style.backgroundImage = 'none'; statusIcon.style.width = 'auto'; statusIcon.style.height = 'auto'; statusIcon.style.minWidth = '0'; statusIcon.style.fontWeight = '700'; statusIcon.style.fontSize = '13px'; statusIcon.style.lineHeight = '16px'; statusIcon.style.textIndent = '0'; statusIcon.style.overflow = 'visible'; statusIcon.style.color = '#ffffff'; } const profileStatusKey = `${getProfileId(statusIcon)}:${status.label}`; if (profileStatusKey !== lastAnnouncedProfileStatus) { lastAnnouncedProfileStatus = profileStatusKey; speakStatus(status.label); } } function updateProfileStatus() { addTextStatusStyles(); document .querySelectorAll('ul.basic-info li[class*="user-status-16-"]') .forEach(replaceStatusIcon); } updateProfileStatus(); new MutationObserver(updateProfileStatus).observe(document.documentElement, { childList: true, subtree: true, }); })();

Mentions: Swervelord [3637232]

Stylite [3270760]

(<)details> (<)summary>Click to expand<(/)summary>

This is the hidden text that appears when you click the summary.

<(/)details>

 

just switch to source code when using these commands, and delete the parentheses to make the code valid