liquid_feedback_frontend
annotate static/js/partialload.js @ 19:00d1004545f1
Dynamic interface using XMLHttpRequests, and many other changes
Bugfixes:
- Only allow voting on admitted initiatives
- Repaired issue search
- Don't display delegations for closed issues on member page
- Don't show revoke link in initiative, when issue is already half_frozen
- Localization for voting JavaScript
- Display author of suggestions
Disclosure of voting data after voting is finished:
- Possibility to inspect every ballot including preferences
- Show number of voters preferring one initiative to another initiative
Interface behaviour changes:
- Reversed default order of drafts
- Default order of suggestions changed
- Show new drafts of initiatives only once per day in timeline
Accessibility:
- Barrier-free voting implemented
- POST links are now accessible without JavaScript
- Changed gray for unsatisfied supporters in bar graph to a lighter gray
Other interface improvements:
- Optical enhancements
- Dynamic interface using XMLHttpRequests
- Show usage terms in about section
- Show own membership in area listing
- Show uninformed supporters greyed out and marked with yellow question mark
- Warning box in non-admitted initiatives
- When voted, don't display voting notice and change label of voting link
- Show object counts in more tabulator heads
- Enlarged member statement input field
Miscellaneous:
- Code cleanup
- Added README file containing installation instructions
- Use new WebMCP function ui.filters{...} instead of own ui.filter and ui.order functions
Bugfixes:
- Only allow voting on admitted initiatives
- Repaired issue search
- Don't display delegations for closed issues on member page
- Don't show revoke link in initiative, when issue is already half_frozen
- Localization for voting JavaScript
- Display author of suggestions
Disclosure of voting data after voting is finished:
- Possibility to inspect every ballot including preferences
- Show number of voters preferring one initiative to another initiative
Interface behaviour changes:
- Reversed default order of drafts
- Default order of suggestions changed
- Show new drafts of initiatives only once per day in timeline
Accessibility:
- Barrier-free voting implemented
- POST links are now accessible without JavaScript
- Changed gray for unsatisfied supporters in bar graph to a lighter gray
Other interface improvements:
- Optical enhancements
- Dynamic interface using XMLHttpRequests
- Show usage terms in about section
- Show own membership in area listing
- Show uninformed supporters greyed out and marked with yellow question mark
- Warning box in non-admitted initiatives
- When voted, don't display voting notice and change label of voting link
- Show object counts in more tabulator heads
- Enlarged member statement input field
Miscellaneous:
- Code cleanup
- Added README file containing installation instructions
- Use new WebMCP function ui.filters{...} instead of own ui.filter and ui.order functions
| author | bsw/jbe | 
|---|---|
| date | Sat Feb 20 22:10:31 2010 +0100 (2010-02-20) | 
| parents | |
| children | 
| rev | line source | 
|---|---|
| bsw/jbe@19 | 1 | 
| bsw/jbe@19 | 2 partialload_queue = []; | 
| bsw/jbe@19 | 3 partialload_queueRPos = 0; | 
| bsw/jbe@19 | 4 partialload_queueWPos = 0; | 
| bsw/jbe@19 | 5 | 
| bsw/jbe@19 | 6 function partialload_getFormKeyValuePairs(form) { | 
| bsw/jbe@19 | 7 var result = {}; | 
| bsw/jbe@19 | 8 for (var i=0; i<form.elements.length; i++) { | 
| bsw/jbe@19 | 9 var inputElement = form.elements[i]; | 
| bsw/jbe@19 | 10 var key = inputElement.name; | 
| bsw/jbe@19 | 11 var value = inputElement.value; | 
| bsw/jbe@19 | 12 if (result[key] == null) result[key] = value; | 
| bsw/jbe@19 | 13 else if (typeof(result[key]) == "object") { | 
| bsw/jbe@19 | 14 result[key][result[key].length] = value; | 
| bsw/jbe@19 | 15 } else { | 
| bsw/jbe@19 | 16 result[key] = [result[key], value]; | 
| bsw/jbe@19 | 17 } | 
| bsw/jbe@19 | 18 } | 
| bsw/jbe@19 | 19 return result; | 
| bsw/jbe@19 | 20 } | 
| bsw/jbe@19 | 21 | 
| bsw/jbe@19 | 22 function partialload_encodeFormData(params) { | 
| bsw/jbe@19 | 23 var result = ""; | 
| bsw/jbe@19 | 24 for (var key in params) { | 
| bsw/jbe@19 | 25 var value = params[key]; | 
| bsw/jbe@19 | 26 if (typeof(value) == "string") { | 
| bsw/jbe@19 | 27 if (result != "") result += "&"; | 
| bsw/jbe@19 | 28 result += encodeURIComponent(key) + "=" + encodeURIComponent(value); | 
| bsw/jbe@19 | 29 } else if (typeof(value) == "object") { | 
| bsw/jbe@19 | 30 var i; | 
| bsw/jbe@19 | 31 for (i=0; i<value.length; i++) { | 
| bsw/jbe@19 | 32 if (result != "") result += "&"; | 
| bsw/jbe@19 | 33 result += encodeURIComponent(key) + "=" + encodeURIComponent(value[i]); | 
| bsw/jbe@19 | 34 } | 
| bsw/jbe@19 | 35 } | 
| bsw/jbe@19 | 36 } | 
| bsw/jbe@19 | 37 return result; | 
| bsw/jbe@19 | 38 } | 
| bsw/jbe@19 | 39 | 
| bsw/jbe@19 | 40 function partialload_addFormDataToUrl(url, params) { | 
| bsw/jbe@19 | 41 if (params != null && typeof(params) != "string") { | 
| bsw/jbe@19 | 42 params = partialload_encodeFormData(params); | 
| bsw/jbe@19 | 43 } | 
| bsw/jbe@19 | 44 if (params != null) { | 
| bsw/jbe@19 | 45 if (url.search(/\?/) >= 0) { | 
| bsw/jbe@19 | 46 if (url.search(/&$/) >= 0) { | 
| bsw/jbe@19 | 47 url = url + params; | 
| bsw/jbe@19 | 48 } else { | 
| bsw/jbe@19 | 49 url = url + "&" + params; | 
| bsw/jbe@19 | 50 } | 
| bsw/jbe@19 | 51 } else { | 
| bsw/jbe@19 | 52 url = url + "?" + params; | 
| bsw/jbe@19 | 53 } | 
| bsw/jbe@19 | 54 } | 
| bsw/jbe@19 | 55 return url; | 
| bsw/jbe@19 | 56 } | 
| bsw/jbe@19 | 57 | 
| bsw/jbe@19 | 58 function partialload_mergeEncodedFormData(data1, data2) { | 
| bsw/jbe@19 | 59 if (data2 == null || data2 == "") return data1; | 
| bsw/jbe@19 | 60 if (data1 == null || data1 == "") return data2; | 
| bsw/jbe@19 | 61 return data1 + "&" + data2; | 
| bsw/jbe@19 | 62 } | 
| bsw/jbe@19 | 63 | 
| bsw/jbe@19 | 64 function partialload_startNextRequest() { | 
| bsw/jbe@19 | 65 var entry = partialload_queue[partialload_queueRPos++]; | 
| bsw/jbe@19 | 66 var req = new XMLHttpRequest(); | 
| bsw/jbe@19 | 67 req.open(entry.method, entry.url, true); | 
| bsw/jbe@19 | 68 req.onreadystatechange = function() { | 
| bsw/jbe@19 | 69 if (req.readyState == 4) { | 
| bsw/jbe@19 | 70 if (req.status == 200) { | 
| bsw/jbe@19 | 71 if (entry.successHandler != null) entry.successHandler(req.responseText); | 
| bsw/jbe@19 | 72 } else { | 
| bsw/jbe@19 | 73 if (entry.failureHandler != null) entry.failureHandler(); | 
| bsw/jbe@19 | 74 } | 
| bsw/jbe@19 | 75 if (partialload_queue[partialload_queueRPos]) { | 
| bsw/jbe@19 | 76 partialload_startNextRequest(); | 
| bsw/jbe@19 | 77 } else { | 
| bsw/jbe@19 | 78 partialload_queue = []; | 
| bsw/jbe@19 | 79 partialload_queueRPos = 0; | 
| bsw/jbe@19 | 80 partialload_queueWPos = 0; | 
| bsw/jbe@19 | 81 } | 
| bsw/jbe@19 | 82 } | 
| bsw/jbe@19 | 83 } | 
| bsw/jbe@19 | 84 if (entry.data) { | 
| bsw/jbe@19 | 85 req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); | 
| bsw/jbe@19 | 86 } | 
| bsw/jbe@19 | 87 req.send(entry.data); | 
| bsw/jbe@19 | 88 } | 
| bsw/jbe@19 | 89 | 
| bsw/jbe@19 | 90 function queuedHttpRequest( | 
| bsw/jbe@19 | 91 url_or_form, | 
| bsw/jbe@19 | 92 urlParams, | 
| bsw/jbe@19 | 93 postParams, | 
| bsw/jbe@19 | 94 successHandler, | 
| bsw/jbe@19 | 95 failureHandler | 
| bsw/jbe@19 | 96 ) { | 
| bsw/jbe@19 | 97 var method; | 
| bsw/jbe@19 | 98 var data = null; | 
| bsw/jbe@19 | 99 if (typeof(postParams) == "string") { | 
| bsw/jbe@19 | 100 data = postParams; | 
| bsw/jbe@19 | 101 } else if (postParams != null) { | 
| bsw/jbe@19 | 102 data = partialload_encodeFormData(postParams); | 
| bsw/jbe@19 | 103 } | 
| bsw/jbe@19 | 104 var url; | 
| bsw/jbe@19 | 105 if (typeof(url_or_form) == "object") { | 
| bsw/jbe@19 | 106 // form element given | 
| bsw/jbe@19 | 107 var form = url_or_form; | 
| bsw/jbe@19 | 108 url = partialload_addFormDataToUrl(form.action, urlParams); | 
| bsw/jbe@19 | 109 var dataFromForm = partialload_encodeFormData( | 
| bsw/jbe@19 | 110 partialload_getFormKeyValuePairs(form) | 
| bsw/jbe@19 | 111 ); | 
| bsw/jbe@19 | 112 if (form.method != null && form.method.search(/^POST$/i) >= 0) { | 
| bsw/jbe@19 | 113 method = "POST"; | 
| bsw/jbe@19 | 114 data = partialload_mergeEncodedFormData(data, dataFromForm); | 
| bsw/jbe@19 | 115 } else { | 
| bsw/jbe@19 | 116 method = (postParams == NULL) ? "GET" : "POST"; | 
| bsw/jbe@19 | 117 url = partialload_addFormDataToUrl(url, dataFromForm); | 
| bsw/jbe@19 | 118 } | 
| bsw/jbe@19 | 119 } else { | 
| bsw/jbe@19 | 120 // URL given | 
| bsw/jbe@19 | 121 url = partialload_addFormDataToUrl(url_or_form, urlParams); | 
| bsw/jbe@19 | 122 if (postParams == null) { | 
| bsw/jbe@19 | 123 method = "GET"; | 
| bsw/jbe@19 | 124 } else { | 
| bsw/jbe@19 | 125 method = "POST"; | 
| bsw/jbe@19 | 126 if (typeof(postParams) == "string") { | 
| bsw/jbe@19 | 127 data = postParams; | 
| bsw/jbe@19 | 128 } else { | 
| bsw/jbe@19 | 129 data = partialload_encodeFormData(postParams); | 
| bsw/jbe@19 | 130 } | 
| bsw/jbe@19 | 131 } | 
| bsw/jbe@19 | 132 } | 
| bsw/jbe@19 | 133 partialload_queue[partialload_queueWPos++] = { | 
| bsw/jbe@19 | 134 method: method, | 
| bsw/jbe@19 | 135 url: url, | 
| bsw/jbe@19 | 136 data: data, | 
| bsw/jbe@19 | 137 successHandler: successHandler, | 
| bsw/jbe@19 | 138 failureHandler: failureHandler | 
| bsw/jbe@19 | 139 }; | 
| bsw/jbe@19 | 140 if (partialload_queueRPos == 0) { | 
| bsw/jbe@19 | 141 partialload_startNextRequest(); | 
| bsw/jbe@19 | 142 } | 
| bsw/jbe@19 | 143 } | 
| bsw/jbe@19 | 144 | 
| bsw/jbe@19 | 145 function setHtmlContent(node, htmlWithScripts) { | 
| bsw/jbe@19 | 146 var uniquePrefix = "placeholder" + Math.floor(Math.random()*10e16) + "_"; | 
| bsw/jbe@19 | 147 var i = 0; | 
| bsw/jbe@19 | 148 var scripts = []; | 
| bsw/jbe@19 | 149 var htmlWithPlaceholders = ""; | 
| bsw/jbe@19 | 150 // NOTE: This function can not handle CDATA blocks at random positions. | 
| bsw/jbe@19 | 151 htmlWithPlaceholders = htmlWithScripts.replace( | 
| bsw/jbe@19 | 152 /<script[^>]*>(.*?)<\/script>/ig, | 
| bsw/jbe@19 | 153 function(all, inside) { | 
| bsw/jbe@19 | 154 scripts[i] = inside; | 
| bsw/jbe@19 | 155 var placeholder = '<span id="' + uniquePrefix + i + '"></span>'; | 
| bsw/jbe@19 | 156 i++; | 
| bsw/jbe@19 | 157 return placeholder; | 
| bsw/jbe@19 | 158 } | 
| bsw/jbe@19 | 159 ) | 
| bsw/jbe@19 | 160 node.innerHTML = htmlWithPlaceholders; | 
| bsw/jbe@19 | 161 var documentWriteBackup = document.write; | 
| bsw/jbe@19 | 162 var documentWritelnBackup = document.writeln; | 
| bsw/jbe@19 | 163 var output; | 
| bsw/jbe@19 | 164 document.write = function(str) { output += str; } | 
| bsw/jbe@19 | 165 document.writeln = function(str) { output += str + "\n"; } | 
| bsw/jbe@19 | 166 for (i=0; i<scripts.length; i++) { | 
| bsw/jbe@19 | 167 var placeholderNode = document.getElementById(uniquePrefix + i); | 
| bsw/jbe@19 | 168 output = ""; | 
| bsw/jbe@19 | 169 eval(scripts[i]); | 
| bsw/jbe@19 | 170 if (output != "") { | 
| bsw/jbe@19 | 171 placeholderNode.innerHTML = output; | 
| bsw/jbe@19 | 172 while (placeholderNode.childNodes.length > 0) { | 
| bsw/jbe@19 | 173 var childNode = placeholderNode.childNodes[0]; | 
| bsw/jbe@19 | 174 placeholderNode.removeChild(childNode); | 
| bsw/jbe@19 | 175 placeholderNode.parentNode.insertBefore(childNode, placeholderNode); | 
| bsw/jbe@19 | 176 } | 
| bsw/jbe@19 | 177 } | 
| bsw/jbe@19 | 178 placeholderNode.parentNode.removeChild(placeholderNode); | 
| bsw/jbe@19 | 179 } | 
| bsw/jbe@19 | 180 document.write = documentWriteBackup; | 
| bsw/jbe@19 | 181 document.writeln = documentWritelnBackup; | 
| bsw/jbe@19 | 182 } | 
| bsw/jbe@19 | 183 | 
| bsw/jbe@19 | 184 function partialLoad( | 
| bsw/jbe@19 | 185 node, | 
| bsw/jbe@19 | 186 tempLoadingContent, | 
| bsw/jbe@19 | 187 failureContent, | 
| bsw/jbe@19 | 188 url_or_form, | 
| bsw/jbe@19 | 189 urlParams, | 
| bsw/jbe@19 | 190 postParams, | 
| bsw/jbe@19 | 191 successHandler, | 
| bsw/jbe@19 | 192 failureHandler | 
| bsw/jbe@19 | 193 ) { | 
| bsw/jbe@19 | 194 if (typeof(node) == "string") node = document.getElementById(node); | 
| bsw/jbe@19 | 195 if (tempLoadingContent != null) setHtmlContent(node, tempLoadingContent); | 
| bsw/jbe@19 | 196 queuedHttpRequest( | 
| bsw/jbe@19 | 197 url_or_form, | 
| bsw/jbe@19 | 198 urlParams, | 
| bsw/jbe@19 | 199 postParams, | 
| bsw/jbe@19 | 200 function(response) { | 
| bsw/jbe@19 | 201 setHtmlContent(node, response); | 
| bsw/jbe@19 | 202 if (successHandler != null) successHandler(); | 
| bsw/jbe@19 | 203 }, | 
| bsw/jbe@19 | 204 function() { | 
| bsw/jbe@19 | 205 if (failureContent != null) setHtmlContent(node, failureContent); | 
| bsw/jbe@19 | 206 if (failureHandler != null) failureHandler(); | 
| bsw/jbe@19 | 207 } | 
| bsw/jbe@19 | 208 ); | 
| bsw/jbe@19 | 209 } | 
| bsw/jbe@19 | 210 | 
| bsw/jbe@19 | 211 function partialMultiLoad( | 
| bsw/jbe@19 | 212 mapping, | 
| bsw/jbe@19 | 213 tempLoadingContents, | 
| bsw/jbe@19 | 214 failureContents, | 
| bsw/jbe@19 | 215 url_or_form, | 
| bsw/jbe@19 | 216 urlParams, | 
| bsw/jbe@19 | 217 postParams, | 
| bsw/jbe@19 | 218 successHandler, | 
| bsw/jbe@19 | 219 failureHandler | 
| bsw/jbe@19 | 220 ) { | 
| bsw/jbe@19 | 221 if (mapping instanceof Array) { | 
| bsw/jbe@19 | 222 var mappingHash = {} | 
| bsw/jbe@19 | 223 for (var i=0; i<mapping.length; i++) { | 
| bsw/jbe@19 | 224 mappingHash[mapping[i]] = mapping[i]; | 
| bsw/jbe@19 | 225 } | 
| bsw/jbe@19 | 226 mapping = mappingHash; | 
| bsw/jbe@19 | 227 } | 
| bsw/jbe@19 | 228 if (typeof(tempLoadingContents) == "string") { | 
| bsw/jbe@19 | 229 for (var key in mapping) { | 
| bsw/jbe@19 | 230 var node = key; | 
| bsw/jbe@19 | 231 if (typeof(node) == "string") node = document.getElementById(node); | 
| bsw/jbe@19 | 232 setHtmlContent(node, tempLoadingContents); | 
| bsw/jbe@19 | 233 } | 
| bsw/jbe@19 | 234 } else if (tempLoadingContents != null) { | 
| bsw/jbe@19 | 235 for (var key in tempLoadingContents) { | 
| bsw/jbe@19 | 236 var node = key; | 
| bsw/jbe@19 | 237 if (typeof(node) == "string") node = document.getElementById(node); | 
| bsw/jbe@19 | 238 setHtmlContent(node, tempLoadingContents[key]); | 
| bsw/jbe@19 | 239 } | 
| bsw/jbe@19 | 240 } | 
| bsw/jbe@19 | 241 queuedHttpRequest( | 
| bsw/jbe@19 | 242 url_or_form, | 
| bsw/jbe@19 | 243 urlParams, | 
| bsw/jbe@19 | 244 postParams, | 
| bsw/jbe@19 | 245 function(response) { | 
| bsw/jbe@19 | 246 var data = eval("(" + response + ")"); | 
| bsw/jbe@19 | 247 for (var key in mapping) { | 
| bsw/jbe@19 | 248 var node = key; | 
| bsw/jbe@19 | 249 if (typeof(node) == "string") node = document.getElementById(node); | 
| bsw/jbe@19 | 250 setHtmlContent(node, data[mapping[key]]); | 
| bsw/jbe@19 | 251 } | 
| bsw/jbe@19 | 252 if (successHandler != null) successHandler(); | 
| bsw/jbe@19 | 253 }, | 
| bsw/jbe@19 | 254 function() { | 
| bsw/jbe@19 | 255 if (typeof(failureContents) == "string") { | 
| bsw/jbe@19 | 256 for (var key in mapping) { | 
| bsw/jbe@19 | 257 var node = key; | 
| bsw/jbe@19 | 258 if (typeof(node) == "string") node = document.getElementById(node); | 
| bsw/jbe@19 | 259 setHtmlContent(node, failureContents); | 
| bsw/jbe@19 | 260 } | 
| bsw/jbe@19 | 261 } else if (failureContents != null) { | 
| bsw/jbe@19 | 262 for (var key in failureContents) { | 
| bsw/jbe@19 | 263 var node = key; | 
| bsw/jbe@19 | 264 if (typeof(node) == "string") node = document.getElementById(node); | 
| bsw/jbe@19 | 265 setHtmlContent(node, failureContents[key]); | 
| bsw/jbe@19 | 266 } | 
| bsw/jbe@19 | 267 } | 
| bsw/jbe@19 | 268 if (failureHandler != null) failureHandler(); | 
| bsw/jbe@19 | 269 } | 
| bsw/jbe@19 | 270 ); | 
| bsw/jbe@19 | 271 } |