Shopify file_url isn't showing correctly - string

I'm editing the following
{% for option in product.options %}
{% if option == 'Colour' %}
{% assign index = forloop.index0 %}
{% assign colorlist = '' %}
{% assign color = '' %}
{% for variant in product.variants %}
{% capture color %}{{ variant.options[index] }}{% endcapture %}
{% unless colorlist contains color %}
<button class="product-colour__item">
<label class="product-colour__item-label" style="background-image:url("{{ color | downcase | handleize | append: '.png' | file_url }}");">
</label>
</button>
{% capture tempList %}{{colorlist | append: color | append:''}}{% endcapture %}
{% assign colorlist = tempList %}
{% endunless %}
{% endfor %}
{% endif %}
{% endfor %}
and it's meant to show like:
style="background-image:url("//cdn.shopify.com/s/files/1/0584/2419/7328/products/deep-rose.png");
instead its showing like:
style="background-image:url(" cdn.shopify.com s files 1 0584 2419 7328 deep-rose.png");
I know it's missing the /products/ as well as the rest of it.
What am I doing wrong?

Related

How to manipulate count based on sub-values in TWIG?

I was wondering how to manipulate / render the count based on sub-rules.
In the current situation specifications are counted and when there are more than 5, a link is shown to show more specifications. I wanted to show only specs that have a value like this:
{% for spec in product.specs | limit(5) %}
{% if spec.value %}
<li>
<span>{{ spec.title }}</span>
{{ spec.value }}
</li>
{% endif %}
{% endfor %}
{% if product.specs | length > 5 %}
<li class="more">{{ 'View all specifications' | t }}</li>
{% endif %}
In this case the count is done before checking the values of the sub-items, so the "Show more" link is visible and clickable, but doesn't show more specifications, because they are stripped out, because the value is empty but is counted as item.
The goal is to hide the "Show more" link when there are < 5 items WITH values.
I hope anyone could point me in the right direction :-)
Thank you very much for thinking with me!
You could either use an extra counter to count the valid elements,
{% for spec in product.specs | limit(5) %}
{% if spec.value %}
<li>
<span>{{ spec.title }}</span>
{{ spec.value }}
</li>
{% endif %}
{% endfor %}
{% set cnt = 0 %}
{% for spec in product.specs %}
{% if spec.value %}{% set cnt = cnt + 1 %}{% endif %}
{% endfor %}
{% if cnt >= 5 %}
<li class="more">{{ 'View all specifications' }}</li>
{% endif %}
Or you can use the filter filter
{% if products.specs| filter(spec => spec.value|default) | length >= 5 %}
<li class="more">{{ 'View all specifications' }}</li>
{% endif %}
Update as for your comment (and as you don't have access to filter)
You can't just limit the result before hand. So in the first part you would also need to use a counter
{% set cnt = 0 %}
{% for spec in product.specs %}
{% if cnt < 5 %}
{% if spec.value %}
<li>
<span>{{ spec.title }}</span>
{{ spec.value }}
</li>
{% set cnt = cnt + 1 %}
{% endif %}
{% endif %}
{% endfor %}

Twig indexpage add numeric in one single category

On a SaaS platform I try to create an indexpage/sitemap for a website with a lot of categories.
Since it's a SaaS platform I'm not able to use/create custom functions whatsoever.
It have to be done at the frontend.
What I try to do is divide a list of categories into a list divided in letters and digits.
So a category name starting with A will go in category "A", a category starting with a number (eg 18 years) will go in a category called "0-9". So I will get an indexpage like so:
[A]
- Alpha
- Anton
- etc..
[B]
- Beta
- Brave
- etc..
[C]
- Charlie
- Cooking
- etc..
[0-9]
- 1 year
- 20 years
- 99 years
- etc..
I managed to get this working for all letters. However it not always put numbers in the [0-9] category. My script sometimes create a seperate index for eg 0 or 7 etc. So like:
[0]
- 1 year
- 18 years
- etc..
[1]
- 2 years
- 22 years
Also the index number is wrong. So it shows 1 under 0 and 2 under 1. Instead of:
[0-9]
- 1 year
- 18 years
- 2 years
- 22 years
I just can't see why that is. So my question is how can I put [numeric] categories in a single categorie called [0-9] instead of having them in a seperate categorie?
My code upto now looks like (some filters are specific platform filters):
{# ---------------- BEGINING ------------------- #}
{% set all_categories = [] %}
{% for category in shop.categories %}
{% set all_categories = all_categories | merge({ (0): category }) %}
{% for sub in category.subs %}
{% set all_categories = all_categories | merge({ (0): sub }) %}
{% for sub_sub in sub.subs %}
{% set all_categories = all_categories | merge({ (0): sub_sub }) %}
{% for sub_sub_sub in sub_sub.subs %}
{% set all_categories = all_categories | merge({ (0): sub_sub_sub }) %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
{% set categories = all_categories %}
{# ---------------- SORT LOGIC ------------------- #}
{# 'categories' array will be sorted and saved as 'grouped_categories' variable #}
{% set sorted_categories = [] %}
{% for key in categories | keys %}
{% set sorted_categories = sorted_categories | merge({ (key): categories[key].title }) %}
{% endfor %}
{% set sorted_categories = sorted_categories | sort %}
{% set first_letter = '' %}
{% set grouped_categories = [] %}
{% set new_group = [] %}
{% for i in sorted_categories | keys %}
{% if(categories[i].title) %}
{% set currect_first_letter = categories[i].title | first | upper %}
{% if(currect_first_letter != first_letter) %}
{% if(new_group) %}
{% set grouped_categories = grouped_categories | merge({ (first_letter): new_group }) %}
{% endif %}
{% set first_letter = currect_first_letter %}
{% set new_group = [categories[i]] %}
{% else %}
{% set new_group = new_group | merge({ (0): categories[i] }) %}
{% endif %}
{% endif %}
{% endfor %}
{% set grouped_categories = grouped_categories | merge({ (first_letter): new_group }) %}
{# ---------------- USING ------------------- #}
<div class="single-letter">
<span class="custom-title">{{ "All themes" }}:</span>
<ul>
{% for letter in grouped_categories[1:] | keys %}
<li>{{ letter }}</li>
{% endfor %}
{% for letter in grouped_categories[:1] | keys %}
<li>{{ '0-9' }}</li>
{% endfor %}
</ul>
</div>
{% for letter in grouped_categories[1:] | keys %}
<div id="letter-{{letter}}" class="letter-wrap">
<h3 class="title">{{ letter }}</h3>
<div class="group">
<ul>
{% for category in grouped_categories[letter] %}
<li>{{ category.title }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endfor %}
{% for letter in grouped_categories[:1] | keys %}
<div id="letter-{{letter}}" class="letter-wrap">
<h3 class="title">{{ '0-9' }}</h3>
<div class="group">
<ul>
{% for category in grouped_categories[letter] %}
<li>{{ category.title }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endfor %}
{# ---------------- THE END ------------------- #}
UPDATE AS PER REQUEST
Updated code
{% for category in categories %}
{% set currect_first_letter = category | first | upper %}
{% if currect_first_letter in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] %}
{% set currect_first_letter = '0-9' %}
{% endif %}
{% if not (currect_first_letter in (grouped_categories | keys)) %}
{% set grouped_categories = grouped_categories | merge({ (currect_first_letter): [], }) %}
{% endif %}
{% set grouped_categories = grouped_categories | merge({ (currect_first_letter) : grouped_categories[currect_first_letter] | merge([ category, ]), }) %}
{% endfor %}
{#{% set sorted_categories = [] %}
{% for key in categories | keys %}
{% set sorted_categories = sorted_categories | merge({ (key): categories[key].title }) %}
{% endfor %}
{% set sorted_categories = sorted_categories | sort %}
{% set first_letter = '' %}
{% set grouped_categories = [] %}
{% set new_group = [] %}
{% for i in sorted_categories | keys %}
{% if(categories[i].title) %}
{% set currect_first_letter = categories[i].title | first | upper %}
{% if(currect_first_letter != first_letter) %}
{% if(new_group) %}
{% set grouped_categories = grouped_categories | merge({ (first_letter): new_group }) %}
{% endif %}
{% set first_letter = currect_first_letter %}
{% set new_group = [categories[i]] %}
{% else %}
{% set new_group = new_group | merge({ (0): categories[i] }) %}
{% endif %}
{% endif %}
{% endfor %}
{% set grouped_categories = grouped_categories | merge({ (first_letter): new_group }) %}#}
This has as result:
The merge filter only works with arrays or hashes; NULL and array given in....
You should be able to solve this if you override the currect_first_letter.
{% set currect_first_letter = categories[i].title | first | upper %}
{% if currect_first_letter in [0, 1, 2, 3, 4, 5, 6, 7, 8 , 9, ] %}
{% set currect_first_letter = '0-9' %} {# change to same group #}
{% endif %}
demo
Okay I've gone over your code and simplified the grouping process a bit.
Here is the code I would use to combine arrays in twig
{% set grouped_categories = [] %}
{% for category in categories %}
{% set currect_first_letter = category | first | upper %}
{# ----- ADDED THIS LINE ------- #}
{% if currect_first_letter in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] %}
{% set currect_first_letter = '0-9' %}
{% endif %}
{# ----------------------------- #}
{% if not (currect_first_letter in (grouped_categories | keys)) %}
{% set grouped_categories = grouped_categories | merge({ (currect_first_letter): [], }) %}
{% endif %}
{% set grouped_categories = grouped_categories | merge({ (currect_first_letter) : grouped_categories[currect_first_letter] | merge([ category, ]), }) %}
{% endfor %}
Validation purpose:
{% for key in grouped_categories|keys %}
Key: {{ key }}
Values:
{% for value in grouped_categories[key] %}
- {{ value }}
{% endfor %}
{% endfor %}
demo
It seems if you use var in [0, 1, ...], before twig 3.X the 0 will return a false positive.
Try to use your original code, the one where everything got grouped in [0-9], but with the following statement
{% if currect_first_letter in [1, 2, 3, 4, 5, 6, 7, 8, 9] or currect_first_letter == '0' %}

How to add "Read More" in text displayed on several lines but only a certain number of lines with twig

I am using the following function in twig to show a part of the content of the description of a news item saved in a database:
{{ new.description|striptags|truncate(300,true)|raw|nl2br }}
With this function inside a p element in the html, I get the text whose characters do not exceed 300 and then I add "Read More" with an element a:
<p >{{ new.description|striptags|truncate(200,true)|raw|nl2br }}
<a class="href_blue" href="{{ path('new', {'id': new.id}) }}">
<strong> [Read More] </strong></a>
</p>
This code works for text that comes in a paragraph with more than 300 characters, but if for example I have another one with several "p" elements that are then changed in twig to elements and I need it to only show me several lines because I have A maximum elevation of the container where it is displayed, I would not know how to do it, since it shows me all line breaks until it does not exceed 300 characters.
To clarify it a little more, I show an image of the result:
What I need is that in the case of Title2 having many line breaks, just show some and add the "Read More" before so that the height of the div is equal to the previous one (to show the example I removed the max- Height and overflow: hidden).
How could I get that?
I greet your help in advance.
You could do something like this in Twig:
{% set paragraphs = new.description|split('</p>') %}
{% set summary = '' %}
{% for i in 1..10 %}
{% set summary = summary ~ paragraphs[i] %}
{% endfor %}
{% set summary = summary ~ '[Read More]' %}
Now you can use the summary variable in your twig file to show the truncated summary.
EDIT #2 based on comments
Then try this instead:
{% set paragraphs = new.description|split('</p>') %}
{% set summary = '' %}
{% for i in 1..(paragraphs|length) %}
{% set summary = summary ~ paragraphs[i] %}
{% if summary|length > 300 %}
{% set shortsummary = summary %}
{% endif %}
{% endfor %}
{% set final_summary = shortsummary|slice(:300) ~ '[Read More]' %}
EDIT #3 Code modified with the solution to the problem
{% set paragraphs = new.description|striptags|truncate(300,true)|raw|nl2br %}
{% set paragraphs = paragraphs|split('<br />') %}
{% set summary = "" %}
{% set cont = 90 %}
{% set type = "" %}
{% if paragraphs|length == 1 %}
{% set summary = paragraphs[0] %}
{% if summary|length <= 300 %}
{% set type = "" %}
{% else %}
{% set type = "anything" %}
{% endif %}
{% else %}
{% for i in 1..(paragraphs|length) %}
{% if summary|length + cont + paragraphs[i-1]|length <= 500 %}
{% set summary = summary ~ "<br>" ~ paragraphs[i-1] %}
{% set cont = cont + 90 %}
{% else %}
{% set type = "anything" %}
{% endif %}
{% endfor %}
{% endif %}
//In the case of a description with less than 300 characters the option "Read More" is not shown
{% if type != "" %}
<p>{{ summary|striptags|truncate(300,true)|raw|nl2br }}<a class="href_blue" href="{{ path('new', {'id': new.id}) }}"> <strong> [Read More] </strong></a></p>
{% else %}
<p>{{ summary|striptags|truncate(300,true)|raw|nl2br }}<a class="href_blue" href="{{ path('new', {'id': new.id}) }}"></a></p>
{% endif %}

Access posts from other page in jekyll pagination

Jekyll pagination enables you to arrange posts neatly on pages. I would like to put the range of dates as a tooltip on the links to the pages, just as:
<li class="pager-item">
Page 2
</li>
The obvious way to do so would be to take the date of the first and the last post on a page. Unfortunatly jekyll-pagination only seems to deliver a list of posts for the current page via paginator.posts.
Maybe I just can't find it in the documentation, so I ask you: is it possible to access a list of posts from another page in jekyll pagination? Something like paginator.pages.2.posts?
An alternate approach would be to build my own paginaton, which should be no problem, but I would prefer to use built-in functions.
You can get the information indirectly:
paginator.previous_page and paginator.next_page give you the page number of respectively the previous and the next pagination page, or nil if the page does not exists.
paginator.per_page gives you the number of posts per page.
paginator.total_posts gives you the total number of posts in the site.
site.posts gives you a reverse chronological list of all posts.
So given the current paginator object, ensuring paginator.next_page != nil, you know the posts from the next pagination page are indexed in site.posts from a to b (included) with:
a = (paginator.next_page) * paginator.per_page
b = a + paginator.per_page - 1
Last pagination page may not be complete: remember checking b < paginator.total_posts.
Ensuring paginator.previous_page != nil, same goes for previous pagination page with:
a = (paginator.previous_page) * paginator.per_page
b = a + paginator.per_page - 1
My current approach looks like this:
{% if include.page > 0 and include.page <= paginator.total_pages %}
{% assign first = include.page | minus:1 | times:paginator.per_page %}
{% assign last = paginator.per_page | times:include.page | minus:1 %}
{% if last > paginator.total_posts %}
{% assign last = paginator.total_posts | minus:1 %}
{% endif %}
{{ site.posts[first].date | date: "%d.%m.%Y" }} bis {{ site.posts[last].date | date: "%d.%m.%Y" }}
{% else %}
OUT_OF_RANGE
{% endif %}
I really don't like the Liquid-Syntax :D
Or :
{% comment %} NOTE : shortcut "p" for "paginator" {% endcomment %}
{% assign p = paginator %}
{% comment %} date formating (see shorthand formats in Ruby's documentation : http://ruby-doc.org/core-2.3.3/Time.html#method-i-strftime) {% endcomment %}
{% assign dateFormat = "%y %b %d" %}
<ul>
{% for post in p.posts %}<li>{{ post.title }} - {{ post.date | date: dateFormat }}</li>
{% endfor %}
</ul>
{% comment %}++++++++++ if previous page == newest posts {% endcomment %}
{% if paginator.previous_page %}
{% assign prevPage = p.page | minus: 1 %}
{% assign prevPageLastIndex = prevPage | times: p.per_page | minus: 1 %}
{% assign prevPageFirstIndex = prevPageLastIndex | minus: p.per_page | plus: 1 %}
{% assign prevPagefirstPostDate = site.posts[prevPageFirstIndex].date | date: dateFormat %}
{% assign prevPagenextPageLastPostDate = site.posts[prevPageLastIndex].date | date: dateFormat %}
{% capture prevPageLink %}
<p><a href="{{ paginator.previous_page_path }}"></p>
Newest posts from
{% if prevPagefirstPostDate != prevPagenextPageLastPostDate %}
{{ prevPagenextPageLastPostDate }} to {{ prevPagefirstPostDate }}
{% else %}
{{ prevPagenextPageLastPostDate }}
{% endif %}
</a>
{% endcapture %}
{% endif %}
{% comment %} ++++++++++ if next page = oldest posts {% endcomment %}
{% if paginator.next_page %}
{% assign nextPage = p.page | plus: 1 %}
{% assign nextPageFirstIndex = p.page | times: p.per_page %}
{% comment %}>>Next page is not the last page = normal computing {% endcomment %}
{% if nextPage != p.total_pages %}
{% assign nextPageLastIndex = nextPageFirstIndex | plus: p.per_page | minus: 1 %}
{% comment %}>>Next page is the last page compute index from p.total_posts{% endcomment %}
{% else %}
{% assign nextPageLastIndex = p.total_posts | minus: 1 %}
{% endif %}
{% assign nextPagefirstPostDate = site.posts[nextPageFirstIndex].date | date: dateFormat %}
{% assign nextPageLastPostDate = site.posts[nextPageLastIndex].date | date: dateFormat %}
{% capture nextPageLink %}
<p><a href="{{ paginator.next_page_path }}"></p>
Previous posts from
{% if nextPagefirstPostDate != nextPageLastPostDate %}
{{ nextPageLastPostDate }} to {{ nextPagefirstPostDate }}
{% else %}
{{ nextPageLastPostDate }}
{% endif %}
</a>
{% endcapture %}
{% endif %}
{{ prevPageLink }}
{{ nextPageLink }}

Liquid and Arithmetic

I am working on some pagination and I am wondering if there is a way to tell liquid to only show 5 pages. The output I am looking for is
<< First 5 6 7 8 9 Last >>
The logic I currently have in place works but it is showing all 30 some pages.
{% for count in (2..paginator.total_pages) %}
{% if count == paginator.page %}
<span class="current">{{ count }}</span>
{% else %}
{{ count }}
{% endif %}
{% endfor %}
I would like to be able to make the 2 and paginator.total_pages be dynamic, I have tried
{% for count in ((paginator.page - 2)..(paginator.page + 2)) %}
This code however does not actually do the math, if paginator.page = 5 then the loop is 5..5 and does not provide the expected results. I can figure out the logic so that it does not hit negative numbers and works as expected but how can I do math equations in this?
You need use a filter on paginator.total_pages to do the arithmetic, and then capture the result in a variable using the capture tag. Once you have the start and end pages, you can write the for loop as you normally would:
{% capture page_start %}{{ paginator.page | minus: 2 }}{% endcapture %}
{% capture page_end %}{{ paginator.page | plus: 2 }}{% endcapture %}
{% for count in (page_start..page_end) %}
{% comment %} ... do your thing ... {% endcomment %}
{% endfor %}
I'm building a blog with Jekyll and I've faced a similar situation. According to what I've found in the Liquid wiki is possible to iterate over a subset of a given collection using limit and offset.
The following example reflects your particular case and should work correctly in every page, from the first to the last one:
{% capture start %}{{ paginator.page | minus: 3 }}{% endcapture %}
{% for i in (1..paginator.total_pages) limit: 5 offset: start %}
...
{% endfor %}
I am using Bootstrap 3.0.3 for my website. I use the following code for pagination.
It has the same effect you're looking for. The code I posted above is what you're looking for, but I will post my bootstrap pagination code here anyways.
{% if paginator.total_pages != 1 %}
{% if paginator.total_pages < 7 %}
<div class="page-body col-md-12">
<ul class="pagination pagination-centered">
{% if paginator.total_pages >= 10 %}
{% if paginator.previous_page %}
<li>
««
</li>
{% else %}
<li class="disabled">
<a>««</a>
</li>
{% endif %}
{% endif %}
{% if paginator.previous_page %}
{% if paginator.previous_page == 1 %}
<li>
«
</li>
{% else %}
<li>
«
</li>
{% endif %}
{% else %}
<li class="disabled">
<a>«</a>
</li>
{% endif %}
{% if paginator.page == 1 %}
<li class="active">
<a>1</a>
</li>
{% else %}
<li>
1
</li>
{% endif %}
{% for count in (2..paginator.total_pages) %}
{% if count == paginator.page %}
<li class="active">
<a>{{count}}</a>
</li>
{% else %}
<li>
{{count}}
</li>
{% endif %}
{% endfor %}
{% if paginator.next_page %}
<li>
»
</li>
{% else %}
<li class="disabled">
<a>»</a>
</li>
{% endif %}
{% if paginator.total_pages >= 10 %}
{% if paginator.next_page %}
<li>
»»
</li>
{% else %}
<li class="disabled">
<a>»»</a>
</li>
{% endif %}
{% endif %}
</ul>
</div>
{% else %}
{% assign page_start = paginator.page | minus: 2 %}
{% assign page_end = paginator.page | plus: 2 %}
{% if page_end > paginator.total_pages %}
{% assign page_end = paginator.total_pages %}
{% assign page_start = paginator.page | minus: 4 %}
{% endif %}
{% if page_start < 2 %}
{% assign page_end = paginator.page | plus: 3 %}
{% assign page_start = paginator.page | minus: 1 %}
{% endif %}
{% if page_start == 0 %}
{% assign page_end = paginator.page | plus: 4 %}
{% assign page_start = paginator.page %}
{% endif %}
<div class="page-body col-md-12">
<ul class="pagination pagination-centered">
{% if paginator.total_pages > 5 %}
{% if paginator.previous_page %}
<li>
««
</li>
{% else %}
<li class="disabled">
<a>««</a>
</li>
{% endif %}
{% endif %}
{% if paginator.previous_page %}
{% if paginator.previous_page == 1 %}
<li>
«
</li>
{% else %}
<li>
«
</li>
{% endif %}
{% else %}
<li class="disabled">
«
</li>
{% endif %}
{% if page_start == 1 %}
{% assign page_end = paginator.page | plus: 4 %}
{% assign page_start = 2 %}
{% if paginator.page == 1 %}
<li class="active">
1
</li>
{% else %}
<li>
1
</li>
{% endif %}
{% endif %}
{% for count in (page_start..page_end) %}
{% if count == paginator.page %}
<li class="active">
{{count}}
</li>
{% else %}
<li>
{{count}}
</li>
{% endif %}
{% endfor %}
{% if paginator.next_page %}
<li>
»
</li>
{% else %}
<li class="disabled">
»
</li>
{% endif %}
{% if paginator.total_pages > 5 %}
{% if paginator.next_page %}
<li>
»»
</li>
{% else %}
<li class="disabled">
<a>»»</a>
</li>
{% endif %}
{% endif %}
</ul>
</div>
{% endif %}
{% endif %}
Try this instead
{% if paginator.total_pages < 7 %}
{% if paginator.page == 1 %}
<span class="current bold">1</span>
{% else %}
1
{% endif %}
{% for count in (2..paginator.total_pages) %}
{% if count == paginator.page %}
<span class="current bold">{{ count }}</span>
{% else %}
{{ count }}
{% endif %}
{% endfor %}
{% else %}
{% assign page_start = paginator.page | minus: 2 %}
{% assign page_end = paginator.page | plus: 2 %}
{% if page_end > paginator.total_pages %}
{% assign page_end = paginator.total_pages %}
{% assign page_start = paginator.page | minus: 4 %}
{% endif %}
{% if page_start < 2 %}
{% assign page_end = paginator.page | plus: 3 %}
{% assign page_start = paginator.page | minus: 1 %}
{% endif %}
{% if page_start == 0 %}
{% assign page_end = paginator.page | plus: 4 %}
{% assign page_start = paginator.page %}
{% endif %}
{% if page_start == 1 %}
{% assign page_end = paginator.page | plus: 4 %}
{% assign page_start = 2 %}
{% if paginator.page == 1 %}
<span class="current bold">1</span>
{% else %}
1
{% endif %}
{% endif %}
{% for count in (page_start..page_end) %}
{% if count == paginator.page %}
<span class="current bold">{{ count }}</span>
{% else %}
{{ count }}
{% endif %}
{% endfor %}
{% endif %}

Resources