Dear Friend,
With a simple twist of Tabview - Part 2 tutorial, you can collect all of your fav blogs into one nice view.
Here is the code, I'll let you figure out how to add it to the TabView widget :-)
var tabView2 = new YAHOO.widget.TabView('multiTab2');
function listLatestPostsTab2a(json) {
listOneTab(json, tabView2, "Hackosphere", true);}
cb.search( "hackosphere.blogspot.com", "posts", 1, 25, 'listLatestPostsTab2a');
function listLatestPostsTab2b(json) {
listOneTab(json, tabView2, "Beautiful Beta", false);}
cb.search( "beautifulbeta.blogspot.com", "posts", 1, 25, 'listLatestPostsTab2b');
function listLatestPostsTab2c(json) {
listOneTab(json, tabView2, "Blogger Hacked", false);}
cb.search( "blogger-hacked.blogspot.com", "posts", 1, 25, 'listLatestPostsTab2c');
function listLatestPostsTab2d(json) {
listOneTab(json, tabView2, "Phydeaux", false);}
cb.search( "phydeaux3.blogspot.com", "posts", 1, 25, 'listLatestPostsTab2d');
function listLatestPostsTab2e(json) {
listOneTab(json, tabView2, "Blog U", false);}
cb.search( "bloggeruniversity.blogspot.com", "posts", 1, 25, 'listLatestPostsTab2e');
function listLatestPostsTab2f(json) {
listOneTab(json, tabView2, "Purple Moggy", false);}
cb.search( "purplemoggy.blogspot.com", "posts", 1, 25, 'listLatestPostsTab2f');
function listLatestPostsTab2h(json) {
listOneTab(json, tabView2, "The Last Word", false);}
cb.search( "lastword.blogspot.com", "posts", 1, 25, 'listLatestPostsTab2h');
Have a wonderful day,
Update:
*26 May 07: Wai Yan Lin translated part 1 and 2 of the TabView widget and this post to Burmese here:
http://waiyanlinn.blogspot.com/2007/05/tabview-widget.html
This blog contains most of my previous posts from hoctro.blogspot.com
Archived Post: TabView Application: A Blogger Hack Directory
Dear Friend,
Here is an application of the TabView widget, a "Blogger Hack Directory". Of course, you would have different interests, once you decide to make a directory for yourself.
http://hoctro-bloggerhackdir.blogspot.com/
For your convenience, you could download the template from the link below:
http://hoctro2007.googlepages.com/bloggerdirectory.xml
Then, create a new blog, and upload the template. Once you know how to alter the contents, you'll be able to create your own version.
For information on how to upload a template, please follow the instructions from this article: Hacking Technique - How To Modify a Template or from "Blogger-Templates" blog.
Have a wonderful day.
Here is an application of the TabView widget, a "Blogger Hack Directory". Of course, you would have different interests, once you decide to make a directory for yourself.
http://hoctro-bloggerhackdir.blogspot.com/
For your convenience, you could download the template from the link below:
http://hoctro2007.googlepages.com/bloggerdirectory.xml
Then, create a new blog, and upload the template. Once you know how to alter the contents, you'll be able to create your own version.
For information on how to upload a template, please follow the instructions from this article: Hacking Technique - How To Modify a Template or from "Blogger-Templates" blog.
Have a wonderful day.
Archived Post: Tab View (Part 2)
Dear Friend,
My next step in perfecting the TabView widget is to add two default tabs to show a blog's latest posts and comments. I also modify the code so that you can have multiple blogs shown in different views.
But first, a quick explanation on "commenting out" things from a Blogger template.
If you want to exclude a section of code inside the two <script> and </script>, you can either use // for a single line, or /* */ for multiple lines.
For template code outside Javascript such as html tags, use this notation instead <!-- -->
Now, to see the effect of multiple tab views, in step 3 from "Introducing TabView Widget - Part 1" tutorial, remove the <!-- in front of and --> after the bold code below so the code looks like this
<div>
<h2>Hoctro's Place</h2>
<div class='yui-navset' id='multiTab1'/>
</div>
<div>
<h2>Hackosphere</h2>
<div class='yui-navset' id='multiTab2'/>
</div>
and also near the end remove the /* in front of and and */ after the bold code below so the segment now looks like this:
// Preferred Labels
for (var i=0; i < labels1.length; i++)
if (labels1[i]) cb.searchLabel(blog1, labels1[i], 'listTab1');
var blog2 = "hackosphere.blogspot.com";
var tabView2 = new YAHOO.widget.TabView('multiTab2');
var labels2 = ['Neo','Widgets', "Blogger Power"];
function listTab2(json) {
listOneTab(json, tabView2, "", false);
}
function listLatestPostsTab2(json) {
listOneTab(json, tabView2, "Latest Posts", true);
}
function listLatestCommentsTab2(json) {
listOneTab(json, tabView2, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog2, "posts", 1, 25, 'listLatestPostsTab2');
// Latest Comments
cb.search( blog2, "comments", 1, 25, 'listLatestCommentsTab2');
// Preferred Labels
for (var i=0; i < labels2.length; i++)
if (labels2[i]) cb.searchLabel("hackosphere.blogspot.com", labels2[i], 'listTab2');
</script>
</b:includable>
</b:widget>
What you will see now is the appearance of another tab view, showing Hackosphere's latest posts, comments, and are watch list of interesting labels.
As you can see, I make it a little bit easier for you to have the ability to add a new tab view, simply by removing the comments. But the process to add a new view from scratch is quite involved, so you need to pay extra attention to make it right. I believe if you interested in reading this article, you already have enough knowledge to proceed. (I wish I can use the ultimate solution, that is writing a pseudocope class, but I have not enough experience to pass value such as json and array to a parameter by reference. So you have to live with the less convenient solution such as this.)
Adding a new tab view to the widget is a three step process, and I will carefully walk you through each step.
If you have not already installed the TabView widget, please do so.
We are adding yet another third view for the purpose of tracking latest development on Hans' Beautiful Beta blog, and it's going to involve a lot of cut-and-paste, modifying and also common sense. Let's name the id of the "div" that will store it as multiTab3.
This step allows you to configure the appearance of the tab views, either vertically, or as a 2 column table, or anything you like.
In step 3's code of part 1, cut and paste this code below right next to it.
<div>
<h2>Hoctro's Place</h2>
<div class='yui-navset' id='multiTab1'/>
</div>
then change h2 content and the id to become (in bold):
<div>
<h2>Beautiful Beta</h2>
<div class='yui-navset' id='multiTab3'/>
</div>
In step 3's code of part 1, cut and paste this code below right next to it.
var blog1 = "hoctro.blogspot.com";
var tabView1 = new YAHOO.widget.TabView('multiTab1');
var labels1 = ['JSON Hacks', 'Label Hacks','Free Templates'];
function listTab1(json) {
listOneTab(json, tabView1, "", false);
}
function listLatestPostsTab1(json) {
listOneTab(json, tabView1, "Latest Posts", true);
}
function listLatestCommentsTab1(json) {
listOneTab(json, tabView1, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog1, "posts", 1, 25, 'listLatestPostsTab1');
// Latest Comments
cb.search( blog1, "comments", 1, 25, 'listLatestCommentsTab1');
// Preferred Labels
for (var i=0; i < labels1.length; i++)
if (labels1[i]) cb.searchLabel(blog1, labels1[i], 'listTab1');
This is labor-intensive, as we want to duplicate everything from "1" to "3", or rename the blog, such as
blog1 -> blog3
hoctro.blogspot.com -> beautifulbeta.blogspot.com
tabView1 -> tabView3
multiTab1 -> multiTab3
labels1 -> labels3
and so on.
Below is my solution to that replacing process, with changed values in bold:
var blog3 = "beautifulbeta.blogspot.com";
var tabView3 = new YAHOO.widget.TabView('multiTab3');
var labels3 = ['hacks', 'tutorials','widgets', 'gadgets']; // These are Hans' labels.
function listTab3(json) {
listOneTab(json, tabView3, "", false);
}
function listLatestPostsTab3(json) {
listOneTab(json, tabView3, "Latest Posts", true);
}
function listLatestCommentsTab3(json) {
listOneTab(json, tabView3, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog3, "posts", 1, 25, 'listLatestPostsTab3');
// Latest Comments
cb.search( blog3, "comments", 1, 25, 'listLatestCommentsTab3');
// Preferred Labels
for (var i=0; i < labels3.length; i++)
if (labels3[i]) cb.searchLabel(blog3, labels3[i], 'listTab3');
I also just realize that the html code from step 2 can be placed anywhere, so I just moved my hoctro.blogspot.com tab view to the front of the blog's widget, and it works as expected.
That's all! Please give it a try.
Have a wonderful day.
Update:
* 24 May 07: A translation of this article to indonesian by Bikin is available here:
http://bikinblogger.blogspot.com/2007/05/tabview-widget-bagian-2.html
*26 May 07: Wai Yan Lin translated also part 1, 2 & fav blogs application to Burmese here:
http://waiyanlinn.blogspot.com/2007/05/tabview-widget.html
My next step in perfecting the TabView widget is to add two default tabs to show a blog's latest posts and comments. I also modify the code so that you can have multiple blogs shown in different views.
But first, a quick explanation on "commenting out" things from a Blogger template.
If you want to exclude a section of code inside the two <script> and </script>, you can either use // for a single line, or /* */ for multiple lines.
For template code outside Javascript such as html tags, use this notation instead <!-- -->
Now, to see the effect of multiple tab views, in step 3 from "Introducing TabView Widget - Part 1" tutorial, remove the <!-- in front of and --> after the bold code below so the code looks like this
<div>
<h2>Hoctro's Place</h2>
<div class='yui-navset' id='multiTab1'/>
</div>
<div>
<h2>Hackosphere</h2>
<div class='yui-navset' id='multiTab2'/>
</div>
and also near the end remove the /* in front of and and */ after the bold code below so the segment now looks like this:
// Preferred Labels
for (var i=0; i < labels1.length; i++)
if (labels1[i]) cb.searchLabel(blog1, labels1[i], 'listTab1');
var blog2 = "hackosphere.blogspot.com";
var tabView2 = new YAHOO.widget.TabView('multiTab2');
var labels2 = ['Neo','Widgets', "Blogger Power"];
function listTab2(json) {
listOneTab(json, tabView2, "", false);
}
function listLatestPostsTab2(json) {
listOneTab(json, tabView2, "Latest Posts", true);
}
function listLatestCommentsTab2(json) {
listOneTab(json, tabView2, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog2, "posts", 1, 25, 'listLatestPostsTab2');
// Latest Comments
cb.search( blog2, "comments", 1, 25, 'listLatestCommentsTab2');
// Preferred Labels
for (var i=0; i < labels2.length; i++)
if (labels2[i]) cb.searchLabel("hackosphere.blogspot.com", labels2[i], 'listTab2');
</script>
</b:includable>
</b:widget>
What you will see now is the appearance of another tab view, showing Hackosphere's latest posts, comments, and are watch list of interesting labels.
As you can see, I make it a little bit easier for you to have the ability to add a new tab view, simply by removing the comments. But the process to add a new view from scratch is quite involved, so you need to pay extra attention to make it right. I believe if you interested in reading this article, you already have enough knowledge to proceed. (I wish I can use the ultimate solution, that is writing a pseudocope class, but I have not enough experience to pass value such as json and array to a parameter by reference. So you have to live with the less convenient solution such as this.)
Adding a new tab view to the widget is a three step process, and I will carefully walk you through each step.
Step 1.
If you have not already installed the TabView widget, please do so.
We are adding yet another third view for the purpose of tracking latest development on Hans' Beautiful Beta blog, and it's going to involve a lot of cut-and-paste, modifying and also common sense. Let's name the id of the "div" that will store it as multiTab3.
Step 2: Adding the HTML code to house the title and tabview
This step allows you to configure the appearance of the tab views, either vertically, or as a 2 column table, or anything you like.
In step 3's code of part 1, cut and paste this code below right next to it.
<div>
<h2>Hoctro's Place</h2>
<div class='yui-navset' id='multiTab1'/>
</div>
then change h2 content and the id to become (in bold):
<div>
<h2>Beautiful Beta</h2>
<div class='yui-navset' id='multiTab3'/>
</div>
Step 3: Adding Javascript code to create a new view
In step 3's code of part 1, cut and paste this code below right next to it.
var blog1 = "hoctro.blogspot.com";
var tabView1 = new YAHOO.widget.TabView('multiTab1');
var labels1 = ['JSON Hacks', 'Label Hacks','Free Templates'];
function listTab1(json) {
listOneTab(json, tabView1, "", false);
}
function listLatestPostsTab1(json) {
listOneTab(json, tabView1, "Latest Posts", true);
}
function listLatestCommentsTab1(json) {
listOneTab(json, tabView1, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog1, "posts", 1, 25, 'listLatestPostsTab1');
// Latest Comments
cb.search( blog1, "comments", 1, 25, 'listLatestCommentsTab1');
// Preferred Labels
for (var i=0; i < labels1.length; i++)
if (labels1[i]) cb.searchLabel(blog1, labels1[i], 'listTab1');
This is labor-intensive, as we want to duplicate everything from "1" to "3", or rename the blog, such as
blog1 -> blog3
hoctro.blogspot.com -> beautifulbeta.blogspot.com
tabView1 -> tabView3
multiTab1 -> multiTab3
labels1 -> labels3
and so on.
Below is my solution to that replacing process, with changed values in bold:
var blog3 = "beautifulbeta.blogspot.com";
var tabView3 = new YAHOO.widget.TabView('multiTab3');
var labels3 = ['hacks', 'tutorials','widgets', 'gadgets']; // These are Hans' labels.
function listTab3(json) {
listOneTab(json, tabView3, "", false);
}
function listLatestPostsTab3(json) {
listOneTab(json, tabView3, "Latest Posts", true);
}
function listLatestCommentsTab3(json) {
listOneTab(json, tabView3, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog3, "posts", 1, 25, 'listLatestPostsTab3');
// Latest Comments
cb.search( blog3, "comments", 1, 25, 'listLatestCommentsTab3');
// Preferred Labels
for (var i=0; i < labels3.length; i++)
if (labels3[i]) cb.searchLabel(blog3, labels3[i], 'listTab3');
I also just realize that the html code from step 2 can be placed anywhere, so I just moved my hoctro.blogspot.com tab view to the front of the blog's widget, and it works as expected.
That's all! Please give it a try.
Have a wonderful day.
Update:
* 24 May 07: A translation of this article to indonesian by Bikin is available here:
http://bikinblogger.blogspot.com/2007/05/tabview-widget-bagian-2.html
*26 May 07: Wai Yan Lin translated also part 1, 2 & fav blogs application to Burmese here:
http://waiyanlinn.blogspot.com/2007/05/tabview-widget.html
Archived Post: a Widget to Show Thumbnail Pictures
Dear Friend,
I'm very proud to show you my original and truly first Blogger Beta Hack.
In a nutshell, the hack takes advantage of the Page Element's Link List and turns it into a Thumbnail Picture List element. As you might know, the link list allows the page owner to quickly add a bunch of urls for quick links to other interesting sites. My hack takes advantage of the GUI interface to quickly add/erase/arrange these links but pushes it further to upload image addresses instead.
Here are the steps to setup this hack. You are also required to know some HTML & CSS to further enhance this hack to make it your own unique version of it.
First, go to Template->Add Elements, then select sidebar's Add Page Elements. Select Link List option at top right corner:
Next, add some sample pictures:
Then, drag-n-drop the newly created link-list from sidebar to post body area. (You can always move it back later.)
Go to Template->Edit HTML. Make sure to check the Expand Widget Template check box. Then look for the LinkList1 widget. It should be in front of all the other widgets, and right after the CSS portion of the code.
Then replace that widget with this one, make sure they have the same name (LinkList1):
<b:widget id='LinkList1' locked='false' title='Random Pics' type='LinkList'>
<b:includable id='main'>
<b:if cond='data:title'><h2><data:title/></h2></b:if>
<div class='widget-content'>
<div class='hoctro_spacer'>
<b:loop values='data:links' var='link'>
<a expr:href='data:link.target' onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'><img alt='' border='0'
expr:src='data:link.target' height='100' style='display:inline; margin:0px auto 10px; ;cursor:pointer;' width='100'/></a>
</b:loop>
</div>
<b:include name='quickedit'/>
</div>
</b:includable>
</b:widget>
As you can see, I use the same code that Blogger provides when it successfully upload an image as a mean to show the image itself. You can use whatever it best fits your purpose.
<a expr:href='data:link.target'
onblur='try {parent.deselectBloggerImageGracefully();} catch(e) {}'>
<img alt='' border='0'
expr:src='data:link.target' height='100'
style='display:inline; margin:0px auto 10px; ;cursor:pointer;'
width='100'/>
</a>
Feel free to change this portion of code to anything you like. Just make sure the src and href parameters must be written as expr:src and expr:href respectively.
Hope you will enjoy this new hack.
Hoctro (9/2006)
Blog: http://hoctro.blogspot.com/
Archived Post: My First Blogger Template Attempt
Dear Friend,
I'm happy to announce my first hack that I improved based on the original hack from Hackosphere (http://hackosphere.blogspot.com/). Many thanks to Mr. Ramani for his hacking ability and his willingness to share with the rest of us.
My hack is based on his hack of showing the "titles only" if you click on a monthly or label listing. Instead of showing the content of all the posts, it'll only show the titles. My improved hack is based upon that by not even showing the date that a post is created, and I also make the posts indented as a nice bulleted list (that you can use CSS to change its appearance, btw.)
Below is the complete code of the hack. I also fixed the bug of the date not showing up in the Main Page / and the Main Page not lined up with the latest comments/posts - Thanks a bunch Vivek/ you're a great tester! pls see the line that is bold, and two other ul tags being commented out at front and back. (7 Sep 06)
Basically, you need to replace the <div id='blog-posts'> portion with the code above. Also, the original hack is here, please refer to it on how to hack the relevant portion.
I predict it's gonna be very much fun hacking Blogger, since the new way of hacking is very much like XSLT, the one I am already familiar with. It's actually much simpler than XSLT, as far as I can tell. I hope I will have many more hacks to share with you in the future.
Thanks for your time and have a nice day!
Hoctro (9/2006)
Blog: http://hoctro.blogspot.com/
I'm happy to announce my first hack that I improved based on the original hack from Hackosphere (http://hackosphere.blogspot.com/). Many thanks to Mr. Ramani for his hacking ability and his willingness to share with the rest of us.
My hack is based on his hack of showing the "titles only" if you click on a monthly or label listing. Instead of showing the content of all the posts, it'll only show the titles. My improved hack is based upon that by not even showing the date that a post is created, and I also make the posts indented as a nice bulleted list (that you can use CSS to change its appearance, btw.)
Below is the complete code of the hack. I also fixed the bug of the date not showing up in the Main Page / and the Main Page not lined up with the latest comments/posts - Thanks a bunch Vivek/ you're a great tester! pls see the line that is bold, and two other ul tags being commented out at front and back. (7 Sep 06)
<!-- posts -->
<!-- <ul>-->
<div id='blog-posts'>
<b:loop values='data:posts' var='post'>
<!--Improved hack from Hackosphere By: Hoctro http://hoctro.blogspot.com - 6 Sep 2006 -->
<!-- This hack allows posts to be shown without dates and as a bullet list -->
<b:if cond='data:post.dateHeader'>
<b:if cond='data:blog.pageType == "item"'>
<h2 class='date-header'><data:post.dateHeader/></h2>
</b:if>
<!--Fix Bug for not showing the date on main page - 7 Sep 2006 -->
<b:if cond='data:blog.homepageUrl == data:blog.url'>
<h2 class='date-header'><data:post.dateHeader/></h2>
</b:if>
</b:if>
<!--Hack by Hackosphere - 6 Sep 2006 -->
<b:if cond='data:blog.homepageUrl != data:blog.url'>
<b:if cond='data:blog.pageType != "item"'>
<ul><li><a expr:href='data:post.url'> <data:post.title/> </a></li></ul>
<b:else/>
<b:include data='post' name='post'/>
</b:if>
<b:else/>
<b:include data='post' name='post'/>
</b:if>
<!--End of Hack by Hackosphere - 6 Sep 2006 -->
<b:if cond='data:blog.pageType == "item"'>
<b:if cond='data:post.allowComments'>
<b:include data='post' name='comments'/>
</b:if>
</b:if>
<!--End of Improved hack from Hackosphere By: Hoctro -->
<!-- </ul>-->
</b:loop>
</div>
Basically, you need to replace the <div id='blog-posts'> portion with the code above. Also, the original hack is here, please refer to it on how to hack the relevant portion.
I predict it's gonna be very much fun hacking Blogger, since the new way of hacking is very much like XSLT, the one I am already familiar with. It's actually much simpler than XSLT, as far as I can tell. I hope I will have many more hacks to share with you in the future.
Thanks for your time and have a nice day!
Hoctro (9/2006)
Blog: http://hoctro.blogspot.com/
Archived Post: How To Modify the Blogger Template - The Core Javacript Library for JSON Widgets
This post explains how to make modifications to your New Blogger template, and also houses the latest Javascript JSON library code. This will make it easier for my others articles (and ultimately my readers) as those articles will be referring to this post on how to open the template and add new code.
I. Installing Steps
A. Accessing the "Template" tab
1. If you're from your blog, and you're logged in, click on "Customize"
2. If you're from one blog, and you want to alter the template of another blog, click on "Dashboard"
3. If you're already on "Dashboard", click on "Layout"
4. if you're already inside the Setting page, click on the "Template" tab
B. Change to "Edit HTML" page
To see the template, click on Edit HTML. By default, the template does not expose the internal structure of each widget, so what you see actually is the short form of it. This is indeed a great thing, since you can see quickly how the template is made up from, in textual form. You could also insert the complete widget code of my hack (as instructed in the referred tutorials) right from this collapsed mode.
1) Before you make any serious modifications, it's best to save a copy to your hard drive.
2) Later on, you could always upload a good template up, overriding the current template.
3) This is the toggle that switches between "collapsed" and "explanded widget templates" modes.
4) To insert a new widget, enter the code inside the pair of "b:section" tags with id='sidebar', anywhere in between any two singly "b:widget" lines. Later on, once the code is accepted, it's very easy to visually drag the widget from one place to another, in "Page Element" view.
C. To add CSS or JavaScript code:
1) The preferred place to add CSS code is right in front of the closing b:skin tag
2) The preferred place to add JavaScript code is right between the closing b:skin tag and the closing head tag.
Also, if the hack is labeled as a "JSON Hack", make sure your feed setting is either "short" or "full", but not "None". Let me elaborate on this one:
a. Make sure your feed settings look like this:
b. and not like this:
Also, make sure in "Settings"->"Archiving", "Enable Post Pages?" is set to "Yes"
II. Installing the core Javacript library object
This is the only location where the Core Library will be posted. The reason I do this instead of making a link line to an external js file is because I don't want my users to have a bad feeling of not sure what's going on with the js. I want you to be in control on when you decide to update your existing library version with this latest code.
You only need to place the code below once in your template, as the code is going to be shared among the calling widgets such as TabView, Unlimited Posts, and Unlimited Comments.
Cut and paste the code and paste it between the closing </b:skin> tag and the closing </head> tag :
<script type='text/javascript'>
// Developed by Hoctro - All rights reserved 2007
// This credit must be included in all your derived usages.
// "cb" is intended to be a common library, where different widgets would
// utitlize the shared operations such as getTitle, getLink, etc. from a json object.
var cb = {
// search function requires these parameters:
// 1. query: a blogger address, such as "hoctro.blogspot.com",
// 2. type: type of return data, either "comments" or "posts",
// 3. start: the start-index parameter (where to start extracting data)
// 4. increment: the number of elements the json will get back. (the smaller value, the faster time to travel back)
// 5. func: the returned function the json object will feed.
search: function(query, type, start, increment, func) {
var script = document.createElement('script');
script.setAttribute('src', 'http://' + query + '/feeds/' + type + '/default?alt=json-in-script&start-index='
+ start + '&max-results=' + increment + '&callback=' + func + '&orderby=published');
script.setAttribute('type', 'text/javascript');
document.documentElement.firstChild.appendChild(script);
},
// searchLabel function return a result of posts w/ a label query
// it requires these parameters:
// 1. query: a blogger address, such as "hoctro.blogspot.com",
// 2. an array of labels
// 3. func: the returned function the json object will feed.
searchLabel: function(query, label, func) {
var script = document.createElement('script');
script.setAttribute('src', 'http://' + query + '/feeds/posts/default/-/' + encodeURIComponent(label) +
'?alt=json-in-script&callback=' + func + '&orderby=published');
script.setAttribute('type', 'text/javascript');
document.documentElement.firstChild.appendChild(script);
},
// getTotalResults needs the json object, and it'll return the total number of comments (or posts) of the blog.
getTotalResults: function(json) {
return json.feed.openSearch$totalResults.$t;
},
// getStartIndex gets the start index of a search inside an json object.
getStartIndex: function(json) {
return json.feed.openSearch$startIndex.$t;
},
// getLink return a href link if "name" matches the content inside "a" tags) of the link
getLink: function(entry, name) {
var alturl;
for (var k = 0; k < entry.link.length; k++) {
if (entry.link[k].rel == name)
alturl = entry.link[k].href;
}
return alturl;
},
// getTitle gets the title of the title of an entry of a json object.
getTitle: function(entry) {
return entry.title.$t;
},
// getContent gets the content inside an entry of a json object.
getContent: function(entry) {
return entry.content.$t;
},
// getCommentAuthor: gets the commenter name inside an entry of a json object.
getCommentAuthor: function(entry) {
return entry.author[0].name.$t;
},
// Given a json label search, this function return the decoded label.
getLabelFromURL: function(json) {
for (var l = 0; l < json.feed.link.length; l++) {
if (json.feed.link[l].rel == 'alternate') {
var raw = json.feed.link[l].href;
// The next two lines are borrowed from Ramani's Neo Template
// code. Thanks Ramani!
var label = raw.substr(raw.lastIndexOf('/')+1);
return decodeURIComponent(label);
}
}
},
txt : function (s) {
return s + " Widget by <a href='http://hoctro.blogspot.com" + "'>Hoctro</a>";
}
};
</script>
Thank you for reading.
Archived Post: Tab View
Dear Friend,
Now that I have the new framework for making widgets in store, I feel confident and start trying to create a new tab widget - using labels as tabs, similar to this Yahoo! widget.
With the wonderful help of Yahoo! TabView widget, the programming time reduces quite a bit.
You can see the result from my homepage:
If you want to install this onto your blog, follow these instructions.
Step 1: Installing the core Javacript library object
First, follow the instructions from this article Hacking Technique: How To Modify a (Beta) Template, in particular section C.2 (for step 1 & 2) and B.4 (for step 3).
Next, install the latest version of the Javacsript Core Library.
Save the template.
Step 2: Installing Yahoo! Tab View requirements
Cut and paste this code below right after step 1's code (such that these code still stay before the closing </head> tag.). See instruction here if you're still not sure.
<link href='http://yui.yahooapis.com/2.3.0/build/tabview/assets/tabview.css' rel='stylesheet' type='text/css'/>
<link href='http://yui.yahooapis.com/2.3.0/build/tabview/assets/border_tabs.css' rel='stylesheet' type='text/css'/>
<script src='http://yui.yahooapis.com/2.3.0/build/yahoo-dom-event/yahoo-dom-event.js' type='text/javascript'/>
<script src='http://yui.yahooapis.com/2.3.0/build/element/element-beta-min.js' type='text/javascript'/>
<script src='http://yui.yahooapis.com/2.3.0/build/tabview/tabview-min.js' type='text/javascript'/>
<style type='text/css'>
.yui-content {
padding:1em; /* pad content container */
}
.yui-navset .yui-content {
border:1px solid #ccc;
}
.yui-navset .yui-nav .selected a, .yui-navset .yui-nav a:hover {
background-color:#fff;
}
.yui-navset .yui-nav li a {
background:#e5e5e5 url(http://developer.yahoo.com/yui/examples/tabview/img/round_4px_trans_gray.gif) no-repeat;
}
.yui-navset .yui-nav li a em {
background:transparent url(http://developer.yahoo.com/yui/examples/tabview/img/round_4px_trans_gray.gif) no-repeat top right;
padding:0.5em;
}
/* top oriented */
.yui-navset-top .yui-nav { margin-bottom:-1px; } /* for overlap, based on content border-width */
.yui-navset-top .yui-nav li a {
border-bottom:1px solid #ccc;
}
.yui-navset-top .yui-nav .selected a { border-bottom:0; }
.yui-navset-top .yui-nav .selected a em { padding-bottom:0.6em; } /* adjust height */
</style>
Save the template.
Step 3: Installing the widget
Add this code between any two "b:widget" tags, save the template, and you're almost done.
<b:widget id='HTML102' locked='false' title='MultiTab Widget' type='HTML'>
<b:includable id='main'>
<div class='widget-content'>
<!-- only display title if it's non-empty -->
<b:if cond='data:title != ""'>
<h2 class='title'
></h2>
</b:if>
<div id='doc'>
<div>
<h2>Hoctro's Place</h2>
<div class='yui-navset' id='multiTab1'/>
</div>
<!--
<div>
<h2>Hackosphere</h2>
<div class='yui-navset' id='multiTab2'/>
</div>
-->
</div>
<div id='103'/>
</div>
<script type='text/javascript'>
// Developed by Hoctro - All rights reserved 2007
// This credit must be included in all your derived usages.
var p1 = document.createElement('h6');
document.getElementById('103').appendChild(p1);
p1.innerHTML = cb.txt('TabView');
function listOneTab(json, tabView, title, act) {
var label = '';
var text = '';
var nPost = 10;
if (title == "")
label += cb.getLabelFromURL(json);
else
label += title;
text += "<div id='" + label + "'><ul>";
var numberPost = (json.feed.entry.length <= nPost) ?
json.feed.entry.length : nPost;
for (var i = 0; i < numberPost; i++) {
var entry = json.feed.entry[i];
text += "<li>" + "<a href='" + cb.getLink(entry, "alternate")
+ "'>" + cb.getTitle(entry) + "</li>";
}
text += '</ul></div>';
tabView.addTab( new YAHOO.widget.Tab({
label: label,
content: text,
active : act
}));
}
var blog1 = "hoctro.blogspot.com";
var tabView1 = new YAHOO.widget.TabView('multiTab1');
var labels1 = ['JSON Hacks', 'Label Hacks','Free Templates'];
function listTab1(json) {
listOneTab(json, tabView1, "", false);
}
function listLatestPostsTab1(json) {
listOneTab(json, tabView1, "Latest Posts", true);
}
function listLatestCommentsTab1(json) {
listOneTab(json, tabView1, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog1, "posts", 1, 25, 'listLatestPostsTab1');
// Latest Comments
cb.search( blog1, "comments", 1, 25, 'listLatestCommentsTab1');
// Preferred Labels
for (var i=0; i < labels1.length; i++)
if (labels1[i]) cb.searchLabel(blog1, labels1[i], 'listTab1');
/*
var blog2 = "hackosphere.blogspot.com";
var tabView2 = new YAHOO.widget.TabView('multiTab2');
var labels2 = ['Neo','Widgets', "Blogger Power"];
function listTab2(json) {
listOneTab(json, tabView2, "", false);
}
function listLatestPostsTab2(json) {
listOneTab(json, tabView2, "Latest Posts", true);
}
function listLatestCommentsTab2(json) {
listOneTab(json, tabView2, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog2, "posts", 1, 25, 'listLatestPostsTab2');
// Latest Comments
cb.search( blog2, "comments", 1, 25, 'listLatestCommentsTab2');
// Preferred Labels
for (var i=0; i < labels2.length; i++)
if (labels2[i]) cb.searchLabel("hackosphere.blogspot.com", labels2[i], 'listTab2');
*/
</script>
</b:includable>
</b:widget>
Save the template.
After you install the above three easy steps, just change these things found in step 3' code:
a. To change the title, look for this line:
<h2>Hoctro's Place</h2>
b. modify the label tabs to become yours:
var labels1 = ["JSON Hacks", "Label Hacks",
"Free Templates", "Notable Hacks"];
c. Change value below from 10 to any value you want for the maximum of posts per tab
var nPost = 10;
d. then replace mine with your blog's name
blog1 = "hoctro.blogspot.com";
For advanced bloggers who would like to manipulate the CSS, "step 2" contains the information to do so. Also consult the Yahoo! TabView widget tutorials and examples for other variations of these tab options.
To add another tabview to this widget such as the picture below, please see part 2.
Until next time.
Update:
* 24 May 07: A translation of this article to Indonesian by Bikin is available here:
http://bikinblogger.blogspot.com/2007/05/tabview-widget-pengantar.html
*26 May 07: Wai Yan Lin translated also part 1, 2 & fav blogs application to Burmese here:
http://waiyanlinn.blogspot.com/2007/05/tabview-widget.html
Now that I have the new framework for making widgets in store, I feel confident and start trying to create a new tab widget - using labels as tabs, similar to this Yahoo! widget.
With the wonderful help of Yahoo! TabView widget, the programming time reduces quite a bit.
You can see the result from my homepage:
If you want to install this onto your blog, follow these instructions.
Step 1: Installing the core Javacript library object
First, follow the instructions from this article Hacking Technique: How To Modify a (Beta) Template, in particular section C.2 (for step 1 & 2) and B.4 (for step 3).
Next, install the latest version of the Javacsript Core Library.
Save the template.
Step 2: Installing Yahoo! Tab View requirements
Cut and paste this code below right after step 1's code (such that these code still stay before the closing </head> tag.). See instruction here if you're still not sure.
<link href='http://yui.yahooapis.com/2.3.0/build/tabview/assets/tabview.css' rel='stylesheet' type='text/css'/>
<link href='http://yui.yahooapis.com/2.3.0/build/tabview/assets/border_tabs.css' rel='stylesheet' type='text/css'/>
<script src='http://yui.yahooapis.com/2.3.0/build/yahoo-dom-event/yahoo-dom-event.js' type='text/javascript'/>
<script src='http://yui.yahooapis.com/2.3.0/build/element/element-beta-min.js' type='text/javascript'/>
<script src='http://yui.yahooapis.com/2.3.0/build/tabview/tabview-min.js' type='text/javascript'/>
<style type='text/css'>
.yui-content {
padding:1em; /* pad content container */
}
.yui-navset .yui-content {
border:1px solid #ccc;
}
.yui-navset .yui-nav .selected a, .yui-navset .yui-nav a:hover {
background-color:#fff;
}
.yui-navset .yui-nav li a {
background:#e5e5e5 url(http://developer.yahoo.com/yui/examples/tabview/img/round_4px_trans_gray.gif) no-repeat;
}
.yui-navset .yui-nav li a em {
background:transparent url(http://developer.yahoo.com/yui/examples/tabview/img/round_4px_trans_gray.gif) no-repeat top right;
padding:0.5em;
}
/* top oriented */
.yui-navset-top .yui-nav { margin-bottom:-1px; } /* for overlap, based on content border-width */
.yui-navset-top .yui-nav li a {
border-bottom:1px solid #ccc;
}
.yui-navset-top .yui-nav .selected a { border-bottom:0; }
.yui-navset-top .yui-nav .selected a em { padding-bottom:0.6em; } /* adjust height */
</style>
Save the template.
Step 3: Installing the widget
Add this code between any two "b:widget" tags, save the template, and you're almost done.
<b:widget id='HTML102' locked='false' title='MultiTab Widget' type='HTML'>
<b:includable id='main'>
<div class='widget-content'>
<!-- only display title if it's non-empty -->
<b:if cond='data:title != ""'>
<h2 class='title'
>
</b:if>
<div id='doc'>
<div>
<h2>Hoctro's Place</h2>
<div class='yui-navset' id='multiTab1'/>
</div>
<!--
<div>
<h2>Hackosphere</h2>
<div class='yui-navset' id='multiTab2'/>
</div>
-->
</div>
<div id='103'/>
</div>
<script type='text/javascript'>
// Developed by Hoctro - All rights reserved 2007
// This credit must be included in all your derived usages.
var p1 = document.createElement('h6');
document.getElementById('103').appendChild(p1);
p1.innerHTML = cb.txt('TabView');
function listOneTab(json, tabView, title, act) {
var label = '';
var text = '';
var nPost = 10;
if (title == "")
label += cb.getLabelFromURL(json);
else
label += title;
text += "<div id='" + label + "'><ul>";
var numberPost = (json.feed.entry.length <= nPost) ?
json.feed.entry.length : nPost;
for (var i = 0; i < numberPost; i++) {
var entry = json.feed.entry[i];
text += "<li>" + "<a href='" + cb.getLink(entry, "alternate")
+ "'>" + cb.getTitle(entry) + "</li>";
}
text += '</ul></div>';
tabView.addTab( new YAHOO.widget.Tab({
label: label,
content: text,
active : act
}));
}
var blog1 = "hoctro.blogspot.com";
var tabView1 = new YAHOO.widget.TabView('multiTab1');
var labels1 = ['JSON Hacks', 'Label Hacks','Free Templates'];
function listTab1(json) {
listOneTab(json, tabView1, "", false);
}
function listLatestPostsTab1(json) {
listOneTab(json, tabView1, "Latest Posts", true);
}
function listLatestCommentsTab1(json) {
listOneTab(json, tabView1, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog1, "posts", 1, 25, 'listLatestPostsTab1');
// Latest Comments
cb.search( blog1, "comments", 1, 25, 'listLatestCommentsTab1');
// Preferred Labels
for (var i=0; i < labels1.length; i++)
if (labels1[i]) cb.searchLabel(blog1, labels1[i], 'listTab1');
/*
var blog2 = "hackosphere.blogspot.com";
var tabView2 = new YAHOO.widget.TabView('multiTab2');
var labels2 = ['Neo','Widgets', "Blogger Power"];
function listTab2(json) {
listOneTab(json, tabView2, "", false);
}
function listLatestPostsTab2(json) {
listOneTab(json, tabView2, "Latest Posts", true);
}
function listLatestCommentsTab2(json) {
listOneTab(json, tabView2, "Latest Comments", false);
}
// Activating calls!
// Latest Posts
cb.search( blog2, "posts", 1, 25, 'listLatestPostsTab2');
// Latest Comments
cb.search( blog2, "comments", 1, 25, 'listLatestCommentsTab2');
// Preferred Labels
for (var i=0; i < labels2.length; i++)
if (labels2[i]) cb.searchLabel("hackosphere.blogspot.com", labels2[i], 'listTab2');
*/
</script>
</b:includable>
</b:widget>
Save the template.
After you install the above three easy steps, just change these things found in step 3' code:
a. To change the title, look for this line:
<h2>Hoctro's Place</h2>
b. modify the label tabs to become yours:
var labels1 = ["JSON Hacks", "Label Hacks",
"Free Templates", "Notable Hacks"];
c. Change value below from 10 to any value you want for the maximum of posts per tab
var nPost = 10;
d. then replace mine with your blog's name
blog1 = "hoctro.blogspot.com";
For advanced bloggers who would like to manipulate the CSS, "step 2" contains the information to do so. Also consult the Yahoo! TabView widget tutorials and examples for other variations of these tab options.
To add another tabview to this widget such as the picture below, please see part 2.
Until next time.
Update:
* 24 May 07: A translation of this article to Indonesian by Bikin is available here:
http://bikinblogger.blogspot.com/2007/05/tabview-widget-pengantar.html
*26 May 07: Wai Yan Lin translated also part 1, 2 & fav blogs application to Burmese here:
http://waiyanlinn.blogspot.com/2007/05/tabview-widget.html
Archived Post: Some small tricks
Dear Friend,
This post is a collection of all the little tweaks I've learned thoughout my last 5-month experience with the (then) Blogger in Beta, and now the New Blogger. Some I've learned from the Blogger tutorial, some from the other hackers, and some from reading the template. I think it would be useful for certain people. I'll update this post as needed. Thanks.
Question #1: What is the URL to get 99 latest posts?
Answer:
Have a linklist widget, and put this URL as the link (replacing "hoctro" with your blog's name):
http://hoctro.blogspot.com/search/label/?max-results=99
Question #2: How to get 99 latest posts by clicking on an item of the "label" widget?
Answer:
You need to open the template in expanded mode, then first look for this line:
<b:widget id='Label1' locked='false' title='Labels' type='Label'>
then look for this line about 10+ lines below it
<a expr:href='data:label.url'><data:label.name/></a>
change that to this
<a expr:href='data:label.url + "?max-results=99"'><data:label.name/></a>
Question #3: I can't drag a widget to my header. How do I make it appendable, just like on the sidebar?
Answer:
From dashboard, go to Layout->Template->Edit HTML and look for this line:
<b:section class='header' id='header' maxwidgets='1' showaddelement='no'>
You need to change it to:
<b:section class='header' id='header' maxwidgets='10' showaddelement='yes'>
Now you can add 9 more widgets to your header, besides the default header itself.
Question #4: How do I change the title of the blog with a banner?
This below example is for the Minima template
1. Go to Edit Html page, collapsed mode, look for the line:
#header-wrapper
then replace that rule and one next to it to look like this:
#header-wrapper {
width:57.69em;
*width:56.3em; /* IE */
min-width:750px;
margin:0 auto 10px;
//border:1px solid $bordercolor;
min-height:200px;
background:url("http://lh6.google.com/_h/5xBoc/s1600/baby.jpg") no-repeat left top;
}
#header {
margin: 5px;
//border: 1px solid $bordercolor;
text-align: center;
display: none;
}
The URL you see there - in bold - is the address of the picture. You could use Blogger to upload a picture, click on it to view the real size, then right click->properties to cut the URL from there.
Below is the discussion on some other tweaks made to make things look right:
1. For #header-wrapper
min-width:750px; - the minimum width shown would be 750px - you should set this to your picture size.
//border:1px solid $bordercolor; - // means commenting things out, in this case we don't want to show the box around the text
min-height:200px; - the minimum height shown would be 200px - you should set this to your picture height size.
2. For #header
//border: 1px solid $bordercolor; - leave out the inner box.
display: none; - not to display header texts by commenting them out.
Getting to know your readers through FeedBurner
Dear Friend,
As some of you might have noticed, recently I have a new feed - courtesy of Feedburner - from my sidebar that says: Subscribe in a reader. To be honest with you, I didn't see the purpose of having yet another feed, besides the default one we all have from Blogger (mine is http://hoctro.blogpost.com/feeds/posts/default .) But a recent feature from FeedBurner makes it all worthwhile. Feedburner now allows you to see who is coming to your site, what are they interested in reading, so on and so forth.
To start with, you need to go to their site:
http://www.feedburner.com/fb/a/home
Next, register an account with FeedBurner by clicking on the "Register" at the top right of its homepage:
Once you're done with registration, you'll be greeted with the Dashboard. Next, you need to enter your blog address in the box, and follow the instructions.
This is my dashboard's look at the moment, after Hoctro's Place is added:
After clicking on your feed's title, the "Analyze" tab is opened. Next, click on "Standard Stats", under "Services" on the left sidebar. The Standard Stats settings appear. In the "Choose One" dropdown, select Blogger:
A tutorial opens in a new popup window, you need to follow exactly what it says:
Essentially, what you have to do is to embed a piece of javascript code to your template, under the Blog widget, so FeedBurner could collect data on your blog.
Once you successfully embedded the code, leave it there for a couple of days, and you'll be able to see collected data later in a nice and easy-to-understand manner, through the newly added "Site stats" submenu. For example, from the Dashboard option, I know how many people visit my blog today, and what are the most popular posts:
There's a lot more in store, so if you have time, then register and see for yourself. You'll be amazed at the wealth of information FeedBurner could offer.
Have a wonderful day,
Hoctro
As some of you might have noticed, recently I have a new feed - courtesy of Feedburner - from my sidebar that says: Subscribe in a reader. To be honest with you, I didn't see the purpose of having yet another feed, besides the default one we all have from Blogger (mine is http://hoctro.blogpost.com/feeds/posts/default .) But a recent feature from FeedBurner makes it all worthwhile. Feedburner now allows you to see who is coming to your site, what are they interested in reading, so on and so forth.
To start with, you need to go to their site:
http://www.feedburner.com/fb/a/home
Next, register an account with FeedBurner by clicking on the "Register" at the top right of its homepage:
Once you're done with registration, you'll be greeted with the Dashboard. Next, you need to enter your blog address in the box, and follow the instructions.
This is my dashboard's look at the moment, after Hoctro's Place is added:
After clicking on your feed's title, the "Analyze" tab is opened. Next, click on "Standard Stats", under "Services" on the left sidebar. The Standard Stats settings appear. In the "Choose One" dropdown, select Blogger:
A tutorial opens in a new popup window, you need to follow exactly what it says:
Essentially, what you have to do is to embed a piece of javascript code to your template, under the Blog widget, so FeedBurner could collect data on your blog.
Once you successfully embedded the code, leave it there for a couple of days, and you'll be able to see collected data later in a nice and easy-to-understand manner, through the newly added "Site stats" submenu. For example, from the Dashboard option, I know how many people visit my blog today, and what are the most popular posts:
There's a lot more in store, so if you have time, then register and see for yourself. You'll be amazed at the wealth of information FeedBurner could offer.
Have a wonderful day,
Hoctro
Corrrecting Anchoring Tags
Dear Friend,
Every one of my posts has a story with it, whether it is a request from an user, or a need of myself to tweak something to look more interesting or at least to make it right. This time is no different :)
Some of my readers will notice that I just recently abandon the comment approval option. You could post a comment, and will see it instantly. Well, that comes with a price. I have to monitor the Latest Comments Feed more often, or my blog will be bombarding with spamming comments.
One of the things I notice, because of this new change-of-mind, is that the comment link only sends me to the top of the post. However, I know that in HTML you could have a tag with an unique name and the link will lead to the right place. Come to find out, the link is correctly formatted, such as this:
http://hoctro.blogspot.com/2006/share.html#3190550298489538229
but the actual HTML code in the content of the comment looks like this
<a name='comment-3190550298489538229'></a>
where it should be coded as
<a name='3190550298489538229'></a>
Looks like the right hand doesn't talk to the left hand, or in this case the person who codes the post widget doen't talk to the guy who codes the feed widget. Just kidding, we love you Blogger guys, really!!!
Now that I know what to fix, I need to find where to fix. After a while, I find the culprit :-)
If you want to fix this problem too, then follow these steps:
1. Open Template->Edit HTML. Turn the option "Expand Widget Templates" on.
2a. Locate the widget named Blog1, by looking for this line:
<b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'>
2b. Locate this line (a function[includable]) with id='comments'
<b:includable id='comments' var='post'>
2c. Look for this line about 10+ lines below:
<a expr:name='"comment-" + data:comment.id'/>
and just simply take out the ["comment-" + ] for the line to become:
<a expr:name='data:comment.id'/>
and you're done.
You can see a sample by clicking on any "latest comment" in my blog's feed (or try this one out, it goes to the end of my "killer post") and it'll take you right to where the comment is located. Now I can check out the users' comment more effectively.
Cheers,
Hoctro
Every one of my posts has a story with it, whether it is a request from an user, or a need of myself to tweak something to look more interesting or at least to make it right. This time is no different :)
Some of my readers will notice that I just recently abandon the comment approval option. You could post a comment, and will see it instantly. Well, that comes with a price. I have to monitor the Latest Comments Feed more often, or my blog will be bombarding with spamming comments.
One of the things I notice, because of this new change-of-mind, is that the comment link only sends me to the top of the post. However, I know that in HTML you could have a tag with an unique name and the link will lead to the right place. Come to find out, the link is correctly formatted, such as this:
http://hoctro.blogspot.com/2006/share.html#3190550298489538229
but the actual HTML code in the content of the comment looks like this
<a name='comment-3190550298489538229'></a>
where it should be coded as
<a name='3190550298489538229'></a>
Looks like the right hand doesn't talk to the left hand, or in this case the person who codes the post widget doen't talk to the guy who codes the feed widget. Just kidding, we love you Blogger guys, really!!!
Now that I know what to fix, I need to find where to fix. After a while, I find the culprit :-)
If you want to fix this problem too, then follow these steps:
1. Open Template->Edit HTML. Turn the option "Expand Widget Templates" on.
2a. Locate the widget named Blog1, by looking for this line:
<b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'>
2b. Locate this line (a function[includable]) with id='comments'
<b:includable id='comments' var='post'>
2c. Look for this line about 10+ lines below:
<a expr:name='"comment-" + data:comment.id'/>
and just simply take out the ["comment-" + ] for the line to become:
<a expr:name='data:comment.id'/>
and you're done.
You can see a sample by clicking on any "latest comment" in my blog's feed (or try this one out, it goes to the end of my "killer post") and it'll take you right to where the comment is located. Now I can check out the users' comment more effectively.
Cheers,
Hoctro
To Show or not to Show your template message
Dear Friend,
Phoenix, one of my readers, noticed that there is some sort of a message bar showing, whenever he clicks on one of the "Label" search. I noticed that too, and knowing Beta code, I thought they must have embedded this new piece of code somewhere on the Blog1 widget.
Indeed it does, and this new feature only happens to blogs that are created recently. I think this is some sort of a "wrapped-up" feature as part of their "Blogger Beta: Feature Complete!".
Here it is, the single function call which causes the message to display:
So you see, the line is inside the Blog1 widget, under the "main" includable. Turning it off is quite simple if you want to. You can either erase the line or put a pair of comment code like so:
<!-- <b:include data='top' name='status-message'/> -->
and the message will disappear from then on.
Cheers,
Hoctro
Update: Please see the comments of this post to have more info on this Beta's message usage. Thanks a bunch, Phydeaux3 & Bravery Onions!
Showing Hint under the Title to View a Page With Comments
Dear Friend,
My friend Carlos asks me how to let readers to see posts with comments. I think this is not possible while a viewer is seeing a label or archived query, or if he or she is looking at the home page. I guess the technical reason why Blogger in Beta didn't implement that, is just simply try to avoid a potentially large stream of data to arrive to the viewer's PC. Imagine a situation where you query a category that has 20 posts in each, each post with 20-30 comments. It'll take quite a while to display that page to your screen.
My work-around to this would be to give a hint to the reader to click on the title of the post in order for him or her to read both the full post and the comments.
If you like this solution, then follow these simple steps:
1. Locate the Blog1 widget
<b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'>
then the includable named "post"
<b:includable id='post' var='post'>
2. Insert the seven lines in bold to the code. What this does is to check if you're allowing comment for a post, your post has at least one comment ( !=0 ), and you are not on the full post (item) page, then insert the hint. Feel free to use your HTML expertise to alter the simple tags I have, or change the text to become clearer.
<b:includable id='post' var='post'>
<div class='post uncustomized-post-template'>
<a expr:name='data:post.id'/>
<b:if cond='data:post.title'>
<h3 class='post-title'>
<b:if cond='data:post.url'>
<a expr:href='data:post.url'><data:post.title/></a>
<b:else/>
<data:post.title/>
</b:if>
</h3>
<b:if cond='data:post.allowComments'>
<b:if cond='data:post.numComments != 0'>
<b:if cond='data:blog.pageType != "item"'>
<div><i>(For full text with comments please click on the title)</i></div>
</b:if>
</b:if>
</b:if>
</b:if>
I apply this fix to my webpage, so you can see how this works.
Have a wonderful day,
Hoctro
Blogger Hack: Adding Introductions
Dear Friend,
Sometimes a little introductory paragraph or two helps "break the ice" between you and your readers, so they know what they are about to read, rather than just guessing based on one or two "label" words. You can see the new hack in effect on my site. Select on "Blogger Beta"->"My Hacks", for example, will display a little introduction first, then all the hack articles.
Below are the steps on how to implement this hack. As usual, make a template backup copy, then try it on your test blog first. Also, remember to check on "Expand Widget Templates."
Step 1: Add "introduction" function to Blog1 widget
First, locate the widget by looking for this line:
<b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'>
Once you see it, look for this line:
<b:includable id='main' var='top'>
Then paste this code right in front of it:
<b:includable id='sub-introduction' var='data:posts'>
<!-- **Introduction Hack - by Hoctro 10/2006 hoctro.blogspot.com ** Step 1 **
**** -->
<b:if cond='data:blog.pageType != "item"'>
<b:loop values='data:posts' var='post'>
<!-- Check for Homepage case -->
<b:if cond='data:blog.url == data:blog.homepageUrl'>
<b:if cond='data:post.title == "Introduction"'>
<div class='post'>
<div class='post-body'>
<p><data:post.body/></p>
</div>
</div>
</b:if>
</b:if>
<!-- Check for matched labels -->
<b:loop values='data:post.labels' var='label'>
<b:if cond='data:post.title == data:label.name'>
<div class='post'>
<div class='post-body'>
<p><data:post.body/></p>
</div>
</div>
</b:if>
</b:loop>
</b:loop>
</b:if>
</b:includable>
Step 2: Modify the main includable of Blog1 widget
Scroll down to this line again,
<b:includable id='main' var='top'>
then look for the portion of code that starts and ends with these lines,
<div id='blog-posts'>
...
<!-- navigation -->
<b:include name='nextprev'/>
You are going to replace everything in between with these lines,
<!-- **Introduction Hack - by Hoctro 10/2006 hoctro.blogspot.com ** Step 2 **
**** -->
<b:include name='sub-introduction' values='data:posts'/>
<b:loop values='data:posts' var='post'>
<b:if cond='data:post.title == "Introduction"'>
<b:if cond='data:blog.pageType == "item"'>
<b:include data='post' name='postQuickEdit'/>
<b:include data='post' name='post'/>
</b:if>
<b:else/>
<b:if cond='data:post.dateHeader'>
<h2 class='date-header'><data:post.dateHeader/></h2>
</b:if>
<b:include data='post' name='postQuickEdit'/>
<b:include data='post' name='post'/>
<b:if cond='data:blog.pageType == "item"'>
<b:if cond='data:post.allowComments'>
<b:include data='post' name='comments'/>
</b:if>
</b:if>
</b:if>
</b:loop>
</div>
Step 3: Name your new introductory posts with "special" titles
Name your "special" new introductory posts' titles with exactly the same label names. for example, for the introductory post of "My Hack" to show correctly on my homepage, I had to name the title as "Blogger_Beta*My_Hacks" (I use my own's two level tab hack, hence the star (*) symbol in the middle) Also, after composing this special post, you need to change the date to some time in the past, so it will not show up as the latest. Also, if your introductory post has more than one label (which you shouldn't do,) make sure the last label is the same as the post's title.
here is the result,
For an introduction in your homepage, you will need something different. You need to create a post with the title "Introduction", do not assign a label (leave it blank), and set the date to a distant future! (I owe Hans from "Beautiful Beta" for this "set-in-a-future-date", by the way. Thanks! Hans.) This will make sure the post always includes in the homepage's post collection, thus it will show up. When displayed, this post will not show a title nor allow any comment from the readers.
Here is the result,
That's all it takes to have introductory paragraphs to show up on your blog. I hope you will able to make use of this hack.
Technical Comments:
Below are my technical comments, explaining the hack's logic. If you are interested in then read on. You're not required to understand my explanations to make it work on your blog.
1. I'm glad I am finally able to write another hack without the help of JavaScript. There is nothing wrong with JavaScript, it's just that stretching beta's own simple language is really fun. Indeed, beta's template doesn't need any Javascript at all, and it still looks great.
2. In Step 1: the "introduction" function, I create a loop, thus in effect make Blog1 loops through its post collection twice. That's how the introductory post can bubble up to be the first in the list. Inside the loop, I have two cases:
-If the reader is at homepage, then check to see if one of the post has the title of "Introduction." If so, prints the body only. This post must not have a label assigned.
- Next, I create another loop to go thru all the labels, and if one of them match the post's title, then also prints the body.
3. In Step 2, the goal is completely different. We want the introduction not to show up twice, yet at the same time it must be visible in the item page, if someone clicks on it from the archived list, hence the if-then-else structure.
I hope you will find some good use of both the hack and its source code as well.
Have a wonderful day.
Hoctro
(10/8/2006)
How to add a new CSS parameter to your Blogger template
Dear Friend,
Cecilia left a comment asking me if I know anything about changing the default background of the blog. As usual, I go looking for answers in several of my CSS books (Bulletproof Web Design, CSS CookBook, Eric Meyer on CSS, etc.) For this one, the answer is right on Chapter 1 of the "Bulletproof Web Design" book. So here it is, if you have one of the Minima designs, please alter the equivalent tags of the template's CSS portion like this:
body {
/*background:$bgcolor;*/
margin:0;
color:$textcolor;
font:x-small Georgia Serif;
font-size/* */:/**/small;
font-size: /**/small;
text-align: center;
background: $bgcolor url(http://photos1.blogger.com/blogger2/7873/821550570340913/1600/bg.gif) repeat-x top left;
}
/* Header
-----------------------------------------------
*/
#header-wrapper {
width:660px;
margin:0 auto 10px;
border-bottom:1px solid $bordercolor;
}
#header {
margin: 5px;
/*border: 1px solid $bordercolor;*/ text-align: center;
color:$pagetitlecolor;
}
/* Outer-Wrapper
----------------------------------------------- */
#outer-wrapper {
width: 660px;
margin:0 auto;
padding:10px;
text-align:left;
border: 1px solid $bordercolor;
font: $bodyfont;
background: #fff;
}
Discussion:
* In CSS, if you want some effects to be temporary disabled, use this /* xxxxxx */ format. Notice that a comment inside another comment is not acceptable, such as
/* xxx /* xxxxxx */ xxx */
*This line, in particular, adds a faded yellow picture to the top-left of the screen, and repeats that picture in the horizontal (x) direction.
background: $bgcolor url(http://photos1.blogger.com/blogger2/7873/821550570340913/1600/bg.gif) repeat-x top left;
* In addition, I tweak some code so that instead of the default two boxes around my title, now I only have a line at the bottom. Since the line is added with same color as the border's, I can change it visually with the "Font and Color" Editing option.
#header-wrapper {
width:660px;
margin:0 auto 10px;
border-bottom:1px solid $bordercolor;
}
* You can add more font and color variables to the template, and they will show up in the "Font and Color" design tab. What this means is that you will have many more options to play around with, not just the default ones from Blogger templates.
For example, I could create a new color variable (inside the <b:skin> tag at the front of the template):
<Variable name="commenttextcolor" description="Comment Text Color"
type="color" default="#999" value="#999999">
and it would show up in the "Font and Color" tab,
This new variable has a name so you can add later as $commenttextcolor in the actual CSS code, a description name for it to show up in "Font and Color" design tab, the type of "color", and a default and actual value. I think Blogger will write whatever your choice back to this "value" so your template is always up-to-date and independent of Blogger's database.
Now that you have a variable, you can apply that to the CSS code, just like any other default variables.
* For my Vietnamese blog, I have used the same code showing in this article to modify its appearance. Please take a look.
Have a nice day,
Hoctro (10/2006)
Blog: http://hoctro.blogspot.com/
Showing a Hint on Where to Post a Comment
Dear Friend,
Nanny22girls from Google Help Groups: Customizing Templates
asks if she could reword the comment line at the end of each post in index pages to say "Leave a comment here", along with the number of comments.
After looking into it, here is my quick fix:
In Template->Edit Html, check on "Expand Widget Templates" to view the entire template. Then, locate <b:includable id='post' var='post'>, and keep scrolling down to see this:
<span class='post-comment-link'>
<b:if cond='data:blog.pageType != "item"'>
<b:if cond='data:post.allowComments'>
<a class='comment-link'
expr:href='data:post.addCommentUrl' expr:onclick='data:post.addCommentOnclick'>
<b:if cond='data:post.numComments == 1'>1
<data:top.commentLabel/><b:else/><data:post.numComments/>
<data:top.commentLabelPlural/></b:if></a>
</b:if>
</b:if>
</span>
You are going to replace the code in bold with this code:
<b:if cond='data:post.allowComments'>
<b:if cond='data:post.numComments == 1'>1
Comment<!--<data:top.commentLabel/>-->
<b:else/><data:post.numComments/>
<data:top.commentLabelPlural/>
</b:if>
<a class='comment-link' expr:href='data:post.addCommentUrl'
expr:onclick='data:post.addCommentOnclick'>Leave your comment here</a>
</b:if>
Notice there is a space at the end of "1" before the code goes to the next line, and the same thing happens with the <data:post.numComments/>. If you don't leave a space, then there won't be a space between the number and the word comment (or comments.) Notice I fix the "1 Comments" bug too.
Here is the result:
and the "1 comments" bug:
I think this enhancement really makes commenting more easier, since the link on where to add your comment now is easier to look for.
Have a nice day,
Hoctro (9/2006)
Blog: http://hoctro.blogspot.com/
Hacking Technique: On Making a New Hack
Dear Friend,
This weekend I was working on a brand new hack code name "Site Map", that would let you see all of your posts (theoretically up to 999 possible posts) as a list of all labels and their belonging posts. Here is an example of such a list:
...
Art
*Picasso's Guernica
*Da Vinci's Mona Lisa
*Dali: What do we know about his works?
Math
*How to solve a quadratic equation?
*Math in College: how tough it is?
*Math in everyday use.
Soccer
*The Italians Wins the World Cup for the fourth time!
and so on.
Well, things go really well, and I'm at a good stopping point. What I have at the moment is a list of all the possible posts in a blog, in chronological order. You can click on this link, or look at my beta playground and click on the "Listing of All Posts" to see the effect.
I would not consider this as a hack, but I'd like to make some comments on the code on the technical side of things, in a hope that some of my readers would be interested in this and turn it into completely unexpected new hack(s). So, if you are interested, please read on.
Here is my logic. First, I'm going to get all the posts in a blog. I think Blogger allows to retrieve up to 999 posts on a query.
Now, the return data would be as a part of the Blog in the form of data:posts. This means I cannot create a new widget to retrieve and process the data, but I have to get it from the Blog1 widget itself. To have a clean cut between the new code and the old one, I will sub-out all the code to a function (Blogger calls this an includable), then in Blog1's main includable I will call this function to do the job. Later on I have to do something so the rest of the full (999) posts' contents will not show up and slow down your computer, but for testing purpose, it's fine to see both new and current code.
Here is the call to the new "siteMap" function:
...
<b:includable id='main' var='top'>
<div id='blog-posts'>
<b:include name='siteMap' values='data:posts'/>
...
Below is the current listing of the function. I will explain more in details. (If you want to try this of course you must edit away all the numbers at the front of each line.)
1 :<b:includable id='siteMap' var='data:posts'>
2 :
3 : <div class='sitemapHack'>
4 : <div id='siteMapList'>
5 : </div>
6 : </div>
7 :<script language='javascript' type='text/javascript'>
8 :
9 : var currentUrl = "<data:blog.url/>";
10: if (currentUrl.search("max-results=999") != -1) {
11: var firstLine = "";
12: var tempLabel = "";
13: <b:if cond='data:blog.pageType == "index"'>
14: <b:if cond='data:blog.url != data:blog.homepageUrl'>
15:<!-- second part : filling in data based on tags -->
16: firstLine = firstLine + "<ul>";
17: <b:loop values='data:posts' var='post'>
18: <b:if cond='data:post.title'>
19: firstLine = firstLine + "<li><a expr:href='data:post.url'><data:post.title/></a></li>";
20: </b:if>
21: </b:loop>
22: firstLine = firstLine + "</ul>";/*1st line*/
23: </b:if>
24: </b:if>
25: obj = document.getElementById('siteMapList');
26: obj.innerHTML = firstLine;
27:}
28:</script>
29:</b:includable>
Line 1 declares the function as siteMap, with the passing value is the collection of all the posts.
Line 3 thru 6 contain the placeholder of the hack's contents. We will keep adding text to a variable declared in line 11, and at the end write all data to this div. As mentioned in my previous article entitled "JavaScript, you completed me!", this portion of the code I follow exactly from Ramani of Hackosphere.
Line 7 declares that we are entering Javascript, and line 27 exits this effect. While we are in JavaScript, you cannot write something like <li> and expect the code to pick this up and turn it into real html code. What you have to do is to write all of that HTML code to a string variable, as we shall see shortly.
Line 9 contains the secret of JavaScript/Beta integration. Whatever inside the two double quotes will turn into a string and is assigned to the variable currentURL. A look at the runtime code confirms this fact.
In fact, by reading the generated source code, I was able to find out many bugs, while programming the code in Beta's HTML edit tool.
Line 10 performs a search to see if the text max-results=999 is inside the currentURL variable (if it's different than -1 then it is, because the returning value indicated the location of the first occurence if there is a match.)
Now that it's matched, line 11 & 12 define some blank texts, while line 13 & 14 perform the checks to see if this is the archive/label kind of returned posts. As you might have known, there are three possible kinds of data that data:posts collection represents. If you are in homepage, data:posts represents the contents of all the posts you decided to show in the front page, whether it is one or ten posts. On the other hand, if you select on a label or a month/day/year archived link, data:posts represents all the possible posts resulting from that query. Finally, if you click on a link to the post, data:posts represents the actual post, so there would be exactly one (1) post in the collection.
In Beta templating language, there aren't any AND or OR logic for you to combine the two conditions into one if statement, so I had to make two if statements as shown in line 13 & 14. If the current page is an indexed type AND it's not at the same time the front page, then we hit the gold mine!
Line 16 starts the string text with an ul tag.
Line 17 thru line 21 set up a nice loop where each post's name is tugged inside its link, in order for you to be able to click on it to lead you to the right item post. In line 19 firstLine variable keeps adding more titles onto itself. In the generated code, the result is super lightweight chunk of code, since we only add Blogger to pass back titles and url only. You will also notice that the b:loop logic is executed on the server side, since what we see on the client side (our generated code) is the result of the content of each loop.
Noticed in line 18, the title is drawn only if it exists.
Once the loop is completed, we close the ul tag and the ifs as in line 21 thru 24.
As previously noted, we look for the unique id siteMapList, then write the content to it in line 25 & 26.
Now that the code is completed, to call it we use this link:
http://blogger-beta-from-ground-up.blogspot.com/search/label/?max-results=999
That was all I did for the posts to show. My next step for this little hack project is to look for all the unique labels contained in the posts, then have a for-loop going through all the found labels and prints all all the posts that match it. Because of this, if you have multiple labels for a particular post, it will show up many times, one for each label. That is acceptable, I think. I personally only assign one label per post right now in my main blog, but in the future, if I find a good benefit, I won't hesistate to add more labels.
Wow! I finally did it! I'm at the end of my explanations!
Have a wonderful day and see you next time, when I present you the completed "Site map" hack.
Hoctro (9/30/2006)
Blog: http://hoctro.blogspot.com/
My Blog Has Just Made It to "Blogs Of Note"!
Dear Friend,
I'm happy to tell you that I have just made it to the Blogs of Note. This is quite an honor and unexpected. I feel like I just have got my own star on Hollywood Boulevard!
I would like to take this opportunity to thank my friends (Ramani, Vivek, Hans, Avatar, John (Freshblog), and others) who have been helping one way or another in shaping the contents of my site. You can check out their sites from my "interesting links" on the sidebar.
Ramani is right. My simple, free counter I set up from "Sitemeter" jumped drastically from 100 a day, which is not a small number by any means, to 2400 (!) in just one day! This is incredible!
For my new readers, welcome!!!! Feel free to check out what's on my site, and leave your comments here on what other topics you would like me to write about: more hacks, hack suggestions, more Blogger Beta how-to tutorials, etc. I'm planning to write an in-depth series on the internal working of the new beta template. This will take 4, 5 articles or more. So stay tuned.
Have a wonderful day and check back often at my site and my friends', as we have quite a few interesting Beta hacks to offer.
Hoctro (9/2006)
Blog: http://hoctro.blogspot.com/
Subscribe to:
Posts (Atom)