views:

235

answers:

1

I'm required to use a limited survey application, and have to adapt the provided code to meet more advanced functionality.

I need to create a weighted ranking question, so users can select their top three choices and the data will go into the survey application and be accessible in the survey reports. The application only supports 2 types of questions (text fill & multiple choice) but I can alter the code, as long as it still sends the form data back to the survey application.

The code is set up so it will show a drop-down menu of 0-3 for each option. Now I want to limit the user's choices so they can only select one "1" "2" or "3", three choices total. Ideally, if the user already had "2" selected for one option and they tried to select it for another option, it would set the first "2" as "0" or blank.

Is this possible to do with javascript? If so, does anyone know of a site that might show code like this, or provide similar enough examples that I could adapt it?

Current code here:

<html>
<head><title>Survey</title></head>
<!-- Changes
- remove br to put dropdown next to text for each item.  Switch text & dropdown order    
for each item.
- add comments to separate each question
- removed blue title font
- add instructions

Goals
- limit choices to one 1 one 2 and one 3, three choices total.
-->
<link href="---" rel="stylesheet" type="text/css">
<body bgcolor="#3c76a3">

<!-- TRANSITIONAL DIALOG BOX -->
<table border="0" align="center" cellpadding="0" cellspacing="0" style="background-attachment: scroll; background-color: #3c76a3; background-repeat: no-repeat; background-position: left top;" bgcolor="#3c76a3" topmargin="0" marginwidth="0" marginheight="0" width="100%" height="100%">
<tr>
<td>
<table border="0" align="center" cellpadding="0" cellspacing="0" id="survey">
<tr>

<td><p>&nbsp;</p>

<!-- HEADER END -->
<!-- FORM START TAG --><form name="survey" action="---" method="POST">
<FONT face="Verdana, Arial, Helvetica, sans-serif">
<b>survey</b><hr>

<!-- 1 -->
<input type=hidden name="Buy R.J. a DeLorean_multiple_answers" value="one">
<font size=2><select name="Buy R.J. a DeLorean" SIZE=1>
<option value="">
<option value="0">0
<option value="1">1
<option value="2">2
<option value="3">3
</select></font>
<input type="hidden" name="Buy R.J. a DeLorean_help" value="">
<b><font size=2>Buy R.J. a DeLorean</font></b>
<hr size=1>

<!-- 2 -->
<input type=hidden name="Fill Lisa's office with marshmallows._multiple_answers"     value="one">
<font size=2><select name="Fill Lisa's office with marshmallows." SIZE=1>
<option value="">
<option value="0">0
<option value="1">1
<option value="2">2
<option value="3">3
</select></font>
<input type="hidden" name="Fill Lisa's office with marshmallows._help" value="">
<b><font size=2>Fill Lisa's office with marshmallows.</font></b>
<hr size=1>

<!-- 3 -->
<input type=hidden name="Install a beer fridge in everyone's filing     cabinets._multiple_answers" value="one">
<font size=2><select name="Install a beer fridge in everyone's filing cabinets." SIZE=1>
<option value="">
<option value="0">0
<option value="1">1
<option value="2">2
<option value="3">3
</select></font>
<input type="hidden" name="Install a beer fridge in everyone's filing cabinets._help" value="">
<b><font size=2>Install a beer fridge in everyone's filing cabinets.</font></b>
<hr size=1>

<!-- 4 -->
<input type=hidden name="Buy a company Cessna_multiple_answers" value="one">
<font size=2><select name="Buy a company Cessna" SIZE=1>
<option value="">
<option value="0">0
<option value="1">1
<option value="2">2
<option value="3">3
</select></font>
<input type="hidden" name="Buy a company Cessna_help" value="">
<b><font size=2>Buy a company Cessna</font></b><br>
<hr size=1>

<!-- 5 -->
<input type=hidden name="Replace Conf2's chairs with miniature ponies._multiple_answers" value="one">
<font size=2><select name="Replace Conf2's chairs with miniature ponies." SIZE=1>
<option value="">
<option value="0">0
<option value="1">1
<option value="2">2
<option value="3">3
</select></font>
<input type="hidden" name="Replace Conf2's chairs with miniature ponies._help" value="">
<b><font size=2>Replace Conf2's chairs with miniature ponies.</font></b>
<hr size=1>

<input type="hidden" name="question_names" value="{Buy R.J. a DeLorean} {Fill Lisa's office with marshmallows.} {Install a beer fridge in everyone's filing cabinets.} {Buy a company Cessna} {Replace Conf2's chairs with miniature ponies.}">
<p align="right"><input type="image" BORDER=0 title="Save Changes" alt="Save Changes" src="---"  name="button_save_changes">
<input type="hidden" name="showconfirm" value="T">
<input type="hidden" name="showresults" value="F">
<input type="hidden" name="preventdupesmemberid" value="T">
<input type="hidden" name="preventdupesip" value="F">
<input type="hidden" name="numberquestions" value="F">
<input type="hidden" name="destinationurl" value="">
<input type="hidden" name="original_survey_id" value="62">
<!-- FORM END TAG --></form>
<!-- FOOTER START -->
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- END HEADER -->
</body>
</html>
A: 

Caveat: the following code has issues. It's not intended to be dropped-in, as-is to your page. It's an illustration of technique that you can apply. Study it and write your own solution.

One option would be to record unavailable options whenever a choice is made.

var choose = (function (maxCount) {
    var chosen = {};
    var count = 0;
    function unchoose(value) {
        if (chosen[value]) {
            delete chosen[value];
            --count;
        }
    }
    return function(option) {
        if (! chosen[option.value]) {
            // option isn't chosen elsewhere
            unchoose(option.prevValue);
            if (count < maxCount) {
                // haven't reached vote limit
                chosen[option.value] = true;
                option.prevValue = option.value;
                ++count;
                return true;
            }
        }
        if (option.prevValue) {
            option.value = option.prevValue;
        } else {
            option.value = "";
        }
        return false;
    }
})(3);

Instead of separate count and chosen variables, you could refactor and create a Set class, which simplifies choice a bit:

function Set() {
    this.items = {};
    this.size=0;
}
Set.prototype.contains = function(item) {
    return this.items[item];
}
Set.prototype.add = function(item) {
    if (!this.contains(item)) {
        this.items[item] = true;
        ++this.size;
    }
}
Set.prototype.remove = function(item) {
    if (this.contains(item)) {
        delete this.items[item];
        --this.size;
    }
}

var choose = (function (maxCount) {
    var chosen = new Set;
    return function(option) {
        if (! chosen.contains(option.value)) {
            // option isn't chosen elsewhere
            chosen.remove(option.prevValue);
            if (chosen.size < maxCount) {
                // haven't reached vote limit
                chosen.add(option.value);
                option.prevValue = option.value;
                return true;
            }
        }
        // invalid choice; undo it
        if (option.prevValue) {
            option.value = option.prevValue;
        } else {
            option.value = "";
        }
        return false;
    }
})(3);

Bind choose to each select's onchange attribute (though think hard before taking this approach, as inline event subscriptions are probelmatic), or use DOM events and subscribe the following listener:

function choiceListener(evt) {
    if (! choose(evt.target)) {
        evt.preventDefault();
    }
}

If you can make more changes, consider using something like jQuery's UI interactions (specifically, UI/Draggable, UI/Droppable and UI/Sortable) to allow the user to drag & drop the items they want to vote for and sort them in order. This provides a much more intuitive interface.

outis
Thank you!This is a great start, and I appreciate the time you've spent putting this together.
leanne