Categorized | Programming

Require Unique Answers in SharePoint Survery Ranking Scale

Posted on 13 August 2010 by Jason Grimme

Let’s pretend you want to create a SharePoint survey where you ask your audience how they would rank the three Lord of the Rings books, in order from their most to least liked.
The best solution would be to create a ranking scale, and list the three books and three choices (Most liked, Middle, Least liked). This would be realtively simple except for that you want to make sure they can only select ‘Most liked’ once. This is where SharePoint has no method of requiring unique answers between questions.

After trying many different methods, I settled on creating a custom JavaScript function on the page that validates that answers to ranking scale questions are unique.

SharePoint Ranking Scale Problem

Using This Script Forces Unique Values

Update:
See this validation post for an alternative way to add validation to a page.

Hooking Into SharePoints Validation Before Submitting

On any SharePoint page, if you create a JavaScript function named PreSaveAction, it will run and require a return true before submitting the page.

My custom function is named RequireUniqueRankings and accepts an array that tells it which ranking matrices you want to force unique answers on. It returns true if there were no problems and returns false if there were, which prevents the form from submitting.

I added the custom code in the survey page using Microsoft Designer.

1
2
3
4
5
6
7
8
9
10
11
12
13
  <script type="text/javascript">
   
    function PreSaveAction()
    {
        // Settings for matrices that require unique values
        // Start with zero and go by order in which they appear in the source
        // Default: False
        var matrices = new Array();
            matrices[0] = true;
            matrices[1] = false;
       
        return RequireUniqueRankings(matrices);
    }

Ugly SharePoint HTML

Microsoft spent a great deal of time making the ranking matrices extremely hard to parse. Not only are the names and IDs of the radio buttons pointless, the values are useless as well. They could have assigned values like 0, 1, 2, 3, etc, but no. They use values such as ctl00, ctl01, and ctl02. This would be tolerable except for the value names keep increasing within the same matrix. For the second option in the same matrix, the exact same three rankings will be ctl03, ctl04, and ctl05 instead of ctl00, ctl01, and ctl02. Why I don’t know, but it certainly is nonsensical.
Example HTML for one rank matrix – Three Items x Three ranks

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
]
<table cellpadding="0" cellspacing="1" border="0" height="95%" summary="Rating Scale Question">
    <tr>
        <td>&nbsp;</td>
        <td class="ms-verticaldots">&nbsp;</td>
        <td class="ms-gridCol">First</td>
        <td class="ms-gridCol">Second</td>
        <td class="ms-gridCol">Third&nbsp;</td>
    </tr>
    <tr>
        <td>&nbsp;</td>
        <td class="ms-verticaldots">&nbsp;</td>
        <th scope="col" class="ms-gridCol">1</th>
        <th scope="col" class="ms-gridCol">2</th>
        <th scope="col" class="ms-gridCol">3</th>
    </tr>
    <tr>
        <td class="ms-sectionline" colspan="100%" height="1"><img alt="" src="/_layouts/images/blank.gif" /></td>
    </tr>
    <!-- First option-->
    <tr>
        <th class="ms-gridT1" scope="row">The Lord of the Rings: Fellowship of the Ring</th>                       
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl00" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl00" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl00').title='The Lord of the Rings: Fellowship of the Ring Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl01" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl01" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl01').title='The Lord of the Rings: Fellowship of the Ring Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl02" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl02" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl02').title='The Lord of the Rings: Fellowship of the Ring Value 3';</script>
        </td>
    </tr>
    <!-- Second option-->
    <tr>
        <th class="ms-gridT1" scope="row">The Lord of the Rings: The Two Towers</th>
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl03" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl03" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl03').title='The Lord of the Rings: The Two Towers Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl04" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl04" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl04').title='The Lord of the Rings: The Two Towers Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl05" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl05" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl05').title='The Lord of the Rings: The Two Towers Value 3';</script>
        </td>
    </tr>
    <!-- Second option-->
    <tr>
        <th class="ms-gridT1" scope="row">The Lord of the Rings: The Return of the King</th>
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center"
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl06" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl06" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl06').title='The Lord of the Rings: The Return of the King Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl07" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl07" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl07').title='The Lord of the Rings: The Return of the King Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl08" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl02$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl08" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl02_ctl00_ctl00_ctl04_ctl00_ctl08').title='The Lord of the Rings: The Return of the King Value 3';</script>
        </td>
    </tr>
    <!-- END OPTIONS -->
</table>

Example HTML – One Matrix – 5 Items x 5 Ranks

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<table cellpadding="0" cellspacing="1" border="0" height="95%" summary="Rating Scale Question">
    <tr>
        <td>&nbsp;</td>
        <td class="ms-verticaldots">&nbsp;</td>
        <td class="ms-gridCol">Low&nbsp;</td>
        <td class="ms-gridCol"></td>
        <td class="ms-gridCol">Average</td>
        <td class="ms-gridCol"></td>
        <td class="ms-gridCol">&nbsp;High</td>
    </tr>
    <tr>
        <td>&nbsp;</td>
        <td class="ms-verticaldots">&nbsp;</td>
        <th scope="col" class="ms-gridCol">1</th>
        <th scope="col" class="ms-gridCol">2</th>
        <th scope="col" class="ms-gridCol">3</th>
        <th scope="col" class="ms-gridCol">4</th>
        <th scope="col" class="ms-gridCol">5</th>
    </tr>
    <tr>
        <td class="ms-sectionline" colspan="100%" height="1">
        <img alt="" src="/_layouts/images/blank.gif" /></td>
    </tr>
    <tr>
        <th class="ms-gridT1" scope="row">First</th>
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl00" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl00" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl00').title='First Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl01" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl01" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl01').title='First Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl02" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl02" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl02').title='First Value 3';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl03" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl03" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl03').title='First Value 4';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl04" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:0" value="ctl04" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl04').title='First Value 5';</script>
        </td>
    </tr>
    <tr>
        <th class="ms-gridT1" scope="row">Second</th>
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl05" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl05" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl05').title='Second Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl06" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl06" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl06').title='Second Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl07" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl07" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl07').title='Second Value 3';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl08" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl08" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl08').title='Second Value 4';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl09" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:1" value="ctl09" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl09').title='Second Value 5';</script>
        </td>
    </tr>
    <tr>
        <th class="ms-gridT1" scope="row">Third</th>
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl10" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl10" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl10').title='Third Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl11" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl11" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl11').title='Third Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl12" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl12" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl12').title='Third Value 3';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl13" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl13" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl13').title='Third Value 4';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl14" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:2" value="ctl14" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl14').title='Third Value 5';</script>
        </td>
    </tr>
    <tr>
        <th class="ms-gridT1" scope="row">Fourth</th>
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl15" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:3" value="ctl15" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl15').title='Fourth Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl16" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:3" value="ctl16" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl16').title='Fourth Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl17" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:3" value="ctl17" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl17').title='Fourth Value 3';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl18" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:3" value="ctl18" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl18').title='Fourth Value 4';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl19" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:3" value="ctl19" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl19').title='Fourth Value 5';</script>
        </td>
    </tr>
    <tr>
        <th class="ms-gridT1" scope="row">Fifth</th>
        <td class="ms-verticaldots">&nbsp;</td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl20" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:4" value="ctl20" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl20').title='Fifth Value 1';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl21" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:4" value="ctl21" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl21').title='Fifth Value 2';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl22" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:4" value="ctl22" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl22').title='Fifth Value 3';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl23" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:4" value="ctl23" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl23').title='Fifth Value 4';</script>
        </td>
        <td align="center">
            <input id="ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl24" type="radio" name="ctl00$m$g_50921f35_b2ce_4835_8087_6ebf6c0e84ec$ctl00$ctl01$ctl03$ctl00$ctl00$ctl04$ctl00$RadioButtons:4" value="ctl24" />
            <script>document.getElementById('ctl00_m_g_50921f35_b2ce_4835_8087_6ebf6c0e84ec_ctl00_ctl01_ctl03_ctl00_ctl00_ctl04_ctl00_ctl24').title='Fifth Value 5';</script>
        </td>
    </tr>
</table>

Validating Ranking Answers

In essence, my script loops through all radio button input elements, and then sorts all of them based on some logic that results in them being split into the different matrices as well as grouping the answer values so that they are 0, 1, 2 instead of ctl00, ctl01, and ctl02.

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    function RequireUniqueRankings(requiredMatrices)
    {
        var matrixCount = 0;
        var rankedMatrixes = new Array();
        rankedMatrixes[matrixCount] = new Object;
        rankedMatrixes[matrixCount]['matrixRadioButtons'] = new Array();
        rankedMatrixes[matrixCount]['matrixRadioSPvalues'] = new Array();
        rankedMatrixes[matrixCount]['matrixRadioNames'] = new Object;
        rankedMatrixes[matrixCount]['matrixRadioValues'] = new Object;
        rankedMatrixes[matrixCount]['matrixRadioSelected'] = new Object;

        // Get all input radio buttons 
        var inputsArr = document.getElementsByTagName("input");

        // Loop through all inputs.  Get matrix radio buttons
        for(var i=0; i<inputsArr.length; i++)
        {      
            if(inputsArr[i].type == "radio")
            {  
                // Determine if this radio button is part of a ranked matrix
                // Assumed pattern: name="ctl00...ctl00$RadioButtons:2"
                var rankMatrixRefEx = /RadioButtons\:\d+/g;
                var isRankMatrixRadio = rankMatrixRefEx.exec(inputsArr[i].name);
                if(isRankMatrixRadio)
                {  
                    // If we have already run into this value, then we are on a new matrix
                    // Loop through all values for current matrix.
                    for(m=0; m<rankedMatrixes[matrixCount]['matrixRadioSPvalues'].length; m++)
                    {
                        if(rankedMatrixes[matrixCount]['matrixRadioSPvalues'][m] == inputsArr[i].value)
                        {
                            matrixCount++;
                            rankedMatrixes[matrixCount] = new Object;
                            rankedMatrixes[matrixCount]['matrixRadioButtons'] = new Array();
                            rankedMatrixes[matrixCount]['matrixRadioSPvalues'] = new Array();
                            rankedMatrixes[matrixCount]['matrixRadioNames'] = new Object;
                            rankedMatrixes[matrixCount]['matrixRadioValues'] = new Object;
                            rankedMatrixes[matrixCount]['matrixRadioSelected'] = new Object;                                       
                        }
                    }
                    rankedMatrixes[matrixCount]['matrixRadioSPvalues'].push(inputsArr[i].value);
                    // Add to list of radio buttons        
                    rankedMatrixes[matrixCount]['matrixRadioButtons'].push(inputsArr[i]);
                    // Add to list of radio groups
                    rankedMatrixes[matrixCount]['matrixRadioNames'][inputsArr[i].name] = inputsArr[i].value;
                }              
            }
        }  
        /*
        Good for debugging
        var list = "";
        for(var i=0; i<rankedMatrixes.length; i++)
        {
            for(var j=0; j<rankedMatrixes[i]['matrixRadioButtons'].length; j++)
            {
                list += i + " : " + rankedMatrixes[i]['matrixRadioButtons'][j].name + "\n";
            }
        }
        alert(list);
        */

           
        // Loop through each of our matrixi and check for unique values
        for(var i=0; i<rankedMatrixes.length; i++)
        {
            // If we didn't require this to have unique values, skip it
            if(!requiredMatrices[i])
            {
                continue;
            }
       
            //Get selected values for each ranked option           
            // Loop through each question/group    
            for( var radioName in rankedMatrixes[i]['matrixRadioNames'])
            {
                var buttonsWithinName = document.getElementsByName(radioName);
                for(var j=0; j<buttonsWithinName.length; j++)
                {
                    // Assoc this unique value with the general value (0, 1, 2, etc)
                    // ex ctl00 = 0; ctl01 = 1; ... ctl04 = 0;
                    rankedMatrixes[i]['matrixRadioValues'][buttonsWithinName[j].value] = j;
                    if(buttonsWithinName[j].checked == true)   
                    {
                        // Assign this value to this name
                        rankedMatrixes[i]['matrixRadioSelected'][radioName] = buttonsWithinName[j].value;
                    }
                }
            }      
                   
            // Return false if user selected a ranking more than once
            // Will keep track of selected values for this group
            var valuesWithinGroup = new Object;
            // For each group
            for( var radioGroup in rankedMatrixes[i]['matrixRadioSelected'])
            {      
                var groupName = radioGroup;
                var groupUniqueValue = rankedMatrixes[i]['matrixRadioSelected'][radioGroup];
                var groupCommonValue = rankedMatrixes[i]['matrixRadioValues'][groupUniqueValue];
                if(valuesWithinGroup[groupCommonValue])
                {
                    // Get the title for this group
                    var groupTitle = document.getElementsByName(groupName)[groupCommonValue].title;
                    alert("You may only select a ranking once between the items.\nPlease revise your ranking for " + groupTitle);
                    return false;
                }
                // Register this rank as taken
                valuesWithinGroup[groupCommonValue] = true;
            }
       
        }// End each matrix

        // If we made it to this point, they have not selected a ranking twice.
        return true;
    }

Final Script

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  <script type="text/javascript">
   
    function PreSaveAction()
    {
        // Settings for matrices that require unique values
        // Start with zero, by order in which they appear in the source
        // Default: to false
        var matrices = new Array();
            matrices[0] = true;
            matrices[1] = true;
       
        return RequireUniqueRankings(matrices);
    }
   
    function RequireUniqueRankings(requiredMatrices)
    {
        var matrixCount = 0;
        var rankedMatrixes = new Array();
        rankedMatrixes[matrixCount] = new Object;
        rankedMatrixes[matrixCount]['matrixRadioButtons'] = new Array();
        rankedMatrixes[matrixCount]['matrixRadioSPvalues'] = new Array();
        rankedMatrixes[matrixCount]['matrixRadioNames'] = new Object;
        rankedMatrixes[matrixCount]['matrixRadioValues'] = new Object;
        rankedMatrixes[matrixCount]['matrixRadioSelected'] = new Object;

        // Get all input radio buttons 
        var inputsArr = document.getElementsByTagName("input");

        // Loop through all inputs.  Get matrix radio buttons
        for(var i=0; i<inputsArr.length; i++)
        {      
            if(inputsArr[i].type == "radio")
            {  
                // Determine if this radio button is part of a ranked matrix
                // Assumed pattern: name="ctl00...ctl00$RadioButtons:2"
                var rankMatrixRefEx = /RadioButtons\:\d+/g;
                var isRankMatrixRadio = rankMatrixRefEx.exec(inputsArr[i].name);
                if(isRankMatrixRadio)
                {  
                    // If we have already run into this value, then we are on a new matrix
                    // Loop through all values for current matrix.
                    for(m=0; m<rankedMatrixes[matrixCount]['matrixRadioSPvalues'].length; m++)
                    {
                        if(rankedMatrixes[matrixCount]['matrixRadioSPvalues'][m] == inputsArr[i].value)
                        {
                            matrixCount++;
                            rankedMatrixes[matrixCount] = new Object;
                            rankedMatrixes[matrixCount]['matrixRadioButtons'] = new Array();
                            rankedMatrixes[matrixCount]['matrixRadioSPvalues'] = new Array();
                            rankedMatrixes[matrixCount]['matrixRadioNames'] = new Object;
                            rankedMatrixes[matrixCount]['matrixRadioValues'] = new Object;
                            rankedMatrixes[matrixCount]['matrixRadioSelected'] = new Object;                                       
                        }
                    }
                    rankedMatrixes[matrixCount]['matrixRadioSPvalues'].push(inputsArr[i].value);
                    // Add to list of radio buttons        
                    rankedMatrixes[matrixCount]['matrixRadioButtons'].push(inputsArr[i]);
                    // Add to list of radio groups
                    rankedMatrixes[matrixCount]['matrixRadioNames'][inputsArr[i].name] = inputsArr[i].value;
                }              
            }
        }  
        /*
        Good for debugging
        var list = "";
        for(var i=0; i<rankedMatrixes.length; i++)
        {
            for(var j=0; j<rankedMatrixes[i]['matrixRadioButtons'].length; j++)
            {
                list += i + " : " + rankedMatrixes[i]['matrixRadioButtons'][j].name + "\n";
            }
        }
        alert(list);
        */

           
        // Loop through each of our matrixi and check for unique values
        for(var i=0; i<rankedMatrixes.length; i++)
        {
            // If we didn't require this to have unique values, skip it
            if(!requiredMatrices[i])
            {
                continue;
            }
       
            //Get selected values for each ranked option           
            // Loop through each question/group    
            for( var radioName in rankedMatrixes[i]['matrixRadioNames'])
            {
                var buttonsWithinName = document.getElementsByName(radioName);
                for(var j=0; j<buttonsWithinName.length; j++)
                {
                    // Assoc this unique value with the general value (0, 1, 2, etc)
                    // ex ctl00 = 0; ctl01 = 1; ... ctl04 = 0;
                    rankedMatrixes[i]['matrixRadioValues'][buttonsWithinName[j].value] = j;
                    if(buttonsWithinName[j].checked == true)   
                    {
                        // Assign this value to this name
                        rankedMatrixes[i]['matrixRadioSelected'][radioName] = buttonsWithinName[j].value;
                    }
                }
            }      
                   
            // Return false if user selected a ranking more than once
            // Will keep track of selected values for this group
            var valuesWithinGroup = new Object;
            // For each group
            for( var radioGroup in rankedMatrixes[i]['matrixRadioSelected'])
            {      
                var groupName = radioGroup;
                var groupUniqueValue = rankedMatrixes[i]['matrixRadioSelected'][radioGroup];
                var groupCommonValue = rankedMatrixes[i]['matrixRadioValues'][groupUniqueValue];
                if(valuesWithinGroup[groupCommonValue])
                {
                    // Get the title for this group
                    var groupTitle = document.getElementsByName(groupName)[groupCommonValue].title;
                    alert("You may only select a ranking once between the items.\nPlease revise your ranking for " + groupTitle);
                    return false;
                }
                // Register this rank as taken
                valuesWithinGroup[groupCommonValue] = true;
            }
       
        }// End each matrix

        // If we made it to this point, they have not selected a ranking twice.
        return true;
    }
     
  </script>

Tags | , ,

4 Responses to “Require Unique Answers in SharePoint Survery Ranking Scale”

  1. Yap Sok Chuan says:

    Thank you very much, Jason. The code works for me.

  2. Brian Hartman says:

    If I have access to sharepoint designer how do I add this code in? I can’t actually edit anything in the server itself just the site I manage. Under the survey I just have
    Allitems
    DispForm
    EditForm
    NewForm
    overview
    summary

    Can I add this code to any of these bits or do I need to be able to edit stuff directly on the server side?

  3. Artem says:

    Hi!!
    Where insert this code??I have sharepoint 2007+designer 2007.
    I open Survery->newForm.aspx, insert code and nothing…
    Help please!!


Leave a Reply

Security Code:

-->