Search code examples
javascriptfor-loopiframetumblronload

Problem assigning onload function to two iframes on the same page?


I'm a novice JavaScript user trying to make a Tumblr theme. I'm trying to style the native Tumblr audio player using JS since it's in an iframe. Problem: when two tumblr audio players load onto the same page, only one gets styled. Here's my JS so far:

var audioIframes = document.body.getElementsByClassName("tumblr_audio_player");
var i;
for (i = 0; i < audioIframes.length; i++) {
  var audioIframeWindow = audioIframes[i].contentWindow;
  audioIframes[i].onload = function () {
    audioIframeDoc=audioIframeWindow.document;
    /*introduce font stylesheet to iframe*/
    var head = audioIframeDoc.head;
    var link = audioIframeDoc.createElement("link");
    link.type = "text/css";
    link.rel = "stylesheet";
    link.href = "https://fonts.googleapis.com/css2?family=Epilogue:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap";
    head.appendChild(link);
    /*actually editing some styles*/
    var audioPlayer = audioIframeDoc.body.getElementsByClassName("audio-player");
    for (j = 0; j < audioPlayer.length; j++) {
      audioPlayer[j].style.background = "{color:2}";
      audioPlayer[j].style.color = "{color:3}";
      audioPlayer[j].style.fontFamily = "Epilogue,sans-serif";
    }
    var audioPBar = audioIframeDoc.body.getElementsByClassName("progress");
    for (k = 0; k < audioPBar.length; k++) {
      audioPBar[k].style.background = "{color:1}";
    }
    var audioArtist = audioIframeDoc.body.getElementsByClassName("track-artist");
    for (l = 0; l < audioArtist.length; l++) {
      audioArtist[l].style.color = "{color:3}";
    }
  }
};

This code works great at changing the iframe style but only if there's only one native tumblr audio player on the page. I did some console debugging stuff and found out that everything done within the onload function defined above gets done twice to one of the iframes rather than once to each of the iframes. I think it has to do with the outer for loop not really working well with the onload event inside? Can someone help me out? PS: I'm also new to stackoverflow so if anyone has any tips on how best to ask questions that would be great too!

Edit: Here's the blog page where I've tagged all my audio posts: https://smileytiger28.tumblr.com/tagged/debuggingfornow. In the console, you can see six #document elements pulled up. The first three just have empty <head> and <body> elements, because those are logged before the iframes are loaded. The last three #document elements are all from within the onload function, so they all have actual contents, but they are all from the same iframe! This means that the problem is that the onload function is looping the right number of times but only for one of the iframes. Can you help me figure out why?


Solution

  • Wow, what a good question, Me! After some research I found a solution in jQuery that will serve my purposes

    $(document).ready(function(){
      $(".tumblr_audio_player").ready(function (){
        $(".tumblr_audio_player").each(function(index,element){
          element.onload = function(){
            // attach Epilogue font in a stylesheet
            let hid = element.contentWindow.document.getElementsByTagName("HEAD")[0];
            let link = element.contentWindow.document.createElement("link");
            link.type = "text/css";
            link.rel = "stylesheet";
            link.href = "https://fonts.googleapis.com/css2?family=Epilogue:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap";
            hid.appendChild(link);
            //main style changes
            let biddy = element.contentWindow.document.getElementsByTagName("BODY")[0];
            let audioPlayer = biddy.getElementsByClassName("audio-player");
            for (j = 0; j < audioPlayer.length; j++) {
              audioPlayer[j].style.background = "{color:2}";
              audioPlayer[j].style.color = "{color:3}";
              audioPlayer[j].style.fontFamily = "Epilogue,sans-serif";
            }
            let audioPBar = biddy.getElementsByClassName("progress");
            for (k = 0; k < audioPBar.length; k++) {
              audioPBar[k].style.background = "{color:1}";
            }
            let audioArtist = biddy.getElementsByClassName("track-artist");
            for (l = 0; l < audioArtist.length; l++) {
              audioArtist[l].style.color = "{color:3}";
            }
          };
        });
      })
    })
    

    Hope this helps :P