New Script Online

Note: there is a newer post you should read instead of/as well as this one: Updated Toolbox Scripts. I’ve finished the Mozilla part of the new script: I think there’s some issues with Internet Explorer, and Safari, but I’ll work on those over the next week. You can use the script by including the following code in the head section of your main page template: <script type="text/javascript" src="http://schinckel.net/images/toolbox.jpg"></script> And then, where you want the following tags, enter them: <!--quicktags--> <!--catchpa--> <!--commentpreview--> <!--resize--> If you put the following inside your comment area, a gravatar will appear for each commenter: {capture name=reader}{comment_author_email}{/capture} <div class="gravatar">{$smarty.capture.reader|encode:"hex"}</div> There’s also the functionality to change post and comment times to a more human readable form: <span class="post_time"> Posted at: 12:34pm</span> Comment times are a bit more difficult: they require a time difference. Getting this on Blogsome is cumbersome at the moment, so I’ll write up a better way of doing it later. At the momement it uses the value obtained through a complicated {Smarty} expression. If you are really desperate, you can find this expression elsewhere on this blog, and put it into a tag as follows: <span class="timesince"><!--{$since}--></span> I’ll write it up so you can just put in <!--{the_time d="U"}-{comment_date d='U'}-->, but that won’t be for a day or so. The other feature I have added is automatic: I’ve got seperate Comments & Trackbacks, and the script will automatically hide whichever one is empty, if the other one isn’t. I will write up a way to seperate Comments & Trackbacks using DOM management, but, again, not right now. Finally, all of the stuff on this page could seriously screw with your template/browser. It is still in beta, and doesn’t work at all in some browsers. I did kill a bug that caused a hang on Firefox Mac, but there may be more of them. Make sure you have a backup of your template, and don’t do this unless you know how to fix it up…

Best pre-onload

I’ve been using domFunction() to determine whether it’s safe to do all of my DOM modification code, but with some testing, I noticed that some pages were causing Firefox to eat up huge amounts of CPU time. I tracked the error down to the domFunction call, as it uses setInterval() to run a function every n seconds. This in itself is nice to know (I was looking for a similar feature a couple of days ago), but the nice part is that it has a stopping function: clearInterval(). You are supposed to use it like this:

1
    timer = setInterval("Function();", interval);

This will then call the function Function every interval milliseconds. Neato. Except I only want a particular thing to happen once. So, as a part of my code, I was calling clearInterval(timer) inside a function called by Function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    function Startup(){
        Gravatars();
        .
        .
        .
        HumanTimePosts();
        
        clearInterval(timer);
    }
        
    //Code for all functions in here.
        
    timer = setInterval(function(){
        if (document.getElementById(\"footer\")){
            Startup();
        }
    }, 1000);

Which should work. Except for some reason, calls to clearInterval cannot come from inside functions called by setInterval. Or something like that. My next solution was to use:

1
2
3
4
5
    function checkDOM(){
        if (getById("footer")||getById("credit")) Startup();
        else setTimeout("checkDOM();",100);
    }
    setTimeout("checkDOM();"

Which solves the problem, but it ugly. Finally, I came across this little number:

1
2
3
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", Startup, null);
    }

This only works with Mozilla browsers, so for the time being I’ve combined the last two.

Recursion

One problem I have encountered is that sometimes templates differ, and one person may have paragraph tags inside a form, with input elements inside them. Other people may have another setup, such as all input elements inside the one paragraph tag, except the comment box. Sometimes, I needed to be able to find the form element that was the parent of a particular element, and sometimes this was it’s immediate parentNode, sometimes it was the grandparent node (node.parentNode.parentNode). So I wrote this nice little function that uses recursion to find the parent that is a form. I’m fairly sure it works okay, and there’s even a little check that will return and explicit false if there is no parent form.

1
2
3
4
5
6
7
8
    function getParentForm(node){
        if (node==document) 
            return false;
        if (node.tagName!="FORM") 
            return getParentForm(node.parentNode); 
        else 
            return node;
    }

Running JavaScript Before onload.

JavaScript has a pretty neat feature. Lets say I have some functions that need to be run when the page has finished loading. Say, like replacing some encrypted email addresses with the gravatar they are associated with. Since you want all of your JavaScript to remain in the external.js file, and not have to add anything other than the one call to the file in the header of the page, you need a method of knowing when the page has finished loading. By setting up as follows, you can do this:

1
2
3
4
    window.onload = function () {
        // Put code or calls to functions in here
        SetupStuff();
    }

This has a couple of disadvantages:

  1. If another script called after yours also has an assignment to window.onload, only their code will run.
  2. Alternately, if you are running after another script, you will replace any assignments they have made to window.onload.
  3. This will only be called when the whole page has run, including any images that need to be downloaded.

Various solutions for the second problem have surfaced, including testing window.onload, and appending to it instead of replacing it, but this does not fix either of the other two problems. Another solution is to have a function call at the end of the HTML code, but this could also fail, since the DOM is not yet complete. I have found a better solution, located at brothercake. It’s not really clear how to use it on that page, but the source is straightforward. What I did was include the text of the domFunction.js file, and right at the bottom of the script, included this line:

1
    var myStartup = new domFunction(Startup);

Right at the top of my code, I have a function called Startup, which contains all of the function calls I want to happen, in the order they need to. Much better than waiting for all of the images to load, even if most of them are cached.

BugMeNot Bookmarklet

Had a good idea for a bookmarklet today: get a username/password for the current domain from bugmenot, and automatically add it into the fields! I’ve got one that pops up a window: [BugMeNot][1], but it would be cool if it interacted with the page.

[1]: javascript:window.open(‘http://www.bugmenot.com/view.php?url='+window.location, ‘bmpopup’, ‘width=500,height=400,menu=no’).focus(); bmpopup.focus();

Backup Blogsome Posts

I didn’t realize this until the other day, but it’s possible to back up every post you’ve ever made using an offline client, such as the excellent ecto. I use the Mac version of this great program, and to back up every post I’ve ever made is as simple as:

  • Find out how many posts you have made.
  • Tell ecto to download this many recent posts.
  • Press the Refresh button.

The first one is easy: when you first log into your Blogsome blog, you’ll see on the dashboard a panel like:

Blog Stats There are currently 393 posts and 284 comments, contained within 19 categories.

Getting this info to your offline composer might be difficult - each one has different settings. In ecto, choose the Account in the main window (Entries & Drafts), and then go to the ecto→Preferences… menu (keyboard shortcut: Cmd-, ). In the window that appears, choose the Recent Entries tab.

I use the following settings: Store copies of published entries locally, uncheck Retrieve titles and summaries only, and insert the desired number of entries to retrieve. Then, click Save, and press Refresh in the main view. It might take some time if you have a lot of entries, but it’s nice to know you have a backup.

Oh, and if you do regular backups, you can set the value to a reasonable value, like 10 or 20, and make sure you do it every now and then before you’ve posted that many new posts. If you make any edits to old posts, they’ll only get picked up in a large backup like this one, though.

•

If you are using another client, the instructions will be similar, but you may have to search around for a while before you find where to change the number of entries to retrieve. Good luck: happy backup.

Spooky iTunes Coincidences

I just listen to random music most of the time. But every now and then a weird series of tracks come up. The normal thing is that tracks that we currently have in the car CD player play. But this one tops everything. The Eagles, New Kid In Town comes on, and I switch over to iTunes Rater to rate it, as I like that song. Then I notice this: The title of the previous song was “Johnny Come Lately”, words that are part of the chorus of “New Kid In Town”. Almost as spooky as the bit in Metal Gear Solid 2 where stuff starts going bunkum, and the voice says:

You’ve been playing this video game for too long. Turn the console off now.

This occurred at around 4am, so I was totally freaked. It was right, I had been playing the game for too long. Although this was actually part of the plot (trying to make Raiden(?) believe he is not real), I was convinced.

The Night Is A Blackbird • [Augie March][2] • [Strange Bird][3]

[2]: http://www.google.com/search?q=%22Augie March%22 [3]: http://www.google.com/search?q=%22Strange Bird%22

Functions Rewrite

I’ve got a bit of JavaScript in my site: Quicktags, Comment Preview, Catchpa and Gravatars, just to name a few of the recent additions. I’ve also got some pretty hairy Smarty Code thrown in there too. Some of it would be better off to be replaced by JavaScript. The two main examples of this are the Time Since code (eg: 22 hours, 34 minutes after the fact), and the _Human Time _code (Posted late at night). I’ve actually rewritten pretty much all of this code, and packaged it all up into one JavaScript, so I can just let other people include one line of code, with some others setting up what features they want, rather than having to wade through the code and find where to add bits. At the moment, most of it is quite functional, but would still require the use of a whole bunch of inline scripting. I’m working to replace this with functions that automatically run after the page has loaded (or, perhaps even better, when the main page has loaded, but before it displays?). So, for instance, you would just have the following code in your main page, inside the <head> section: <script type="text/javascript" src="http://schinckel.net/images/blogsome.jpg"><script> And, then in the templates, include a block of text that looks like: <div class="options" style="display:none;"> gravatar preview quicktags </div> You can have different features on different templates: the one above would make sense on a comments page, but not on others, for example. There will be robust error checking as to validity of particular features and their applicability on a particular page, but only including features you actually plan to use will make the page load faster. This ultimately should make the page load faster than with all of the inline code, and calls to several external javascripts. I think browsers will cache the blogsome.jpg file (it’s really a .js file, but don’t tell anyone), so the initial load time will be reduced on successive page loads. It will also mean I can add or improve features, and fix bugs. The tricky part is turning out to be catering for different layouts: the gravatar part was easy: the only code a user needs to put into their blog is the simple {capture name=reader}{comment_author_email}{/capture} <div class="gravatar">{$smarty.capture.reader|encode:"hex"}</div> Where they want the gravatar to appear, and it will work. Setting up for the Catchpa, which is pretty simple, turned out to be a little sticky. It all depends on how people’s templates are set up: what the structure of their form looks like. It might be easier to have them insert some HTML code, and then look for that. It makes it a little more work for the user, but more reliable.

Enlarge Text Area.

Last update for tonight: <a class='button' onclick='javascript:document.getElementById("the_id").rows+=10;'> Make Text Box Bigger </a> And similar for Make Text Boxes Smaller. It’s working on my comment box as we speak. Try it out. (Thanks to Dunstan).

Posted... (human time display)

Following on from the previous post, I’ve also shamelessly poached another idea from Dunstan: human-readable timestamps. Just pop this into your post.html file, where you want the ’time’ to appear.

    {capture name=hour}{the_time d="G"}{/capture}
    {assign var=hour value=$smarty.capture.hour}
    Posted
    {if $hour eq "00" or $hour eq "01" or $hour eq "02"}
        in the wee hours,
    {elseif $hour eq "03" or $hour eq "04" or $hour eq "05" or $hour eq "06"}
        terribly early in the morning,
    {elseif $hour eq "07" or $hour eq "08" or $hour eq "09"}
        early in the morning,
    {elseif $hour eq "10"}
        mid-morning,
    {elseif $hour eq "11"}
        late morning,
    {elseif $hour eq "12" or $hour eq "13"}
        mid-morning,
    {elseif $hour eq "14"}
        early afternoon,
    {elseif $hour eq "15" or $hour eq "16"}
        mid-afternoon,
    {elseif $hour eq "17"}
        late afternoon,
    {elseif $hour eq "18" or $hour eq "19"}
        early evening,
    {elseif $hour eq "20" or $hour eq "21"}
        evening,
    {elseif $hour eq "22"}
        late evening,
    {elseif $hour eq "23"}
        late at night,
    {/if}