I’ve put together this code for Shopify that creates a string containing all the variant image src’s apparent in a product. It then compares this list to the overall product.media
object and "filters out" the images that share the same URL as the variant images, so that I get a string that only contains URL’s for images not associated with a variant. I can then use this final string/array with a for loop that only outputs images not connected to a variant, for example to use with a gallery that only should contain "general images" of the product.
The code for creating this looks like this:
{% comment %}
Filter out images that is not variant images for gallery use
variant_image_srcs: String that contains all variant image srcs
gallery_images: String that created with a for loop and contains images that doesn't match it's src with any of the variant_image_srcs
gallery_images_array: String that's split and ready to be used with for loop using for example 'image | product_img_url: '1000x' filter
{% endcomment %}
{% capture variant_image_srcs %}
{% for variant in product.variants %}
{% if variant.featured_image.id != null %}
{{variant.featured_image.src }}{% if forloop.last != true %}, {% endif %}
{% endif %}
{% endfor %}
{% endcapture %}
{% capture gallery_images %}
{% for media in product.media %}
{% unless variant_image_srcs contains media.preview_image.src %}
{{media.preview_image.src }}{% if forloop.last != true %}, {% endif %}
{% endunless %}
{% endfor %}
{% endcapture %}
{% assign gallery_images_array = gallery_images | split: ", " %}
The captured gallery_images
is using this not so optimal line: {% if forloop.last != true %}, {% endif %}
that puts a ,
at the end of each item, in order to differentiate them. The problem is that the last media.preview_image.src
that should be added to the string is not always the last item in the for loop, causing the captured string to have this trailing ,
that outputs an image that can’t be found, as there are no image.src
with the string ,
.
I guess the same problem would apply to the first for loop if the variant.featured_image.id != null
would return false
.
Is there a way to remove an exact set of characters (in this case ‘, ‘) from the right of a string in Liquid or how can I otherwise do this so that ‘, ‘ is not added to the last truthy item?
Hope you understand the problem and I would love to get some input on how to make this more waterproof and effective.
3
Answers
There is an interesting feature or bug in liquid that you can use in your case.
When you split a string based a specific hook if there is nothing after that string that element is excluded from the array.
For example:
1,2,3,4,
if we split it by,
we expect top get[1,2,3,4,'']
, but we actually get[1,2,3,4]
, the last item is removed automatically since it’s empty.This only works if this is the LAST item, it doesn’t work if it’s the first or somewhere else.
In your case this probably doesn’t work since you have too much white spaces around the liquid tags. So instead of using just
{% %}
use{%- -%}
this will automatically strip white spaces and new lines.So your tags should become like so:
{%- capture -%} / {%- if -%} / {%- for -%} / {%- endcapture -%} / {%- endif -%} / {%- ednfor -%}
Another possible approach besides the above answer is to use remove_first string filter. But for that, you would have to append comma first and then image src. You can just remove the if condition then.
Simple Approach:
Just append another random character (e.g. #END), and simply remove it at last.