Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • trfletch 598 posts 604 karma points
    Nov 03, 2009 @ 18:10
    trfletch
    0

    Drop down filter using XSLT

    I'm not sure this is possible with XSLT but wanted to check anyway. I have an Umbraco V4 installation and I have a page that lists its child pages and the content of them (it's actually a list of comments but that doesn't really matter). Currently it lists all the child pages but I want the user to be able to filter the comments shown with a dropdown menu (the comment contains a property type called 'commenttype' that I want to filter by). Is this possible using just XSLT or would some sort of user control be required (I don't really have any .net experience so I would prefer if I could do it with XSLT). The XSLT that currently lists the comments is as follows:


    <xsl:for-each select="$currentPage/node">
      <xsl:sort select="@createDate" order="descending"
    />
      <span class="name"><xsl:value-of select="data [@alias = 'name']"/></span><br/>
      <span class="commenttype"><em><xsl:value-of select="data [@alias = 'commenttype']"/>:</em></span>
        <p><xsl:value-of select="data [@alias = 'comment']"/></p>
    <p class="small">Posted: <xsl:value-of select="umbraco.library:FormatDateTime(@createDate, 'dd MMMM yyyy')"/></p>
         <xsl:if test="data [@alias = 'attachment'] !=''">
        <a target="_blank">
          <xsl:attribute name="href">
        <xsl:value-of select="data [@alias = 'attachment']"/>
        </xsl:attribute><img src="/images/attachment.jpg" />&nbsp;View attachment</a>
      </xsl:if>
    <hr />

    </xsl:for-each>
  • dandrayne 1138 posts 2262 karma points
    Nov 03, 2009 @ 21:54
    dandrayne
    1

    I see two options here:

    1.  xslt:  You'd probably need to post back to the page  in order to activate some kind of filter for the xslt to act on, like

    <xsl:variable name="commentTypeFilter">
    <xsl:choose>
    <xsl:when test="string-length(umbraco.library:Request('commenttype')) &gt; 0">
    <xsl:value-of select="umbraco.library:Request('commenttype')"/>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="''"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:variable>

    Then you'd have a filter in order to pick out only the commenttype you want in xslt in your for-each.

    You'd also need to create a  dropdown of all the comment types, so if you don't want to hard-code it you'd need something like the following to get a unique list for a dropdown

    <xsl:variable name="unique-list" select="$currentPage//node/data[@alias='commenttype' and not(.=following::node/data[@alias='commenttype'])]" />
    <select id="comment_type" name="comment_type">
    <option value="">Please choose</option>
    <xsl:for-each select="$unique-list">
    <xsl:sort order="ascending" data-type="text" />
    <option value="{.}">
    <xsl:value-of select="." />
    </option>
    </xsl:for-each>
    </select>

    Then just a form around the select posting back to the page (or a little javascript).

    2.  Javascript:  Give each comment a class with the commenttype, show and hide by class with jquery whatever.

    I'd probably go for number 1, it depends how many comments you're expecting though

    Dan

     

     

  • trfletch 598 posts 604 karma points
    Nov 04, 2009 @ 11:25
    trfletch
    0

    Sorry for my ignorance but would the first piece of XSLT you mentioned go into the XSLT I already have for listing the comments and the second part (the one for the select box) go into a separate XSLT file?

  • dandrayne 1138 posts 2262 karma points
    Nov 04, 2009 @ 13:53
    dandrayne
    0

    Yep, the second piece of xslt would probably go in a separate file, depending on where you want the filter to be.  I'd put that separately in a macro and just place it where you want your select field to go

    For the first piece you'd just alter your for-each like (beware freely typed code following!)

    <xsl:choose>
    <xsl:when test="commentTypeFilter != ''">
    <xsl:for-each select="$currentPage/node [string(./data [@alias='commenttype') = '$commentTypeFilter'">

    </xsl:for-each>
    </xsl:when>
    <xsl:otherwise>
    <!-- Your normal loop -->
    </xsl:otherwise>
    </xsl:choose>

    Dan

  • trfletch 598 posts 604 karma points
    Nov 04, 2009 @ 16:51
    trfletch
    0

    Ok thanks, I have now modified my XSLT with what you said above plus a few corrections :-)
    Just wondered how I go about creating the postback form for the select control? Will it not cause a problem because the master template contains a form and I thought you couldn't have a form within a form?

  • Josh Townson 67 posts 162 karma points
    Nov 04, 2009 @ 16:57
    Josh Townson
    0

    You are right - you can't have a form within a form. Try this:

    <select id="comment_type" name="comment_type" onchange="document.forms[0].submit()">
    ...
    </select>

    That will submit the first form found on the page (should be the only 1 in .NET's model)

  • dandrayne 1138 posts 2262 karma points
    Nov 04, 2009 @ 16:58
    dandrayne
    0

    Yeh that will be an issue.  You could either remove the form surrounding the textarea and apply more 'locally' where it is actually needed, or do something like (in jQuery, again freely typed and untested!)

    $(".selectClass").change( function() {
    window.location = window.location+"?commenttype="+$(this).children(option:selected).text();
    });


    This could also be done in pure javscript or in your preferred library

    Hope this helps,
    Dan

     

  • trfletch 598 posts 604 karma points
    Nov 04, 2009 @ 17:13
    trfletch
    0

    Hi Josh,

    Thanks for the response, I did try what you said but unfortunately it did work because I have another form on my page that is used to fill in the comment in the first place and what you suggested tries to submit that form when selecting something from the drop down list.

  • trfletch 598 posts 604 karma points
    Nov 04, 2009 @ 17:15
    trfletch
    0

    Hi Dan,

    Thanks for the response, I am not that familar with jquery, where exactly would I put the code you suggested and unfortunately i don't know what you mean by doing it in pure javascript or in my preferred library.

  • dandrayne 1138 posts 2262 karma points
    Nov 04, 2009 @ 17:25
    dandrayne
    1

    Something like the following, changing selectClass to your class or id of the select field

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
    <script type="text/javascript">

    $(function() {
    $(".selectClass").change( function() {
    window.location = window.location+"?commenttype="+$(this).children(option:selected).text();
    });
    });

    </script>

    Although it (jQuery) does seem like a lot of overhead just to submit a form.

    Dan

  • dandrayne 1138 posts 2262 karma points
    Nov 04, 2009 @ 17:27
    dandrayne
    0

    p.s.

    children(option:selected)

    Should be

    children("option:selected")

    (still untested though!)

    Dan

  • Josh Townson 67 posts 162 karma points
    Nov 04, 2009 @ 18:07
    Josh Townson
    0
    <select id="comment_type" name="comment_type" onchange="this.form.submit()">
    ...
    </select>

    This should submit the form the select element is in. Personally I prefer Dan's option - it is cleaner and more pure, but only if you're already got jQuery on the page. Alternatively, you could write some actual javascript code to do what Dan is suggesting (it would just be a lot longer than in jQuery).

    Just FYI - jQuery is a javascript library (its very good) - which means it makes doing things in javascript really easy, but adds a significant amount to be downloaded (mitigated in the case of multiple pages or using a shared jQuery resource).

  • trfletch 598 posts 604 karma points
    Nov 04, 2009 @ 18:11
    trfletch
    0

    Thanks for the response, maybe I am being a bit dumb but I now have the following which does show a drop down list populated by any comment types I have but when I select one of the comment types from the list nothing happens not even a javascript error.

     

      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
    </script>
      <script type="text/javascript">
        $(function() {
          $(".comment_type").change( function() {
            window.location = window.location+"?commenttype="+$(this).children("option:selected").text();
          });
        });
      </script>
  • dandrayne 1138 posts 2262 karma points
    Nov 04, 2009 @ 20:57
    dandrayne
    0

    Hmm.  I found this quite interesting, as I can see a few uses of it.  There's a major flaw in my earlier code, in which the querystring will keep getting appended to the current page so it's not very usable.  Here's a solution I was able to work up (test page at http://allbutlost.com/umbtest/)

    <style type="text/css">
    select.comment_type { display:none }
    </style>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {

    $(".comment_type").show().change( function() {
    window.location = location.href.substring(0,location.href.indexOf('?'))+"?commenttype="+$(this).children("option:selected").text();
    });

    });

    </script>

    In this I only get the first part of the string to post back to, and I've also hidden the select box with css, then shown it again with jquery.  This way people without js turned on won't see a useless select box.  The test page seems to work fine.

    Dan

    p.s.  I've used text() to get the actual text from the select box.  If you want the value change this to val()

     

     

  • trfletch 598 posts 604 karma points
    Nov 05, 2009 @ 18:48
    trfletch
    0

    Once again, thanks for the response, I have added the code in the post above to my masterpage in the head section and I have the follow code in my drop down XSLT and List Comments XSLT but when I select something from the drop down box nothing happens. Am I missing something?

    Dropdown XSLT:

    <xsl:variable name="unique-list" select="$currentPage//node/data[@alias='commenttype' and not(.=following::node/data[@alias='commenttype'])]" />
      <select id="comment_type" name="comment_type">
        <option value="">Please choose</option>
        <xsl:for-each select="$unique-list">
          <xsl:sort  order="ascending" data-type="text" />
          <option value="{.}">
            <xsl:value-of select="." />
          </option>
        </xsl:for-each>
      </select>

    List comments XSLT:

    <xsl:choose>
      <xsl:when test="commentTypeFilter != ''">
        <xsl:for-each select="$currentPage/node [string(./data [@alias='commenttype']) = '$commentTypeFilter']">
         <xsl:sort select="@createDate" order="descending"/>
      <span class="name"><xsl:value-of select="data [@alias = 'name']"/></span><br/>
      <span class="commenttype"><em><xsl:value-of select="data [@alias = 'commenttype']"/>:</em></span>
        <p><xsl:value-of select="data [@alias = 'comment']"/></p>
    <p class="small">Posted: <xsl:value-of select="umbraco.library:FormatDateTime(@createDate, 'dd MMMM yyyy')"/></p>
         <xsl:if test="data [@alias = 'attachment'] !=''">
        <a target="_blank">
          <xsl:attribute name="href">
        <xsl:value-of select="data [@alias = 'attachment']"/>
        </xsl:attribute><img src="/images/attachment.jpg" />&nbsp;View attachment</a>
      </xsl:if>
    <hr />
        </xsl:for-each>
      </xsl:when>
      
      <xsl:otherwise>
         <xsl:for-each select="$currentPage/node">
           <xsl:sort select="@createDate" order="descending"/>

      <span class="name"><xsl:value-of select="data [@alias = 'name']"/></span><br/>
      <span class="commenttype"><em><xsl:value-of select="data [@alias = 'commenttype']"/>:</em></span>
        <p><xsl:value-of select="data [@alias = 'comment']"/></p>
    <p class="small">Posted: <xsl:value-of select="umbraco.library:FormatDateTime(@createDate, 'dd MMMM yyyy')"/></p>
         <xsl:if test="data [@alias = 'attachment'] !=''">
        <a target="_blank">
          <xsl:attribute name="href">
        <xsl:value-of select="data [@alias = 'attachment']"/>
        </xsl:attribute><img src="/images/attachment.jpg" />&nbsp;View attachment</a>
      </xsl:if>
    <hr />
          </xsl:for-each>

      </xsl:otherwise>
      </xsl:choose>
  • dandrayne 1138 posts 2262 karma points
    Nov 05, 2009 @ 19:53
    dandrayne
    0

    Hmm, should work fine...  a few Qs

    1. Does the querystring get appended to the url? 
    2. Are there any javascript errors?
    3. When you view source can you see the javascript on the page?

    And is there a demo page I can look at?

    Dan

  • trfletch 598 posts 604 karma points
    Nov 09, 2009 @ 13:52
    trfletch
    0

    Hi Dan,

    No the querystring does not get appended.

    There are no javascript errors.

    You can see the javascript in the source of the page.

    Demo page here http://ideas.imprezait.co.uk/test.aspx

  • dandrayne 1138 posts 2262 karma points
    Nov 09, 2009 @ 15:48
    dandrayne
    0

    Your select doesn't have a class of "comment_type".  Add that and try again

  • trfletch 598 posts 604 karma points
    Nov 09, 2009 @ 15:54
    trfletch
    0

    Ok thanks, I have added that and now it is appending the URL but it still shows all the comments instead of filtering them.

  • dandrayne 1138 posts 2262 karma points
    Nov 09, 2009 @ 19:31
    dandrayne
    0

    Cool, now we're getting somewhere!

    Now it looks like your xslt which is causing trouble. Could you post what you're using?

    One problem I can see is using values like "commenttype=Idea for new system" - the querystring probably won't work with the spaces. You should probably store commentTypes like "ideas" or "suggestions", then try again against the new values.  You'd need to insert these one-word commentTypes as values of the select box, then change the jQuery to post back the val() and not the text() as I described a few posts ago)

    e.g.

    <option value="ideas">Idea for new system</option>

    and

    window.location = location.href.substring(0,location.href.indexOf('?'))+"?commenttype="+$(this).children("option:selected").val();

    Then adjust the xslt accordingly.  Feel free to post your xslt again so I can see if it has any potential problems.

    Dan

Please Sign in or register to post replies

Write your reply to:

Draft