Context: This is a Soundcloud API javascript and iframe that is suppose to play the correct sound of the soundcloud link when you hover over the link.

Problem: The problem is that I get an error saying "SC.Widget function should be given either iframe element or a string specifying id attribute of iframe element" when I hover over a link. The error occurs at this line of code:

widget = SC.Widget(event.currentTarget.childNodes[1]);

HTML (Iframe the src is customized to play that particular link):

<div class="clickme">
    <iframe  src="https://w.soundcloud.com/player/?url=https://soundcloud.com{{-list2[1]-}}&show_artwork=true"
                                        "width=300" height="200" scrolling="no" frameborder="0" style="display: none" allow="autoplay">
                                </iframe>
</div>

Javascript(Soundcloud API):

    <script type="text/javascript">
        
        let widget;
        let currentWidget;


        
        $(document).ready(function () {
            console.log("ready!");
            var menu = document.getElementsByClassName("clickme");
            for (i = 0; i < menu.length; i++) {
                var list = menu[i];
                var link = String(list.outerHTML);


                if (link.includes('soundcloud')) {
                    list.addEventListener("mouseenter", function (event) {


                        if (event.currentTarget.childNodes[1] == currentWidget) {
                            widget.play();
                        } else {
                            if (widget) {
                                widget.unbind(SC.Widget.Events.PLAY);
                                widget.unbind(SC.Widget.Events.READY);
                                widget.unbind(SC.Widget.Events.FINISH);
                            }

                            widget = SC.Widget(event.currentTarget.childNodes[1]);
                            /*<!--widget = SC.Widget(idIndex);-->*/

                            widget.bind(SC.Widget.Events.READY, function () {
                                widget.bind(SC.Widget.Events.PLAY, function () {
                                    // get information about currently playing sound
                                    console.log('sound is beginning to play');

                                });
                                // get current level of volume
                                widget.getVolume(function (volume) {
                                    console.log('current volume value is ' + volume);
                                });
                                // set new volume level
                                widget.setVolume(50);
                                // get the value of the current position
                                widget.bind(SC.Widget.Events.FINISH, function () {
                                    // get information about currently playing sound
                                    console.log('replaying sound');
                                    widget.seekTo(0);
                                    widget.play();
                                });
                            });

                            widget.play();
                        }
                        currentWidget = event.currentTarget.childNodes[1];

                    });
                    list.addEventListener("mouseleave", function (event) {

                        console.log('pause soundcloud ');
                        if (widget) {
                            widget.pause();
                        }
                    });
                }
            }

        });
    </script>
1

There are 1 best solutions below

1
Hicham On

As the error message states, you have to pass either an <iframe /> or an ID to an <iframe />. It means that event.currentTarget.childNodes[1] is probably NOT an <iframe /> (even less a string representing an DOM's element id).


I suggest you console.log() the entire event if you want to use mouse events to get corresponding <iframe />, or you make a clever use of id. Otherwise I'd recommend using a more robust method to get the iframe HTMLElement to pass to the SoundCloud Widget.


In the following snippet, Element.querySelector() is used to find iframes, but jQuery can do the same. Pass your mouse over one of the list elements and you should see the widget's methods logged in the Console.

// Run when DOM is ready

(function() {
  // Make sure the SoundCloud Widget API is loaded in DOM
  if (!(window.SC && window.SC.Widget)) {
    return;
  }

  let currentWidget = null;
  const listItems = document.getElementsByTagName('li');

  for (const listItem of listItems) {
    listItem.addEventListener('mouseover', event => {
      // Get the <iframe /> HTMLElement
      const iframe = listItem.querySelector('iframe');
      const widget = SC.Widget(iframe);

      // Set the current widget
      currentWidget = widget;

      // The logged object should have the "load", "bind", ... methods
      for (const properties in currentWidget) {
        console.log(properties);
      }

      // Unbind, set volume, ...
      // ...
    });
  }
})()
<html>

<head>
  <script src="https://w.soundcloud.com/player/api.js" charset="utf-8"></script>
</head>

<body>
  <ul>
    <li>
      <iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177612306&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
    </li>
    <li>
      <iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177613530&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
    </li>
    <li>
      <iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177615096&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
    </li>
    <li>
      <iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177644181&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
    </li>
    <li>
      <iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/1177647310&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>
    </li>
  </ul>
</body>

</html>