Excel Crap at Printing

I’m having a bad evening. I’ve been trying to print several pages of an Excel document to a PDF file, so I can send it off. What it’s doing, however, is not printing them to one PDF, but seperate files. Now, that’s not too bad, but each file has the same name, so only the most recent one is actually being left on the disk. What I’ve had to do is print each one seperately, and combine them in Adobe Acrobat. What would have happened if I didn’t have Acrobat? Fuck Microsoft.

ABC Shop Crap

ABC Shop – Boyer Lectures 2005

Please note these downloads are compatible with most MP3 players and encoded with Windows Media software for PCs running Windows 98 or later. Please see website for full terms and conditions.

Okay, so they are compatible with most MP3 players, yet they are not MP3 files. Oh, and might I add they are not compatible with iPods, the most common MP3 player… It gets better: ABC Digital Music Service – abcshop.com.au Downloads – Powered by DestraMusic.com V3.0

Internet Explorer V6+ is required to purchase, download and aquire licenses. Unfortunately, this service does not support Macintosh systems.

Or Linux, or other OS, or anything relatively old. Nice one ABC. This site gets even worse. They claim to support “most MP3 players,” yet in actual fact only support WMA players, a subset of personal music players. I suspect this is verging on false advertising.

Don't Dirty Stats with your Visits

I often spend a heap of time tweaking stuff on my blog, and these show up as hits in the Referrers list, as well as on Performancing Metrics, a system of tracking readership. Now, it’s rather simple to stop your visits counting towards your stats. First, visit your site, and ensure you are logged in. In your address bar at the top of your browser, type in javascript:document.cookie, and press return. Find the cookie entry that starts with wordpressuser_, and copy the garbage-looking string after it – this is the md5 hash of your server name – to the clipboard. Find the location of your stat-gathering code. Before it starts, enter: {if $smarty.cookie.wordpressuser_md5string != "username"} and after it ends, enter: {/if} Make sure to replace md5string with your md5 hash! • This could also be used to have any text show/not show when you visit your own blog. Like Google AdSense ads, for instance.

Performancing Stats for Blogsome

This post is a Blogsome specific post with information gleaned from HOWTO: Wordpress Visitor Count Plugin Using Metrics API. If you aren’t using Blogsome, then you’ll be better off visiting there. If you are using Performancing Metrics as your system for tracking usage patterns, you may wish to have a counter of some sort. It’s possible to do this, safely and securely with just a little bit of Smarty. First, you’ll need to get your current Performancing Authorisation Key. This will not change unless you change your password, so keep that in mind if this stops working at some stage… To get your API key, you’ll need to visit a URL like the following, but with your username and password. http://performancing.com/perfstats/api.php?action=getauth&uid;=some+user&pwd;=mypass If you put this into a Firefox address bar, it will display the XML, but the only part we need is the part inside the <auth> tags. Don’t give this to anyone, else they can see all of your Performancing stats. You can now use this key to get some stats. As a test, we’ll get the basic stats of your blog. Copy and paste the URL below, and insert it into the address bar. Then, replace KEY with your authorisation key, and schinckel with your blogsome ID:

http://performancing.com/perfstats/api.php?action=getvisitorstats&auth;=KEY&blog;_domain=schinckel.net

You’ll be presented with some XML that looks like:

 1     <response>
 2         <request>
 3             <auth>KEY</auth>
 4             <blog_domain>schinckel.net</blog_domain>
 5             <action>getvisitorstats</action>
 6         </request>
 7         <ChartURL>
 8             http://performancing.com/perfstats/api.php?action=getchart&blog_domain=schinckel.net&dtype=visitor_stats&ctype=line&m=today&d1=2006-04-17&d2=
 9         </ChartURL>
10         <Visits>20</Visits>
11         <AverageVisitsPerDay>20.0000</AverageVisitsPerDay>
12         <AverageVisitLength>517.9500</AverageVisitLength>
13         <RepeatVisitors>0</RepeatVisitors>
14     </response>

You can then use the ChartURL to see a nice graph, something like: Performancing Stats If this doesn’t work, then check your API key, and all of the URLs you’ve typed in so far. Now, let’s imagine we just want a counter for total blog views. The URL will need to look a bit like (I’ve broken it onto seperate lines first to help you understand it): http://performancing.com/perfstats/api.php?action=getvisitorstats &auth;=KEY&blog;domain=blogname.blogsome.com&m;=date_range &d1;=start_date&d2;=end_date We’ll look at how to get the current date a bit later: for now, put a date at some point in the future. Mine, sans the authorisation key was: http://performancing.com/perfstats/api.php?action=getvisitorstats&auth;=KEY&blog;domain=schinckel.net&m;=date_range&d1;=2006-01-01&d2;=2007-01-01 Which generated the following XML:

 1     <response>
 2         <request>
 3             <auth>KEY</auth>
 4             <blog_domain>schinckel.net</blog_domain>
 5             <action>getvisitorstats</action>
 6         </request>
 7         <ChartURL>
 8             http://performancing.com/perfstats/api.php?action=getchart&blog_domain=schinckel.net&dtype=visitor_stats&ctype=line&m=date_range&d1=2006-01-01&d2=2007-01-01
 9         </ChartURL>
10         <Visits>9204</Visits>
11         <AverageVisitsPerDay>271.3529</AverageVisitsPerDay>
12         <AverageVisitLength>289.5818</AverageVisitLength>
13         <RepeatVisitors>242</RepeatVisitors>
14     </response>

It’s possible to use the {fetch file="URL" assign="stats"} to grab this data and store it in a variable, so the whole lot isn’t displayed. You may have noticed that the Auth Key is included in the response! Now, the only bit we are really interested in is the

1     <Visits>9204</Visits>

section, so we need some way to extract this. Smarty allows for Regular Expressions, and we want to use one that will match everything up to and including , and discard this. We’ll want to repeat that with onwards. Due to a limitation, we’ll need three regexes, since there are newlines in there that much with the simlest method.

1     {$stats|regex_replace:"/[\r\t\n]/":""|regex_replace:"/.<Visits>/":""|regex_replace:"/<\/Visits>./":""}

Thus, my final data is:

<div class="highlight"><pre><code class="html">    <span class="nt">&lt;li&gt;</span>{fetch file=&quot;http://performancing.com/perfstats/api.php?action=getvisitorstats<span class="err">&amp;</span>auth=KEY<span class="err">&amp;</span>blog_domain=schinckel.net<span class="err">&amp;</span>m=date_range<span class="err">&amp;</span>d1=2006-01-01<span class="err">&amp;</span>d2=2007-01-01&quot; assign=&quot;stats&quot;}
    {$stats|regex_replace:&quot;/[\r\t\n]/&quot;:&quot;&quot;|regex_replace:&quot;/.*<span class="nt">&lt;Visits&gt;</span>/&quot;:&quot;&quot;|regex_replace:&quot;/<span class="err">&lt;</span>\/Visits&gt;.*/&quot;:&quot;&quot;} Post views.
<span class="nt">&lt;/li&gt;</span>

Of course, that’s with a hard-coded finish date. What if we want to finish on today? Again, there’s a way to do it in $smarty: {$smarty.now|date_format:"%Y-%m-%d"} To add this to the end of the URL, use:

1     {assign var="URL" value="http://performancing.com/perfstats/api.php?action=getvisitorstats&auth=KEY&blog_domain=schinckel.net&m=date_range&d1=2006-01-01&d2="}
2     {assign var="today" value=$smarty.now|date_format:"%Y-%m-%d"}
3     {fetch file=$URL|cat:$today assign="stats"}

It’s also simple to get a current day’s post hit count, using single_date instead of date_range. I’ll leave that one up to you.

Resizable Comment Area

I’ve already had resizable Textarea implemented in this blog – the two buttons that appear at the bottom of the comment box, next to Preview/Post Reply. However, today over on MacGeekery, I came across something even better. A resize widget, that can be dragged to resize the comment entry box. Getting this to work wasn’t quite as simple as just cutting and pasting code, however. Eventually, I rewrote the code from scratch, using some of my toolbox tools also. The script starts by finding every <textarea>, and then, if it has the class resizable, it adds an enclosing <div> tag, and a grippie <div> tag. This then allows for CSS to style the grippie tag.

 1     function ResizableComment(){
 2         textareas = document.getElementsByTagName('textarea');
 3         
 4         var textarea;
 5         for (var i=0; textarea = textareas[i]; i++){
 6             if (textarea.className.match(resizable)){
 7                 // Insert resizable <div>
 8                 ta = document.createElement('div');
 9                 ta.className = resizable-textarea;
10                 textarea.parentNode.insertBefore(ta, textarea);
11                 ta.insertBefore(textarea,ta.firstChild);
12                 // Insert Grippie
13                 grippie = document.createElement('div');
14                 grippie.className = 'grippie';
15                 w = textarea.offsetWidth - 2;
16                 grippie.style.width = px(w);
17                 textarea.parentNode.insertBefore(grippie, textarea.nextSibling);
18                 grippie.onmousedown = beginResize;
19                 // Remove bottom border
20                 textarea.style.marginBottom = 0;
21                 textarea.style.borderBottom = 0;
22             }
23         }
24     }

Notice also that it sets the onmousedown action for the grippie to a function called beginResize.

 1     function beginResize(e){
 2         var coords = getMousePos(e);
 3         window.resizing = eventTarget(e).parentNode.firstChild; // Textarea.
 4         window.resizing.style.height = px(window.resizing.offsetHeight);
 5         window.start_resizer = coords[1];
 6         document.body.onmouseup = endResize;
 7         document.body.onmousemove = duringResize;
 8         return false;
 9     }
10     
11     function duringResize(e){
12         var coords = getMousePos(e);
13         window.end_resizer = coords[1];
14         if (window.start_resizer == window.end_resizer) return;
15         window.height_change = window.end_resizer - window.start_resizer;
16         if (window.resizing.offsetHeight + height_change - 1 < 115) return;
17         window.resizing.style.height = px(window.resizing.offsetHeight + height_change - 1); // Need the -1 to work!
18         window.start_resizer = window.end_resizer;
19     }
20     
21     function endResize(e){
22         duringResize(e);
23         document.body.onmouseup = null;
24         document.body.onmousemove = null;
25     }

The beginResize function in turn sets up a few things, including which element needs to be resized, and the functions that need to be called as it happens. These functions use another pair of functions:

 1     function getMousePos(e) {
 2         var posx = 0; var posy = 0;
 3         if (!e) e = window.event;
 4         if (e.pageX || e.pageY){
 5             posx = e.pageX;
 6             posy = e.pageY;
 7         } else if (e.clientX || e.clientY){
 8             posx = e.clientX + document.body.scrollLeft;
 9             posy = e.clientY + document.body.scrollTop;
10         }
11     
12         return new Array(posx, posy);
13     }
14     
15     function px(val){return val + px;}

Don’t Believe AnymoreThe WhitlamsTorch The Moon ★★½

Testing XMLRPC

This is a test of the XMLRPC interface. I think Ronan may have fixed it. This is a single quote ‘ This is a double quote “ This is an image: Matthew Schinckel

Seance On A Wet Afternoon • “Ultra-Lounge, Vol. 16: Mondo Hollywood” • John Barry

Image Scan

Here’s some amusing images that passed across my feed/email in the past couple of days: This first one is what one of M.C. Escher’s paintings may have looked like if done in primary school, complete with Teacher comments. Escher Child The next two came from Limbic Nutrition, and made me smile.