Create new page layout layouts/page/filterdemo.html
Create an empty content file.
hugo new filterdemo.mdSet to use the layout created above in the frontmatter of filterdemo.md:
layout: filterdemodraft: false.Grab hugotagsfilter-...js and put it somewhere in your static directory.
In your filterdemo.html file:
<script src="{{ "vendor/htf/hugotagsfilter-...js" | relURL}}"></script>Initialize HTF, passing an optional config object. This demo uses the following:
var htfConfig = {
filters: [
{
name: 'section',
prefix: 'sect-',
buttonClass: 'sect-button',
allSelector: '#selectAllSections',
attrName: 'data-section',
selectedPrefix: 'ssect-',
countPrefix: 'csect-'
},
{
name: 'tags',
prefix: 'tag-',
buttonClass: 'tag-button',
allSelector: '#selectAllTags',
attrName: 'data-tags',
selectedPrefix: 'stags-',
countPrefix: 'ctags-'
},
{
name: 'authors',
prefix: 'auth-',
buttonClass: 'auth-button',
allSelector: '#selectAllAuthors',
attrName: 'data-authors',
selectedPrefix: 'sauth-',
countPrefix: 'cauth-'
}
],
showItemClass: "show-item",
filterItemClass: "tf-filter-item",
activeButtonClass: "active",
counterSelector: "selectedItemCount",
populateCount: true,
setDisabledButtonClass: "disable-button"
}
var htf = new HugoTagsFilter(htfConfig);
filters : array of config for each filter set. Each config object needs:
name : filter identifierprefix : Each term toggler button needs to be assigned a unique ID. The prefix is used to identify terms belonging to the same filter set, e.g. tags-post, tags-weather, tags-random are tag filters, sect-post, sect-documentation are section filters.buttonClass : Class attribute applied to button togglers. Must start with the prefix.allSelector : Selector for the Select All X button.attrName : Data attribute name to use to identify items.selectedPrefix : Specify prefix to use to identify the element containing a count of items selected by the tag.countPrefix : Specify prefix to use to identify the element containing a count of all items with tag.showItemClass : class to apply to items to signify that they should be visible.filterItemClass : class applied to items to indicate that it is included in items to be filtered.activeButtonClass : class to apply to button toggler to signify active statuscounterSelector: optional selector for element to display count of items displayed.populateCount: set to true if you want to keep a counter of tags and items associated. Must define selectedPrefix or countPrefix on each filter item.setDisabledButtonClass: Specify a class name to denote disabled button, e.g. when there are no items displayed that have the button’s tag.
You can use as many filter categories as needed.
Tags and section filters are configured by default. If no config object is passed in initialising HTF, the following will be used:
var defaultFilters = [
{
name: 'tag',
prefix: 'tft-',
buttonClass: 'tft-button',
allSelector: '#tfSelectAllTags',
attrName: 'data-tags'
},
{
name: 'section',
prefix: 'tfs-',
buttonClass: 'tfs-button',
allSelector: '#tfSelectAllSections',
attrName: 'data-section'
}
]
This demo uses the following styles (in addition to bare.css)
/*** Important ***/
.tf-filter-item {
display: none;
}
button.active {
background-color: #ddd;
}
button.disable-button {
border-style: dashed;
}
.show-item {
display: inline-block;
/* or whatever display style is appropriate
* for tf-filter-item when it is showing;
*/
}
/*** Aesthetics ***/
.tf-items-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.tf-item {
width: 250px;
margin: 8px;
background: #fff;
padding: 2rem;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, .2);
border-radius: 2px;
margin-bottom: 2rem
}
pre code {
overflow-x: auto;
}$pages and $sections should be fairly straight-forward.
{{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
{{ $sections := .Site.Params.mainSections }}I don’t have authors configured in my config.toml, only on the front matter of the content, which is why I have to get all authors declared for all content. You may need to do this differently depending on your own setup.
{{ $.Scratch.Set "authors" (slice ) }}
{{ range where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
{{ with .Params.author }}
{{ if eq ( printf "%T" . ) "string" }}
{{ if ( not ( in ($.Scratch.Get "authors") . ) ) }}
{{ $.Scratch.Add "authors" . }}
{{ end }}
{{ else if ( printf "%T" . ) "[]string" }}
{{ range . }}
{{ if ( not ( in ($.Scratch.Get "authors") . ) ) }}
{{ $.Scratch.Add "authors" . }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}Counting and tracking untagged is not required.
{{ $tags := $.Site.Taxonomies.tags.ByCount }}
{{ $.Scratch.Set "untagged" 0 }}
{{ range $pages }}
{{ with .Params.tags }}{{ else }}{{ $.Scratch.Add "untagged" 1 }}{{ end }}
{{ end }}For each filter set you want to use, generate buttons (or your preferred element) to use as toggles. For each button:
Assign an id beginning with the prefix defined in its config.
Assign the class defined as buttonClass.
Set onclick="htf.checkFilter()", passing as parameters the term and the prefix
Add a ‘Select All x’ button as well.
onclick="htf.showAll('x')"allSelector
If you want to keep a counter of
you also need to add an element inside the button to contain its count (see examples)
<span id="ssect-{{ . | urlize }}"> -count-</span><div><h2><span id="selectedItemCount"></span> Items</h2></div>
<div class="tf-items-container">
{{ range $pages.ByPublishDate.Reverse }}
<div class="tf-filter-item tf-item"
data-tags="{{ with .Params.tags }}{{ range . }}{{ . | replaceRE "[.]" "_" | urlize }} {{ end }}{{ else }} tfuntagged{{ end }}"
data-section="{{ .Section }}"
data-authors="{{ with .Params.author }}{{ if eq ( printf "%T" . ) "string" }}{{ . | replaceRE "[.]" "_" | urlize }}{{ else if eq ( printf "%T" . ) "[]string" }}{{ range . }}{{ . | replaceRE "[.]" "_" | urlize }} {{end}}{{end}}{{else}}no-author{{end}}"
>
<h6>{{.Section}}</h6>
<h5>{{ with .Params.author }}{{ if eq ( printf "%T" . ) "string" }}{{.|humanize|title}}{{ else if eq ( printf "%T" . ) "[]string" }}{{ range . }}{{.|humanize|title}} {{end}}{{end}}{{else}}No Author{{end}}</h5>
<h4><a href="{{ .RelPermalink }}">{{ .Title }}</a></h4>
<div>{{ with .Params.tags }}{{ range . }}<tag>{{ . | humanize | title }}</tag> {{ end }}{{ else }}<tag>untagged</tag>{{ end }}</div>
</div>
{{ end }}
</div>