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

32 comments:

  1. Many thanks - works perfectly for what I wanted - www.wprc.biz

    ReplyDelete
  2. Good to know that we can still do it in real. I have tried several script that did not work. But this time works. Thank you very much.

    ReplyDelete
    Replies
    1. You're very welcome! But I hope people don't think too badly of other authors and their non-working scripts. I'm sure those scripts worked in the past but were broken when Blogger changed how something worked. Changes like that are an unfortunate hazard of programming around web-based services.

      Delete
  3. Hi,
    thanks for the script. Was checking for something like this for a week. but this is not solving my problem completely.

    Does this have any limits? I tried it in my blog - keeveees.blogspot.in. It did not start from the beginning. Rather shows one of the my posts in the middle.
    The only logical thing I can think of is that this post is from a day having multiple posts? Is there a problem if one date has many posts?

    ReplyDelete
    Replies
    1. Sorry about the late reply! Had to change my notification email addy some time ago and just found that I mucked up the change!

      A limit wasn't intended, but I hadn't tested it too much with multiple posts on the same day, so there might be one. I'll see if I can find a way to get around your problem and will post the results, positive or negative, by 12:00PM Eastern / 4:00PM UTC next Tuesday, Sept. 3 at the latest.

      In the mean time... If anybody else out there finds a solution, please post your fix!

      Delete
    2. Ok, I couldn't relax until some answer was found, so I'm *way* early.

      The short story is...

      The script's functionality is limited to posts shown on your blog's main page, as determined by your blog's settings.

      The long story is...

      I'm guessing that you're expecting the entire blog to be reordered. That's a reasonable expectation. Unfortunately, JavaScript dropped into a Blogger template can only do that if all of the blog's posts are shown on the main page. That's because the JavaScript runs in your browser and only has access to posts on the page being viewed. It doesn't actually have access to your posts stored on Blogger's system. So posts in the middle will be shown if less than all of the blog's posts are shown on the main page.

      In testing, the script seems to work correctly otherwise. Feel free to post another comment if you're having a different problem with it.

      Delete
  4. I put in the code before the body tag, but it did not reverse the blogs. Instead, I see !-- Start Post Reversal Code --> at the very top of the blog - just below the browser menu and just above the Blogger menu bar, and the text is unfortunately not a link. I am on a MacBook Pro running OS10.8.5. The browser is Firefox 18.0.1. All my blogs are on the main page. Any ideas about what I am doing wrong?

    ReplyDelete
    Replies
    1. The text between '<!--' and '-->' is a comment, so you should never see it on the page in your browser. Looks like you might have missed the very first '<' character in the code.

      Delete
  5. Actually, I inserted it before the '< body >' tag instead of the '< /body >' tag. Now it works! In fact it works so well that it reversed the technique I used for previous blogs of putting dates in reverse order and then putting the real date in the title - sigh. I did notice it doesn't reverse the sidebar date order, but maybe that's a lot of work for something that is not very annoying.

    ReplyDelete
    Replies
    1. Glad ya got it working!

      As for the sidebar date order... Assuming you're referring to the Blog Archive gadget, Blogger provides an option to "Show Oldest Posts First." Go to the Layout section for your blog and click the Edit link on the Blog Archive gadget. That'll get you to the "Configure Blog Archive" dialog where you can set the option.

      Delete
  6. So it does! Thank you. Now, can you get around the 1MB page size limit, which is fine for text but limits the number of posts on the main page with pictures and videos? I suppose I could use the jump break feature, but it seems a little ugly.

    ReplyDelete
    Replies
    1. Hmmm... I've never really considered the page size limit... I'll have to give it some thought. And I'm not familiar with the jump break feature; have to look that up soon, too.

      Off the top of my head, though, I'd have to say, "Probably not." Except that you could reduce your picture file sizes in a number of ways before uploading using the graphic editor of your choice.

      Delete
    2. Actually, to lower image file sizes in a post without sacrificing quality in the zoomed images, you can manually create your own thumbnails of the high quality images and upload them. Then get into the post's source code and substitute the thumbnail URL for the high quality image URL in the image displayed on the page while keeping the link URL still pointed at the high quality image. When the thumbnail's clicked on, the high quality image is then loaded.

      I did this earlier today with the large image on the post Getting VectorLinux To Recognize PCMCIA Cards and cut it down from 500KB to 95KB. If coding is your thing, you can take a look at the source of that page for specifics. If not, I'll get an understandable post about it up by sometime this weekend. But keep in mind... 11:59pm Eastern Time on Sunday counts as "sometime this weekend." :^)

      Delete
  7. Would you be able to provide the code to make comments appear newest to oldest? I need the most recent comments to appear at the top. Thank you.

    ReplyDelete
    Replies
    1. I hadn't considered the problem. It seems that it would be a significant project in itself, and I doubt I'd be able to tackle it without some strong motivation like personal need. Or maybe a bag of money... ;^) But it sounds like a project worth pursuing if one were interested enough. Anyone out there in the blogosphere want to take this on?

      Delete
  8. I seem to have put my bags of money in a 'safe place'. �� My friends daughter is using blogger to post her schoolwork and it would help her to see the most recent. If not code, is there any other option that you might know of? Maybe a widget of some kind...? Thanks again.

    ReplyDelete
    Replies
    1. Good to hear that your bags of money are safe. I'd probably just waste 'em all on coffee anyway. :^)

      I did a quick search and found an article entitled "Reverse the Order Of Comments In Google Blogger" at http://www.oneminuteinfo.com/2011/07/reverse-order-of-comments-in-blogger.html. I don't know if it'll still work since it's from 2011.

      Other than that, I really don't know. Sorry.

      Delete
  9. I copied and pasted the html and place right above the body tag and then saved the template but it didn't reverse the posts. Can someone please help me? I don't know why it didn't work but anyway my blog is at http://harpsketa.blogspot.com/ Can someone possibly email me at harpsketa@msn.com? I'm desperate to reverse the order of my posts.

    ReplyDelete
    Replies
    1. Looking at the source code of your blog, I see that you have pasted in David Merriman's script rather than mine. I developed the script presented in this post because Mr. Merriman's script no longer functioned properly.

      I've tried the script presented above on a test blog using the same template as you're using and it worked properly. Try using the script above and see if it works for you.

      Delete
  10. This worked for me, except it did not put Day 1 for the first post. It put Day 2 for the first post. (Day 1 has all the info about the blog.) So, I had to take the code out, and I'll try to research another way.

    ReplyDelete
    Replies
    1. I combined Day 1 onto the Day 2 post. Looks great! :)

      Delete
    2. Nice workaround!

      Weird that the script would put Day 2 first. I wouldn't think it would be capable of doing that without coding in an explicit start of reordering from the second post and some kind of awkward repositioning of the first post.

      For my own edification and in case someone else runs into this problem, I'll check out your blog to see what template your using and hopefully get a chance to look into the cause sometime in the not-too-distant future.

      Delete
    3. Well... I would take a look at your blog, but I can't seem to easily track it down. Could you post a link to your blog or indicate what template you're using?

      Delete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Hello,

    The hack works fine in some templates but in that

    https://www.guiadearousa.com/search/label/arousa
    ¿what can I do to make it works?

    Thanks!

    ReplyDelete
    Replies
    1. From a quick search of your site's page source, it's clear that the template used lacks a couple of the "Magic Words" that the script uses. A simplistic view would be that those just need to be changed to the right words, and everything would work fine. Unfortunately, it's not that simple.

      It's almost certain that the logical structure of the code in the template used is significantly different than the particular template with which I made the script to work, and that would require rewriting the guts of the script. Before doing that, the structure of the non-functioning template would need to be understood. Together, these would -- at least for me :( -- be impossible to do without investing at least several hours.

      HTML/CSS/Javascript experts out there are cordially invited to rewrite the script for other templates in their copious spare time. :)

      Incidentally, the "Magic Words" aren't in any way magic. They're just convenient tag attributes that happened to be available in the template the script was created to work with to locate particular items in that template's code.

      Delete
    2. Ok. Finally I decides to change the template for another thats works with your script. ;)

      Delete
  13. When I want my posts to read in a sequential time line like a story, I just place all posts on the same page. Just enter each new post as an addition to the initial post. Don't ever hit 'New Post', just hit 'Update' after each new entry. To convert an earlier blog that has been laid out in blog sequence into a story line, just cut each earlier posting and paste onto the end of the initial post. Just remember to never hit 'New Post' and hit 'Update' after each paste. I don't know what the limit is to how much can be in one post, but I have entered 200+ photos and text with no problem. This has worked well for me for many long travel stories.

    ReplyDelete
    Replies
    1. Do dates have to be added manually, or is a date provided with each update? And, pasting into the initial post doesn't provide a list of links to individual posts (i.e. a "Blog Archive"), does it?

      If the blog archive's not needed (assuming it's not provided), it's certainly a good solution, especially in that it's less brittle than javascript coding on top of Blogger's javascript. But not as much geeky fun to implement. :)

      Delete