Forum Discussion

  • Kris, Thank you. This explains why all website won't work with this call. 

     

    • Jean-Guy-Boulay's avatar
      Jean-Guy-Boulay
      Community Member

      Yes, it's hit or miss when connecting to external websites depending on permissions set on the server. Storyline WebObjects are entirely built on an iframe, do an 'inspect' and search the code for the word and you'll see what I mean. When you run locally embedded content through the web object it's running content in the same location so it won't throw up security flags to the browser.  When I tested the script I was only able to load up Imgur images, a course hosted on my server, and the Elearning heroes community website; anything else was blocked.

  • Thanks everyone! I was able to use Jean-Guy's version to show a Smartsheet form inside a Storyline object. This is the code that worked for me:

    var player = GetPlayer();

    //This will work with the first iframe on the slide with the class name of "shown"
    var iFrameId = document.getElementsByClassName('shown')[2];
    console.log(iFrameId);

    var src="https://app.smartsheet.com/b/form/12345";

    var score=player.GetVar ("Score");

    //Build the smartURL here > var fullurl = src + "?var1=" + value1 + "&var2=" + value2;
    var fullurl = src + "?Quiz=" + score;

    //Send the new smartURL to the web object
    iFrameId.setAttribute('src', fullurl);

  • It seems something has changed, because my files that used to work (just above) are no longer working. I get the sad web page icon. It's the same with Jean-Guy's file that was working above. Does anyone know if there's a workaround, or what we can change to get web objects to work in Storyline again?

    • Jean-Guy-Boulay's avatar
      Jean-Guy-Boulay
      Community Member

      If you delete and add a new webobject with the same address it will work again. The new storyline webobject needs to be replaced. But, Chrome security updates have gimped much of the communication. I have switched to postMessage for SL to WebObject and vice versa communication.

      The iframe is still being assigned to the iFrameId, but the variable delivery will no longer work. 
      I switched to postMessage last year to deliver variables between webobject and storyline.

      You can add a javascript trigger to send a post message with the variables. Pretty sure this needs to be added on the same layer as the webObject.

      /////////////////////// In SL ///////////////////////////////

      var player = GetPlayer();

      const iframe = document.querySelector('iframe[data-dv_ref="iframe"]');

      const var1  = player.GetVar("var1");

      // Function to send message to the iframe
      function sendVar(data) {
       iframe.contentWindow.postMessage(data, '*'); // '*' for all origins (adjust if needed)
      console.log("Message sent To Iframe");
      }

      const eventData = { dataName: var1};//dataName can be anything, just make sure it matches the listener you have in the webobject.
      console.log("sending custom event to iframe");
      sendVar(eventData);
      /////////////////// In SL end ///////////////////////////////////
      /////////////////// In web object ///////////////////////////////
      // add this to your webobject in a script
      window.addEventListener('message', function(event) {
         if (event.data.dataName) {
      const var1 = event.data.dataName; //this is the variable to that was sent.
        console.log("Received Var from parent:", var1 );
         }
       });
      /////////////////// In web object end ////////////////////////

      I hope this helps/works for you.

  • Hey everyone - I found 2 simple changes that fixed this for me, so I wanted to share. It seems that Articulate may have changed the number of iFrames in the slide, so I had to change the [2] to [1].

    It also seems that the "placeholder" URL I was using for w3schools.com changed something that was preventing my web object in Storyline from opening, so I changed from w3schools.com to example.com. 

    With only these two changes, everything's working as it has for the last couple years.

    Hope this helps for someone else. It took a lot of experimentation - and a couple hours of help from my niece's boyfriend who knows JavaScript! ;-)

     

     

  • FYI - Something in the Storyline code (for the number of i-frames) changed again in the last couple weeks and now the [2] is required. 

     

     

    • Jean-Guy-Boulay's avatar
      Jean-Guy-Boulay
      Community Member

      The number in the parenthesis is an index number. It's specifically target the IFrame you are looking to effect. In order for that to work in the example above you must be sure that the iframe is the 3rd one in the project. This is a bad practice for several reasons but the main one is that storyline may dynamically change that index number at anytime. This is why I just use the data-ref name that I mentioned above (const iframe = document.querySelector('iframe[data-dv_ref="iframe"]');).  Why, because it works only on the screen/layer you have the javascript trigger. (hint to Articulate: you need to give us the ability to tag or id the iframes we have in a project).

      I'm not understanding the current intent, but if you absolutely need to use the index id for the current iFrame shown you can use this:

      function getVisibleIframe() {
        const showniFrames = document.getElementsByClassName('shown');
        for (let i = 0; i < shownFrames.length; i++) {
          if (showniFrames[i].offsetParent !== null) { // Check if the element is in the document
            return showniFrames[i];
          }
        }
        return null; // If no visible iframe found
      }
      const iFrameId = getVisibleIframe();
      
      if (iFrameId) {
        // Do something with the visible iframe
        console.log(iFrameId);
      } else {
        console.log("No iframe is currently visible.");
      }

      You can also set it up so that it identifies the last iFrame in you project:

      function getLastShownIframeIndex() {
        const shownFrames = document.getElementsByClassName('shown');
        if (shownFrames.length > 0) {
          return shownFrames[shownFrames.length - 1];// If you are publishing to the review link, then remove the '-1' because the content gets wrapped in another iframe on the review site, otherwise this should work. 
        } else {
          return -1; // Indicates no shown frames
        }
      }
      const lastShownIndex = getLastShownIframeIndex();
      if (lastShownIndex !== -1) {
        //do something with the iframe
      } else {
        console.log("No iframes are currently shown.");
      }