SVGs for custom Hotspot question

Intro

About 5 years ago I published this blog explaining the workflow for such a question using shape buttons. The embedded example in that blog was of course a SWF output.  With release 11.5 the possibility to use SVG’s as buttons, and to control the clickable area, combined with multistate object made me feel it is time to update this old post.

Why a custom Hotspot Question?

The default hotspot question slide has several limitations. To me the most frustrating limitations are:
  • hotspots have to be rectangular
  • partial scoring is impossible
With a custom question you can have
  • hotspots with any shape
  • partial scoring, which still can be reported to a LMS
  • full control

Limitations of custom questions

  • developing custom question slides always takes more time
  • although the total score will be correct when using partial scoring, some quizzing system variables will consider each correct hotspot as separate question. You need to keep that in mind for the fields in the score slide (number of questions/correct questions not correct)
  • to the full functionality (Retake/Review) takes a lot of time.

In this post I will show a pretty simple example, no retake/review but with the possibility of having the score stored in the quizzing system variable cpQuizInfoPointsscored.

Example

Have a look at this two-slide file (rescalable HTML5). On the first slide you will be asked to click 4 West-European countries. On a correct click, the country flag appears bottom left. You will not be able to click that country anymore. Move to the second slide (Next button) to see the final score.

Please be a bit patient when you see a ‘pink’ feedback (which is the correct style). It may be due to the amount of SVG’s on the slide, but it takes time to hear the audio and see the flag appear and animated.
If the embedded movie is too small for your device, you click this link.

Setup

Look at the screenshot, which shows the Timeline and the Properties, Actions tab for one of the non-correct SVG-buttons  (Luxemburg). In the Style tab, the option ‘Enable Click in Bounding Box’ is disabled to limit the clickable area to the shape of the SVG itself (see recent post). In the screenshot both groups (countries/flags) are expanded. 

For the SVG buttons (countries) Success message is activated and used to display feedback. Those messages have two different styles: grey for the wrong clicks, and pink for the correct ones. After the correct message, an audio clip sounds and the flag of that country will appear at the bottom left. Both for correct and incorrect SVG’s the state will change to the Visited state when clicked: That visited state is grayscale for incorrect clicks. No advanced actions needed so far.


Actions

The on enter event of the question slide triggers the simple action ‘Hide Gr_Flags’

Success event for the correct countries, needs an Advanced action. In this case a user variable will store the score. It is not really necessary because the clicks are reported and have a score, the system variable cpQuizInfoPointsscored will have the correct scoe as well. Have a look at the action for Belgium:

The first three commands are self-explanatory. Why did first apply the effect (line 4) to the group, and wait 0,1 sec before showing the flag? Because that will avoid flickering, a trick I learned from another user many months ago.

Duplicate that action, and edit it for the three other correct SVG’s.

Why did I not use a Shared Action?

If you are a fan, you know that I mostly use Shared actions when possible. This was also the case for this example.Of course, I created first a shared action. But a strange phenomenon appeared: the Effect was not applied for each instance of the shared action, only for the first one. I wanted the whole group to be animated after a correct answer. Yes, I could have ungrouped and changed the action, but then that meant another advanced action On Enter for the slide (where I now hide the group). Moreover I like to have the effect emphasize the whole group instead of one flag.

Still looking out for the reason of this non-consistent behavior. Really this is the first time I encounter a difference between an advanced and shared action behavior. Be sure, will update this post when I have an answer.

Custom Short Answer Question

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:
  1. 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)

  2. 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:
  1. 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

  2. v_notOne and v_notTwo for the words that are forbidden in the answer 

  3. v_Answer to be associated with the TextArea or Scrolling Text that will store the value typed in the answer

  4. v_TA_OK: the Boolean variable explained above; default value = 0, will only be set to 1 if all conditions result in correct.

  5. 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.