Spotify App API: tab pages, playlist UI refresh - spotify

I am building a Spotify App with four tab pages. The content of all tabs are loaded on initial load of the app. Each tab contain one or more playlists that are being populated with data from 3rd party web apis that are resolved into spotify tracks.
The selected tab works fine. the playlist show up a expected. The problem is with tabs that are initially hidden but later selected. Here the playlist looks like this when selected:
not fully rendered playlist
Looking in the Inspector I can see that the content has not yet rendered:
<div class="sp-list sp-light" tabindex="0">
<div style="height: 100px; ">
</div>
</div>
When I do a resize of the Spotify desktop app, the playlist is finally rendered:
rendered playlist after resize
To populate the playlist I use the 'standard' spotify models and views:
var playlist = new views.List(tempPlaylist);
//where tempPlaylist is a new models.Playlist();
//that has been populated with tempPlaylist.add(search.tracks[0].uri);
playerPlaylistDiv.append(playlist.node);
I am only seing this issue when using tabs. When displaying all content on one long page all playlists are fully rendered. I wonder if it has to do with timing: that I am hiding content that has not yet fully rendered? Any thoughts much appreciated.
I handle tab changes this way:
/* Handle URI arguments */
models.application.observe(models.EVENT.ARGUMENTSCHANGED, tabs);
/* Handle tab changes */
function tabs() {
var args = models.application.arguments;
// Hide all sections
$('section').hide();
// Show current section
$("#" + args[0]).show();
}
FYI I am using the Spotify preview 0.8.10.3.

I am not sure this is the same thing, but I ran into similar issues trying to create tracklistings from playlist-uris on the fly; also couldn't track it down any closer (the containing DOM was certainly rendered and ready); and it only happened on certain playlists, never e.g. on albums.
I was able to circumentvent this problem by "cloning" playlist - obviously there's a "performance" hit ...
// assuming uri is the playlist's URI
models.Playlist.fromURI( uri, function(originalPlaylist) {
var tempPlaylist = new model.Playlist();
$.each(originalPlaylist.tracks, function(t) { tempPlaylist.add(t); });
var tracklist = new views.List(tempPlaylist);
// etc...
}
I am not sure what's on here, but maybe that helps you along :)
PS. Also - make sure you have a doctype-declaration in index.html (), the spotify client does some weird things if you don't.

The solution I've found is this:
I arrowed it down to being an issue with showing/hiding the content since showing the full content without tabs never causes issues. So instead of using .show()/.hide() I now hide and show the content by setting the height of the sections to 100%/0:
// Hide all other sections
$("section#" + args).siblings().height('0');
// Show current section
$("section#" + args).height('100%');
Not sure why this works, but it does (for me at least).

I had the same problem (see Spotify List objects created from localStorage data come up blank) and fixed it by doing the hide()/show() of divs before any processing. Previously I was constructing the playlist and then show()ing the div after which led to a blank list.

I think I've actually managed to solve this and I think it's bulletproof.
Basically I was trying to solve this by trying to convince the API that it needed to redraw the playlist by hiding things/scrolling things/moving things which worked occasionally but never consistently. It never occurred to me to change the playlist itself. Or at least make the API think the playlist has changed.
You can do so by firing an event on the Playlist object.
var models = sp.require('$api/models');
...
// playlist is your Playlist object. Usually retrieved from models.Playlist.fromURI
playlist.notify(models.EVENT.CHANGE, playlist);
These are just standard Spotify functions and the list updates because it thinks something has changed in the playlist. Hope this helps someone!

Related

Chrome extension won't allow get request

I'm trying to create my first chrome extension. Basically I have a simple html page and some javascript that im using to allow users to enter some data, the script will format it correctly and then output it:
<form>
MAC ADDRESS: <input type="text" id="mac" name="macAddress" maxlength="17" >
<button onclick="convert(); return false;">Convert</button>
</form>
Javascript:
function convert() {
var mac = document.getElementById('mac').value; //get string
var mac2 = mac.replace(/\:|-/g,""); //remove colons and dashes
//
//add fullstops after every 4th character, appart from last character.
//
mac2 = mac2.replace(/(.{4})(?!$)/g , '$1.');
//output string
document.getElementById("outputDiv").innerHTML= mac2;
};
My problem is that while this works fine as a normal web page, the get method, to the same page, is not working when I tried to implement it as an extension.
I've followed the tutorials on google's site and the extension is showing up but it doesn't seem to be able to handle get requests. I've tried modifying the manifest file using different suggestions I found on here but still no success.
Theres nothing in the console when I try to debug it (something briefly flickers up when I submit the get request but it doesn't stay up long enough to see what the issue is).
I'd really appreciate it if someone could point me in the right direction with this!
Due to the Content Security Policy applied to extensions:
Inline JavaScript will not be executed. This restriction bans both inline blocks and inline event handlers (e.g. ).
[...]
The inline event handler definitions must be rewritten in terms of addEventListener and extracted into popup.js.
For more info atake a look at the docs.

Navigate to a Spotify track's page with it autoplaying?

Linking to the song with a Spotify URI ie (href="spotify:track:5hOvK49BB8MKmMm5zM1mJD") causes the track to play when all I want is to go to the album page and show the track highlighted. I've implemented an event.preventDefault(); as suggested here, but I'm not sure of what the handler should look like to go to the track page.
There's no such thing as a track page — as you see, you actually get to the album page.
To get the behaviour you want, get the track's album and link to that instead.

Tracks don't show in Spotify-Playlist-View

I'm using the default playlist object from the JS-Spotify library and constructing a playlist.
Then I use this Code:
var playlistList = new views.List(pl);
playlistList.node.classList.add('sp-light');
$(".favAlbums").append(playlistList.node);
But for the first time when I load the page with this view the tracks don't show in the playlist DIV. The playlist DIV itself does. What could cause that? (I'm using exactly the same code at a different place where it works just perfectly)
Update:/
It seems to be a rendering issue because when I resize the Spotify application the track entries appear. But before resizing the DIV is empty in the inspector.

delay "creation" of div, not just showing of div

I may not be using the proper terminology but hopefully I get my question across properly. What I'm wondering is if it's possible to "delay" the "creation" of a specific div, rather than just delay the FadeTo or Show jquery command.
I ask because I'm using the Vimeo API which is completely mind-boggling and frustrating (at least for me - it's a source of endless shame and I wallow in self-pity when attempting any such Vimeo API coding). What I'm trying to do is just delay the autoplay of the iframe code for an embedded Vimeo video. The problem is that I have the div containing the vimeo iframe set to hide for a good three seconds after the page loads before it fades in, but since it's just hidden the video starts playing anyway before the visitor can actually see it. I'm just using &autoplay=1 for the vimeo embed...
So, I suppose the only other solution besides getting this confusing Vimeo API to try to delay the video that way is to be able to just use a jQuery command to delay the vimeo iframe from even loading/being created on the page, until the container div fades in.
If this is possible I will bless my lucky charms. And double points if someone answers in the next few hours! Thanks so much!!!
I just editted my answer and applied it to fit your code you provided:
So what I did here is: 1) load jquery into your page2)when jquery sees your div with id="div" as 'ready', it will fire an alert that says loaded (you can remove this it was just for testing purposes), and then delay the src from loading in your iframe for 2 seconds (2000 miliseconds)
3) So you can change the 2000 to whatever time you want, and make sure the "player_1" matches your iframes id
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
$(document.getElementById('div')).ready(function()
{
alert('loaded');
setTimeout('document.getElementById("player_1").src="http://www.youtube.com/v/82CYNj7noic?autoplay=1"', 2000);
});
</script>
<div id="div" class="div">
<iframe class="iframe" id="player_1" > </iframe>
</div>
​
​
Does this work for you?? I hope I've helped!!

How I do create a animated loading indicator spotify apps

How I do use the loading_indicator.png provided in the design resources folder to make it act like an ajax loader?
This is how I display a loading indicator when starting my app, taken from the 'home' application (What's New). In your index.html:
<div class="loading">
<div class="throbber"><div></div></div>
</div>
In you app.css:
#import url("sp://import/css/eve.css");
adam.css being the dark Spotify theme and eve.css the light. Then, when your application is finished loading, just remove the element. You can do it with the dom methods in the spotify dom.js. In your app.js:
var dom = sp.require('sp://import/scripts/dom');
var loadingEl = dom.queryOne('.loading');
dom.destroy(loadingEl);
I don't know if the dom.js will be in the official API or not. Otherwise you can remove it any other way (standard dom methods, other js libraries you're using, etc):
var loadingEl = document.querySelector('.loading');
loadingEl.parentNode.removeChild(loadingEl);
Note that the above example does not necessarily use the loading_indicator.png but whatever images that are used by the adam.css and eve.css themes.
If you wan't to use the loader as a normal ajax loading indicator inside your app, then all the normal rules of web apps apply. Display loader when initiating ajax call, hide it in completed-callback, position it with css.
I realize this is an old topic, but with the 1.X API there is an easier way to do this by using the Throbber class which allows you to instantiate and hide fairly simply via JS.
var tracks = document.getElementById('tracks');
var throbber = Throbber.forElement(tracks);
// (wait for tracks to load and render)
throbber.hide();
Just make sure to include the Throbber class at the beginning of your JS:
require([
'$views/throbber#Throbber'
], function (Throbber) {

Resources