Saturday, December 11, 2010

jQuery UI Tabs + XSLT + Double Page_Load Event + and carriage return

You know, one of the great things about having ADHD is I now have an excuse for getting side tracked and going on a code jungle adventure to solve bugs of epic proportions.

And that's just what happened this weekend!

I've been using jQuery a lot more right along with ASP.NET MVC 2.  As most, I keep working on old projects and simply bring them up to speed, try different things out, the like.

For those new to jQuery, it is a high performance, micro footprint, JavaScript library that that makes it possible to make client side development as extreme as something like Facebook for developers even like me... Not only that, there are literally thousands of extensions for this thing.  The one I was playing with is known as jQuery UI Tabs

I chose to use an XML/XSL content engine I had written to do some email templating.  I wanted to convert this to a dynamic form that would be driven by XML. Basically, I wanted to create the input form + output(s) from common schema and neither knows of the other or has dependency.  Which is pretty much what XML is there for... ;)

One such feature was to be able to break the input into a friendly / easy to use Form.  Using an XSL transform, It rendered an HTML form of 1..x # of tabs. Without the details of how the whole tab system works, for each tab, you have a
with a unique identifier such as tabs-#.  Where # is a sequential value from 1..x.  Using the syntax

 $("#tabs").tabs();

The XSL that transform to XSL looks like so:

<xsl:template match="tab">
    <xsl:variable name="tabNumber">
      <xsl:number value="position()" format="1" />
    xsl:variable>
 
    <div>
      <xsl:attribute name="id">
          tr_<xsl:value-of select="$tabNumber" />
      xsl:attribute>


Clearly looks clean. Code generates, tabs generate...

but then... something weird happens..  The tabs show up a second time, but this time, no formatting, everything looks horrible on the screen, and the Page_Load is called again by a GET.  Combine this with the dynamic nature of the control, and it becomes incredibly hard to debug.

I disabled all my jQuery/JavaScript I had written.  Still getting a double load.  Not only that, injecting it.  I disabled the tabs portion itself, still coming up twice.  I'm getting a JavaScript runtime error much like when ASP.NET Ajax has two versions (1.0.xxx & 3.5) in the same application.  Checked that... Fine.

Maybe jQuery has a bug in this version (I had downloaded 1.4.2 a few months back), so I upgraded to 1.4.4.  I switched to the Google CDN.  Over and over it kept coming back like a g*d damn zombie!

I go back to my XSL, did I have a script reference in there?  Nothing stands out.

Finally, trusty ol 'View HTML' and your favorite text editor.  Combing line by line, I'm trying to figure it out.  It's not standing out.  Until I finally come to the

<div id="tr_tabs-2">

or that's what I thought it should have looked like........

Not quite though sport!  Looked a little more like

<div id="&#xA;          tr_tabs-2">

Well, that certainly won't be found by tabs, and looks like we might have a little bug if so.  I don't know, I wasn't going to full investigate it.  I wanted to fix this and be done.  Why would this happen?  Back to XSL

Ends up, Visual Studio and some editors like to put extra spaces and XSL doesn't like concating + string trimming without using XSL functions. 

Remember this nugget?


<div>
      <xsl:attribute name="id">
          tr_<xsl:value-of select="concat('tabs-', $tabNumber)" />
      xsl:attribute>


That little tr_ constant throws the whole thing off.  If you change it to (you will also notice the added spacing in Visual Studio when pressing delete)   It works.


<xsl:attribute name="id">tr_<xsl:value-of select="$tabNumber" />xsl:attribute>

However, knowing how I like to hit Format Document, and this seemed like an easy mistake to make, I couldn't imagine this was the best way.  Nope!  of course not.  Using the XSL function (concat) solved this easily and still can use my format document feature in VS!  

<div>
      <xsl:attribute name="id">
        <xsl:value-of select="concat('tr_tabs-', $tabNumber)" />
      xsl:attribute>


No more double GET and odd behavior.  I hope this helps someone!

No comments:

Post a Comment