Using Shoutcast, Display Now Playing Album Art - javascript

I have a small 70x70 box in an HTML player I built where I wish to place in the album artwork to coincide with my now playing information from my shoutcast server. Is there a way, using the artist-song information the shoutcast server provides, that I can search a web service (amazon/last.fm) and have it place the (most likely) album cover there?
Here is the JS code I'm using now:
jQuery(document).ready(function() {
pollstation();
//refresh the data every 30 seconds
setInterval(pollstation, 30000);
});
// Accepts a url and a callback function to run.
function requestCrossDomain( callback ) {
// Take the provided url, and add it to a YQL query. Make sure you encode it!
var yql = 'http://s7.viastreaming.net/scr/yql.php?port='+port+'&username='+user+'&callback=?';
// Request that YSQL string, and run a callback function.
// Pass a defined function to prevent cache-busting.
jQuery.getJSON( yql, cbFunc );
function cbFunc(data) {
// If we have something to work with...
if ( data ) {
// Strip out all script tags, for security reasons. there shouldn't be any, however
data = data[0].results.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
data = data.replace(/<html[^>]*>/gi, '');
data = data.replace(/<\/html>/gi, '');
data = data.replace(/<body[^>]*>/gi, '');
data = data.replace(/<\/body>/gi, '');
// If the user passed a callback, and it
// is a function, call it, and send through the data var.
if ( typeof callback === 'function') {
callback(data);
}
}
// Else, Maybe we requested a site that doesn't exist, and nothing returned.
else throw new Error('Nothing returned from getJSON.');
}
}
function pollstation() {
requestCrossDomain(function(stationdata) {
var lines = stationdata.split('|+|');
jQuery('#sname').html(lines[0]);
jQuery('#sgenre').html(lines[1]);
jQuery('#clisteners').html(lines[2]);
jQuery('#bitrate').html(lines[3]);
jQuery('#artist_block').html('' + jQuery.trim(lines[4]) + '');
var prev = lines[5].split('+|+');
jQuery('#np_table').html('');
for (var i = 0; i < 8; i++)
{
if(typeof(prev[i]) != 'undefined')
{
jQuery('#np_table').append('<tr>'+'<td>'+ prev[i] + '</td>'+'</tr>');
jQuery("tr:odd").css("background-color", "#154270");
}
}
jQuery('#mplayers').html(lines[6]);
jQuery('#mobile').html(lines[7]);
jQuery();
} );
}
and here's the HTML:
<div id="col_left">
<div id="now_playing">
<div id="np_ribbon"><span>Now Playing</span></div>
<div id="np_img"><img name="nowplayingimage" src="" width="70" height="70" alt="album cover" style="background-color: #000000" /></div>
<div id="artist_block">
<span class="artist_name"><strong>Artist:</strong> Artist name</span><br />
<span class="song_name"><strong>Song:</strong> "song title"</span><br />
<span class="album_name"><strong>Album:</strong> Album Name</span> <br />
</div>
<div id="player">
<div id="container"><script type="text/javascript" src="http://shoutcast.mixstream.net/js/external/flash/s7.viastreaming.net:8790:0:::999999:::1"></script></div>
</div>
</div><!-- end now playing -->
<div id="recent">
<div class="table_title">Recently Played</div>
<table id="np_table">
</table>
</div><!-- end recent -->
</div><!-- end col_left -->
So naturally, I want the image to appear where the div "np_img" is. Any ideas what code to use and how to implement it. You can probably tell by my code that I'm an amateur so please be clear and gentle. :)

You can use the iTunes search API. It supports JSONP so you can use it directly within your webpage, without worrying about cross-domain.
As #Brad mentioned, iTunes has terms of use. In particular:
(...) provided such Promo Content: (i) is placed only on pages that promote
the content on which the Promo Content is based; (ii) is proximate to
a "Download on iTunes" or "Available on the App Store" badge (as
approved by Apple) that acts as a link directly to pages within iTunes
or the App Store where consumers can purchase the promoted content. (...)
Here's how the code looks like:
​function refreshArtwork(artist, track) {
$.ajax({
url: 'http://itunes.apple.com/search',
data: {
term: artist + ' ' + track,
media: 'music'
},
dataType: 'jsonp',
success: function(json) {
if(json.results.length === 0) {
$('img[name="nowplayingimage"]').attr('src', '');
return;
}
// trust the first result blindly...
var artworkURL = json.results[0].artworkUrl100;
$('img[name="nowplayingimage"]').attr('src', artworkURL);
}
});
}

Related

ReactJs doesn't render second map function but when i update the file it does

So, I'm fetching data from an API and using states. At the beginning, I don't get data from API and render the page with using the states with the data I wrote in the file. (I'm trying to say that I'm using static data at the first load). It works well. No problem at all. Then, when I get an input from user I connect with the API, do all the fetching and stuff and update the states. Everything seems normal. Data is received from API, states are updated, no error on console, first map function is rendered etc. but the second map function isn't. But surprisingly, when I change anything in the file and save it (you know that live server updates the page but doesn't reload), it applies the changes that I've done, and it also renders the second map function with using data I received earlier.
My first map function is this:
<div id="hourlyForecast">
{ weatherData.hourly.map((item, index) => {
/* ----- I'm getting a long string from API and these 2 lines are to get the part that i need from that string ------ */
let startFrom = item.dt_txt.length - 8;
let iNeed = item.dt_txt.toString().substr(startFrom, 5);
return (
<div className="hourly" key={index}>
<div className="hour">{iNeed}</div>
<div className="image">
<img
src={`/icons/${item.weather[0].icon}.png`}
alt="weather-icon"
/>
</div>
<div className="degrees">
{Math.round(item.main.temp)}°C
</div>
<div className="wind">
<img
src="wind.png"
alt="wind-icon"
style={{ transform: `rotate(${item.wind.deg}deg)` }}
/>{
{item.wind.speed} m/s
</div>
</div>
)
})
}
</div>
It is working, I guess. After that, I have this second map function:
<div id="daily">
{weatherData.daily.map((item, index) => {
return (
<div className="daily" key={index}>
<div className="day">
/* ------ Api gives me timestamp and this function returns me the day in human words :) ----- */
{giveMeDay(item.dt * 1000)}
</div>
<div className="dailyDegrees">
{Math.round(item.temp)}°C
</div>
<div className="dailyDesc">
{item.desc}
</div>
<div className="img">
<img src={`./icons/${item.icon}.png`} alt="weather-icon" />
</div>
</div>
);
})
}
</div>
It is also working, it should. I mean, they are not that complex.
So, all with that, here are what happens:
At first load I use static data, and it renders the second map function
(IMAGE) Rendered component with static data
When I enter an input it triggers the API Call, and it should re-render, but it does not (IMAGE) Empty Component even though API Call works
But when I change anything in the file after the API Call and save it, live server updates and the second map function is rendered. Let's say I change "°C" in the second map function with "°F" and save it. Then, everything works. (IMAGE) File updated without page being reloaded
I guess that's all I can say. I just don't understand the problem. Surely would appreciate any help.
Here is the part that I do the API stuff: (It can be a mess 'cause gotta do 3 API calls and didn't want to use async function due to my lack of experience with it)
var datam = {};
const work = (e) => {
e.preventDefault();
try {
fetch(
`${ApiUrl}weather?q=${e.target.cityName.value}&appid=${ApiKey}&units=metric&lang=en`
)
.then((data) => {
return data.json();
})
.then((gelen) => {
console.log(gelen);
if (gelen.cod === 200) {
datam = {
degrees: Math.round(gelen.main.temp),
description: gelen.weather[0].description,
feels_like: gelen.main.feels_like,
city: `${e.target.cityName.value}, ${gelen.sys.country}`,
min: gelen.main.temp_min,
max: gelen.main.temp_max,
icon: gelen.weather[0].icon,
lat: gelen.coord.lat,
lon: gelen.coord.lon,
};
} else {
alert("Couldn't get the data");
}
})
.then(() => {
console.log(datam);
fetch(
`${ApiUrl}forecast?lat=${datam.lat}&lon=${datam.lon}&units=metric&appid=${ApiKey}&lang=en`
)
.then((fivedays) => fivedays.json())
.then((veri) => {
console.log(veri);
datam.hourly = [];
if (veri.cod === "200") {
for (let i = 0; i < 8; i++) {
datam.hourly[i] = veri.list[i];
}
console.log(datam);
}
})
.then(() => {
datam.daily = [];
fetch(
`${ApiUrl}onecall?lat=${datam.lat}&lon=${datam.lon}&exclude=current,hourly,minutely,alerts&units=metric&appid=${ApiKey}&lang=en`
)
.then((donus) => donus.json())
.then((yanit) => {
console.log(yanit);
for (let i = 0; i < 6; i++) {
datam.daily[i] = {};
datam.daily[i]["temp"] = yanit.daily[i + 1].temp.day;
console.log("1");
datam.daily[i].desc =
yanit.daily[i + 1].weather[0].description;
datam.daily[i].icon = yanit.daily[i + 1].weather[0].icon;
datam.daily[i].dt = yanit.daily[i + 1].dt;
}
});
})
.then(() => {
console.log(datam);
// ------------ weatherData is the main state I'm using -----------
setWeatherData(datam);
// ------------ searched state is the important for only the first load. If they do the search i change what is being rendered -----------
setSearched(true);
});
//
});
} catch (error) {
alert(error);
}
};
The problem is this here: (VIDEO) Everything Works but doesn't appear until VS Code recompile

Add a javascript result to an image url

So what im trying to do is query a Minecraft server with javascript, and with the response i get back with the api, i want to grab the .playerlist and put the response in this url (https://cravatar.eu/avatar/ {name} /100.png) for each person connected
If someone knows a better way to achieve this, i would very much appreciate your input!
Im also pretty new to javascript, so not fully know what im doing :/
Heres the HTML that i have (i know it may be messy, its also not fully my code)
<div class="card"> <div class="icon"><img src="https://cdn.worldvectorlogo.com/logos/minecraft-1.svg"></div><div class="header">
<div class="image"> <img src="https://res.cloudinary.com/lmn/image/upload/e_sharpen:100/f_auto,fl_lossy,q_auto/v1/gameskinnyc/u/n/t/untitled-a5150.jpg" alt="" /> </div>
<h2>Server Status</h2>
</div>
<div id="rest">Loading...</div>
<img src="https://cravatar.eu/avatar/" $face "/>
</div>
And here is the javascript
//Query api at this address
var url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, function(r) {
//data is the JSON string
if(r.error){
$('#rest').html('Server Offline.');
return false;
}
var p1 = '';
if(r.Players > 0 ){ p1 = '<br>'+r.Playerlist; }
// Text to display below
$('#rest').html('Total Online: '+r.Players+p1);
// Trying to add playerlist to html url
$('#face').html+p1;
});
Since you've pasted jQuery code, I'll submit my answer in jQuery. However, I do recommend you learn primitive JavaScript and not focus your attention just on jQuery... it's become something of a meme on StackOverflow.
Starting off, you really should be wrapping your code in $(document).ready this'll only run the code when the page has loaded.
$(document).ready(() => {
// The document is ready, let's run some code!
});
Then add your AJAX request as normal inside this bracket.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
});
});
Okay, whilst writing this, I checked the URL provided by OP and saw that it was timing out so I've grabbed a sample response from the Minetools' documentation.
{
"MaxPlayers": 200,
"Motd": "A Minecraft Server",
"Playerlist": [
"Connor",
"Kamil",
"David"
],
"Players": 3,
"Plugins": [],
"Software": "CraftBukkit on Bukkit 1.8.8-R0.2-SNAPSHOT",
"Version": "1.8.8",
"status": "OK"
}
So in your JSON response, you can see that Playerlist is a array which can contain multiple things in one variable. You can also iterate through an array, which is what we'll be doing to build the image URLs.
We iterate through an array using forEach.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
response.Playerlist.forEach(playerName => {
console.log(playerName);
});
});
});
//Console:
//Connor
//Kamil
//David
Now that we're iterating through the player list we can start assembling the URLs for these images and adding them to your document's body.
I've cleaned up your HTML, take note of the new div#user-images I've added. This'll be the place where jQuery will add your images from the forEach loop.
<div class="card">
<div class="icon">
<img src="https://cdn.worldvectorlogo.com/logos/minecraft-1.svg">
</div>
<div class="header">
<div class="image">
<img src="https://res.cloudinary.com/lmn/image/upload/e_sharpen:100/f_auto,fl_lossy,q_auto/v1/gameskinnyc/u/n/t/untitled-a5150.jpg" alt="" />
</div>
<h2>Server Status</h2>
</div>
<!-- This div tag will need to hide when there is no error, or say when there is. -->
<div id="rest">Loading...</div>
<!-- The user images will be added inside this div. -->
<div id="user-images"></div>
</div>
Now we have our HTML ready we can start using the jQuery function appendTo to add elements into our div#user-images.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
response.Playerlist.forEach(playerName => {
$(`<img src="https://cravatar.eu/avatar/${playerName}" />`).appendTo("#user-images");
});
});
});
Your div#user-images should start filling up with the images of players from the Playerlist array.
I noticed you added a simple way of showing whether or not there's an error with the API. We can interact with div#rest to show/hide or change text depending on the success of the response.
$(document).ready(() => {
let url = "https://api.minetools.eu/query/play.aydaacraft.online/25565";
$.getJSON(url, response => {
if(response.error){
$("#rest").html("The server is offline!");
}else{
//There is no error, hide the div#rest
$("#rest").hide();
response.Playerlist.forEach(playerName => {
$(`<img src="https://cravatar.eu/avatar/${playerName}" />`).appendTo("#user-images");
});
}
});
});
And that's it really. I hope this gives you some understanding of arrays, and iterating through them, as well as some DOM functions from jQuery.

If HTML response is null, display alternate content

My api call returns html, but if that html is empty e.g. I get a console html response of "", I want to display a default message using knockout. So I'm guessing that it needs to recognise that "" is empty and then display my alternate content.
View model -
var MyText = ko.observable();
var company = shell.authenticatedCompany();
hazibo.helpTextGet(company.name, company.userName, company.password).then(function (data) {
MyText(data);
});
return {
MyText: MyText
};
View -
<section class="help-text">
<div class="flex-container">
<div class="flex-item" data-bind="html: MyText">This is my alternate message if the html response is ""</div>
</div>
</section>
There are a few ways you could go about it. Personally I like to keep as much code out of the markup as possible so I would check your response data in the api callback and set it there. No need to create messy looking data bindings if you just update the observable appropriately.
hazibo.helpTextGet(company.name, company.userName, company.password).then(function (data) {
if(!data) {
MyText("This is my alternate message...");
}else{
MyText(data);
}
});
If you need to preserve what the api call actually returned you could place the logic in a computed instead, and bind to that.
One way to achieve this is to use a computed observable to determine which set of html to display:
https://jsfiddle.net/dw1284/ucnewzwo/
HTML:
<section class="help-text">
<div class="flex-container">
<div class="flex-item" data-bind="html: ItemHtml()"></div>
</div>
</section>
JavaScript:
function ViewModel() {
var self = this;
// Html populated from API call
self.MyText = ko.observable('');
// Default Html
self.Default = ko.observable('This is my alternate message if the html response is ""');
// Computed observable chooses which HTML to display (bind this to view)
self.ItemHtml = ko.computed(function() {
if (!self.MyText() || self.MyText() === '') {
return self.Default();
} else {
return self.MyText();
}
});
}
ko.applyBindings(new ViewModel());

JS events source detection

I'm working on a part of my web site where people can vote on publications, I have many in the same page, and next every publication there are two images one to agree and the other to disagree. I want to change the images, so when someone votes, whether agree or not, the image changes to say he already voted.
Here's my code:
JPS:
<logic:iterate id="comment" name="Liste_Comments" scope="request">
<html:img src="pages/images/ok.png" alt="Vote pour!" paramId="code" paramName="comment" paramProperty="code" onclick="voterComment('pour');"/>
<html:img src="pages/images/ko.png" alt="Vote contre!" paramId="code" paramName="comment" paramProperty="code" onclick="voterComment('contre');"/>
<bean:write name="comment" property="libelle" />
<bean:write name="comment" property="subject" />
<br>
</logic:iterate>
Script:
<script type="text/javascript">
function voterComment(vote) {
var url = "<%=request.getContextPath()%>/VoteComment.do";
new Ajax.Request(url, {
parameters: {vote: vote},
onSuccess: function(transport, json) {
if (json.error) {
alert(json.error);
}
else{
window.event.srcElement.src = "pages/images/photo.jpg";
}
}
});
}
</script>
I have a problem to access to the image that was clicked!!
Thanks guys, in advance, for your great helping :)
You can change you html to send the value of this to the click handler. This will contain a reference to the source element - in this case the image that was clicked.
<html:img ... paramProperty="code" onclick="voterComment(this, 'pour');"/>
Javascript:
function voterComment(sourceImage , vote) {
var url = "<%=request.getContextPath()%>/VoteComment.do";
new Ajax.Request(url, {
parameters: {vote: vote},
onSuccess: function(transport, json) {
if (json.error) {
alert(json.error);
}
else{
sourceImage.src = "pages/images/photo.jpg";
}
}
});
}

one json-request to multiple DOM-destinations - how?

I'm having a "list" that I want to populate with a background-json request.
Items have different headings and traffic should be minimal (mobile webapp),
DOM-structure something like:
<div id="deckStart">
<div id="cardContacts">
<h2>Contacts</h2>
<div id="cardContactsContent">nothing here until JSON</div>
</div>
<div id="cardTodo">
<h2>To do</h2>
<div id="cardTodoContent">nothing here until JSON</div>
....
//EDIT
OK, this works:
x$(window).on('load', function() {
x$(window).xhr('json.txt', {
async: true,
callback: function() {
var t = eval('(' + this.responseText + ')');
for(var key in t) {
var obj = t[key];
x$('#' + key).html('inner',obj);
}
}
});
but why doesn't JSON.parse work on chrome? Eval seems dirty..
//end edit
What would be the most efficient way to populate the respective content-divs with one single JSON-request?
Temp load into JS-array?
Temp load into hidden DOM-part?
Some regexp-trick or other I cannot think of?
The network stability / speed is unreliable.
regards,
Can you get jQuery on there? You could do it in a heartbeat with jQuery...

Categories

Resources