April 19, 2012

Swapping to Reverse Post Order on Blogger


Sometimes an oldest-to-newest order of blog posts would be better than Blogger's standard newest-to-oldest arrangement. A blog about a project is an example. The posts would proceed from oldest to newest so a visitor to the blog could start reading at the project introduction and proceed from there. Unfortunately, Blogger doesn't provide this as an option.

There are a number of existing approaches to this problem but, for various reasons, none of those exactly fit my needs. So I decided to roll my own.

David Merriman's script served as the starting point in locating post container nodes in Blogger's template. From there, the idea was to create a script that locates the blog's post container and then searches concurrently for posts from both the top and bottom of that container. When a post is reached at each end, those posts would be swapped. The concurrent search would then continue on toward the center of the container. The search would end once the center is reached, at which point the contained posts would have been reversed by the preceding swaps. The process is then repeated for each day of posts to reorder multiple posts within days.

The resulting drop-in hack is shown below. To use it, copy and paste the entire script into your Blogger template just before the </body> tag and then save the template. View your blog, reloading if needed, and your posts should be displayed in reverse order. Take a look at http://diyreader.blogspot.com to see it in use.

<!-- Start Post Reversal Code -->
<script type='text/javascript'>
//<![CDATA[
  // -----------------------------------------------------------------------------------------
  // Name   : PRS - Post Reversal Script for Blogger - Version 1.0
  // Author : David Yockey
  // URL    : http://techsquirrels.blogspot.com/2012/04/swapping-to-reverse-post-order-on.html
  // -----------------------------------------------------------------------------------------

  // Temp variable used to shorten classname references
  var cn;

  // This function is called as needed in the main program below.
  function ReversePosts(BlogPostContainer,PostClass) {

    // Arguments:
    //    BlogPostContainer -- The node containing the posts to be reversed.
    //    PostClass -- The className of each of the posts in the container to be reversed.
    //                 (may be a single name from among names in the class attribute of the posts)

    // Flag for checking whether any posts are found
    var found=false;

    var BlogPosts = BlogPostContainer.childNodes;  // May include text-nodes containing
                                                   // whitespace in addition to post-nodes

    // Set index variables to top and bottom of BlogPosts list
    var i=0;
    var j=BlogPosts.length-1;

    for( ; ; ) {     // Start Endless Loop

      // Find next Post from the top
      while( (i < j) && (!(cn=BlogPosts[i].className) || !(cn.match(PostClass))) )
        ++i;

      // Find next Post from the bottom
      while( (i < j) && (!(cn=BlogPosts[j].className) || !(found=cn.match(PostClass))) ) // (see Footnote 1)
        --j;

      if( found && i < j ) {
        // Swap Posts (see Footnote 2)
        var tempi = BlogPosts[i].cloneNode(true);           // Store a copy of Post i in tempi
        var tempj = BlogPosts[j].cloneNode(true);           // Store a copy of Post j in tempj
        BlogPostContainer.replaceChild(tempi,BlogPosts[j]); // Replace Post j with Post i in tempi
        BlogPostContainer.replaceChild(tempj,BlogPosts[i]); // Replace Post i with Post j in tempj
      } else {
        // Done
        break;        // Break out of Endless Loop
      }

      ++i; --j;
    }
  }
  // Footnote 1:
  //   If a post is found from one end, then a post must necessarily be found from the other.
  //   So, recording and later checking for a post from one end is sufficient to ensure that
  //   one was found from both.
  //
  // Footnote 2:
  //   At least in Firefox 11.0 on Fedora Linux, replacing a child directly with another child
  //   causes some text-nodes containing whitespace to be deleted. That node deletion messes up
  //   the positions of the posts in the BlogPosts list. This is avoided by cloning both posts
  //   rather than just one and replacing both posts from the cloned copies.


  // *** MAIN POST REVERSAL PROGRAM ***

  // Magic Words
  var BlogWidget             = 'Blog1';
  var BlogPostContainerClass = 'blog-posts';
  var BlogPostClass          = 'date-outer';
  var DatePostContainerClass = 'date-posts';
  var DatePostClass          = 'post-outer';

  var Blog1 = document.getElementById(BlogWidget);

  // Find the node containing the blog posts
  var BlogPostContainer;
  var x=0;
  do {
    BlogPostContainer = Blog1.childNodes[x++];
  } while ( !(cn=BlogPostContainer.className) || !(cn.match(BlogPostContainerClass)) );

  // Reverse different day posts
  ReversePosts(BlogPostContainer,BlogPostClass);

  // Reverse same day posts - Loop thru contents of BlogPostContainer to find each day's posts
  var BlogPosts = BlogPostContainer.childNodes;
  for ( i = 0; i < BlogPosts.length; ++i ) {

    // Check for an actual post-node rather than a text-node or such
    if ( (cn=BlogPosts[i].className) && cn.match(BlogPostClass) ) {
      var DatePostContainer;
      x=0;

      // Find the node containing the posts to be reversed for the current day being processed
      do {
        DatePostContainer = BlogPosts[i].childNodes[x++];
      } while ( !(cn=DatePostContainer.className) || !(cn.match(DatePostContainerClass)) );

      ReversePosts(DatePostContainer,DatePostClass);
    }
  }
//]]>
</script>
<!-- End Post Reversal Code -->
Code highlighting (if your browser displays it...) powered by google-code-prettify.

The script doesn't include an option to select whether or not to reverse the order. If you need this option, you might want to try MS-potilas's script, although I haven't tried it myself.

My thanks go to David Merriman and MS-potilas for their prior work on this problem and the guidance it provided.
09/25/2012 -- You may also be interested in: Hiding Blog Post Manipulation

April 2, 2012

Sideblog: DIY Reader

A place for details on modding an old laptop into a stationary tablet-like reader. Post questions and comments about aspects of interest to you. http://diyreader.blogspot.com