Textpattern tips, tutorials and code snippets

Turn article custom fields into a table

I wanted to turn a bunch of articles into a table, and asked on the forum for some help.

The difficulty was that not every custom_field had a value, so formatting empty cells was a challenge.

Enter the smd_each and zem_nth plugins..

This tip requires that the smd_each and zem_nth plugins to be installed and activated.

First cut…

<txp:output_form form="page-header"/>
<!-- ............................................................................ -->

<txp:article_custom section="releases" limit="999" sort="custom_5 asc" limit="999">
<!-- Is the vintage different? <txp:if_different><txp:custom_field name="wine_vintage" /><txp:variable name="different" value="1" /> <txp:else/><txp:variable name="different" value="" /></txp:if_different> -->

<!-- Then add it to a variable. <txp:if_variable name="different" value="1"><txp:variable name="vintages"><txp:custom_field name="wine_vintage" /><txp:if_first_article><txp:else/>,</txp:if_first_article><txp:variable name="vintages" /></txp:variable></txp:if_variable> --> 
</txp:article_custom>

<!-- Reset the "different" variable <txp:variable name="different" value="1" /> -->

<txp:article_custom section="releases" limit="999" sort="custom_34 asc" limit="999">
<!-- Is the release Different? <txp:if_different><txp:custom_field name="wine_release_name" /><txp:variable name="different" value="1" /> <txp:else/><txp:variable name="different" value="" /></txp:if_different> -->

<!-- Then add it to a variable. <txp:if_variable name="different" value="1"><txp:variable name="releases"><txp:custom_field name="wine_release_name" /><txp:if_first_article><txp:else/>,</txp:if_first_article><txp:variable name="releases" /></txp:variable></txp:if_variable> --> 
</txp:article_custom>

<table id="vintageGuide"><!-- We have all we need to create a table. create the header row first-->
  <tr><th class="releaseName">Releases</th><txp:smd_each type="txpvar" include="vintages" delim="," subset="2"><th class="v-{smd_var_value}">{smd_var_value}</th></txp:smd_each></tr>

<!-- Reset the "different" variable <txp:variable name="different" value="" /> -->

<txp:article_custom section="releases" limit="999" sort="custom_34 asc">
<!-- Is the Release Name Different? <txp:if_different><txp:custom_field name="wine_release_name" /><txp:variable name="different" value="1" /><txp:else/><txp:variable name="different" value="" /></txp:if_different> -->

<!-- First insert the release name td --> <txp:if_variable name="different" value="1"><tr<txp:zem_nth step="1" of="2"> class="odd"</txp:zem_nth>><td class="releaseName"><txp:custom_field name="wine_release_name"/></td><txp:variable name="thisRelease"><txp:custom_field name="wine_release_name" /></txp:variable>

<!-- Then create the fields --><txp:smd_each type="txpvar" include="vintages" delim="," subset="2"><td><txp:article_custom section="releases" wine_vintage='{smd_var_value}' limit="999" wine_release_name='<txp:variable name="thisRelease" />' sort="custom_5 asc"><txp:if_custom_field name="wine_cellaring" value="">—<txp:else/><txp:custom_field name="wine_cellaring" /></txp:if_custom_field></txp:article_custom></td></txp:smd_each></tr> 
</txp:if_variable> 
</txp:article_custom>  
</table>

<!-- ............................................................................ -->
<txp:output_form form="page-footer"/>

Second cut…

After some discussion and comment from Gocom about performance, etc came up with another method using his plugin etc_query:

<txp:variable name="releases"><!-- json array of data -->
  <txp:article_custom sort="custom_34,custom_5 ASC" limit="999">
    <txp:if_first_article><txp:else />,</txp:if_first_article>
    {"release":"<txp:custom_field name='wine_release_name' />", "vintage":"<txp:custom_field name='wine_vintage' />", "cellaring":"<txp:custom_field name='wine_cellaring' />"}
    <txp:variable name="vintage" value='<txp:variable name="vintage" />,<txp:custom_field name="wine_vintage" />' />
  </txp:article_custom>
</txp:variable>

<-- find the min and max vintages -->
<txp:etc_query data="{?vintage||ltrim($|,)}" markup="raw">
  <txp:variable name="min" value="{$do_list.min}" />
  <txp:variable name="max" value="{$do_list.max}" />
</txp:etc_query>

<table><thead><tr>
  <th>Releases</th><txp:etc_query data="[{?min}..{?max}]" break="th" /></tr></thead>
  <tbody>
    <txp:etc_query data='[<txp:variable name="releases" />]' markup="json">
      <txp:if_variable name="release" value="{release?}"><txp:else />
        <!-- complete and close the previous row -->
        <txp:etc_query data="[{{?cmin,max}}<.{?max}]" markup="json" break="td">-</txp:etc_query>
        <txp:if_variable name="cmin"></tr></txp:if_variable>
        <!-- start the next one -->
        <tr><td><b>{release?}</b></td>
        <txp:variable name="cmin" value="{?min|1|-1}" />
      </txp:if_variable>
      <!-- fill the gaps between vintages -->
      <txp:etc_query data="[{{?cmin}}<<{vintage?}]" markup="json" break="td">-</txp:etc_query>
      <td>{cellaring?}</td>
      <txp:variable name="cmin" value="{vintage?}" />
      <txp:variable name="release" value="{release?}" />
    </txp:etc_query>
    <txp:etc_query data="[{?cmin}<.{?max}]" markup="json" break="td">-</txp:etc_query>
  </tr></tbody>
</table>

Try it out and see how you go!

Use Textile help to style your comments