At work I have been noticing an increase in time it takes to remove a file from a solution. Several weeks ago it took about ten seconds, but recently it has been taking a few minutes.
The other day while waiting for a file to be deleted I decided to figure out what was causing the problem. I was able to do some research, find the problem, and fix the problem while Visual Studio was trying to remove a file Once I fixed the problem the file finished deleting.
The Fix
It’s a simple fix, really. Empty your recycle bin. I had about two gigabytes of files and after removing them, the deletion process took less than a second. It’s unusual to be happy when you get what should have received in the first place. Then again, it’s a Microsoft product. Maybe I should be happy it works most of the time .
Today my script that I wrote for Require Unique Answers in SharePoint Survery Ranking Scale was rejected because it used designer which is frowned upon for ghosting pages. I was left to quickly find a way to include a content editor web part on the survey page that contained the JavaScript.
Luckily, I found out that you can trick SharePoint into displaying the survey page in edit mode, which allows you to add web parts.
Trixie Little Hobbitses
Let’s say the link to your survey is http://mySite/documents/survey/newform.aspx.
Of course, you don’t really need to keep the source parameter on the URL.
You can then add your web part, most likely a content editor web part.
To add custom validation, add JavaScript using the PreSaveAction() method like the following and in the referenced post at the beginning of this article.
1 2 3 4 5 6 7
<script type="text/javascript"> function PreSaveAction() { // Put your custom validation here returntrue; } </script>
Update: Adding validation on Survey Edit page
After some user testing, I discovered that users could edit survey submissions (if enabled) without my Javascript validation. I took a shot at trying to add a content editor web part to the edit.aspx page and it worked as well. Simply add the same toolpaneview=2 bit onto the end of the aspx page and the add web part interface will be displayed.
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.
Using This Script Forces Unique Values
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
] <tablecellpadding="0"cellspacing="1"border="0"height="95%"summary="Rating Scale Question"> <tr> <td> </td> <tdclass="ms-verticaldots"> </td> <tdclass="ms-gridCol">First</td> <tdclass="ms-gridCol">Second</td> <tdclass="ms-gridCol">Third </td> </tr> <tr> <td> </td> <tdclass="ms-verticaldots"> </td> <thscope="col"class="ms-gridCol">1</th> <thscope="col"class="ms-gridCol">2</th> <thscope="col"class="ms-gridCol">3</th> </tr> <tr> <tdclass="ms-sectionline"colspan="100%"height="1"><imgalt=""src="/_layouts/images/blank.gif"/></td> </tr> <!-- First option--> <tr> <thclass="ms-gridT1"scope="row">The Lord of the Rings: Fellowship of the Ring</th> <tdclass="ms-verticaldots"> </td> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <thclass="ms-gridT1"scope="row">The Lord of the Rings: The Two Towers</th> <tdclass="ms-verticaldots"> </td> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <thclass="ms-gridT1"scope="row">The Lord of the Rings: The Return of the King</th> <tdclass="ms-verticaldots"> </td> <tdalign="center" <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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>
<tablecellpadding="0"cellspacing="1"border="0"height="95%"summary="Rating Scale Question"> <tr> <td> </td> <tdclass="ms-verticaldots"> </td> <tdclass="ms-gridCol">Low </td> <tdclass="ms-gridCol"></td> <tdclass="ms-gridCol">Average</td> <tdclass="ms-gridCol"></td> <tdclass="ms-gridCol"> High</td> </tr> <tr> <td> </td> <tdclass="ms-verticaldots"> </td> <thscope="col"class="ms-gridCol">1</th> <thscope="col"class="ms-gridCol">2</th> <thscope="col"class="ms-gridCol">3</th> <thscope="col"class="ms-gridCol">4</th> <thscope="col"class="ms-gridCol">5</th> </tr> <tr> <tdclass="ms-sectionline"colspan="100%"height="1"> <imgalt=""src="/_layouts/images/blank.gif"/></td> </tr> <tr> <thclass="ms-gridT1"scope="row">First</th> <tdclass="ms-verticaldots"> </td> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <thclass="ms-gridT1"scope="row">Second</th> <tdclass="ms-verticaldots"> </td> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <thclass="ms-gridT1"scope="row">Third</th> <tdclass="ms-verticaldots"> </td> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <thclass="ms-gridT1"scope="row">Fourth</th> <tdclass="ms-verticaldots"> </td> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <thclass="ms-gridT1"scope="row">Fifth</th> <tdclass="ms-verticaldots"> </td> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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> <tdalign="center"> <inputid="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.
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); returnfalse; } // 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. returntrue; }
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); returnfalse; } // 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. returntrue; }
Much like iPods, clothes, laptops, and houses, the color of your KitchenAid stand mixer matters. KitchenAid offers more than thirty different colors for the Artisan series and a handful for the other model types.
Because people have different tastes; and, because certain colors have limited availability, this has created a difference in value between mixers of the exact same model. This is extremely evident when buying a mixer online through Amazon or eBay where the consumer truly is king.
List / Images of All KitchenAid Mixer Colors
Here are all the color varieties that I have found thus far. I have attempted to put them in order by color . For now this list only contains colors for the Artisin and does not have the colors for the Pro 600 – but it will in the future.
Much to my dismay, there was not a lot of price variance for the same mixer model between retailers. It is possible that since KitchenAid has their "Authentic Retailer", they are able to mandate prices like Apple and their iPods.
Because of this, I won’t spend a lot of time supplying prices for individual retailers (Though I did do a lot of research on this). On a similar note, I didn’t visit every online store and check their price. I checked the main ones, including Amazon and eBay.
Pricing Summary
How do you like that? A summary before any of the data. I figured that many people won’t care about my research data.
Buying In The Store (Stubborn)
If you insist on buying in a local retailer, it doesn’t really matter which store you buy it from. The Classic model will be about $200, the Artisan will be $300, and the Pro 600 will be $400. If this isn’t the price at your store, try a different one.
Buying Online (Wise)
If you are up for buying online, I tip my hat to you. Not only are the prices cheaper, but you have greater selection of the many colors that KitchenAid offers. I bet your local retailer doesn’t carry thirty different colors, do they? I would recommend Amazon.com for buying online, they seem to be about 15% less than local stores. eBay is another great place to look for these, even new.
Buying Used or Refurbished (Practical)
With the stand mixers, you don’t always have to buy them new. These last for decades and thus there is nothing wrong with buying one that is used or refurbished.eBay has an enormous amount of auctions for KitchenAid stand mixers for sale in used and new-in-box. A used mixer can be consistently found for half the price of the new item in stores. This is absolutely the best deal that you can count on finding.
KitchenAid has a massive refurbished program and sells through their website in addition to eBay (Their account is KitchenAid). Their eBay listings ended up being about 5% cheaper than through their website. They all come with warranties.
Supporting Data
As mentioned earlier, I won’t really cover buying these magnificent machines in your local retail store. The prices are pretty much all the same and the only way you will find a deal is if it is on some special sale, which I can’t of course predict. I’m covering consistent data.
KitchenAid Mixers Pricing - eBay vs Retail. Prices include shipping.
Table: Contains price averages for specific KitchenAid Stand Mixer models.
Model
Average Price
(Including Shipping)
Classic eBay Used
$110
Classic eBay Refurb
$120
Classic eBay New
$147
Classic Retail
$214
Artisan eBay Used
$147
Artisan eBay Refurb
$183
Artisan eBay New
$217
Aresian Retail
$298
Pro 500 eBay Used
$170
Pro 500 eBay Refurb
$198
Pro 500 eBay New
$223
Pro 500 Retail
$285
Pro 600 eBay Used
$247
Pro 600 eBay Refurb
$272
Pro 600 eBay New
$304
Pro 600 Retail
$415
All prices above and below include the price of shipping, so as to make it easier to compare the cost with buying locally.
Table: Documents the price difference between used, new, and retail mixers as a percentage. This is perhaps the most important information I have here!
Model
eBay Used vs New
eBay New vs Retail
eBay Used vs Retail
Refurb vs Retail
KitchenAid Classic
25%
31%
49%
44%
KitchenAid Artisan
32%
27%
51%
39%
KitchenAid Pro 500
24%
22%
40%
31%
KitchenAid Pro 600
19%
27%
40%
34%
Averages
25%
27%
45%
37%
You can see that even buying the mixers new on eBay is a fabulous deal. Some interesting statistics to highlight are that:
Buying a new mixer on eBay is about 27% cheaper than buying in a store.
A used mixer in good condition is about 25% cheaper than buying it new on eBay.
Therefore, a used mixer on eBay is about half the cost of a new one from the store.
Refurbished mixers (which are practically new) are about 37% less than the cost of a new item from a retailer.
If you ever watch television, on cooking shows you always see a KitchenAid stand mixer. If you watch a movie where the character has a nice kitchen, you will always see a KitchenAid stand mixer. If your friend likes to cook, chances are he/she has a KitchenAid stand mixer. These beasts of a tool are a symbol that you enjoy cooking, and that you have value buying tools that will last you a lifetime. I have wanted to buy one of these for many years, but being that they cost a few hundred dollars, you can bet your bottom Dollar that I am going to do a lot of research. Especially if I plan on using it for several decades.
This post will be part of a series of articles that I will post in the next few days. I will link to all of them here.
Models
The first thing to decide has been which model I want. There are three main models of the stand mixer, but there are also several other models, special editions, and varieties made special for different stores.
The three most common models are Classic, Artisan, and Pro 600. The Pro 500 model is a small upgrade from the artisan and the Pro 5 Plus seems to be a model that is sold to stores like CostCo, Sams Club, and Kohls, and then given a different model name. Here is a summary on the seven models that I came across most frequently.
Visual Comparison
Classic
Artisan
90th Anniversary
Pro 500
Pro 5 Plus
Pro 600
Feature Comparison
Classic
Classic Plus
Artisan
90th Anniv.
Pro 500
Pro 5 Plus
Pro 600
Wattage
250 Watts
275 Watts
325 Watts
325 Watts
325 Watts
450 Watts
575 Watts
Speeds
10
10
10
10
10
10
10
Bowl Size
4.5 Quarts
4.5 Quarts
5 Quarts
5 Quarts
5 Quarts
5 Quarts
6 Quarts
Head Tilt
Yes
Yes
Yes
Yes
No
No
No
Bowl Lift
No
No
No
No
Yes
Yes
Yes
Height
14 inches
14 inches
14 inches
14 inches
1.65 inches
16.5 inches
16.5 inches
Soft Start
No
No
No
No
Yes
Yes
Yes
Speed Sensor
No
No
No
No
?
Yes
Yes
Auto Shutoff
No
No
No
No
Yes
Yes
yes
Bowl
Steel
Steel
Steel
Glass
Steel
Steel
Steel
Opposite Spinning
?
?
Yes
Yes
Yes
Yes
Yes
Feature Explanations
Wattage:
Many people will dispute the importance of the wattage, but it should be considered. Typically, the more wattage, the greater the ability of the mixer to power through more tough mixtures and doughs.
Head Tilt / Bowl Lift:
Head tilts make it easier to add ingredients to the bowl but the mixer must be turned off. It is also easier to clean the head since it flips out towards you. With the bowl lift system, you can lower the bowl while it is running, but may be more difficult to clean.
Bowl:
The 90th anniversary model is currently the only way to get a glass bowl. It is rumored however that KitchenAid will sell glass bowls for the tilt-head models in the near future.
Soft Start:
Using this feature, the mixer will start with a low speed and increase to the speed of your choice. This reduces the initial splatter effect caused by starting at high speeds.
Speed Sensor:
Mixers with this feature will adjust based on how easy/difficult it is to spin through your substance.
Auto Shutoff:
As a safety precaution, the mixer will turn off if it is really struggling in order to prevent the motor from dying out.
Opposite Spinning:
I wasn’t sure what this feature is called, but it is where the beater spins in one direction while the shaft spins the opposite direction. This moves the beater to 67 different points around the bowl.
Analysis
All KitchenAid Stand Mixers are made with absolute quality in mind. It used to be that some models were made with a plastic shell but that is no longer the case. If purchased from a normal retailer (or from KitchenAid), all models come with a one year warranty. If you are really strapped for cash then the Classic model is the cheapest, but it if you are going to spend over two hundred dollars on a premium product you might as well spend a little more and get the upgrade (Artisan).
The Artisan seems to be the happy medium and also has the tilt head which is a feature I am very interested in. It is missing the smart features such as soft start and auto shutoff which I see could be very useful. The Pro 600 model is obviously the most advance, with almost 600 watts, a larger bowl size, and all the remaining features. The Pro 5 Plus however has all of the same features as the Pro 600, but less wattage.
As this point the most important things to consider in a product like this are what you need it to do and which product fits those needs best. I am currently leaning towards the Artisan because it is slightly smaller and has the tilt head, but the smart features of the Pro 5 Plus are very appetizing. Pricing will be very important in the decision of which model to buy and is also a very huge subject! For this reason, it will be covered in a future article.
The past few days I have been doing research on …something that interests me very much, which I will save for another post. I have been entering this data into Excel, and today came upon a situation where doing some regex find / replace would be very helpful. I have used regular expressions in Notepad++ before, but I hadn’t done it with captured groups.
What I had was HTML code for a select box full of several colors. I wanted a quick way to extract the colors and get rid of the rest.
Regular expressions are easy, but I wanted to have a heading for the next section so I felt like this needed one as well. Rather than extracting the text from the actual label of the select option, I am grabbing the contents of the title attribute. Captured groups are created by surrounding with parenthesis.
1
.*title="([\w\s]+).*
Captured Groups
In Dreamweaver I remember referencing captured groups in find and replace with a dollar sign and then the number. This did not work in notepad++. Instead, I figured out you use a forward slash (/). So, for the first captured group, you do \1. For the second, \2, etc.
1
\1
Make sure that you check the “Use Regular Expressions” checkbox, otherwise NotePad++ will think you are crazy.