Search

There are plenty javascript solutions for dividing a text into chunks (divs) by means of wordcount, and to create newspaper-like columns of text. Has anyone ever tried this with recursion counting the pararaphs (thats the closest useable node, we cant use words as they are not nodes, right?). Does it sound like a good idea?

it's definitely possible. it just might be kinda of taxing on the server if you have a large article and needs to process all the xml. I've actually written something like this to count the number of titles and split it up after n amount and make a new column. you can probably use that same logic but just apply it accordingly.

I've done something similar to wtdtan, using h2 elements as an indicator to break up different articles coming from a single data field.

You can get a word count but I'm not sure what kind of processing it would take. If you go this route, you could always output your content to a dynamic datasource, and have Symphony cache it for you. I do that with my navigation (gives me an xml nodeset of my entire sitemap without much server overhead at all).

The datasource has a global (from the core, php) word count attribute in each entry also. But the question is how to split up say a paragraph. The JS solutions just insert a

into the code but such unclosed tags cannot be done in xslt. The above h2 examples I assume all split things up outside parent tags, not inside them, correct?

It depends on how fine you need the control. If you're splitting mid-paragraph so that your columns are exactly equal, obviously this is going to break when the user increases their font size in the browser (or has a slightly different rendering of the font). You'll also run into problems of nested elements, such as links and strong/emphasis elements within paragraphs. If splitting mid-paragraph then you need to make sure you also split these and re-open them on the next column.

A much simpler solution is to count the number of paragraphs and split columns equally based on this. I've written a basic "columnise" template which is called thusly:

<xsl:call-template name="columnise">
    <xsl:with-param name="content" select="/data/section/entry/content" />
</xsl:call-template>

Simply passes in a content node (which is a section field with a text formatter, so contains paragraph and heading nodes).

<xsl:template name="columnise">
    <xsl:param name="content" select="$content" />  
    <xsl:variable name="split" select="ceiling(count($content/*[name()='p']) div 2)" />
    <div class="column">
        <xsl:copy-of select="$content/*[name()='p' and position() &lt;= $split]" />
    </div>
    <div class="column">
        <xsl:copy-of select="$content/*[name()='p' and position() &gt; $split]" />
    </div>
</xsl:template>

The template receives the content and works out which paragraph to split on. If there's an even number, e.g. 10 it will split between 5 and 6 (5 in each column). If an odd number e.g. 11 if will put 6 in the first column and 5 in the second. This could well be expanded to make it recursive so that you can pass a number of columns to use, and the template works out the best split. For brevity I have only used two hard-coded columns.

Obviously this doesn't solve the problem of paragraphs being different lengths.

Another trick is to use a horizonal rule as a marker. You could then have a recursive template which finds all


elements and puts them into columns (using preceding/following-siblings).

using $content in your xpath expression works? i always thought that threw errors.

@wtdtan

You can use $vars in selects, but not in matches (or modes btw).

As far as my H2 solution, you're right, I can't wrap each article in an output element for the reason you point out. You can do it, but it is messy and generally bad xsl mojo. If you're desperate, let me know and I'll dig up the example.

The best way (which I didn't pursue too far since I didn't need it), would be to use the wordcount in some sort of a match that would only include part of the paragraph, then use some sort of offset. Not sure it's possible but could be.

It would involve -using the util I linked to to create tokens out of words (in order to use position function) -putting the word count/2 into a var, $half -running a select on the result tree fragment that the util outputs to say -'apply to 'word' elements whose position is less than $half' -then apply to 'word elements whose position is greater than $half

That might do it. To abstract it, you'd have to use a '$column-start' and '$column-end' rather than just the $half, but then it could be a single template...

Using a horizontal rule or an offset sure seems like innovative approaches!

Although in my setup (liqued layout in ems) I would have no problem with word count, it still stays a bit complex because of the possible child tag brakes. I feel the most effcient and semantic way that keeps the editors in control is to use a horizontal rule and transform that into divs with class column.

I am still looking at how to achieve this with recursion and siblings; the main doc and a thread here and on our forum

However for now my editors would just have to copy and paste the

themselves...

Using Nick Dunns approach above, I've managed to get my content split over 2 columns as outlined in the template example, I'm now seeing how it is working and am trying to see how - if the user places anything other than a <p> tag in the content block it doesn't get rendered to the page.. how would one go about ensuring that, lets say <h2> and <h3> tags are included without affecting the <p> column split? racking my little brain on this one :)

Depending on what you are trying to achive you should keep an eye on the CSS3 column-count Property

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details