<!DOCTYPE html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
<link rel='icon' type="image/x-icon" href='images/KHUM-Favicon.svg' />
<link rel='stylesheet' href='styles/common.css' />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="description" content="Humboldt's Radio Without the Rules">
<meta name="keywords" content="Humboldt, KHUM, Radio">
<script src='../scripts/json-display.js'></script> <title>KHUM | 104.7 & 104.3 FM</title>
<link rel='stylesheet' href='styles/index.css' />
</head>
<body>
<div id='grid'>
<div id='nav-container' class='container'><link rel='stylesheet' href='styles/nav.css' />
<nav>
<img src='images/KHUM-Logo.svg'>
<article class='content-height left-connected'>
<ul>
<a href='../index.php'><p>Home</p></a>
<a href='#' id='nav-listen-live'><p>Listen Live</p></a>
<div class='list-gap'></div>
<a href='../djs.php'><p>DJs</p></a>
<a href='../schedule.php'><p>Schedule</p></a>
<a href='../features.php'><p>Features</p></a>
<a href='../notices.php'><p>Notices</p></a>
<a href='../playlist.php'><p>Playlist</p></a>
<div class='list-gap'></div>
<a href='https://lostcoastoutpost.com/lowdown/' target="_blank"><p>Goodtime Guide</p></a>
<div class='list-gap'></div>
<a href='https://lccswag.myspreadshop.com/khum?collection=YwLBkQzcXf' target="_blank"><p>Swag</p></a>
<a href='../contact.php'><p>Contact</p></a>
<!-- <a href='../advertise.php'><p>Advertise</p></a>
<a href='../jobs.php'><p>Jobs</p></a> -->
</ul>
<h5>Radio Without the Rules</h5>
</article>
<article class='content-height left-connected' style='margin-top: auto;'>
<ul>
<a href='https://www.facebook.com/KHUMradio/' target='_blank'><p>Facebook</p></a>
<a href='https://www.instagram.com/khumradio/' target='_blank'><p>Instagram</p></a>
<a href='https://twitter.com/KHUMradio' target='_blank'><p>Twitter</p></a>
</ul>
</article>
<script>
document.getElementById("nav-listen-live").onclick = () => {
window.open('listen-live.php','KHUM - Listen Live','popup,innerWidth=720,innerHeight=400,screenX=50%,screenY=50%,resizable=no');
};
</script>
</nav></div>
<div id='alert-container' class='container'><article id='notice' class='left-connected' style='flex-direction: column;'>
<div class='json-article info-pop-up' id='notice-receiver'></div>
</article>
<script>
let noticeArticle = JSON.parse('[{"tag":"img","label":"image1","alt":"KHUM Phones are back! 707-232-5486","source":"https://lccibackend.com/merlin/imageDepot/KHUM%20Phones%20are%20Back.png","classes":["half-width","float-right"],"undefined":"image1"},{"tag":"p","label":"paragraph1","textContent":"So EXCITING!","classes":["center-align"],"undefined":"paragraph1"},{"tag":"p","label":"paragraph1","textContent":"Once again, KHUM has open lines of communication! Give us a call and let us know what we can play for you, or just simply say hello!","classes":["left-align"],"undefined":"paragraph1"},{"label":"paragraph","tag":"p","textContent":"[Phone]: 707-232-5486","classes":["center-align"],"undefined":"paragraph"}]');
displayJSON(document.getElementById('notice-receiver'), noticeArticle);
console.log(1);
</script>
</div>
<div id='nextfeature-container' class='container'>
<article id='nextfeature' class='right-connected'>
<h2>Catch the next feature:</h2>
<div class='json-article info-pop-up' id='nextfeature-receiver'>
<header>
<h1><script>console.log("Got id: for feature: .");</script></h1><h2>12:00am</h2></header>
</div>
</article>
<script>
const nextFeatureJSONreceiver = document.getElementById('nextfeature-receiver');
let nextFeatureArticle = JSON.parse('');
displayJSON(nextFeatureJSONreceiver, nextFeatureArticle);
async function requestNextFeature() {
const url = 'scripts/return-next-feature.php';
const response = await fetch(url).then(_response => {
return _response.json();
}).then(_message => {
nextFeatureArticle = JSON.parse(_message.article);
nextFeatureJSONreceiver.textContent = '';
let nextFeatureH1 = document.createElement('h1');
nextFeatureH1.textContent = _message.title;
let nextFeatureH2 = document.createElement('h2');
nextFeatureH2.textContent = _message.times;
nextFeatureJSONreceiver.appendChild(nextFeatureH1);
nextFeatureJSONreceiver.appendChild(nextFeatureH2);
displayJSON(nextFeatureJSONreceiver, nextFeatureArticle);
checkDelay = _message.check_delay * 1000;
setTimeout(requestNextFeature, checkDelay);
});
}
requestNextFeature();
</script>
</div>
<div id='nowplaying-container' class='container'><script>let songID = 8508;</script>
<script>
let currentSong = "Rhythms Del Mundo";
let currentArtist = "GORILLAZ";
let currentTime = "4:01 pm";
let likeCount = 0;
let dislikeCount = 0;
</script>
<article id='nowplaying' class='content-height right-connected'>
<h3>Now Playing</h3>
<img id='now-playing-img' src='images/khum-missing.jpg' alt='The Album Cover Art service is temporarily down.'>
<ul>
<li>
<abbr id='nowplaying-abbr' title="Rhythms Del Mundo"><h1 id='nowplaying-song'>Rhythms Del Mundo</h1></abbr>
<p><i id='nowplaying-artist'>GORILLAZ</i></p>
</li>
<li class='like-dislike'>
<button id = 'nowplaying-button-up' class='likebutton upbutton-8508' onclick='vote(8508, 0, choice="vUp")'><img src='images/icon-thumbsup.svg'><p id=''>0</p></button>
<button id = 'nowplaying-button-down' class='dislikebutton downbutton-8508' onclick='vote(8508, 0, choice="vDown")'><img src='images/icon-thumbsdown.svg'><p id=''>0</p></button>
</li>
<a href='#' id = 'listen-live-button'><p>Listen Live</p></a>
</ul>
</article>
<script>
// async function updateAlbumArt(_artist, _album){
// document.getElementById("now-playing-img").src = "images/khum-loading.gif";
// if(!_album){ document.getElementById("now-playing-img").src = "images/khum-missing.jpg"; return; }
// let idSearchURL = "https://musicbrainz.org/ws/2/release/?query=album:" + _album;
// if(_artist){ idSearchURL += " AND artist:" + _artist; }
// idSearchURL += "&fmt=json";
// const response = await fetch(idSearchURL);
// if(!response.ok){ document.getElementById("now-playing-img").src = "images/khum-missing.jpg"; return; }
// const json = await response.json();
// let albumId = json.releases[0].id;
// let imageSearchURL = "http://coverartarchive.org/release/" + albumId + "/front";
// const imageResponse = await fetch(imageSearchURL);
// if(!imageResponse.ok){ document.getElementById("now-playing-img").src = "images/khum-missing.jpg"; return; }
// document.getElementById("now-playing-img").src = imageResponse.url;
// }
// updateAlbumArt("GORILLAZ", "");
</script>
<!-- Update "now playing" song using server-sent events from lccibackend -->
<script>
document.getElementById("listen-live-button").onclick = () => {
window.open('listen-live.php','KHUM - Listen Live','popup,innerWidth=720,innerHeight=400,screenX=50%,screenY=50%,resizable=no');
};
window.onload = function() {
const nowPlayingSong = document.getElementById("nowplaying-song");
const nowPlayingAbbr = document.getElementById("nowplaying-abbr");
const nowPlayingArtist = document.getElementById("nowplaying-artist");
const nowPlayingButtonUp = document.getElementById("nowplaying-button-up");
const nowPlayingButtonDown = document.getElementById("nowplaying-button-down");
let recentlyPlayedExists = false;
let playlistExists = false;
let updatePlaylist = false;
if(document.getElementById("recentlyplayed-container")){ recentlyPlayedExists = true; }
if(document.getElementById("playlist-container")){ playlistExists = true; }
if(playlistExists){ if(document.getElementById("playlist-container").classList.contains("update-live")){ updatePlaylist = true; } }
const timeFormat = (date) => { //time formatting function (hh:mm am or pm)
let hours = date.getHours();
let minutes = date.getMinutes();
const ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0' + minutes : minutes;
return hours + ':' + minutes + ' ' + ampm;
};
if(typeof(EventSource)=="undefined") { //check for browser support
document.getElementById("nowplaying-text").innerHTML="Radio Without The Rules";
} else {
let eSource = new EventSource("https://lccibackend.com/lcc_sse.php?station=2"); //create an object, passing it the name and location of the server-side script
eSource.onmessage = function(event) { //detect message receipt
let jdata = JSON.parse(event.data);
if (jdata.station == '2') {
if (jdata.title != currentSong) {
nowPlayingButtonUp.classList.remove("upbutton-"+songID);
nowPlayingButtonDown.classList.remove("downbutton-"+songID);
if(recentlyPlayedExists) {
addRecentSong(currentSong, currentArtist, currentTime);
}
currentSong = jdata.title;
currentArtist = jdata.artist;
let dateObj = new Date(jdata.play_date);
currentTime = timeFormat(dateObj);
upVotes = jdata.up;
if(upVotes==null){ upVotes=0; }
downVotes = jdata.down;
if(downVotes==null){ downVotes=0; }
songID = jdata.song_id;
if(upVotes==0 && downVotes==0){votes="0";} else {votes = "1";}
if(playlistExists && updatePlaylist) {
addPlaylistSong(currentSong, currentArtist, currentTime, songID, votes, upVotes, downVotes);
}
if(!jdata.cover_art_url) {
document.getElementById("now-playing-img").src = "images/khum-missing.jpg";
} else {
document.getElementById("now-playing-img").src = jdata.cover_art_url;
}
nowPlayingSong.textContent = currentSong; //write the received data to the page
nowPlayingAbbr.title = currentSong;
nowPlayingArtist.textContent = currentArtist;
nowPlayingButtonUp.classList.add("upbutton-"+songID);
nowPlayingButtonUp.disabled = false;
nowPlayingButtonUp.firstElementChild.nextSibling.textContent = upVotes;
nowPlayingButtonUp.setAttribute("onclick","vote('"+songID+"', '"+votes+"', choice='vUp')");
nowPlayingButtonDown.classList.add("downbutton-"+songID);
nowPlayingButtonDown.disabled = false;
nowPlayingButtonDown.firstElementChild.nextSibling.textContent = downVotes;
nowPlayingButtonDown.setAttribute("onclick","vote('"+songID+"', '"+votes+"', choice='vDown')");
// updateAlbumArt(jdata.artist, jdata.album);
}
}
}
}
}
</script>
<!-- Handle up and down voting -->
<script>
function updown(postData) {
const requestOptions = { // Fetch request options
method: 'POST',
headers: {
//'Content-Type': 'application/json' <--breaks CORS preflight
'Content-Type': 'application/x-www-form-urlencoded'
},
body: JSON.stringify(postData)
};
// URL of the server endpoint -- fetch_receiver.js has to be running on lccibackend for all this to work
const serverURL = 'http://lccibackend.com/data';
// Make the fetch request
fetch(serverURL, requestOptions)
.then(response => {
if (!response.ok) { //throw error if fetch() doesn't go through
console.log('The fetch response was not ok');
}
return response.json();
})
.then(data => {
//console.log('Response from server:', data); Delete if no errors.
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
}
function vote(songID, votes, choice) {
let songUpButtons = document.getElementsByClassName("upbutton-"+songID);
let songDownButtons = document.getElementsByClassName("downbutton-"+songID);
let chUp, chDown, chField;
switch(choice) {
case 'vUp':
for (let i = 0; i < songUpButtons.length; i++){
songUpButtons[i].firstElementChild.nextElementSibling.textContent = Number(songUpButtons[i].firstElementChild.nextElementSibling.textContent) + 1;
songUpButtons[i].disabled=true;
}
for (let i = 0; i < songDownButtons.length; i++){
songDownButtons[i].disabled=true;
}
chUp = 1;
chDown = 0;
chField = 'up';
break;
case 'vDown':
for (let i = 0; i < songUpButtons.length; i++){
songUpButtons[i].disabled=true;
}
for (let i = 0; i < songDownButtons.length; i++){
songDownButtons[i].firstElementChild.nextElementSibling.textContent = Number(songDownButtons[i].firstElementChild.nextElementSibling.textContent) + 1;
songDownButtons[i].disabled=true;
}
chUp = 0;
chDown = 1;
chField = 'down';
break;
}
let postData = {
votes: votes,
id: 'null',
song_id: songID,
station: '2',
up: chUp,
down: chDown,
field: chField
};
//Send postData to lccibackend fetch_receiver.js
updown(postData);
}
</script></div>
<div id='recentlyplayed-container' class='container'>
<article id='recentlyplayed' class='content-height right-connected'>
<h3>Recently Played</h3>
<ul id='recentlyplayed-ul'>
<li><abbr class='recentlyplayed-abbr' title="It's a Shame"><h1>It's a Shame</h1></abbr><p><i>Knaves</i></p><p>3:58 pm</p></li><div class='list-gap'></div><li><abbr class='recentlyplayed-abbr' title="Hey, Did I Do You Wrong?"><h1>Hey, Did I Do You Wrong?</h1></abbr><p><i>San Cisco</i></p><p>3:55 pm</p></li><div class='list-gap'></div><li><abbr class='recentlyplayed-abbr' title="Revolution"><h1>Revolution</h1></abbr><p><i>Dr. John</i></p><p>3:52 pm</p></li>
<a href='./playlist.php'><p>View Playlist</p></a>
</ul>
</article>
<template id='recentlyplayed-template'>
<li>
<abbr class='recentlyplayed-abbr'><h1 class='recentlyplayed-title'></h1></abbr>
<p><i class='recentlyplayed-artist'></i></p>
<p class='recentlyplayed-time'></p>
</li>
</template>
<script>
const recentlyPlayedList = document.getElementById('recentlyplayed-ul');
const recentlyPlayedTemplate = document.getElementById('recentlyplayed-template');
function newRecentlyPlayedEntry() { return( recentlyPlayedTemplate.content.cloneNode(true) ); }
function addRecentSong(title, artist, time) {
let recentlyPlayedEntry = newRecentlyPlayedEntry();
recentlyPlayedEntry.querySelector(".recentlyplayed-title").textContent = title;
recentlyPlayedEntry.querySelector(".recentlyplayed-abbr").title = title;
recentlyPlayedEntry.querySelector(".recentlyplayed-artist").textContent = artist;
recentlyPlayedEntry.querySelector(".recentlyplayed-time").textContent = time;
let listGap = document.createElement("div");
listGap.classList.add("list-gap");
recentlyPlayedList.insertBefore(listGap, recentlyPlayedList.firstChild);
recentlyPlayedList.insertBefore(recentlyPlayedEntry, recentlyPlayedList.firstChild);
recentlyPlayedList.lastChild.previousElementSibling.previousElementSibling.remove();
recentlyPlayedList.lastChild.previousElementSibling.previousElementSibling.remove();
}
</script></div>
<div id='nav-trim' class='trim'></div><div id='nav-bg' class='bg'></div>
<div id='aside-trim' class='trim'></div><div id='aside-bg' class='bg'></div>
<div id='main-trim' class='trim'></div><div id='main-bg' class='bg'></div>
</div>
<link rel='stylesheet' href='styles/footer.css' />
<footer>
<!-- <button onClick='showPopUp("pop-up-pawscause")'><p>Paws Cause</p></button> -->
<button onClick='window.open("http://humboldtpawscause.com/", "_blank");'><p>Paws Cause</p></button>
<button onClick='showPopUp("pop-up-lostcoastcommunications")'><p>The LCC Family</p></button>
<p class='reverse-text'>© 1996 - 2025 || KHUM || LCCi ||
<a href='../eeo-report.php'>EEO REPORT</a> •
<a href='../fcc-applications.php'>FCC APPLICATIONS</a> •
<a href='../contest-rules.php'>CONTEST RULES</a> •
<a href='https://publicfiles.fcc.gov/fm-profile/khum' target='_blank'>PUBLIC FILE</a>
</p>
</footer>
<menu id='mobile-menu'>
<div id='mobile-nav-container'>
<img src='images/KHUM-Logo.svg'>
<ul>
<a href='../index.php'><p>Home</p></a>
<a href='../listen-live.php'><p>Listen Live</p></a>
<div class='list-gap'></div>
<a href='../djs.php'><p>DJs</p></a>
<a href='../schedule.php'><p>Schedule</p></a>
<a href='../features.php'><p>Features</p></a>
<a href='../notices.php'><p>Notices</p></a>
<a href='../playlist.php'><p>Playlist</p></a>
<div class='list-gap'></div>
<a href='https://lostcoastoutpost.com/lowdown/' target="_blank"><p>Goodtime Guide</p></a>
<div class='list-gap'></div>
<a href='https://lccswag.myspreadshop.com/khum?collection=YwLBkQzcXf' target="_blank"><p>Swag</p></a>
<a href='../contact.php'><p>Contact</p></a>
<!-- <a href='../advertise.php'><p>Advertise</p></a>
<a href='../jobs.php'><p>Jobs</p></a> -->
</ul>
<p class='reverse-text'>© 1996 - 2025 || KHUM || LCCi<br>
<a href='../eeo-report.php'>EEO REPORT</a><br>
<a href='../fcc-applications.php'>FCC APPLICATIONS</a><br>
<a href='../contest-rules.php'>CONTEST RULES</a><br>
<a href='https://publicfiles.fcc.gov/fm-profile/khum' target='_blank'>PUBLIC FILE</a>
</p>
</div>
<div id='mobile-aside'>
<button id='showMenuButton' onClick='showMenu()' style='background-color:var(--color-lightgreen); border: 2px solid var(--color-mediumgreen); border-radius: 999px;'><img src='../images/mobile-hamburger-button.svg' style='height:50%;'></img></button>
<button id='hideMenuButton' onClick='hideMenu()' style='background-color:var(--color-lightgreen); border: 2px solid var(--color-mediumgreen); border-radius: 999px;' class='hidden'><img src='../images/mobile-x-button.svg' style='height:50%;'></img></button>
<button onClick='window.open("http://humboldtpawscause.com/", "_blank");'><img src="../images/paws-button.svg"></button>
<!-- <button onClick='showPopUp("pop-up-pawscause")'><img src="../images/paws-button.svg"></button> -->
<button onClick='showPopUp("pop-up-lostcoastcommunications")'><img src="../images/lcc-button.svg"></button>
<button onClick="window.location.href='https://www.facebook.com/KHUMradio/';"><img src="../images/facebook-button.svg"></button> <!-- https://www.facebook.com/KHUMradio/ -->
<button onClick="window.location.href='https://www.instagram.com/khumradio/';"><img src="../images/instagram-button.svg"></button> <!-- https://www.instagram.com/khumradio/ -->
<button onClick="window.location.href='https://twitter.com/KHUMradio';"><img src="../images/twitter-button.svg"></button> <!-- https://twitter.com/KHUMradio -->
</div>
</menu>
<div id='pop-up-container' class='container hidden'>
<article id='pop-up-pawscause' class='pop-up hidden' onClick='stopE(event)'>
<h3>Paws Cause</h3>
<button onClick='hidePopUps()' class='close-pop-up'>X</button>
<iframe src="http://humboldtpawscause.com/widget/"></iframe>
<ul>
<li><h1>Humboldt's resource for reuniting<br>lost pets with their people</h1></li>
<a href='http://humboldtpawscause.com/' target="_blank"><p>Visit their site</p></a>
</ul>
</article>
<article id='pop-up-lostcoastcommunications' class='pop-up hidden info-pop-up-container' onClick='stopE(event)'>
<h3>The LCC Family</h3>
<button onClick='hidePopUps()' class='close-pop-up'>X</button>
<div class='info-pop-up'>
<div>
<a href='https://www.advertise.lostcoastcommunications.com/' target='_blank' style='width:100%; margin-bottom: 2rem;'><img src='../images/lcc-logo-wide.svg'></img></a>
</div>
<div>
<a href='https://lostcoastoutpost.com/' target='_blank' style='width:45%;'><img src='../images/LoCO_svg-screen_circle.svg' style='width:100%; margin: 0 0.5rem;'></img></a>
<a href='http://khum.com/' target='_blank' style='width:45%;'><img src='../images/KHUM_svg-screen_circle.svg' style='width:100%; margin: 0 0.5rem;'></img></a>
<a href='http://kslg.com/' target='_blank' style='width:45%;'><img src='../images/KSLG_svg-screen_circle.svg' style='width:100%; margin: 0 0.5rem;'></img></a>
<a href='http://kwpt.com/' target='_blank' style='width:45%;'><img src='../images/KWPT_svg-screen_circle.svg' style='width:100%; margin: 0 0.5rem;'></img></a>
<a href='http://941lounge.com/' target='_blank' style='width:45%;'><img src='../images/KLGE_svg-screen_circle.svg' style='width:100%; margin: 0 0.5rem;'></img></a>
</div>
</div>
</article>
</div>
<script>
function stopE(e) {e.stopPropagation();}
const popUpContainer = document.getElementById("pop-up-container");
const popUpPawsCause = document.getElementById("pop-up-pawscause");
const popUpLostCoast = document.getElementById("pop-up-lostcoastcommunications");
const mobileMenu = document.getElementById("mobile-menu");
const mobileMenuOpenButton = document.getElementById("showMenuButton");
const mobileMenuCloseButton = document.getElementById("hideMenuButton");
function hideMenu() {
mobileMenu.classList.remove('menuTop');
mobileMenuOpenButton.classList.remove('hidden');
mobileMenuCloseButton.classList.add('hidden');
}
function showMenu() {
mobileMenu.classList.add('menuTop');
mobileMenuCloseButton.classList.remove('hidden');
mobileMenuOpenButton.classList.add('hidden');
}
function hidePopUps() {
let children = popUpContainer.children;
for(let i = 0; i < children.length; i++) {
children[i].classList.add('hidden');
}
popUpContainer.classList.add('hidden');
}
function showPopUp(popUpId) {
console.log("showing pop up with id: " + popUpId);
popUpContainer.classList.remove('hidden');
document.getElementById(popUpId).classList.remove('hidden');
}
function showPawsCause(){
popUpPawsCause.classList.remove('hidden');
}
function showLostCoast(){
popUpContainer.classList.remove('hidden');
popUpLostCoast.classList.remove('hidden');
}
popUpContainer.addEventListener('click', () => {hidePopUps();});
</script></body>