Last active
May 3, 2022 01:22
-
-
Save RealityRipple/f093fff4431847ebf5f26fdfe3ad4315 to your computer and use it in GitHub Desktop.
Track Display for StreamElements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<script> | |
var userID = 'your_account'; /* streamelements account ID */ | |
var userName = 'your_channel'; /* broadcaster name (to negate requester matching your name) - use '' to show your own name */ | |
var index = 1; /* queue index, starting from 1 for the next song and counting up */ | |
var fadePad = 32; /* left and right margin */ | |
var scrollRate = 20; /* lower is faster */ | |
var interval = 2; /* update time in seconds */ | |
var fadeTime = 0.5; /* fade speed in seconds */ | |
var normPad = 8; /* label padding. must equal #label's left and right padding value */ | |
var scrollPad = 6; /* padding between label and track name when scrolling */ | |
var label = 'Next Up:'; /* use '' for no label */ | |
var fitScroll = false; /* set to true to scroll text that fits */ | |
var fitScrollRate = 15; /* lower is faster */ | |
var trackDisp = '%DISP_CHANNEL%%DISP_TITLE%%DISP_USER%'; /* display of below variables */ | |
var channelDisp = '%CHANNEL% - '; /* channel name display (with text shown when a channel is provided, empty if no channel or live learn) */ | |
var titleDisp = '%TITLE%'; /* title display */ | |
var userDisp = ' for %USER%'; /* requester username display (with text shown when a song is by request, empty if no requester) */ | |
var emptyOpenDisp = 'The queue is empty! You can add a song with the !sr command.' /* message to display when the queue does not have enough songs to reach this index and song requests are open */ | |
var emptyClosedDisp = 'None! Last Song'; /* message to display when the queue does not have enough songs to reach this index and song requests are closed */ | |
/* | |
* Example Track Displays: | |
* | |
* trackDisp = '%DISP_CHANNEL%%DISP_TITLE%%DISP_USER%' | |
* channelDisp = '%CHANNEL% - ' | |
* titleDisp = '%TITLE%' | |
* userDisp = 'for %USER' | |
* => Pink Floyd - Wish You Were Here for RealityRipple | |
* | |
* trackDisp = '%DISP_USER%%DISP_TITLE%%DISP_CHANNEL%' | |
* channelDisp = ' by %CHANNEL%' | |
* titleDisp = '%TITLE%' | |
* userDisp = '%USER%\'s Request: ' | |
* => RealityRipple's Request: Wish You Were Here by Pink Floyd | |
* | |
* trackDisp = '%DISP_TITLE%' | |
* channelDisp = ''; | |
* titleDisp = '%TITLE%'; | |
* userDisp = ''; | |
* => Wish You Were Here | |
*/ | |
var trackStyle = { | |
'style1': {title: 'Stairway to Heaven'}, | |
'style2': {channel: 'Topic - Led Zeppelin'}, | |
'style3': {user: 'RealityRipple'} | |
}; | |
</script> | |
<style> | |
.text | |
{ | |
font-size: 32px; | |
line-height: 36px; /* adjust as needed for the text-shadow */ | |
color: #FFFFFF; | |
text-shadow: 2px 2px 3px #000000; | |
/* font-family: 'Comic Sans MS'; */ | |
} | |
.style1 | |
{ | |
color: #FFFF00; | |
} | |
.style2 | |
{ | |
font-style: italic; | |
} | |
.style3 | |
{ | |
color: #008000; | |
} | |
</style> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>Track Display for StreamElements</title> | |
<style> | |
:root | |
{ | |
--pos: 0px; | |
} | |
body | |
{ | |
text-align: left; | |
margin: 0; | |
} | |
table | |
{ | |
border: 0; | |
visibility: hidden; | |
position: fixed; | |
opacity: 0; | |
} | |
#label | |
{ | |
margin: 0; | |
background-color: transparent; | |
padding: 2px 8px 8px; | |
white-space: nowrap; | |
} | |
#trackBox | |
{ | |
width: 100%; | |
overflow: hidden; | |
position: relative; | |
} | |
.track | |
{ | |
margin: 0; | |
top: 0; | |
display: none; | |
position: absolute; | |
background-color: transparent; | |
padding: 2px 0; | |
white-space: nowrap; | |
animation-name: fullWidth; | |
animation-timing-function: ease-in-out; | |
animation-direction: alternate; | |
animation-iteration-count: infinite; | |
visibility: hidden; | |
opacity: 0; | |
} | |
@keyframes fullWidth | |
{ | |
from | |
{ | |
transform: translate(0, 0); | |
} | |
to | |
{ | |
transform: translate(var(--pos), 0); | |
} | |
} | |
</style> | |
<script> | |
var sTitle = false; | |
var sChannel = false; | |
var sUser = false; | |
var lastW = 0; | |
var lastD = 0; | |
var queueOpen = false; | |
function sleep(ms) | |
{ | |
return new Promise(resolve => setTimeout(resolve, ms)); | |
} | |
function loadUser() | |
{ | |
let p = new Promise((resolve, reject) => | |
{ | |
let x = new XMLHttpRequest(); | |
x.open('GET', 'https://api.streamelements.com/kappa/v2/songrequest/' + userID + '/settings/public', true); | |
x.onreadystatechange = function() | |
{ | |
if(x.readyState !== 4) | |
return; | |
if (x.status !== 200 && x.status !== 0) | |
return; | |
if (x.responseText === '') | |
return; | |
parseRequests(x.responseText); | |
resolve(true); | |
} | |
x.send(null); | |
} | |
); | |
return p; | |
} | |
function parseRequests(sJSON) | |
{ | |
let j = JSON.parse(sJSON); | |
queueOpen = (j.hasOwnProperty('enabled') && j.enabled); | |
} | |
function updateTrack() | |
{ | |
sTitle = false; | |
sChannel = false; | |
let x = new XMLHttpRequest(); | |
x.open('GET', 'https://api.streamelements.com/kappa/v2/songrequest/' + userID +'/queue/public', true); | |
// 'https://api.streamelements.com/kappa/v2/songrequest/' + userID + '/queue/public' | |
x.onreadystatechange = function() | |
{ | |
if(x.readyState !== 4) | |
return; | |
if (x.status !== 200 && x.status !== 0) | |
return; | |
if (x.responseText === '') | |
return; | |
parseTrack(x.responseText); | |
displayTrack(); | |
} | |
x.send(null); | |
} | |
function cleanTitle(s) | |
{ | |
let enclosedEnd = /[([][^()[\]]+ (video|lyrics|remaster)[)\]]$/gi; | |
let enclosedMatch = /[([](video|lyrics|hd|full|720p|1080p|remastered|high quality)[)\]]$/gi; | |
let paddedEnd = /[~-]+[^-~]+(lyrics|video)$/gi; | |
let paddedMatch = /[~-]+ *(lyrics|video|hd|full|720p|1080p|high quality)$/gi; | |
while (s.match(enclosedEnd) || | |
s.match(enclosedMatch) || | |
s.match(paddedEnd) || | |
s.match(paddedMatch)) | |
{ | |
s = s.replace(enclosedEnd, '').trimEnd(); | |
s = s.replace(enclosedMatch, '').trimEnd(); | |
s = s.replace(paddedEnd, '').trimEnd(); | |
s = s.replace(paddedMatch, '').trimEnd(); | |
} | |
let rawEnd = / (lyrics|1080p|720p)$/gi; | |
while (s.match(rawEnd)) | |
s = s.replace(rawEnd, '').trimEnd(); | |
return s; | |
} | |
function cleanChannel(s) | |
{ | |
while (s.slice(-8) === ' - Topic') | |
s = s.slice(0, -8); | |
return s; | |
} | |
function parseTrack(sJSON) | |
{ | |
let j = JSON.parse(sJSON); | |
if (!Array.isArray(j) || j.length < index) | |
{ | |
sTitle = false; | |
if (queueOpen) | |
{ | |
if (emptyOpenDisp !== null && emptyOpenDisp !== '') | |
sTitle = emptyOpenDisp; | |
} | |
else | |
{ | |
if (emptyClosedDisp !== null && emptyClosedDisp !== '') | |
sTitle = emptyClosedDisp; | |
} | |
sChannel = false; | |
sUser = false; | |
return; | |
} | |
sTitle = cleanTitle(j[index - 1].title); | |
if (j.hasOwnProperty('channel')) | |
sChannel = cleanChannel(j[index - 1].channel); | |
else | |
sChannel = false; | |
if (j[index - 1].hasOwnProperty('user') && j[index - 1].user.hasOwnProperty('username') && j[index - 1].user.username.toLowerCase() !== userName.toLowerCase()) | |
sUser = j[index - 1].user.username; | |
else | |
sUser = false; | |
} | |
async function showTable() | |
{ | |
let tbl = document.getElementById('trackTable'); | |
if (tbl.style.visibility === 'visible') | |
return; | |
tbl.style.opacity = '0'; | |
tbl.style.visibility = 'visible'; | |
tbl.style.transitionProperty = 'opacity'; | |
tbl.style.transitionDuration = fadeTime + 's'; | |
tbl.style.opacity = '1'; | |
} | |
async function hideTable() | |
{ | |
let tbl = document.getElementById('trackTable'); | |
if (tbl.style.visibility !== 'visible') | |
return; | |
tbl.style.transitionProperty = 'opacity'; | |
tbl.style.transitionDuration = fadeTime + 's'; | |
tbl.style.opacity = '0'; | |
await sleep(fadeTime * 1000); | |
tbl.style.transitionProperty = ''; | |
tbl.style.transitionDuration = ''; | |
tbl.style.visibility = ''; | |
tbl.style.opacity = ''; | |
} | |
function showFade() | |
{ | |
let tb = document.getElementById('trackBox'); | |
if (!tb.hasAttribute('style')) | |
tb.setAttribute('style', '-webkit-mask-image: linear-gradient(to right, transparent 0, black ' + fadePad + 'px, black calc(100% - ' + fadePad + 'px), transparent 100%);'); | |
} | |
function hideFade() | |
{ | |
let tb = document.getElementById('trackBox'); | |
if (tb.hasAttribute('style')) | |
tb.removeAttribute('style'); | |
} | |
async function showTrack() | |
{ | |
let t = document.getElementById('track'); | |
if (t.style.visibility === 'visible') | |
return; | |
t.style.visibility = 'visible'; | |
t.style.opacity = '0'; | |
t.style.transitionProperty = 'opacity'; | |
t.style.transitionDuration = fadeTime + 's'; | |
t.style.opacity = '1'; | |
await sleep(fadeTime * 1000); | |
t.style.transitionProperty = ''; | |
t.style.transitionDuration = ''; | |
} | |
function styleTrack(measureOnly) | |
{ | |
if (trackStyle === false) | |
return; | |
for (let s in trackStyle) | |
{ | |
if (!measureOnly) | |
{ | |
if (document.getElementById('track').classList.contains(s)) | |
document.getElementById('track').classList.remove(s); | |
} | |
if (document.getElementById('measure').classList.contains(s)) | |
document.getElementById('measure').classList.remove(s); | |
if (trackStyle[s].hasOwnProperty('user')) | |
{ | |
if (sUser === false) | |
continue; | |
if (!sUser.toLowerCase().split(', ').includes(trackStyle[s].user.toLowerCase())) | |
continue; | |
} | |
if (trackStyle[s].hasOwnProperty('title')) | |
{ | |
if (sTitle === false) | |
continue; | |
if (sTitle.toLowerCase() !== trackStyle[s].title.toLowerCase()) | |
continue; | |
} | |
if (trackStyle[s].hasOwnProperty('channel')) | |
{ | |
if (sChannel === false) | |
continue; | |
if (sChannel.toLowerCase() !== trackStyle[s].channel.toLowerCase()) | |
continue; | |
} | |
if (!measureOnly) | |
document.getElementById('track').classList.add(s); | |
document.getElementById('measure').classList.add(s); | |
} | |
} | |
async function hideTrack() | |
{ | |
let t = document.getElementById('track'); | |
if (t.style.display !== 'inline-block') | |
{ | |
t.style.opacity = '0'; | |
t.style.display = 'inline-block'; | |
} | |
else | |
{ | |
t.style.transitionProperty = 'opacity'; | |
t.style.transitionDuration = fadeTime + 's'; | |
t.style.opacity = '0'; | |
await sleep(fadeTime * 1000); | |
t.style.transitionProperty = ''; | |
t.style.transitionDuration = ''; | |
} | |
t.style.opacity = ''; | |
t.style.visibility = ''; | |
t.innerHTML = ''; | |
} | |
function measureTrack(s) | |
{ | |
styleTrack(true); | |
let t = document.getElementById('measure'); | |
t.style.display = 'inline-block'; | |
t.innerHTML = s; | |
let w = t.getBoundingClientRect()['width']; | |
t.style.display = ''; | |
t.innerHTML = ''; | |
return w; | |
} | |
async function displayTrack() | |
{ | |
let t = document.getElementById('track'); | |
let l = document.getElementById('label'); | |
if (sTitle === false) | |
{ | |
lastW = 0; | |
lastD = 0; | |
await hideTable() | |
if (t.hasAttribute('style')) | |
t.removeAttribute('style'); | |
t.innerHTML = ''; | |
return; | |
} | |
let w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
let dTitle = titleDisp.replace('%TITLE%', sTitle); | |
let dChannel = ''; | |
if (channelDisp !== false && sChannel !== false) | |
dChannel = channelDisp.replace('%CHANNEL%', sChannel); | |
let dUser = ''; | |
if (userDisp !== false && sUser !== false) | |
dUser = userDisp.replace('%USER%', sUser); | |
let track = trackDisp.replace('%DISP_TITLE%', dTitle).replace('%DISP_CHANNEL%', dChannel).replace('%DISP_USER%', dUser); | |
let d = measureTrack(track); | |
let h = false; | |
let range = 0; | |
if (l.style.paddingRight === scrollPad + 'px') | |
range = Math.abs((normPad * 2) - (normPad + scrollPad)); | |
if (label !== '') | |
{ | |
if (d + (normPad * 2) > w - range) | |
{ | |
if (l.style.paddingRight !== scrollPad + 'px') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = scrollPad + 'px'; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
else | |
{ | |
if (fitScroll) | |
{ | |
if (l.style.paddingRight !== scrollPad + 'px') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = scrollPad + 'px'; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
else | |
{ | |
if (l.style.paddingRight !== '') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = ''; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
} | |
} | |
if (!h && w === lastW && d === lastD) | |
return; | |
lastW = w; | |
lastD = d; | |
if (!h) | |
await hideTrack(); | |
styleTrack(false); | |
range = 0; | |
if (l.style.paddingRight === scrollPad + 'px') | |
range = Math.abs((normPad * 2) - (normPad + scrollPad)); | |
if (d + (normPad * 2) > w - range) | |
{ | |
d -= w; | |
d += fadePad * 2; | |
let u = Math.ceil(d * scrollRate); | |
if (u < 2000) | |
u = 2000; | |
if (l.style.paddingRight !== scrollPad + 'px' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = scrollPad + 'px'; | |
showFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', '-' + Math.ceil(d) + 'px'); | |
t.style.marginLeft = fadePad + 'px'; | |
t.style.marginRight = fadePad + 'px'; | |
t.style.animationDuration = u + 'ms'; | |
await showTable(); | |
await showTrack(); | |
} | |
else | |
{ | |
if (fitScroll) | |
{ | |
let m = w - d; | |
m -= normPad; | |
let u = Math.ceil(m * fitScrollRate); | |
if (u < 2000) | |
u = 2000; | |
if (l.style.paddingRight !== scrollPad + 'px' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = scrollPad + 'px'; | |
hideFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', Math.ceil(m) + 'px'); | |
t.style.marginLeft = ''; | |
t.style.marginRight = ''; | |
t.style.animationDuration = u + 'ms'; | |
await showTable(); | |
await showTrack(); | |
} | |
else | |
{ | |
if (l.style.paddingRight !== '' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = ''; | |
hideFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', '0px'); | |
t.style.marginLeft = ''; | |
t.style.marginRight = ''; | |
t.style.animationDuration = ''; | |
await showTable(); | |
await showTrack(); | |
} | |
} | |
} | |
function showLabel() | |
{ | |
let l = document.getElementById('label'); | |
if (label === '') | |
{ | |
l.style.paddingLeft = '0px'; | |
l.style.paddingRight = '0px'; | |
l.style.width = '1px'; | |
l.innerHTML = '​'; | |
} | |
else | |
l.innerHTML = label; | |
} | |
</script> | |
</head> | |
<body> | |
<table id="trackTable"> | |
<tr> | |
<td id="label" class="text"></td> | |
<td id="trackBox"><div id="track" class="track text"></div></td> | |
</tr> | |
</table> | |
<div id="measure" class="track text"></div> | |
<script> | |
async function init() | |
{ | |
await loadUser(); | |
window.setInterval(loadUser, interval * 1000); | |
showLabel(); | |
window.setInterval(updateTrack, interval * 1000); | |
updateTrack(); | |
} | |
init(); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<script> | |
var userID = 'your_account'; /* streamelements account ID */ | |
var userName = 'your_channel'; /* broadcaster name (to negate requester matching your name) - use '' to show your own name */ | |
var index = 1; /* queue index, starting from 1 for the next song and counting up */ | |
var fadePad = 32; /* left and right margin */ | |
var scrollRate = 20; /* lower is faster */ | |
var interval = 2; /* update time in seconds */ | |
var fadeTime = 0.5; /* fade speed in seconds */ | |
var normPad = 8; /* label padding. must equal #label's left and right padding value */ | |
var scrollPad = 6; /* padding between label and track name when scrolling */ | |
var label = 'Coming Up:'; /* use '' for no label */ | |
var fitScroll = false; /* set to true to scroll text that fits */ | |
var fitScrollRate = 15; /* lower is faster */ | |
var trackDisp = '%DISP_CHANNEL%%DISP_TITLE%%DISP_USER%'; /* display of below variables */ | |
var channelDisp = '%CHANNEL% - '; /* channel name display (with text shown when a channel is provided, empty if no channel or live learn) */ | |
var titleDisp = '%TITLE%'; /* title display */ | |
var userDisp = ' for %USER%'; /* requester username display (with text shown when a song is by request, empty if no requester) */ | |
var emptyOpenDisp = '' /* message to display when the queue does not have enough songs to reach this index and song requests are open */ | |
var emptyClosedDisp = ''; /* message to display when the queue does not have enough songs to reach this index and song requests are closed */ | |
/* | |
* Example Track Displays: | |
* | |
* trackDisp = '%DISP_CHANNEL%%DISP_TITLE%%DISP_USER%' | |
* channelDisp = '%CHANNEL% - ' | |
* titleDisp = '%TITLE%' | |
* userDisp = 'for %USER' | |
* => Pink Floyd - Wish You Were Here for RealityRipple | |
* | |
* trackDisp = '%DISP_USER%%DISP_TITLE%%DISP_CHANNEL%' | |
* channelDisp = ' by %CHANNEL%' | |
* titleDisp = '%TITLE%' | |
* userDisp = '%USER%\'s Request: ' | |
* => RealityRipple's Request: Wish You Were Here by Pink Floyd | |
* | |
* trackDisp = '%DISP_TITLE%' | |
* channelDisp = ''; | |
* titleDisp = '%TITLE%'; | |
* userDisp = ''; | |
* => Wish You Were Here | |
*/ | |
var trackStyle = { | |
'style1': {title: 'Stairway to Heaven'}, | |
'style2': {channel: 'Topic - Led Zeppelin'}, | |
'style3': {user: 'RealityRipple'} | |
}; | |
</script> | |
<style> | |
.text | |
{ | |
font-size: 32px; | |
line-height: 36px; /* adjust as needed for the text-shadow */ | |
color: #FFFFFF; | |
text-shadow: 2px 2px 3px #000000; | |
/* font-family: 'Comic Sans MS'; */ | |
} | |
.style1 | |
{ | |
color: #FFFF00; | |
} | |
.style2 | |
{ | |
font-style: italic; | |
} | |
.style3 | |
{ | |
color: #008000; | |
} | |
</style> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>Track Display for StreamElements</title> | |
<style> | |
:root | |
{ | |
--pos: 0px; | |
} | |
body | |
{ | |
text-align: left; | |
margin: 0; | |
} | |
table | |
{ | |
border: 0; | |
visibility: hidden; | |
position: fixed; | |
opacity: 0; | |
} | |
#label | |
{ | |
margin: 0; | |
background-color: transparent; | |
padding: 2px 8px 8px; | |
white-space: nowrap; | |
} | |
#trackBox | |
{ | |
width: 100%; | |
overflow: hidden; | |
position: relative; | |
} | |
.track | |
{ | |
margin: 0; | |
top: 0; | |
display: none; | |
position: absolute; | |
background-color: transparent; | |
padding: 2px 0; | |
white-space: nowrap; | |
animation-name: fullWidth; | |
animation-timing-function: ease-in-out; | |
animation-direction: alternate; | |
animation-iteration-count: infinite; | |
visibility: hidden; | |
opacity: 0; | |
} | |
@keyframes fullWidth | |
{ | |
from | |
{ | |
transform: translate(0, 0); | |
} | |
to | |
{ | |
transform: translate(var(--pos), 0); | |
} | |
} | |
</style> | |
<script> | |
var sTitle = false; | |
var sChannel = false; | |
var sUser = false; | |
var lastW = 0; | |
var lastD = 0; | |
var queueOpen = false; | |
function sleep(ms) | |
{ | |
return new Promise(resolve => setTimeout(resolve, ms)); | |
} | |
function loadUser() | |
{ | |
let p = new Promise((resolve, reject) => | |
{ | |
let x = new XMLHttpRequest(); | |
x.open('GET', 'https://api.streamelements.com/kappa/v2/songrequest/' + userID + '/settings/public', true); | |
x.onreadystatechange = function() | |
{ | |
if(x.readyState !== 4) | |
return; | |
if (x.status !== 200 && x.status !== 0) | |
return; | |
if (x.responseText === '') | |
return; | |
parseRequests(x.responseText); | |
resolve(true); | |
} | |
x.send(null); | |
} | |
); | |
return p; | |
} | |
function parseRequests(sJSON) | |
{ | |
let j = JSON.parse(sJSON); | |
queueOpen = (j.hasOwnProperty('enabled') && j.enabled); | |
} | |
function updateTrack() | |
{ | |
sTitle = false; | |
sChannel = false; | |
let x = new XMLHttpRequest(); | |
x.open('GET', 'https://api.streamelements.com/kappa/v2/songrequest/' + userID +'/queue/public', true); | |
// 'https://api.streamelements.com/kappa/v2/songrequest/' + userID + '/queue/public' | |
x.onreadystatechange = function() | |
{ | |
if(x.readyState !== 4) | |
return; | |
if (x.status !== 200 && x.status !== 0) | |
return; | |
if (x.responseText === '') | |
return; | |
parseTrack(x.responseText); | |
displayTrack(); | |
} | |
x.send(null); | |
} | |
function cleanTitle(s) | |
{ | |
let enclosedEnd = /[([][^()[\]]+ (video|lyrics|remaster)[)\]]$/gi; | |
let enclosedMatch = /[([](video|lyrics|hd|full|720p|1080p|remastered|high quality)[)\]]$/gi; | |
let paddedEnd = /[~-]+[^-~]+(lyrics|video)$/gi; | |
let paddedMatch = /[~-]+ *(lyrics|video|hd|full|720p|1080p|high quality)$/gi; | |
while (s.match(enclosedEnd) || | |
s.match(enclosedMatch) || | |
s.match(paddedEnd) || | |
s.match(paddedMatch)) | |
{ | |
s = s.replace(enclosedEnd, '').trimEnd(); | |
s = s.replace(enclosedMatch, '').trimEnd(); | |
s = s.replace(paddedEnd, '').trimEnd(); | |
s = s.replace(paddedMatch, '').trimEnd(); | |
} | |
let rawEnd = / (lyrics|1080p|720p)$/gi; | |
while (s.match(rawEnd)) | |
s = s.replace(rawEnd, '').trimEnd(); | |
return s; | |
} | |
function cleanChannel(s) | |
{ | |
while (s.slice(-8) === ' - Topic') | |
s = s.slice(0, -8); | |
return s; | |
} | |
function parseTrack(sJSON) | |
{ | |
let j = JSON.parse(sJSON); | |
if (!Array.isArray(j) || j.length < index) | |
{ | |
sTitle = false; | |
if (queueOpen) | |
{ | |
if (emptyOpenDisp !== null && emptyOpenDisp !== '') | |
sTitle = emptyOpenDisp; | |
} | |
else | |
{ | |
if (emptyClosedDisp !== null && emptyClosedDisp !== '') | |
sTitle = emptyClosedDisp; | |
} | |
sChannel = false; | |
sUser = false; | |
return; | |
} | |
sTitle = cleanTitle(j[index - 1].title); | |
if (j.hasOwnProperty('channel')) | |
sChannel = cleanChannel(j[index - 1].channel); | |
else | |
sChannel = false; | |
if (j[index - 1].hasOwnProperty('user') && j[index - 1].user.hasOwnProperty('username') && j[index - 1].user.username.toLowerCase() !== userName.toLowerCase()) | |
sUser = j[index - 1].user.username; | |
else | |
sUser = false; | |
} | |
async function showTable() | |
{ | |
let tbl = document.getElementById('trackTable'); | |
if (tbl.style.visibility === 'visible') | |
return; | |
tbl.style.opacity = '0'; | |
tbl.style.visibility = 'visible'; | |
tbl.style.transitionProperty = 'opacity'; | |
tbl.style.transitionDuration = fadeTime + 's'; | |
tbl.style.opacity = '1'; | |
} | |
async function hideTable() | |
{ | |
let tbl = document.getElementById('trackTable'); | |
if (tbl.style.visibility !== 'visible') | |
return; | |
tbl.style.transitionProperty = 'opacity'; | |
tbl.style.transitionDuration = fadeTime + 's'; | |
tbl.style.opacity = '0'; | |
await sleep(fadeTime * 1000); | |
tbl.style.transitionProperty = ''; | |
tbl.style.transitionDuration = ''; | |
tbl.style.visibility = ''; | |
tbl.style.opacity = ''; | |
} | |
function showFade() | |
{ | |
let tb = document.getElementById('trackBox'); | |
if (!tb.hasAttribute('style')) | |
tb.setAttribute('style', '-webkit-mask-image: linear-gradient(to right, transparent 0, black ' + fadePad + 'px, black calc(100% - ' + fadePad + 'px), transparent 100%);'); | |
} | |
function hideFade() | |
{ | |
let tb = document.getElementById('trackBox'); | |
if (tb.hasAttribute('style')) | |
tb.removeAttribute('style'); | |
} | |
async function showTrack() | |
{ | |
let t = document.getElementById('track'); | |
if (t.style.visibility === 'visible') | |
return; | |
t.style.visibility = 'visible'; | |
t.style.opacity = '0'; | |
t.style.transitionProperty = 'opacity'; | |
t.style.transitionDuration = fadeTime + 's'; | |
t.style.opacity = '1'; | |
await sleep(fadeTime * 1000); | |
t.style.transitionProperty = ''; | |
t.style.transitionDuration = ''; | |
} | |
function styleTrack(measureOnly) | |
{ | |
if (trackStyle === false) | |
return; | |
for (let s in trackStyle) | |
{ | |
if (!measureOnly) | |
{ | |
if (document.getElementById('track').classList.contains(s)) | |
document.getElementById('track').classList.remove(s); | |
} | |
if (document.getElementById('measure').classList.contains(s)) | |
document.getElementById('measure').classList.remove(s); | |
if (trackStyle[s].hasOwnProperty('user')) | |
{ | |
if (sUser === false) | |
continue; | |
if (!sUser.toLowerCase().split(', ').includes(trackStyle[s].user.toLowerCase())) | |
continue; | |
} | |
if (trackStyle[s].hasOwnProperty('title')) | |
{ | |
if (sTitle === false) | |
continue; | |
if (sTitle.toLowerCase() !== trackStyle[s].title.toLowerCase()) | |
continue; | |
} | |
if (trackStyle[s].hasOwnProperty('channel')) | |
{ | |
if (sChannel === false) | |
continue; | |
if (sChannel.toLowerCase() !== trackStyle[s].channel.toLowerCase()) | |
continue; | |
} | |
if (!measureOnly) | |
document.getElementById('track').classList.add(s); | |
document.getElementById('measure').classList.add(s); | |
} | |
} | |
async function hideTrack() | |
{ | |
let t = document.getElementById('track'); | |
if (t.style.display !== 'inline-block') | |
{ | |
t.style.opacity = '0'; | |
t.style.display = 'inline-block'; | |
} | |
else | |
{ | |
t.style.transitionProperty = 'opacity'; | |
t.style.transitionDuration = fadeTime + 's'; | |
t.style.opacity = '0'; | |
await sleep(fadeTime * 1000); | |
t.style.transitionProperty = ''; | |
t.style.transitionDuration = ''; | |
} | |
t.style.opacity = ''; | |
t.style.visibility = ''; | |
t.innerHTML = ''; | |
} | |
function measureTrack(s) | |
{ | |
styleTrack(true); | |
let t = document.getElementById('measure'); | |
t.style.display = 'inline-block'; | |
t.innerHTML = s; | |
let w = t.getBoundingClientRect()['width']; | |
t.style.display = ''; | |
t.innerHTML = ''; | |
return w; | |
} | |
async function displayTrack() | |
{ | |
let t = document.getElementById('track'); | |
let l = document.getElementById('label'); | |
if (sTitle === false) | |
{ | |
lastW = 0; | |
lastD = 0; | |
await hideTable() | |
if (t.hasAttribute('style')) | |
t.removeAttribute('style'); | |
t.innerHTML = ''; | |
return; | |
} | |
let w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
let dTitle = titleDisp.replace('%TITLE%', sTitle); | |
let dChannel = ''; | |
if (channelDisp !== false && sChannel !== false) | |
dChannel = channelDisp.replace('%CHANNEL%', sChannel); | |
let dUser = ''; | |
if (userDisp !== false && sUser !== false) | |
dUser = userDisp.replace('%USER%', sUser); | |
let track = trackDisp.replace('%DISP_TITLE%', dTitle).replace('%DISP_CHANNEL%', dChannel).replace('%DISP_USER%', dUser); | |
let d = measureTrack(track); | |
let h = false; | |
let range = 0; | |
if (l.style.paddingRight === scrollPad + 'px') | |
range = Math.abs((normPad * 2) - (normPad + scrollPad)); | |
if (label !== '') | |
{ | |
if (d + (normPad * 2) > w - range) | |
{ | |
if (l.style.paddingRight !== scrollPad + 'px') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = scrollPad + 'px'; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
else | |
{ | |
if (fitScroll) | |
{ | |
if (l.style.paddingRight !== scrollPad + 'px') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = scrollPad + 'px'; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
else | |
{ | |
if (l.style.paddingRight !== '') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = ''; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
} | |
} | |
if (!h && w === lastW && d === lastD) | |
return; | |
lastW = w; | |
lastD = d; | |
if (!h) | |
await hideTrack(); | |
styleTrack(false); | |
range = 0; | |
if (l.style.paddingRight === scrollPad + 'px') | |
range = Math.abs((normPad * 2) - (normPad + scrollPad)); | |
if (d + (normPad * 2) > w - range) | |
{ | |
d -= w; | |
d += fadePad * 2; | |
let u = Math.ceil(d * scrollRate); | |
if (u < 2000) | |
u = 2000; | |
if (l.style.paddingRight !== scrollPad + 'px' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = scrollPad + 'px'; | |
showFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', '-' + Math.ceil(d) + 'px'); | |
t.style.marginLeft = fadePad + 'px'; | |
t.style.marginRight = fadePad + 'px'; | |
t.style.animationDuration = u + 'ms'; | |
await showTable(); | |
await showTrack(); | |
} | |
else | |
{ | |
if (fitScroll) | |
{ | |
let m = w - d; | |
m -= normPad; | |
let u = Math.ceil(m * fitScrollRate); | |
if (u < 2000) | |
u = 2000; | |
if (l.style.paddingRight !== scrollPad + 'px' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = scrollPad + 'px'; | |
hideFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', Math.ceil(m) + 'px'); | |
t.style.marginLeft = ''; | |
t.style.marginRight = ''; | |
t.style.animationDuration = u + 'ms'; | |
await showTable(); | |
await showTrack(); | |
} | |
else | |
{ | |
if (l.style.paddingRight !== '' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = ''; | |
hideFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', '0px'); | |
t.style.marginLeft = ''; | |
t.style.marginRight = ''; | |
t.style.animationDuration = ''; | |
await showTable(); | |
await showTrack(); | |
} | |
} | |
} | |
function showLabel() | |
{ | |
let l = document.getElementById('label'); | |
if (label === '') | |
{ | |
l.style.paddingLeft = '0px'; | |
l.style.paddingRight = '0px'; | |
l.style.width = '1px'; | |
l.innerHTML = '​'; | |
} | |
else | |
l.innerHTML = label; | |
} | |
</script> | |
</head> | |
<body> | |
<table id="trackTable"> | |
<tr> | |
<td id="label" class="text"></td> | |
<td id="trackBox"><div id="track" class="track text"></div></td> | |
</tr> | |
</table> | |
<div id="measure" class="track text"></div> | |
<script> | |
async function init() | |
{ | |
await loadUser(); | |
window.setInterval(loadUser, interval * 1000); | |
showLabel(); | |
window.setInterval(updateTrack, interval * 1000); | |
updateTrack(); | |
} | |
init(); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<script> | |
var userID = 'your_account'; /* streamelements account ID */ | |
var userName = 'your_channel'; /* broadcaster name (to negate requester matching your name) - use '' to show your own name */ | |
var fadePad = 32; /* left and right margin */ | |
var scrollRate = 20; /* lower is faster */ | |
var interval = 2; /* update time in seconds */ | |
var fadeTime = 0.5; /* fade speed in seconds */ | |
var normPad = 8; /* label padding. must equal #label's left and right padding value */ | |
var scrollPad = 6; /* padding between label and track name when scrolling */ | |
var label = 'Now Playing:'; /* use '' for no label */ | |
var fitScroll = false; /* set to true to scroll text that fits */ | |
var fitScrollRate = 15; /* lower is faster */ | |
var trackDisp = '%DISP_CHANNEL%%DISP_TITLE%%DISP_USER%'; /* display of below variables */ | |
var channelDisp = '%CHANNEL% - '; /* channel name display (with text shown when a channel is provided, empty if no channel or live learn) */ | |
var titleDisp = '%TITLE%'; /* title display */ | |
var userDisp = ' for %USER%'; /* requester username display (with text shown when a song is by request, empty if no requester) */ | |
/* | |
* Example Track Displays: | |
* | |
* trackDisp = '%DISP_CHANNEL%%DISP_TITLE%%DISP_USER%' | |
* channelDisp = '%CHANNEL% - ' | |
* titleDisp = '%TITLE%' | |
* userDisp = 'for %USER' | |
* => Pink Floyd - Wish You Were Here for RealityRipple | |
* | |
* trackDisp = '%DISP_USER%%DISP_TITLE%%DISP_CHANNEL%' | |
* channelDisp = ' by %CHANNEL%' | |
* titleDisp = '%TITLE%' | |
* userDisp = '%USER%\'s Request: ' | |
* => RealityRipple's Request: Wish You Were Here by Pink Floyd | |
* | |
* trackDisp = '%DISP_TITLE%' | |
* channelDisp = ''; | |
* titleDisp = '%TITLE%'; | |
* userDisp = ''; | |
* => Wish You Were Here | |
*/ | |
var trackStyle = { | |
'style1': {title: 'Stairway to Heaven'}, | |
'style2': {channel: 'Topic - Led Zeppelin'}, | |
'style3': {user: 'RealityRipple'} | |
}; | |
</script> | |
<style> | |
.text | |
{ | |
font-size: 32px; | |
line-height: 36px; /* adjust as needed for the text-shadow */ | |
color: #FFFFFF; | |
text-shadow: 2px 2px 3px #000000; | |
/* font-family: 'Comic Sans MS'; */ | |
} | |
.style1 | |
{ | |
color: #FFFF00; | |
} | |
.style2 | |
{ | |
font-style: italic; | |
} | |
.style3 | |
{ | |
color: #008000; | |
} | |
</style> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>Track Display for StreamElements</title> | |
<style> | |
:root | |
{ | |
--pos: 0px; | |
} | |
body | |
{ | |
text-align: left; | |
margin: 0; | |
} | |
table | |
{ | |
border: 0; | |
visibility: hidden; | |
position: fixed; | |
opacity: 0; | |
} | |
#label | |
{ | |
margin: 0; | |
background-color: transparent; | |
padding: 2px 8px 8px; | |
white-space: nowrap; | |
} | |
#trackBox | |
{ | |
width: 100%; | |
overflow: hidden; | |
position: relative; | |
} | |
.track | |
{ | |
margin: 0; | |
top: 0; | |
display: none; | |
position: absolute; | |
background-color: transparent; | |
padding: 2px 0; | |
white-space: nowrap; | |
animation-name: fullWidth; | |
animation-timing-function: ease-in-out; | |
animation-direction: alternate; | |
animation-iteration-count: infinite; | |
visibility: hidden; | |
opacity: 0; | |
} | |
@keyframes fullWidth | |
{ | |
from | |
{ | |
transform: translate(0, 0); | |
} | |
to | |
{ | |
transform: translate(var(--pos), 0); | |
} | |
} | |
</style> | |
<script> | |
var sTitle = false; | |
var sChannel = false; | |
var sUser = false; | |
var lastW = 0; | |
var lastD = 0; | |
function sleep(ms) | |
{ | |
return new Promise(resolve => setTimeout(resolve, ms)); | |
} | |
function updateTrack() | |
{ | |
sTitle = false; | |
sChannel = false; | |
let x = new XMLHttpRequest(); | |
x.open('GET', 'https://api.streamelements.com/kappa/v2/songrequest/' + userID +'/playing', true); | |
// 'https://api.streamelements.com/kappa/v2/songrequest/' + userID + '/queue/public' | |
x.onreadystatechange = function() | |
{ | |
if(x.readyState !== 4) | |
return; | |
if (x.status !== 200 && x.status !== 0) | |
return; | |
if (x.responseText === '') | |
return; | |
parseTrack(x.responseText); | |
displayTrack(); | |
} | |
x.send(null); | |
} | |
function cleanTitle(s) | |
{ | |
let enclosedEnd = /[([][^()[\]]+ (video|lyrics|remaster)[)\]]$/gi; | |
let enclosedMatch = /[([](video|lyrics|hd|full|720p|1080p|remastered|high quality)[)\]]$/gi; | |
let paddedEnd = /[~-]+[^-~]+(lyrics|video)$/gi; | |
let paddedMatch = /[~-]+ *(lyrics|video|hd|full|720p|1080p|high quality)$/gi; | |
while (s.match(enclosedEnd) || | |
s.match(enclosedMatch) || | |
s.match(paddedEnd) || | |
s.match(paddedMatch)) | |
{ | |
s = s.replace(enclosedEnd, '').trimEnd(); | |
s = s.replace(enclosedMatch, '').trimEnd(); | |
s = s.replace(paddedEnd, '').trimEnd(); | |
s = s.replace(paddedMatch, '').trimEnd(); | |
} | |
let rawEnd = / (lyrics|1080p|720p)$/gi; | |
while (s.match(rawEnd)) | |
s = s.replace(rawEnd, '').trimEnd(); | |
return s; | |
} | |
function cleanChannel(s) | |
{ | |
while (s.slice(-8) === ' - Topic') | |
s = s.slice(0, -8); | |
return s; | |
} | |
function parseTrack(sJSON) | |
{ | |
let j = JSON.parse(sJSON); | |
if (!j.hasOwnProperty('title')) | |
{ | |
sTitle = false; | |
sChannel = false; | |
sUser = false; | |
return; | |
} | |
sTitle = cleanTitle(j.title); | |
if (j.hasOwnProperty('channel')) | |
sChannel = cleanChannel(j.channel); | |
else | |
sChannel = false; | |
if (j.hasOwnProperty('user') && j.user.hasOwnProperty('username') && j.user.username.toLowerCase() !== userName.toLowerCase()) | |
sUser = j.user.username; | |
else | |
sUser = false; | |
} | |
async function showTable() | |
{ | |
let tbl = document.getElementById('trackTable'); | |
if (tbl.style.visibility === 'visible') | |
return; | |
tbl.style.opacity = '0'; | |
tbl.style.visibility = 'visible'; | |
tbl.style.transitionProperty = 'opacity'; | |
tbl.style.transitionDuration = fadeTime + 's'; | |
tbl.style.opacity = '1'; | |
} | |
async function hideTable() | |
{ | |
let tbl = document.getElementById('trackTable'); | |
if (tbl.style.visibility !== 'visible') | |
return; | |
tbl.style.transitionProperty = 'opacity'; | |
tbl.style.transitionDuration = fadeTime + 's'; | |
tbl.style.opacity = '0'; | |
await sleep(fadeTime * 1000); | |
tbl.style.transitionProperty = ''; | |
tbl.style.transitionDuration = ''; | |
tbl.style.visibility = ''; | |
tbl.style.opacity = ''; | |
} | |
function showFade() | |
{ | |
let tb = document.getElementById('trackBox'); | |
if (!tb.hasAttribute('style')) | |
tb.setAttribute('style', '-webkit-mask-image: linear-gradient(to right, transparent 0, black ' + fadePad + 'px, black calc(100% - ' + fadePad + 'px), transparent 100%);'); | |
} | |
function hideFade() | |
{ | |
let tb = document.getElementById('trackBox'); | |
if (tb.hasAttribute('style')) | |
tb.removeAttribute('style'); | |
} | |
async function showTrack() | |
{ | |
let t = document.getElementById('track'); | |
if (t.style.visibility === 'visible') | |
return; | |
t.style.visibility = 'visible'; | |
t.style.opacity = '0'; | |
t.style.transitionProperty = 'opacity'; | |
t.style.transitionDuration = fadeTime + 's'; | |
t.style.opacity = '1'; | |
await sleep(fadeTime * 1000); | |
t.style.transitionProperty = ''; | |
t.style.transitionDuration = ''; | |
} | |
function styleTrack(measureOnly) | |
{ | |
if (trackStyle === false) | |
return; | |
for (let s in trackStyle) | |
{ | |
if (!measureOnly) | |
{ | |
if (document.getElementById('track').classList.contains(s)) | |
document.getElementById('track').classList.remove(s); | |
} | |
if (document.getElementById('measure').classList.contains(s)) | |
document.getElementById('measure').classList.remove(s); | |
if (trackStyle[s].hasOwnProperty('user')) | |
{ | |
if (sUser === false) | |
continue; | |
if (!sUser.toLowerCase().split(', ').includes(trackStyle[s].user.toLowerCase())) | |
continue; | |
} | |
if (trackStyle[s].hasOwnProperty('title')) | |
{ | |
if (sTitle === false) | |
continue; | |
if (sTitle.toLowerCase() !== trackStyle[s].title.toLowerCase()) | |
continue; | |
} | |
if (trackStyle[s].hasOwnProperty('channel')) | |
{ | |
if (sChannel === false) | |
continue; | |
if (sChannel.toLowerCase() !== trackStyle[s].channel.toLowerCase()) | |
continue; | |
} | |
if (!measureOnly) | |
document.getElementById('track').classList.add(s); | |
document.getElementById('measure').classList.add(s); | |
} | |
} | |
async function hideTrack() | |
{ | |
let t = document.getElementById('track'); | |
if (t.style.display !== 'inline-block') | |
{ | |
t.style.opacity = '0'; | |
t.style.display = 'inline-block'; | |
} | |
else | |
{ | |
t.style.transitionProperty = 'opacity'; | |
t.style.transitionDuration = fadeTime + 's'; | |
t.style.opacity = '0'; | |
await sleep(fadeTime * 1000); | |
t.style.transitionProperty = ''; | |
t.style.transitionDuration = ''; | |
} | |
t.style.opacity = ''; | |
t.style.visibility = ''; | |
t.innerHTML = ''; | |
} | |
function measureTrack(s) | |
{ | |
styleTrack(true); | |
let t = document.getElementById('measure'); | |
t.style.display = 'inline-block'; | |
t.innerHTML = s; | |
let w = t.getBoundingClientRect()['width']; | |
t.style.display = ''; | |
t.innerHTML = ''; | |
return w; | |
} | |
async function displayTrack() | |
{ | |
let t = document.getElementById('track'); | |
let l = document.getElementById('label'); | |
if (sTitle === false) | |
{ | |
lastW = 0; | |
lastD = 0; | |
await hideTable() | |
if (t.hasAttribute('style')) | |
t.removeAttribute('style'); | |
t.innerHTML = ''; | |
return; | |
} | |
let w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
let dTitle = titleDisp.replace('%TITLE%', sTitle); | |
let dChannel = ''; | |
if (channelDisp !== false && sChannel !== false) | |
dChannel = channelDisp.replace('%CHANNEL%', sChannel); | |
let dUser = ''; | |
if (userDisp !== false && sUser !== false) | |
dUser = userDisp.replace('%USER%', sUser); | |
let track = trackDisp.replace('%DISP_TITLE%', dTitle).replace('%DISP_CHANNEL%', dChannel).replace('%DISP_USER%', dUser); | |
let d = measureTrack(track); | |
let h = false; | |
let range = 0; | |
if (l.style.paddingRight === scrollPad + 'px') | |
range = Math.abs((normPad * 2) - (normPad + scrollPad)); | |
if (label !== '') | |
{ | |
if (d + (normPad * 2) > w - range) | |
{ | |
if (l.style.paddingRight !== scrollPad + 'px') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = scrollPad + 'px'; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
else | |
{ | |
if (fitScroll) | |
{ | |
if (l.style.paddingRight !== scrollPad + 'px') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = scrollPad + 'px'; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
else | |
{ | |
if (l.style.paddingRight !== '') | |
{ | |
await hideTrack(); | |
l.style.paddingRight = ''; | |
w = document.getElementById('trackBox').getBoundingClientRect()['width']; | |
h = true; | |
} | |
} | |
} | |
} | |
if (!h && w === lastW && d === lastD) | |
return; | |
lastW = w; | |
lastD = d; | |
if (!h) | |
await hideTrack(); | |
styleTrack(false); | |
range = 0; | |
if (l.style.paddingRight === scrollPad + 'px') | |
range = Math.abs((normPad * 2) - (normPad + scrollPad)); | |
if (d + (normPad * 2) > w - range) | |
{ | |
d -= w; | |
d += fadePad * 2; | |
let u = Math.ceil(d * scrollRate); | |
if (u < 2000) | |
u = 2000; | |
if (l.style.paddingRight !== scrollPad + 'px' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = scrollPad + 'px'; | |
showFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', '-' + Math.ceil(d) + 'px'); | |
t.style.marginLeft = fadePad + 'px'; | |
t.style.marginRight = fadePad + 'px'; | |
t.style.animationDuration = u + 'ms'; | |
await showTable(); | |
await showTrack(); | |
} | |
else | |
{ | |
if (fitScroll) | |
{ | |
let m = w - d; | |
m -= normPad; | |
let u = Math.ceil(m * fitScrollRate); | |
if (u < 2000) | |
u = 2000; | |
if (l.style.paddingRight !== scrollPad + 'px' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = scrollPad + 'px'; | |
hideFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', Math.ceil(m) + 'px'); | |
t.style.marginLeft = ''; | |
t.style.marginRight = ''; | |
t.style.animationDuration = u + 'ms'; | |
await showTable(); | |
await showTrack(); | |
} | |
else | |
{ | |
if (l.style.paddingRight !== '' && l.style.paddingRight !== '0px') | |
l.style.paddingRight = ''; | |
hideFade(); | |
t.innerHTML = track; | |
document.documentElement.style.setProperty('--pos', '0px'); | |
t.style.marginLeft = ''; | |
t.style.marginRight = ''; | |
t.style.animationDuration = ''; | |
await showTable(); | |
await showTrack(); | |
} | |
} | |
} | |
function showLabel() | |
{ | |
let l = document.getElementById('label'); | |
if (label === '') | |
{ | |
l.style.paddingLeft = '0px'; | |
l.style.paddingRight = '0px'; | |
l.style.width = '1px'; | |
l.innerHTML = '​'; | |
} | |
else | |
l.innerHTML = label; | |
} | |
</script> | |
</head> | |
<body> | |
<table id="trackTable"> | |
<tr> | |
<td id="label" class="text"></td> | |
<td id="trackBox"><div id="track" class="track text"></div></td> | |
</tr> | |
</table> | |
<div id="measure" class="track text"></div> | |
<script> | |
function init() | |
{ | |
showLabel(); | |
window.setInterval(updateTrack, interval * 1000); | |
updateTrack(); | |
} | |
init(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment