Using Spotify webAPI to play random album of artist (ID) - html

here is my "little" project, as I am not a developer myself please don't blame me for my stupid questions.
I want to create a "audio book machine".
I want to use a Website, that shows several Artists of audiobooks. If I click on one artist, a random audiobook of the clicked artist should be played.
I had a look at this code example: http://jsfiddle.net/qlmhuge/t7a1sh4u/
// find template and compile it
var templateSource = document.getElementById('results-template').innerHTML,
template = Handlebars.compile(templateSource),
resultsPlaceholder = document.getElementById('results'),
playingCssClass = 'playing',
audioObject = null;
var fetchTracks = function (albumId, callback) {
$.ajax({
url: 'https://api.spotify.com/v1/artists/61qDotnjM0jnY5lkfOP7ve/albums/',
success: function (response) {
callback(response);
}
});
};
var searchAlbums = function (query) {
$.ajax({
url: 'https://api.spotify.com/v1/search',
data: {
q: 'artist:' + query,
type: 'album',
market: "DE"
},
success: function (response) {
resultsPlaceholder.innerHTML = template(response);
}
});
};
results.addEventListener('click', function(e) {
var target = e.target;
if (target !== null && target.classList.contains('cover')) {
if (target.classList.contains(playingCssClass)) {
audioObject.pause();
} else {
if (audioObject) {
audioObject.pause();
}
fetchTracks(target.getAttribute('data-album-id'), function(data) {
audioObject = new Audio(data.tracks.items[0].preview_url);
audioObject.play();
target.classList.add(playingCssClass);
audioObject.addEventListener('ended', function() {
target.classList.remove(playingCssClass);
});
audioObject.addEventListener('pause', function() {
target.classList.remove(playingCssClass);
});
});
}
}
});
searchAlbums('TKKG');
but I cannot figure out how to change it to play a random album by one artist.
The artist will be defindes by the spotify ID so that the artist ist the correct one.
Can someone help me out with my problem? What else info is needed to complete my goal?
I would be very thankful if one can give me a hint, or whatever, to get to the right direction.
Best regards,
goeste

You have to modify your fetchTracks function here:
var fetchTracks = function (albumId, callback) {
$.ajax({
url: 'https://api.spotify.com/v1/albums/' + albumId,
success: function (response) {
callback(response);
}
});
};
jsFiddle link

I got a little closer to the finish line... well, I guess:
I found the following on GitHub:
var SpotifyWebApi = require('spotify-web-api-node');
var spotifyApi = new SpotifyWebApi();
// credentials are optional
// var spotifyApi = new SpotifyWebApi({
// clientId : '',
// clientSecret : '',
// redirectUri : ''
// });
// Get albums by a certain artist
spotifyApi.getArtistAlbums('3meJIgRw7YleJrmbpbJK6S')
.then(function(data) {
console.log('Artist albums', data.body);
}, function(err) {
console.error(err);
});
However, I only get 20 albums out of 35. I need to increase the limit. The max limit is 50, as I read on the developer site of Spotify. As I only need to get one out of the 35 albums (randomly), how can I implement the randomize function and also play function in order to work?
I am still figuring out how to create a link from the results to show on a website with node.js.
Best regards, and thank you in advance for any assistance/help!
-goeste

Related

variable insert to a blink function

I'm new to HTML and ajax. I'm trying to insert a ip list from flask , to the ajax and trigger the js function to blink.
but somehow I can't find a way to insert the ip variable (response[i]) into the function value column in a right way.
it is to trigger the blink on the required ip tab in html.
function ajaxForm(){
// var form= new FormData(document.getElementById("myform2"));
var data = {"name":"John Doe"}
$.ajax({
url:"{{ url_for('Submit_form') }}",
type:"post",
contentType:'application/json',
data:JSON.stringify(data),
dataType: "json",
processData:false,
// async: false
success:function(response){
// alert(response)
if (response == "success")
{alert("Success !!!" );}
else {
for(i in response)
{
BLINK(response[i]);
}
}
},
// #time out 也进入 error
error:function(e){
// alert(e.)
alert("Failed submit form trigger!!!!");
}
})
}
<script type="text/javascript">
function BLINK(){
var t = null;
function blink() {
var obj = $('input[id="IP"][value=response[i]]') . <---- here
obj.addClass("blink-class");
t = setTimeout(function () {
obj.removeClass("blink-class");
t = setTimeout(function () {
blink(IP);
}, 550);
}, 550);
}
blink(IP);
t = setTimeout(function () {
clearTimeout(t);
}, 5000);
}
At first, you shoul always provide the HTML code too :) because now we dont know if the issue is there.
So let's try to solve the problem blindly :)
if i see this correctly, you just go wrong on the element and make it even more complicated than it is since you're using jquery, because if u have an ID on your elem, check this out:
// change this:
var obj = $('input[id="IP"][value=response[i]]') . <---- here // .. is your problem :)
obj.addClass("blink-class");
// with the dot you add this obj, which is it self, on it self :) that cant work :)
// you can try:
var obj = $('input[value="' + response[i] + '"]') // with NO dot and no fixed ID!
obj.addClass("blink-class");
// or try this
var obj = $('#' + response[i]);
obj.addClass("blink-class");
// and put the IP into the ID attraktion of your input element.
Second Problem is you are using an undefined variable "ID":
blink(IP); // in your timeout function
but you didnt declare this var, so if i understand your code right then your response[i] should be the IP?
Your function should look like this:
function BLINK(IP) { // <-- here you need the ip as parameter for your: BLINK(response[i]) from ajax
var t = null;
function blink() {
var obj = $('#' + IP) // and put IP in the id from input
obj.addClass("blink-class")
t = setTimeout(function () {
obj.removeClass("blink-class");
t = setTimeout(function () {
blink(IP);
}, 550);
}, 550);
}
blink(IP);
t = setTimeout(function () {
clearTimeout(t);
}, 5000);
}
try this, if its doesnt work please provide complete html and your css code too, also we could need an eventually error message from console, you can see that by pressing F12 in FireFox or Chrome and then switch to the console tab, press F5 then to reload the page and see errors, post it too please.
Or try out my jsfiddle for you:
https://jsfiddle.net/AIQIA/tjg659sr/17/
You have to remove dots from your IP and put it as id in your elem you wants get to blink, further you need to remove the dots from the response[i] or in your php code before, easy use $ip = preg_replace('/\./','',$ip);
Or use this to use only the complete IP in your input value, then you dont need to remove dots:
https://jsfiddle.net/AIQIA/tjg659sr/21/
greetz Toxi

Pass a random JSON pair into an aframe component

Edit 3: The code is now working across numerous objects (thanks to Noam) and he has also helped in getting the random function working alongside it. I'll update the code in the question once its implemented.
Edit 2: I've taken #Noam Almosnino's answer and am now trying to apply it to an Array with numerous objects (unsuccessfully). Here's the Remix link. Please help!
Edit: I've taken some feedback and found this page which talks about using a JSON.parse function. I've edited the code to reflect the new changes but I still can't figure out exactly whats missing.
Original: I thought this previous answer would help in my attempt to parse a json file and return a random string and its related pair (e.g Title-Platform), but I couldn't get it to work. My goal is to render the output as a text item in my scene. I've really enjoyed working with A-frame but am having a hard time finding documentation that can help me in this regard. I tried using the following modified script to get text from the Json file...
AFRAME.registerComponent('super', { // Not working
schema: {
Games: {type: 'array'},
jsonData: {
parse: JSON.parse,
stringify: JSON.stringify}
},
init: function () {
var el = this.el;
el.setAttribute('super', 'jsonData', {src:"https://cdn.glitch.com/b031cbf1-dd2b-4a85-84d5-09fd0cb747ab%2Ftrivia.json?1514896425219"});
var hugeArray = ["Title", "Platform",...];
const el.setAttribute('super', {Games: hugeArray});
el.setAttribute('position', {x:-2, y:2, z:-3});
}
});
The triggers are also set up in my html to render the text. My code is being worked on through glitch.com, any help will be much appreciated!
To load the json, I think you need to use an XMLHttpRequest (as Diego pointed out in the comments), when that's loaded, you can set the text through setAttribute.
Here's a basic example on glitch:
https://glitch.com/edit/#!/a-frame-json-to-text
On init it does the request, then when done, it set's the loaded json text onto the entity.
AFRAME.registerComponent('json-text-loader', {
schema: {},
init: function () {
var textEntity = document.querySelector('#text');
var url = 'json/text.json';
var request = new XMLHttpRequest();
request.open( 'GET', url, true );
request.addEventListener( 'load', function ( event ) {
var jsonText = JSON.parse( event.target.response )
textEntity.setAttribute("value", jsonText.text)
} );
request.send( null );
}
});
Updated version: https://glitch.com/edit/#!/peppermint-direction
AFRAME.registerComponent('json-text-loader', {
schema: {},
init: function () {
var textEntity = document.querySelector('#text');
var url = 'json/text.json';
var request = new XMLHttpRequest();
request.open( 'GET', url, true );
request.addEventListener( 'load', function ( event ) {
var games = JSON.parse( event.target.response ).games;
// Get a random game from the list
var randomGame = games[Math.floor(Math.random()*games.length)];
// Get the next game if it's available
var nextGame = null
if (games.indexOf(randomGame) < games.length - 1) {
nextGame = games[games.indexOf(randomGame) + 1]
}
// Build the string for the games
var gameInfo = randomGame.Title + '\n' + randomGame.Developer + '\n\n'
if (nextGame != null) {
gameInfo += nextGame.Title + '\n' + nextGame.Developer + '\n'
}
textEntity.setAttribute("value", gameInfo);
var sceneEl = document.querySelector('a-scene');
sceneEl.querySelector('a-box').setAttribute('material', {src:"https://cdn.glitch.com/4e63fbc2-a1b0-4e38-b37a-9870b5594af8%2FResident%20Evil.jpg?1514826910998"});
});
request.send( null );
}
});

Button for markupCore extension not showing in dockingpanel

I have followed Philippe Leefsma's tutorial on how to implement the markup tool, but without any luck. Link here: http://adndevblog.typepad.com/cloud_and_mobile/2016/02/playing-with-the-new-view-data-markup-api.html
and here: https://developer.api.autodesk.com/viewingservice/v1/viewers/docs/tutorial-feature_markup.html
I get errors that I need to include requireJS, but I don't want to use it. So instead I used this script in my html file:
<script src="https://autodeskviewer.com/viewers/2.2/extensions/MarkupsCore.js">
I don't know if this is the right way to go? I get no errors in the console, but the markup button doesn't show up in the dockingpanel.
This is my code for loading the extension in the viewer:
viewerApp = null;
function initializeViewer(containerId, urn, params) {
function getToken(url) {
return new Promise(function (resolve, reject) {
$.get(url, function (response) {
resolve(response.access_token);
});
});
}
var initOptions = {
documentId: 'urn:' + urn,
env: 'AutodeskProduction',
getAccessToken: function (onGetAccessToken) {
getToken(params.gettokenurl).then(function (val) {
var accessToken = val;
var expireTimeSeconds = 60 * 30;
onGetAccessToken(accessToken, expireTimeSeconds);
});
}
}
function onDocumentLoaded(doc) {
var rootItem = doc.getRootItem();
// Grab all 3D items
var geometryItems3d =
Autodesk.Viewing.Document.getSubItemsWithProperties(
rootItem, { 'type': 'geometry', 'role': '3d' }, true);
// Grab all 2D items
var geometryItems2d =
Autodesk.Viewing.Document.getSubItemsWithProperties(
rootItem, { 'type': 'geometry', 'role': '2d' }, true);
// Pick the first 3D item otherwise first 2D item
var selectedItem = (geometryItems3d.length ?
geometryItems3d[0] :
geometryItems2d[0]);
var domContainer = document.getElementById('viewerContainer');
var config = { extensions: ["Autodesk.Viewing.MarkupsCore"] };
// GUI Version: viewer with controls
var viewer = new Autodesk.Viewing.Private.GuiViewer3D(domContainer, config);
viewer.loadExtension("Autodesk.Viewing.MarkupsCore");
viewer.initialize();
viewer.loadModel(doc.getViewablePath(selectedItem));
var extension = viewer.getExtension("Autodesk.Viewing.MarkupsCore");
viewerApp = viewer;
}
function onEnvInitialized() {
Autodesk.Viewing.Document.load(
initOptions.documentId,
function (doc) {
onDocumentLoaded(doc);
},
function (errCode) {
onLoadError(errCode);
})
}
function onLoadError(errCode) {
console.log('Error loading document: ' + errCode);
}
Autodesk.Viewing.Initializer(
initOptions,
function () {
onEnvInitialized()
})
}
Any help is highly appreciated!
Unfortunately there has been a few changes to the API since I wrote that blog post. The MarkupCore.js is now included in the viewer3D.js source, so you don't need to reference any extra file or use requireJS if you use the latest version of the viewer API.
Keep in mind that this is an API-only feature, so even after loading the markup extension, you won't get any UI out of the box. You have to implemented it yourself, for example create a dialog with buttons that may eventually create markups by calling the API.
Some of the code from my blog post may still be valid and give you an idea about what you need to do.
Hope that helps.

Combining AJAX/JSON call with iScroll

I am making a list form my JQM site from JSON data and are having no trouble with this. Now I want to add iScroll to the scene and if I use static list it works just fine, but when I get the list from JSON it won't fetch how many li I have and I can not scroll down to the bottom if I have lets say 20 li. I dont know how to combine my javascript so here is what i got so far [EDIT]:
var myScroll;
$(document).on('pageshow', function (){
var userid=1,
dataUrl = 'http://duefmun.dk/html5data/playermenu.php?callback=?&userid=' + userid,
dataCallback = function (data) {
var content = [];
$.each(data, function (i, val) {
content.push(val.list);
});
$('#games').html(content.join('')).listview('refresh');
},
fetchData = function () {
myScroll = new iScroll('wrapper');
if (myScroll.isReady()){
$.getJSON(dataUrl, dataCallback);
}
};
fetchData();
setInterval(fetchData, 20000);
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', function () { setTimeout(loaded, 200); }, false);
});
Hope this makes sense and any help is appreciated :-)
EDIT: I have edited the post with something I think should be right but it is still not working? Please help :-/
My suggestion is that you should create iScroll after you get your data. So, your code should be:
...
fetchData = function () {
if (myScroll.isReady()){
$.getJSON(dataUrl, dataCallback);
}
};
fetchData();
setInterval(fetchData, 20000);
myScroll = new iScroll('wrapper');
...

Load JSON file to Backbone collection

Hi I'm looking for proper solution to load JSON to Backbone collection. I saw a lot of post with this problem, but I still don't understand how to do it correctly.
For example, Could You explain me please why this project doesn't work?
http://blog.joelberghoff.com/2012/07/22/backbone-js-tutorial-part-1/
Edit:
When I look at the results using Firebug, it shows me an empty object, collection is empty.
Why?
EDIT:
hmmm, still doesn't work :/ Now I don't see anything in firebug and one the page. :(
$(function() {
var Profile = Backbone.Model.extend();
var ProfileList = Backbone.Collection.extend({
model: Profile,
url: 'profiles.json'
});
var ProfileView = Backbone.View.extend({
el: "#profiles",
template: _.template($('#profileTemplate').html()),
render: function(eventName) {
_.each(this.model.models, function(profile){
var profileTemplate = this.template(profile.toJSON());
$(this.el).append(profileTemplate);
}, this);
return this;
}
});
var profiles = new ProfileList();
var profilesView = new ProfileView({model: profiles});
var profiles = new ProfileList();
profiles.fetch();
profiles.bind('reset', function () {
console.log(profiles);
profilesView.render();
});
});
Your fetch call is asynchronous, as I'm sure it's written in the tutorial. So when you're doing the console.log, your collection is still empty.
Farther in the tutorial..:
var profiles = new ProfileList();
profiles.fetch({reset: true});
profiles.bind('reset', function () { console.log(profiles); });
This should work.