I am trying to add breadcrumbs for my product pages on an ecommerce store. I need some help with the liquid syntax.
I want to include the first product tag as a part of the breadcrumb, unless the tag is 'stickers', 'stationery', or 'accessories', in which case I would like to use the second tag. If the second tag is also either 'stickers', 'stationery', or 'accessories', I would like to use the third tag, and so on.
Perhaps a better way to say this would be: I would like to call the first available tag that isn't either 'stickers', 'stationery', or 'accessories'.
The closest I have gotten is this:
{% if product.tags.first contains 'stickers' or product.tags.first contains 'stationery' or product.tags.first contains 'accessories' %}
<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb"><span itemprop="title">{% if product.tags.size > 0 %}{% assign words = product.tags.last | split: '-' %}{% for word in words %}{% if word == 'and' %}{{ word }} {% else %}{{ word | capitalize }} {% endif %} {% endfor %}{% endif %}</span></li>
{% else %}
<li itemscope itemtype="http://data-vocabulary.org/Breadcrumb"><span itemprop="title">{% if product.tags.size > 0 %}{% assign words = product.tags.first | split: '-' %}{% for word in words %}{% if word == 'and' %}{{ word }} {% else %}{{ word | capitalize }} {% endif %} {% endfor %}{% endif %}</span></li>
{% endif %}
This is inelegant, but it works up until a point. The point at which is breaks down is when both the first and last tags fall into one of the categories I wanted to exclude.
As far as I can see, there doesn't seem to be an option to call something like "product.tags.second" (only "first" and "last" seem to work).
I am a little out of my depth and would really appreciate some advice on how to sort this out.
The platform I'm on is Shopify.
Thanks!
Here's a couple of ways you could approach it:
<!-- 1. Loop through the product tags to find the first tag you want included in the breadcrumb -->
{% assign found_tag = false %}
{% assign tag_for_breadcrumb = '' %}
{% for tag in product.tags %}
{% if found_tag == false and tag != 'stickers' and tag != 'stationery' and tag != 'accessories' %}
{% assign tag_for_breadcrumb = tag %}
{% assign found_tag = true %}
{% endif %}
{% endfor %}
{{ tag_for_breadcrumb }}
<!-- 2. Convert the tags array into a string, remove the tags you don't want, and then get the first tag from those remaining -->
{% assign tag_string = product.tags | join: ' ' %}
{% assign filtered_tag_string = tag_string | remove: 'stickers' | remove: 'stationery' | remove: 'accessories' %}
{% assign filtered_tag_array = filtered_tag_string | split: ' ' %}
{{ filtered_tag_array.first }}
Related
I'm having an issue with a for loop in Shopify. I'm sure it used to work, but I can't get it to work over the number 9 now.
{% assign productTag1 = Availability14 %} (in this example, the product has only 1 tag, which is Availability14)
{% assign avail_stop = false %}
{% for j in (0..15) %}
{% assign check_avail = 'Availability' | append:j %}
{% if productTag1 contains check_avail %}
{% assign avail_stop = true %}
{% capture tag_name %}{{check_avail}}{% endcapture %}
{% break %}
{% endif %}
{% endfor %}
{% if avail_stop %}
{% assign availability = check_avail | remove:'Availability' | plus:0 %}
{% endif %}
At the moment, I'm returning 1, not 14. I imagine it's something to do with the fact 14 includes a 1, but I can't wrap my head around it.
Any help is appreciated.
You have a {% break %} statement in your if. Once the if becomes true it will exit the loop instantly.
If you want to skip the next code you must use {% continue %} not {% break %}.
On my mind this is an issue with conditional operator. As you said, 14 contains 1, so why not simply use strict conditional operator like this:
{% if productTag1 == check_avail %}
{% assign has_stop = true %}
{% break %}
{% endif %}
(or did I miss something?)
I'm trying to find a way to have the "if contains" conditions all appear in one line rather than having to repeat the code every single time.
Here is what the code looks like:
var selector = document.querySelector('tr[data-variant-id="{{ item.variant.id }}"] .product__description__variant');
{% assign pre_order_message = '' %}
{% for tag in item.product.tags %}
{% if tag contains 'weeks' %}
{% assign count = count | plus: 1 %}
{% assign pre_order_message = tag | split:'**' | last %}
var para = document.createElement("p");
para.classList.add('hc-shipping');
var node = document.createTextNode("Expected to begin shipping {{ pre_order_message }} from order date.");
para.appendChild(node);
selector.after(para);
{% endif %}
{% endfor %}
var selector = document.querySelector('tr[data-variant-id="{{ item.variant.id }}"] .product__description__variant');
{% assign pre_order_message = '' %}
{% for tag in item.product.tags %}
{% if tag contains 'January' %}
{% assign count = count | plus: 1 %}
{% assign pre_order_message = tag | split:'**' | last %}
var para = document.createElement("p");
para.classList.add('hc-shipping');
var node = document.createTextNode("Expected to begin shipping {{ pre_order_message }}.");
para.appendChild(node);
selector.after(para);
{% endif %}
{% endfor %}
I just want to make sure I can group together what lies between the ' ... ' on the line, that states {% if tag contains ' ' %}. Any way to fix? Thanks!
You can use and/or to combine conditions, more info about this here.
By the way if you just want to make sure a tag exists in product tags, you can do this:
{% if item.product.tags contains 'weeks' %}
Do something...
{% endif %}
Instead of looping through all the tags, you'll save a couple of lines that way ;)
One last thing, you can DRY the code by using code snippets, here's a quick read about this.
Assuming I have a list of tags: iFix_6.3, iFix_7.0, iFix_7.1, iFix_8.0, announcement, and so on... and I want to run an operation only on certain several tags. How can I check for these multiple values?
There is contains, but I'm looking for the opposite of it and for multiple values...
Here is an example where I actually filter out all posts that contain the iFix_6.3 tag, thus display all other posts. This actually does not work yet... plus needs to be extended to work for multiple tags.
// posts with iFix_xxx tag should be filtered from the main posts view.
{% assign postUpdates = site.posts | where_exp:"item", "item.tags != 'iFix_6.3'" %}
{% for post in postUpdates limit:10 %}
<div class="postItem inline">
<p class="postDate">{% if post.pinned %}<span class="glyphicon glyphicon-pushpin"></span>{% endif %}{{post.date | date: '%B %d, %Y'}}</p>
<p class="postTitle">{{post.title}}</p>
</div>
{% endfor %}
You can do this by building an array of excluded tags (excluded_tags) using split and a string of the comma-separated tags. Then for each post, you iterate on the post's tags. Check if the tag is in excluded_tags using contains, if it is then raise the flag filtered_out to not display the post, using the unless control flow tag.
{% assign excluded_tags = "iFix_6.2,iFix_6.3,announcement" | split : "," %}
{% for post in site.posts limit:10 %}
{% assign filtered_out = False %}
{% for tag in post.tags %}
{% if excluded_tags contains tag %}
{% assign filtered_out = True %}
{% break %}
{% endif %}
{% endfor %}
{% unless filtered_out %}
...
{% endunless %}
{% endfor %}
Seems unless would solve the case.
{% assign postUpdates = site.posts | where_exp:"item", "unless item.tags contains 'iFix_6.3'" %}
I want to render the “Tags:” label only if the post has actual tags. When I write
{{post.tags | size}}
I get the number of tags. However, if I put it in an {% if %} condition:
{% if post.tags | size != '0' %}
it always yields true. I worked around this problem with
{% capture tagsize %}{{post.tags | size}}{% endcapture %}
{% if tagsize != '0' %}
but it seems very ugly. Is there a better way to do this?
Note: I use GitHub Pages, so using a plugin – other than being an overkill – is not an option. My Jekyll version is 2.0.4 as specified here as of date.
By default {{ post.tags }} == empty array.
As we cannot do {% if post.tags != [] %}, we just add array: [] in _config.yml.
We can now do :
{% if post.tags != site.array %}
Do something
{% endif %}
tag size returns an integer and not a string so you should compare against 0 and not '0'
{% if page.tags.size != 0 %}
<!-- some code to render tags -->
{% endif %}
I am migrating my Wordpress blog to Jekyll, which I like a lot so far. The current setup in the new site is like this:
use category to distinguish two types of posts (e.g., blog and portfolio)
use tag as normal
The challenge right now is to display all tags within a category because I want to create two separate tag clouds for two types of posts.
As far as I know, Liquid supports looping over all tags in a site like this:
{% for tag in site.tags %}
{{ tag | first }}
{% endfor %}
But I want to limit the scope to a specific category and am wishing to do something like this:
{% for tag in site['category'].tags %}
{{ tag | first }}
{% endfor %}
Any advice will be appreciated.
This seems to work for all kinds of filters like category or other front matter variables - like "type" so I can have type: article or type: video and this seems to get tags from just one of them if I put that in the 'where' part.
{% assign sorted_tags = site.tags | sort %}
{% for tag in sorted_tags %}
{% assign zz = tag[1] | where: "category", "Photoshop" | sort %}
{% if zz != empty %}
<li><span class="tag">{{ tag[0] }}</span>
<ul>
{% for p in zz %}
<li>{{ p.title }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
zz is just something to use to filter above the first tag[0] since all it seems to have is the tag itself, so you can filter anything else with it. tag[1] has all of the other stuff.
Initially I was using if zz != null or if zz != "" but neither of them worked.
This will work, it will list only the tags on post of category 'X'. Replace X with the name of the category.
{% for post in site.categories['X'] %}
{% for tag in post.tags %}
{{ tag }}
{% endfor %}
{% endfor %}