Forum Discussion

MathNotermans-9's avatar
MathNotermans-9
Community Member
3 years ago

Global scope for Javascript variables in Storyline

As Storyline publishes all code and variables to separate functions in the user.js file the scope for individual variables is local. The solution i show here creates a global scope for functions and variables so you can reuse your Javascript code and variables anywhere in a Storyline project.

Basically i make use of a WebObject to add an external Javascript to Storyline. In that script variables are stored globally so you can reuse them anytime. Also with this solution you can add any custom function to the globalScript.js file. Those functions can then be called from any spot in Storyline.

Lets see it working first.

https://360.articulate.com/review/content/d02ea9a4-b779-4447-befa-7af5a2d02e21/review
In this Storyline you can enter 2 values. A property name and its value. Those will be saved in a Javascript object and can be called with a global function or directly. When adding your first one... it shows in the textfield on the left... then you can continue to the next slide...and do the same... either edit one of the added values...or add a new one.

The function iterateObject(_obj,_desiredoutput); you can use to get your variables and values. Offcourse the argument _obj is for your Object in Javascript. In this case  its 'globObj', but you can add as many as you want and customize them. The argument _desiredoutput is for what you want returned. Default that is a string, but you can choose to get an array.

Alright some more info on how it works. As you can see in the Storyline file i use a separate scene for the WebObject that loads the Javascript file(s).

As you can see i use subfolders for my Javascript files. Nothing more then the empty index.html and the globalScripts.js in its own subfolder for the WebObject.

To load the Javascripts files into Storyline i use a Javascript trigger on the start of the timeline. This is probably best added to a Master Slide and ensure its only loaded when the variable 'javascriptsLoaded' is False.

When changing anything to the 'globalScripts.js' or the WebObject you would need to change 2 variables in the script. amountOfLibs and webObjectURL. The latter offcourse refers to the folder Storyline publishes the webObject to. And you would need to publish and check the name of the folder when changing anything.

Then you can call the functions from the 'globalScript.js'. In this sample i only added 2 functions. One to set the variables and one to get them again. Both work on any spot in the Storyline. After the Javascript is loaded you can set and get variables from anywhere in your Storyline.

Do hope this is usefull for some of you. 

  • As WebObjects keep their files persistent in the Storyline file.. download the globalScope.story.... publish it and magically the js-file is on your computer in the published folder. Instead of previewing...Open Folder and go into story_content/WebObjects/5yVih3lSjPj/globals
    and there it is.

  • Hi all, and particularly @Math.

    I'm very interested in this solution, but where can I find your GlobalScript.js file ?

  • steveparadis's avatar
    steveparadis
    Community Member

    Hello Guys,

    My personal solution is to use a webObject on the first scene, with sessionStorage.

    I do load a webObject (first slide and off stage). the code in the index.html is simply :

    *************************************
    <script>
    sessionStorage.setItem("msg_EN","Hello world!");
    sessionStorage.setItem("msg_FR","Bonjour le monde!");
    sessionStorage.setItem("msg_ES","Hola mundo!");
    </script>
    *************************************

    These become available for each slides even for other webObjects :

    var player = GetPlayer();
    player.SetVar("greetings",sessionStorage.getItem("msg_EN"));

    If you care about making the variables more "private", you can always use base64 encode/decode, here is the function I use:

    ****************************************
    function encodeB64(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
    function toSolidBytes(match, p1) {
    return String.fromCharCode('0x' + p1);
    }));
    }

    function decodeB64(str) {
    return decodeURIComponent(atob(str).split('').map(function(c) {
    return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
    }

  • if you wan't to use small solutions for global variables in javascript - use window-variables (storyline is technical a single-page application)

    https://javascript.info/global-object

    example

    javascript trigger 1:

    function hallo(){
    window.myText = "hallo";
    }


    javascript trigger 2:

    function printHallo(){
    console.log( window.myText );
    }

    normaly window variables are not used*, the normal javascript would be

    var myText;

    function hallo(){
    myText = "hallo";
    }

    function printHallo(){
    console.log( myText );
    }

    the result is the same, but this it is not possible in a trigger javascript

    Jürgen

    * as a developer you should not use such things - global variables are nasty. If you are not careful, they can cause big problems. Normally you encapsulate variables. 

  • CoriHastings's avatar
    CoriHastings
    Community Member

    Thank you Math! I would love to try this on my current project but with a looming deadline, it's probably not going to happen. Hopefully on the next one!