Help with javascript to show layers - too much processing using built-in SL360 variables/triggers/layers

Jul 10, 2020

I wonder if any javascript wizards might be able to help me. I am building a "game" in Storyline 360. In the game, the learner is going shopping with a character, and makes decisions on what to buy. As the learner makes decisions, variables change from "false" to "true" and different images show on the screen. On the final slide in the game, a layer appears depending on what was purchased, with images showing depending on the value of the variables. This all works great using built-in variables, triggers, and layers. However, this final slide has about 30 layers, and within each trigger to show the correct layer, there are 6 "if" conditions to process. That's a lot of processing and I've noticed in Review that it takes many seconds for the processing to take place and for the layer to show. This is a game for learners with ID/DD and the delay may be very confusing. For this reason, I was wondering if the processing to show the correct layer could be done with javascript instead of built-in Storyline triggers to show layers.

The logic is like so:

***************************

if var1 is true AND var2 is false AND var3 is false AND var4 is false AND var5 is false AND var6 is false
show layer "var1"
else if
var1 is false AND var2 is true AND var3 is false AND var4 is false AND var5 is false AND var6 is false
show layer "var2"
else if
var1 is false AND var2 is false AND var3 is true AND var4 is false AND var5 is false AND var6 is false
show layer "var3"

... keeps going ...

else if
var1 is true AND var2 is true AND var3 is false AND var4 is false AND var5 is false AND var6 is false
show layer "var1and2"

... keeps going ...

else
show layer "var2andvar4andvar6"

***************************

As I mentioned, there are about 30 layers so there would be many "else if" conditions that would run.

I've looked at several posts here in the community, but I'm still not sure how I would do this. Any help with accomplishing this would be so appreciated! Thank you!

34 Replies
Ned Whiteley

Hi Mary Beth,

I'm not a javascript expert and so can't really help you there, but I was wondering if you might be making this too complicated.

There maybe a very good reason why you need so many layers and attached complex triggers, but I thought I would forward the attached example in case it might give you an option for an easier solution.

This is a very simple example where there are five vegetables available for selection and, once the user clicks on the Checkout button, they are then jumped to the next slide where everything they selected at the "supermarket" is now shown on the workbench.

No layers are used as it instead relies on state changes based on the value of the True/False variables that are set when the user selects an option on the first slide. All the items on the second slide have an initial state of Hidden, which changes to Normal if their associated variable is True when the timeline starts for slide 2.

Hope it helps.

Mary Beth Faccioli

Hi Ned,

Thanks so much for your response! Unfortunately my case isn’t as simple as your example.

Depending on choices the learner makes, a different, custom illustration of the character shows on the final slide via layers. So it’s not a matter of each selected item showing vs not showing. It’s a matter of every possible combination of selected items triggering a unique, custom illustration of the character - a separate illustration for each possible combination.

For example, if the learner chooses a hat, the final illustration shows the character in the hat. If they choose a coat, the final illustration shows the character in the coat. If they choose both hat and coat, the final illustration shows the character in both the hat and coat. If they don’t select the hat or coat, the final illustration shows the character without them. Etc. There are about 30 possibilities.

I appreciate your response!

Ned Whiteley

Hi Mary Beth,

There is another option that might be a bit more streamlined that would use less variables and less complex triggers. It is a little bit different, but could work.

If you allocated a value to each item of clothing using, for example, alternate prime numbers from 13 upwards, you should be able to get a unique value for whatever is selected for purchase.

If you have a hat (13), gloves (19), coat (29), bag (37) and boots (43) your options would be:

hat (13)
hat and gloves (32)
hat, gloves and coat (61)
hat, gloves, coat and bag (98)
hat, gloves, coat, bag and boots (141)

gloves (19)
gloves and coat (48)
gloves, coat and bag (85)
gloves, coat, bag and boots (128)

coat (29)
coat and bag (66)
coat, bag and boots (109)

bag (37)
bag and boots (80)

boots (43)

You now only need one variable that you increment by the appropriate amount depending on what is selected and when you jump the user to the next slide, simple triggers show the appropriate image depending on the value of the variable. 

I'm not sure if there is a limit on the number of states that can be created for an image, but if there isn't or if that number is greater than the number of options you have, you could simply use different states of your character instead of using 30 different layers.

I have only tried it with five items and, with the extra items you have, you do run the risk that you get to the last option and discover that you no longer have a unique number, but I just thought I would suggest it just in case it could be of some help.

Andrew Hanley

Hi Mary,

The JS you are requesting should be fairly straight forward to create and its something ive done in the past because as you say, its alot quicker and easier to update/adapt than having a huge amount of ASL triggers.

If you are still needing it Im happy to try to help.

Is your outcome always a basic, single result - or are you looking for something flexible? ie.  a randomised pick/result based on your Learner's true/false variables?

Mary Beth Faccioli

Hi Andrew,

Thanks so much for your response! I am still needing help and I'd really appreciate anything you can offer!

The outcome is a single result (e.g. an image with the character wearing what was chosen during shopping) based on the true/false variables. There is one specific illustration for each possibility. So for example if the learner chose a hat, boots, and a shirt during the game, the variables for those items would change to true (they drag the item onto the character which triggers the variable to change from false to true) and then in the final slide, the layer would show with the specific illustration of the character wearing the hat, boots, and shirt. If they only chose a hat, the illustration of the character in a hat would show (via layer).

I've attached an attempt I made with javascript to see if I could get some of the layers to show. It didn't work! With this javascript, the idea was to see which of the conditions was true, and then to change the layer variable to "yes". Then in the story file, I have triggers to show the specific layer if the layer variable is "yes". If I display a variable on the screen to test (e.g. %kikiBootsLyr%) I can see that the javascript I wrote isn't changing the variable. I really don't know javascript so there could be something simple I'm doing incorrectly!

Thanks for any help you can provide! Much appreciated.

Andrew Hanley

Hi Mary, Im happy to help if I can!

At this point in time, I dont think Storyline allows layers to be shown/hidden via any javascript commands directly, so we need to get a little creative.  :)

The Input:

console.log("JS DEBUG --- starting javascript...");

var _player = GetPlayer();
var _itemList = "";
var _var1 = _player.GetVar('var1');
var _var2 = _player.GetVar('var2');
var _var3 = _player.GetVar('var3');
var _var4 = _player.GetVar('var4');
var _var5 = _player.GetVar('var5');

if( _var1 == true ) _itemList += "Hat";
if( _var2 == true ) _itemList += "Boots";
if( _var3 == true ) _itemList += "Scarf";
if( _var4 == true ) _itemList += "Gloves";
if( _var5 == true ) _itemList += "Coat";

if( _itemList == "" ) _itemList = "nothing";

console.log("_itemList:"+_itemList);

_player.SetVar("finalItemList",_itemList);

console.log("JS DEBUG --- ending javascript.");

Depending on when and how you want your final results slide to display, I would suggest that you should place this javascript on a trigger for "When Timeline Starts..." or even on a separate layer which you can then "show" at any point you need to. In certain circumstances, this gives a little better adaptibility than "when timeline starts" triggers.

NOTE - you will need to change the 'var1', 'var2', etc to whatever your custom variables are called for each item of clothing. I have just gone with the classic var1 (never a good idea! - always better to call your variables something related to their actual use)

So if your boolean variable inside Storyline was called "hatChosen", then you would change line #5 of my code to:

var _var1 = _player.GetVar('hatChosen');

and so on with the other variable names.

The Output:

So, this simple javascript just returns a string. This string will be made of the names of each item of clothing chosen.

eg.

"hatgloves"

"hatglovescoatboots"

"glovescoat"

"scarfbootscoat" etc etc

From that string, you should be able to create a separate trigger to show whichever layer is required. Again, for ease of updating and adaptability, I would always put this on its own layer called "GetItemList" and then "show" this layer whenever its required.

Im sorry that we are unable to get javascript to do everything including showing the correct layer - that would of course be much simpler and more efficient, but at least this way all those reams and reams of "if" triggers in Storyline are removed, and you are left with a relatively small, and very easy to update, single trigger for each of your results layers.

Let me know if I can help in any other way, or if Ive blundered above and missed out an important part!

Andrew Hanley

Top Tip -  always have the "console" open in your browser (usually found under the Developer Tools menu or similar) when checking your javascript. That's why I always include the lines

console.log...

because it gives us a clear indication of when our JS actually runs, as well as enabling us to quickly output and view variables within our code.

Andrew Hanley

Hi Dave.

Thats very true, thanks for sharing. I hadn’t factored that in before so it’s great to know that.

However in this particular example, I think it wouldn’t reduce the trigger count because Mary will still require a “show layer A if answer A” scenario. 

I wonder if there is another refinement which would go this last step for her? I can’t think of it!

Mary Beth Faccioli

Hi Andrew and Phil,

I'm not finished working with Andrew's javascript for all of the images, but in testing with 6 illustrations, it's working BEAUTIFULLY!

Andrew, if you have a paypal I'd be happy to drop you a big tip for providing this solution!

Phil - this could be also done with states, as Ned was offering above. I'm going to finish with Andrew's solution, using the layers I've already created, and if that works well in terms of processing time, I plan to go with it in the sake of saving development time. Do you have a sense that triggering states instead of triggering layers would be more efficient in terms of processing? The same number of triggers would be needed. Instead of 26 layers, I would need 26 states. I'm not able to share the illustrations publicly, but they are each custom for each of the conditions.

Andrew Hanley

@Mary - that’s awesome! Really good job and well done on getting it up and running. I’m delighted! (And no paypal required at all - but thank you very much for your kind offer, it’s very much appreciated)

 

@Phil - very good point about the states I hadn’t considered that option. However, I find States within Storyline much more cumbersome to work with than Layers.

So I’m curious if there is something you know that I don’t! :D

Even if Mary used States as opposed to Layers, wouldn’t that still require a long list of triggers to manage the States to display correctly?

Phil Mayor

I always find states to have less of an overhead than layers, but for illustrations you need a little more work to ensure they are the same size and do not move. Best of this is done on export in illustrator. But if they are all the same size you could create all the states in one go using the import function.

I would still use the JavaScript to control especially with 20+ variations, I just find it odd it is taking long to load.

States at the moment feel a bit laggy in the editor, I hope this will improve.

Sent from my iPhone

Andrew Hanley

Re: loading speed

Storyline loads all assets of a slide (layers, states, etc) when that slide initially displays. Therefore I guess you are asking for quite a bit to load before your Results slide can run.

Might it be better to have each of your results illustrations on a separate SLIDE instead, and then just “jump to slide” rather than “show layer”?

That way you are only ever loading one image at a time.

Mary Beth Faccioli

Andrew - I think you're right. I will consider changing this, although this is going to make my story view unviewable. I actually have three different games in one, and the learner clicks to go through each. So, three sets of characters, each in it's own scene, with this need for 26 different conditions each scene. But that's okay - I'm glad to have this in the pocket to test if needed. And it will be interesting to see what the story view looks like in the end lol.

This discussion is closed. You can start a new discussion or contact Articulate Support.