Wednesday, March 12, 2008

What You REALLY Mean with WYMEditor and Symphony

WYMEditor is a great way to enter content into your Symphony site. You can place images, create lists, and even apply custom css classes with very little effort. However, WYMEditor itself does have some limitations. You can't create container elements, so this leads to (among other things)img tags needing to be placed inside p tags. Not cool.

Luckily for Symphonians, XSL can easily handle these shortcomings. In this post, I'll be showing a couple simple xsl templates that can be used to work around some of WYMEditor's limitations.

Usually, when you output the contents of an entry that has been added through WYMEditer, you would use a simple copy-of:

<xsl:copy-of select='my-section/wymeditor-content'>


Copy-of is needed instead of value-of because we want to output all the xhtml tags that are contained within the 'wymeditor' element. But we could also apply more xsl templates to clean up the xhtml that WYMediter has created.

Liberating the IMG tag

One of the most useful features of WYMEditor in Symphony is the handy image browser that ubu put together for the Symphony Campfire Service. Unfortunately, WYMEditor itself doesn't let you place IMGs by themselves, they need to be within other tags. In order to modify how Symphony's XSL processor outputs the IMG tags from WYMEditor, we need to apply-templates to the content of the WYM-created fields:

<xsl:apply-templates select="fields/wymeditor-content/*" mode='content-render'/>

<xsl:template match="*" mode="content-render">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates mode="content-render"/>
</xsl:copy>
</xsl:template>

We're using an XSL mode so our match templates only apply in the context of the WYMEditor content element (I use 'content-render' but the name is arbitrary). The copy element duplicates html tags, but not the contents or attributes of the tag. To do that, we use the copy-of element targeting the tag's attributes, then apply-templates inside the tag. So far, we're getting the same results as the plain old copy-of. Now its time to let our IMG tag out of it's enclosing p tag.

To do so, we add this template:

<xsl:template match="p[./img]" mode="content-render">
<xsl:apply-templates mode="content-render"/>
</xsl:template>


This is a good solution if you just want to avoid putting your images in p blocks. But we can use this concept to do more. To simply delete a p tag from the output, we could add a custom class button (see the WYMEditor documentation) called '.delete-this', and use this template;

<xsl:template match="*[@class='delete-this']" mode="content-render">
<xsl:apply-templates mode="content-render"/>
</xsl:template>


Presto, that p tag is gone. To replace the p tag with a div, just add a 'make-me-a-div' class button, and this template:

<xsl:template match="*[@class='make-me-a-div']" mode="content-render">
<div>
<xsl:apply-templates mode="content-render"/>
</div>
</xsl:template>

Adding Tag Attributes


WYMEditor also has the annoying limitation of not allowing 'rel' attributes, which are useful for things like javascript lightboxes. Using this same method, we can add the necessary rel tags. Lets say I'm using the handy cross-framework Shadowbox viewer. I create a class button called 'rel-shadowbox', and add this template

<xsl:template match="*[@class='rel-shadowbox']" mode="content-render"<
<xsl:copy>
<xsl:copy-of select="@*[not(.='rel-shadowbox')]"/>
<xsl:attribute name='rel'><xsl:text>shadowbox</xsl:text></xsl:attribute >
&t;xsl:apply-templates mode="content-render"/>
</xsl:copy>
</xsl:template>


An important note about manipulating classes: adding an attribute to an element in xsl replaces all existing contents of the attribute. This means if you are using a'marker' class like those I've demonstrated, you'll need to use xsl string functions to remove the marker class but leave the rest in.

Conclusion and Caveats

As you can see, the flexibility of XSL offers a simple and easy-to-use solution to some of the limitations of WYMEeditor. The above examples are only meant to show the concept; your specific needs may vary. The only real caveat to this technique is that it leads to storing xhtml code in your Symphony DB that requires transformation for output i.e. the code becomes dependent on your xsl templates in order to take its desired form. But when the alternative is using CSS to hide the fact that all of your IMGs are wrapped in Ps, then I think this is an acceptable solution.

1 comment:

5chw4r7z said...

Hey, sorry to hijack your
comments, but trying to get in touch and can't see any contact info.
Can you drop me a line, please? Thanks in advance!
This is about a project I have not your comments, no worries.