Textpattern tips, tutorials and code snippets

File download list excluding empty categories

The following code was written in reply to this request on the Textpattern forum.

The objective

The objective was to display a list of files, ordered by categories and subcategories, with headings for each category, but without displaying headings for categories without content (files). In this example both the parent categories and the child categories can contain files. So the output would have to be like this:

<h2>Parent category title</h2>
// list of files in parent category (if any)
<h3>Child category title</h3>
// list of files in child category
<h3>Another child category title</h3>
// list of files in child category
<h2>Another parent category title</h2>
...etcetera

If a child category doesn’t contain any files, the category title should not be displayed. Also, if neither the parent nor it’s child categories contain any files, the parent category title shouldn’t be displayed either.

The code

This is the code that does it, you can place it on a page, in a form, or inside an article body. If used inside an article, remember to switch Textile off or precede the code with notextile. to prevent it being wrapped in <p> tags.

<txp:category_list type="file" children="0" break="">
	<!-- check if this parent category or it's children contain one or more files -->
	<txp:variable name="check1" value='<txp:file_download_list category=''<txp:category_list type="file" parent=''''<txp:category />'''' break=","><txp:category /></txp:category_list>'' limit="1"><txp:file_download_name /></txp:file_download_list>' />
	<txp:if_variable name="check1" value="">
	<txp:else />
		<h2><txp:category title="1" /></h2>
		<txp:file_download_list wraptag="ul" break="li" category='<txp:category />'><txp:file_download_link><txp:file_download_name /></txp:file_download_link></txp:file_download_list>
		<txp:category_list type="file" parent='<txp:category />' exclude='<txp:category />' break="">
			<!-- check if this child category contains one or more files -->
			<txp:variable name="check2" value='<txp:file_download_list category=''<txp:category />'' limit="1"><txp:file_download_name /></txp:file_download_list>' />
			<txp:if_variable name="check2" value="">
			<txp:else />
				<h3><txp:category title="1" /></h3>
				<txp:file_download_list wraptag="ul" break="li" category='<txp:category />'><txp:file_download_link><txp:file_download_name /></txp:file_download_link></txp:file_download_list>
			</txp:if_variable>
		</txp:category_list>
	</txp:if_variable>
</txp:category_list>

How it works

The first tag, <txp:category_list type="file" children="0" break="">, displays a list of only the parent categories. For each of these parent categories we are going to check if there is at least one file in either this parent category or in one of its child categories. To be able to perform this check we need to set a variable first:

Variable ‘check1’: the value attribute is given a value by a file_download_list tag that outputs a list of files in that parent category and/or it’s children; the category attribute inside the file_download_list tag gets a value of a comma separated list of the parent category and it’s child categories, generated by yet another category_list tag1; because we only need to know if there is at least one file, we set the limit attribute in the file_download_list tag to 1. If there are no files, the value is empty.

The check: <txp:if_variable name="check1" value="">. An empty value means that there are no files in either parent or child categories, so we don’t display anything. In any other case (<txp:else />) we display the parent category’s title.

After it, <txp:file_download_list wraptag="ul" break="li" category='<txp:category />'> will display a list of files in the parent category. If there are no files in it, the tag won’t display anything, so no need for variables to check for content here.

The next category_list tag, <txp:category_list type="file" parent='<txp:category />' exclude='<txp:category />' break="">, displays a list of all the parent’s child categories. Again, for each of these child categories, we need to check if they contain at least one file, making use of a second variable:

Variable ‘check2’: the value here is filled by a file_download_list tag that outputs a list of files in that child category. If there are no files, the value is empty.

The check is done in the same way as the first one; if the value is not empty, the child category’s title is displayed, followed by a list of files in that category.

1 Note that because we are nesting tags in attributes more than one level deep, tags in each subsequent level need to be escaped (more on parsing tag attributes in Textbook):

<txp:variable value=
	'<txp:file_download_list category= // first level
		''<txp:category_list parent=    // second level
			''''<txp:category />         // third level

Here is the page that demonstrates the use of this code.

Use Textile help to style your comments