Posting Blocks of Code on Blogger

I had a hell of a time getting code blocks to look and behave as I wanted across the varied browsers on Blogspot. Simply, I wanted the white space preserved so I could indent lines, and I didn't want my text wrapped. Sounds like the <pre> tag should cover it, right? Ha! There's a whole litany of issues that arise in Internet Explorer when invoking the horizontal scroll-bar; Blogger's template was telling IE to word-wrap the <pre>; And even Firefox - though rightly - managed to give me a bit of the run around. Before I get into it all here's the final, working CSS I've discovered for code blocks. Copy it now! (Though don't run off without reading the Template Tip toward the bottom of the post.)

pre.code {
width: 94%;
overflow: auto;
overflow-y: hidden;
display: block;
line-height: 1.2em;
background-color: #f5f5ff;
padding: 0.5em 1em;
border: 1px solid #bebab0;
padding-bottom:15px;
}


From the CSS you can divine that I'm using <pre class="code"> to wrap my blocks. I started out using <pre><code>, and perhaps that could be made to work as well, but somewhere throughout my cross-browser compatibility struggles I ditched the code tag. It's redundant anyway. Pre tags preserve your whitespace and set a monospace type. Code tags set a monospace type. So why bother saying the same thing twice? Why? Why say it twice? Seriously, why should I say it twice?

I also had a lot of trouble with the <pre><code> arrangement where, because I was wrapping one in the other, IE would favor the <code>, ignore the <pre>, eat my whitespace and word-wrap my text. Meanwhile Firefox looked perfect - that is until you grabbed the scrollbar. Scrolling the code block would leave the background-color and border behind, sliding us into a void of undeclared white-space. In the end it proved too much hassle keeping the redundant <code> tag in just for it's own sake.

Even with the <code> tag out the window, I ran into the much maligned IE v-scroll bug. When a Mozilla browser adds a horizontal scroll bar to a block, it does it on the outside of the block. IE does it on the inside... You say tomato, I say flibbidy floo. Problem is, IE doesn't seem to account for the space the h-scroll has come to occupy. It doesn't stretch the container out, it just slaps the bar over the top of it. Now you've got a horizontal bar blocking out the last line in your <pre>, which necessitates that IE stamp a vertical scroll bar onto the block as well!

Sure, this is an ugly and unnecessarily contrived way of getting the job done: granted; but there's a bigger downside than aesthetics here. If you try to post a single line of code into a <pre>, Internet Explorer's intrusive horizontal and vertical scroll bars completely obscure your text. Scroll up, scroll down, the most you'll ever see is a sliver of what's there. Your one-line block of code is now a tasty block of scroll bar.

The simple style sheet above cures all that ails. I'm not going to explain it, just take it and go! Oh, but not until after reading this next part, of course.

The Aforementioned Template Tip


Even with the CSS implementation described here IE continued to word-wrap my code blocks. Testing outside of Blogspot proved the CSS good. So I started peeling through Blogspot's template, looking for some overriding declaration. I didn't catch it myself, but eventually found an old post on the Blogger Help forums containing the offending declaration's locale.

#main-wrap1 {
...
word-wrap: break-word; /* fix for long text breaking sidebar float
in IE */
}


If IE refuses to respect the <pre> tags on your Blogspot site, search your template for a word-wrap: break-word; being declared in the #main-wrap1 id and comment it out. If your template doesn't have a #main-wrap1 id, then you'll have to poke around until you find what your template calls it.

Caution: You'll likely find more than a few word-wrap: break-word; declarations throughout the template, and it's best not to remove them all. It should be obvious - by their names - which declarations belong to the sidebars, headers, footers, etc., and which belongs to the div(s) where your posts live.

Why, you guys? Why should I say it twice?

Blogger Bug - Internal Links Rewritten by the Composer

The best way to link to your own articles on Blogger is - or should be - with an internal link. Instead of using the full address to an article ("http://myblog.blogspot.com/2009/05/my-article.html") we should prefer an ambiguous internal link ("/2009/05/my-article.html")

Using an internal link means that if I decide to change the namespace of my blog at some point in the future the link will remain valid, since it only ever specified the subdirectory paths. This is especially important if you are using a domain name with your blogspot site, as you may in the future cease to own the domain. If you were to specify the full address in your links they will all break and become invalid if and when you let your domain lease run out.

The Bug


Entering Compose mode in Blogger's text editor resolves and rewrites all ambiguous links as children of www.blogger.com, thereby breaking them.

Example


Starting in the Compose window I click the Link button. In the URL field I enter the following ambiguous, internal link:

/2009/05/my-article.html


If I switch into the Edit Html mode my link is still properly preserved and displays the HTML code:

<a href="/2009/05/my-article.html">Visit My Article<a>


However, if I switch back into the Compose window - though I cannot see it yet - in the background my link has been resolved and specified. The HTML now reads:

<a href="http://www.blogger.com/2009/05/my-article.html">Visit My Article<a>


Not only has this negated the purpose of the ambiguous link - which is to maintain site integrity across changes in the domain name - but it has broken the link by resolving it to www.blogger.com instead of our blogspot site.

Even worse: Because the trigger here is simply entering into the Compose mode, if you merely attempt to edit or update an article containing ambiguous links, and if the editor opens into the Compose mode by default, then it will have already broken all internal links on the page just by reopening the post. If you save this reopened post you will have corrupted all your links.

Workaround


The only solution here is to never, ever use Compose mode. Switch into the Edit Html interface and get comfy. It's not much of a workaround, I know, but it's the only "solution" I've found.

I had hopes of finding a different access method that would allow linking to blogspot sites by blogID and postID. Alas I can find no record of the proper method for this and spamming the likely implementations hasn't gotten me anywhere, either.

For now, those concerned with using and maintaining ambiguous links will want to make sure the Settings>Formatting> option "Convert line breaks" is set to Yes and relegate themselves to the Edit Html interface. It's probably not a bad idea in any circumstance, as this is surely not the only bug in the Composer.

Blogger Bug - Corrupted Javascript for() loops

The Bug


Twice, when I have had call to write a javascript implementation for a blogspot page I have found that everything beneath the first line of a for() loop is chewed up, garbled, and spit back out upon saving it. Blogger doesn't throw an error of any kind, it just saves your code to the gadget, having silently mutated and destroyed what was written. This is observed by simply returning to the gadget via the edit button. There the code will be corrupt.


Example


<script type="text/javascript">

function addPlayers() {
var allmp3s = document.getElementsByName('mp3');
for (i=0;i<allmp3s.length;i++){
var mp3Player = buildEmbed(allmp3s[i]);
allmp3s[i].insertBefore(document.createElement('br'), allmp3s[i].firstChild);
allmp3s[i].insertBefore(mp3Player, allmp3s[i].firstChild);
}
}
</script>


Paste the code above into an HTML/Javascript gadget and save it. Now click edit to return to the code. Others have confirmed that as of this post's date blogspot corrupts it like so:

<script type="text/javascript">
function addPlayers() {
var allmp3s = document.getElementsByName('mp3');
for (i=0;i<allmp3s.length;i++){
}
}
mp3player="buildEmbed(allmp3s[i]);
" br var allmp3s[i].firstchild);
allmp3s[i].insertbefore(document.createelement( ),
allmp3s[i].insertbefore(mp3player,></script>


Workaround


Simply use another type of loop. A while() loop and a counter variable can be used to do accomplish the same results your for() loop might have. I haven't observed Blogger to corrupt while() loops.

A Good Reason to Kill Yourself

This summary is not available. Please click here to view the post.

Embed Flash MP3 Players w/ Javascript

What it Does:


The code provided here finds any <a> tags on the page that have been assigned the attribute, name="mp3". Then, using the URL from the <a> tag, it generates and places the proper code, embedding a flash mp3 player just above that <a> tag's link. Unaltered, this script uses the "Maxi" mp3 player hosted and available for download at http://flash-mp3-player.net/. (Though you need not download anything to run this script.)

Why?


First: Convenience. With this implementation I need only create a standard link and give it a name. From there, my mp3 player will appear on it's own, without all the ubiquitous <object><param><embed> malarky typically required to embed a flash file.

Secondly, to enable a reasonable level of dynamism to my Blogspot hosted site. If and when someone designs a slicker or more efficient mp3 player or... let's say the mp3 player I've been linking to disappears from its server someday - I'd like to be able to fix the broken links and integrate a new player into my site without having to edit every single post in which I'd ever embedded an audio file. This javascript standardizes the website's mp3 player, so that changing the embed code in the script effectively changes the embed code everywhere on the site.

How?


<script type="text/javascript">
/*
-----------------------------------------------
Dynamic Flash Embedder (for Linking MP3s)

Written by: Roy Tousignant
Date: 15 May 2009
URL: tvopiate.blogspot.com
----------------------------------------------- */

var playerloc = 'http://flash-mp3-player.net/medias/player_mp3_maxi.swf'

function buildObj(mp3) {
var flashtags = '<object data="'+playerloc+'" width="200" height="20" type="application/x-shockwave-flash">'
flashtags += '<param value="'+playerloc+'" name="movie">';
flashtags += '<param value="mp3='+mp3.href+'&amp;showstop=1&amp;showvolume=1" name="FlashVars">';
flashtags += '</object><br/>';

var obj = document.createElement('span');
obj.innerHTML = flashtags;
return obj;
}

function addPlayers() {
var mp3objs = document.getElementsByName('mp3');
var i = 0;
while (i < mp3objs.length) {
if(mp3objs[i].tagName == "A") {
mp3objs[i].parentNode.insertBefore(buildObj(mp3objs[i]), mp3objs[i]);
}
i++;
}
}

window.onload=addPlayers;
</script>


Usage


If you're using Blogger add a HTML/JavaScript gadget to your layout and paste in the code provided above. It doesn't matter where in your Blogspot layout you place the gadget. It will work just the same.

With the code in place you simply create links to the mp3 files you want to embed, making sure to include name="mp3" in the <a> tag. You can do this anywhere on your page: in posts; in the sidebars; in the header...

<a href="http://www.mymp3host.com/song.mp3" name="mp3">Download my Song</a>


That's it. Any links you make that carry the name "mp3" will magically receive an embedded mp3 player one line break above the link, allowing visitors to stream the file right there.

More Usage


Changing the flash player will probably require some basic understanding of simple coding. It's pretty straightforward to those who know, but for those who don't I'll provide an example. (Be it any help to you or not.)

To change the mp3 player that is being embedded you just need to edit the 'playerloc' and 'flashtags' variables near the top of the script to reflect the object/embed code for the new player.

For example, Google has a flash MP3 player that can be linked to. To embed Google's player manually onto a page you would use this object/embed code:

<object data="http://www.google.com/reader/ui/3247397568-audio-player.swf?audioUrl=http://www.mymp3host.com/song.mp3" width="400" height="27" type="application/x-shockwave-flash">
<param value="http://www.google.com/reader/ui/3247397568-audio-player.swf?audioUrl=http://www.mymp3host.com/song.mp3" name="movie">
<param name="flashVars" value="playerMode=embedded">
</object>


Therefore, to integrate Google's embed code into our script you would replace the playerloc and flashtags variables in our javascript code with:

var playerloc='http://www.google.com/reader/ui/3247397568-audio-player.swf?audioUrl=';

var flashtags = '<object data="' + playerloc + mp3.href + '" width="400" height="27" type="application/x-shockwave-flash">';
flashtags += '<param value="' + playerloc + mp3.href + '" name="movie">';
flashtags += '<param name="flashVars" value="playerMode=embedded">';
flashtags += '</object><br/>';


Note here that Google's player looks for the mp3 location to be included in-line with the link to the audio player itself, whereas the Maxi MP3 Player being used by default expects the mp3's url to be declared in the flashVar param.

And that's all the hints you get. ...ya' bunch of noobs.

Design Notes


"Why did you use a while loop instead of a for loop," you ask? To avoid a bug in blogger's code. In development whenever I saved the script to Blogger's HTML/Javascript gadget, use of the for loop caused everything thereafter to be scrambled.

End of Line


I suppose that's it. Wow, it might've taken as long documenting it as it did writing the damned thing. And I was trying to keep it brief! Actually it took me about 10 hours, start to finish, developing this script; forced to learn all sorts of javascript functions I'd never worked with before; fighting the Blogspot bugs to make it work in the gadget... Well.

Do leave me a comment if you're using it. I'd love to see my handiwork gracing other sites. And if you have any problems with it... 'the hell do I care?