Delaying a function in Captivate’s Javascript window

Hello, I’m working on a project in Captivate 2017 and have a slide where I’d like an object to animate in, I am animating it in the javascript window (the on enter action of the slide) and I have it written like:

var keyframes = [
{
transform:’scale0.4)’
},
{
transform:’scale1)’
}
];
var options =
{
delay: 1000,
endDelay: 0,
duration: 500,
easing: ‘ease-out’,
}

I’d like it to animate on it’s own (not based on user interaction), but not until after a second or so.  With the delay in the options variable that works, however I’d like the object to not be visible until the animation starts.  I tried writing something like:

cp.hide(‘bar’);

function playAnim(f,g,e){
cp.enable(f);
g();
pAnim = e.animate(keyframes, options);
pAnim.play();
}

function unhideBar(){
cp.show(‘bar’);
}

setTimeout(playAnim(‘bar’,unhideBar,barc), 1000);

but the setTimeout method does not seem to be working? (I’ve never used setTimeout before so I’m not sure if I’m using it correctly).

I also previously tried writing it as window.setTimeout …. but that didn’t work either.

Any advice is much appreciated, thanks!

The post Delaying a function in Captivate’s Javascript window appeared first on eLearning.

Advanced Actions, Shared Actions, or JavaScript – Which one is right for you?

When you build your eLearning project with Adobe Captivate you have several options for customizing the way the elements or components of your project work. You can control almost every aspect of your project with Advanced Actions, Shared Actions, or JavaScript but how do you know which approach is right for your project?

When I first started working with Adobe Captivate I used Advanced Actions almost exclusively. Part of this was because they worked and part of it was because I was intimidated by Shared Actions and JavaScript. Two things I took away from building a few eLearning projects using only Advanced Actions are 1) it’s a perfectly acceptable approach, 2) it will likely result in the size of your project increasing. I found that the biggest advantage to using Advanced Actions, at least for me, is the ease of troubleshooting and making changes. It’s easy to tweak an Advanced Action when you want to change how something works and, if something isn’t working properly, it’s easy to pinpoint the mistake in an Advanced Action because you can “see” all of the commands in the action and what they are assigned to. The biggest drawback that I have witnessed to Advanced Actions is that the need to build many Advanced Actions can quickly lead to unnecessary bloat in your project. I often found myself writing the same action over and over because I needed to apply it to different buttons or different slides and before I knew what was happening I had 15 Advanced Actions that all did the same thing.

When I overcame my intimidation with Shared Actions I was able to turn those 15 Advanced Actions that did the same thing into 1 Shared Action and apply it in all 15 places that I had used the Advanced Actions and tis, I believe, is the greatest strength of a Shared Action. If you plan ahead, you can build a handful of Shared Action that you can use over and over; getting the same results you would with Advanced Actions without the project size and without the wasted time building additional actions. Another big advantage of Shared Actions is the ability to “share” actions between projects. If you have an action that is common across many of your projects you can export the action from the original project, save it on your computer, and then import it into another project when you need it. Shared Actions may be a step up from Advanced Actions but they aren’t without their drawbacks. You can’t directly edit a Shared Action once it’s been created, instead you will need to use the Shared Action as a template or model for building a new Shared Action. Another potential drawback is troubleshooting, because you can’t “see” what’s inside a Shared Action you are dependent on the names you, or the person who built the Shared Action, provided for the Shared Action’s parameters. This drawback can be mostly avoided with good authoring practices.

A word (or two) about JavaScript. There are very few things I have done using JavaScript that could not be accomplished with either Advanced Actions or Shared Actions. What I have found is that I can often increase my build speed (sometimes dramatically) by using JavaScript and, honestly, there are things I need to do in some of my more advanced projects that I can’t do with either Advanced or Shared Actions.

So, what do I use when I build a project? I usually use mostly Shared Actions with a few Advanced Actions and some JavaScript thrown in. It isn’t unusual for me to build a short Shared Action with some JavaScript attached to it. For example, I might have an Shared Action that allows the author to set the value of a variable and then execute some JavaScript I have attached that performs different functions based on the value of the variable. Could I have done this without the JavaScript? Yes, but if the Shared Action gets over complex and requires the author to input a bunch of parameters each time the Shared Action is used the using JavaScript for that part of the process can be a big time saver in the authoring process.

One final thing, I expect some of you may be thinking, “I don’t know JavaScript, should I learn it?” Should you learn it, it certainly wouldn’t hurt but it isn’t necessary either. Learn Captivate first. Learn what you can do with Advanced Actions and Shared Actions and  then worry about whether or not you should learn JavaScript.

The post Advanced Actions, Shared Actions, or JavaScript – Which one is right for you? appeared first on eLearning.

Creating a free-text question and using quiz variables

I am working on a quiz question in Captivate and I’m not sure if I am going about it the right way. My plan was to keep poking through previously answered questions, but couldn’t find exactly what I’m looking to find.

I want to create a quiz question that requires a user to input a value, but the question needs to be dynamic and change each time the user accesses the course. I have already successfully created my variables, but I’m not familiar with the different system quiz variables that exist. I’ve learned that many of the quiz variables need to be adjusted using JavaScript, but I don’t know what I should manipulate in my JavaScript.

I tried using the generic “fill in the blank” quiz question, but this will not work as far as I can tell because I can’t add a variable as a “blank” to keep the question dynamic as I mentioned before.

Here is a simplified version of my variables and the associated question:

X = random number between 2 & 5

Y = random number between 0 & 5

Z = X + Y

Given the values of variables X & Y, provide the value of Z

I have been able to create my variables and they function great. My thought was to have users input their response in a free-text box and then use advanced actions to add points to the learner’s score if the free-text box variable matches the “Z” variable in the problem presented. However, I found most of the system quiz variables cannot be manipulated using the advanced actions. So now I am left to do this through JavaScript. This would be fine, except that I am worried I won’t be getting the results I want if I just increment variable cpQuizInfoTotalCorrectAnswers by 1.

My next step is to just play around with the variables and hope I don’t mess up my project too much.

Has anyone tried to do this before and can help me out? If there is another way to do this right within the UI without JavaScript, that would be great! Just let me know

Thanks!

NOTE: Attached below is my project. It is still in the beginning phases, but gives a concept of the variables. In the final result, the user will only see limited variables (the values listed in the black box) and will have to input the value of the other variables by performing their own calculation. Ignore the formatting, as this will eventually change.

Play

The post Creating a free-text question and using quiz variables appeared first on eLearning.

Moving an interactive object off the stage…can I?

I’m attempting to use JavaScript, on-enter to a slide, to move a button off of the stage and later move it back on when it is needed.  I’m not using show/hide for reasons that aren’t germane to the question I’m asking.

I’ve done this before with images…moved them off of the stage with JS “on-enter” and then animated them onto the stage when a button is selected.  I’m actually able to animate the button in question and move it around with JS, but I can’t make it move off of the stage on-enter.

At this point, the only explanation I can think of is that Captivate won’t let me move an interactive object completely off of the stage.

Does anyone have any info or have experience with this?

Thanks.

Jay

The post Moving an interactive object off the stage…can I? appeared first on eLearning.

Random Animated Spinner

Overview

There are lots of fun ways to include randomness into your learning interactions. For example, your design might include a point system, and every correct response the learner gets a change to spin a wheel to earn a random amount of points. Or you may have designed your learning as a board game that requires learners to ‘randomly’ travel across a board. Each board square would offer different challenges, information or rewards.  You could also have a scenario where you offer series of challenges or obstacles that are randomly selected.

This blog tutorial covers how to create your own animated spinner.  As a warning this tutorial uses a lot of javascript and some basic geometry. There are lots of ways to modify this method, and of course change the design to look much nicer.

I will attempt to explain a little bit of the javascript at the end.   Please feel free to download the example .cptx file.

randomSpinner

*Note that for the purposes of this tutorial, I will be using a 6 section wheel, with the arrow’s starting point at 90 degrees.  This can all be modified, but the numbers would need to be altered. 

Step 1: Create your image assets

  • Import an image of a wheel with 6 sections.    I aligned the image horizontally and vertically on the slide. Note that the arrow should align with the 90 degree section on the wheel.
  • Import an image of an arrow pointing at 90 degrees (i.e. to the right). Align horizontally and vertically as well.  Give the arrow the id ‘arrow’.
  • I added a little Captivate shape circle in the center as well.
  • Add the text to each section (I used numbers, but you could substitute for words as well.

Step 2: Add variables

  • Click project –> variables.
  • Add a variable called ‘prize’ with the value of 0

Step 3: Add Textbox

  • Create a textbox with the id ‘txt’ and hide it from view
  • Have it display the variable ‘prize’

Step 4: Create and program Spin Button

Create a shape and use as a button.

On press Execute the following javascript:

var eRot = Math.random() * (2520 – 2160) + 2160;
cp.hide(‘txt’)

switch (true) {
case (eRot < 2220):
prize = 3;
break;
case (eRot < 2280):
prize = 4;
break;
case (eRot < 2340):
prize = 5;
break;
case (eRot < 2400):
prize = 6;
break;
case (eRot < 2460):
prize = 1;
break;
case (eRot < 2520):
prize = 2;
break;
}

arrowc.animate([
{
transform: ‘rotate(0deg)’,
transformOrigin: ‘center’,
},
{
transform: ‘rotate(‘ + (eRot) + ‘deg)’,
transformOrigin: ‘center’,
}
], {fill: ‘forwards’, easing: ‘cubic-bezier(0, 0, 0.10, 1)’, duration: 7000 }).onfinish = revealPrize;

function revealPrize(){
cp.show(‘txt’)
}

Explanation of Javascript (for those interested )

There are two main principles used in this script – the animation and the random number.

Random Number

When the script is executed, the variable eRot is assigned a random number between 2160 – 2520 and evaluated in a switch statement.  Why 2160?  I wanted the arrow to rotate 6 times before stopping.  So 360 x 6 = 2160  and add another 360 gives you a range between 2160 and 2520.  Therefore the arrow will spin five times and then stop somewhere between 1 and 360 degrees.

The ‘switch’ statement evaluates eRot and determines what to set ‘prize’.  Because there are 6 sections (360 / 6 = 60) each section is 60 degrees.  Therefore stopping anywhere between 2160 and 2220 will give you the ‘3’ wedge.  (Remember that the arrow started pointing at 90 degrees).   This is how the random number corresponds exactly with the prize number.

Animation

I have a few other blog tutorials on animation but will point out a few additional details here.

https://elearning.adobe.com/2018/01/how-to-animate-buttons-and-lots-of-other-cool-javascript-stuff/

https://elearning.adobe.com/2018/03/animated-scale-drag-drop/

I am using a transform rotate animation and have set the transformOrigin to center (so that the arrow will rotate around the middle).

transform: ‘rotate(0deg)’,
transformOrigin: ‘center’,

On the second animation ‘frame’ I set the rotate to eRot using

transform: ‘rotate(‘ + (eRot) + ‘deg)’,

For the options I’m using a custom easing (using a ‘cubic-bezier’)  so that the arrow slows down gradually.

easing: ‘cubic-bezier(0, 0, 0.10, 1)’

The other feature on this animation is it uses a callback function. Essentially this executes another function when the animation ends.

.onfinish = revealPrize;  //executes revealPrize when the animation ends

I then create a function called revealPrize that shows the text box.

cp.show(‘txt’)

I hope this will be useful to some people in their projects.  Please feel free to comment or ask any questions about the script.

The post Random Animated Spinner appeared first on eLearning.

Two ways to Build Interactive ‘Selector Bars’

Overview

My last blog tutorial showed how to add a slider bar:  https://elearning.adobe.com/2018/06/add-slide-bar-projects/

This tutorial covers two ways you can create a ‘selector bar’.  With a selector bar, the learner uses button clicks to control the input level.

This tutorial uses much less javascript than the slider bars tutorial – however it does use some.  As always the sample file can be downloaded here:

selectorBars

Step 1: Create the Selector Object

  1. Create a rectangle shape on your slide.  Give the rectangle the id ‘obj’.
  2. Select the rectangle and click ‘State View’.  In the ‘Normal Default’ slide add as many circles as you want.  In my example, I use ten.
  3. Duplicate the ‘Normal Default’ slide for as many circles as you have.  In the sample I have ten circles, so I added ten more ‘state’ slides – 11 in total. You can keep the default names ‘NewState1’ etc.
  4. For the first state slide ‘NewState1’ add a fill to the first circle.  For the next state slide ‘NewState2’ fill the first and second circle. Complete the sequence until all circles are filled.
  5. By the end you should have a rectangle with the id ‘obj’ and 10 additional state views – each view filling more circles

+ / – BUTTONS VARIATION

Step 2a: Add Variables

Under Project, click variables. Add a new variable named ‘click’ and give it a value of 0

Step 3a: Create your +  Button

Create a shape. Add a ‘+’ on it.  Click use as button.  On click execute javascript and add the following script:

var stateMax = cp.model.data.obj.stl.length – 1
var lastState = cp.model.data.obj.stl[stateMax].stn

if(cp.getCurrentStateNameForSlideItem(‘obj’) ==lastState){
}
else {
click = click + 1
var newState = cp.model.data.obj.stl[click].stn
cp.changeState(“obj”, newState);

}

I will explain – for those interest what the javascript means at the end of this tutorial.

Step 4a: Create your –  Button

Create a shape. Add a ‘-‘ on it.  Click use as button.  On click execute javascript and add the following script:

if(click ==0){
}
else {
click = click – 1
var newState = cp.model.data.obj.stl[click].stn
cp.changeState(“obj”, newState);
}

Again, I will explain the javascript at the end of the tutorial.

CLICK ON SELECTOR VARIATION

Step 2b: Create ‘invisible’ buttons

For each circle on your selector, create an invisible button (a shape with 0 alpha fill and outline).  Click ‘use as a button’ and delete the rollover and down state views.  On click execute javascript and add the following script:

cp.changeState(“obj”,NewState1);

You will then have to add the correct stateName for each button (i.e. NewState2, NewState3, etc.)

Explanation of Javascript

The only complicated javascript I believe is using the first method with the + / – buttons.  So I will cover a bit of the scripting here.

I use the cp.model.data to retrieve information of the Captivate objects.

For example, the script “cp.model.data.obj.stl” returns the array for the different ‘states’ of ‘obj’.  The “.stn” returns the state name as a string.  Therefore “cp.model.data.obj.stl[0].stn” would return the “Normal”.  This means you can use a variable integer to change the state of an object.

The script uses the variable ‘click’ as that integer.  Here are some comments for the script.

var stateMax = cp.model.data.obj.stl.length – 1   //Sets ‘stateMax’ to the total length of the stl array
var lastState = cp.model.data.obj.stl[stateMax].stn // sets lastState as the string of the last item in the stl array

if(cp.getCurrentStateNameForSlideItem(‘obj’) ==lastState){
}  // If the current state is equal to the ‘laststate’, it will do nothing
else { // If the current state is not equal to the ‘laststate’ it will do the following
click = click + 1  // add 1 to click
var newState = cp.model.data.obj.stl[click].stn  //set newState to equal the string name in the stl array (identified from the click integer)
cp.changeState(“obj”, newState); //Changes ‘obj’ to the new string

}

Additional Notes

I know there are probably other and possibly easier ways to achieve this, however I find this would save time if you had an object with many different states. ‘If statements’ in advanced actions can get a bit out of hand if you have many.

The script essentially provides the ability to control a state based on an integer, rather than relying on the state’s name.  I think there could be other possible applications for this. For example, you could have final score on a quiz that would could then determine which state is visible.

Please feel free to write any comments or ask any questions.

Enjoy.

The post Two ways to Build Interactive ‘Selector Bars’ appeared first on eLearning.

Runtime Conditions or Variables For Dynamic Text Entry Fields in Articulate Storyline 360

We came across a customization request from our client, Runtime auto update input field values. In order to fulfill the requirement, we used JavaScript. Following is a brief description of the step by step process of Runtime Conditions/Variables for dynamic text entry fields in Articulate Storyline 360. Step 01: Create as many input fields as…

Changing States vs Animation – (A Reason to Learn JavaScript)

At some point in your life you very well may have heard the phrase – “There is more than one way to skin the cat.” – not sure where or how that originated but I think most of us understand the meaning behind this idiomatic expression.

Creating projects with Captivate is no different. Arriving at your desired result could very well have taken any number of pathways. However, as much as those results might be the same, there can also be some subtle differences that can potentially make an impact on final presentation. I happen to think that it is good for us as developers to learn multiple ways to get the job done and then be able to choose which way provides the better impact. In many cases, there will be no marked difference, and so you may as well go with the method that is the quickest and easiest.

I think one of the areas where differences can be seen is when we compare state changes and animations. Now, you might feel differently and, to be sure, this is a subjective thing without any right or wrong answer per se. We’re merely talking about preferences here. Nonetheless, I find it to be an interesting topic for discussion and I will allow you to decide for yourself.

In my example, I have provided two of the seemingly exact same status indicator. The only difference between them is the manner by which they function.  The indicator on the left uses the native Captivate ability to change states to move the bar while the indicator on the right uses JavaScript to animate the bar.

The premise of the interaction is simple – pick items on the list to take with you that do not exceed 25 pounds. Click on the ‘Check Weight’ button to see where you come in. As you do so, pay attention to how the status indicators respond. Which do you prefer? Here is the link to the working comparison.

**Please note that I have no idea what the weights of these things are. I just picked some values that I thought might be close so try not to hold that against me. ** 

https://s3.us-east-2.amazonaws.com/captivateshare/meterClimb/index.html

Same end result. Subtle difference in presentation. The snap versus the glide.

Don’t get me wrong. I love the ability to do state changes and use them often. However, I always think it is worth the time to learn new skills and develop one’s craft.

If you plan to develop for years to come, I encourage you to take some time to enhance your craft and learn a little JavaScript. It can help you to create some experiences that have a little something extra above your competition.

The post Changing States vs Animation – (A Reason to Learn JavaScript) appeared first on eLearning.

Animation of Objects – Three Examples (Part 2)

This is the concluding post for the animating objects post from earlier.

If you missed the post with the examples, you may want to check it out.
Animation of Objects (Part 1)

In this post, I want to go through and explain the code behind how the animations work.

I will address this all in five parts.

  1. Initial Issues
  2. The Single Button
  3. The Two Button
  4. The onEnter Action
  5. The Indicator Bar

Initial Issues

Initially, I had created an arrow and then another state for it. From a sequencing standpoint, I had the arrow go off the screen, change state, then come back on. However, it was very choppy. I realized that my command to change states was causing the second state to ‘snap’ into position rather than slide back on like the other arrow slid off. Then I tried another approach. I thought I would try placing the second state off of the stage. I figured that way we would not see the snapping and it could slide onto the stage. That simply didn’t work at all, I think, because it was off of the stage. This is what led me to my work around which I will cover with the onEnter action.

The Single Button

On the round trip button I decided to implement a variable called  arrowVis  to track which of my arrows was currently on the screen. So the variable toggles between two values: up or down. My starting point is with the up arrow visible so the default value for  arrowVis is “up”. This allows me to do a check for the arrow on stage and perform a slightly different action based on that.

So, if the visible arrow is the up arrow – we are going to animate it to the left by adjusting the left margin by -300px over the course of 500 milliseconds. Then the down arrow will slide on the screen by adjusting the left margin of that arrow by 150px. I have this on a setTimeout for two seconds so that the other arrow has time to get off the stage and give a pause before it comes on. Finally, after 2.5 seconds, which should be the time for the swap to complete, I change the variable to reflect the new item on stage. This is the way I managed to keep the variable correct so that I did not have conflicts.

if (window.arrowVis==”up”) {
$(document).ready(function() {
$(“#upc”).animate({left: “-300px”}, 500);
});

setTimeout(function() {
$(document).ready(function() {
$(“#downc”).animate({left: “150px”}, 500);
});
},2000);

setTimeout(function() {
arrowVis=”down”;
},2500);
}

if (window.arrowVis==”down”) {
$(document).ready(function() {
$(“#downc”).animate({left: “-150px”}, 500);
});

setTimeout(function() {
$(document).ready(function() {
$(“#upc”).animate({left: “0px”}, 500);
});
},2000);

setTimeout(function() {
arrowVis=”up”;
},2500);
}

The Two Button

In this animation, we are basically doing the same thing but with a picture rather than an object and through the use of two buttons rather than one.

In essence, the core code that does the animating work is the same but I had to work in some extra code to tweak performance. You will notice that on the swap button, we move the normal picture off stage and bring the hex version on about a second later. You will also notice that I disable the buttons during the animation and re-enable them afterwards. That is because I was able to mess up the animation by clicking too fast on the buttons. I allowed you to see both of them together at some point.

SWAP Button
$(document).ready(function() {
$(“#sunc”).animate({left: “400px”}, 500);
cp.disable(“swap”);
cp.disable(“swapBack”);
});

setTimeout(function() {
$(document).ready(function() {
$(“#hexSunc”).animate({left: “0px”}, 500);
cp.enable(“swap”);
cp.enable(“swapBack”);
});
},1500);

SWAP BACK Button
$(document).ready(function() {
$(“#hexSunc”).animate({left: “400px”}, 500);
cp.disable(“swap”);
cp.disable(“swapBack”);
});

setTimeout(function() {
$(document).ready(function() {
$(“#sunc”).animate({left: “0px”}, 500);
cp.enable(“swap”);
cp.enable(“swapBack”);
});
},1500);

The onEnter Action

So both of the swap animations suffered from the same issue – getting a smooth swap animation. It seemed that as long as the object started on the stage and was animated off that I could bring it back just fine. The trick was making the object animate off of the stage without being able to see it. Now I will admit that there is probably a better way to do this with code but I am not an expert in JavaScript so I went with a white box to hide the object as it animated off onEnter. So I actually start with all the objects on the stage and animate two of them off to their hidden locations. Once they are off stage, I hide the white boxes so that they don’t block the objects animating on.

$(document).ready(function() {
$(“#downc”).animate({left: “-150px”}, 10);
$(“#hexSunc”).animate({left: “400px”}, 10);
});

setTimeout(function() {
cp.hide(“cover”);
cp.hide(“cover2”);
}, 1000);

The Indicator Bar

I wanted to also make a form of this that could be a bit more controlled. To pull this off, I created a variable called chevronPos to track the position of the chevron along the bar. Then I can make sure it does not slide past the edges of the bar. So on the back button (red), our start position, we simply state that as long as the position is not equal to 0, go ahead and move the chevron back 40px. On the green arrow we do the same thing only we are saying that as long as the chevron position is not equal to 640 we can go ahead and move 40px to the right. On each button press we also adjust the variable value up or down accordingly.

if (window.chevronPos!=0) {
chevronPos=(chevronPos-40);
$(document).ready(function() {
$(“#chevronc”).animate({left: “-=40px”}, 500);
});
}

if (window.chevronPos!=640) {
chevronPos=(chevronPos+40);
$(document).ready(function() {
$(“#chevronc”).animate({left: “+=40px”}, 500);
});
}

Hopefully this was helpful in giving you some new ideas for you projects.
Please feel free to share your ideas and ask any questions that you have.

The post Animation of Objects – Three Examples (Part 2) appeared first on eLearning.