Intro
This is not the first time I publish about creating a Custom Short Answer Question. The default type in Captivate is pretty limited: the user should enter exactly the same answer as the defined correct answer which is almost impossible with this type of question. The normal validation for such a question is to check if some keywords are present, and eventually if some other keywords have not been used. My previous posts were created with Captivate 5 for publish to SWF only:
Widgets were meant for SWF-output only, including the widget by Jim (this one, he has some widgets that are also compatible with HTML5). Since Captivate 7 the TextArea widget got a companion, the 'Scrolling Text Interaction'. Don't be confused by the name, it is essentially the same widget, but compatible with HMTL5 output.
This week I accepted another challenge from a Captivate user on the forum, concerning the use of TextArea (or Scrolling Text) with a more complicated condition than the one I described in the previous blog posts: How to verify that a variable "does not contain" a value? As you probably know, the operators in the IF part of a conditional action are bit limited: there is an operator 'contains' but no negative counterpart. My first reaction was to propose the use of JS, but my intuition told me I should also try with advanced actions. This post will explain how I solved that problem, and I was very happy when the King of Javascript in Captivate, Jim Leichliter posted his alternative with JS in the same thread, scroll down to find the script.
In this post I will explain the conditional advanced action, and also point to another well-hidden gem, only in Captivate 8: the Captivate team has now embedded the variable control in the Scrolling Text Interaction! Don't tell that they are not listening to users :) What was only possible with the extended TextArea widget by Jim in previous versions, can be done with the supplied Scrolling Text Interaction.
Challenge
The description of the problem: " We are basically validating the content in the widget and showing appropriate feedback. Since the user can enter anything in the widget, we are only tracking the keywords. To be precise, we are trying to create an Advanced Action like this, where the text entry should contain the words Organizational, Behavioral, and Managerial but not the words Transformation and Non-Compliance. If the entry contains any of the "illegal" words, then incorrect feedback caption should appear."
Translated: when the answer is submitted, the conditional action should show a Positive feedback when:
- the three first words are included in the text
- the last two words are not included in the text
If those conditions are not all fulfilled, the Negative feedback should be made visible.
Because of the missing operator 'does not contain' this cannot be done with one decision, one IF combination using AND, which explains why the user was stuck.
Solution 'Divide et Impera'
After a long career as professor, this has become one of my mottoes: make it simple by splitting up the problem:
- Check first if all the conditions are fulfilled and store that result in a Boolean variable. There are a lot of Booleans in Captivate: variables that can have only two values, No/Yes, 0/1, False/True. I will mostly choose for the 0/1 combi. I created a user variable v_TA_OK with a default value of 0 (meaning all conditions are not yet OK)
- Show the appropriate feedback based on the value of that Boolean.
This was possible because of the typical way Advanced actions are executed in Captivate:
- all statements are executed in sequence and
- all decisions are executed in sequence
- the action is not stopped when a positive condition is met
This has led to a conditional advanced action with three decisions.
Movie
Watch this movie, created with Captivate 8, customized theme 'Flat', using custom shape buttons (one is a freeform shape) with three states and the new Scrolling Text Interaction.
Advanced actions - variables
Variables
To make the question more universal, I didn't use literals for the words, but stored them into variables. These variables were created:
-
v_one, v_two, v_three to store the words (can also be more words in one variable, but they'll have to appear in that sequence) that have to be included in the answer
-
v_notOne and v_notTwo for the words that are forbidden in the answer
-
v_Answer to be associated with the TextArea or Scrolling Text that will store the value typed in the answer
-
v_TA_OK: the Boolean variable explained above; default value = 0, will only be set to 1 if all conditions result in correct.
-
v_null: an empty variable that is needed to create conditions for the other advanced actions (as the ones that check if all word fields have been filled); I will not explain those actions here; more info: Where is Null?
Conditional action Check_Short
This action is triggered by the Submit button on the Short Answer slide. This was the answer to the problem presented at the beginning. I will not explain the other advanced actions like the one triggered by the Reset button or the different actions On Enter for slides to reset the situation to normal. The action has 3 decisions:
OKWords
This decision checks if all the imposed words are present in the Short Answer, using the operator 'contains', with AND combination. If that is the case, the Boolean v_TA_OK will be set to 1.
NotOK
The not-allowed words are checked with this decision, using again the operator 'contains' but this time in an OR combination, because even if only one of those words is present, the negative feedback has to appear. If any of the words appears, the Boolean v_TA_OK is reset to 0. It is very important that this check only occurs after the first decision! After this second decision (in this case) all conditions have been evaluated and the Boolean variable v_TA_OK has its final value, will be used in the last decision
FBack
Only this last decision has also an ELSE part, as you can see in the total view of this conditional action:
As I explained in the last slide of the movie, because of the stack order, where an Interaction always is on top even though it is not on top in the Timeline, I had to hide the Interaction to be able to show the Feedback groups, because they were in the same location. Here is the Timeline of this Short Answer slide:
You see that the Interaction (indication is Widget on timeline) is not on top. The Next button is not on this slide, but on the first slide and timed for the rest of the project. That shape button is hidden/shown when necessary.
Tips
Variables are case sensitive, and contrary to validation of a Text Entry Box it is not possible to get rid of that case sensitivity for variables associated with this interaction. If necessary you'll have to create more decisions.
I wanted to emphasize the importance of sequence by this blog post, and the fact that Captivate will always evaluate all conditions/decisions. This is not always the case in normal programming languages. Trying to explain:
- The first decision is positive, variable v_TA_OK will be set to 1, but there will not be ending of the condition
- If the first decision is negative, variable v_TA_OK will remain at 0, no need to include an ELSE part. This means that the variable can never be set to 1 anymore, but the second decision will nevertheless be checked by CP.
- If both negative words are not included, nothing happens with the second decision, v_TA_OK will keep its value 1 or 0 depending on the result of the first decision, because there is no ELSE part.
- If one of both negative words are included, the second decision will reset v_TA_OK to 0, whatever its value was at the end of the first decision
The new possibility in Captivate 8 to change the value of the variable associated with the Scrolling Text Interaction and have this displayed in the interaction is important if you remain on the same slide. Contrary to the extended version of Jim's TextArea widget, the rule that variables for each interaction are cleared when you leave the slide is also applying to the Scrolling Text. If you want to keep value of the variable you have to transfer it to another variable.