Koumpounophobia 0.4 Now Available

Post to Post Links II error: No post found with slug "koumpounophobia-wordpress-plugin" is a WordPress plugin that enhances the HTML Editor in several ways, giving you new buttons, modal dialogs, and the ability to add your own buttons.

The new version 0.4 is compatible with Internet Explorer 7 and 8. It also fixes the “scroll position” bug in Firefox 3 (the editor no longer scrolls to the top after you use a Koumpounophobia modal dialog). It’s available for download at wordpress.org.

Getting it to work with Internet Explorer took a lot of research, but in the end it required only a few additional lines of code. The problem was that IE would forget the cursor position in the editor when you used a modal dialog, causing your tag to always be inserted at the beginning of your post. If you do a search for “textarea cursor position” you’ll see a lot of electrons being spilled by others trying to solve this problem for their own projects. I’ll write a separate post on this, as the solution in many cases doesn’t require the dozens and dozens of lines of code that a lot of people are using.

Web Consulting Projects Wrap-Up

Last year I had several web consulting projects. I just finished the last of them, and I’m not planning on doing any more, so I figure now’s a good time to post a wrap-up. All 5 of these sites are running on WordPress.

Boxing Dragons - Original Asian ArtBoxing Dragons – Original Asian Art

Boxing Dragons – Original Asian Art

Body of Knowledge - Personal TrainingBody of Knowledge – Personal Training

Body of Knowledge – Personal Training

The Hope Funds for Cancer ResearchThe Hope Funds for Cancer Research

The Hope Funds for Cancer Research

 
Kai's Candy CompanyKai’s Candy Company

Kai's Candy Company

Newport Homes for SaleNewport Homes for Sale

Newport Homes for Sale

 
  • Body of Knowledge Personal Training: the most interesting part of the site is accessible only by their clients. I created a custom WordPress plugin that enables their clients to schedule appointments online. The plugin synchronizes the appointments with Body of Knowledge’s Google Calendar, and on the administrative side, provides invoicing and other bookkeeping capabilities.
  • Newport Homes for Sale – Terry Toppa, Broker Associate: you may recognize the last name 😉 . This is a site for my Dad’s real estate listings. It uses my Post to Post Links II error: No post found with slug "shashin-wordpress-plugin" and Post to Post Links II error: No post found with slug "deko-boko-wordpress-plugin". His friend Jim is a photographer, and he provided some fantastic pictures of Newport that really bring the site to life.
  • Boxing Dragons – Original Asian Art: I didn’t come up with the graphic designs on the other sites listed here, but I did for this one. I am by no means a graphic designer, but I can fake it sometimes. This site is over a year old now, and drove a lot of the improvements that went into Shashin 2.0 last year.
  • Kai’s Candy Company: this was my own business (why can’t I count myself as a client? 😉 ), which is now closed. I worked with a wonderful graphic designer, Paula Weindel, who created the site design for us. Our business volume never justified implementing a full-fledged shopping cart; Google Checkout served our needs just fine. After the business closed, I moved the site to free hosting with Google Page Creator.
  • The Hope Funds for Cancer Research: this project involved converting a static site to a dynamic one, and training their staff to use WordPress so they can manage most of the site without needing programming skills.

Post-to-Post Links II Now at WordPress.org

Post-to-Post Links II is a plugin for creating links to other posts, pages, tags, or categories on your WordPress site, and it’s now available for download at wordpress.org. I also created Post to Post Links II error: No post found with slug "post-to-post-links-wordpress-plugin".

There are a couple improvements with this version:

  • Now you can use it with tag slugs and tag IDs too
  • Fixed a bug with using category slugs

As explained in the readme file, it unfortunately can’t interpret the tags from Scott Reilly’s old “Easy Post-to-Post Links” plugin. I used his plugin heavily, and if you want to convert your old tags for use with my new plugin, you can. Doing so requires 1. you to be comfortable running a SQL query and 2. that you consistently used only post slugs or only IDs with Scott’s plugin. If you used IDs in some tags and slugs in others, then you can’t make the conversion (as there’s nothing in the syntax of Scott’s tag itself that indicates whether you’re linking by ID or slug).

These are the steps:

  1. Make a backup of your WordPress database, or at least the wp_posts table. This is very important, in case you make a mistake in the SQL.
  2. Run this SQL statement if you always used slugs for your links:
    update wp_posts set post_content = replace(post_content,'[post=','[p2p type="slug" value=');

    Or run this SQL statement if you always used IDs for your links:

    update wp_posts set post_content = replace(post_content,'[post=','[p2p type="id" value=');

I use the “text” attribute the same way Scott did, so that portion of the tag will carry over seamlessly in the conversion.

Koumpounophobia Now at WordPress.org

Koumpounophobia is a plugin for adding custom buttons to the WordPress HTML Editor, and it’s now available for download at wordpress.org. I also created a Post to Post Links II error: No post found with slug "koumpounophobia-wordpress-plugin".

I’ve made a few improvements with this version:

  • Now uses the jQuery plugin UI Dialog for controlling the modal input dialogs
  • Fixed bug with buttons for self closing tags that don’t use an input dialog (the button mistakenly tried to add a closing tag)
  • Simplified the HTML and CSS for the form input dialogs

If you made your own input dialogs based on the initial release, the HTML needed is now simpler. Please see the dialogs.html in the new version.

If you were using the initial release in conjunction with Post-to-Post Links II, you’ll want download a fresh copy of Post-to-Post Links II as well (not at wordpress.org yet, but it’ll be there soon now also at wordpress.org).

It still doesn’t work correctly in Internet Explorer 🙁 But I haven’t given up…

Practical XSLT Examples: Transforming an XML Document to XHTML

Having been involved with only one significant XSLT project using PHP (the PennMed Clinical Trials project), I don’t consider myself an expert. I did run into some issues, however, that required me to go beyond what was available in the online tutorials I found, and to dig into discussion forums, as well as figure out some things on my own. I’ll share some of those experiences here, with practical examples of transforming an XML document to XHTML. This is not a general introduction or tutorial. For that, I recommend the w3schools.com XSLT Tutorial.

  1. Should you perform the transformation on the client side or server side? Unless you have some special reason not to, I recommend transforming on the server side. Why make yourself deal with possible cross-browser compatibility issues in your XSL code, when you can instead have the server do the transformation, and send the browser nice, tidy XHTML instead?
  2. Using PHP’s XSLTProcessor: the PHP portion of the transformation is straightforward. The 7 lines of code in the example on the php.net site is very similar to the code I used in my application.
  3. The XML file: here’s a sample XML file from my project. It’s a document describing a clinical trial. My examples below will come from this document.
  4. Your XSL stylesheet’s outermost template match: everything I read said the outermost template match in your XSL file should be:
    <xsl:template match="/">

    which indicates the root of the document tree, therefore giving you access to all the document’s content. I disagree with this recommendation, at least as far as my project goes. The clinical trials XML documents have all their content contained in a single “clinical_study” tag. Therefore my outermost template match is:

    <xsl:template match="clinical_study">

    This way, I don’t have to repeat “clinical_study/” in every child XSL tag.

  5. Tags that appear only once: it’s vital to fully understand the XML documents you’re processing, so you know which tags might appear multiple times, and whether they have child tags. Tags that appear only once are the easiest to process. Here’s an example of how to display the value of such a tag; this is from a list of eligibility criteria for a clinical trial:
    <li>Gender: <xsl:value-of select="eligibility/gender"/></li>
  6. Tags that appear multiple times, without children: A clinical trial can address one or more medical conditions. They are listed in the XML like this:
    <condition>Metastatic Anaplastic Thyroid Cancer</condition>
    <condition>Metastatic Differentiated Thyroid Cancer</condition>

    Looping through them requires applying a separate xsl template tag. At the point in the XSL stylesheet where we want the conditions to be displayed, we apply the template like this:

    <ul>
    <xsl:apply-templates select="condition"/>
    </ul>

    Then near the end of the XSL stylsheet, after we close the main “clinical_study” template, we define this template:

    <xsl:template match="condition">
        <li><xsl:value-of select="."/></li>
    </xsl:template>

    The “.” indicates that we want to select the value of the tag itself (analagous to a “.” when listing the contents of a directory, which refers to the directory itself).

  7. Tags that appear multiple times, with children: the clinical trials XML documents can have one or more “location” tags (the example here happens to have only one). In our transformation, we want to display the contact information for the studies where the location is the University of Pennsylvania or the Children’s Hospital of Pennsylvania. As before, we indicate the template tag to apply, but this time with a conditional test which I’ll explain below:
    <xsl:if test="location/facility[contains(name,$upenn) or contains(name,$chop)]">
        <h3>Local Contact</h3>
        <xsl:apply-templates select="location" mode="contact"/>
    </xsl:if>

    …And the template:

    <xsl:template match="location" mode="contact">
        <xsl:if test="contains(facility/name, $upenn) or contains(facility/name, $chop)">
            <p>
            <xsl:choose>
              <xsl:when test="contact/last_name">
                <xsl:value-of select="contact/last_name"/>
                <xsl:if test="contact/phone">, <xsl:value-of select="contact/phone"/></xsl:if>
                <xsl:if test="contact/phone_ext"><xsl:text> </xsl:text>x<xsl:value-of select="contact/phone_ext"/></xsl:if>
                <xsl:if test="contact/email">, <a href="mailto:{contact/email}"><xsl:value-of select="contact/email"/></a></xsl:if>
              </xsl:when>
              <xsl:otherwise>
                A local contact person has not been assigned yet.
              </xsl:otherwise>
            </xsl:choose>
            <br />
            <xsl:value-of select="facility/name"/><br />
            <xsl:value-of select="facility/address/city"/>, <xsl:value-of select="facility/address/state"/><xsl:text> </xsl:text><xsl:value-of select="facility/address/zip"/><br />
            </p>
        </xsl:if>
    </xsl:template>

    There’s a lot going on here…

  8. Variable scope: You can define your own variables in XSL:
    <xsl:variable name="chop">Children's Hospital of Philadelphia</xsl:variable>

    It’s important to note that they are scoped tightly. If you define or alter the value of a variable within a loop, that value will be gone when the loop ends. In this case I defined my variables near the top of the document, before the “clinical_study” template, so they are available for use in any template in the stylesheet.

  9. Testing for a condition in multiple tags: The use of XPath predicates allows us to search through all of the “location” tags in the XML document. Note that this:
    <xsl:if test="location/facility[contains(name,$upenn) or contains(name,$chop)]">

    is not equivalent to:

    <xsl:if test="contains(location/facility/name,$upenn) or contains(location/facility/name,$chop)">

    The former searches all the “location” tags in the document for Penn or CHOP, and we’re using it to determine whether we should show the “Local Contact” section. We use code similar to the latter within the “location” template, as we check each location (if we tried to use it in the main clinical_study template, it would check only the first “location” tag in the document).

  10. The template “mode” attribute: in my XSL I need to loop through the “location” tags more than one time, and for more than one purpose. I loop through them once to get contact information, which is what this template is for. I loop through them again later in the stylesheet to extract information on the Investigators leading the trials. For that I have a different “location” template with mode=”investigator”.
  11. Handling quotes: the reason I defined a variable for CHOP instead of running the “contains” test on a plain string is that the XSL processor will throw an error on the apostrophe in “Children’s”. Unlike XHTML, it’s not valid syntax to put single quotes within a double quote delimited string.
  12. Referencing XML values within an XHTML tag: To get the contact person’s email address in a “mailto” link, we delimit the value in curly braces – <a href="mailto:{contact/email}">. The curly braces extract the value of the tag.
  13. Adding spaces: ther XSL parser aggressively strips spaces. It will honor spaces between words in your stylesheet, but it will strip spaces between tags. To force a space, use <xsl:text> </xsl:text> (this one took a while for me to track down, as discussion forum posts I found on this topic focused on using entities as the solution, but that is not an elegant approach, as &nbsp; is not a native XML entity, and this wouldn’t be a semantically correct use of it anyway). The parser doesn’t do this just to be annoying. If you were using it to create, for example, a PDF document, you would be glad it aggressively strips spaces, as stray spaces could cause major headaches in that context.

Two New WordPress Plugins: Koumpounophobia and Post-to-Post Links II

Update: Koumpounophobia is now at wordpress.org and so is Post-to-Post Links II. I’ve updated the download links below.

I’m releasing beta versions of two new WordPress plugins: Koumpounophobia and Post-to-Post Links II. I’ll create documentation pages for them soon. In the meantime please see the readme.txt files that come with them for details. Here’s the overview:

Koumpounophobia

Koumpounophobia is powered by jQuery, and enhances the WordPress HTML Editor button bar in 5 ways:

  1. It replaces the anchor and image buttons with new versions that provide input dialogs with more options (image width, height, etc.)
  2. It adds two new buttons: div and span, each with their own input dialogs (for class, style, etc. attributes)
  3. It lets you add your own buttons and create custom input dialogs for them
  4. It provides an API for other plugins to add buttons and custom input dialogs
  5. You have total control over which Koumpounophobia-based buttons will appear in the button bar

This is a beta release, and since it involves some fairly intricate JavaScript code, browser compatibility is an issue. In my testing so far it works beautifully in Firefox 3 and Google Chrome. It does not work well in IE 6, 7, or 8 (even without Koumpounophobia installed, the HTML Editor has some problems in IE8). I’d appreciate feedback on how it works in other browsers (please leave a comment on this post – let me know your operating system too).

If you’re wondering about the name, Koumpounophobia is a phobia of buttons. I learned about it because my 3 year old has a mild case of it (he won’t wear anything with buttons, and he won’t let you hold him if you’re wearing buttons). I thought the name was appropriate since there haven’t been any improvements to the WordPress HTML Editor in years – someone must be afraid of the buttons 😉

This plugin was a real challenge to create because the WordPress “quicktags” code that creates the HTML Editor’s button bar was not written with customization in mind. It has no hooks for runtime access. This is why so few plugins add buttons to the HTML Editor, while the Visual Editor, with its well documented API, is lavished with attention. Those of us who like to work directly with the HTML deserve some nice buttons too!

Download Koumpounophobia

Post-to-Post Links II

Using the Post-to-Post Links II shortcode in your posts and pages, you can create links to other posts, pages, or categories on your WordPress site. You use the ID number or the slug to identify the post, page, or category for your link. The link will use its title as the link text, or you can supply your own link text. See the readme.txt file for examples of the shortcode syntax.

It makes linking within your site more convenient, and it means your links won’t break if you ever change your permalink structure or re-arrange your categories.

This plugin was inspired by the Easy Post-to-Post Links plugin written (but no longer maintained by) Scott Reilly. Unfortunately though, it cannot interpret the old Easy Post-to-Post Links tags. Post-to-Post Links II uses WordPress’ robust Shortcode API, which is not compatible with the syntax Scott used in Easy Post-to-Post Links. (Update: but you can convert them – see here)

I’m releasing it at the same time as Koumpounophobia because it uses the Koumpounophobia API to register a new button for the HTML Editor. So if you want a handy button for its shortcode, install Koumpounophobia too. Or if you’re a plugin developer, it’s a good working example of how to add buttons to the HTML Editor using Koumpounophobia.

Download Post-to-Post Links II

Shashin 2.3.5 Now Available

I had hoped to finish version 2.4 by now, but I’ve been busy with other projects and haven’t had enough time for it. So I’m releasing 2.3.5, which will be the final patch for version 2.3. There were a few bugs that people discovered since the last patch, and I don’t want to delay getting the fixes out. You can download it from wordpress.org, or if you already have a previous version installed, your plugin menu should give you a link within the next 24 hours to automatically upgrade.

Patches aren’t supposed to have new features, but this has a couple small ones, since I had already finished working on them.

  1. In addition to floating left or right, you can use “center” as an option for positioning your shashin tags and widgets. For example:
    [simage=600,576,y,center]

    This gives the picture with key 600 a width of 576, shows the caption, and centers the picture. Shashin uses the CSS “margin-left: auto; margin-right: auto;” technique to center the picture. This means you can leave out the “clear” argument if you’re centering, as the subsequent content will be automatically pushed below the picture.

  2. The simage tag has a new, optional 6th argument, which lets you specify an alternate thumbnail image. This is particularly useful for videos, as sometimes Picasa is unable to generate a thumbnail (I’ve run into this with a couple of mp4 videos, where the Picasa-generated thumbnail is just a solid black image). You can see it in Post to Post Links II error: No post found with slug "takanawa-yochien-kindergarten-video". The thumbnail is a still frame from the middle of the video. The syntax looks like this:
    [simage=432,288,y,left,none,433]

    The number at the end is the photo key for the thumbnail image to use. Note this option is available only for the simage tag.

These are the bug fixes:

  • Fixed incomplete localization code for widget menus
  • In the album photo admin menu, now correctly saves whether photos should be included in random display
  • The salbumphotos tag can now handle sort order options with spaces (e.g. “pub_date desc”)
  • The salbumphotos tag no longer shows a “go back” link, as there’s nothing to go back to

Penn Medicine Clinical Trials

The Clinical Trials search site I developed. My co-worker Joe created the design.The Clinical Trials search site I developed. My co-worker Joe created the design.

The Clinical Trials search site I developed. My co-worker Joe created the design.

 

In the six years I’ve been working at Penn, this is my first project that’s publicly accessible: Penn Medicine Clinical Trials. It’s a web application to help researchers as well as the general public find clinical trials at the U Penn School of Medicine and the Children’s Hospital of Philadelphia. My co-worker Joe did a great job on the design, and I implemented the functionality. Joe gets the credit for the Google-like “less is more” user interface, which is dramatically different from the clinical trials sites at other leading medical research institutions.

I wrote a script that runs nightly to pull down XML documents on the clinical trials from ClinicalTrials.gov (a website created by the National Institutes of Health to provide a central clearinghouse for information relating to clinical trials in the US). The script then parses out the most important data and puts it in a database, where its used for full text searching. For displaying the pages on each trial, I created an XSL template that’s used to dynamically transform the XML documents for display as web pages.

This was actually part of a larger project – the redesign and relaunch of PennMed’s ITMAT (Institute for Translational Medicine and Therapeutics) web site. Joe created that design as well, and I provided the functionality for the member pages. These pages are dynamically updated as members update their profiles and new members join.

I have a few posts in mind based on this work, as I solved some problems on my own where there weren’t adequate explanations online. The topics are XML handling with PHP’s SimpleXMLItetator, XSL transformations with PHP’s XSLTProcessor, and an interesting CSS problem with the Clinical Trials “sticky footer” that we had to figure out. Stay tuned.

Making Unrelated WordPress Posts Look Like They Are In The Same Category

In my page header you’ll see there’s the linked photo for “Japan and Other Travel.” I recently decided to separate my “Japan” category from my “Travel” category, since I’ve been writing a fair number of posts about Japan that aren’t directly related to my travel there. But I still have plenty of posts that are about my time in Japan. So supporting that link in my header became a problem since WordPress doesn’t have the concept of multiple category parents (that is, WordPress can only display posts together on a page if they are in the same category, or have a common category parent).

One solution would be to use tags – to give all my “Travel” and “Japan” posts a common tag, and then link to the tag. That’s a perfectly good solution, but I decided against it because I’m lazy. I’m not currently using tags at all, and I don’t want to go back and update something like 150 posts with the new tag. Even if I wrote a database query to take care of the old posts in a single batch, I’d still have to always remember to put any new posts under the right category and the right tag. In addition to being lazy, I’m also forgetful.

Instead, I did the following:

  1. I created a new top-level category named “Japan and Other Travel,” and I made a note of the category ID number assigned to it. This category will be an empty shell. I won’t ever assign any posts to it.
  2. I created a new template in my theme named category-96.php. That number in the filename is the ID number that was assigned to the category. When displaying a category page, WordPress will automatically first look for a template specific to that category before moving on to a catch-all template.
  3. category-96.php consists of nothing more than the following lines of code:
    <?php
    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    query_posts("cat=42,92&paged=$paged");
    require_once(TEMPLATEPATH . '/index.php');
    ?>

    This uses some of the same code that’s in a post I wrote last year, about how to limit the categories that appear on your home page. Normally this category page would have nothing on it, since I don’t have any posts assigned to it. The call to query_posts() overrides that, and instead gets posts from the two category ID numbers that I passed to it. The $paged variable keeps track of which page someone is on if they click links to see older entries in the category. The require_once() call pulls in the index.php file for my theme to display the posts (if my theme had a category.php file, I would have used that instead).

And that’s it! The empty category doesn’t show up in my category list in the sidebar, because by default wp_list_categories() excludes categories with no posts in them.

I like this solution because now that I’ve set it up, I can go back to being lazy and forgetful.

Shashin 2.3 Now Available at wordpress.org

Beta testing is now done, and Shashin 2.3 is available for download from wordpress.org. If you have the beta version, go get the final version from wordpress.org. Thanks very much to everyone who helped with testing – you found bugs that I had missed and provided helpful feedback on the new features.

Update 2/10: …even more bug fixes – version 2.3.4 is now available. A few people using Shashin with WordPress on Windows were having problems adding certain photos. This is fixed now (the problem had to do with photos that had no date indicating when they were taken – mySQL on Windows insists on having a date). Also, the [salbumlist] tag is now working again (I overlooked it in my previous testing). Lastly, you can now put more than one [salbumthumbs] or [salbumlist] tag on a page (it never occurred to me to try this, but someone wanted to, and now it’ll work).

Update 1/30: Yet another minor release is now available – version 2.3.3. I rewrote the album syncing method for faster performance. There should be a noticeable improvement when clicking “sync all,” especially if you have a lot of albums (or a lot of photos in your albums). I also fixed a bug – Shashin wasn’t correctly updating its photo data when an album was moved from one Picasa album to another. Shashin can now also handle a # character at the end of album URLs when adding an album (the # appears in certain Picasa links – it’s not actually part of the album URL, and it was tripping up the RSS feed).

Update 1/25: Another bug fix release is now available at wordpress.org – version 2.3.2. This is an important one, so please upgrade. You’ll need to deactivate and then reactivate Shashin after uploading the new version. It fixes a problem with albums getting added multiple times when you try to sync albums. It also fixes a problem with the album thumbnail widget – it now automatically links the album thumbnails to Picasa, instead of trying to load all your photos in the sidebar. And it includes the first localization file contribution – Shashin in Dutch!

Update 1/23: I just updated Shashin at wordpress.org with a couple of bug fixes (version 2.3.1). It wasn’t loading language localization files correctly, and in certain situations it was reporting a database error when there wasn’t one. Both problems are fixed.