dans.blog


The miscellaneous ramblings and thoughts of Dan G. Switzer, II

Celebrating Dan² Day

Yesterday my Dad and I celebrating our birthdays. I was born on my Dad's 25th birthday—which is something I've always enjoyed. It's pretty rare to share a birthday with a parent (although my Grandma and Great-Grandma on my mother's side shared a birthday,) but it's a bond between us that is something I'm glad we share.

Since winter is a slower time for my parents, my Mom and Dad drove to Columbus and my Mom made dinner at our house for my Dad and me. She always makes us Beef Stroganoff as it's our favorite meal. Ironically,  neither of our wives care much for it but they make it for us because they know we love it.

Whenever we have a leap year, it always makes me think how close I was to being a leap year baby. If I would have been born 3.5 hours later, I would have actually been celebrating my birthday today. However, I was already almost 3 weeks late, so I'm pretty sure I was just waiting for my Dad's birthday.

By the way, I was an extremely cute baby:


Solution to adding drop shadows to a Suckerfish-style menu...

I'm working on a dropdown menu based on the <ul /> tag. The menu can have an unlimited number of children menus and I decided the "suckerfish" method was a very effective method for achieving my menu structure.

One of the problems I ran into was trying to implement a drop shadow layer for the menus. While there are many ways to implement a drop shadow, I thought the most straight forward method was to use a shadow <div /> with the same dimensions of the menu it's shadowing. The problem I ran into is I couldn't properly get the drop shadow to appear below it's anchored menu. It kept wanting to appear above the menu.

In my code I was explicitly setting the <ul /> tag being displayed to have a z-index one higher than the drop shadow, but the drop shadow always remained on top. After tracking the problem for a bit, I realized was that the because of the nested nature of the <ul /> tags, even though I was explicitly defining a z-index, the <ul /> was inheriting from the parent.

The fix was just to move the shadow <div /> as a sibling to the <ul /> it's shadowing. Once I did this I was able to correctly place the shadow <div /> underneath the <ul /> tag it was shadowing.


Using a PKCS12 key to for signing JAR files

We recently bought a Self-Signing Cert from Comodo through Tucow's Authors site. Through Tucows I was able to get a 3 year cert for $195—which is cheaper than a 1 year cert from either Thawte or Verisign.

I was expecting them to send me a cert via e-mail, but instead they install the certificate into the browser in which you purchased the certificate. From this point on Comodo doesn't offer any instructions on how to use the cert, so I had to do some research.

First, I'd recommend buying your cert using Firefox. If the cert gets installed into Internet Explorer, you need to jump through a bunch of hoops to generate the p12 file from the pvk format. Once you have your cert stored as a PKCS12 file, the steps for signing your Java Applet are pretty straightforward.

The instructions below show you how to sign an applet provided your personal cert has installed into Firefox. If you already have your p12 file, the you can skip to step 11(the directions use the filename of self-sign.p12 for the exported key.)

  1. Open Firefox v2.x
  2. Go to Tools > Options...
  3. Click on the Advanced button
  4. Go to the Encryption tab
  5. Click on the View Certificates button
  6. On the Your Certificates tab you should see your personal cert
  7. Click your personal cert
  8. Click the Backup button
  9. Save the file to your desktop as: self-sign.p12 (the p12 extension will be added for you automatically)
  10. Enter a password for the certificate when prompted by Firefox (you'll need this value later)
  11. Now that the cert has been exported, we need to get the "alias" so we know what to use when signing the applet.
  12. From a command prompt run:
    keytool -list -storetype pkcs12 -keystore /path/to/your/self-sign.p12

    (The keytool is a command line tool located in your JDK's /bin folder.)
  13. Enter the password you assigned in step 10
  14. You should now see some output that looks like:

    Keystore type: PKCS12
    Keystore provider: SunJSSE

    Your keystore contains 1 entry

    [Alias], Jan 1, 2008, keyEntry,
    Certificate fingerprint (MD5): hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh:hh

    The [Alias] is a string that might be look like a UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx) or it could just be string of various text. The alias will be the part of the text up to the first comma before the date.

  15. To sign a jar, we use:
    jarsigner -storetype pkcs12 -keystore /path/to/your/self-sign.p12 yourJar.jar [Alias]

    Or if you prefer Ant, you can use something like:
    <target name="signjar" depends="jar">
      <input
        message="Please enter keystore password:"
        addproperty="keypass" />
      <signjar jar="${lib}/yourJar.jar" storetype="pkcs12"
        keystore="/path/to/your/self-sign.p12" alias="[Alias]"
        storepass="${keypass}"/>
    </target>

I highly recommend creating an Ant build.xml script for compiling and signing your JAR. The biggest benefit is once you get it set up, there's nothing manual you need to do.


Update on Nikki's Surgery - Week 2

Well finally got the infection under control—at least for the most part. Her left hind leg, which was the one that was really swollen, got back to normal size by Thursday of last week. He right hind leg is still a little irritated, but they were able to take her staples out yesterday. The funny thing is the leg that looked so bad last week, looks really good.

The incision has healed up nicely and you barely notice it. The right leg is still a little red and swollen. Since she still has a bit of an infection and the leg is tender, they want us to keep the eCollar on when we can't keep an eye on her—just to prevent excessive licking. We're able to keep the eCollar off as long as we can keep an eye out to make sure she doesn't keep licking at the wound.

She still handling being in her kennel well. She hasn't really complained, other than the occasion crying around 6am when she needs her potty break.

The one thing that has Jenn and I little concerned is that when we got back to the house yesterday (after getting the staples out) she slipped a bit in the driveway. The Vet told us we didn't have to use her sling anymore, but our intention was to keep using it since it's been so icy outside. Unfortunately, right after I lifted her out of the SUV, but before I could get the sling on her, she slipped a bit in the driveway. She was walking a bit tenderly yesterday, so we're monitoring it closely to make sure she didn't injure it. I think it's just that the infection is still a little tender after getting the staples removed, but we'll know more today I think.

She's also definitely getting her strength back. She's really started to drag us around the backyard. Part of the reason I want to keep using the sling is it helps me control her a little bit. If she's putting to much stress on her back legs, I can lift her rear up a bit and that gets her to stop.

Hopefully by the end of week 3, the infection will be completely gone.


Firebug Tip: console.log([label, value]);

[UPDATED: Thursday, February 28, 2008 at 8:02:17 AM]

I thought maybe this was a tip worth blogging. I like to use labels in my debug information as it helps me to quickly identify the debug statement that generated the output. Appending a label string to a simple value is easy enough in JavaScript, as it'll automatically be converted to a string. However, this doesn't work for complex values. You can place the label on a separate line, but I like to try to keep things to one line whenever possible. The way I do this is to use an array to output my label first and then the value:

console.log(["my label", complexObject]);

This gives you the benefit of generating a label and a value all on one line. I find the syntax very easy to read in the Firebug console and it keeps everything on one line—just the way I want it. The output will look like:

["my label", {...}]

Hopefully someone else will find this tip useful.

UPDATE:
For those of you who want a Firebug to output a hyperlink to the line that invoked the message, you might want to use console.debug() instead.


Updates to jQuery Field & Calculations Plug-ins

Over the weekend I made a few changes to my Field & Calculations plug-ins. One big change is I moved the plug-ins to the jQuery SVN repository. This should help people to find the plug-ins and will provide an easy way to stay on top of the changes.

The biggest overall change to the Field Plug-in is the addition of callbacks to the a few of the methods, especially the createCheckboxRange. This allows you to do something like change the background color of the checkbox's row. I also added a default setting (checkboxRangeKeyBinding) which allows you to configure which keyboard event triggers the range selection. This still defaults to the [SHIFT] key, but I can see where you might want to change this binding in certain situations.

The changes I made to the Calculation Plug-in should make it even easier to implement. I altered the sum() and avg() methods so that you can now create bindings to easily update the page. Previously, the methods only performed the calculations, so you had to write your own binding calls. Now if you want to update the element #totalSum whenever the user changes a value in a field beginning with the keyword "sum", you can do: $("input[@name^=sum]").sum("keyup", "#totalSum");

Here's a list of the changes that I've made in the past few days:

Field Plug-in

  • Moved source code to jQuery SVN repository: http://jqueryjs.googlecode.com/svn/trunk/plugins/field/
  • Changed the limitSelection() function to use an options argument, instead of all the individual arguments
  • Optimized the createCheckboxRange to reduced complexity and code size. Functionality has not changed.
  • createCheckboxRange() no longer breaks the chain
  • Added callback to autoAdvance() method
  • Added callback to createCheckboxRange() method
  • Added configurable setting for the [SHIFT] key bind to the createCheckboxRange()
  • Added the $.Field.setProperty() and getProperty() methods
  • Fixed "bug in checkbox range" (http://plugins.jquery.com/node/1642)
  • Fixed "Bug when setting value on a select element and the select is empty" (http://plugins.jquery.com/node/1281)

Calculation Plug-in

  • Moved source code to jQuery SVN repository: http://jqueryjs.googlecode.com/svn/trunk/plugins/calculation/
  • Fixed bug in sMethod in calc() (was using getValue, should have been setValue)
  • Added arguments for sum() to allow auto-binding with callbacks
  • Added arguments for avg() to allow auto-binding with callbacks


Pictures of Nikki after Surgery

[UPDATED: Thursday, February 21, 2008 at 10:55:31 AM]

Jenn took some pictures last night of Nikki. I wish we would have taken a few pictures over the weekend when he leg was really swollen. The swelling has gone way down and her energy level has gone way up. She's acting more and more normal. This is both good and bad. We're elated that she's feeling better, but she's a very high energy dog and trying to curtail her enthusiasm is going to be tough task for the next 5 weeks.

nikki_surgery_11 nikki_surgery_02 nikki_surgery_03
nikki_surgery_04 nikki_surgery_05 nikki_surgery_06
nikki_surgery_07 nikki_surgery_08 nikki_surgery_09
nikki_surgery_10 nikki_surgery_01  

The leg with the red blotches is that leg that was really swollen over the weekend. It was at least twice as big as it is now.

UPDATE: I added a lightbox effect to the gallery to make it easier to view.


Watch jQuery Calculation Plug-in in action!

A few weeks ago I posted a blog entry on my jQuery Calculation Plug-in. However, I never think I do an adequate job of describing what it does so I thought a little video might be more useful. Since I just installed Jing a few days ago, I thought this plug-in made a perfect candidate for my first Jing post!

Something I forgot to specifically mention in my demo, but which I think is really significant, is that the dynamic calculation code would work regardless of how many rows were in your table. If you only had 1 item in your basket or 20 items, the exact same code is used. The key is to use a naming convention that is consistent and easy for jQuery to parse.

My original post goes into the technical details behind the demo above, so make sure to read the post for the detailed information on what's going on.


Update on Nikki's Surgery - Week 1

Well, the last week has been pretty hectic. Nikki had infections in both legs, so we didn't get much sleep over the weekend as we were using hot compresses to try to draw the infection out. She was getting a lot of seepage out of her right hind leg (which is pretty normal) but her left leg swelled up to probably 3-4 times its normal size by Friday night.

We were worried about it enough to take her back to MedVet's ER on Saturday to have it checked out. They ended up changing her antibiotic prescription. Since the ER visit, the swelling and infection looks to be decrease each day. She barely had any seepage out of her right hind leg yesterday and the swelling in her left hind leg has reduced by probably 50%.

As far as her attitude, she's been a real trooper. Everyday she's acting more and more like herself. She's definitely getting bored being crated all day, but she's being much better about it than I thought she would. She typically heads right back to her crate all on her own after we go out for our walk/potty break.

The one thing we've had trouble getting done is her leg stretching routines. Since we spent so much time using hot compresses to get the swelling down, we had trouble getting her to lay still long enough for us to also do the stretching. We usually only get one leg in at a time—when we're supposed to do both legs. However, I talked to the Dr. Barnhart (the surgeon) and he told me that while the exercise are designed to help the recovery, their not crucial to the process and it won't cause the procedure to fail in the long run.

I still want to step up that bit of therapy though. I'm sure the stretching exercises will only help the recovery period, so hopefully we can get her on a better schedule for that part of the therapy.

Overall I think the biggest issue Jenn & I are both battling with is lack of sleep. I've got to stay up for her late night pills, but the dogs are getting me up by 6am each morning. Somehow the 5 to 5½ hours of sleep I'm getting just isn't cutting it. I'm scheduled to go back for my second sleep study next week—in which they'll get me fitted for a CPAP machine to try to fix my sleep apnea issues. Hopefully that will increase the restfulness of my sleep.

Anyway, I'll try to get some pictures of Nikki online. I've gotten really bad of taken pictures of late. I really wish I would have snapped a few pictures when her leg was all swelled up.


My TurboTax dilemma solved with great Customer Service...

Good service oftens goes unnoticed, so I wanted to public thank Bob Meighan, the VP of TurboTax, for helping me get some older .tax files in which I could locate either the PDFs or the original documents I had printed.

I tried tracking down my old TurboTax installations, but I couldn't find the files for the years I was missing. They've either been thrown out or were lost in our robbery last year.

My guess is this isn't an uncommon request, but Bob got me the PDFs I needed ASAP. Anyway, I always like to recognize when a company goes the extra mile to help me out quickly.


Accessing privileged methods in a Java Applet via JavaScript

I've been working on a Java applet that can get images from the user's clipboard or take screenshots of the user's desktop and upload them to a server via HTTP. The last piece of the puzzle was to make sure I could access the task methods via JavaScript, as the interface will most likely be driven by HTML.

I've been using a self-signed cert to sign the Java Applet so that I can access the user's clipboard and take the screenshot. All of this was tested and working extremely well from if I used the Applet UI. However, as soon as I would try to invoke one of the sandboxed functions from JavaScript the applet started throwing the error:

AccessControlException is thrown: access denied (java.awt.AWTPermission accessClipboard)

I tried a number of things to get around this problem. I thought it was something I was doing wrong when I was signing the applet (since it was working fine from within the Applet's built-in UI controls.) After playing around with the cert signing process and getting no where, I finally came across the post JavaScripting in Applets - Getting Out of the Sandbox where a comment from Stéphane Bury pointed me to a solution.

public static void doSpecialWork(String param1){ final String fParam1 = param1; java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { public Object run() { // put the code of your method here ... ... return ""; } }); }

My final solution was to write a command() method which I can use to trigger off the internal privileged methods:

/** * The method to invoke from JS to perform the privileged methods--which throw * security errors if you try to access them directly. * * @param command - the command you want to perform (clipboard, screenshot, upload) */ public void command(String command){ final String cmd = command; java.security.AccessController.doPrivileged( new java.security.PrivilegedAction(){ public Object run() { // execute the privileged command executeCommand(cmd); // we must return an object, so we'll return an empty string return ""; } } ); }

As you can see the method is very basic, it just passes the command it received to a private method which actually executes the command. Now I can access any of the privileged methods in my applet with this little helper method.


e / TextMate Command - Open Target Document

[UPDATED: Saturday, March 08, 2008 at 10:26:56 AM]

I've been playing around with e - TextEditor this weekend to see if maybe it'll replace Textpad for me. I've always liked the speed of Textpad and it does a really good job on large files. I use Eclipse as my main IDE, so when it comes to a Notepad replacement my two main requirements are fast load times and the ability to handle large text files (for reading logs.)

However I keep seeing some of the really cool things that TextMate can do, so I've been keeping an eye out on e - TextEditor. It has a couple of features that would make quick editing of HTML files extremely easy. I really like the ability to selected a bunch of words or tags in a document and easily replace them.

One of the key features of e is it's TextMate bundle support—which really allows you to extend the functionality of the program. While surfing the e forums, I came across a Bundle command which allows you to open the file you have selected in the document (or the file where the caret is positioned.) This script makes it really easy to open files being loading from <script />, <style /> or any other tag you may use for loading files.

The original script, posted by tanguyr, I found either needed you to add e.exe to the Windows PATH environment or you needed to hard code the path to e.exe. I fixed the problem by using one of e's environmental variables. The $TM_SUPPORT_PATH variable points to a sub-directory above where the e.exe file exists, so I just use a relative path to get to the e.exe executable.

To add this command to e, go to the Bundles > Edit Bundles > Show Bundle Editor. I added this script to the Source bundle, as it seemed to make the most sense to me. Select the Source folder and click the + button and select the "New Command" option. I decided to call the command "Open Target Document", if you don't like the name choice something you like better.

Paste the following Bash script into the source area.

more…


The only valid measurement of code quality: WTFs/minute

 WTFs per minute


Using MSSQL to define distinct cross-column relationships...

Someone asked me this morning how they could determine distinct relationships. They wanted to be able to retrieve all the distinct rows where someone had defined another user as a friend or any users who had defined them as a friend. The table schema looked like this:

friend_user1 friend_user2
1 10
2 6
10 1
6 1
2 1
10 2

As you can see friend 1 is pretty popular amongst other users. However, he only has 1 person defined as friend of his—friend 10. What we need to do is to find all distinct cross-column relationships in the table—which means only one row should be returned for the relationship between friend 1 and friend 10.

more…


CommitMonitor notifies you of changes to your SVN repositories

Phill Nacelli blogged about a great tool for monitoring SVN repositories called CommitMonitor from Stefan's Tools. Just last week I set up a post-commit script to e-mail me when updates were commited to a few of my SVN repositories. When you do all your work via telecommuting, staying in touch with updates to your repositories can be somewhat problematic—especially when you have lots of repositories.

I like being proactive and knowing when other developers are adding new committing new code. Some of our repositories aren't frequently updated, so proactive monitoring really helps me stay up-to-date. Up to now my choices were to either configure a post-commit script to e-mail changes or to check the repository logs for changes.

That's all changed with CommitMonitor. It's basically an RSS reader for your SVN repositories. You can set it up to monitor any number of repositories and you can configure how frequently updates are checked for. When CommitMonitor checks the repository any changes will be shown to you via a small pop-up window in the lower right hand corner.

CommitMonitor is a single executable that you can download in a zip file. I've always favored applications that allow you to just unzip and run—it makes it very easy to remove the application if don't like it.

From my brief experience with CommitMonitor I see this tool as being extremely helpful to my workflow.  Go download it now and see how it helps you!