Twitter like countdown characters for open ends

Since in Confirmit there’s no option to limit the characters in a text area, here’s a simple script that will show a nice countdown, as you type, twitter like, and will also limit the number of characters to a max

Or course, you can set up a custom validation that will check for the open end length in confirmit validation tab, the advantage of this script is that is very visual, and the respondent doesn’t have to hit the next button and get an error message back.

First make sure you include the jQuery library in your skin header.

The script below works with one textarea per page, but it can be easily customized to work with more

In the open end instruction tab, place the following script:



To explain a bit what the script does, the limit here is set to 120 characters, and you can change that,

The span will be updated as you type, when the limit is reached, will truncate the text and re-set it back to the text area.

Also when it gets to the 0 remaining, I'm adding the "errorquestion" class to the countdown span, that's the default confirmit error CSS style class for the error messages, so the respondents will get one more hint to see when they have reached the limit

Happy coding everyone!

isEmailTaken, isUsernameTaken and two non-standard ways to use them

The two functions are more related to the respondent recruitment surveys and are used to check if any previous respondents have registered with the same email address or user name. They are not really known, but they’re really powerful.

The power comes from the the fact they give you access to the global data, from inside a respondent link. I always wished for some Confirmit internal functions to call and get access to other individuals responses, from inside a script. I know there are all kind of alternatives from a simple API app, or even using a scripting extension, but nothing I know that’s already available in Confirmit. (not sure if there’s anything planned for Confirmit 16).

Anyways, we have these two associated with their question IDs “email” and “username” and as I said, here are two simple scenarios that demonstrate how we can use them in a regular survey.

A first scenario would be an open link survey, let’s say we have it distributed to a number of websites and later in the survey or at the end, we collect their email address for another follow up (right after this first survey) and you don’t have time to collect all the emails and sort/eliminate duplicates and so on.

It’s nothing easier than creating an open end question with “email” as questionID, make it look nice, one row etc
then add a condition node, and call the function

!isEmailTaken( f("email").get())

depending on the logic, you can use a redirect to the second survey or just terminate.

The second example is a little bit more complex and is outlined below:

We want to give 100 free Amazon vouchers or another electronic incentive to the first 100 respondents who complete the study. We can even add a note it in the invitation letter, to boost the response rate… (First 100 respondents get a 5.00$ voucher etc).

The issue is that we need to assign an unique voucher number to a respondent who completes the study. Forget the idea of pre-assigning them when they start, we may or not have enough vouchers to use, and who will stay to sort everything after all?

function vouchers(){
var labelsArr=f("vouchers").domainLabels();
/*the vouchers is a multi randomized question with the vouchers as answers
//if more values are required, you can always create a set, and use a standard randomize script, you can find in any scripting manuals
//vouchers and username are hidden question
*/
f("username").set(labelsArr[0]);
var found = false;
var counter=1;
while (found==false && counter<labelsArr.length){
	if(isUsernameTaken(f("username").get())){
		f("username").set(labelsArr[counter]);
		counter++;
	}
	else found =true;
}
return found;
}

you may call the function from a condition node or script node then redirect/or not the respondent to Amazon and claim their free voucher

As a last note, these are working as global variables, it doesn’t matter what the respondent status is, the functions will check even if the respondent has the incomplete status.

Ugly errors in Confirmit… and what can we do

I’m sure you may already know how “nice” the errors look like especially when you get a long answer grid, unanswered.

Here’s one
confirmit grid error

Just imagine how would look if the answer text is longer and there are even more in the list…

Remember what I said in some earlier posts, don’t let Confirmit run it for you, you take control over it. So now, the first thing would be to remove the default, generic error message, “Please review your responses on this page….etc” You can easily remove it from the theme or from script

Honestly, I don’t see any good reason to have it.

Now let’s make the second one look nicer, or straight to the point, why do we need to tell what answers are missing, I know there’s an option to highlight the missing ones so we can use that to give them a visual.

Anyways, just call these two functions from the inside “Validation” area

 ClearErrorMessage(); //this clears the generic "page" message
 ClearQuestionErrorMessage(); //this removes the question specific error message

The next step would be to define our own error message, something like:

SetQuestionErrorMessage(CurrentLang(),"Please enter one answer for each row");

If you’re looking to automate more you may combine the first two in a custom function and call it as you wish

then for the second one, in case you have plenty of languages you may come with a way to read them from a question label, so you may have everything ready with just one function call

Calling confirmit functions from inside the theme. Part2: dynamic content

One other possible usage of calling functions from a theme is to actually display a piece of html code dynamically created inside the survey.

Here is one example of a function that based on a question answer returns an image string:

function content(){
var content="";

if (f("q1").get()=="1") content="<img src=\"images/top1.png\" />";
else content="<img src=\"images/top2.png\" />";

return content;
}

Just place the function call in the theme,

^content()^

What will happen is that if the answer with precode 1 is selected it will return the first image if not it’s the second image returned

Based on this simple example you can come with more complex content, depending on your needs, you can also have the logic based on background variables, like language, or gender etc.

And don’t forget to deselect the option “Html encode output of piping expressions” before compiling

Automatically close a project when quota is full using Confirmit APIs (C# .NET) & JSONP – Part2

In the previous post, we’ve covered the .NET application that connects to Confirmit APIs and closes a project.
Let’s see now what we need to do in order to actually call it from a Confirmit survey.

Since the topic is close a project when the quota is reached, we’ll first need a condition node, with a quota check qf(‘quota1’)

In the “then” branch, you continue to use your own scripts, set the respondent status SetStatus(‘quotafull’) and everything else you may have, but not do the redirect yet (if you’re using one)

Add an info question type with the following content. You can use the instruction area as well.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="http://jquery-jsonp.googlecode.com/files/jquery.jsonp-2.1.4.min.js"></script>

<script>
//hide navigationarea(s)
$(function() {
	$('.navigationarea').hide();
});


function callback(data){
	//if(typeof data.status!="undefined") //you can use the data.status here
	//show navigationarea back...
	$('.navigationarea').show();

	//or redirect them to whatever URL you need
}

$.jsonp({url: "http://your domain to Confirmit Close Project/?projectID=^ProjectID()^",complete: function(data) {}});
</script>

As you can see the only parameter we send is the project ID.

There could be more to add, like showing a div with a message “Please wait!” or an ajax loading gif etc

For a better understanding on how everything works, as soon as the quota is reached, the first respondent who gets in the condition qf(‘quota1’), true now, will trigger the call to the .NET app that closes the study.
After this, it doesn’t mater how many respondents are currently on the link, no one else will made it to the end (of survey). If clicking on the “next” button, the system will answer with the standard message, “Sorry, but this survey has been closed.”

Check an older post, and find out how can you customize it for this particular study (you can also have a redirect right from the theme)

Helper function that displays friendly alerts or help messages

Whenever you create a survey template, and plan to have it ready to use by the rest of the team, it’s always better to make sure nothing goes out of control.
It’s possible, depending of the complexity of the scripts to need to set some values, and store them in hidden questions, or any other variables you may then later use in other function calls that let’s say can control the logic or filter some questions out depending on the setup.

Even if you are very careful, and add all the instructions needed, it’s always possible to have wrong values, wrong parameters or any other silly human mistakes.

Don’t let confirmit catch the errors (if you’re lucky enough), you need to take control: checking the parameters, values, limits, and anything else you may need, plus… think of the debugging time you’ll save.

This function does not do any of them, it’s You who should add and check your specifics.
What this function does is to help you displaying friendly alerts or help messages with instructions to your fellow team members, at the time the survey is tested.

so here are some examples: the former shows the message in a div, the latter will pop up a message with your predefined instruction text

function ErrorHelp(errorMsg,fnName){
//creates a div with the content
Response.Write("<div style=\"font-size: 24px; color: red\">Error:"+ errorMsg +" in function  " + fnName + "</div>");
}

function ErrorHelp2(instructions,fnName){
//popup alert with the corresponding instructions
Response.Write("<script type=\"text/javascript\"> alert(\""+fnName + " usage: " + instructions +"\"); </script>");
}

Calling confirmit functions from inside the theme. Part1: respondent statistics

One of the feature I like in Confirmit is that you can call functions you have defined in a survey script node from inside the theme.

When it comes to automate things, they are my favorite. The reason is, calling it from the theme it makes it run every time the page refreshes, (or the submit button (back/next) is pressed).
It’s not time consuming, it’s easy and elegant. (imagine what would be to add a script node calling the function after each question or place it on every question in the validation field..)

There are lots of possible scenarios I could think off, and one good example of using this is to track the questions where the respondents were screened out or dropped out.

So let’s say you have your question IDs named q1, q2 and so on..

you only need to have:

  • two single question type named droppedlist and screenedlist sharing the same list of answers, where you have added all the question IDs. Hidden!
  • a script node with the function below
    function setLastQuestion(){
    	var questionID=CurrentForm().toLowerCase();
    
    	if (questionID.indexOf('internal')==-1){
    		f('droppedlist').set(questionID.substr(1))
    	}
    	else{
    		if (GetStatus()=="screened"){
    			f('screenedlist').set(f('droppedlist').get());
    			f('droppedlist').set(null);
    		}
    	}
    }
    
  • and the function call from your theme
    ^setLastQuestion()^

and some comments:
screenedlist will have the questions where people were screened out only if a stop (screened) node was used in the logic.
droppedlist would be the last questions they’ve answered
If there are more than one question on the same page, only the last Id
is tracked