The Review Area.
Some people love it, most people hate it, either way it’s an aspect of Question Widgets, and Question Widgets are what I’m teaching.
What is the Review Area?
In theory, the Review Area is supposed to supply the audience feedback on how they answered the question. When they answer it correctly, the Review Area has the stock response of ‘You answered this correctly!’ It’s when the audience gets the question wrong where things get complicated. The general consensus is that there is only one correct answer and many wrong answers. Not that this is true in real life, but that’s how it works in Captivate. So although you can only have one message for when the answer is correct, which is controlled in the Review Area’s properties…
…You could have potentially unlimited messages for each way the audience can get the question wrong. So Captivate allows the widget to take control of what feedback will be given if the question is incorrect.
This feedback is controlled by WidgetFactory’s Answer objects.
The Review Area and Question Widgets
Here’s the theory: You create an answer object to represent how the audience answered the question. These answers, once created, are added to an answer list. Then after the question has been submitted, Captivate takes the answer list and displays it in the review area.
An answer object has three properties, each of which are Strings:
- answerID: Something to identify this answer object when it is dealt with by compareAnswers (See next section)
- chosenAnswer: What will appear in the ‘Your Answer’ section of the Review Area.
- correctAnswer: What will appear in the ‘Correct Answer’ section of the Review Area.
So here’s what you do:
- Import the Answer class: import widgetfactory.Answer;
- Create an Answer object: var answer:Answer = new Answer();
- The constructor for the Answer class, the () in the new Answer()bit, takes three parameters. These parameters correspond to the three properties above: answerID, chosenAnswer, and correctAnswer. answerID is required, the others are optional. So at the very least, you would have to have something like: new Answer(“answerIdentity”);
- If you don’t define chosenAnswer and correctAnswer in the step above, then use the answer object’s properties to assign them a value. For example: answer.correctAnswer = “Red”; answer.chosenAnswer = “Blue”;
- Add the answer to the answer list with QuestionWidget’s addAnswer() method: addAnswer(answer).
Let’s see how that looks in an example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package { import widgetfactory.Answer; import widgetfactory.QuestionWidget; public class ReviewAreaExampleOne extends QuestionWidget { override protected function submit():void { var answer:Answer = new Answer("answer1"); answer.chosenAnswer = "User's Answer"; answer.correctAnswer = "Correct Answer"; // You could also write: // var answer:Answer = new Answer("answer1","User's Answer", "Correct Answer"); // That would give you the exact same object. addAnswer(answer); } } } |
Click here to download this widget.Have a play around with the chosenAnswer and correctAnswer values and see how they come up in the Review Area.
You may be wondering what happens if you add multiple answers to the answer list.
1 2 3 4 5 6 7 | override protected function submit():void { var answer1:Answer = new Answer("answer1","User's Answer", "Correct Answer"); var answer2:Answer = new Answer("answer2", "User's Other Answer", "Other Correct answer"); addAnswer(answer1); addAnswer(answer2); } |
In that case, all answers are displayed in the Review Area separated by comas.
Note that Answers have no effect on how the question is scored. If the correctAnswer and chosenAnswer properties don’t match, it’s not going to score the question as incorrect. Scoring is ONLY handled by isCorrectAnswer.
For some Question Widgets, just a static response like “You got it wrong dude” will be fine. With other ones you may have a chance to give valuable feedback. For example, say you built a Question Widget that was a hangman game. If during the game you recorded what letters the audience guessed, then you could assign them to chosenAnswer, while correctAnswer held what the correct letters would have been.
Although this works quite well for hangman, as it is a text based game, it would be much more difficult to give meaningful feedback for a certain Drag and Drop widget.
There is however, another way Answers could come in useful.
Advanced Question Reviewing
Answers work in tandem with the compareAnswers Template Method. Let’s meet that method.
1 2 3 4 |
You may recognize some of those parameters. Yep, they’re the same as Answer class’ properties. When the audience reviews the quiz, compareAnswers() is called for each answer in the answer list. With this information about how the audience answered the question, the widget could provide some visual feedback to show how the question should have been answered. For example, what if we added some code to the Question Widget we made in Part 1 to make the button we pressed glow when we review the question.
All we need to do is add a few lines to the submit method and add the compareAnswers method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | override protected function submit():void { // Create the answer. var answer:Answer = new Answer("AnswerID"); // The correct answer is always going to be the same. answer.correctAnswer = "CorrectButton"; // Unless otherwise stated, the question is complete. isCompleteAnswer = true; // If the correctAnswerButton is selected... if (correctAnswerButton.selected == true) { // ...then the question is answered correctly isCorrectAnswer = true; // Set the chosen answer to be the same as the correct answer. answer.chosenAnswer = answer.correctAnswer; // if the incorrectAnswerButton is selected... } else if (incorrectAnswerButton.selected == true) { // ...then the question is answered incorrectly isCorrectAnswer = false; // Set the chosen answer to be the incorrect button. answer.chosenAnswer = "IncorrectButton"; // If no buttons are selected... } else { // ...then the question hasn't been answered at all isCompleteAnswer = false; } // Add our answer to the answer list. addAnswer(answer); } // Review quiz time override protected function compareAnswers(answerID:String, chosenAnswer:String, correctAnswer:String):void { // If the question was answered correctly... if (chosenAnswer == correctAnswer) { // ...make the correctAnswerButton glow green. correctAnswerButton.filters = [new GlowFilter(0x00FF00,1,6,6,2,3)]; // If the question was answered incorrectly... } else { // ...make the incorrectAnswerButton glow red. incorrectAnswerButton.filters = [new GlowFilter(0xFF0000,1,6,6,2,3)]; } } |
Click here to download this widget.
Of course, in this case it would probably be easier to check the isCorrectAnswer property to see how the question was answered, but don’t rain on my parade.
You can see how if you had multiple answers and just the chosenAnswer and correctAnswer properties to work with in compareAnswers, it could become difficult to determine which answer you’re currently dealing with. This is why we have the answerID.
Sometimes you may just want to use this Template Method to run code when the question is being reviewed. However, compareAnswers() will not be called without any answers to compare! So if make sure you have at least one answer in the answer list.
Here ends the Question Widget Saga. That is unless anyone has any further questions on Questions?




Pingback: Tweets that mention Question Widgets – Part 4 | The Widget King -- Topsy.com
Hi,
interesting. I wish you would continue to write up this interesting stuff.
Do you have a way (function) to read from captivate what was the correct answer and the given answer? From a normal Captivate Quiz slide?
You know – just without having to create a question widget on my own. I would like to use this to make a new review area. That way it could be used on normal Quiz slides as well as on question widget slide.
Best
Thor
Hi Thor,
What I’d recommend is that you do a little bit of Captivate exploration using Wyves’ CPXray widget and De MonsterDebugger: http://blog.flash-factor.com/widgets/cp-x-ray-widget/
Create a new Captivate movie to test with, insert a question slide, and add the CPXray widget to it. Publish the movie and use the drop down menu on the widget to trace the question slide into MonsterDebugger. Then I recommend exploring the question slide’s _question property which holds a lot of juicy information about the current state of the question (don’t forget to check it when you go back and review the quiz as well).
Once you’re done with that, you can access all that information in the _question property with the following: widgetSlide._question
I recommend you trace it out in De MonsterDebugger so that you can see what properties it has and what information is contained in them. Otherwise you’re kind of flying blind.
For the record: I LOOOOOOOOOOOOOOOOOOOOVE De Monster Debugger!
Hi tristan, congratulations on your work!
I tried the widget example and works fine, but if I export as SCORM, the LMS (Moodle) does not store the text of the responses. Any solution?
Thanks
I’m not sure. I’m not all that familiar with SCORM, it’s probably something I should get into learning sometime though. There may be a way to communicate with the SCORM Javascript to insert your answer into it, but I currently don’t know how to do that.
CaptivateDev.com has a series of articles on communication between Captivate and Javascript, perhaps there is some information in there that will help you. here’s the first post: http://captivatedev.com/2011/03/30/captivate-javascript-series-part-1-the-basics/
This is curious because your widget successfully sent responses to Captivate and SCORM is managed by Captivate, so it should work.
I will continue investigating … Thank you very much for your attention!
Greetings from Spain (excuse my robotic english)
Is there a way to retrieve the chosenAnswer property from a Captivate template question slide via a Static Widget?
eg. a static widget is placed on a standard multiple choice slide. upon the user clicking “submit”, the widget is able to read the chosenAnswer property (‘A’, ‘B’ etc).
Many thanks.
Hi Nicholas,
I’m not sure if I you can access the chosenAnswer property, but I think I can get you something a little better.
Each question slide has a ‘_question’ property. This is where a lot of the details about the question are stored. Inside here is an array called ‘answers’. What form it takes is different for each question type. For a multiple choice question, each choice is represented by an object in the array (so choice 1 would be at index 0, choice 2 at index 1, so on). Here’s what you’d write to access the data for the first choice (assuming the widget is on the same slide as the question):
widgetSlide._question.answers[0]
These objects have a lot of information, so I strongly suggest that you use MonsterDebugger to trace them out and see exactly what you’d like to access. But there are two properties in particular that I think you’d find useful.
The first is ‘answered’, which is a Boolean that indicates whether the user selected that choice. The other is ‘answeredCorrectly’, which indicates if the user was right in selecting/not selecting this choice. Once again, here’s how you’d access that for the first choice:
widgetSlide._question.answers[0].answered
widgetSlide._question.answers[0].answeredCorrectly
Of course the information about how the user answered the question would only be there after they’ve actually answered it. So listen for the QuestionWidgetEvent.QUESTION_SUBMITTED event (dispatched on the widget) to be informed of when the user has submitted the question.
I hope that gives you the information you need
Tristan,
Hi Tristan
Thank you for your response.
Unfortunately I cannot find either widgetSlide._question.answers[0].answered
or widgetSlide._question.answers[0].answeredCorrectly even after the QUESTION_SUBMITTED event.
I can find widgetSlide._question.answers and see it has a length of three (my multiple choice slide has 3 possible answers). MonsterDebugger shows me that there are only two properties for each of the array’s contents: answerholder_mc and _rblcon.
Perhaps I am doing smthg wrong but after several hours, I am at a loss.
Is this a multiple choice question with Tick Boxes or Radio Buttons?
Also, what version of Captivate are you using?
A standard radio button multiple choice slide from Captivate 5.5
Okay, the answeredCorrectly thing is for multiple choice answers with multiple answers (The checkbox one), it seems be different on single answer questions (radio buttons). I’ll have a look into those and be back.
Okay, for a RadioButton multiple choice question, instead of looking for the ‘answered’ and ‘answeredCorrectly’ properties, you want to look for the ‘selected’ property (which will tell you if the user selected that choice) and the ‘isTrueAnswer’ property (which will tell you if this choice is correct or not).
However, it seems it takes the ‘selected’ property a little while to update after the question has been submitted. So it might be an idea to have a short timer delay on the code that checks these properties.
checking against the ‘selected’ property is what i ended up doing and yes … there is a small delay (?)
many thanks for the insight
Hey Tristan,
I downloaded the as3 and fla files for SimpleQuestionButton. I opened them in Flash CS5.5 and compiled my own swf with them. I then added it to a question pool in Captivate 5 and added it to the filmstrip. When I run the project, the widget does not show up at all? The swf widget I compiled does work if I add it directly to the filmstrip though. If I use the swf that came in the zip file you posted then it appears just fine from the question pool and the filmstrip. Any ideas why I can’t recompile the source code to get a working widget on my computer?
Hey Tristan,
I noticed the date of this post is from January and widgetfactory 5.1 was built after you posted this example. So I deleted widgetfactory 5.1 and replaced it with widgetfactory 5.0 and now everything works as it should. I can compile the code and the resulting swf works from both a question pool and inserting it directly to the filmstrip. It would appear that one of the changes you made from 5.0 to 5.1 caused this issue to happen. I’m hoping that’s specific enough for you to know what part of the library needs to be updated. Can you let me know when/if you do? I’d like to use 5.1 rather than 5.0 as I’m sure you’ve put it through more rigorous testing. Thanks again for all your efforts, the library has been a fantastic resource for making Captivate widgets!
Hi Cam.
While building WidgetFactory 5.1 I fixed a serious bug for Captivate 4. In doing so however, this little oddity crept in.
Here’s the issue: The first time the widget enters the Properties Dialog, no properties have been set previously. So when you try and update the interface with the properties it causes an error. This error results in the properties never being saved.
Captivate 5 has a little trick to stop this happening. It calls the saveProperties() template method before it enters the Properties Dialog, in the hopes that this would give it suitable ‘default’ properties. In WidgetFactory 5.1 however, that call never happens.
You can however provide your widget with default properties to work off by implementing the Widget King Widget Properties Method.
Note that although Captivate 5 has this ‘fix’, Captivate 4 does not. If you do not account for the circumstance that your widget has no properties to update the interface with, then your widget will not work in Captivate 4.
This issue will be fixed in the next version of WidgetFactory.
Thanks for the reply Tristan, looking forward to the next release of WidgetFactory!
Hi Tristan.
First of all, thank you SO much for posting this. I have already created my own question widgets and am very excited about the endless customization possibilities!
In testing my widget functionality, I have run across a small oddity that I’m not sure how to fix.
I have a CP slide which contains my question widget on slide 1. I have a second slide with a standard CP multiple choice question slide on slide 2. When a user skips slide 1 and then goes back to complete slide 1, the review feedback always has the “You did not answer this question completely” (which is the default feedback that I didn’t change) even if the user hits the back button and answers the question correctly. The score is calculated correctly on the quiz review slide and the question is recorded as
I did download the CPXray widget and Monster Debugger. I found that the isQuestionSkipped property is set to true even after the user has gone back and hit the submit button. It seems as if the standard question slide (on slide 2) the isQuestionSkipped property is set to false again if the user hits the submit button.
In Monster Debugger, if I manually change the isQuestionSkipped property, it works as expected.
Long story short, how do I modify the isQuestionSkipped property in my widget?
Hi Rob,
I’m having trouble finding this ‘isQuestionSkipped’ property. Can you tell me what version of Captivate you’re using and whereabouts in the Captivate Movie you found it?
Tristan,
Hi Tristan,
I am using Captivate version 5.5.
The “isQuestionSkipped” property appears to be attached to each question slide. In Monster Debugger, the path I follow in the Application panel is rdQSlide > _question (Object). When I highlight the _question(Object) in the Application panel, “isQuestionSkipped” appears in the Properties panel and returns either a true or false value.
Thank you in advance for your assistance!
Okay I’ve found ‘isQuestionSkipped’. The good news is that you can change it. The bad news is that the isQuestionSkipped property has been removed in Captivate 6, so you’ll have to find some other work around for that version.
If your widget is placed on the Question slide, then it can access the isQuestionSkipped from runtime mode like so:
widgetSlide._question.questionSkipped = false;
However, before executing the above code, it would probably be a good idea to check if ‘_question’ and ‘_questionSkipped’ exist on the slide you’re trying to access them on. So ideally your code would look something like this:
if (widgetSlide.hasOwnProperty(‘_question’)) {
if (widgetSlide._question.hasOwnProperty(‘questionSkipped’) {
widgetSlide._question.questionSkipped = false;
}
}
Give that a go.
Works like a charm! Thank you so much!