Skip to content

Additional filters

Roland Toth Pal edited this page Feb 2, 2019 · 90 revisions

The module comes with additional helper filters besides the built-in ones. Some of them are ProcessWire-specific or included only for demonstration purposes. If you don't need them you can disable in the module's settings page.

activeclass

Adds an 'active' class if the Page passed is the current page, or it is a children of the parent page (multi-level). Useful for navigation items or sliders for example. You can change the default className to another one by passing it as a parameter (added using ":'current'" in the following snippet). Note that you need to take care of the spaces if you use another classes on the element.

<ul n:inner-foreach="$menuItems as $p">
    <li class="menu-item {$p|activeclass:'current'}">
        <a href="{$p->url)}">{$p->title|noescape}</a>
    </li>
</ul>

append, prepend

Appends or prepends data. Can be used with simple strings and arrays too. Note that if you use it with associative arrays, array items may be overwritten because of array_merge.

This filter can be useful when chaining filters so you can modify the original data in one step.

{var $arr = array(4,5,6)}
{var $arr_assoc = array('one' => 'first', 'two' => 'second', 'three' => 'third')}

{('Hello')|append:' World!'}
{*outputs: Hello World!*}

{('World!')|prepend:'Hello '}
{*outputs: Hello World!*}

{$arr|prepend:3}
{*outputs: array(3,4,5,6)*}

{$arr|append:7}
{*outputs: array(4,5,6,7)*}

{$arr|prepend:array(1,2,3)}
{*outputs: array(1,2,3,4,5,6)*}

{$arr|append:array(7,8,9)}
{*outputs: array(4,5,6,7,8,9)*}

{$arr_assoc|append:array('three' => 'new_third')|bd}
{*outputs: array('one' => 'first', 'two' => 'second', 'three' => 'new_third')*}

bd, bdl, d

Fires bd(), bdl() or d() functions of Tracy Debugger module.

{$page->title|bd}
{$page->title|bdl}
{$page->title|d}

bgimage

Adds an inline style with background-image: url(...).

<div {$page->featured_image->size(1180,320)|bgimage|noescape}></div>
// result:
// <div style="background-image: url('/site/assets/files/1/image.1180x320.jpg')"></div>

bgset

Adds data-bgset tag to elements to be used with Lazysizes bgset plugin.

Requires lazysizes.js and ls.bgset.js added manually and adding the "lazyload" class to the element. For IE11 respimage polyfill is also needed.

Parameter $divisor can be used to set the placeholder size (defaults to 4).

<div {$page->images->first()->width(900)|bgset:3|noescape} class="lazyload"></div>
// output:
// <div style="background-image: url('/site/assets/files/1/image.200x75.jpg')" data-bgset="/site/assets/files/1/image.600x225.jpg" class="lazyload"></div>

bodyclass

Adds some classes to the element (preferably to the "body") reflecting the page ID, template and user language, page number (if applicable) and $view->viewFile:

  • page ID: eg. "page-1032"
  • template name: "template-basic-page" (or "home" in case of the homepage)
  • language: "lang-default"
  • pagination: "pagenum-2"
  • viewFile: eg. "v-partials-featured_slider"
<body class="{$page|bodyclass}">

You can also add custom classes using "$page->bodyclass" (string or array). Note that currently custom body classes will overwrite each other when used more than one times so you need to manually ensure to get around this, eg. creating an array and appending items).

breadcrumb

Generates markup (unordered HTML list) for breadcrumbs. Note that no separator is added, use CSS for that.

Pass an array of options to fine-tune:

  • root: root page to start the breadcrumb from (selector or Page). Default: Home page
  • addHome: whether to prepend the Home page. Default: true
  • field: which field to use for the link texts. Default: "title"
  • addCurrent: append the current page. Default: false
  • addCurrentLink: whether to add link when appending the current page. Default: false
  • class: CSS class to add to the "ul" tag. Default: "breadcrumb". Pass an empty string to remove class.
  • id: CSS id to add to the "ul" tag. Default: none (no id added)
  • addAttributes: add "data-page" attributes to 'LI' tags with the corresponding page id. Default: false
<div>
    {$page|breadcrumb|noescape}
    {$page|breadcrumb:array('addCurrent' => true, 'addHome' => false, 'addCurrentLink' => true)|noescape}
    {$page|breadcrumb:array('root' => 1038, 'addCurrent' => true, 'id' => 'breadcrumb-top', 'class' => 'breadcrumb custom-class')|noescape}
</div>

Default values

You can set default values by adding a $view->breadcrumbDefaults array, eg. in ready.php file:

$view->breadcrumbDefaults = array(
    'addHome'    => false,
    'addAttributes'   => true
);
```php


## consolelog

Logs to the console (developer tools).

```php
{$page->title|consolelog}

count

Returns the number of items in PageArray. Can be used for checking if there's any items to show (eg. with n:if).

{var $services = 'template=services, parent.template=home'}
<div n:if="($services|count)">
    {* do something if there are items in $services PageArray *}
</div>

default

Returns the specified default value if empty or falsy value is passed. You can use it for example to substitute simple if-else conditions.

<div>
    {$page->product_description|default:'No description is available for this product.'}
</div>

embediframe

Generates markup for responsive iframe embed.

Apply the filter to the embed url (not the video url nor the whole embed code). Determines aspect ratio from width/height parameters and adds it as an inline style. Requires a few lines of additional CSS, see below.

Parameters (array):

  • width: iframe width in pixels (get from embed code, default: 560)
  • height: iframe height in pixels (get from embed code, default: 315)
  • upscale: if set to false, the iframe won't be bigger than the original width
  • attr: attributes to add to the iframe tag
  • wrapAttr: attributes to add to the wrapper tag. Note: overrides the default class="embed-wrap" attribute
  • srcAttr: use this to change the default src tag to something else, eg. data-src for lazy loading purposes
  • urlParams: use to add extra parameters to the source url, eg. "?autoplay=1" for videos
{var $url = 'https://www.youtube.com/embed/IHqnLQy9R1A'}

{$url|embediframe|noescape}
{$url|embediframe: array('attr' => 'class="lazyload" allowfullscreen')|noescape}
{$url|embediframe: array('attr' => 'class="lazyload" allowfullscreen', 'wrapAttr' => 'class="embed-wrap video"', 'srcAttr' => 'data-src')|noescape}

CSS:

.embed-wrap {
  margin: 0 auto; /* optional */
}
.embed-wrap > div {
  position: relative;
  height: 0;
}
.embed-wrap iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

Generated markup

Default (no parameters):

<div class="embed-wrap"><div style="padding-bottom:56.25%"><iframe width="560" height="315" src="https://www.youtube.com/embed/IHqnLQy9R1A"></iframe></div></div>

With various parameters:

<div class="embed-wrap video"><div style="padding-bottom:56.25%"><iframe width="560" height="315" data-src="https://www.youtube.com/embed/IHqnLQy9R1A" class="lazyload" allowfullscreen></iframe></div></div>

Default values

You can set default values by adding a $view->embediframeDefaults array, eg. in ready.php file:

$view->embediframeDefaults = array(
    'width'    => 600,
    'height'   => 480,
    'wrapAttr' => 'class="iframe-wrapper"',
);

Tips

  • adjust the wrapper element width to set the iframe width (in CSS)
  • to lazyload iframes width Lazysizes add the class lazyload and set srcAttr to data-src (plus include lazysizes.js too)

embedyoutube

Generates markup for the Light Youtube Embed method.

You'll need to add the JavaScript and CSS from the site linked above.

{$page->youtube_link|embedyoutube}

The filter handles standard youtube URLs and playlist URLs too.

first, last, firstkey, lastkey

Returns the first or last item of an array. If the data supplied is not an array, returns the original data.

<p>
    {$myArray|first}
    {$myArray|last}
</p>

Filters firstkey and lastkey return the first and last keys of an associative array.

get

Provides an easy way to get a field value of a page. Defaults to the "title" field. Using this filter eliminates the need of the extra parenthesis.

<p>
    {1|get:httpUrl}
</p>

getchildren

Returns child pages, applied to a selector or a Page. A selector string can be passed to filter children.

{foreach (1023|getchildren) as $p}
    {$p->title|noescape}
{/foreach}
{foreach ($page|getchildren:'limit=4') as $p}
    {include 'partials/article.latte', p => $p}
{/foreach}

Alias children can also be used:

{if (1088|children:'template=blog')->count()}
    ...
{/if}

getline, getlines

The getlines filter explodes lines of a textarea field into an array, optionally with a filter to retrieve specific items only.

If a separator is present in the source data then an associative array is returned. Default separator is = which can be modified (see below).

Empty lines and lines starting with "//" will be skipped.

The filter always returns an array (even if empty) so use a foreach to display data, or use first or last filters. From v049 you can use the getline filter instead to retrieve only one line.

Example 1: simple array

Textarea field content:

Maria
John
// Peter (will be skipped)
Benedict
<p n:foreach="($my_field|getlines) as $value">
    {$value}
</p>

Example 2: associative array

Textarea field content:

sitename = My Site
phone = 123456789
// facebook_id = 54546464646 (will be skipped)
<p n:foreach="($my_field|getlines) as $key => $value">
    {$key}: {$value}
</p>

Use comma-separated values to add filters. Only matching items will be retrieved:

<p n:foreach="($my_field|getlines:'facebook,linkedin') as $social">
    {$social}
</p>

Use $my_field|getlines:'',':' to change the separator to : (or anything else).

Multilanguage support

Multilanguage is supported via InputfieldTextareaLanguage. If you've set the field's behavior to inherit values from default language if it's empty on the given language, data will be available for all languages.

However, if the field on a non-default language is not empty, the missing lines won't be inherited. In such cases you will have to supply an array (pageID, fieldname) instead of field data (available from v0.4.7) to ensure inheritance.

<p n:foreach="(array(1, 'settings')|getlines:'facebook,linkedin') as $social">
    {$social}
</p>

The example above will use facebook and linkedin values from the "default" language of the "settings" textarea if they were not found in the current language (using the "Home" page, id 1). This means that you can set common data in the "default" language, and add overrides to other languages, no need to duplicate everything in each language tab.

Tip: for site-wide settings set up a variable in ready.php and use it in view files like this:

// ready.php - save the Home page's 'settings' textarea field content to a $settings variable
$view->settings = $pages->get(1)->settings;
<p n:foreach="$settings|getlines:'facebook,linkedin') as $social">
    {$social}
</p>

Filter getline works the same way as getlines but returns a string instead an array:

<html lang="{$settings|getline:'locale'}">

getembedurl

Retrieves embed url from video urls. Currently Youtube and Vimeo are supported. Can be useful to use with embediframe filter.

{$page->video_url|getembedurl|embediframe|noescape}

getpage

This is a "filter" version of the macro "page" (see above) that makes really easy to reference a page by ID or selector.

Note: use parenthesis to access the returned Page object's methods.

<p>
    {(1|getpage)->title}
</p>

getpages

This is a "filter" version of the macro "pages" (see above). The difference is that you can pass an extra selector too.

<p n:foreach="('parent=1088'|getpages) as $p">
    {$p->title|noescape}
</p>

{* $view->servicesPages is set in ready.php and contains "template=service,sort=-created" *}
{* now get only 6 of them *}
<p n:foreach="($servicePages|getpages:'limit=6') as $p">
    {$p->title|noescape}
</p>

getparent

Simply returns the given PageArray's parent page, eg. when using with getpages filter.

<p>
    {('template=portfolio-items'|getpages|getparent)->title}
</p>

group

Allows creating groups from a PageArray based on a page field value. This can be handy if you would like to output pages grouped by category or other value.

Returns an array of:

  • key: sanitized field value, eg. to use for class names
  • title: the human-readable name of the group (field value)
  • items: array of Pages in the group
{foreach ($page->children()->sort('sort')|group:'section') as $group}
    <h2>{$group['title']}</h2>

    <div class="{$group['key']}">
        {foreach $group['items'] as $p}
            <div>
                <a href="{$p->url}">{$p->title}</a>
            </div>
        {/foreach}
    </div>
{/foreach}

imageattrs

Adds width, height and alt attributes to an image.

By default the filter adds an "alt" attribute with image description or an empty tag if no description is provided. To disable add -alt to the first parameter.

<img src="{$page->img_field}" {$page->img_field|imageattrs|noescape} />
<img src="{$page->img_field}" {$page->img_field|imageattrs:'-alt'|noescape} />

lazy

Adds data-src tag to img tag to be used with Lazysizes.

Requires lazysizes.js added manually and adding the "lazyload" class to the image. For IE11 respimage polyfill is also needed.

Parameter $divisor can be used to set the placeholder size (defaults to 4).

<img src="{$page->images->first()->width(900)|lazy:3|noescape}" alt="" class="lazyload" />
// output:
// <img src="/site/assets/files/1/image.300x0.jpg" data-src="/site/assets/files/1/mobile.900x0.jpg" class="lazyload" alt="">

list

List array items with a separator.

Similar to the built-in "implode" filter but accepts string too.

A separator string and a HTML tag can be passed to surround each item. Empty items will be skipped.

{array($page->title, ($page->modified|date:'%Y'), $page->name)|list:'|','span'|noescape}

Result:

<span>Home</span>|<span>2017</span>|<span>en</span>

localname

This is a helper filter to avoid empty localnames in multilanguage setups.

If the page name for the non-default language is the same as of the default language, the built-in localName may return an empty string. The filter will return the appropriate page name in these cases.

Additionally you can pass a language name or ID to get the page name on that language.

$page->localname
$page->localname:'dutch'

niceurl

Removes "http(s)" and/or "www" from a link, useful for outputting shorter links.

{* remove www and http *}
<a href="{$page->httpUrl}">{$page->httpUrl|niceurl}</a>
{* remove "http" only *}
<a href="{$page->httpUrl}">{$page->httpUrl|niceurl:'http'}</a>
{* remove "www" only *}
<a href="{$page->httpUrl}">{$page->httpUrl|niceurl:'www'}</a>
{* remove trailing "/" *}
<a href="{$page->httpUrl}">{$page->httpUrl|niceurl:'/'}</a>
{* remove "www" and trailing "/" *}
<a href="{$page->httpUrl}">{$page->httpUrl|niceurl:'www/'}</a>

onlynumbers

Removes everything other than numbers. You could also use the built-in "replaceRE" filter.

<p>
    {$page->phone|onlynumbers}
</p>

optionchecked

Check if a Select Options field on a page has a given option selected.

Consider a field named "page_options" with a selectable option 3=show_header|Show header. In this case you can use one of the following to check if it's checked on a given page:

  • page_options.3
  • page_options.show_header
  • page_options.Show header
{if ($page|optionchecked:'page_options.show_header')}
<header>
    <p>This line is visible only if the $page has "show_header" checked/selected.</p>
</header>
{/if}

The filter also checks whether the page template contains the field so there will be no error when applying it to pages with different templates (eg. when listing various type of pages).

protectemail

Protects email with different methods (javascript/js, javascript_charcode, hex, drupal, texy). Defaults to javascript mode.

{var $email = 'info@domain.com'}

{$email|protectemail|noescape}
{$email|protectemail:'javascript'|noescape}
{$email|protectemail:'hex','Email me','class="mailto-link"'|noescape}
{$email . '?subject=The%20subject%20of%20the%20mail'|protectemail:'js','Email me','class="button"'|noescape}

renderpager

Returns a pagination markup (pager) when applied to a PageArray. Accepts one parameter: a number (numPageLinks) or an array to override the defaults. The alias "pager" can also be used.

{$pArr|renderpager|noescape}
{$pArr|renderpager:2|noescape}
{$pArr|renderpager:array('nextItemLabel' => 'next')|noescape}
{$pArr|renderpager:$customPaginationSettings|noescape}

In the examples above $customPaginationSettings is an array that you can set eg. in ready.php:

$view->customPaginationSettings = array(
    'numPageLinks'       => 3, // Default: 10
    'getVars'            => null, // Default: empty array
    'baseUrl'            => array(), // Default: empty
    'listMarkup'         => "<ul class='pagination'>{out}</ul>",
    'itemMarkup'         => "<li class='{class}'>{out}</li>",
    'linkMarkup'         => "<a href='{url}'><span>{out}</span></a>",
    'nextItemLabel'      => 'next page',
    'previousItemLabel'  => 'previous page',
    'separatorItemLabel' => '',
    'separatorItemClass' => '',
    'nextItemClass'      => 'next',
    'previousItemClass'  => 'previous',
    'lastItemClass'      => 'last',
    'currentItemClass'   => 'active'
);

Default values

You can set common default values by creating a $view->renderPagerDefaults array, eg. in ready.php file. This way all pagers will use these settings but you can override them individually in view files if needed.

$view->renderPagerDefaults = array(
    'nextItemLabel' => 'Next',
    'previousItemLabel' => 'Prev'
);

replacesubs

Allows adding placeholders in format ((item)) to fields to replace them with data coming from an array. Mainly for replacing placeholders in CKEditor content, eg. with global contact data, social links, etc.

Consider the following settings textarea as the replacement data source:

phone = 123456
email = abcd@domain.com

Now you can use ((phone)) and ((email)) placeholders in eg. a CKEditor field to replace values. For example, the body CKEditor HTML content may look like this:

<ul>
   <li><strong>Phone</strong>: ((phone))</li>
   <li><strong>Email</strong>: <a href="mailto:((email))">((email))</a></li>
</ul>

Then in your latte file you can apply the filter and set the source array of replacements. In this example the replacement source is a simple textarea, from which the filter will create a replacement array:

{$page->body|replacesubs:$page->settings|noescape}

The main advantage is that you don't need to hardcode keys into template files, unlike with getline/getlines. So eg. if you need to add another phone number, just add phone2 = 99999 to the Settings field and the corresponding markup to the CKEditor.

sanitize

Applies ProcessWire's sanitizer. The alias "sanitizer" can also be used.

{('Lorem ipsum')|sanitize:'fieldName'}
{$p->body|sanitize:'text', ['multiLine' => false]}
{$p->body|sanitize:'text', array('multiLine' => true, 'stripTags' => false)}
{('2017/02/28')|sanitizer:'date', 'YYY F j.', array('returnFormat' => 'Y. F j.')}

savetemp

Allows saving temporary data to reuse later with $gettemp().

<img n:if="($page->images->get('tags=logo')|savetemp)" src="{($gettemp()->width(700)|savetemp)->url}"
 width="{$gettemp()->width}" height="{$gettemp()->height}" />

In this example the img tag is outputted only if there is an image with a tag "logo", and right here we save the image object to a variable using savetemp. When adding the src tag we don't need to repeat the $page->images->get('tags=logo') part again but use $gettemp() to retrieve it. After that we resize and save again, to use the resized image to add width and height attributes.

The filter doesn't modify the data it was called on. This means you can use it when chaining filters to save a certain state, eg:

<p>{('HELLO')|lower|savetemp|firstUpper|append:' World!'} - saved: {$gettemp()}</p>
// outputs: Hello World! - saved: hello

Macros iff and setvar provide similar features but savetemp is more versatile as it can be added more easily to existing markup.

srcset

Generate image variations and markup for the "data-srcset" or "data-bgset" attribute (requires Lazysizes).

Image sizes

  • image sizes need to be in a width x height format, eg. 540x320.
  • separate set of image sizes with a comma, eg. 540x320,270x160
  • use 0 if you would like to keep the existing image ratio, eg. 800x0 or 0x640
  • multipliers or divisors can be used, eg. 300x200,*3,/2. Here the second set will be 900x600, the third one 150x100. The filter will rearrange the sets in the final markup (from smallest to largest)
  • the first image size in a set should not be a multiplier nor a divisor (1)

You'll need to add the lazyload class to the image to make Lazysizes work, and also the data-sizes tag. If you need a low quality placeholder or a fallback image in a noscript tag you will have to generate them manually.

(1) You can use the keyword original to for the width and height of the image:

original,600x0,300x0 => 900x600, 600x400, 300x200 (if the input image is 900x600px)

Example:

<img data-srcset="{$page->images->first()|srcset:'540x320,*3,/2'|noescape}" data-sizes="auto" class="lazyload" alt=""/>

Generated markup:

<img data-srcset="/site/assets/files/1170/img.270x160.jpg 270w,/site/assets/files/1170/img.540x320.jpg 540w,/site/assets/files/1170/img.1620x960.jpg 1620w" data-sizes="auto" class="lazyload" alt=""/>

Image resize options array can be passed as optional second parameter (read more here):

<img data-srcset="{$page->images->first()|srcset:'1200x600,/2,/4', array('upscaling'=>true)|noescape}" data-sizes="auto" class="lazyload" alt=""/>

Note that the following CSS rule should be present if you are using data-sizes="auto": img[data-sizes="auto"] { display: block; width: 100%; } (read more at the Lazysizes documentation).

You can also use the filter to generate markup for the bgset Lazysizes plugin:

<div data-bgset="{$img|srcset:'1200x360,/2,/3'|noescape}" class="lazyload" data-sizes="auto"></div>

The filter adds an associative array of image variation widths and urls, sorted in ascending order, to a temporary variable that you can get using $gettemp() - see the savetemp filter for more info. You can use this to output the smallest or largest image variation's url, for example for LQIP's or noscript tags:

<noscript>
    <img src="{$gettemp()|last}" alt=""/>
</noscript>

surround

Surround item or array of items with html tag. The angle brackets can be included or excluded around html tags.

{$page->title|surround:'h2'|noescape}
{$page->title|surround:'<h2>'|noescape}
{$page->children->title()|surround:'li'|surround:'ul class="list" data-tooltip="Children of {$page->title}"'|noescape}

truncatehtml

Truncates html string. Unlike the built-in truncate filter it adds closing html tags to the end.

Parameters:

  • limit: truncate text on this character count. Default: 120. Truncating can be disabled using false).
  • break: truncate before the first occurrence of the break character (after the number of characters set in limit). Default: ' '.
  • pad: character(s) to add at the end of truncated text (inside html tags). Default: '…' (ellipsis).

Use null to use the default values.

{*truncate html at 100 chars*}
{$page->body|truncatehtml:100|noescape}

{*truncate html at 100 chars, break on ' ' (null = default) and add ' [...]' pad*}
{$page->body|truncatehtml:100,null,' [...]'|noescape}

{*truncate html at 120 chars (null = default), and truncate before the first paragraph that occurs after 120 chars*}
{$page->body|truncatehtml:null,'<p',''|noescape}

{*disable truncating, eg. for testing*}
{$page->body|truncatehtml:false|noescape}