source: main/trunk/greenstone3/web/interfaces/default/js/user_comments.js@ 38237

Last change on this file since 38237 was 38237, checked in by anupama, 9 months ago

The ajax errorResponse function wasn't being called on perl's gsdl_cgi->generate_error(). So a silent die call would happen that wasn't being noticed. The ajax successResponseFunction now checks for the ERROR: message generated by gsdl_CGI generate_error() and the JavaScript error handler is now thus called anyway. But I'm not sure this is the right way to handle it? What about all the other ajax calls where the errorResponse function isn't called?

File size: 27.5 KB
Line 
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)
20gs.usercomments = {};
21
22gs.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());
30gs.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
36gs.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
98gs.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/
190gs.usercomments.insertAfter = function(newNode, existingNode) {
191 existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
192}
193
194gs.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
244gs.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
346gs.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
357gs.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
446gs.usercomments.removedMetadata = function(metapos, modifiedMetapos) {
447 modifiedMetapos.unshift(metapos); // add metapos to start of array
448}
449
450gs.usercomments.removeFailed = function(data, metapos) {
451 var result = (data.responseText) ? data.responseText : data;
452 alert("Remove failed. Got: " + result);
453 failure = true;
454}
455
456gs.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
505gs.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
595gs.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
644gs.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
Note: See TracBrowser for help on using the repository browser.