The EnterPage 15-01
May 7, 2012

In this issue:

Exam Engine 4 Offers Database-Driven Exams Completely in HTML/JavaScript

Storyboarder 2 Exports ToolBook Screen Captures and Content to PowerPoint or Word

Platte Canyon/Jeff Rhodes Blog

Programming for e-Learning Developers Segment

Expert Information from Learning & Mastering ToolBook

OpenScript Tip from Learning & Mastering ToolBook

Web Hint from Learning & Mastering ToolBook

JavaScript Tip

VBTrain.Net Nugget



Introduction

Welcome to our first newsletter of 2012! We are happy to be back with information on an exciting new version of Exam Engine, Storyboarder version 2 with export to PowerPoint, the link to the new blog, and Programming for e-Learning Developers tips on ToolBook, JavaScript, and .NET.



Exam Engine 4 Offers Database-Driven Exams Completely in HTML/JavaScript

We have completely rewritten this popular exam authoring tool in HTML and JavaScript, which means that it no longer requires Flash or Silverlight. This allows you to support any browser (IE 7 and later plus Firefox, Safari, etc.) and mobile devices like the iPad. Editing your templates or styles can now be accomplished in your favorite HTML editor or a free product like Visual Web Developer 2010 Express. Here are some of the new features.
  • Deploys via HTML and JavaScript with NO plugins
  • Supports Internet Explorer 7 and later, Firefox, Safari, and other browsers
  • Validates login and password against included web service
  • Validates login and exam so that unauthorized users are excluded from an exam
  • Allows users to review questions at the end of the exam if desired. Questions are locked but show how the student answered. Any media associated with the question will play.
  • Displays score by objective as well as overall score
  • Detects HTML 5 media capabilities and uses it to play media if available
  • Revert to Flash, Windows Media Player, or QuickTime as appropriate if HTML media playback is not supported
  • Optionally includes ALL audio (mp3, oga, wav) and video (mp4, webm, ogv, wmv) formats to support media on all major browsers
  • Optionally shows HTML 5 audio controls when playing audio
  • Lets you choose between graphical buttons and jQuery UI buttons
  • Has an enhanced Reporter application with new and redesigned reports that show data by exam, user, and question
  • Includes new reports for the Question Editor
  • Seamlessly updates version 2 and version 3 exams
  • Includes source [HTML and JavaScript] to allow advanced users to extend product
  • Much more!

Information

Example

Purchase


Storyboarder 2 Exports ToolBook Screen Captures and Content to PowerPoint or Word

The Platte Canyon® Storyboarder creates a Microsoft Word or (new) PowerPoint storyboard from an existing ToolBook book. The document or presentation includes an optional screen capture of each page, field, button, and other text, question answers/feedback, simulation information, and other content - all in the same order top to bottom as in your book. For the PowerPoint storyboard, you can put the content in speaker notes and/or a contents textbox. You can also have an optional comments textbox on each slide. You can run Storyboarder in author-level ToolBook or download the complete ToolBook runtime installation.

There is a free evaluation version that works with ToolBook books of up to five pages so that you can try it out.

Information

Purchase

Platte Canyon/Jeff Rhodes Blog

We've joined the 21st century and now have a blog in addition to 15 years worth of EnterPage newsletters. Most topics are related to programming, but there is information on leadership videos and whatever else we find relevant. We hope you will visit often and consider subscribing to the RSS feed.

Blog

RSS Feed


Programming for e-Learning Developers Segment

This feature is a short segment from Jeff's Programming for e-Learning Developers book.

HTTP Post Explained

ToolBook and some other authoring tools don't have specific web service functionality but you can usually use their HTTP Post functionality to connect to a web service. Let's first spend a minute explaining HTTP Post. Think of a standard web page with some entry fields. The actual HTML is shown below:
<table>
	<tr>
	<td>Email:</td>
	<td><input type="text" id="emailAddress" name="emailAddress" class="InputField" /></td>
	</tr>
	<tr>
		<td>Copy Emails:</td>
		<td><input type="text" id="copyAddress" name="copyAddress" class="InputField" /></td>
	</tr>
	<tr>
		<td>Subject:</td>
		<td><input type="text" id="subjectInfo" name="subjectInfo" class="InputField" /></td>
	</tr>
	<tr>
		<td>Body:</td>
		<td><input type="text" id="bodyInfo" name="bodyInfo" class="InputField" style=""  /></td>
	</tr>
</table>
<br />
<input type="submit" id="submitBtn" value="Submit" />

When the user clicks the "Submit" button, the page "posts." Code on the web server can then use the Request object to figure out what the user entered as shown below.
Protected Sub Page_Load(ByVal sender As Object, _
	ByVal e As System.EventArgs) Handles Me.Load

	If Me.IsPostBack = False Then
		Dim emailId As String = Request("emailAddress")
		Dim copyId As String = Request("copyAddress")
		Dim subjectId As String = Request("subjectInfo")
		Dim bodyId As String = Request("bodyInfo")

		' Call method to send email here
		Response.Write("Email Sent")
	End If
End Sub

We check the IsPostBack property of the page to skip the initial loading of the page and only read the information once the user clicks the "Submit" button. We then read the Request object by looking for a key with the same name as the element on the page.

So what does all this have to do with HTTP Post? Developers soon realized that rather than making the user type the info into the web page itself, you could send these parameters (emailAddress, copyAddress, etc.) programmatically. They would still show up in the Request object. The HTML of the page, plus whatever got sent in the Response.Write line at the end, would be returned to the calling program. This is not a bad solution but not as clean as using Web Services. The good news as I mentioned above, though, is that you can normally call a web service with HTTP Post.

Programming for e-Learning Developers Information

Order Programming for e-Learning Developers ($45 with free shipping in the U.S.)


Expert Information from Learning & Mastering ToolBook 

By Tomas Lund, ToolBookConsulting.com

ToolBook Menu Not Marking Chapters as Complete

The ToolBook menu object sometimes fails to update itself. The result is that chapters which should be marked complete are not or chapters are marked as complete when they should not.

The fix is relatively simple:

  1. Open your ToolBook file in author mode and go to the page with the menu
  2. Select the menu object on the page
  3. Open ToolBook's Command Window (press Shift + F3) and type (or copy/ paste) the following:
    clear TBK_ChapterList of selection
    send update to selection
    
  4. Press Enter
The menu will now rebuild itself based on the pages and chapters in the ToolBook file and the problem will be fixed.


OpenScript Tip from Learning & Mastering ToolBook

By Jeff Rhodes, Platte Canyon Multimedia Software Corporation

Enabling or Disabling Voice Recordings

How would you write a tool like the "Voice Recording Toggle" that is available via LiveXtensions? The first task is to figure out how the enabling happens. If you check the "Enable voice recording playback for this page" box on the Voice Recordings tab of the Properties for Page sheet and then check the User Properties of the page using the Property Browser, you'll see that it adds a property called TBK_VoiceRecordings. It is true if recordings are enabled and false otherwise. That leads to an implementation from the Command Window like the code below. Notice how we check whether the property of the page is NULL. That keeps us from setting the property where there is no voice recording in the first place.
isEnabled = TRUE
step num from 1 to pageCount of this book
	pageId = page num
	if TBK_VoiceRecording of pageId <> NULL
		TBK_VoiceRecording of pageId = isEnabled
	end if
end step


Web Hint from Learning & Mastering ToolBook

By Clifton Slegar, Pioneer Graphics Software Development

Determining if the User Entered Various Words

Question: I am trying to create the logic for determining if the user typed in one or more terms into a field.

Answer: Here is a JavaScript approach since it appears you are exporting this to DHTML:

Create a file with the following contents (function IS case-sensitive):

function tbfunction_verifyText( txt ) {
     var m = txt.match(/ (the|this) /g);
     return (m instanceof Array) ? m.length : 0; 
}

What does it do?

It basically searches for the words "the" or "this" and creates an array of what was found in the parameter txt. If the array exists and has a length, the function will return a value greater than 0 indicating the words are valid. Otherwise it returns 0, meaning the words were not found in the parameter txt. I tested this and it works great!

In the Actions Editor you would call the function this way:

On key up ... (Parameters: keyCode, shiftDown, ctrlDown)
     verifyText( text of field "answer" ); store return value in x
     If x > 0
         -- all is okay so do whatever you need here
     End If

If you wanted to get fancier in your checking, just change the function to include more words, each separated by a pipe as in the example above. The function can easily be adapted for other languages if necessary.

Code snippets like the above can easily be executed from within a field in exported ToolBook content using the PowerPac function exeJavascriptDirect(). This saves having to make a whole bunch of little code files when all you need is a little snippet. But nevertheless, the PowerPac is not necessary. Just make a file, import it and call the function directly.

At any rate this gives you another option, probably one that is less cumbersome than chaining a lot of words to an Actions statement with the qualifier "contains."

Editor note: As Clifton mentions, this can also be done via the Actions Editor but it is a bit more verbose since you cannot use regular expressions like Clifton's JavaScript solution does. In the Actions Editor solution, you would put the text of the field into a variable and then use the "contains" operator. So if your variable was fieldText, the logic would look like this:

If fieldText contains "this" or fieldText contains "the" Then
	-- do something here
End If



JavaScript Tip

By Jeff Rhodes, Platte Canyon Multimedia Software Corporation

JavaScript and jQuery in Exam Engine 4

As mentioned earlier in this newsletter, the new version of Exam Engine is completely HTML and JavaScript. The navigation buttons and other common elements are in the main page (index.htm) as is an iFrame that contains each of the templates. One of these templates is login.htm, which is used if the developer has specified to use a login page in the absence of an LMS. Let's look at that page to get an idea of the design and how the jQuery library comes in handy.

Here is the HTML of the login.htm page.
<body>
    <span id="loginLabel"></span>
	<img id="loginImageBtn" src="" alt="" />
	<input id="loginBtn" type="button" />
	<input id="studentName" type="text" />
	<input id="studentPassword" type="password" />
	<span id="statusBlock"></span>
</body>

The position, font, and other formatting are implemented with a style sheet. But we need to add the functionality with JavaScript. Here is the "load page" script:

var usePassword;

$(function () {
	var loginText = parent.ReadExamSetting("LoginPageMessage", "Enter your name:");
	var loginBtn;
	var studentNameId = $("#studentName");
	var passwordId = $("#studentPassword");

	usePassword = parent.ReadExamSettingBoolean("LoginPageUsePassword", false);

	$("#loginLabel").html(loginText);

	if (parent.UsejQueryUiButtons == true) {
		loginBtn = $("#loginBtn");
		$("#loginImageBtn").hide(); // needed for Firefox
	}
	else {
		loginBtn = $("#loginImageBtn");
		$("#loginBtn").hide(); // needed for Firefox
	}

	parent.ConfigureButton(loginBtn, "Login", LoginBtn_Click);
	parent.SetBtnStatus(loginBtn, "Login", true, true, true); // visible, enabled, in template

	if (usePassword == true) {
		passwordId.show();
		passwordId.keydown(studentName_KeyDown);
	}
	else {
		passwordId.hide();
		studentNameId.keydown(studentName_KeyDown);
	}

	// Hide Countdown Timer
	parent.CountdownTimerRef.hide();
	parent.TransitionControlRef.show();
});

We declare usePassword outside the function block so that we can use its value when the user actually clicks the Login button. The $(function() { syntax is part of jQuery and means that the page if fully loaded and all the objects are in place. We read our loginText variable with the ReadExamSetting function. The first parameter is the name of the setting and the second is a default value. This setting is originally created in the Exam Engine Configuration Editor and is stored in an XML file that is part of the exam. parent refers to the main page and its ExamEngineSettings.js file. The studentNameId and passwordId variables are jQuery objects. The "#studentName" is a selector that identifies an object with an id of "studentName." This is the input control in the HTML above.

Next, we read the usePassword value from the exam as well. We then set the text of our loginLabel span control with this syntax: $("#loginLabel").html(loginText);. The first part creates the jQuery object using the selector as we saw above. We then call its html method and set its value to the loginText value that we read above.

Our next set of logic is to use either jQuery UI buttons or normal graphic buttons. We set the loginBtn variable to the appropriate object (input for jQueryUI or img for graphical) and hide the other object. At that point, we call two common functions, ConfigureButton and SetBtnStatus. These associate the proper "click" handler, set the states of the buttons, and load graphics if needed.

We then use our usePassword variable to either show or hide the password input control. Based on whether it is showing, we either add a KeyDown handler to it or the login input. This is so the user can press the Enter key rather than having to click or tab to the Login button. Notice the handy jQuery syntax to handle the keydown event with the studentName_KeyDown function: passwordId.keydown(studentName_KeyDown);.

We end by hiding the "countdown" timer and showing the iFrame itself (TransitionControlRef). The main point is that using jQuery simplifies getting our hands on object references and gives us a standard set of properties and methods.


VBTrain.Net Nugget

By Jeff Rhodes, Platte Canyon Multimedia Software Corporation

Using jQuery UI Along with ASP.NET Web Forms

I like the jQuery UI objects, particularly its Button and Datepicker widgets. But what if you want to use them on a normal ASP.NET web form? Back in the early 2000's, I wrote the VBTrain Graphical Button control to generate all the JavaScript needed to swap out graphics for the up, down, over, and disabled states. But now jQueryUI does all of that for us. Making the two technologies work together is pretty simple. Here is what the input control looks like:

<input id="SubmitBtn" runat="server" value="Submit" type="submit" />

The only change we made was the runat="server" part. This is what allows us to recognize it in server-side code.

The next step is to add jQuery UI. We do this with the appropriate .js and css files loaded in the head of the file. We are using the Start theme, which is why the reference is "css/start/."
<link href="css/start/jquery-ui-1.8.17.custom.css" rel="stylesheet" type="text/css" />
<script src="scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="scripts/jquery-ui-1.8.17.custom.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(function () {
        $("input:submit").button();
    });
</script>

You might recognize the "load" function from the previous article. Once the page is fully loaded, it executes. We then use a new type of selector: "input:submit". This means that we find all input controls that have a type of submit. We then call the button() method on each one. This is what loads all the appropriate graphics and associated scripts. If there had been 10 input buttons (of type submit) on the page, that one line would have configured all of them.

The last step is handling the click in our "code behind" file. That handler is shown below.
Private Sub SubmitBtn_ServerClick(sender As Object, e As System.EventArgs) Handles SubmitBtn.ServerClick
    ' take action here
End Sub


Those of you who are used to normal ASP.NET buttons will see that the event is a bit different: ServerClick rather than the normal Click. But the functionality is exactly the same.



The EnterPage is distributed up to four times per year, with occasional special issues. Individuals who have expressed interest in Platte Canyon Multimedia Software Corporation or its products receive The EnterPage. Suggestions for articles or proposals for article submissions are welcome. Send information to ep@plattecanyon.com. Back issues of the EnterPage are available at:

http://www.plattecanyon.com/enterpage.aspx

Platte Canyon Multimedia Software Corporation, 8870 Edgefield Drive, Colorado Springs, CO 80920, (719) 548-1110