Time Since (...after the fact).

I had noticed lots of blogs had a nice little Posted x hours, y minutes after the fact tag attached to Comments. I thought this was pretty cool, and had a very short attempt at this some time ago. Then, over on Binary Bonsai, Michael mentioned how the plugin was broken, and how it needs fixing. Well, I didn’t fix the PHP version, but I did write a pure Smarty version!

    {* 
    
    "Time Since" Smarty Code 
    
    Author: Matt Schinckel <matt@schinckel.net>
        http://schinckel.net
    
    Based on a WordPress Plugin "Time Since" 
        http://binarybonsai.com/wordpress/timesince
    
    Notes: Insert this whole text where you want the
    text to appear.  If keen, you could move the first
    pair of lines to a place outside of the comment loop,
    but still inside the post.  This might save some
    precious server seconds.
    
    The accuracy of the 'time since' decreases over time:
    there aren't 30.4 days in every month, for instance.
    
    *}
    
    {capture name=post_time}{the_time d="U"}{/capture}
    {assign var=post_time value=$smarty.capture.post_time}
    
    {capture name=comment_time}{comment_date d='U'}{/capture}
    {assign var=comment_time value=$smarty.capture.comment_time}
    
    
    {assign var=since value=$comment_time-$post_time}
    
    
    {if $since < 3600}
        {assign var=name1 value="minute"}{assign var=sec1 value=60}
        {assign var=name2 value="second"}{assign var=sec2 value=1}
    {elseif $since < 86400}
        {assign var=name1 value="hour"}{assign var=sec1 value=3600}
        {assign var=name2 value="minute"}{assign var=sec2 value=60}
    {elseif $since < 604800}
        {assign var=name1 value="day"}{assign var=sec1 value=86400}
        {assign var=name2 value="hour"}{assign var=sec2 value=3600}
    {elseif $since < 2626560}
        {assign var=name1 value="week"}{assign var=sec1 value=604800}
        {assign var=name2 value="day"}{assign var=sec2 value=86400}
    {elseif $since < 31536000}
        {assign var=name1 value="month"}{assign var=sec1 value=2626560}
        {assign var=name2 value="week"}{assign var=sec2 value=604800}
    {else}
        {assign var=name1 value="year"}{assign var=sec1 value=31536000}
        {assign var=name2 value="month"}{assign var=sec2 value=2626560}
    {/if}
    {math equation='floor(a/b)' a=$since b=$sec1 assign=count1}
    {math equation='floor((a-floor(a/b)*b)/c) a=$since b=$sec1 c=$sec2 assign=count2}
    Posted {$count1} {$name1}{if $count1 != 1}s{/if},
           {$count2} {$name2}{if $count2 != 1}s{/if} after the fact.

Another Gravatar Implementation

I recalled at some stage there was a Smarty Modifier called escape. I think it was when I was looking for one called rot13. Anyways, you can use this and the JavaScript function unescape() to obfuscate the email address. You’ll need this code early in your template: I stick it at the start just after <html>

1
2
3
    <script type="text/javascript" 
        src="http://schinckel.net/images/md5.jpg">
    </script>

This fragment will insert the Gravatar Image:

    {capture name=reader}{comment_author_email}{/capture}
    <script type="text/javascript">
    document.write('<div class="right">');
    document.write('<img src="http://www.gravatar.com/avatar.php?gravatar_id='); 
    document.write(hex_md5(unescape("{$smarty.capture.reader|escape:"hex"}"))); 
    document.write('&size=40" alt="" />');
    document.write('</div>');
    </script>

This seems to more reliably display the Gravatars, so I’d suggest you use it instead. Either that, or Gravatar just fixed up their servers…

Show/Hide JavaScript Code

There’s a little one-liner I’ve just learned for showing or hiding the contents of a particular <div> tag. (May also work for other types of tag). The stuff you want to show or hide needs to have an id attribute. I use it to hide some stuff if there are no Comments or Trackbacks, since I’ve seperated them, and this was the best way to hide the title.

1
2
3
    <div id="the_id">
        Text/Data To Hide Goes Gere
    </div>

Then, you can use this code to hide it (in an {if} block, for instance):

1
2
3
    <script type="text/javascript">
        document.getElementById("the_id").style.display = "none";
    </script>

And this to show it:

1
2
3
    <script type="text/Javascript">
        document.getElementById("the_id").style.display = "block";
    </script>

I haven’t tried, but it’s also probably possible to have show/hide links:

1
2
3
4
5
6
7
8
9
    <div id="the_id">
        Text/Data to Hide Goes Here.
    </div>
    <a onclick="javascript:document.getElementById('the_id').style.display = 'none'">
        Hide Text
    </a>
    <a onclick="javascript:document.getElementById('the_id').style.display = 'block'">
        Show Text
    </a>

Of course, if you want to hide text in-place (without rearranging the flow of the remainder of the text), you’ll need:

1
2
3
4
5
6
7
8
9
    <div id="the_id">
        Text/Data to Hide Goes Here.
    </div>
    <a onclick="javascript:document.getElementById('the_id').style.visibility = 'hidden'">
        Hide Text
    </a>
    <a onclick="javascript:document.getElementById('the_id').style.visibility = 'visible'">
        Show Text
    </a>

Script to XHTML

I wrote my own script to convert the selection (or whole front document) in Script Editor to XHTML. It uses the same CSS tags as Jonathon’s program, but does not add the style data in, unless a property is set. I’ve also got the Source Code for his program, so it will be interesting to see similarities.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
    (*
    Script to XHTML v1.0
    ©2005 Matthew Schinckel
    http://schinckel.net/
    
    Converts selection (or whole document) into XHTML code.
    
    Insert the StyleSheet into your CSS if you want.  Else set externalCSS to false.
    
    Put it in your Scripts Menu, and it will work a treat for you.  
    Even copies the data to the clipboard.
    
    Bugs/Issues:
    
    • Script Editor reports the start of comments [--] as being black, not grey.
    • Doesn't handle references.
    • Operators and values are treated all as values.
    
    *)
    
    property StyleSheet : "
    .AppleScript { background-color:#ffffff; border: solid black 1px; padding:0.5em 1em 1em 1em; text-align:left; font-family: Verdana,Sans-Serif; overflow:auto; font-size:0.9em; white-space:pre; line-height:1.2em; margin-bottom:9px;}
    .as_new_text  { font-family:Courier; color: purple; }
    .as_operators  { color: black; }
    .as_language  { font-weight: bold; color: blue; }
    .as_application  { color: blue; }
    .as_comments, .as_comment  { font-style:italic; color: gray; }
    .as_values  { color: black; }
    .as_variables ,.as_variable { color: green; }
    .as_references  { color: purple; }
    "
    property externalCSS : true
    
    -- The HTML code either side of the block.
    property htmlStart : "<pre class='AppleScript'>" & return
    property htmlEnd : return & "</pre>" & return
    
    property tagStart : "<span class='"
    property tagMiddle : "'>"
    property tagEnd : "</span>"
    
    -- Apparently, this one is different to 'return'
    property enter : "
    "
    -- For testing, set this to 2, for use via Script Menu, set to 1.
    property win : 1
    
    if externalCSS is not true then set htmlStart to htmlStart & "<style>" & return & StyleSheet & return & "</style>" & return
    
    tell application "Script Editor"
    	set theData to contents of selection of document of window win
    	if (theData is "") then
    		-- No selection, let's do the whole document.
    		set textList to attribute run of contents of document of window win
    		set fontList to font of attribute run of contents of document of window win
    		set colorList to color of attribute run of contents of document of window win
    	else
    		set textList to attribute run of contents of selection of document of window win
    		set fontList to font of attribute run of contents of selection of document of window win
    		set colorList to color of attribute run of contents of selection of document of window win
    	end if
    end tell
    
    set html to ""
    
    repeat with i from 1 to the count of textList
    	set theClass to whichClass(item i of fontList, item i of colorList)
    	set theText to my HTMLify(item i of textList)
    	set html to html & tagStart & theClass & tagMiddle & theText & tagEnd
    end repeat
    
    set the clipboard to htmlStart & html & htmlEnd
    beep
    
    -- Utility Functions
    
    on whichClass(theFont, theColor)
    	-- Set the class according to the font or colour.
    	if theFont is "Verdana-Bold" then return "as_language"
    	if theColor is {16384, 32768, 0} then return "as_variables"
    	if theColor is {19660, 19960, 19960} then return "as_comments"
    	if theColor is {0, 0, 65535} then return "as_application"
    	if theColor is {32768, 0, 32768} then return "as_new_text"
    	return "as_values"
    end whichClass
    
    on replace(theText, find, replace)
    	-- Nice replace function
    	set OldDelims to AppleScript's text item delimiters
    	set AppleScript's text item delimiters to find
    	set newText to text items of theText
    	set AppleScript's text item delimiters to replace
    	set theResult to newText as text
    	set AppleScript's text item delimiters to OldDelims
    	return theResult
    end replace
    
    on HTMLify(someText)
    	-- This might need some more entries.
    	-- Perhaps a better way of doing it...?
    	set someText to replace(someText, "&", "&amp;")
    	set someText to replace(someText, "\"", "&quot;")
    	set someText to replace(someText, "<", "&lt;")
    	set someText to replace(someText, ">", "&gt;")
    	--set someText to replace(someText, tab, "&nbsp;&nbsp;&nbsp;&nbsp;")
    	--set someText to replace(someText, enter, "<br />" & enter)
    	--set someText to replace(someText, return, "<br />" & return)
    	return someText
    end HTMLify

I will not tickle you!

Got this one from Boing Boing:

'Fixed' XHTML Export

Since I need to replace all " in the generated XHTML with ‘, I use the replace function from the previous post.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    (* 
    Bugs:
    
    Does not like no selection: no real way to get the selection from SEE anyway.
    Sometimes does not execute if called from Script Menu.  Intermittant.
    *)
    
    -- If called from Script Menu, need to do this.
    
    tell application "SubEthaEdit"
    	activate
    	tell application "System Events" to keystroke "C" using {command down}
    end tell
    
    set theStart to (the clipboard)
    
    set the clipboard to (my replace(theStart, "\"", "'"))
    
    beep
    
    -- Another way of the Replace Function being called:
    
    -- set the clipboard to (replaceText from theStart to "'" instead of "\"")
    
    on replace(theText, find, replace)
    	set OldDelims to AppleScript's text item delimiters
    	set AppleScript's text item delimiters to find
    	set newText to text items of theText
    	set AppleScript's text item delimiters to replace
    	set theResult to newText as text
    	set AppleScript's text item delimiters to OldDelims
    	return theResult
    end replace
    
    -- Alternate version of replace()
    
    to replaceText from theText to replace instead of find
    	set OldDelims to AppleScript's text item delimiters
    	set AppleScript's text item delimiters to find
    	set theText to text items of theText
    	set AppleScript's text item delimiters to replace
    	set theText to theText as text
    	set AppleScript's text item delimiters to OldDelims
    	theText
    end replaceText

Code Markup

I like to present styled code for my readers, but I’m not totally happy with my methods of getting it: SubEthaEdit’s Export as XHTML is very cool, but I still have to tweak it so it looks nice. And I’ve got a great program for getting the XHTML version of the code Script Editor (AppleScript) is currently displaying. But, I’d like more flexibility. I want the code to be tagged with classes, like it’s possible to do with the Script Editor add-on, rather than using inline styles. I’ve already done this for the Script Editor code, but I just need to remember to remove the inline stylesheet from the start of the generated code. Unfortunately the Script has been saved as a Run Only. I’d love to know a way to decompile one of these Scripts…apparently there isn’t. I’ll have to write my own. Or see if Jon is nice enough to give the Source Code. As for the SubEthaEdit part: I should be able to do it. I’ve learned a couple of tricks that will help.

Insert iTunes Data into Post

I used to use ecto to paste all of my entries on my blog, but with Blogsome’s XMLRPC issue, I have to use a browser. But it would be nice to automatically get the name and information about my currently playing iTunes track, just like ecto used to do. I wrote an AppleScript that does this, and, inserts the data in at the insertion point for you. Because it’s intended to be run from the Script Menu, and everything run from there runs as “System Events”, I had to hard code in the browser name. If you use another browser, just replace the second line with whatever your browser is called.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
property star : «data utxt2605» as Unicode text
property browser : "Camino"
on run {}
    
    tell application "System Events"
        try
            get process "iTunes"
        on error
            return "No Track"
        end try
    end tell
    
    tell application "iTunes"
        set theTrack to current track
        set theArtist to artist of theTrack
        set theAlbum to album of theTrack
        set theRating to rating of theTrack
        set theTrack to name of theTrack
    end tell
    
    set theString to "<p class=’itunes’> " & theTrack & " • <a href='http://www.google.com/search?q=%22" & theArtist & "%22>" & theArtist & "</a> • <a href=’http://www.google.com/search?q=%22" & theAlbum & "%22>" & theAlbum & "</a> " & myRating(theRating)
    set the clipboard to theString
    
    tell application browser
        activate
        tell application "System Events" to keystroke "v" using {command down}
    end tell
end run

on myRating(theRating)
    set theResult to ""
    set theTimes to (theRating - 9) / 20 as integer
    repeat theTimes times
        set theResult to theResult & star
    end repeat
    return theResult
end myRating

Amazon Funnies

I was hunting for some artwork for some iTunes tracks tonight (very nearly this morning), and I came across this page for the album There is a Way to Fly, by Coda. According to this, people who listen to Coda are likely to be on drugs! Or maybe I just misinterpreted it: maybe Coda is an addiction I need to kick.

The Offer • [Augie March][2] • [Sunset Studies][3]

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

MIT OpenCourseWare

MIT OpenCourseWare | OCW Home This is kind of nice: MIT is now putting a whole lot of their courses online for free. Looks to be some interesting stuff in there, not sure how much detail there is in the courses though. Will report when I’ve downloaded and played around with one or two…