Caveats
Before we begin, note that the present state of the Blogger tags are rather limiting and don't yet make it possible to actually solve this problem all out for post pages, without additional labour on your part (such as manualy maintaining the Previos and Next links in each post's text body -- doable though painful) -- the solution given below gives previous and next date links for your archive pages, not Previous / Next post pages. (They can of course be put on item pages too, but on a busy blogging day with three items posted, both the Previous and Next links will skip over a note or two, jumping straight to the nearest date in either direction.) There, you have been warned, now let's get to it!Prerequisites
You must make sure your Blogger settings are right, since this method requires you to archive by day. Also, you have to republish the entire blog every time you add a post on a new date, or there will not be any "Next date" links for the days running up to the last post. This is because this solution is based on scanning the Archives secion of your blog for links, comparing the dates between the links available there and the dates of the post visited, to pick out the next and previous dates for the two navigation links. Crude, yet effective. This requires reposting the entire blog, because Blogger would not otherwise add today's archive page link to yesterday's archives section. (And it's either update all posts or just today's. Too bad for us; we'll just have to wait for the extra needless processing of our blog history.) One more thing: by implication, to manage to parse these dates, both your date header and archive date formats must contain all of year, month and date. "Sunday", or "November 20" is not enough.Anyway, find the Archive settings, and set the Archive Frequency to "Daily":
Then it's time to muck about with the template. Pick the Template tab in the view above, mark all contents, copy them and save them in a file somewhere safe. There is no undo button anywhere in sight, so you want to provide you the option, in case you're not satisfied with the results, or something goes very wrong. (I won't be able to help you, so you had better help yourself. I'm only going to say this once.)
Now seek out the
<BlogDateHeader>
tag; it should be somewhere in the <body>
tag, and you might have to scroll through lots and lots of stylesheets before you find it. Mine looked like this before editing:<BlogDateHeader>
<div class="DateHeader"><$BlogDateHeaderDate$></div>
</BlogDateHeader>
and we will change it a bit to toss in some additions, marked in bold face below:
<BlogDateHeader>
<div style="float:left; visibility:hidden; padding:0.5em;"
id="prev-date"><a accesskey="P">« Previous Date «</a>
</div>
<div style="float:right; visibility:hidden; padding:0.5em;"
id="next-date"><a accesskey="N">» Next Date »</a>
</div>
<div id="seen-date" class="DateHeader"><$BlogDateHeaderDate$></div>
</BlogDateHeader>
The style attributes and order of these tags isn't important; it's just a sketchy way of making them show up somewhat naturally in the page flow; your own styling should hopefully look a little better, to blend in better with the rest of your blog template. If you so prefer, you may skip the added divs and tuck the id and style attributes on to the
<a>
tags themselves, instead. The accesskey attributes give nice shortcuts to these links; Alt + P/N in most environments, Shift + Escape followed by P or N in Opera. In other Mac browsers, it's Control + P/N.This adds the basis for where the navigation will end up. As you see, they will be hidden by default -- the mentioned script code will turn them on, when there is something to be clicked for each link. If you always want both links visible, even when unclickable, delete the "visibility:hidden;" part. Should you want just the key bindings, but not the visible links, substitute with "display:none;" instead.
Next, we must make sure the archive section is adressable by the script. Seek out (or add anew, if there is none) the
<BloggerArchives>
tag. Mine looked like this:<BloggerArchives>
<a href="<$BlogArchiveURL$>"><$BlogArchiveName$></a> /
</BloggerArchives>
and after our modifications, it will look like this:
<div id="archive"><BloggerArchives>
<a href="<$BlogArchiveURL$>"><$BlogArchiveName$></a> /
</BloggerArchives></div>
The only bit that matters about it is that there is the
<a>
tag above somewhere in it and that it is surrounded by a tag with the id="archive"
attribute. Below this we will add the big portion of code that does the links. Optionally, you may stow all but the leading makePrevNextLinks()
line away somewhere up in your <head>
tag, if you prefer. Just make sure that the makePrevNextLinks()
line appears in the page flow below the above sections, and things will run just fine.The final blow is the large chunk of code below. Tune it to use your date format (you may want to open up the Settings / Formatting page in a different browser window to find out what date format settings you use, in case you forgot. The two select boxes below need to use the same format (though they won't tell the same date, unless you are one of the few readers who happen to catch this note today, the same day I wrote it), or the code will not work. When you pick a date format, the first two lines of the code below changes accordingly; should you later feel you want to use some other date format, come back here and readjust them to see what values to put there.
Add the huge
<script>
block -- if you just want it on the archive pages where it always works reliably, encase it in an <ArchivePage>...</ArchivePage>
container, and it won't appear on the main page and item pages. If your choice of Date Language isn't English and either of your date formats includes a month name, also be sure to edit the monthNames variable to read exactly (case matters!) how month names are listed in your language of choice, separated by the vertical bar character. Once you are done, save the template and republish your blog, and voilà -- Previous and Next buttons!<script type="text/javascript">
var monthNames = 'January|February|March|April|May|June|July|' +
'August|September|October|November|December';
var dateHeaderParser = getDateHeaderParser( 1 );
var archiveParser = getArchiveParser( 9 );
makePrevNextLinks(); // Don't change anything from here onwards:
function makePrevNextLinks()
{
var prevNode = document.getElementById( 'prev-date' );
var seenNode = document.getElementById( 'seen-date' ), seen;
var nextNode = document.getElementById( 'next-date' );
if( !seenNode ) return alert( 'No tag with id="seen-date" found!' );
if( !(seen = dateHeaderParser( seenNode.innerHTML )) )
return alert( 'Failed to parse date "'+ seenNode.innerHTML +
'"; did you really set the right format?' );
seen = seen.getTime();
var all = getDates(), prev, next;
for( next in all )
if( next == seen )
{
next = null;
continue;
}
else if( next > seen )
break;
else if( next < seen )
{
prev = next;
next = null;
}
if( prev && prevNode )
{
if( prevNode.noveName != 'A' )
prevNode = prevNode.getElementsByTagName( 'a' ).item( 0 );
prevNode.href = all[prev];
prevNode.style.visibility = 'visible';
}
if( next && nextNode )
{
if( nextNode.noveName != 'A' )
nextNode = nextNode.getElementsByTagName( 'a' ).item( 0 );
nextNode.href = all[next];
nextNode.style.visibility = 'visible';
}
}
function getDates()
{
var ar = document.getElementById( 'archive' );
if( ar )
{
var all = ar.getElementsByTagName( 'a' ), dates = {}, i;
for( i=0; i<all.length; i++ )
{
var link = all[i];
var date = archiveParser( link.innerHTML );
if( date ) dates[date.getTime()] = link.href;
}
return dates;
}
}
function getArchiveParser( formatNo )
{
var fmt = { 0:'MonthName Day, Year', 1:'MonthNo/Day/Year',
2:'MonthNo\\.Day\\.Year', 3:'YearMonthNoDay',
4:'Day\\.MonthNo\\.Y2', 5:'Year-MonthNo-Day',
/*6:'MonthName Day',*/ 7:'MonthName Day, Year',
8:'Year/MonthNo/Day', 9:'MonthNo/Day/Y2',
10:'Y2_MonthNo_Day', 11:'Day MonthName Year',
12:'Day MonthName', 13:'Day/MonthNo/Year',
14:'Day/MonthNo/Y2' }[ formatNo ];
return fmt ? getDateParser( fmt ) : alert( 'Archive date format type ' +
(formatNo ? formatNo + ' not supported! (Year needed?)' : ' not given!') );
}
function getDateHeaderParser( formatNo )
{
var fmt = { 1:'MonthName Day, Year', 2:'MonthNo/Day/Year',
3:'MonthNo\\.Day\\.Year', 4:'YearMonthNoDay',
14:'Year/MonthNo/Day', 6:'Year-MonthNo-Day',
5:'Day\\.MonthNo\\.Y2', 7:'MonthNo\\.Day\\.Year',
/*8:'Weekday', 10:'MonthName Day',*/
12:'MonthName Day, Year', 18:'Day MonthName Year',
23:'Day MonthName, Year' }[ formatNo ];
return fmt ? getDateParser( fmt ) : alert( 'Date header format type ' +
(formatNo ? formatNo + ' not supported! (Year needed?)' : ' not given!') );
}
function sortNumeric( a, b )
{
return parseInt( a ) - parseInt( b );
}
function findInArray( array, value )
{
for( var i=0; i<array.length; i++ )
if( array[i] == value ) return i;
return -1;
}
function getDateParser( format )
{
var what = { Year:'\\d{4}', Y2:'\\d{2}', MonthName:monthNames,
MonthNo:'\\d{1,2}', Day:'\\d{1,2}' };
var re = format, monthNo = {}, where = {}, order = [], tmp, i, type;
for( i=0, tmp = what.MonthName.split( '|' ); i<tmp.length; i++ )
monthNo[tmp[i]] = i;
for( type in what ) // for each match type,
if( (tmp = format.indexOf( type )) >= 0 ) // if used in this format,
{
where[tmp] = type; // store away its match position, to find out
order[order.length] = parseInt( tmp ); // which paren matched what
re = re.replace( type, '('+ what[type] +')' ); // and fix the regexp
}
for( i=0, order = order.sort( sortNumeric ); i<order.length; i++ )
order[i] = where[order[i]]; // map back to mnemonics, again
var getYear = function( match )
{
var where = findInArray( order, 'Year' ) + 1;
if( where ) return parseInt( match[where], 10 );
where = findInArray( order, 'Y2' ) + 1;
if( !where ) return (new Date).getFullYear();
var year = parseInt( match[where], 10 ) + 1900;
if( year < 1990 ) year += 100;
return year;
};
var getMonth = function( match )
{
var where = findInArray( order, 'MonthName' ) + 1;
if( where ) return monthNo[ match[where] ];
where = findInArray( order, 'MonthNo' ) + 1;
if( where ) return parseInt( match[where], 10 ) - 1;
return (new Date).getMonth();
};
var getDate = function( match )
{
var where = findInArray( order, 'Day' ) + 1;
if( where ) return parseInt( match[where], 10 );
return (new Date).getDate();
};
re = new RegExp( '\\b'+ re +'\\b', 'i' ); // make it a real RegExp
return function( raw )
{
var match = re.exec( raw );
if( match )
return new Date( getYear(match), getMonth(match), getDate(match) );
};
}
</script>
Very nice!
ReplyDeleteHow did you make your calendar?
In a fashion quite similar to that outlined in my article on calendar navigation.
ReplyDelete;) I'm still waiting for the IE version of the script
ReplyDeleteOh men! I re-invent the wheel :D
ReplyDeleteTake a look this example http://adivina.blogspot.com/2004_03_01_adivina_archive.html
Just I prefer monthly, not daily. I am working on the explain post, i think is more easy than yours.
Anyway, great job!
Mario
I'm trying to do it in my blog: luison-off.blogspot.com But I don't get it! I think I followed every step correctly... But the problem is that if you open the page it will say: "No tag with id='seen date' found!" I don't know what to do... I already having problems with the calendar too... :S it was saying NaN NaN NaN everywhere... Could you please help me??? Thank you very much!!!!
ReplyDeleteIt's me again... jejeje After a long time trying and trying... finally I guess I've fixed some of the problems. Now it doesn't say nothing worng when you open it.. and the calendar it's working again!... But the problem now is that the previous and next links don't work. Really I'm getting crazy with this... :S Could anybody help me please? Thanks a lot.
ReplyDeleteYour page misses the makePrevNextLinks function definition, which takes up most of this post; you try to call it without having defined it somewhere first. Or, if you have put it in an external script somewhere, you try to call it prior to having included that script in the page, which is the same thing to a web browser.
ReplyDeleteWhen ripping out a script tag to an external file, by the way, lose the leading <-- and trailing //--> -- I'm somewhat surprised to see the calendar work even with them intact. I would not expect all browsers to handle that syntactic error, though.
Ok. Actually it wasn't missing the "makePrevNextLinks" function definition... It was in the bottom of the page... but I fixed it and put it in the head all together. Anyway I still having problems... it says "No tag with id:"seen-date" found!"... I will fix the calendar later... I'm thinking to put it in my own server... Thanks a lot!
ReplyDeleteThank you so much! I know nothing about script but your explanation was very easy to follow. I had to fiddle with a few things, but it all worked out and now I have previous and next links. Thanks again!
ReplyDeleteThanks dude, this'll really come in handy with my scanlation blog
ReplyDeleteHow to copy the code so I don't have to type all of them ???
ReplyDeletethanks
Thank you so much for figuring this beautiful solution and for sharing it with easy to follow instructions! *appreciative smile*
ReplyDeleteI had a bit of a struggle as IE wouldn't behave with the visiblity property. I did a shameless hack of making the default colours the same as my background (in lieu of making the links hidden) and then assigned the appropriate colour property when there was a link present. Not elegant but it works.
Thanks again!
hi there! if I want the previous next links on the main page, what do I encase the long script in? thanks!
ReplyDeleteI believe you might be looking for the MainPage or even MainOrArchivePage tag for that, but you will probably also have to take your time to understand and retailor the code to work in that environment. Best of luck with that; I am afraid I won't invest time in doing it myself.
ReplyDeleteThanks for all those amazing tools that have made my blogger life a whole lot easier (especially the catogerizer).
ReplyDeleteI was wondering, in your script here : "Also, you have to republish the entire blog every time you add a post on a new date, or there will not be any "Next date" links for the days running up to the last post."
So, my question is - is there a script that would work this way : when I press "publish" for my new post, would first publish my new post and then republish the whole blog? that would take care of the only "downfall" this script has. Maybe this could be embedded into one of your already existing scripts
Oh! My God!
ReplyDeleteYour blogger is very nice,especially sidebar calendar process so smart!
I like your blogger template!
Thank you!
I in your blogger,learn Information is very much!
So sorry...
I come from Taiwan,english isn't good...
I wish you understand my type...^^|||
This's blogger cheat is what I've been waiting for so long. But I just don't get on the last 3 paragraphs. Actually, where I've to put the script in?
ReplyDeleteI've put it inside the head section but got the error "No tag with id='seen date' found!" and the script doesn't work.
and where's the ArchivePage tag? My theme doesn't has it. Create it my self? in which section?
Please help. Thanks..
hi this is something ive been looking for a terribly long time. i have a question though. in this script the archives links all show up. if i wanted them to appear in a drop down list can you tell me what code i should use? thanks in advance.
ReplyDeleteritu
This script does not (and should not) address that need. You may wish to browse around Freshblog and perhaps pay most attention to its wiki of blogger hacks.
ReplyDeletethanks johan. thats been a BIG help :)
ReplyDeleteI love this hack and appreciate folks like yourself that share your gift of mastering these codes with everyone free of charge.
ReplyDeleteIt works for me wonderfully in firefox, but is invisible and does not work in IE 6 or 7. Any thoughts that I may have missed in the comments above, when you have the time.
Thank you very much :)
ReplyDeleteI finally got what I've been looking for :)
I've been looking for this hack for ages! Thankyou! Anyway I'm having serious problems to get it working. Just like ax2m said, I'm not sure if I was supposed to place the big block in the "head", and I keep getting the alert "no tag with id=seen-date" :( The "next" and "previous" words doesnt show up until I remove the visiblity feature, and still they dont link anything. Hope someone can help :/
ReplyDeleteI get that alert, "no tag with id=seen-date" as well. What does that mean? What am I doing wrong?
ReplyDeleteThis tutorial was written two years ago for a Blogger template system that doesn't match the one in use today. My best suggestion is to seek more recent hotwos elsewhere on how to achieve similar things. Freshblog mentioned above is probably the best starting point.
ReplyDeleteI'm using the classic template though. Does that matter? Thanks for your help.
ReplyDelete