includes/clientside/static/comments.js
changeset 1 fe660c52c48f
child 29 e5484a9e0818
equal deleted inserted replaced
0:902822492a68 1:fe660c52c48f
       
     1 // Comments
       
     2 
       
     3 var comment_template = false;
       
     4 
       
     5 function ajaxComments(parms) {
       
     6   setAjaxLoading();
       
     7   var pid = strToPageID(title);
       
     8   if(!parms)
       
     9   {
       
    10     var parms = {
       
    11       'mode' : 'fetch'
       
    12     };
       
    13   }
       
    14   parms.page_id = pid[0];
       
    15   parms.namespace = pid[1];
       
    16   if(comment_template)
       
    17     parms.have_template = true;
       
    18   parms = ajaxEscape(toJSONString(parms));
       
    19   ajaxPost(stdAjaxPrefix+'&_mode=comments', 'data=' + parms, function() {
       
    20     if(ajax.readyState == 4) {
       
    21       unsetAjaxLoading();
       
    22       selectButtonMajor('discussion');
       
    23       unselectAllButtonsMinor();
       
    24       // IE compatibility - doing ajax.responseText.substr() doesn't work
       
    25       var rsptxt = ajax.responseText + '';
       
    26       if ( rsptxt.substr(0, 1) != '{' )
       
    27       {
       
    28         document.getElementById('ajaxEditContainer').innerHTML = '<p>Comment system Javascript runtime: invalid JSON response from server, response text:</p><pre>' + ajax.responseText + '</pre>';
       
    29         return false;
       
    30       }
       
    31       var response = parseJSON(ajax.responseText);
       
    32       switch(response.mode)
       
    33       {
       
    34         case 'fetch':
       
    35           document.getElementById('ajaxEditContainer').innerHTML = 'Rendering response...';
       
    36           if(response.template)
       
    37             comment_template = response.template;
       
    38           setAjaxLoading();
       
    39           renderComments(response);
       
    40           unsetAjaxLoading();
       
    41           break;
       
    42         case 'redraw':
       
    43           redrawComment(response);
       
    44           break;
       
    45         case 'annihilate':
       
    46           annihiliateComment(response.id);
       
    47           break;
       
    48         case 'materialize':
       
    49           alert('Your comment has been posted. If it does not appear right away, it is probably awaiting approval.');
       
    50           hideCommentForm();
       
    51           materializeComment(response);
       
    52           break;
       
    53         case 'error':
       
    54           alert(response.error);
       
    55           break;
       
    56         default:
       
    57           alert(ajax.responseText);
       
    58           break;
       
    59       }
       
    60     }
       
    61   });
       
    62 }
       
    63 
       
    64 function renderComments(data)
       
    65 {
       
    66   
       
    67   var html = '';
       
    68   
       
    69   // Header
       
    70   
       
    71     html += '<h3>Article Comments</h3>';
       
    72     
       
    73     var ns = ( strToPageID(title)[1]=='Article' ) ? 'article' : ( strToPageID(title)[1].toLowerCase() ) + ' page';
       
    74   
       
    75     // Counters
       
    76     if ( data.auth_mod_comments )
       
    77     {
       
    78       var cnt = ( data.auth_mod_comments ) ? data.count_total : data.count_appr;
       
    79       if ( cnt == 0 ) cnt = 'no';
       
    80       var s  = ( cnt == 1 ) ? '' : 's';
       
    81       var is = ( cnt == 1 ) ? 'is' : 'are';
       
    82       html += "<p id=\"comment_status\">There "+is+" " + cnt + " comment"+s+" on this "+ns+".";
       
    83       if ( data.count_unappr > 0 )
       
    84       {
       
    85         html += ' <span style="color: #D84308">' + data.count_unappr + ' of those are unapproved.</span>';
       
    86       }
       
    87       html += '</p>';
       
    88     }
       
    89     else
       
    90     {
       
    91       var cnt = data.count_appr;
       
    92       if ( cnt == 0 ) cnt = 'no';
       
    93       var s  = ( cnt == 1 ) ? '' : 's';
       
    94       var is = ( cnt == 1 ) ? 'is' : 'are';
       
    95       html += "<p id=\"comment_status\">There "+is+" " + cnt + " comment"+s+" on this "+ns+".";
       
    96       if ( data.count_unappr > 0 )
       
    97       {
       
    98         var s  = ( data.count_unappr == 1 ) ? '' : 's';
       
    99         var is = ( data.count_unappr == 1 ) ? 'is' : 'are';
       
   100         html += ' However, there '+is+' '+data.count_unappr+' additional comment'+s+' awaiting approval.';
       
   101       }
       
   102       html += '</p>';
       
   103     }
       
   104     
       
   105   // Comment display
       
   106   
       
   107   if ( data.count_total > 0 )
       
   108   {
       
   109     var parser = new templateParser(comment_template);
       
   110     for ( var i = 0; i < data.comments.length; i++ )
       
   111     {
       
   112       var tplvars = new Object();
       
   113       
       
   114       if ( data.comments[i].approved != '1' && !data.auth_mod_comments )
       
   115         continue;
       
   116       
       
   117       tplvars.ID = i;
       
   118       tplvars.DATETIME = data.comments[i].time;
       
   119       tplvars.SUBJECT = data.comments[i].subject;
       
   120       tplvars.DATA = data.comments[i].comment_data;
       
   121       tplvars.SIGNATURE = data.comments[i].signature;
       
   122       
       
   123       if ( data.comments[i].approved != '1' )
       
   124         tplvars.SUBJECT += ' <span style="color: #D84308">(Unapproved)</span>';
       
   125       
       
   126       // Name
       
   127       tplvars.NAME = data.comments[i].name;
       
   128       if ( data.comments[i].user_id > 1 )
       
   129         tplvars.NAME = '<a href="' + makeUrlNS('User', data.comments[i].name) + '">' + data.comments[i].name + '</a>';
       
   130       
       
   131       // User level
       
   132       tplvars.USER_LEVEL = 'Guest';
       
   133       if ( data.comments[i].user_level >= data.user_level.member ) tplvars.USER_LEVEL = 'Member';
       
   134       if ( data.comments[i].user_level >= data.user_level.mod ) tplvars.USER_LEVEL = 'Moderator';
       
   135       if ( data.comments[i].user_level >= data.user_level.admin ) tplvars.USER_LEVEL = 'Administrator';
       
   136       
       
   137       // Send PM link
       
   138       tplvars.SEND_PM_LINK=(data.comments[i].user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/Compose/To/' + ( data.comments[i].name.replace(/ /g, '_') )) +'">Send private message</a><br />':'';
       
   139       
       
   140       // Add buddy link
       
   141       tplvars.ADD_BUDDY_LINK=(data.comments[i].user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' + ( data.comments[i].name.replace(/ /g, '_') )) +'">Add to buddy list</a><br />':'';
       
   142       
       
   143       // Edit link
       
   144       tplvars.EDIT_LINK='<a href="#edit_'+i+'" onclick="editComment(\''+i+'\', this); return false;" id="cmteditlink_'+i+'">edit</a>';
       
   145       
       
   146       // Delete link
       
   147       tplvars.DELETE_LINK='<a href="#delete_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">delete</a>';
       
   148       
       
   149       // Moderation: (Un)approve link
       
   150       var appr = ( data.comments[i].approved == 1 ) ? 'Unapprove' : 'Approve';
       
   151       tplvars.MOD_APPROVE_LINK='<a href="#approve_'+i+'" id="comment_approve_'+i+'" onclick="approveComment(\''+i+'\'); return false;">'+appr+'</a>';
       
   152       
       
   153       // Moderation: Delete post link
       
   154       tplvars.MOD_DELETE_LINK='<a href="#mod_del_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">Delete</a>';
       
   155       
       
   156       var tplbool = new Object();
       
   157       
       
   158       tplbool.signature = ( data.comments[i].signature == '' ) ? false : true;
       
   159       tplbool.can_edit = ( data.auth_edit_comments && ( ( data.comments[i].user_id == data.user_id && data.logged_in ) || data.auth_mod_comments ) );
       
   160       tplbool.auth_mod = data.auth_mod_comments;
       
   161       
       
   162       parser.assign_vars(tplvars);
       
   163       parser.assign_bool(tplbool);
       
   164       
       
   165       html += '<div id="comment_holder_' + i + '"><input type="hidden" value="'+data.comments[i].comment_id+'" /><input type="hidden" id="comment_source_'+i+'" />' + parser.run() + '</div>';
       
   166     }
       
   167   }
       
   168   
       
   169   // Posting form
       
   170   
       
   171     html += '<h3>Got something to say?</h3>';
       
   172     html += '<p>If you have comments or suggestions on this article, you can shout it out here.';
       
   173     if ( data.approval_needed )
       
   174       html+=' Before your post will be visible to the public, a moderator will have to approve it.';
       
   175     html += ' <a id="leave_comment_button" href="#" onclick="displayCommentForm(); return false;">Leave a comment...</a></p>';
       
   176     html += '<div id="comment_form" style="display: none;">';
       
   177     html += '  <table border="0">';
       
   178     html += '    <tr><td>Your name/screen name:</td><td>';
       
   179     if ( data.user_id > 1 ) html += data.username + '<input id="commentform_name" type="hidden" value="'+data.username+'" size="40" />';
       
   180     else html += '<input id="commentform_name" type="text" size="40" />';
       
   181     html += '    </td></tr>';
       
   182     html += '    <tr><td>Comment subject:</td><td><input id="commentform_subject" type="text" size="40" /></td></tr>';
       
   183     html += '    <tr><td>Comment:</td><td><textarea id="commentform_message" rows="15" cols="50"></textarea></td></tr>';
       
   184     if ( !data.logged_in && data.guest_posting == '1' )
       
   185     {
       
   186       html += '  <tr><td>Visual confirmation:<br /><small>Please enter the confirmation code seen in the image on the right into the box. If you cannot read the code, please click on the image to generate a new one. This helps to prevent automated bot posting.</small></td><td>';
       
   187       html += '  <img alt="CAPTCHA image" src="'+makeUrlNS('Special', 'Captcha/' + data.captcha)+'" onclick="this.src=\''+makeUrlNS('Special', 'Captcha/' + data.captcha)+'/\'+Math.floor(Math.random()*10000000);" style="cursor: pointer;" /><br />';
       
   188       html += '  Confirmation code: <input type="text" size="8" id="commentform_captcha" />';
       
   189       html += '  <!-- This input is used to track the ID of the CAPTCHA image --> <input type="hidden" id="commentform_captcha_id" value="'+data.captcha+'" />';
       
   190       html += '  </td></tr>';
       
   191     }
       
   192     html += '    <tr><td colspan="2" style="text-align: center;"><input type="button" onclick="submitComment();" value="Submit comment" /></td></tr>';
       
   193     html += '  </table>';
       
   194     html += '</div>';
       
   195     
       
   196   document.getElementById('ajaxEditContainer').innerHTML = html;
       
   197   
       
   198   for ( i = 0; i < data.comments.length; i++ )
       
   199   {
       
   200     document.getElementById('comment_source_'+i).value = data.comments[i].comment_source;
       
   201   }
       
   202   
       
   203 }
       
   204 
       
   205 function displayCommentForm()
       
   206 {
       
   207   document.getElementById('leave_comment_button').style.display = 'none';
       
   208   document.getElementById('comment_form').style.display = 'block';
       
   209 }
       
   210 
       
   211 function hideCommentForm()
       
   212 {
       
   213   document.getElementById('leave_comment_button').style.display = 'inline';
       
   214   document.getElementById('comment_form').style.display = 'none';
       
   215 }
       
   216 
       
   217 function editComment(id, link)
       
   218 {
       
   219   var ctr = document.getElementById('subject_'+id);
       
   220   var subj = trim(ctr.firstChild.nodeValue); // If there's a span in there that says 'unapproved', this eliminates it
       
   221   ctr.innerHTML = '';
       
   222   var ipt = document.createElement('input');
       
   223   ipt.id = 'subject_edit_'+id;
       
   224   ipt.value = subj;
       
   225   ctr.appendChild(ipt);
       
   226   
       
   227   var src = document.getElementById('comment_source_'+id).value;
       
   228   var cmt = document.getElementById('comment_'+id);
       
   229   cmt.innerHTML = '';
       
   230   var ta = document.createElement('textarea');
       
   231   ta.rows = '10';
       
   232   ta.cols = '40';
       
   233   ta.value = src;
       
   234   ta.id = 'comment_edit_'+id;
       
   235   cmt.appendChild(ta);
       
   236   
       
   237   link.style.fontWeight = 'bold';
       
   238   link.innerHTML = 'save';
       
   239   link.onclick = function() { var id = this.id.substr(this.id.indexOf('_')+1); saveComment(id, this); return false; };
       
   240 }
       
   241 
       
   242 function saveComment(id, link)
       
   243 {
       
   244   var data = document.getElementById('comment_edit_'+id).value;
       
   245   var subj = document.getElementById('subject_edit_'+id).value;
       
   246   var div = document.getElementById('comment_holder_'+id);
       
   247   var real_id = div.getElementsByTagName('input')[0]['value'];
       
   248   var req = {
       
   249     'mode' : 'edit',
       
   250     'id'   : real_id,
       
   251     'local_id' : id,
       
   252     'data' : data,
       
   253     'subj' : subj
       
   254   };
       
   255   link.style.fontWeight = 'normal';
       
   256   link.innerHTML = 'edit';
       
   257   link.onclick = function() { var id = this.id.substr(this.id.indexOf('_')+1); editComment(id, this); return false; };
       
   258   ajaxComments(req);
       
   259 }
       
   260 
       
   261 function deleteComment(id)
       
   262 {
       
   263   //var c = confirm('Do you really want to delete this comment?');
       
   264   //if(!c);
       
   265   //  return false;
       
   266   var div = document.getElementById('comment_holder_'+id);
       
   267   var real_id = div.getElementsByTagName('input')[0]['value'];
       
   268   var req = {
       
   269     'mode' : 'delete',
       
   270     'id'   : real_id,
       
   271     'local_id' : id
       
   272   };
       
   273   ajaxComments(req);
       
   274 }
       
   275 
       
   276 function submitComment()
       
   277 {
       
   278   var name = document.getElementById('commentform_name').value;
       
   279   var subj = document.getElementById('commentform_subject').value;
       
   280   var text = document.getElementById('commentform_message').value;
       
   281   if ( document.getElementById('commentform_captcha') )
       
   282   {
       
   283     var captcha_code = document.getElementById('commentform_captcha').value;
       
   284     var captcha_id   = document.getElementById('commentform_captcha_id').value;
       
   285   }
       
   286   else
       
   287   {
       
   288     var captcha_code = '';
       
   289     var captcha_id   = '';
       
   290   }
       
   291   var req = {
       
   292     'mode' : 'submit',
       
   293     'name' : name,
       
   294     'subj' : subj,
       
   295     'text' : text,
       
   296     'captcha_code' : captcha_code,
       
   297     'captcha_id'   : captcha_id
       
   298   };
       
   299   ajaxComments(req);
       
   300 }
       
   301 
       
   302 function redrawComment(data)
       
   303 {
       
   304   if ( data.subj )
       
   305   {
       
   306     document.getElementById('subject_' + data.id).innerHTML = data.subj;
       
   307   }
       
   308   if ( data.approved && data.approved != '1' )
       
   309   {
       
   310     document.getElementById('subject_' + data.id).innerHTML += ' <span style="color: #D84308">(Unapproved)</span>';
       
   311   }
       
   312   if ( data.approved )
       
   313   {
       
   314     var appr = ( data.approved == '1' ) ? 'Unapprove' : 'Approve';
       
   315     document.getElementById('comment_approve_'+data.id).innerHTML = appr;
       
   316     var p = document.getElementById('comment_status');
       
   317     var count = p.firstChild.nodeValue.split(' ')[2];
       
   318     if ( p.firstChild.nextSibling )
       
   319     {
       
   320       var span = p.firstChild.nextSibling;
       
   321       var is = ( data.approved == '1' ) ? -1 : 1;
       
   322       var n_unapp = parseInt(span.firstChild.nodeValue.split(' ')[0]) + is;
       
   323       n_unapp = n_unapp + '';
       
   324     }
       
   325     else
       
   326     {
       
   327       var span = document.createElement('span');
       
   328       p.innerHTML += ' ';
       
   329       span.innerHTML = ' ';
       
   330       span.style.color = '#D84308';
       
   331       var n_unapp = '1';
       
   332       p.appendChild(span);
       
   333     }
       
   334     span.innerHTML = n_unapp + ' of those are unapproved.';
       
   335     if ( n_unapp == '0' )
       
   336       p.removeChild(span);
       
   337   }
       
   338   if ( data.text )
       
   339   {
       
   340     document.getElementById('comment_' + data.id).innerHTML = data.text;
       
   341   }
       
   342   if ( data.src )
       
   343   {
       
   344     document.getElementById('comment_source_' + data.id).value = data.src;
       
   345   }
       
   346 }
       
   347 
       
   348 function approveComment(id)
       
   349 {
       
   350   var div = document.getElementById('comment_holder_'+id);
       
   351   var real_id = div.getElementsByTagName('input')[0]['value'];
       
   352   var req = {
       
   353     'mode' : 'approve',
       
   354     'id'   : real_id,
       
   355     'local_id' : id
       
   356   };
       
   357   ajaxComments(req);
       
   358 }
       
   359 
       
   360 // Does the actual DOM object removal
       
   361 function annihiliateComment(id) // Did I spell that right?
       
   362 {
       
   363   // Approved?
       
   364   var p = document.getElementById('comment_status');
       
   365   
       
   366   if(document.getElementById('comment_approve_'+id))
       
   367   {
       
   368     var appr = document.getElementById('comment_approve_'+id).firstChild.nodeValue;
       
   369     if ( p.firstChild.nextSibling && appr == 'Approve' )
       
   370     {
       
   371       var span = p.firstChild.nextSibling;
       
   372       var t = span.firstChild.nodeValue;
       
   373       var n_unapp = ( parseInt(t.split(' ')[0]) ) - 1;
       
   374       if ( n_unapp == 0 )
       
   375         p.removeChild(span);
       
   376       else
       
   377         span.firstChild.nodeValue = n_unapp + t.substr(t.indexOf(' '));
       
   378     }
       
   379   }
       
   380   
       
   381   var div = document.getElementById('comment_holder_'+id);
       
   382   div.parentNode.removeChild(div);
       
   383   var t = p.firstChild.nodeValue.split(' ');
       
   384   t[2] = ( parseInt(t[2]) - 1 ) + '';
       
   385   delete(t.toJSONString);
       
   386   if ( t[2] == '1' )
       
   387   {
       
   388     t[1] = 'is';
       
   389     t[3] = 'comment';
       
   390   }
       
   391   else
       
   392   {
       
   393     t[1] = 'are';
       
   394     t[3] = 'comments';
       
   395   }
       
   396   t = implode(' ', t);
       
   397   p.firstChild.nodeValue = t;
       
   398 }
       
   399 
       
   400 function materializeComment(data)
       
   401 {
       
   402   // Intelligently get an ID
       
   403 
       
   404   var i = 0;
       
   405   var brother;
       
   406   while ( true )
       
   407   {
       
   408     var x = document.getElementById('comment_holder_'+i);
       
   409     if(!x)
       
   410       break;
       
   411     brother = x;
       
   412     i++;
       
   413   }
       
   414   
       
   415   var parser = new templateParser(comment_template);
       
   416   var tplvars = new Object();
       
   417   
       
   418   if ( data.approved != '1' && !data.auth_mod_comments )
       
   419     return false;
       
   420   
       
   421   tplvars.ID = i;
       
   422   tplvars.DATETIME = data.time;
       
   423   tplvars.SUBJECT = data.subject;
       
   424   tplvars.DATA = data.comment_data;
       
   425   tplvars.SIGNATURE = data.signature;
       
   426   
       
   427   tplvars.NAME = data.name;
       
   428   if ( data.user_id > 1 )
       
   429     tplvars.NAME = '<a href="' + makeUrlNS('User', data.name) + '">' + data.name + '</a>';
       
   430   
       
   431   if ( data.approved != '1' )
       
   432     tplvars.SUBJECT += ' <span style="color: #D84308">(Unapproved)</span>';
       
   433   
       
   434   // User level
       
   435   tplvars.USER_LEVEL = 'Guest';
       
   436   if ( data.user_level >= data.user_level_list.member ) tplvars.USER_LEVEL = 'Member';
       
   437   if ( data.user_level >= data.user_level_list.mod ) tplvars.USER_LEVEL = 'Moderator';
       
   438   if ( data.user_level >= data.user_level_list.admin ) tplvars.USER_LEVEL = 'Administrator';
       
   439   
       
   440   // Send PM link
       
   441   tplvars.SEND_PM_LINK=(data.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/Compose/To/' + ( data.name.replace(/ /g, '_') )) +'">Send private message</a><br />':'';
       
   442   
       
   443   // Add buddy link
       
   444   tplvars.ADD_BUDDY_LINK=(data.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' + ( data.name.replace(/ /g, '_') )) +'">Add to buddy list</a><br />':'';
       
   445   
       
   446   // Edit link
       
   447   tplvars.EDIT_LINK='<a href="#edit_'+i+'" onclick="editComment(\''+i+'\', this); return false;" id="cmteditlink_'+i+'">edit</a>';
       
   448   
       
   449   // Delete link
       
   450   tplvars.DELETE_LINK='<a href="#delete_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">delete</a>';
       
   451   
       
   452   // Moderation: (Un)approve link
       
   453   var appr = ( data.approved == 1 ) ? 'Unapprove' : 'Approve';
       
   454   tplvars.MOD_APPROVE_LINK='<a href="#approve_'+i+'" id="comment_approve_'+i+'" onclick="approveComment(\''+i+'\'); return false;">'+appr+'</a>';
       
   455   
       
   456   // Moderation: Delete post link
       
   457   tplvars.MOD_DELETE_LINK='<a href="#mod_del_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">Delete</a>';
       
   458   
       
   459   var tplbool = new Object();
       
   460   
       
   461   tplbool.signature = ( data.signature == '' ) ? false : true;
       
   462   tplbool.can_edit = ( data.auth_edit_comments && ( ( data.user_id == data.user_id && data.logged_in ) || data.auth_mod_comments ) );
       
   463   tplbool.auth_mod = data.auth_mod_comments;
       
   464   
       
   465   parser.assign_vars(tplvars);
       
   466   parser.assign_bool(tplbool);
       
   467   
       
   468   var div = document.createElement('div');
       
   469   div.id = 'comment_holder_'+i;
       
   470   
       
   471   div.innerHTML = '<input type="hidden" value="'+data.comment_id+'" /><input type="hidden" id="comment_source_'+i+'" />' + parser.run();
       
   472   
       
   473   if ( brother )
       
   474   {
       
   475     brother.parentNode.insertBefore(div, brother.nextSibling);
       
   476   }
       
   477   else
       
   478   {
       
   479     // No comments in ajaxEditContainer, insert it after the header
       
   480     var aec = document.getElementById("ajaxEditContainer");
       
   481     aec.insertBefore(div, aec.firstChild.nextSibling.nextSibling);
       
   482   }
       
   483   
       
   484   document.getElementById('comment_source_'+i).value = data.comment_source;
       
   485   
       
   486   var p = document.getElementById('comment_status');
       
   487   var t = p.firstChild.nodeValue.split(' ');
       
   488   var n = ( isNaN(parseInt(t[2])) ) ? 0 : parseInt(t[2]);
       
   489   t[2] = ( n + 1 ) + '';
       
   490   delete(t.toJSONString);
       
   491   if ( t[2] == '1' )
       
   492   {
       
   493     t[1] = 'is';
       
   494     t[3] = 'comment';
       
   495   }
       
   496   else
       
   497   {
       
   498     t[1] = 'are';
       
   499     t[3] = 'comments';
       
   500   }
       
   501   t = implode(' ', t);
       
   502   p.firstChild.nodeValue = t;
       
   503   
       
   504   if(document.getElementById('comment_approve_'+i))
       
   505   {
       
   506     var appr = document.getElementById('comment_approve_'+i).firstChild.nodeValue;
       
   507     if ( p.firstChild.nextSibling && appr == 'Approve' )
       
   508     {
       
   509       var span = p.firstChild.nextSibling;
       
   510       var t = span.firstChild.nodeValue;
       
   511       var n_unapp = ( parseInt(t.split(' ')[0]) ) - 1;
       
   512       if ( n_unapp == 0 )
       
   513         p.removeChild(span);
       
   514       else
       
   515         span.firstChild.nodeValue = n_unapp + t.substr(t.indexOf(' '));
       
   516     }
       
   517     else if ( appr == 'Approve' && !p.firstChild.nextSibling )
       
   518     {
       
   519       var span = document.createElement('span');
       
   520       p.innerHTML += ' ';
       
   521       span.innerHTML = '1 of those are unapproved.';
       
   522       span.style.color = '#D84308';
       
   523       var n_unapp = '1';
       
   524       p.appendChild(span);
       
   525     }
       
   526   }
       
   527   
       
   528 }
       
   529 
       
   530 function htmlspecialchars(text)
       
   531 {
       
   532   text = text.replace(/</g, '&lt;');
       
   533   text = text.replace(/>/g, '&gt;');
       
   534   return text;
       
   535 }
       
   536 
       
   537 // Equivalent to PHP trim() function
       
   538 function trim(text)
       
   539 {
       
   540   text = text.replace(/^([\s]+)/, '');
       
   541   text = text.replace(/([\s]+)$/, '');
       
   542   return text;
       
   543 }
       
   544 
       
   545 // Equivalent to PHP implode() function
       
   546 function implode(chr, arr)
       
   547 {
       
   548   if ( typeof ( arr.toJSONString ) == 'function' )
       
   549     delete(arr.toJSONString);
       
   550   
       
   551   var ret = '';
       
   552   var c = 0;
       
   553   for ( var i in arr )
       
   554   {
       
   555     if(i=='toJSONString')continue;
       
   556     if ( c > 0 )
       
   557       ret += chr;
       
   558     ret += arr[i];
       
   559     c++;
       
   560   }
       
   561   return ret;
       
   562 }
       
   563 
       
   564 function nl2br(text)
       
   565 {
       
   566   var regex = new RegExp(unescape('%0A'), 'g');
       
   567   return text.replace(regex, '<br />' + unescape('%0A'));
       
   568 }
       
   569