Webpop Extensions Q & A

Michael Ruescher

We get lots of support requests related to writing custom extensions. Here's a list of extension related questions and answers so that we can all learn from each other.

Q: I'm using the truncate attribute to render a excerpt of my blog posts. If there is an inline image near the start of a post body, it gets included in the excerpt (not wanted). Is there a way to pull only the text combined with truncate ?

A: Create a "utils.js" file your extensions folder and add the following:

var html = require("html");
exports.plain = function(options,enclosed,scope) {
  return html.parse(scope[options.field]).text();
};

This extension method uses the html module to convert the contents of a field into plain text. This would strip out any tags, including images.

Then in your template, you could render a truncated, plain text version of the body field by passing it in as an option to the extension tag. Passing in format="html" will rebuild the markup for the paragraph structure.

<pop:content>
  <pop:utils:plain field="body" format="html" truncate="100"/>
</pop:content>

Q: I'm using jquery.cookie to store a comma seperated list of product id's in a cookie, how can I render the actual products based on the id's stored in the cookie?

A: Create cookie_cart.js in your extensions folder and add the following:

exports.products = function() {
  var items = request.cookies.products.split(',');
  var products = []

  items.forEach(function(item) {
    product = site.content({from: item });
    products.push( product );
  });
  return products;
}

Then you can render out your products like so in your templates:

<pop:cookie_cart:products>
  <pop:title wrap="h1"/>
  <pop:description wrap="p"/>
</pop:cookie_cart:products>

Q: I know I can render size of a file field with <pop:size/>, but is there a way to format it as Mb rather than just bytes?

A: Create file_size.js in your extensions folder and add the following:

exports.in_mb = function(options, enclosed, scope) {
  var size_in_mb = scope.size/100000;
  var formatted_mb = parseFloat(size_in_mb).toFixed(2);
  return formatted_mb + "mb"
}

Then in your templates you can render out the file size with:

<pop:file>
  <pop:file_size:in_mb/>
<pop:file>

Q: How can I increment a number for each item in a collection?

If I'm using an image gallery:

<pop:gallery wrap="ul"> 
  <li class="image1"><pop:value /></li>
</pop:gallery>

How can I increment the number in the class for each item, so that the rendered result is:

<ul> 
  <li class="image1"><img /></li>
  <li class="image2"><img /></li>
  <li class="image3"><img /></li>
</ul>

A: You can take advantage of the fact that the Pop Tags engine is essentially already doing a for each loop when it iterates through a collection. So you can create a new Pop Tag which simply increments and returns its value every time it's evaluated within the scope of a collection.

Create list.js in your extensions folders and add the following:

var count = 0;
exports.count = function() { return count++ }

And then you can use <pop:list:count/> inside of any collection to render the current count of the collection item being rendered, use it to make dynamic CSS like so:

<pop:gallery wrap="ul">
<li class="image<pop:list:count/>"><pop:value /></li>
</pop:gallery> 
« Back to Blog Index

Sign up now

30 days free trial. Sign up in 60 seconds. Upgrade, downgrade, cancel at any time.
×
blog comments powered by Disqus