0

I am making a website with an API to gather artist/song information (MusixMatch) along with the YouTube API. My goal is to output certain data to the screen for each search result and show a related youtube video. The formatting for each result is fine and the first AJAX call outputs it correctly. The issue is that I have nested the Youtube API within the MusixMatch API so that I can run the video search queries with the artist data. That works fine and I can get the video to display but for some reason I cannot get it to display in the div I created for each result.

$.ajax({
       type: "GET",
        data: {
            apikey:"85f6c6b42df5d50c164d2e47183cb357",
            q_track: songSearch,
            f_has_lyrics: 1,
            s_artist_rating: "desc",
            s_track_rating: "desc",
            format:"jsonp",
            callback:"jsonp_callback"
        },
        url: "https://api.musixmatch.com/ws/1.1/track.search",
        dataType: "jsonp",
        jsonpCallback: 'jsonp_callback',
        contentType: 'application/json',
        success: function(data) {
            console.log(data);
            var live = 'Live';
            var remaster = 'Remaster';
            var edit = 'Edit';
            var myHTML = '';
            for (var i = 0; i < data.message.body.track_list.length; i++) {

                if ((data.message.body.track_list[i].track.track_name).search(live) > 0 || (data.message.body.track_list[i].track.track_name).search(remaster) > 0 || (data.message.body.track_list[i].track.track_name).search(edit) > 0){

                    continue;
                }

                myHTML += '<li class="artistName list-group-item">';
                myHTML += '<span class="name">' + data.message.body.track_list[i].track.track_name + '</span></br>';
                myHTML += '<span class="rating">Artist Name: ' + data.message.body.track_list[i].track.artist_name + '</span></br>';

                $('#song_output').append(myHTML);
                myHTML = '';

                $.ajax({
                       type: "GET",
                        data: {
                            part: "snippet",
                            key: 'AIzaSyBYLyCoBwVBnxICX2w38cnO_kkoQzW09Ko',
                            maxResults: 1,
                            q: data.message.body.track_list[i].track.track_name + ' ' +  data.message.body.track_list[i].track.artist_name ,
                        },
                        url: "https://www.googleapis.com/youtube/v3/search",
                        dataType: "JSON",
                        contentType: 'application/json',
                        success: function(data) {
                            console.log(data);
                            var video = 'data.items[0].id.videoId';
                            postVideo(video);

                        },
                        error: function(jqXHR, textStatus, errorThrown) {
                            console.log(jqXHR);
                            console.log(textStatus);
                            console.log(errorThrown);
                        },
                        complete: function(){
                        }

            })
              function postVideo(video){
                  myHTML += '<iframe width="560" height="315" src="https://www.youtube.com/embed/' + video + '" frameborder="0" allowfullscreen></iframe></br>';
                 myHTML += '</div>'
                myHTML += '</li>';
              }  

            }
            $('#song_output').append(myHTML);

        },
        error: function(jqXHR, textStatus, errorThrown) {
            console.log(jqXHR);
            console.log(textStatus);
            console.log(errorThrown);
        },
        complete: function(){
             $("#ajaxIndicator").modal('hide');
        }

            })

Sorry if this is not enough information but I can provide more if needed. Does anyone have an idea of what could be causing the to display outside of the div instead of inside of it despite it being output within it?

Don
  • 3,876
  • 10
  • 47
  • 76
punygod
  • 197
  • 2
  • 17
  • 1
    it's because `$.ajax` is asynchronous, and you're calling `$('#song_output').append(myHTML);` under the assumption that `$.ajax` is syncrhonous – Jaromanda X May 10 '17 at 02:16
  • @JaromandaX Okay so my thinking is that with each loop that will be done for each search result, it will build the beginning of the HTML div and set it to an output variable, then I call the youtube api which will get me the video url. Set the – punygod May 10 '17 at 02:30
  • You're appending the html before it is filled – Jaromanda X May 10 '17 at 02:37
  • @JaromandaX I've removed the first instance of the append and as far as I can tell it is not appending until the entire for loop has run and the myHTML variable is full. Any ideas what it still does not display? Thank you for helping. – punygod May 10 '17 at 03:01
  • I am really sorry, due to the "formatting" of the code I thought you were appending "too soon" - I've reopened the question – Jaromanda X May 10 '17 at 03:41
  • actually, scratch that - you ARE doing it wrong, the final `$('#song_output').append(myHTML);` is executed **before** any of the inner `$.ajax` would complete – Jaromanda X May 10 '17 at 03:44
  • there's an easy fix, which would mean the iframe order is more or less random, or a more complex fix, which will preserve the order of the iframes - which would you like? – Jaromanda X May 10 '17 at 03:45
  • also, `var video = 'data.items[0].id.videoId';` will result in the src url having the exact string `data.items[0].id.videoId` in it, which wont be right – Jaromanda X May 10 '17 at 03:47
  • @JaromandaX Well i would need the iframe videos to correspond with the with search results so it would be best if i could get them in the order they were called – punygod May 10 '17 at 03:47
  • @JaromandaX and to the point about the video variable, that is okay because that variable is to be placed within the actual url since the youtube api only returns the unique video id and not the entire link – punygod May 10 '17 at 03:49
  • `that is okay` no it isn't ... because the actual URL you will be using for src, i.e. `https://www.youtube.com/embed/data.items[0].id.videoId` will never be valid – Jaromanda X May 10 '17 at 04:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143823/discussion-between-andrewxt-and-jaromanda-x). – punygod May 10 '17 at 04:05
  • look at [this rewrite](https://jsfiddle.net/as13s4dx/1/) - see if it helps you at all (ignore the previous broken version) – Jaromanda X May 10 '17 at 04:40
  • @JaromandaX Wow thank you so much. This is exactly the result I was trying to get. I will read up on some of the functions you used so I can understand it better. – punygod May 10 '17 at 04:54
  • I avoided posting it as an answer because I think it actually is a duplicate of https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call - albeit a little more complex – Jaromanda X May 10 '17 at 04:55

0 Answers0