1 | // http://toddmotto.com/avoiding-anonymous-javascript-functions
|
---|
2 | // https://toddmotto.com/everything-you-wanted-to-know-about-javascript-scope/
|
---|
3 | // pass event to addEventListener onmouseover
|
---|
4 | // http://stackoverflow.com/questions/256754/how-to-pass-arguments-to-addeventlistener-listener-function
|
---|
5 | // http://stackoverflow.com/questions/8714472/cant-pass-event-to-addeventlistener-closure-issue
|
---|
6 | // https://www.sitepoint.com/demystifying-javascript-closures-callbacks-iifes/
|
---|
7 | // http://stackoverflow.com/questions/4869712/new-without-delete-on-same-variable-in-javascript
|
---|
8 | // http://stackoverflow.com/questions/7375120/why-is-arr-faster-than-arr-new-array
|
---|
9 | // http://stackoverflow.com/questions/874205/what-is-the-difference-between-an-array-and-an-object
|
---|
10 | // http://stackoverflow.com/questions/33514915/what-s-the-difference-between-and-while-declaring-a-javascript-array
|
---|
11 | // http://www.nfriedly.com/techblog/2009/06/advanced-javascript-objects-arrays-and-array-like-objects/
|
---|
12 | // stackoverflow.com/questions/36661748/what-is-the-exact-negation-of-ifvariable-in-javascript
|
---|
13 | // http://stackoverflow.com/questions/784929/what-is-the-not-not-operator-in-javascript
|
---|
14 |
|
---|
15 | /***************
|
---|
16 | * USER COMMENTS
|
---|
17 | ****************/
|
---|
18 |
|
---|
19 | // avoid making usercomments js functions global (which attaches them as properties to the window object)
|
---|
20 | gs.usercomments = {};
|
---|
21 |
|
---|
22 | gs.usercomments.defaults = {
|
---|
23 | "metaname_username" : "username",
|
---|
24 | "metaname_usertimestamp": "usertimestamp",
|
---|
25 | "metaname_usercomment" : "usercomment"
|
---|
26 | }
|
---|
27 |
|
---|
28 | // http://stackoverflow.com/questions/6312993/javascript-seconds-to-time-with-format-hhmmss
|
---|
29 | // Call as: alert(timestamp.printTime());
|
---|
30 | gs.usercomments.formatTime = function(timestamp) {
|
---|
31 | var int_timestamp = parseInt(timestamp, 10); // don't forget the second param
|
---|
32 | var date = new Date(int_timestamp);
|
---|
33 | return date.toLocaleDateString() + " " + date.toLocaleTimeString();
|
---|
34 | }
|
---|
35 |
|
---|
36 | gs.usercomments.loadUserComments = function(opt_metaname_username, opt_metaname_usertimestamp, opt_metaname_usercomment) {
|
---|
37 |
|
---|
38 | // don't bother loading comments if we're not on a document page (in which case there's no docid)
|
---|
39 | var doc_id = gs.variables["d"]; ///"_cgiargdJssafe_" in GS2
|
---|
40 |
|
---|
41 | if(!doc_id) {
|
---|
42 | return;
|
---|
43 | }
|
---|
44 |
|
---|
45 | // Don't allow the user to add comments (which calls set-meta-array) until we've finished loading all
|
---|
46 | // user comments (which calls get-meta-array). Since get-meta-array and set-meta-array are called
|
---|
47 | // asynchronously, this is to help prevent any overlap in these functions' access of meta files in
|
---|
48 | // index|archives|import.
|
---|
49 | // Prevent users from adding comments by disabling the submit button
|
---|
50 | // until existing comments have been retrieved and displayed
|
---|
51 | var submitButton = document.getElementById("usercommentSubmitButton");
|
---|
52 | if(submitButton) { // there'll be no submitButton if the comment form is not displayed (user not logged in)
|
---|
53 | submitButton.disabled = true;
|
---|
54 | }
|
---|
55 |
|
---|
56 | // Since we have a docid, get toplevel section of the docid
|
---|
57 |
|
---|
58 | var period = doc_id.indexOf(".");
|
---|
59 | if(period != -1) {
|
---|
60 | doc_id = doc_id.substring(0, period);
|
---|
61 | }
|
---|
62 |
|
---|
63 | /* The current pattern of use (from usercomments.xsl) is to globally override/redefine
|
---|
64 | the metadata names in gs.usercomments.defaults{ values }. However, anticipating
|
---|
65 | future, more general use, loadUserComments() and addUserComment() have been written
|
---|
66 | with the ability to have optional parameters passed in the supersede the values in
|
---|
67 | gs.usercomments.defaults{} */
|
---|
68 |
|
---|
69 | var username_rec = {
|
---|
70 | metaname: opt_metaname_username || gs.usercomments.defaults.metaname_username, // e.g. "username"
|
---|
71 | metapos: "all"
|
---|
72 | };
|
---|
73 |
|
---|
74 | var timestamp_rec = {
|
---|
75 | metaname: opt_metaname_usertimestamp || gs.usercomments.defaults.metaname_usertimestamp, // e.g. "usertimestamp"
|
---|
76 | metapos: "all"
|
---|
77 | };
|
---|
78 |
|
---|
79 | var comment_rec = {
|
---|
80 | metaname: opt_metaname_usercomment || gs.usercomments.defaults.metaname_usercomment, // e.g. "usercomment"
|
---|
81 | metapos: "all"
|
---|
82 | };
|
---|
83 |
|
---|
84 | var doc_rec = {
|
---|
85 | docid: doc_id,
|
---|
86 | metatable: [username_rec, timestamp_rec, comment_rec]
|
---|
87 | };
|
---|
88 |
|
---|
89 | var docArray = [doc_rec];
|
---|
90 |
|
---|
91 | //var json_result_str = gs.functions.getMetadataArray(gs.variables["c"], gs.variables["site"], docArray, "index");
|
---|
92 |
|
---|
93 | gs.functions.getMetadataArray(gs.variables["c"], gs.variables["site"], docArray, "index",
|
---|
94 | gs.usercomments.loadedUserComments, false); // false for asynchronous
|
---|
95 | }
|
---|
96 |
|
---|
97 |
|
---|
98 | gs.usercomments.loadedUserComments = function(data)
|
---|
99 | {
|
---|
100 | // don't bother displaying comments if we're not on a document page
|
---|
101 | // (in which case there's no usercommentdiv).
|
---|
102 | // This shouldn't happen here, since we only call this from loadUserComments()
|
---|
103 | // and that first checks we're actually on a document page.
|
---|
104 | var usercommentdiv = document.getElementById("usercomments");
|
---|
105 | if(usercommentdiv == undefined || usercommentdiv == null) {
|
---|
106 | return;
|
---|
107 | }
|
---|
108 |
|
---|
109 | // data is xmlHttpRequest Object if gsajaxapi is used for the ajax call.
|
---|
110 | // And data is a string if jQuery AJAX was used.
|
---|
111 | // Using JavaScript's feature sensing to detect which of the two we're dealing with:
|
---|
112 | var json_result_str = (data.responseText) ? data.responseText : data;
|
---|
113 |
|
---|
114 | var result = JSON.parse(json_result_str);
|
---|
115 | // result contains only one docrec (result[0]), since we asked for the usercomments of one docid
|
---|
116 | var metatable = result[0].metatable;
|
---|
117 |
|
---|
118 | var i = 0;
|
---|
119 | var looping = true;
|
---|
120 |
|
---|
121 | var canDeleteComments = gs.variables["userCanDeleteComments"];
|
---|
122 |
|
---|
123 | // if there's at least one existing comment OR if the form is currently being displayed
|
---|
124 | // (regardless of whether previous comments exist), display a heading for the comments section
|
---|
125 | if(metatable[0].metavals[0] != undefined || document.getElementById("usercommentform") != undefined) {
|
---|
126 | var heading=document.createElement("div");
|
---|
127 | var attr=document.createAttribute("class");
|
---|
128 | attr.nodeValue="usercommentheading";
|
---|
129 | heading.setAttributeNode(attr);
|
---|
130 | var txt=document.createTextNode(gs.variables["textusercommentssection"]); ///"_textusercommentssection_" in GS2
|
---|
131 | heading.appendChild(txt);
|
---|
132 | usercommentdiv.appendChild(heading);
|
---|
133 | }
|
---|
134 |
|
---|
135 |
|
---|
136 | // metatable[0] = list of usernames, metatable[1] = list of timestamps, metatable[2] = list of comments
|
---|
137 | // the 3 lists/arrays should be of even length. Assuming this, loop as long as there's another username
|
---|
138 | while(looping) {
|
---|
139 | var metaval_rec = metatable[0].metavals[i];
|
---|
140 | if(metaval_rec == undefined) {
|
---|
141 | looping = false;
|
---|
142 | }
|
---|
143 | else {
|
---|
144 |
|
---|
145 | var username = metaval_rec.metavalue;
|
---|
146 | var timestamp = metatable[1].metavals[i].metavalue;
|
---|
147 | var comment = metatable[2].metavals[i].metavalue;
|
---|
148 |
|
---|
149 | // No need to sort by time, as the meta are already stored sorted
|
---|
150 | // and hence retrieved in the right order by using the i (metapos) counter
|
---|
151 | // If sorting the array of comment records, which would be by timestamp, see
|
---|
152 | // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort
|
---|
153 |
|
---|
154 | // for each usercomment, create a child div with the username, timestamp and comment
|
---|
155 | gs.usercomments.displayInUserCommentList(usercommentdiv, username, timestamp, comment, canDeleteComments, i);
|
---|
156 |
|
---|
157 | i++;
|
---|
158 | }
|
---|
159 | }
|
---|
160 |
|
---|
161 | if(canDeleteComments != 0) {
|
---|
162 | var delButtonDiv = document.createElement("div");
|
---|
163 | delButtonDiv.setAttribute("id", "del-button-div");
|
---|
164 | var delCommentsButton = document.createElement("button");
|
---|
165 | delCommentsButton.innerHTML = "Delete selected";
|
---|
166 | delCommentsButton.setAttribute("id", "del-selected-comments-button");
|
---|
167 | //delCommentsButton.setAttribute("onclick", gs.usercomments.deleteSelectedComments);
|
---|
168 | // alternatively: https://www.w3schools.com/jsref/met_element_addeventlistener.asp
|
---|
169 |
|
---|
170 | delCommentsButton.addEventListener("click", gs.usercomments.removeSelectedComments);
|
---|
171 | // Arduous way: deletes each metadata individually
|
---|
172 | //delCommentsButton.addEventListener("click", gs.usercomments.deleteSelectedComments);
|
---|
173 |
|
---|
174 | delButtonDiv.appendChild(delCommentsButton);
|
---|
175 |
|
---|
176 | var prevNode = document.getElementById("usercomments");
|
---|
177 | gs.usercomments.insertAfter(delButtonDiv, prevNode);
|
---|
178 | }
|
---|
179 |
|
---|
180 | var submitButton = document.getElementById("usercommentSubmitButton");
|
---|
181 | // Now we've finished loading all user comments,
|
---|
182 | // allow the user to add a comment by enabling the submit button again
|
---|
183 | if(submitButton) {
|
---|
184 | submitButton.disabled = false;
|
---|
185 | }
|
---|
186 | }
|
---|
187 |
|
---|
188 |
|
---|
189 | // https://www.javascripttutorial.net/javascript-dom/javascript-insertafter/
|
---|
190 | gs.usercomments.insertAfter = function(newNode, existingNode) {
|
---|
191 | existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
|
---|
192 | }
|
---|
193 |
|
---|
194 | gs.usercomments.displayInUserCommentList = function(usercommentdiv, username, timestamp, comment, canDeleteComments, metapos) {
|
---|
195 |
|
---|
196 | if(metapos == undefined) {
|
---|
197 | metapos = document.querySelectorAll('div[class=usercomment]').length;
|
---|
198 | }
|
---|
199 |
|
---|
200 | var divgroup=document.createElement("div");
|
---|
201 | var attr=document.createAttribute("class");
|
---|
202 | attr.nodeValue="usercomment";
|
---|
203 | divgroup.setAttributeNode(attr);
|
---|
204 |
|
---|
205 | var divuser=document.createElement("div");
|
---|
206 | var divtime=document.createElement("div");
|
---|
207 | var divcomment=document.createElement("div");
|
---|
208 |
|
---|
209 | if(canDeleteComments != 0) {
|
---|
210 | var deleteCheckBox = document.createElement("input");
|
---|
211 | deleteCheckBox.style.cssFloat = "left";
|
---|
212 | deleteCheckBox.setAttribute("type", "checkbox");
|
---|
213 | deleteCheckBox.setAttribute("class", "del-me-comment");
|
---|
214 | deleteCheckBox.setAttribute("data-metapos", metapos);
|
---|
215 | deleteCheckBox.setAttribute("data-username", username);
|
---|
216 | deleteCheckBox.setAttribute("data-timestamp", timestamp);
|
---|
217 | deleteCheckBox.setAttribute("data-comment", comment);
|
---|
218 | divgroup.appendChild(deleteCheckBox);
|
---|
219 | }
|
---|
220 |
|
---|
221 | divgroup.appendChild(divuser);
|
---|
222 | var txt=document.createTextNode(username);
|
---|
223 |
|
---|
224 | divuser.appendChild(txt);
|
---|
225 |
|
---|
226 | divgroup.appendChild(divtime);
|
---|
227 | txt=document.createTextNode(gs.usercomments.formatTime(timestamp)); // format timestamp for date/time display
|
---|
228 | divtime.appendChild(txt);
|
---|
229 |
|
---|
230 | // any quotes and colons in the fields would have been protected for transmitting as JSON
|
---|
231 | // so decode their entity values
|
---|
232 | comment = comment.replace(/"/gmi, '"');
|
---|
233 | comment = comment.replace(/&58;/gmi, ':');
|
---|
234 |
|
---|
235 | divgroup.appendChild(divcomment);
|
---|
236 | txt=document.createTextNode(comment);
|
---|
237 | divcomment.appendChild(txt);
|
---|
238 |
|
---|
239 | usercommentdiv.appendChild(divgroup);
|
---|
240 |
|
---|
241 | }
|
---|
242 |
|
---|
243 | // Uses remove array to remove multiple metadata in one ajax call
|
---|
244 | gs.usercomments.removeSelectedComments = function(eventObject, opt_metaname_username, opt_metaname_usertimestamp, opt_metaname_usercomment)
|
---|
245 | {
|
---|
246 | // https://stackoverflow.com/questions/590018/getting-all-selected-checkboxes-in-an-array
|
---|
247 | // https://stackoverflow.com/questions/6166763/jquery-multiple-checkboxes-array
|
---|
248 |
|
---|
249 | var selectedComments = document.querySelectorAll('input[class=del-me-comment][type=checkbox]:checked');
|
---|
250 |
|
---|
251 | if(selectedComments.length > 0) {
|
---|
252 |
|
---|
253 | // Don't allow the user to submit further comments or delete comments
|
---|
254 | // until the metadata has been updated
|
---|
255 | document.getElementById("usercommentSubmitButton").disabled = true;
|
---|
256 | var delCommentsButton = document.getElementById("delCommentsButton");
|
---|
257 | if(delCommentsButton != undefined) {// should be defined when in this function
|
---|
258 | delCommentsButton.disabled = true;
|
---|
259 | }
|
---|
260 |
|
---|
261 | // User comment meta are at topmost section of the document.
|
---|
262 | // So only get the docId up to any period mark:
|
---|
263 | var _docid = document.AddUserCommentForm.d.value;
|
---|
264 | var period = _docid.indexOf(".");
|
---|
265 | if(period != -1) {
|
---|
266 | _docid = _docid.substring(0, period);
|
---|
267 | }
|
---|
268 |
|
---|
269 | //document.querySelectorAll('input[class=del-me-comment][type=checkbox]:checked').forEach(elem => console.log(elem.getAttribute('data-username')));
|
---|
270 |
|
---|
271 | var metadataPositions = [];
|
---|
272 | var failure = false;
|
---|
273 |
|
---|
274 | // Need to have metapositions in descending order for remove_metadata_array to work
|
---|
275 | // Start deleting from end of metadata list, so we don't have to recalculate metapos each time
|
---|
276 | /*
|
---|
277 | for (var i = 0; i < selectedComments.length; i++) {
|
---|
278 | var metapos = selectedComments[i].getAttribute("data-metapos");
|
---|
279 | metadataPositions.unshift(metapos); // add metapos to start of array
|
---|
280 | }*/
|
---|
281 |
|
---|
282 | for (var i = selectedComments.length - 1; i >= 0; i--) {
|
---|
283 | var metapos = selectedComments[i].getAttribute("data-metapos");
|
---|
284 | metadataPositions.push(metapos); // add next lowest metapos to end of array
|
---|
285 | }
|
---|
286 | }
|
---|
287 |
|
---|
288 | // now we have all the metapositions we need to delete
|
---|
289 | // create a JSON of indicating the username, timestamp and comment metadata need to be deleted
|
---|
290 | // at all those metapositions
|
---|
291 |
|
---|
292 | // removeMetadataArray escapes the entire JSON, so we don't individually escape the fields here
|
---|
293 |
|
---|
294 | // For creating the JSON object that gets turned into a string, see
|
---|
295 | // http://msdn.microsoft.com/en-us/library/ie/cc836459%28v=vs.94%29.aspx
|
---|
296 | // http://jsfiddle.net/qmacro/W54hy/
|
---|
297 |
|
---|
298 | var username_rec = {
|
---|
299 | metaname: opt_metaname_username || gs.usercomments.defaults.metaname_username, // e.g. "username"
|
---|
300 | metapositions: metadataPositions
|
---|
301 | };
|
---|
302 |
|
---|
303 | var timestamp_rec = {
|
---|
304 | metaname: opt_metaname_usertimestamp || gs.usercomments.defaults.metaname_usertimestamp, // e.g. "usertimestamp"
|
---|
305 | metapositions: metadataPositions
|
---|
306 | };
|
---|
307 |
|
---|
308 | var comment_rec = {
|
---|
309 | metaname: opt_metaname_usercomment || gs.usercomments.defaults.metaname_usercomment, // e.g. "usercomment"
|
---|
310 | metapositions: metadataPositions
|
---|
311 | };
|
---|
312 |
|
---|
313 | var doc_rec = {
|
---|
314 | docid: _docid,
|
---|
315 | metatable: [username_rec, timestamp_rec, comment_rec],
|
---|
316 | //metamode: "accumulate"
|
---|
317 | };
|
---|
318 |
|
---|
319 | var docArray = [doc_rec];
|
---|
320 |
|
---|
321 | // Don't allow the user to submit further comments or delete any
|
---|
322 | // until the metadata has been updated
|
---|
323 | document.getElementById("usercommentSubmitButton").disabled = true;
|
---|
324 | var delCommentsButton = document.getElementById("delCommentsButton");
|
---|
325 | if(delCommentsButton != undefined) {
|
---|
326 | delCommentsButton.disabled = true;
|
---|
327 | }
|
---|
328 |
|
---|
329 | console.log("About to remove usercomments at metapositions: " + metadataPositions);
|
---|
330 |
|
---|
331 | gs.functions.removeMetadataArray(
|
---|
332 | gs.variables["c"],
|
---|
333 | gs.variables["site"],
|
---|
334 | docArray,
|
---|
335 | null, //metamode
|
---|
336 | "import|archives|index",
|
---|
337 | function(ajaxResult) { return gs.usercomments.doneRemovingMetadata(ajaxResult, metadataPositions); },
|
---|
338 | false, // false for asynchronous, see comment in gs.usercomments.addUserComment()
|
---|
339 | function(ajaxError) { return gs.usercomments.removeMultipleCommentsFailed(ajaxError); }
|
---|
340 | );
|
---|
341 |
|
---|
342 | //console.log("metapositions to remove: " + metadataPositions);
|
---|
343 | //console.log("docArray:\n" + JSON.stringify(docArray));
|
---|
344 | }
|
---|
345 |
|
---|
346 | gs.usercomments.removeMultipleCommentsFailed = function(data) {
|
---|
347 | var result = (data.responseText) ? data.responseText : data;
|
---|
348 | alert("Remove failed. Got: " + result);
|
---|
349 | failure = true;
|
---|
350 |
|
---|
351 | // TODO, force a page reload so that the usercomments' state somewhat better reflects what's in DBs
|
---|
352 | location.reload();
|
---|
353 | }
|
---|
354 |
|
---|
355 |
|
---|
356 | // Removes single metadata at a time
|
---|
357 | gs.usercomments.deleteSelectedComments = function() {
|
---|
358 | // https://stackoverflow.com/questions/590018/getting-all-selected-checkboxes-in-an-array
|
---|
359 | // https://stackoverflow.com/questions/6166763/jquery-multiple-checkboxes-array
|
---|
360 |
|
---|
361 | var selectedComments = document.querySelectorAll('input[class=del-me-comment][type=checkbox]:checked');
|
---|
362 |
|
---|
363 | if(selectedComments.length > 0) {
|
---|
364 |
|
---|
365 | // Don't allow the user to submit further comments or delete comments
|
---|
366 | // until the metadata has been updated
|
---|
367 | document.getElementById("usercommentSubmitButton").disabled = true;
|
---|
368 | var delCommentsButton = document.getElementById("delCommentsButton");
|
---|
369 | if(delCommentsButton != undefined) {// should be defined when in this function
|
---|
370 | delCommentsButton.disabled = true;
|
---|
371 | }
|
---|
372 |
|
---|
373 | // User comment meta are at topmost section of the document.
|
---|
374 | // So only get the docId up to any period mark:
|
---|
375 | var _docid = document.AddUserCommentForm.d.value;
|
---|
376 | var period = _docid.indexOf(".");
|
---|
377 | if(period != -1) {
|
---|
378 | _docid = _docid.substring(0, period);
|
---|
379 | }
|
---|
380 |
|
---|
381 | //document.querySelectorAll('input[class=del-me-comment][type=checkbox]:checked').forEach(elem => console.log(elem.getAttribute('data-username')));
|
---|
382 |
|
---|
383 | var modifiedMetapos = [];
|
---|
384 | var failure = false;
|
---|
385 |
|
---|
386 | // start deleting from end of metadata list, so we don't have to recalculate metapos each time
|
---|
387 | for (var i = selectedComments.length-1; i >= 0; i--) {
|
---|
388 |
|
---|
389 | var metapos = selectedComments[i].getAttribute("data-metapos");
|
---|
390 | //var username = selectedComments[i].getAttribute("data-username");
|
---|
391 | //var timestamp = selectedComments[i].getAttribute("data-timestamp");
|
---|
392 | //var comment = selectedComments[i].getAttribute("data-comment");
|
---|
393 | //console.log("metapos: " + metapos);
|
---|
394 |
|
---|
395 | // There is no remove array version yet!!!
|
---|
396 |
|
---|
397 | //var result = gs.functions.removeMetadataAtPos(gs.variables["c"], gs.variables["site"], docArray, "accumulate", "import|archives|index");
|
---|
398 | gs.functions.removeMetadataAtPos(gs.variables["c"],
|
---|
399 | gs.variables["site"],
|
---|
400 | _docid,
|
---|
401 | gs.usercomments.defaults.metaname_username,
|
---|
402 | metapos,
|
---|
403 | //"import|archives|index",
|
---|
404 | null, //function(ajaxResult) { alert(ajaxResult); },
|
---|
405 | function(ajaxError) { return gs.usercomments.removeFailed(ajaxError, metapos); },
|
---|
406 | true); // true for synchronous, meaning is opposite to explanation for addUserComment() function below
|
---|
407 |
|
---|
408 | if(failure) {
|
---|
409 | continue;
|
---|
410 | }
|
---|
411 | gs.functions.removeMetadataAtPos(gs.variables["c"],
|
---|
412 | gs.variables["site"],
|
---|
413 | _docid,
|
---|
414 | gs.usercomments.defaults.metaname_usertimestamp,
|
---|
415 | metapos,
|
---|
416 | //"import|archives|index",
|
---|
417 | null, //function(ajaxResult) { alert(ajaxResult); },
|
---|
418 | function(ajaxError) { return gs.usercomments.removeFailed(ajaxError, metapos); },
|
---|
419 | true); // true for synchronous, meaning is opposite to explanation for addUserComment() function below
|
---|
420 |
|
---|
421 | if(failure) {
|
---|
422 | continue;
|
---|
423 | }
|
---|
424 | gs.functions.removeMetadataAtPos(gs.variables["c"],
|
---|
425 | gs.variables["site"],
|
---|
426 | _docid,
|
---|
427 | gs.usercomments.defaults.metaname_usercomment,
|
---|
428 | metapos,
|
---|
429 | //"import|archives|index",
|
---|
430 | null, //function(ajaxResult) { alert(ajaxResult); },
|
---|
431 | function(ajaxError) { return gs.usercomments.removeFailed(ajaxError, metapos); },
|
---|
432 | true); // true for synchronous, meaning is opposite to explanation for addUserComment() function below
|
---|
433 |
|
---|
434 |
|
---|
435 | gs.usercomments.removedMetadata(metapos, modifiedMetapos);
|
---|
436 | failure = false; // reinitialise
|
---|
437 | }
|
---|
438 |
|
---|
439 | //console.log("modifiedMetapos: " + modifiedMetapos);
|
---|
440 |
|
---|
441 | gs.usercomments.doneRemovingMetadata(null, modifiedMetapos);
|
---|
442 | }
|
---|
443 | }
|
---|
444 |
|
---|
445 |
|
---|
446 | gs.usercomments.removedMetadata = function(metapos, modifiedMetapos) {
|
---|
447 | modifiedMetapos.unshift(metapos); // add metapos to start of array
|
---|
448 | }
|
---|
449 |
|
---|
450 | gs.usercomments.removeFailed = function(data, metapos) {
|
---|
451 | var result = (data.responseText) ? data.responseText : data;
|
---|
452 | alert("Remove failed. Got: " + result);
|
---|
453 | failure = true;
|
---|
454 | }
|
---|
455 |
|
---|
456 | gs.usercomments.doneRemovingMetadata = function(data, modifiedMetapos) {
|
---|
457 |
|
---|
458 | // data is xmlHttpRequest Object if gsajaxapi is used for the ajax call.
|
---|
459 | // And data is a string if jQuery AJAX was used.
|
---|
460 | // Using JavaScript's feature sensing to detect which of the two we're dealing with:
|
---|
461 | var result = (data.responseText) ? data.responseText : data;
|
---|
462 |
|
---|
463 | // check for gsdl_cgi->generate_error() result, which ends up in a silent die statement
|
---|
464 | // unless we look for it in the "success" result, in the form of a message starting
|
---|
465 | // with "ERROR:"
|
---|
466 | if(result.indexOf("ERROR: ") !== -1 || result.indexOf("<Error>") !== -1) {
|
---|
467 | gs.usercomments.removeMultipleCommentsFailed(data);
|
---|
468 | return;
|
---|
469 | }
|
---|
470 |
|
---|
471 | //console.log("@@@ Done removing metadata:\n" + result);
|
---|
472 |
|
---|
473 | var userCommentsDiv = document.getElementById("usercomments");
|
---|
474 |
|
---|
475 | // modifiedMetaPos has all the positions for usercomments metadata that need to be removed, in normal (ascending) order
|
---|
476 | // So start at end, removing usercomments with highest metapos
|
---|
477 | for (var i = modifiedMetapos.length-1; i >= 0; i--) {
|
---|
478 | var metapos = modifiedMetapos[i];
|
---|
479 |
|
---|
480 | //console.log("About to remove usercomment at metapos " + metapos);
|
---|
481 |
|
---|
482 | // find the checkbox with data-metapos=metapos and delete its username, timestamp, comment
|
---|
483 | var removeUserCommentForCheckbox = document.querySelector("input[data-metapos=\""+metapos+"\"]");
|
---|
484 | var usercommentDivToRemove = removeUserCommentForCheckbox.parentElement; // get the <div class="usercomment"/> above this checkbox
|
---|
485 | userCommentsDiv.removeChild(usercommentDivToRemove);
|
---|
486 | }
|
---|
487 |
|
---|
488 | // Now re-number the metapos for all the input class=del-me-comment
|
---|
489 | var usercommentCheckboxes = document.querySelectorAll('input[class=del-me-comment][type=checkbox]');
|
---|
490 | for (var i = 0; i < usercommentCheckboxes.length; i++) {
|
---|
491 | usercommentCheckboxes[i].setAttribute("data-metapos", i);
|
---|
492 | }
|
---|
493 |
|
---|
494 | // whether there was an error or not, re-enable the submit button now
|
---|
495 | // that the removeMetada ajax operations have completed.
|
---|
496 | document.getElementById("usercommentSubmitButton").disabled = false;
|
---|
497 | var delCommentsButton = document.getElementById("delCommentsButton");
|
---|
498 | if(delCommentsButton != undefined) {
|
---|
499 | delCommentsButton.disabled = false;
|
---|
500 | }
|
---|
501 |
|
---|
502 | }
|
---|
503 |
|
---|
504 |
|
---|
505 | gs.usercomments.addUserComment = function(_username, _comment, _docid, doc,
|
---|
506 | opt_metaname_username, opt_metaname_usertimestamp, opt_metaname_usercomment) {
|
---|
507 |
|
---|
508 | // don't add empty strings for name/comment
|
---|
509 |
|
---|
510 | // http://stackoverflow.com/questions/498970/how-do-i-trim-a-string-in-javascript
|
---|
511 | //var trimmed_username=_username.replace(/^\s+|\s+$/g, '');
|
---|
512 | var trimmed_comment = _comment.replace(/^\s+|\s+$/g, '');
|
---|
513 |
|
---|
514 | if(!trimmed_comment) {
|
---|
515 | doc.AddUserCommentForm.comment.value = "";
|
---|
516 | //document.AddUserCommentForm.username.value = "";
|
---|
517 | document.getElementById("usercommentfeedback").innerHTML = gs.variables["textisempty"]; ///"_textisempty_" in GS2
|
---|
518 | return;
|
---|
519 | }
|
---|
520 |
|
---|
521 | // Need to the add user comment meta of username, timestamp and comment to the
|
---|
522 | // topmost section of the document. So only get the docId up to any period mark:
|
---|
523 | var period = _docid.indexOf(".");
|
---|
524 | if(period != -1) {
|
---|
525 | _docid = _docid.substring(0, period);
|
---|
526 | }
|
---|
527 |
|
---|
528 |
|
---|
529 | // Want to store username, timestamp and comment in import/metadata.xml, archives/doc.xml
|
---|
530 | // and index/col.gdb.
|
---|
531 |
|
---|
532 | // For getting the current time, see
|
---|
533 | // http://stackoverflow.com/questions/3830244/get-current-date-time-in-seconds
|
---|
534 | var _timestamp = new Date().getTime(); // div by 1000 to get seconds. valueOf() may return string
|
---|
535 |
|
---|
536 | // setMetadataArray escapes the entire JSON, so we don't individually escape the fields here
|
---|
537 | // If we did, and called gsapi.setMetadata or gs.functions (in javascript-global-functions.js) instead,
|
---|
538 | // then resort to escaping first, e.g.
|
---|
539 | // _comment = escape(_comment);
|
---|
540 | // gsapi.setMetadata(_docid, "usercomment", null, _comment, "accumulate", "import|archives|index");
|
---|
541 |
|
---|
542 |
|
---|
543 | // Use the new JSON metatable format to set username, timestamp and comment meta for docid in one go
|
---|
544 |
|
---|
545 | // For creating the JSON object that gets turned into a string, see
|
---|
546 | // http://msdn.microsoft.com/en-us/library/ie/cc836459%28v=vs.94%29.aspx
|
---|
547 | // http://jsfiddle.net/qmacro/W54hy/
|
---|
548 |
|
---|
549 | var username_rec = {
|
---|
550 | metaname: opt_metaname_username || gs.usercomments.defaults.metaname_username, // e.g. "username"
|
---|
551 | metavals: [_username]
|
---|
552 | };
|
---|
553 |
|
---|
554 | var timestamp_rec = {
|
---|
555 | metaname: opt_metaname_usertimestamp || gs.usercomments.defaults.metaname_usertimestamp, // e.g. "usertimestamp"
|
---|
556 | metavals: [_timestamp]
|
---|
557 | };
|
---|
558 |
|
---|
559 | var comment_rec = {
|
---|
560 | metaname: opt_metaname_usercomment || gs.usercomments.defaults.metaname_usercomment, // e.g. "usercomment"
|
---|
561 | metavals: [_comment]
|
---|
562 | };
|
---|
563 |
|
---|
564 | var doc_rec = {
|
---|
565 | docid: _docid,
|
---|
566 | metatable: [username_rec, timestamp_rec, comment_rec],
|
---|
567 | metamode: "accumulate"
|
---|
568 | };
|
---|
569 |
|
---|
570 | var docArray = [doc_rec];
|
---|
571 |
|
---|
572 | // Don't allow the user to submit further comments or delete any
|
---|
573 | // until the metadata has been updated
|
---|
574 | document.getElementById("usercommentSubmitButton").disabled = true;
|
---|
575 | var delCommentsButton = document.getElementById("delCommentsButton");
|
---|
576 | if(delCommentsButton != undefined) {
|
---|
577 | delCommentsButton.disabled = true;
|
---|
578 | }
|
---|
579 |
|
---|
580 | //var result = gs.functions.setMetadataArray(gs.variables["c"], gs.variables["site"], docArray, "accumulate", "import|archives|index");
|
---|
581 | gs.functions.setMetadataArray(gs.variables["c"],
|
---|
582 | gs.variables["site"],
|
---|
583 | docArray, "accumulate",
|
---|
584 | "import|archives|index",
|
---|
585 | function(ajaxResult) { return gs.usercomments.doneUpdatingMetatada(ajaxResult, _username, _timestamp, _comment); },
|
---|
586 | false); // false for asynchronous,
|
---|
587 | // async here is ok since we're disabling the comment submit button, so no further set-meta-array calls
|
---|
588 | // can be made until the ajax call returns and the callback is called which re-enables the submit button
|
---|
589 | // But disabling submit does not protect against concurrent access such as someone else editing the
|
---|
590 | // document (doing set-meta operations, updating archives/index/import) at the same time as someone else
|
---|
591 | // adding user comments (doing set-meta-array, updating archives|index|import).
|
---|
592 |
|
---|
593 | }
|
---|
594 |
|
---|
595 | gs.usercomments.doneUpdatingMetatada = function(data, _username, _timestamp, _comment)
|
---|
596 | {
|
---|
597 | // data is xmlHttpRequest Object if gsajaxapi is used for the ajax call.
|
---|
598 | // And data is a string if jQuery AJAX was used.
|
---|
599 | // Using JavaScript's feature sensing to detect which of the two we're dealing with:
|
---|
600 | var result = (data.responseText) ? data.responseText : data;
|
---|
601 |
|
---|
602 | // clear the comment field as it has now been submitted, but not the username field
|
---|
603 | // as the user is logged in, so they should be able to commit again under their username.
|
---|
604 | document.AddUserCommentForm.comment.value = "";
|
---|
605 |
|
---|
606 | // check for locked collection error
|
---|
607 | var errorIndex = result.indexOf("ERROR");
|
---|
608 | // check for any error discovered on the server side
|
---|
609 | var responseErrorIndex = result.indexOf("<error");
|
---|
610 |
|
---|
611 | if(errorIndex != -1) {
|
---|
612 | var endIndex = result.indexOf("\\n");
|
---|
613 | var error = result.substring(errorIndex,endIndex);
|
---|
614 | errormessage="ERROR: Unable to add comment. " + error;
|
---|
615 | document.getElementById("usercommentfeedback").innerHTML = errormessage;
|
---|
616 | }
|
---|
617 | else if (responseErrorIndex != -1) {
|
---|
618 | var endIndex = result.indexOf("</error>");
|
---|
619 | var startIndex = result.indexOf(">", responseErrorIndex+1);
|
---|
620 | var error = result.substring(startIndex+1,endIndex);
|
---|
621 | errormessage="ERROR: Unable to add comment. " + error;
|
---|
622 | document.getElementById("usercommentfeedback").innerHTML = errormessage;
|
---|
623 | }
|
---|
624 | else { // success!
|
---|
625 | document.getElementById("usercommentfeedback").innerHTML = gs.variables["textcommentsubmitted"]; ///"_textcommentsubmitted_" in GS2
|
---|
626 |
|
---|
627 | // update display of existing user comments to show the newly added comment
|
---|
628 | var usercommentdiv = document.getElementById("usercomments");
|
---|
629 | if(usercommentdiv != undefined) {
|
---|
630 | gs.usercomments.displayInUserCommentList(usercommentdiv, _username, _timestamp, _comment);
|
---|
631 | }
|
---|
632 | }
|
---|
633 |
|
---|
634 | // whether there was an error or not, re-enable the submit button now
|
---|
635 | // that the set-meta-array operation has completed.
|
---|
636 | document.getElementById("usercommentSubmitButton").disabled = false;
|
---|
637 | var delCommentsButton = document.getElementById("delCommentsButton");
|
---|
638 | if(delCommentsButton != undefined) {
|
---|
639 | delCommentsButton.disabled = false;
|
---|
640 | }
|
---|
641 |
|
---|
642 | }
|
---|
643 |
|
---|
644 | gs.usercomments.commentAreaSetup = function() {
|
---|
645 | gs.usercomments.loadUserComments();
|
---|
646 |
|
---|
647 | $("div#commentarea").html('<textarea required="required" name="comment" rows="10" cols="64" placeholder="Add your comment here..."></textarea>');
|
---|
648 |
|
---|
649 | }
|
---|
650 |
|
---|
651 |
|
---|
652 | // "Handlers added via $(document).ready() don't overwrite each other, but rather execute in turn"
|
---|
653 | // as explained at http://stackoverflow.com/questions/15564029/adding-to-window-onload-event
|
---|
654 | // This way we ensure we don't replace any other onLoad() functions, but append the loadUserComments()
|
---|
655 | // function to the existing set of eventhandlers called onDocReady
|
---|
656 | $(document).ready(gs.usercomments.commentAreaSetup);
|
---|
657 |
|
---|