Widgety Hackery

Final Update: The makers of the “Day in History” widget have changed the code in such a way that there is no longer any way to hack it. Sorry folks. It was Javascript, but is now what appears to be a compiled program. I will not distribute the old hackable version, though perhaps it can be found elsewhere. I will leave this page up for those who still want to see it — perhaps there’s still something to be learned from it. Thanks for stopping by, and I’m sorry I don’t have any better news.

I got my copy of Mac OS X “Tiger” a couple days ago, and promptly fell upon the Widgets feature. I’m a web guy, and widgets (quite brilliantly) are essentially miniature web pages — they are constructed from all the same things you use to make web pages.

This, of course, makes them almost trivially easy to hack.

As I was browsing the Widgets download page, I noticed this one, which is a “Today in History” calendar, listing interesting historic tidbits for today’s (or any other you select) date.

One feature of this Widget is that the entries have links in them, so that if you have the World Book Encyclopedia software installed on your computer, it takes you straight to the related article. That’s all well and good if you have that program, but I figured I could make it a bit more useful — so I rummaged around in the guts of the thing and jimmied it so that the links instead lead you to Wikipedia.

Here’s how to do it:

First off, I did this all in TextWrangler. (You can also use BBEdit if you have it.) If you don’t have TextWrangler, go download it — it’s free! (Truly, this is one of those programs that Apple should just stick on every Mac at the factory!) We’ll be using grep, but don’t worry if you’re not familiar with it, I’ll walk you through it all. (The reason I insist on the two programs listed above is that there are different variations of grep from application to application. BBEdit and TextWrangler, from the same company, have identical implementations.)

Okay, ready? Here we go….

  1. Go download the Widget and install it. To install manually, place it in the /Users/<you>/Library/Widgets/ directory.
  2. In Finder, right-click (control-click) on the Widget file and select “Show Package Contents”. This will open the widget file as a folder.
  3. From the “Day in History” contents folder you just opened, go into the “months” folder. You will see 12 documents, one for each month — “april.js” and so on. Select all of them and open them in TextWrangler.
  4. Under the Search menu (in TextWrangler) select “Find…”.
  5. Okay, here’s where it gets interesting. Make sure the “Use Grep” checkbox is checked. Also check the “Multi-File Search” box. A drawer will slide out of the side of the window. Check the “Open Text Documents” box. All 12 files listed under it should become checked when you do this.
  6. Run the following Find/Replace All:
    Find:
    &lt;a href=.+?&gt;(.+?)&lt;/a&gt;
    Replace All with:
    &lt;a href=\\"javascript: widget.openURL('http://en.wikipedia.org/wiki/\1')\\"&gt;\1&lt;/a&gt;
  7. Next run the following Find/Replace All repeatedly until there are no more matches. (You should have to click “Replace All” six or so times. In TextWrangler you need to re-check the “Multi-File Search” box every time.):
    Find:
    widget\.openURL([^&gt;]+)( ([^&gt; ]+))&gt;
    Replace All with:
    widget.openURL\1_\3&gt;
  8. Third, Find/Replace All the following:
    Find:
    widget\.openURL\('([^']+)'([^']+)'\)
    Replace All with:
    widget.openURL('\1\\\\'\2')

    (Note: this step fixes any links that have a single-quote in the text. If there were any link text strings that had more than one single-quote, this would take two steps, one of which would be repeated like the previous one. Lucky for us, none have more than one single-quote.)

  9. Save and close all documents.
  10. Go into Dashboard and check it out. Either activate the widget as you normally would, or if it was already running, click on it and hit command-R to refresh it.

I’ve been playing with it and it runs like a champ. I think I’m going to have fun with widgets. Put questions in the Comments section. Have Fun! ๐Ÿ™‚

Update: This can easily be modified to accommodate other search sites. For example, to search Google, the Replace string in Step 6 becomes:

&lt;a href=\\"javascript: widget.openURL('http://www.google.com/search?q=\1')\\"&gt;\1&lt;/a&gt;

and the Replace string for step 7 becomes:

&lt;widget.openURL\1+\3&gt;

Yep. That easy. ๐Ÿ™‚

Update 2:

Troubleshooting

From comments I see that some people are having difficulties. I just ran through it again, doing straight “Cut and Paste”s from the strings presented in these instructions into the Find… Replace dialog in TextWrangler, so I know there aren’t any typos. Let’s see if we can figure some of this out….

First off, you can compare your results to mine This is line two of the file “may.js”, after the hack:

[ {text:"&lt;a href=\"javascript: widget.openURL('http://en.wikipedia.org/wiki/May_Day')\"&gt;May Day&lt;/a&gt; (International Labor Day).", cat:2},

Hopefully that right off helps some people spot the problem.

Next are the following things to double check:

  • Did you open all twelve month.js files? In TextWrangler, you should have had a Drawer slide out the side of the window showing all twelve open files.
  • You open the Find…Replace dialog by clicking Find… in the Search menu. At the top of the dialog is the box for the Find string, and at the bottom is the box for the Replace string.
  • Did you check the “Use Grep” checkbox in the dialog window?
  • Did you check the “Multi-File Search” checkbox at the bottom of the dialog window? When you checked it and the drawer slid out of the side of the window, did you check the “Open Text Documents” box and confirm that all 12 files were listed and checked?
  • Did you re-check the “Multi-File Search” checkbox each time you ran the second Find/Replace string?
  • Did you avoid putting any extraneous spaces or linebreaks on the other Find or Replace strings?
  • If nothing seems to have changed when you finished, did you refresh the view of the widget by hitting <command>-r?

If you’re still having trouble, drop me an email with line 2 from the file “may.js” pasted in, so I can get a good look at what’s going wrong.

22 Responses to “Widgety Hackery”

  1. Jeff Harrell Says:

    Great post, Strider. Thanks for this. (I’m not actually a fan of the Wikipedia, so I won’t be following your instructions, but I think the history widget is really neat.)

  2. Strider Says:

    Of course, it could probably be altered to accommodate the site of your choice. I chose Wikipedia because it was an easily parseable URL.
    [edited — see update in main post!]

    I’m also guessing that a real grep wiz could streamline the process a bit (such as removing the need to “repeat until done” step 7.

  3. ErikZ Says:

    Cool hack. I hope you posted this to some sort of wiget group/webpage. ๐Ÿ™‚

  4. Strider Says:

    Z —

    As it is a hack of a presumeably copyrighted widget (which is clearly intended as a “value-add” to commercial software), I chose the better part of valor in posting an actual hacked widget.

    As to posting the _instructions_ to other sites, I haven’t yet. That’s a good idea though…. ๐Ÿ™‚

  5. macdaddy Says:

    I tried the modification but nothing has changed. When I click on one of the links, it will not activate my web browser to access wikipedia. Has anyone else had this problem or am I just doing the mod wrong?

  6. Will Says:

    Yeah, I had problems when i got to the find/replace step. It finds everything but then I don’t know how to replace because I can’t check that box in the find menu. If you could go into some more detail I think that would help. Thanks

  7. Sam Says:

    I’m experiencing the same problem as macdaddy. Everything worked accordingly in TextWrangler, but now the links in the “day in History” widget are dead.

  8. Strider Says:

    I’ve added some troubleshooting info above, as “Update 3” at the end of the post. I hope it helps.

    Is anybody having success? I’d like to hear from you all too! ๐Ÿ™‚

  9. Greg Maletic Says:

    Though I can appreciate why you might want to do this hack, World Book created this widget to promote their brand, not Wikipedia. And it’s probably a violation of their copyright.

  10. Jonas Says:

    Nice _instruction_ you made here! For me it worked without problems. If you strictly follow the instructions, it’s no problem. For those who have to download textwrangler it might me a bit of work, but it’s worth it!
    Thanks again!
    Jonas

  11. Macanally Says:

    I tried the hack, everything replaced fine, the widget restarted and the first entry booted straight into Wikipedia.
    Magic.
    But then the second, third and fourth links didn’t.
    But the fifth, sixth and seventh did.
    Eight to eleven — nada.
    It seems place names link through fine, but anything else just sits there.
    This is pretty bizarre behaviour.
    I checked the sample code line against the troubleshooter above and the two check out.
    Just can’t figure this one out.

  12. Strider Says:

    There are a couple issues with the hack. First and foremost is that I still need to fix a bug affecting any entries that have a single-quote/apostrophe in the link text.

    Second is that a problem a few people seem to be having is step seven, which must be run MULTIPLE TIMES until the find doesn’t have any more matches. The first find/replace will find about 1600 matches, then fewer, then fewer, until I think the 7th attempt finds no matches.

    Third, every time you do a find/replace, you have to again check the “multi-file search” checkbox. TextWrangler clears this after every search, and you have to check it again.

    Good Luck!

  13. pablosed Says:

    It seems to me that all of the links within the widget that are one word work, and all those with a space in between 2 or 3 words are dead, problem with the programming?
    Thanks for the hack though good stuff!

  14. Greg Says:

    It works great for me but I had to do step 7 multiple times like you said but I also had to do step 8 multiple times. Thanks for the hack.

  15. postglock Says:

    Excellent stuff here Strider, nice clear instructions, too. I don’t imagine that hacking freeware will be against the law though, perhaps distributing the hacked software, but once it’s on your computer, you can do what you like! (Especially as it’s just html!)
    Well done!

  16. Wild Bill Says:

    This is excellent.

    I would also like a hack where this program automatically changed the date to the current date.

    I also suggest you re-write your instructions #7 to read the following:

    7. Next run the following Search/Replace ALL repeatedly until there are no more matches. You will have to do this 6 or 7 times, EVEN IF YOU ARE USING Search/Replace ALL.

    (Note: In TextWrangler you need to re-check the รข??Multi-File Searchรข?ย box each time.)

  17. Strider Says:

    SIGNIFICANT CHANGES have been made. I’ve updated the instructions above, streamlining things a bit and fixing what I believe are the only remaining bugs. I eliminated the original first Find/Replace set, and added a new step that fixes a problem with links that contained single quotes, such as “Mother’s Day”.

    I also made some clarifications within the instructions, and added one or two explanatory notes.

    Wild Bill suggests a further hack that I too would love to see (but it’s a bit beyond my ability): one that makes the widget auto-update to today’s date. The easy fix right now is command-r, which refreshes the widget and in the process opens it on today’s date.)

  18. gabeos Says:

    Hello,

    I think I figured out why people were having issues. The grep:

    <a href=”.+?”>(.+?)<\\a>

    Doesn’t match anything. The end should be escaped like so:

    <a href=”.+?”>(.+?)</a>

    I think that will fix at least some of the issues .. it fixed mine.

    [Note: The comment program garbled gabeos’ grep string. This is my best guess as to what he really meant — ed.]

  19. Strider Says:

    Aha! It looks as though they’ve updated the widget. Originally all the links were (incorrectly) closed with <\a>. They’ve fixed it, which requires us to change the first search string.

    I’ll made the change in the instructions above.

  20. Dulli Says:

    I tried the hack and its a wonderfull notion. It seems to work when I do it but beyond a doubt every time I reload the widget it ceases working. This does not apply only to the links the entire widget stops displaying anything on its face. I wonder if you have any idea why this could be happening. My 2nd line of may.js lines up with yours and i followed your instructions through multiples times taking special care to repeat step 7. Any ideas why I have lost the information the widget was originaly displaying?

  21. Strider Says:

    The folks at MacKiev keep changing the widget, and that keeps breaking the hack. This time it’s *really* broken, I ran through it all and got the same result as Dulli. I’ll see if I can fix it again as time permits. Sorry folks — that bit’s out of my hands….

  22. Jerry Greenberg Says:

    In Textwrangler, when I get to step #7, this is the message I receive: The pattern “widget\.openURL([^>]+)( ([^> ]+))>” was not found?
    Now what???
    Thanks

Comments are invited and encouraged

Anti-Spam Quiz: