Monday, July 09, 2007

Long Time No See

So you may (or may not) have noticed that I haven't really been around recently. No new posts, not answering comments or emails, etc......

Well, besides being busy, I've also decided to move over & start using Wordpress.

You can now find me at moggy.laceous.com

Saturday, May 12, 2007

Sliced Bread

I just happened to be taking a look at Thickbox again the other day (which functionality-wise is an extension of Lightbox), and I noticed that it was using the jQuery library. Since I'd never heard of this library before, I decided to investigate. It turns out this is the single sweetest javascript library I've come across (in other words, the coolest thing since sliced bread :P), and will most likely change the way I develop with javascript in the future.

Normally, if you have a div element on your page with an ID of "foo", you'd grab it like:

document.getElementById("foo")

With jQuery you'd grab it like:
$("#foo")

or
$("div#foo")

Similarly, if you have a class named "foo_class" then you would query that like:
$(".foo_class")

You could even query every div in the page like:
$("div")

Another huge benefit is $(document).ready(). Normally you would code off of the window.onload() event, but if you have a lot of images then your script might not fire off for a little while. $(document).ready() doesn't wait around for all the images to load. As soon as the DOM is ready, your script starts firing off.

As an example, here's how you might stop all the links on your page from working:
$(document).ready(function() {
$("a").click(function() {
return false;
)};
)};

jQuery also returns itself which makes it chainable. This means that instead of writing the following with 3 lines (one to add a class, one to show it, and one to set the innerHTML), we can just use this one line (for example):
$("a").addClass("test").show().html("foo");

jQuery also has other cool things like an iterator so you can write foreach loops, simple effects, and even special functions to make ajax/json easier. There's also a good community of users who have made plugins. Some of these plugins include:
  • Interface (an effects library similar to script.aculo.us)
  • Thickbox
  • TableSorter (makes it easy to dynamically sort a table)

Documentation can be found here, here, here, or here

Saturday, May 05, 2007

What's Your Timezone Offset?

I previously noticed that when creating my calendar that timezones in Blogger seem a little "messed-up" (See the calendar instructions & scroll down to the timezone section).

I recently saw a post by phydeaux3 complaining about the same thing.

So instead of relying on Settings -> Formatting -> Time Zone to get your actual UTC offset (which doesn't seem to be correct 100% of the time), I wrote this little script to get your actual offset.

Click here to view the script.

This uses a JSON feed callback so make sure to have (at the very least) summary feeds enabled. It's kinda strange that feeds have the correct UTC offset, but other (more user friendly) parts do not.

Friday, May 04, 2007

Display Random Post

Ever wanted a way to display a random post? Well, now you can :D

First, add the following javascript to your page's header (Template -> Edit HTML)

<script type="text/javascript">
//<![CDATA[
var _yourBlogUrl = "http://purplemoggy.blogspot.com";

function randomPost() {
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
var theUrl = _yourBlogUrl +"/feeds/posts/summary?alt=json-in-script&callback=getTotalPostsCallback&start-index=1&max-results=1";
script.setAttribute("src", theUrl);
document.documentElement.firstChild.appendChild(script);
};
function getTotalPostsCallback(json) {
var totalResults = json.feed.openSearch$totalResults.$t;
if (totalResults > 0) {
getRandomPostNumber(totalResults);
}
};
function getRandomPostNumber(totalResults) {
var randomNumber = Math.floor((Math.random() * totalResults) + 1);
getRandomUrl(randomNumber);
};
function getRandomUrl(randomNumber) {
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
var theUrl = _yourBlogUrl +"/feeds/posts/summary?alt=json-in-script&callback=getTheUrlCallback&start-index=" + randomNumber + "&max-results=1";
script.setAttribute("src", theUrl);
document.documentElement.firstChild.appendChild(script);
};
function getTheUrlCallback(json) {
var theUrl = json.feed.entry[0].link[0].href;
window.location.href = theUrl;
}
//]]>
</script>

Make sure to replace the _yourBlogUrl variable with your blog's URL.

Then just add the following link anywhere in your page
<a href="javascript:randomPost();">View Random Post</a>


Since this uses JSON feed callbacks, you'll need to make sure that you (at the very least) have summary feeds enabled for your blog.

Friday, April 13, 2007

Blogger Calendar Archive

Alright, after a long delay, here's my latest hack.

A calendar archive widget :D

Just click the image to view a working example & get the instructions.

Pic

Saturday, April 07, 2007

3.0

Well, it looks like the Creative Commons 3.0 license has been released, so I've gone ahead and updated that at the bottom of the page.

Oh, and I've finally gotten an Internet connection at my new place, so I'm finally back online :D

I'll try and get around to answering all the comments & emails I missed the past couple of months ;)

l8tr

Monday, February 05, 2007

Dexter

Well, in my quest to not just post Blogger stuff I present two really good books I recently read listened to ;)

I first heard about these when I saw an ad for Dexter, a new show on Showtime that I thought looked sort of interesting. I don't get Showtime, however, and after learning that this show was based off of a couple books I checked them out from the local library... and was really impressed! I especially liked the dark humor and the self-referential stuff.

Note: the protagonist is a serial killer, so if you're squeamish these books might not be for you!

Darkly Dreaming Dexter

Free Image Hosting at www.ImageShack.us
From the Inside Flap
Meet Dexter, a polite wolf in sheep’s clothing . . . a monster who cringes at the site of blood . . . a serial killer whose one golden rule makes him immensely likable: he only kills bad people.

Dexter Morgan isn’t exactly the kind of man you’d bring home to Mom. Though he’s playful and has a wonderfully ironic sense of humor, Dexter’s one character flaw (his proclivity for murder) can be off-putting. But at heart Dexter is the perfect gentleman, supportive of his sister, Deb, a Miami cop, and interested only in doing away with people who really deserve his special visit. Dex is quite good-looking but totally indifferent to (and, frankly, a bit puzzled by) the attentions paid to him by women. Despite the fact that he can’t stand the sight of blood, he works as a blood-spatter analyst for the Miami police department, a job that allows him to keep tabs on the latest crimes and keep an eye open for his next quarry.

Dexter’s well-organized life is suddenly disrupted when a second, much more visible serial killer appears in Miami. Dex is intrigued, even delighted, by the fact that the other killer appears to have a style reminiscent of his own. Yet he can’t help but feel that the mysterious new arrival is not merely invading his turf, but reaching out to him as well. This new killer seems to be doing more than copying Dexter—he seems to be saying, "Come out and play." Dexter’s secret life makes for a lonely existence . . . even a lovable monster can be intrigued by the prospect of finding a friend.

Introducing one of the most witty and original narrators in years, Jeff Lindsay’s Darkly Dreaming Dexter is a fresh, surprising, and brilliantly executed novel that is sure to receive wide acclaim.

Dearly Devoted Dexter
Free Image Hosting at www.ImageShack.us
From Booklist
*Starred Review* Dexter, your friendly neighborhood serial killer, is a police department blood-spatter expert who, in his spare time, kills people. Not just anyone, you understand--he only kills other killers, people whom he believes deserve it. Is this because Dexter really has a heart of gold? No, he's a monster (he is the first to admit it), but at least he tries to steer his evil into productive channels. In the second of Lindsay's alliteratively titled thrillers (following last year's Darkly Dreaming Dexter), Dexter's nemesis, Sergeant Doakes, is getting a little too close for comfort, and there is also the matter of a psychopath on the loose. When Dexter's two problems eventually link up . . . well, what's a well-meaning homicidal maniac to do? Dexter, the cheerfully sociopathic crime fighter, is one of mystery fiction's most original, compelling, and oddly endearing heroes. Lindsay digs a little deeper under Dexter's surface this time, showing us a little more about what makes him tick, but readers shouldn't worry. There are volumes still to be written about this gruesomely fascinating character. David Pitt
Copyright © American Library Association. All rights reserved

There's also a 3rd book that Amazon's saying will be released on August 14th, 2007.

Apparently there's also some differences between the book and the TV show. The main one being that that book is all from Dexter's point of view, while the TV show expands more on the secondary characters.

Integrating Your Feedburner Feed

This tutorial will show you how to use your Feedburner feed with your Blogger (out of) beta blog.

1) Feed Auto-Detection
First, go to Template -> Edit HTML and towards the top you'll notice a line that says

<b:include data='blog' name='all-head-content'/>

which actually spits out something like
  <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
<meta content='true' name='MSSmartTagsPreventParsing'/>
<meta content='blogger' name='generator'/>
<link rel="alternate" type="application/atom+xml" title="Minima Theme Switch Demo - Atom" href="http://minima-switch.blogspot.com/feeds/posts/default" />
<link rel="alternate" type="application/rss+xml" title="Minima Theme Switch Demo - RSS" href="http://minima-switch.blogspot.com/feeds/posts/default?alt=rss" />
<link rel="service.post" type="application/atom+xml" title="Minima Theme Switch Demo - Atom" href="http://www.blogger.com/feeds/8301582465326140745/posts/default" />
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www2.blogger.com/rsd.g?blogID=8301582465326140745" />

when viewing the page source (in Firefox right click & choose 'View Page Source')

For your blog, you'll wanna copy & paste those lines from your blog's page source (the actual code it spits out will be different for everyone so DON'T JUST COPY & PASTE THIS!), then go ahead and edit the href's on the 2 lines that say rel="alternate" (as shown in bold) with your Feedburner feed
  <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
<meta content='true' name='MSSmartTagsPreventParsing'/>
<meta content='blogger' name='generator'/>
<link rel="alternate" type="application/atom+xml" title="Minima Theme Switch Demo - Atom" href="http://feeds.feedburner.com/YourFeedburnerFeed" />
<link rel="alternate" type="application/rss+xml" title="Minima Theme Switch Demo - RSS" href="http://feeds.feedburner.com/YourFeedburnerFeed" />
<link rel="service.post" type="application/atom+xml" title="Minima Theme Switch Demo - Atom" href="http://www.blogger.com/feeds/8301582465326140745/posts/default" />
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www2.blogger.com/rsd.g?blogID=8301582465326140745" />

Now take what you've constructed at this point and replace the all-head-content part (as shown in the 1st codebox) with this.

2) Replacing Clickable Atom Feeds
Go to Template -> Edit HTML, check the box to Expand Widget Templates and find the following
<b:includable id='feedLinksBody' var='links'>
<div class='feed-links'>
<data:feedLinksMsg/>
<b:loop values='data:links' var='f'>
<a class='feed-link' expr:href='data:f.url' expr:type='data:f.mimeType' target='_blank'><data:f.name/> (<data:f.feedType/>)</a>
</b:loop>
</div>
</b:includable>

This is the code for the part that shows either
Subscribe to: Posts (Atom)

or
Subscribe to: Post Comments (Atom)

depending on the page-type (label, permalink, homepage, etc.)

Replace that with
<b:includable id='feedLinksBody' var='links'>
<div class='feed-links'>
<data:feedLinksMsg/>
<b:loop values='data:links' var='f'>
<b:if cond='data:blog.pageType == "item"'>
<a class='feed-link' expr:href='data:f.url + "?alt=rss"' type='application/rss+xml'><data:f.name/> (RSS)</a>
<b:else/>
<a class='feed-link' href='http://feeds.feedburner.com/YourFeedburnerFeed' type='application/rss+xml'><data:f.name/> (RSS)</a>
</b:if>
</b:loop>
</div>
</b:includable>

This will make that link point to your Feedburner feed for all pages except for the permalink pages which points to the per-post-comment feed for that post. Just replace the part in bold with your specific Feedburner feed.

Sunday, January 28, 2007

Recommedations Thru Social Bookmarking

Alright, WikiFray asked me about adding a [+]RECOMMENDED drop-down link for socially bookmarking your blogger posts. Instead of creating it from scratch I figured DynamicDrive would have a script I could start with to easily create this.

I started out by using the AnyLink CSS Menu (click the link for a demo & tutorial)

The first thing you'll wanna do is add some CSS something like the following between your <head></head> tags:

.anylinkcss{
position:absolute;
visibility: hidden;
border:1px solid black;
border-bottom-width: 0;
font:normal 12px Verdana;
line-height: 18px;
z-index: 100;
background-color: #E9FECB;
width: 205px;
}
.anylinkcss a{
width: 100%;
display: block;
text-indent: 3px;
border-bottom: 1px solid black;
padding: 1px 0;
text-decoration: none;
font-weight: bold;
text-indent: 5px;
}
.anylinkcss a:hover{ /*hover background color*/
background-color: black;
color: white;
}

Then you're gonna want to add a link to an external javascript file (again, in your page's header section)
<script type="text/javascript" src="http://yggomelprup.googlepages.com/anylink.js">
/***********************************************
* AnyLink CSS Menu script- © Dynamic Drive DHTML code library (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code
***********************************************/
</script>

The external javascript file is located here. You can leave it as is or upload to someplace else of your choosing.

Finally, you're gonna want to add the following somewhere in the body of your template:
         <b:if cond='data:blog.pageType == "item"'>
<a href="javascript:void(0);" onClick="return clickreturnvalue()" onMouseover="dropdownmenu(this, event, 'anylinkmenu1')">[+] Recommend</a>
<div id="anylinkmenu1" class="anylinkcss">
<a expr:href='"http://digg.com/submit?phase=2&amp;url=" + data:post.url + "&amp;title=" + data:post.title' class='snap_nopreview' target='_blank'>Digg</a>
<a expr:href='"http://reddit.com/submit?url=" + data:post.url + "&amp;title=" + data:post.title' class='snap_nopreview' target='_blank'>Reddit</a>
<a expr:href='"http://del.icio.us/post?url=" + data:post.url + "&amp;title=" + data:post.title' class='snap_nopreview' target='_blank'>del.icio.us</a>
<a expr:href='"http://furl.net/storeIt.jsp?u=" + data:post.url + "&amp;t=" + data:post.title' class='snap_nopreview' target='_blank'>Furl</a>
<a expr:href='"http://ma.gnolia.com/bookmarklet/add?url=" + data:post.url + "&amp;title=" + data:post.title' class='snap_nopreview' target='_blank'>Ma.gnolia.com</a>
<a expr:href='"http://www.sphere.com/search?q=" + data:post.url' class='snap_nopreview'>Sphere</a>
<a expr:href='"http://www.ifeedreaders.com/bookmark.php?theurl=" + data:post.url + "&amp;thetitle=" + data:post.title' class='snap_nopreview' target='_blank'>More...</a>
</div>
</b:if>

Note: this will only show up on the permalink pages. Personally, I added it to the post-footer-line-1 section of my template.

Sunday, January 14, 2007

Switch Menu

Alright, I've had a number of requests about my 'More Links' section in the sidebar. Basically that's just DynamicDrive's Switch Menu script.

Click here for a demo as well as a tutorial.

From the demo, you'll notice that you can use styled text as well as an image.

The following is copied and pasted from that page:

Step 1: Insert the below code to the <HEAD> of your page:
<style type="text/css">
.menutitle{
cursor:pointer;
margin-bottom: 5px;
background-color:#ECECFF;
color:#000000;
width:140px;
padding:2px;
text-align:center;
font-weight:bold;
/*/*/border:1px solid #000000;/* */
}

.submenu{
margin-bottom: 0.5em;
}
</style>

<script type="text/javascript">

/***********************************************
* Switch Menu script- by Martial B of http://getElementById.com/
* Modified by Dynamic Drive for format & NS4/IE4 compatibility
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

var persistmenu="yes" //"yes" or "no". Make sure each SPAN content contains an incrementing ID starting at 1 (id="sub1", id="sub2", etc)
var persisttype="sitewide" //enter "sitewide" for menu to persist across site, "local" for this page only

if (document.getElementById){ //DynamicDrive.com change
document.write('<style type="text/css">\n')
document.write('.submenu{display: none;}\n')
document.write('</style>\n')
}

function SwitchMenu(obj){
if(document.getElementById){
var el = document.getElementById(obj);
var ar = document.getElementById("masterdiv").getElementsByTagName("span"); //DynamicDrive.com change
if(el.style.display != "block"){ //DynamicDrive.com change
for (var i=0; i<ar.length; i++){
if (ar[i].className=="submenu") //DynamicDrive.com change
ar[i].style.display = "none";
}
el.style.display = "block";
}else{
el.style.display = "none";
}
}
}

function get_cookie(Name) {
var search = Name + "="
var returnvalue = "";
if (document.cookie.length > 0) {
offset = document.cookie.indexOf(search)
if (offset != -1) {
offset += search.length
end = document.cookie.indexOf(";", offset);
if (end == -1) end = document.cookie.length;
returnvalue=unescape(document.cookie.substring(offset, end))
}
}
return returnvalue;
}

function onloadfunction(){
if (persistmenu=="yes"){
var cookiename=(persisttype=="sitewide")? "switchmenu" : window.location.pathname
var cookievalue=get_cookie(cookiename)
if (cookievalue!="")
document.getElementById(cookievalue).style.display="block"
}
}

function savemenustate(){
var inc=1, blockid=""
while (document.getElementById("sub"+inc)){
if (document.getElementById("sub"+inc).style.display=="block"){
blockid="sub"+inc
break
}
inc++
}
var cookiename=(persisttype=="sitewide")? "switchmenu" : window.location.pathname
var cookievalue=(persisttype=="sitewide")? blockid+";path=/" : blockid
document.cookie=cookiename+"="+cookievalue
}

if (window.addEventListener)
window.addEventListener("load", onloadfunction, false)
else if (window.attachEvent)
window.attachEvent("onload", onloadfunction)
else if (document.getElementById)
window.onload=onloadfunction

if (persistmenu=="yes" && document.getElementById)
window.onunload=savemenustate

</script>

Step 2: And herein lies the HTML code for the menu itself. Add the below where you want the menu to appear on your page:
<!-- Keep all menus within masterdiv-->
<div id="masterdiv">

<div class="menutitle" onclick="SwitchMenu('sub1')">Site Menu</div>
<span class="submenu" id="sub1">
- <a href="new.htm">What's New</a><br>
- <a href="hot.htm">What's hot</a><br>
- <a href="revised.htm">Revised Scripts</a><br>
- <a href="morezone/">More Zone</a>
</span>

<div class="menutitle" onclick="SwitchMenu('sub2')">FAQ/Help</div>
<span class="submenu" id="sub2">
- <a href="notice.htm">Usage Terms</a><br>
- <a href="faqs.htm">DHTML FAQs</a><br>
- <a href="help.htm">Scripts FAQs</a>
</span>

<div class="menutitle" onclick="SwitchMenu('sub3')">Help Forum</div>
<span class="submenu" id="sub3">
- <a href="http://www.codingforums.com">Coding Forums</a><br>
</span>

<div class="menutitle" onclick="SwitchMenu('sub4')">Cool Links</div>
<span class="submenu" id="sub4">
- <a href="http://www.javascriptkit.com">JavaScript Kit</a><br>
- <a href="http://www.freewarejava.com">Freewarejava</a><br>
- <a href="http://www.cooltext.com">Cool Text</a><br>
- <a href="http://www.google.com">Google.com</a>
</span>

<img src="about.gif" onclick="SwitchMenu('sub5')"><br>
<span class="submenu" id="sub5">
- <a href="http://www.dynamicdrive.com/link.htm">Link to DD</a><br>
- <a href="http://www.dynamicdrive.com/recommendit/">Recommend Us</a><br>
- <a href="http://www.dynamicdrive.com/contact.htm">Email Us</a><br>
</span>

</div>

Customization

So you're now wondering how flexible the script is when it comes to customizing the menu to your liking. The good news is, quite.

Physical changes (adding/deleting items) to the menu are all done in the code of Step 2. Study it for a while, and you'll soon see the required structure. All menu items must be added within the "masterdiv' DIV. For each item, wrap the containing links in a SPAN tag with a unique incrementing ID starting with "sub1", (ie: "sub1", "sub2" etc), and use this ID within the onClick event handler to expand/contract it. As you can see in the demo, an image can be used for the menu item itself instead of plain text.

To make cosmetic changes to the menu, it is recommended you do so via CSS, by editing the style sheet of Step 1.

Enjoy this fully DOMesticated script!

There's one slight change I made, and that was adding span tags inside the div tags of line 4 in the 2nd codebox
<div class="menutitle" onclick="SwitchMenu('sub1')"><span>Site Menu</span></div>

and then I styled the CSS by changing .menutitle{} to .menutitle span{} (from the 1st codebox). This let me just underline the words instead of the entire line.