Alright, I think I've got this one figured out. Let's start by creating an open-end question for the zip code and add a free format question to the same page.
The free format question should have a hidden, text variable named "_flag," and this code:
<input name="[% QuestionName() %]_flag" id="[% QuestionName() %]_flag" type="hidden" value=""/>
The free format should be given a skip that skips to your terminate page under these conditions:
Length(FreeFormatQ_flag) > 0
"FreeFormatQ" being the name of the free format question.
Now, let's go back to the open-end question. We need to add this somewhere to the question (e.g., footer, HTML head):
<input id="zipErrorCount" type="hidden" value="0"/>
Finally, this is the custom JavaScript verification for the open-end:
[% Begin Unverified Perl
# Params
my $stateQ = 'SelectQ';
my $freeFormatQ = 'FreeFormatQ';
my %zipCodes = (
1 => [123, 124, 125],
2 => [234, 235, 236],
3 => [345, 346, 347]
);
my $maxIncorrectZipCodes = 2;
my $errorMessage = 'Bad zip code.';
# Run
my $return = 'var zipCodes = {';
my @zips = @{$zipCodes{GETVALUE($stateQ)}};
my $sep = '';
foreach my $zip (@zips) {
$return .= $sep . $zip . ':1';
$sep = ',';
}
$return .= '};';
$return .= 'var freeFormatVariable = \'' . $freeFormatQ . '_flag\';';
$return .= 'var maxIncorrect = ' . $maxIncorrectZipCodes . ';';
$return .= 'var message = \'' . $errorMessage . '\';';
return $return;
End Unverified %]
var errorCount = Number($('#zipErrorCount').val());
if (!zipCodes[Number(SSI_GetValue('[% QuestionName() %]'))]) {
errorCount++;
if (errorCount > maxIncorrect) {
$('#' + freeFormatVariable).val(1);
}
else {
$('#zipErrorCount').val(errorCount);
strErrorMessage = message;
}
}
Lines 3 and 4 should be updated with the names of the state and free format question, respectively. Lines 6-8 can be updated and repeated to represent the valid zip codes for each state. Then lines 10 and 11 can optionally be updated if you want to change how many incorrect attempts respondents are allowed or what error message they are shown on an incorrect response.