Guest

voiceinsideyou

By: a guest on Nov 24th, 2008  |  syntax: None  |  size: 22.70 KB  |  hits: 1,455  |  expires: Never
download  |  raw  |  embed  |  report abuse
Copied
  1. // ==UserScript==
  2. // @name           MusicBrainz enhanced voting
  3. // @description    Adds a number of features to the voting page
  4. // @version        2008-11-23
  5. // @author         Jugdish (partly hacked by voiceinsideyou)
  6. // @namespace      4D898C47-898C-4516-9602-C072BCCC27FB
  7. //
  8. // @include        http://*.musicbrainz.org/mod/search/results.html*
  9. // @include        http://musicbrainz.org/mod/search/results.html*
  10. // ==/UserScript==
  11.  
  12. /*
  13.     This program is free software; you can redistribute it and/or modify
  14.     it under the terms of the GNU General Public License as published by
  15.     the Free Software Foundation; either version 2 of the License, or
  16.     (at your option) any later version.
  17.  
  18.     This program is distributed in the hope that it will be useful,
  19.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.     GNU General Public License for more details.
  22.  
  23.     You should have received a copy of the GNU General Public License
  24.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25. */
  26.  
  27.  
  28. //#######################################################################
  29. //                          UTILITY FUNCTIONS
  30. //#######################################################################
  31. var HTTP = {
  32.         // This is a list of XMLHttpRequest-creation factory functions to try
  33.         _factories: [
  34.                 function() { return new XMLHttpRequest(); },
  35.                 function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
  36.                 function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
  37.         ],
  38.  
  39.         // When we find a factory that works, store it here.
  40.         _factory: null,
  41.  
  42.         newRequest: function() {
  43.                 if (HTTP._factory != null) return HTTP._factory();
  44.        
  45.                 for (var i = 0; i < HTTP._factories.length; i++) {
  46.                         try {
  47.                                 var factory = HTTP._factories[i];
  48.                                 var request = factory();
  49.                                 if (request != null) {
  50.                                         HTTP._factory = factory;
  51.                                         return request;
  52.                                 }
  53.                         }
  54.                         catch(e) {
  55.                                 continue;
  56.                         }
  57.                 }
  58.                 // If we get here, none of the factory candidates succeeded,
  59.                 // so throw an exception now and for all future calls.
  60.                 HTTP._factory = function() { throw new Error("XMLHttpRequest not supported"); }
  61.                 HTTP._factory(); // Throw an error
  62.         },
  63.        
  64.         post: function(url, values, callback, cb_arg) {
  65.                 var request = HTTP.newRequest();
  66.                 request.onreadystatechange = function() {
  67.                         if (request.readyState == 4) {
  68.                                 if (request.status == 200)
  69.                                         callback(cb_arg, HTTP._getResponse(request));
  70.                                 else
  71.                                         alert("Error: HTTP Response "+request.status+"\n"+request.statusText);
  72.                         }
  73.                 }
  74.                 request.open("POST", url);
  75.                 // This header tells the server how to interpret the body of the request.
  76.                 request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  77.                 // Encode the properties of the values object and send them as the body of the request.
  78.                 var encoded = HTTP.encodeFormData(values);
  79.                 request.send(encoded);
  80.         },
  81.        
  82.         encodeFormData: function(data) {
  83.                 var pairs = [];
  84.                 var regexp = /%20/g; // A regular expression to match an encoded space
  85.                 var regexp2 = /%3D/g;
  86.                 for(var name in data) {
  87.                         var value = data[name].toString();
  88.                         // Create a name/value pair, but encode name and value first
  89.                         // The global function encodeURIComponent does almost what we want,
  90.                         // but it encodes spaces as %20 instead of as "+". We have to
  91.                         // fix that with String.replace()
  92.                         var pair = encodeURIComponent(name).replace(regexp,"+") + '=' + encodeURIComponent(value).replace(regexp,"+").replace(regexp2,"=");
  93.                         pairs.push(pair);
  94.                 }
  95.                 // Concatenate all the name/value pairs, separating them with &
  96.                 return pairs.join('&');
  97.         },
  98.        
  99.         _getResponse: function(request) {
  100.                 // Check the content type returned by the server
  101.                 switch(request.getResponseHeader("Content-Type")) {
  102.                         case "text/xml":
  103.                                 // If it is an XML document, use the parsed Document object.
  104.                                 return request.responseXML;
  105.                         case "text/json":
  106.                         case "text/javascript":
  107.                         case "application/javascript":
  108.                         case "application/x-javascript":
  109.                                 // If the response is JavaScript code, or a JSON-encoded value,
  110.                                 // call eval() on the text to "parse" it to a JavaScript value.
  111.                                 // Note: only do this if the JavaScript code is from a trusted server!
  112.                                 return eval(request.responseText);
  113.                         default:
  114.                                 // Otherwise, treat the response as plain text and return as a string.
  115.                                 return request.responseText;
  116.                 }
  117.         }
  118. }
  119.  
  120. function getElementsByClass(classname, tagname, root) {
  121.     if (!root) root = document;
  122.     else if (typeof root == "string") root = document.getElementById(root);
  123.  
  124.     // if no tagname was specified, use all tags
  125.     if (!tagname) tagname = "15-";
  126.  
  127.     // Find all descendants of the specified root with the specified tagname
  128.     var all = root.getElementsByTagName(tagname);
  129.  
  130.     // If no classname was specified, we return all tags
  131.     if (!classname) return all;
  132.  
  133.     // Otherwise, we filter the element by classname
  134.     var elements = [];  // Start with an empty array
  135.     for(var i = 0; i < all.length; i++) {
  136.         var element = all[i];
  137.         if (isMember(element, classname)) // isMember() is defined below
  138.             elements.push(element);       // Add class members to our array
  139.     }
  140.  
  141.     return elements;
  142.  
  143.     function isMember(element, classname) {
  144.         var classes = element.className;  // Get the list of classes
  145.         if (!classes) return false;             // No classes defined
  146.         if (classes == classname) return true;  // Exact match
  147.  
  148.         var whitespace = /\s+/;
  149.         if (!whitespace.test(classes)) return false;
  150.  
  151.         var c = classes.split(whitespace);  // Split with whitespace delimiter
  152.         for(var i = 0; i < c.length; i++) { // Loop through classes
  153.             if (c[i] == classname) return true;  // and check for matches
  154.         }
  155.  
  156.         return false;
  157.     }
  158. }
  159.  
  160. function getText(n) {
  161.     var strings = [];
  162.     getStrings(n, strings);
  163.     return strings.join("").replace(/^\s*/,"").replace(/\s*$/,"");
  164.  
  165.     function getStrings(n, strings) {
  166.         if (n.nodeType == 3 /* Node.TEXT_NODE */)
  167.             strings.push(n.data);
  168.         else if (n.nodeType == 1 /* Node.ELEMENT_NODE */) {
  169.             for(var m = n.firstChild; m != null; m = m.nextSibling) {
  170.                 getStrings(m, strings);
  171.             }
  172.         }
  173.     }
  174. }
  175.  
  176. function insertAfter(newElement, targetElement) {
  177.         var parent = targetElement.parentNode;
  178.         if (parent.lastChild == targetElement)
  179.                 parent.appendChild(newElement);
  180.         else
  181.                 parent.insertBefore(newElement, targetElement.nextSibling);
  182. }
  183.  
  184. //#######################################################################
  185. //                               GLOBALS
  186. //#######################################################################
  187. var currUser = "You";
  188. var noteBoxes = new Object();
  189. var addLinks = new Object();
  190. var voteForm = null;
  191. var voteButton = null;
  192. var editTable = null;
  193. var numTasks = 0;
  194. var numErrors = 0;
  195. var numProcessed = 0;
  196. var doVotes = true;
  197. var incAllVotes = false;
  198. var vInputs = {
  199.         "approve": new Object(),
  200.         "yes": new Object(),
  201.         "no": new Object(),
  202.         "abs": new Object(),
  203.         "novote": new Object(),
  204.         "cancel": new Object()
  205. };
  206.  
  207. //#######################################################################
  208. //                              FUNCTIONS
  209. //#######################################################################
  210. function updateButton() {
  211.         voteButton.value = "Enter "+(doVotes ? "votes/" : "")+"approves + notes »";
  212. }
  213.  
  214. function compactNode(n) {
  215.         if (n.style) {
  216.                 n.style["marginLeft"] = "0px";
  217.                 n.style["marginRight"] = "0px";
  218.                 n.style["paddingLeft"] = "1px";
  219.                 n.style["paddingRight"] = "1px";
  220.         }
  221. }
  222.  
  223. function setVoteColor(cell) {
  224.         var inputs = cell.getElementsByTagName("input");
  225.         var bgColor = "white";
  226.         for (var i = 0; i < inputs.length; i++) {
  227.                 if (inputs[i].checked) {
  228.                         switch (inputs[i].value) {
  229.                                 case "approve":
  230.                                         bgColor = "#00a650";
  231.                                         inputs[i].parentNode.style["borderColor"] = "white";
  232.                                         break;
  233.                                 case "yes":
  234.                                         bgColor = "#eeffee";
  235.                                         inputs[i].parentNode.style["borderColor"] = "#88ff88";
  236.                                         break;
  237.                                 case "no":
  238.                                         bgColor = "#ffeeee";
  239.                                         inputs[i].parentNode.style["borderColor"] = "#ff8888";
  240.                                         break;
  241.                                 case "abs":
  242.                                         bgColor = "#ffffcc";
  243.                                         inputs[i].parentNode.style["borderColor"] = "#eeee66";
  244.                                         break;
  245.                                 case "cancel":
  246.                                         bgColor = "#ff0000";
  247.                                         inputs[i].parentNode.style["borderColor"] = "white";
  248.                                         break;
  249.                         }
  250.                 } else
  251.                         inputs[i].parentNode.style["borderColor"] = "transparent";
  252.         }
  253.         cell.style["backgroundColor"] = bgColor;
  254. }
  255.  
  256. function updateVoteColor(input) {
  257.         var ancestor = input;
  258.         while (ancestor.className != "vote" && ancestor.parentNode)
  259.                 ancestor = ancestor.parentNode;
  260.         if (ancestor.className == "vote")
  261.                 setVoteColor(ancestor);
  262. }
  263.  
  264.  
  265. //#######################################################################
  266. //                             CALLBACKS
  267. //#######################################################################
  268. function cb_post(editid, response) {
  269.         numProcessed++;
  270.         voteButton.value = (numTasks-numProcessed)+" task"+(numTasks-numProcessed == 1 ? "" : "s")+" remaining...";
  271.        
  272.         var responseText = response.replace(/[\n\t]/g,"");
  273.         if (!responseText.match(/note saved successfully/i) && !responseText.match(/Status:<\/td><td>Change\&nbsp\;applied/i) && !responseText.match(/To&nbsp;be&nbsp;cancelled/i))
  274.                 numErrors++;
  275.        
  276.         // if we are the last one, check if any failed
  277.         if (numProcessed == numTasks) {
  278.                 if (numErrors)
  279.                         alert(numErrors+" HTTP POST failed!");
  280.                 if (voteForm && doVotes)
  281.                         voteForm.submit();
  282.                 else
  283.                         window.location.reload();
  284.         }
  285. }
  286.  
  287. //#######################################################################
  288. //                            EVENT HANDLERS
  289. //#######################################################################
  290. function captureSubmit(e) {
  291.         numErrors = 0;
  292.         numTasks = 0;
  293.         // count selected approves
  294.         for (id in vInputs["approve"])
  295.                 if (vInputs["approve"][id].checked)
  296.                         numTasks++;
  297.         // count selected cancels
  298.         for (id in vInputs["cancel"])
  299.                 if (vInputs["cancel"][id].checked)
  300.                         numTasks++;
  301.         for (id in noteBoxes) {
  302.                 if ((id in vInputs["approve"]) && vInputs["approve"][id].checked)
  303.                         continue;
  304.                 else if ((id in vInputs["cancel"]) && vInputs["cancel"][id].checked)
  305.                         continue;
  306.                 if (document.getElementById("textarea_"+id).value)
  307.                         numTasks++;
  308.         }
  309.  
  310.         if (numTasks) {
  311.                 //alert("Submitting "+numTasks+" tasks");
  312.                 var target = e ? e.target : this;
  313.                 e.stopPropagation();
  314.                 e.preventDefault();
  315.                 voteButton.disabled = true;
  316.                 voteButton.value = numTasks+" tasks remaining...";
  317.                 numProcessed = 0;
  318.                
  319.                 // submit selected approves
  320.                 for (id in vInputs["approve"]) {
  321.                         if (vInputs["approve"][id].checked) {
  322.                                 var note = "";
  323.                                 if (id in noteBoxes) {
  324.                                         var textarea = document.getElementById("textarea_"+id);
  325.                                         if (textarea.value) {
  326.                                                 note = textarea.value;
  327.                                                 delete noteBoxes[id];
  328.                                         }
  329.                                 }
  330.                                 HTTP.post("/mod/approve.html", { notetext: note, submitvalue: "Approve edit »", editid: id }, cb_post, id);
  331.                         }
  332.                 }
  333.                
  334.                 // submit selected cancels
  335.                 for (id in vInputs["cancel"]) {
  336.                         if (vInputs["cancel"][id].checked) {
  337.                                 var note = "";
  338.                                 if (id in noteBoxes) {
  339.                                         var textarea = document.getElementById("textarea_"+id);
  340.                                         if (textarea.value) {
  341.                                                 note = textarea.value;
  342.                                                 delete noteBoxes[id];
  343.                                         }
  344.                                 }
  345.                                 HTTP.post("/mod/remove.html", { notetext: note, submitvalue: "Cancel edit »", editid: id }, cb_post, id);
  346.                         }
  347.                 }
  348.         }
  349. }
  350.  
  351. function captureAllVotes(e) {
  352.         var results;
  353.         if (results = e.target.id.match(/^rowidOverride-(.*)$/)) {
  354.                 for (type in vInputs) {
  355.                         for (id in vInputs[type]) {
  356.                                 vInputs[type][id].checked = (results[1] == type && e.target.checked) ? true : false;
  357.                                 updateVoteColor(vInputs[type][id]);
  358.                         }
  359.                 }
  360.                 var n = e.target.id.match(/approve/) ? document.getElementById(e.target.id.replace(/approve/,"cancel")) : (e.target.id.match(/cancel/) ? document.getElementById(e.target.id.replace(/cancel/,"approve")) : null);
  361.                 if (n) n.checked = false;
  362.                 updateVoteColor(e.target);
  363.         }
  364. }
  365.  
  366. function captureVoteChange(e) {
  367.         var results;
  368.         if (e.target.name && (results = e.target.name.match(/^rowid([0-9]+)$/))) {
  369.                 var n = e.target.id.match(/approve/) ? document.getElementById(e.target.id.replace(/approve/,"cancel")) : (e.target.id.match(/cancel/) ? document.getElementById(e.target.id.replace(/cancel/,"approve")) : null);
  370.                 if (n) n.checked = false;
  371.                 updateVoteColor(e.target);
  372.         }
  373. }
  374.  
  375. //#######################################################################
  376. //                           BEGIN EXECUTION
  377. //#######################################################################
  378. // determine user name
  379. var results = getElementsByClass("sidemenu-box","div",document.body);
  380. for (var i = 0; i < results.length; i++) {
  381.         var links = results[i].getElementsByTagName("a");
  382.         if (links.length && links[0].href && links[0].href.match(/\/show\/user\/$/)) {
  383.                 currUser = links[0].innerHTML;
  384.                 break;
  385.         }
  386. }
  387.  
  388. // find all voting radio button inputs
  389. var nodes = document.getElementsByTagName("input");
  390. for (var i = 0; i < nodes.length; i++) {
  391.         var results;
  392.         if (nodes[i].type == "radio" && (results = nodes[i].id.match(/^rowid([0-9]+)-(.*)$/)))
  393.                 if (results[2] in vInputs)
  394.                         vInputs[results[2]][results[1]] = nodes[i];
  395. }
  396.  
  397. // find main edit table
  398. var editTable = getElementsByClass("editlist","table",document.body)[0];
  399.  
  400. var rows = [];
  401. for (var i = 0; i < editTable.lastChild.childNodes.length; i++) {
  402.         var child = editTable.lastChild.childNodes[i];
  403.         if (child.tagName && child.tagName.toLowerCase() == "tr" && child.className == "showedit")
  404.                 rows.push(child);
  405. }
  406. for (var i = 0; i < rows.length; i++) {
  407.         var tables = rows[i].getElementsByTagName("table");
  408.         if (tables.length && tables[0].className == "editfields") {
  409.                 var text = getText(tables[0]).replace(/[\r\n]/g,"");
  410.                 var results;
  411.                 if (results = text.match(/Editor:.+Edit ID:\s+([0-9]+)/)) {
  412.                        
  413.                         var id = results[1];
  414.                        
  415.                         var n1, n2;
  416.                         var r = document.createElement("tr");
  417.                         r.style["display"] = "none";
  418.                         noteBoxes[id] = r;
  419.                        
  420.                         tables = i+2 < rows.length ? rows[i+2].getElementsByTagName("table") : null;
  421.                         if (tables && tables.length && tables[0].className == "noteslist") {
  422.                                 // exist notes on edit
  423.                                 tables[0].appendChild(r);
  424.                                 r.className = "noteslist even";
  425.                                 n1 = r;
  426.                         } else {
  427.                                 // no notes on edit
  428.                                 insertAfter(r, rows[i+1]);
  429.                                 r.className = "showedit";
  430.                                 r.appendChild(n1 = document.createElement("td"));
  431.                                 n1.className = "notes";
  432.                                 n1.setAttribute("colspan","3");
  433.                                 n1.innerHTML = "Notes:<br />";
  434.                                 n1.appendChild(n2 = document.createElement("table"));
  435.                                 n2.className = "noteslist";
  436.                                 n2.style["width"] = "100%";
  437.                                 n2.appendChild(n1 = document.createElement("tr"));
  438.                                 n1.className = "noteslist first";
  439.                         }
  440.                         n1.appendChild(n2 = document.createElement("td"));
  441.                         n2.className = "noter";
  442.                         n2.innerHTML = "<strong><a href=\"/show/user/\" title=\"User: "+currUser+"\">"+currUser+"</a></strong>:";
  443.                         n1.appendChild(n2 = document.createElement("td"));
  444.                         n2.className = "text";
  445.                         n2.appendChild(n1 = document.createElement("textarea"));
  446.                         n1.setAttribute("rows","3");
  447.                         n1.setAttribute("cols","40");
  448.                         n1.setAttribute("id","textarea_"+id);
  449.                         n1.style["width"] = "100%";
  450.                        
  451.                         // insert "approve" and "cancel" radio buttons
  452.                         if (i+1 < rows.length) {
  453.                                 tables = getElementsByClass("votechoice","table",rows[i+1]);
  454.                                 if (tables.length == 1)
  455.                                         tables[0].style["width"] = "100%";
  456.                                 var votehead = getElementsByClass("votehead","td",rows[i]);
  457.                                 if (votehead.length == 1) {
  458.                                         var links = votehead[0].getElementsByTagName("a");
  459.                                         var doApprove = false;
  460.                                         var doCancel = false;
  461.                                         for (var j = 0; j < links.length; j++) {
  462.                                                 if (links[j].href) {
  463.                                                         if (links[j].href.match(/\/mod\/approve.html/)) {
  464.                                                                 doApprove = true;
  465.                                                                 // hide link
  466.                                                                 links[j].style["display"] = "none";
  467.                                                                 if (links[j].previousSibling && links[j].previousSibling.nodeType == 3) links[j].previousSibling.data = "";
  468.                                                         } else if (links[j].href.match(/\/mod\/remove.html/)) {
  469.                                                                 doCancel = true;
  470.                                                                 // hide link
  471.                                                                 links[j].style["display"] = "none";
  472.                                                                 if (links[j].previousSibling && links[j].previousSibling.nodeType == 3) links[j].previousSibling.data = "";
  473.                                                         }
  474.                                                 }
  475.                                         }      
  476.                                         // add radio/checkbox button
  477.                                         if (doApprove || doCancel) {
  478.                                                 var votecell = getElementsByClass("vote","td",rows[i+1]);
  479.                                                 var tdApprove, labelApprove, inputApprove;
  480.                                                 var tdCancel, labelCancel, inputCancel;
  481.                                                 if (votecell.length == 1) {
  482.                                                         if (doApprove) {
  483.                                                                 tdApprove = document.createElement("td");
  484.                                                                 labelApprove = document.createElement("label");
  485.                                                                 labelApprove.setAttribute("for","rowid"+id+"-approve");
  486.                                                                 labelApprove.style["border"] = "2px transparent dotted";
  487.                                                                 tdApprove.appendChild(labelApprove);
  488.                                                                 inputApprove = document.createElement("input");
  489.                                                                 inputApprove.type = "checkbox";
  490.                                                                 inputApprove.name = "rowid"+id;
  491.                                                                 inputApprove.id = "rowid"+id+"-approve";
  492.                                                                 inputApprove.value = "approve";
  493.                                                                 inputApprove.checked = false;
  494.                                                                 vInputs["approve"][id] = inputApprove;
  495.                                                         }
  496.                                                         if (doCancel) {
  497.                                                                 tdCancel = document.createElement("td");
  498.                                                                 labelCancel = document.createElement("label");
  499.                                                                 labelCancel.setAttribute("for","rowid"+id+"-cancel");
  500.                                                                 labelCancel.style["border"] = "2px transparent dotted";
  501.                                                                 tdCancel.appendChild(labelCancel);
  502.                                                                 inputCancel = document.createElement("input");
  503.                                                                 inputCancel.type = "checkbox";
  504.                                                                 inputCancel.name = "rowid"+id;
  505.                                                                 inputCancel.id = "rowid"+id+"-cancel";
  506.                                                                 inputCancel.value = "cancel";
  507.                                                                 inputCancel.checked = false;
  508.                                                                 vInputs["cancel"][id] = inputCancel;
  509.                                                         }
  510.                                                         if (tables.length == 1) { // vote options on this edit
  511.                                                                 labelApprove.innerHTML = "<br /><b>APV</b>";
  512.                                                                 inputApprove.type = "radio";
  513.                                                                 var tr = tables[0].getElementsByTagName("tr")[0];
  514.                                                                 tr.insertBefore(tdApprove,tr.firstChild);
  515.                                                                 labelApprove.insertBefore(inputApprove,labelApprove.firstChild);
  516.                                                         } else { // can't vote on this edit
  517.                                                                 labelCancel.innerHTML = "<br /><b>CANCEL</b>";
  518.                                                                 labelCancel.insertBefore(inputCancel,labelCancel.firstChild);
  519.                                                                 var table = document.createElement("table");
  520.                                                                 table.className = "votechoice votechoice4";
  521.                                                                 table.style["width"] = "100%";
  522.                                                                 var tr = document.createElement("tr");
  523.                                                                 if (doApprove) {
  524.                                                                         labelApprove.innerHTML = "<br /><b>APPROVE</b>";
  525.                                                                         tr.appendChild(tdApprove);
  526.                                                                         labelApprove.insertBefore(inputApprove,labelApprove.firstChild);
  527.                                                                 }
  528.                                                                 tr.appendChild(tdCancel);
  529.                                                                 table.appendChild(tr);
  530.                                                                 votecell[0].innerHTML = "";
  531.                                                                 votecell[0].appendChild(table);
  532.                                                         }
  533.                                                 }
  534.                                         }
  535.                                 }
  536.                         }
  537.                 }
  538.         }
  539. }
  540. // find "Enter votes" button
  541. for (var i = 0; i < document.forms.length; i++) {
  542.         if (document.forms[i].action.match(/\/bare\/vote.html$/)) {
  543.                 voteForm = document.forms[i];
  544.                 voteForm.addEventListener("submit",captureSubmit,true);
  545.                 for (var j = 0; j < voteForm.elements.length; j++) {
  546.                         if (voteForm.elements[j].type == "submit" && voteForm.elements[j].value.match(/^Continue »/i)) {
  547.                                 voteButton = voteForm.elements[j];
  548.                                 updateButton();
  549.                                 break;
  550.                         }
  551.                 }
  552.         }
  553. }
  554. // reset form
  555. if (voteForm) voteForm.reset();
  556.  
  557. if (!voteButton) {
  558.         doVotes = false;
  559.         voteButton = document.createElement("input");
  560.         voteButton.type = "button";
  561.         voteButton.addEventListener("click",captureSubmit,true);
  562.         updateButton();
  563.        
  564.         if (editTable) {
  565.                 var div = document.createElement("div");
  566.                 div.style["textAlign"] = "right";
  567.                 div.style["marginBottom"] = "20px";
  568.                 div.innerHTML = "Click here to enter notes for items on this page: ";
  569.                 insertAfter(voteButton,div.lastChild);
  570.                 insertAfter(div,editTable);
  571.         }
  572. }
  573.  
  574. // prep all radio/checkboxes
  575. for (var i = 0; i < rows.length; i++) {
  576.         var votecell = getElementsByClass("vote","td",rows[i]);
  577.         if (votecell.length == 1) {
  578.                 compactNode(votecell[0]);
  579.                 var inputs = votecell[0].getElementsByTagName("input");
  580.                 for (var j = 0; j < inputs.length; j++) {
  581.                         compactNode(inputs[j]);
  582.                         compactNode(inputs[j].parentNode);
  583.                         inputs[j].addEventListener("change",captureVoteChange,true);
  584.                         if (inputs[j].parentNode.lastChild.nodeType == 3 && inputs[j].parentNode.lastChild.data.match(/No.+?vote/))
  585.                                 inputs[j].parentNode.lastChild.data = "None";
  586.                 }
  587.                 setVoteColor(votecell[0]);
  588.         }
  589. }
  590.  
  591. if (incAllVotes) {
  592.         // prepare overriding vote radio buttons
  593.         var tr, td;
  594.         var overrideTable = document.createElement("table");
  595.         overrideTable.className = "votechoice votechoice4";
  596.         tr = document.createElement("tr");
  597.         overrideTable.appendChild(tr);
  598.         for (type in vInputs) {
  599.                 for (id in vInputs[type]) {
  600.                         td = document.createElement("td");
  601.                         var label = document.createElement("label");
  602.                         label.setAttribute("for","rowidOverride-"+type);
  603.                         var input = document.createElement("input");
  604.                         input.type = "radio";
  605.                         input.name = "rowidOverride";
  606.                         input.id = "rowidOverride-"+type;
  607.                         input.value = type;
  608.                         input.checked = false;
  609.                         input.addEventListener("click",captureAllVotes,true);
  610.                         var text = document.createTextNode(type.charAt(0).toUpperCase()+type.substring(1));
  611.                         if (type == "approve") {
  612.                                 text.data = "APV";
  613.                                 label.style["border"] = "2px transparent dotted";
  614.                                 label.style["fontWeight"] = "bold";
  615.                         } else if (type == "cancel") {
  616.                                 text.data = "CNL";
  617.                                 label.style["border"] = "2px transparent dotted";
  618.                                 label.style["fontWeight"] = "bold";
  619.                         }
  620.                         else if (type == "novote") text.data = "None";
  621.                         label.appendChild(input);
  622.                         label.appendChild(document.createElement("br"));
  623.                         label.appendChild(text);
  624.                         td.appendChild(label);
  625.                         tr.appendChild(td);
  626.                         compactNode(input);
  627.                         compactNode(label);
  628.                         break;
  629.                 }
  630.         }
  631.         var inputs = overrideTable.getElementsByTagName("input");
  632.         if (inputs.length) {
  633.                 if (inputs.length <= 2) {
  634.                         for (var i = 0; i < inputs.length; i++) {
  635.                                 inputs[i].type = "checkbox";
  636.                                 if (inputs[i].id.match(/approve/)) inputs[i].nextSibling.nextSibling.data = "APPROVE";
  637.                                 else if (inputs[i].id.match(/cancel/)) inputs[i].nextSibling.nextSibling.data = "CANCEL";
  638.                         }
  639.                 }
  640.                 // add "All Votes" box to top of page
  641.                 tr = document.createElement("tr");
  642.                 tr.className = "showedit";
  643.                 tr.appendChild(document.createElement("td"));
  644.                 tr.appendChild(td = document.createElement("td"));
  645.                 td.setAttribute("align","right");
  646.                 td.innerHTML = "<strong>ALL VOTES:</strong>&nbsp;";
  647.                 tr.appendChild(td = document.createElement("td"));
  648.                 td.className = "vote";
  649.                 td.appendChild(overrideTable);
  650.                 compactNode(td);
  651.                 editTable.lastChild.insertBefore(tr, editTable.lastChild.firstChild);
  652.         }
  653. }