Comments (AJAX): Now paginated server side. Fixes issue 2.
authorDan
Fri, 18 Dec 2009 05:12:02 -0500
changeset 1173 b5b8e7ab0914
parent 1172 db6b116b8ea7
child 1174 def792dd9b1b
Comments (AJAX): Now paginated server side. Fixes issue 2.
includes/clientside/static/comments.js
includes/clientside/static/paginate.js
includes/comment.php
includes/namespaces/default.php
includes/sessions.php
includes/template.php
--- a/includes/clientside/static/comments.js	Fri Dec 18 05:05:01 2009 -0500
+++ b/includes/clientside/static/comments.js	Fri Dec 18 05:12:02 2009 -0500
@@ -5,13 +5,14 @@
 
 window.ajaxComments = function(parms)
 {
-  load_component(['l10n', 'paginate', 'template-compiler', 'toolbar', 'flyin']);
+  load_component(['l10n', 'paginate', 'template-compiler', 'toolbar', 'flyin', 'jquery', 'jquery-ui']);
   setAjaxLoading();
   var pid = strToPageID(title);
   if(!parms)
   {
     var parms = {
-      'mode' : 'fetch'
+      mode: 'fetch',
+      pagenum: 0
     };
   }
   parms.page_id = pid[0];
@@ -35,13 +36,25 @@
       switch(response.mode)
       {
         case 'fetch':
-          document.getElementById('ajaxEditContainer').innerHTML = '<div class="wait-box">Rendering '+response.count_total+' comments...</div>';
           if(response.template)
             comment_template = response.template;
           setAjaxLoading();
           renderComments(response);
           unsetAjaxLoading();
           break;
+        case 'refetch':
+          var html = '';
+          for ( var i = 0; i < response.comments.length; i++ )
+          {
+            html += window._render_comment(response.comments[i], response);
+          }
+          $('#' + response.passback.paginator_id + '_0')
+            .css('height', 'auto')
+            .css('background-color', 'transparent')
+            .css('background-image', 'none')
+            .fadeTo('fast', 100)
+            .html(html);
+          break;
         case 'redraw':
           redrawComment(response);
           break;
@@ -118,7 +131,7 @@
   if ( data.count_total > 0 )
   {
     comment_render_track = 0;
-    var commentpages = new paginator(data.comments, _render_comment, 0, 10, data);
+    var commentpages = new paginator(data.comments, _render_comment, 0, data.per_page, data, Math.ceil(data.count_total / data.per_page), window._comment_page_flip);
     html += commentpages.html;
   }
   
@@ -630,6 +643,36 @@
   }
 }
 
+window._comment_page_flip = function(paginator, page_number)
+{
+  // get ID
+  var random_id = paginator.random_id;
+  // update paginate control
+  paginator.set_page(page_number);
+  $('.' + random_id + '_control').html(paginator._build_control(page_number));
+  paginator.offset = page_number;
+  // set to loading state
+  $('#' + random_id + '_0')
+    .css('height', 500)
+    .html('')
+    .fadeTo("fast", 0.7)
+    .css('background-position', 'center 51px')
+    .css('background-repeat', 'no-repeat')
+    .css('background-color', 'white')
+    .css('background-image', 'url(' + cdnPath + '/images/loading-big.gif' + ')')
+    .animate({ height: 150 }, 500, function()
+      {
+        // load the new comments
+        ajaxComments({
+            mode: 'fetch',
+            pagenum: page_number,
+            passback: {
+              paginator_id: random_id
+            }
+          });
+      });
+}
+
 window.viewCommentIP = function(id, local_id)
 {
   // set "loading" indicator on IP button
--- a/includes/clientside/static/paginate.js	Fri Dec 18 05:05:01 2009 -0500
+++ b/includes/clientside/static/paginate.js	Fri Dec 18 05:12:02 2009 -0500
@@ -11,7 +11,7 @@
  
 var pagin_objects = new Object();
 
-window.paginator = function(data, callback, offset, perpage, passer)
+window.paginator = function(data, callback, offset, perpage, passer, ov_num_pages, ov_flip_func)
 {
   load_component('flyin');
   if ( !perpage || typeof(perpage) != 'number' || ( typeof(perpage) == 'number' && perpage < 1 ) )
@@ -30,9 +30,26 @@
     this.passer = passer;
   else
     this.passer = false;
-  this.num_pages = Math.ceil(data.length / perpage );
+  if ( ov_num_pages )
+  {
+    this.num_pages = ov_num_pages;
+    this.flip_func = ov_flip_func;
+  }
+  else
+  {
+    this.num_pages = Math.ceil(data.length / perpage);
+    this.flip_func = false;
+  }
   this.random_id = 'autopagin_' + Math.floor(Math.random() * 1000000);
   this._build_control = _build_paginator;
+  this.set_page = function(number)
+  {
+    this.offset = number * this.perpage;
+    var html = this._build_control(number);
+    var elements = getElementsByClassName(document.body, 'div', this.random_id + '_control');
+    for ( var i = 0; i < elements.length; i++ )
+      elements[i].innerHTML = html;
+  }
   if ( this.num_pages > 1 )
   {
     var pg_control = '<div class="'+this.random_id+'_control">'+this._build_control(0)+'</div>';
@@ -68,7 +85,7 @@
 
 window._build_paginator = function(this_page)
 {
-  var div_styling = ( IE ) ? 'width: 1px; margin: 10px auto 10px 0;' : 'display: table; margin: 10px 0 0 auto;';
+  var div_styling = ( IE ) ? 'width: 1px; margin: 10px auto 10px 0;' : 'display: table; margin: 10px 0 10px auto;';
   var begin = '<div class="tblholder" style="'+div_styling+'"><table border="0" cellspacing="1" cellpadding="4"><tr><th>' + $lang.get('paginate_lbl_page') + '</th>';
   var block = '<td class="row1" style="text-align: center; white-space: nowrap;">{LINK}</td>';
   var end = '</tr></table></div>';
@@ -201,6 +218,12 @@
   if ( __paginateLock )
     return false;
   var theobj = pagin_objects[pagin_id];
+  if ( theobj.flip_func )
+  {
+    theobj.flip_func(theobj, jump_to);
+    __paginateLock = false;
+    return true;
+  }
   var current_div = false;
   var new_div = false;
   for ( var i = 0; i < theobj.num_pages; i++ )
--- a/includes/comment.php	Fri Dec 18 05:05:01 2009 -0500
+++ b/includes/comment.php	Fri Dec 18 05:12:02 2009 -0500
@@ -97,6 +97,8 @@
     }
     $ret = Array();
     $ret['mode'] = $data['mode'];
+    if ( isset($data['passback']) )
+      $ret['passback'] = $data['passback'];
     switch ( $data['mode'] )
     {
       case 'fetch':
@@ -106,6 +108,31 @@
         {
           $ret['template'] = file_get_contents(ENANO_ROOT . '/themes/' . $template->theme . '/comment.tpl');
         }
+        $approve_clause = $this->perms->get_permissions('mod_comments') ? '' : " AND approved = " . COMMENT_APPROVED;
+        // Get totals
+        $q = $db->sql_query('SELECT approved FROM ' . table_prefix . "comments WHERE page_id = '$this->page_id' AND namespace = '$this->namespace'{$approve_clause};");
+        if ( !$q )
+          $db->die_json();
+        $counts = array('total' => 0, 'approved' => 0, 'unapproved' => 0, 'spam' => 0);
+        while ( $row = $db->fetchrow() )
+        {
+          $counts['total']++;
+          switch($row['approved']):
+            case COMMENT_APPROVED:   $counts['approved']++;   break;
+            case COMMENT_UNAPPROVED: $counts['unapproved']++; break;
+            case COMMENT_SPAM:       $counts['spam']++;       break;
+          endswitch;
+        }
+        $counts['unapproved'] = $counts['total'] - $counts['approved'];
+        $data['counts'] = $counts;
+        // FIXME, this should be a user preference eventually
+        $ret['per_page'] = $per_page = getConfig('comments_per_page', 10);
+        $page = ( !empty($data['pagenum']) ) ? intval($data['pagenum']) : 0;
+        if ( $page > 0 )
+        {
+          $ret['mode'] = 'refetch';
+        }
+        $limit_clause = "LIMIT $per_page OFFSET " . ($page * $per_page);
         $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,( c.ip_address IS NOT NULL ) AS have_ip,u.user_level,u.user_id,u.email,u.signature,u.user_has_avatar,u.avatar_type, b.buddy_id IS NOT NULL AS is_buddy, ( b.is_friend IS NOT NULL AND b.is_friend=1 ) AS is_friend FROM '.table_prefix.'comments AS c
                                LEFT JOIN '.table_prefix.'users AS u
                                  ON (u.user_id=c.user_id)
@@ -115,11 +142,10 @@
                                  ON ( ( u.user_rank = r.rank_id ) )
                                WHERE page_id=\'' . $this->page_id . '\'
                                  AND namespace=\'' . $this->namespace . '\'
+                                 ' . $approve_clause . '
                                GROUP BY c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,c.ip_address,u.user_level,u.user_id,u.email,u.signature,u.user_has_avatar,u.avatar_type,b.buddy_id,b.is_friend
-                               ORDER BY c.time ASC;');
-        $count_appr = 0;
-        $count_total = 0;
-        $count_unappr = 0;
+                               ORDER BY c.time ASC
+                               ' . $limit_clause . ';');
         $ret['comments'] = Array();
         if (!$q)
           $db->die_json();
@@ -127,10 +153,6 @@
         {
           do {
             
-            // Increment counters
-            $count_total++;
-            ( $row['approved'] == 1 ) ? $count_appr++ : $count_unappr++;
-            
             if ( !$this->perms->get_permissions('mod_comments') && $row['approved'] != COMMENT_APPROVED )
               continue;
             
@@ -174,9 +196,10 @@
           } while ( $row = $db->fetchrow($q) );
         }
         $db->free_result();
-        $ret['count_appr'] = $count_appr;
-        $ret['count_total'] = $count_total;
-        $ret['count_unappr'] = $count_unappr;
+        $ret['count_appr'] = $counts['approved'];
+        $ret['count_total'] = $counts['total'];
+        $ret['count_visible'] = $this->perms->get_permissions('mod_comments') ? $counts['total'] : $counts['approved'];
+        $ret['count_unappr'] = $counts['unapproved'];
         $ret['auth_mod_comments'] = $this->perms->get_permissions('mod_comments');
         $ret['auth_post_comments'] = $this->perms->get_permissions('post_comments');
         $ret['auth_edit_comments'] = $this->perms->get_permissions('edit_comments');
--- a/includes/namespaces/default.php	Fri Dec 18 05:05:01 2009 -0500
+++ b/includes/namespaces/default.php	Fri Dec 18 05:12:02 2009 -0500
@@ -1005,6 +1005,8 @@
     $row = $db->fetchrow();
     
     // Get comment counts
+    // FIXME: Apparently there's a bit of recursion in here. Fetching permissions depends on this cdata function.
+    // Perhaps we should eliminate session's dependency on cdata? (What is it used for?)
     $q = $db->sql_query('SELECT approved FROM ' . table_prefix . "comments WHERE page_id = '$page_id_db' AND namespace = '$namespace_db';");
     // yay parallel assignment
     $row['comments_approved'] = $row['comments_unapproved'] = $row['comments_spam'] = 0;
--- a/includes/sessions.php	Fri Dec 18 05:05:01 2009 -0500
+++ b/includes/sessions.php	Fri Dec 18 05:12:02 2009 -0500
@@ -4356,9 +4356,10 @@
       ORDER BY target_type ASC, page_id ASC, namespace ASC;';
       
     $q = $session->sql($bs);
-    if ( $row = $db->fetchrow() )
+    if ( $row = $db->fetchrow($q, true) )
     {
-      do {
+      do
+      {
         $rules = $session->string_to_perm($row['rules']);
         $is_everyone = ( $row['target_type'] == ACL_TYPE_GROUP && $row['target_id'] == 1 );
         // log where this comes from
--- a/includes/template.php	Fri Dec 18 05:05:01 2009 -0500
+++ b/includes/template.php	Fri Dec 18 05:12:02 2009 -0500
@@ -829,7 +829,9 @@
             COMMENT_UNAPPROVED => $cdata['comments_unapproved'],
             COMMENT_SPAM => $cdata['comments_spam']
           );
-        $num_comments = array_sum($approval_counts);
+        $num_comments = $session->check_acl_scope('mod_comments', $this->namespace) && $this->page->perms->get_permissions('mod_comments')
+                          ? array_sum($approval_counts)
+                          : $approval_counts[COMMENT_APPROVED];
       }
       else
       {