I am building an application that downloads a user's now playing data from Spotify and then serves the information as a webpage widget that the user can add to their livestreams to show their viewers what music they are playing in their livestream.
On the backend I have a Flask server that fetches the information and then pushes an update on the frontend via a websocket - this is to avoid having to refresh the page. On the web page I have an Updater.js file that receives the information from the backend and updates the widget to display the new song.
The problem I am having is that I am unable to update the cover image using the Updater.js script. At first I did so by saving the image under the same name and triggering an update on the image by adding a ?t=timestamp to the end of the image url. It worked for awhile, until I updated my Firefox and it stopped working on both Firefox and Chrome.
I changed it so that the Flask server saves the image with a number attached that increments, and then deletes the previous image. I have tried updating the page to display the new image, but it seems that the web page cannot access my server's static files. I have tried different link formats, but I haven't found anything that works so far.
Is there some way that I can access images in the static folder using JavaScript and update it on the page, or will I only be able to achieve this using render_template?
Updater.js:
// This file listens to the backend, and updates the widget when a new song has started playing
// Use this function to update the cover image without refreshing the page
function refresh_image(url)
{
let image = document.getElementById("cover_art");
image.src = url
console.log(image.src)
}
const socket = new WebSocket("ws://" + location.host + "/update");
const image_link = "http://localhost:"
console.log("Communication between server and browser is initialized")
// Listen for data being pushed from the backend
socket.addEventListener("message", package => {
let song = "";
let artists = "";
let port = "";
let image_num = "";
let artists_done = false;
let song_done = false;
let port_done = false;
console.log(package.data)
// Seperate data into variables
for (let i = 0; i < package.data.length; i++)
{
// Artists
if (artists_done == false)
{
while (package.data[i] != ";")
{
artists += package.data[i];
i++;
};
i++;
artists_done = true;
};
// Song
if (song_done == false)
{
while (package.data[i] != ";")
{
song += package.data[i];
i++;
};
i++;
song_done = true;
};
// port
if (port_done == false)
{
while (package.data[i] != ";")
{
port += package.data[i];
i++;
};
i++;
port_done = true;
};
// Image_num
image_num += package.data[i];
};
// Assemble the image src
image_src = "/static/image" + image_num + ".jpg";
// Update widget
refresh_image(image_src)
document.getElementById("song_title").innerHTML = song;
document.getElementById("artists").innerHTML = artists;
console.log("Widget is successfully updated")
});
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="static/style.css">
<title>OBS Music Widget</title>
</head>
<body>
<script src="static/updater.js"></script>
<div id="widget">
<div id="cover"><img id="cover_art" src="{{url_for('static', filename='image.jpg')}}" alt="Song cover image"></div>
<div id="info">
<p id="song_title">{{ song }}</p>
<p id="artists">{{ artists }}</p>
</div>
</div>
</body>
</html>
Related
i am making a meme api webpage
i want the webpage to display a new meme fetched from reddit using reddit api.
i have completed the api and it perfectly shows new memes on every refresh.
i want to embed these images in readme markdown as images
for that i am using
<img src="https://mywebpage.com/">
but i am not getting images when embedded in md.
Here is the code of my webpage-
index.html-
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="script.js"></script>
</head>
<body>
<img src="loading.gif" id="meme" alt="meme didnt load :(" width="256px">
</body>
</html>
Script.js-
// function to fetch memes
function meme () {
let fetchRes = fetch("https://www.reddit.com/r/ProgrammerHumor/hot.json");
fetchRes.then(res => res.json()).then(d => {
// Generates a random number for the random meme
var randomNumber = Math.floor(Math.random() * 26)
// Actually gets the data from the api
var memeImg = d.data.children[randomNumber].data.url
var permalink = d.data.children[randomNumber].data.permalink
var postURL = `https://reddit.com${permalink}`
// setting the text to the data
document.getElementById('meme').src = memeImg;
})
}
// Reload page button
function reloadPage () {
document.location.reload(true)
}
// Calling the meme function
meme()
I'm very new to programming.
I'm working on a school project, and I was given an API that displays random dogs each time the web browser is refreshed. For whatever reason I'm getting a 404 error, but I can see the url changing along with the dog breed within the console. On my HTML page I get the broken image icon where the photo is suppose to load in.
Here is my code:
let xhrdog = new XMLHttpRequest(); //first ajax request, dog photos from api
xhrdog.onreadystatechange = function() {
if (xhrdog.readyState === 4) {
if (xhrdog.status === 200) {
let ajdog = JSON.parse(xhrdog.responseText);
let image = document.createElement('img')
image.src = ajdog //xhrdog.responseText;
let dog = document.getElementById('dog')
dog.appendChild(image);
}
}
}
xhrdog.open('GET', 'https://dog.ceo/api/breeds/image/random');
xhrdog.send();
Any help would be greatly appreciated.
You are very nearly there. It is just that, as you had spotted in the console, you are getting more than the img url back from the service. It is sending a string which you can parse as JSON, as you are doing.
When you have parsed it you actually have an object, not just a single string, in ajdog. One item in that is 'message' and that holds the full url of the dog image. So use ajdog.message rather than just ajdog to put in your img.src.
Here's the snippet with this change:
let xhrdog = new XMLHttpRequest(); //first ajax request, dog photos from api
xhrdog.onreadystatechange = function () {
if (xhrdog.readyState === 4) {
if (xhrdog.status === 200) {
let ajdog = JSON.parse(xhrdog.responseText);
console.log(xhrdog.responseText);//LOOK IN THE CONSOLE TO SEE WHAT IS SENT
let image = document.createElement('img');
image.src = ajdog.message; //xhrdog.responseText;
let dog = document.getElementById('dog');
dog.appendChild(image);
}
}
}
xhrdog.open('GET', 'https://dog.ceo/api/breeds/image/random');
xhrdog.send();
<div id="dog"></div>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img src="" alt="">
<script>
//https://dog.ceo/api/breeds/image/random
async function randomDog(){
//store the promise with url
const result = await fetch('https://dog.ceo/api/breeds/image/random').then((data)=>{
return data.json()
})
//return a object
return result
}
//instanstiate image
const img= document.querySelector('img')
//this function is returning a promise
randomDog().then((data)=>{
//console.log(data)
img.setAttribute('src',data.message)
})
</script>
</body>
</html>
I would label my coding skills as intermediate thus what I am asking may or may not be simple or obvious (I wouldn't know the difference). Also I sincerely thank any and everyone who gives this even an ounce of attention.
My objective is to grab raw song metadata from another server (in which I am a client of) via the jsonp and ajax method. Once I successfully obtain the metadata (Artist, Title & album), I then would like to display it in my website’s page title (please see pics below).
The reason I would like to do this is because from what I could gather via an extensive and worn out research, it seems that most Bluetooth Audio devices are reading the metadata from the page title (browser tab):
Google Music playing in browser
BT Audio player
What I would love to do seems like it should be simple to do, yet I cannot figure away to display "Artist, Title and Album" in my browser like Spotify, Youtube or Google Music does.
My code below is able to pull the raw data, convert it using jsonp and I can successfully push only ONE element from the raw data (IE 'title') by placing it as an ID element. However, how can I push all three (Artist, Title & Album) to the page title?
<!DOCTYPE html>
<html
lang=en
dir="ltr"
class="mobile-web-player"
>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
function update(metadataObj) {
if (metadataObj && metadataObj.m_Item2) {
var title = document.getElementById('title');
title.innerHTML = metadataObj.m_Item2.Title;
var artist = document.getElementById('artist');
artist.innerHTML = 'by ' + metadataObj.m_Item2.Artist;
var album = document.getElementById('album');
album.innerHTML = metadataObj.m_Item2.Album + ' ';
}
}
</script>
<script type="text/javascript">
var stationID = 'X123';
var apiToken = 'X12345';
// refresh MetaData every 5 seconds
function fetchMetadata(stationID, apiToken) {
$.ajax({
type: 'get',
cache: false,
url: "https://listen.samcloud.com/webapi/station/X123/history/npe?token=X12345&callback=update&format=json",
//async: true,
datatype: 'jsonp',
});
}
fetchMetadata(stationID, apiToken);
window.setInterval(function() {
fetchMetadata(stationID, apiToken);
}, 5000);
</script>
<!-- I can successfully send the song's title to my page title via <title id> method -->
<title id="title">My Radio Station</title>
</head>
<body>
</body>
</html>
In your update() function you can call document.title to set the new tab title instead of setting the <title> tag. For example:
function update(metadataObj) {
if (metadataObj && metadataObj.m_Item2) {
var title = document.getElementById('title');
var artist = document.getElementById('artist');
var album = document.getElementById('album');
// If you are using es6
document.title = `Playing ${title} from ${artist} - ${album}`;
// If not using es6
// document.title = 'Playing '+ title + ' from '+ artist +' - album';
}
}
You could change your update function to the following to write Artist, Title, and Album to the web pages title.
function update(metadataObj) {
if (metadataObj && metadataObj.m_Item2) {
var title = document.getElementById('title');
title.innerHTML = metadataObj.m_Item2.Title + ' ' + metadataObj.m_Item2.Album + ' ' + metadataObj.m_Item2.Artist;
}
}
Right now we have a web application that is ran on a local network where the clients run everything in javascript. In order to make sure everything is in sync these clients currently utilize an AJAX request to the server by sending the last "syncId" that it has recieved. The server then responds with an array tree of commands to get this client up to date. This is executed every second and has yet to cause any issues with network bandwith or latency however we are installing a system in a bigger client next month that may push the limits of this method and I am wondering if it is feasible to have the server "PUSH" the sync events to the clients in real time.
srvResponse=httpGet("CDSSync.php?sessionKey="+sessionKey+"&lastUpdate="+lastUpdate);
if(srvResponse!=0){
syncEvents=srvResponse.split(";");
for(var i=0; i<syncEvents.length; i++){
syncItem=syncEvents[i].split(",");
window["syncFunction_"+syncItem[1]](syncItem[2]);
lastUpdate=syncItem[0];
}
}
The above is where my system checks for events to be synced where syncItem[0] is a autoIncrement ID, syncItem[1] is a code for the event being handled and syncItem[2] is a parameter for the function. the httpGet function being called although not in this code is just a function that fetches from the server and returns the response.
Take a look at www.firebase.com, you can set up a push service from javascript clients to all others in minutes. Try the simple tutorial first:
<!doctype html>
<html>
<head>
<script src='https://cdn.firebase.com/js/client/2.2.1/firebase.js'></script>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'></script>
<link rel='stylesheet' type='text/css' href='/resources/tutorial/css/example.css'>
</head>
<body>
<div id='messagesDiv'></div>
<input type='text' id='nameInput' placeholder='Name'>
<input type='text' id='messageInput' placeholder='Message'>
<script>
var myDataRef = new Firebase('https://hbw30ob2a8y.firebaseio-demo.com/');
$('#messageInput').keypress(function (e) {
if (e.keyCode == 13) {
var name = $('#nameInput').val();
var text = $('#messageInput').val();
myDataRef.push({name: name, text: text});
$('#messageInput').val('');
}
});
myDataRef.on('child_added', function(snapshot) {
var message = snapshot.val();
displayChatMessage(message.name, message.text);
});
function displayChatMessage(name, text) {
$('<div/>').text(text).prepend($('<em/>').text(name+': ')).appendTo($('#messagesDiv'));
$('#messagesDiv')[0].scrollTop = $('#messagesDiv')[0].scrollHeight;
};
</script>
</body>
</html>
I am using tokbox trial for video chatting on my website. But the problem i am facing is that ::: User 1 can see and hear User 2 clearly. User 2 can see User 1 clearly, but user 2 couldnt here user 1. And code i am using
<html>
<head>
<title>Monkvyasa | Test</title>
<script src='http://static.opentok.com/webrtc/v2.2/js/opentok.min.js'></script>
<script type="text/javascript">
// Initialize API key, session, and token...
// Think of a session as a room, and a token as the key to get in to the room
// Sessions and tokens are generated on your server and passed down to the client
var apiKey = "xxxxxxx";
var API_KEY=apiKey;
var sessionId = "2_MX40NTAyMDgxMn5-xxxxxxxxxxxxxxxxxxxxHBXZEZoWHN-fg";
var token = "T1==cGFydG5lcl9pZD00NTAyMDgxMiZzaWc9ZDNiYjYyZGE2NTBkYmUzMTUyNGNjNDZjYzAzY2NjZWRhZGY3NTEyZjpyb2xlPW1vZGVyYXRvciZzZXNzaW9uX2lkPTJfTVg0xxxxxxxxxxxxxxxxxxxxxxxxBNM1JsYlRCUFdXWkhSSEJYWkVab1dITi1mZyZjcmVhdGVfdGltZT0xNDEzMjAwMjIxJm5vbmNlPTAuMTk1MzEwNTU0MzY1MjEwNSZleHBpcmVfdGltZT0xNDEzMjg0MzY5";
// Initialize session, set up event listeners, and connect
var session;
var connectionCount = 0;
function connect() {
session = TB.initSession(sessionId);
session.addEventListener("sessionConnected", sessionConnectHandler);
session.addEventListener('streamCreated', function(event){
e=event;
console.log(e);
for (var i = 0; i < event.streams.length; i++) {
streams = event.streams;
// Make sure we don't subscribe to ourself
alert("new user connected :)");
if (streams[i].connection.connectionId == session.connection.connectionId) {
return;
}
// Create the div to put the subscriber element in to
var div = document.createElement('div');
div.setAttribute('id', 'stream' + streams[i].streamId);
document.body.appendChild(div);
session.subscribe(streams[i], div.id);
}
});
session.connect(API_KEY, token);
}
function sessionConnectHandler(event) {
var div = document.createElement('div');
div.setAttribute('id', 'publisher');
var publisherContainer = document.getElementById('publisherContainer');
// This example assumes that a publisherContainer div exists
publisherContainer.appendChild(div);
var publisherProperties = {width: 500, height:450};
publisher = TB.initPublisher(API_KEY, 'publisher', publisherProperties);
session.publish(publisher);
}
function disconnect() {
session.disconnect();
}
connect();
</script>
</head>
<body>
<h1>Monkvysa videofeed test!</h1>
<input style="display:block" type="button" id="disconnectBtn" value="Disconnect" onClick="disconnect()">
<table>
<tr>
<td> <div id="publisherContainer"></div></td> <td><div id="myPublisherDiv"></div></td>
</tr>
</table>
</body>
</html>
Thanks in advance
The code looks mostly correct, except you're using an older form of the 'streamCreated' event handler. In the latest version of the API, you no longer need to iterate through the event.streams array, you actually get one invocation of the event handler per stream.
In order to further dig into the problem, would you be able to add a link to a gist containing all the console logs? To make sure the logs are being outputted, you can call OT.setLogLevel(OT.DEBUG); at the beginning of the script.
Lastly, the newer API is greatly simplified and you could save yourself the effort of DOM element creation and iteration. What you have implemented is basically identical to our Hello World sample applications, which you can find in any of our server SDKs, for example here: https://github.com/opentok/opentok-node/blob/61fb4db35334cd30248362e9b10c0bbf5476c802/sample/HelloWorld/public/js/helloworld.js