Solstice Coil

Escaping apostrophes for Javascript in XSLT

Recently I came accross a bit of a challange trying to code up a site that uses XSLT and Javascript. When clicking on a user name, a JS function was called with paramters to bring up details about the user, like this:

<a href="#" onclick="showDetails('Waldo','Camouflage expert','Hard to spot, wears a red striped shirt'); return false">Waldo</a>


The problem was that the data coming from my XML file had apostrophes in it, and Javascript doesn't tend to like them inside strings that are already defined by single quotes. But how do you esacpe characters in XSLT? Well, after much googling I'm happy to say I ended up with a viable solution that works quite well.

First, put this in with your other XSLT templates:

<xsl:template name="globalReplace">
<xsl:param name="source"/>
<xsl:param name="from"/>
<xsl:param name="to"/>
<xsl:choose>
<xsl:when test="contains($source,$from)">

<xsl:value-of select=
"concat(substring-before($source,$from),
$to)"/>
<xsl:call-template name="globalReplace">
<xsl:with-param name="source"
select="substring-after($source,$from)"/>
<xsl:with-param name="from" select="$from"/>
<xsl:with-param name="to"
select="$to"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$source"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>



Then, populate data like this:

  <xsl:variable name="escaped_name">
<xsl:call-template name="globalReplace">
<xsl:with-param name="source" select="Name"/>
<xsl:with-param name="from">'</xsl:with-param>
<xsl:with-param name="to">\'</xsl:with-param>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="escaped_title">
<xsl:call-template name="globalReplace">
<xsl:with-param name="source" select="Title"/>
<xsl:with-param name="from">'</xsl:with-param>
<xsl:with-param name="to">\'</xsl:with-param>
</xsl:call-template>
</xsl:variable>

<xsl:variable name="escaped_description">
<xsl:call-template name="globalReplace">
<xsl:with-param name="source" select="Description"/>
<xsl:with-param name="from">'</xsl:with-param>
<xsl:with-param name="to">\'</xsl:with-param>
</xsl:call-template>
</xsl:variable>

<a href="#" onclick="showDetails('{$escaped_name}','{$escaped_title}','{$escaped_description}'); return false"><xsl:value-of select="Name"/></a>


variable name - of your choice
source - node to be escaped (haystack)
from - character to be replace (needle)
to - character to replace

What this does, essentialy ,is to apply our recursive global replace template to the data in the XML node, and save it in a variable. Then we just pull up the variable using the "value-of" short notation format.
And presto - escaped apostrophe's! (or any  other character for that matter).

Hopefully I suffered the headaches of fighting with XSLT so you won't have to. I'm kinda like Jesus, when you come to think about it...

- opher

Firefox bug prevents Firebug from inspecting anchor elements

It's not often that I come across bugs in Firebug\Firefox, as both softwares usually act very solid but I guess a major one was bound to happen at some point.

So it seems that the latest version of Firefox, 2.0.0.12, fails to show the CSS properties and applied styles of anchor tags (<A>) in the Firebug style window. Meaning - if you enter inspect mode and go over an anchor element, you only get the last element you viewed before that; Firefox won't show you the CSS properties of the anchor element you selected, or other elements inside it. Bummer.

Luckily though Firefox has rather fast version cycles, with the next one (2.0.0.13) planned to be released March 25, hopefully with a fix to this annoying bug. Until then you can downgrade to an older version of Firefox like 2.0.0.11 and continue working as usual.

- opher

Horizontally centering content with dynamic width in CSS

Oh, hai!
You probably came here because you want to know how to dynamically center stuff with CSS. And that's great, because I'm going to show you just that. But wait!
How about you listen to some of my music too? That way you both get the info you want AND you can show off to your friends about this new and cool band that you know about and they don't. Great code and good alternative-progressive rock: It's a win-win situation, really. Enjoy!

Update!
Long overdue, but this solution now finally uses semantic HTML! Yey!

Just returned from a lecture by Christopher Schmitt at the ISOC convention, which was really interesting. He introduced and covered several aspects of CSS to a tough Israeli audience, a congregation that found itself mostly dumbfounded by this "new" technology. Heh, It's about time someone gave those people a nudge. My only caveat with the lecture that he only showed slides and not how live code behaves in a browser. I believe it would have been much more effective had he showed a simple web page and illustrated changes on the fly with Firebug instead of just looking at the code, but maybe that's just me. Anyhow I promised I'll send him my solution to centering content with dynamic width so here it is!

Centering in CSS always requires some amount of work. It's rather easy when you know the exact dimensions of the element you're trying to center - but what happens if you want to horizontally center something of unknown width? For example - a list of links in a footer or a header? After much testing and fiddling around I've come up with a solution that is both viable and cross browser.

The markup goes a little something like this:

<div class="centeringContainer">
	<div class="centered">
		My Content
	</div>
</div>

and the CSS:

.centered{
 	margin-left: auto;
 	margin-right: auto;
 	display: table;
 } 

So what happens here? We're giving our centered span element a display type of "table" rather than "block" or "inline", and since "table" knows how do be centered with auto margins, so does our div. Problem solved...

...or is it? Seems like IE always has a party to poop on and it doesn't like "display: table". Luckily, we can use "display: inline" to switch the div render type from "block" to "inline". This of course requires the entire content to be centered using "text-align: center", hence the centeringContainer div. On top of that, and because of the IE hasLayout bugs we need to enforce the weird propiteray "zoom: 1". This in essence changes nothing in the rendered element, but it does set its hasLayout value to true. So we create an IE only stylesheet file that has this:

.centered{
 	display: inline;
        zoom: 1;
 }
 
 .centeringContainer{
 	text-align: center;
 } 

Slap on conditional comments for IE browsers only that override the default:

<!--[if IE 6]>
	<link rel="stylesheet" href="ie6.css">
<![endif]-->

<!--[if IE 7]>
	<link rel="stylesheet" href="ie7.css">
<![endif]-->

And there you have it. The reason I have two separate conditional stylesheets is just force of habit, since usually I find myself having to rely on these to fix specific bugs in IE6\IE7.

Click here for a clean live example.

- opher
Syndicate content

All content © 2005-2011 Solstice Coil