Someone on TXP Forum asked for a simple way to construct a tree of articles sorted by year/month, with article counts, like this:
- 2019 (2)
- 2018 (1)
- 2017 (2)
- 2016 (1)
- 2015 (4)
…and so on. trenc came out with an elegant solution for the tree, presented below with small modifications. We have added empty span
placeholders for counts and put the tree into the archive
variable for further needs.
The code
<txp:variable name="archive">
<txp:article_custom sort="Posted desc" limit="999">
<txp:variable name="year" value='<txp:if_different><txp:posted format="%Y" /></txp:if_different>' />
<txp:variable name="month" value='<txp:if_different><txp:posted format="%Y-%m" /></txp:if_different>' />
<txp:if_first_article>
<li><txp:posted format="%Y" /> (<span></span>)<ul>
<li><txp:posted format="%b" /> (<span></span>)<ul>
<txp:else />
<txp:if_variable name="month" value=""><txp:else />
</ul></li>
<txp:if_variable name="year" value=""><txp:else />
</ul></li>
<li><txp:posted format="%Y" /> (<span></span>)<ul>
</txp:if_variable>
<li><txp:posted format="%b" /> (<span></span>)<ul>
</txp:if_variable>
</txp:if_first_article>
<li class="article"><txp:permlink><txp:title /></txp:permlink></li>
<txp:if_last_article>
</ul></li></ul></li>
</txp:if_last_article>
</txp:article_custom>
</txp:variable>
Roughly speaking, every time a new month/year is encountered, we close the current article list and open the next one.
Counters
But the problem of counters remains – see these empty ()
spans? A natural solution is to query the database for article counts for each year/month, but this would take time. And actually the articles are already retrieved – we only have to count them.
Use etc_query to replace the empty span tags
This is the very job for etc_query plugin, which does it in one line:
<txp:etc_query data='<txp:variable name="archive" />' query="li" replace=".//span={count(..//li[@class='article'])}" wraptag="ul" />
How it works? It takes the archive
list, retrieves the top li
elements (years), and replaces each span
placeholder with the number of all li
with class="article"
found inside its parent. Could it be any easier?
Thanks for this tutorial! It is my first time working with the etc_query plugin. The above code is giving me the following error:
Tag error: <txp:etc_query data=’<txp:variable name=“archive” />’ wraptag=“ul” query=“li” replace=”.//span=$[{count(..//li[@class=‘article’])}]$”/> -> Warning: DOMDocument::saveHTML() expects exactly 0 parameters, 1 given on line 410
textpattern/lib/txplib_misc.php(653) : eval()‘d code:410 DOMDocument->saveHTML()
textpattern/lib/txplib_misc.php(653) : eval()‘d code:222 etc_evaluate_string()
textpattern/publish.php:1188 etc_query()
textpattern/publish.php:1100 processTags()
textpattern/publish.php:538 parse()
index.php:45 textpattern()
Am I doing something wrong, or is there a typo in the code?
Hi Stacey,
this probably means that your php version is prior to 5.3.8 required by etc_query. The only solution in this case will be to upgrade, I’m afraid.
The
etc_query
syntax has a little changed in v.0.97(?), these $[]$ are not needed anymore.Here is a version of the etc_query snippet that would add the class “current” (while keeping any existing class to all ancestor <li>s of currently viewed page. This could let you do some cool stying and/or scripting.