Jekyll and Liquid for-loop - html

I want to create a little side navigation for on-page navigation.
The site contains multiple images one above the other, the navigation is inside every single image and is linking to the individual id's.
I am using jekyll with the liquid templating engine. To not hard code every single element I created a for-loop which gets its data of a seperat .yml file.
This is how it should looks like:
Image
My problem is that its not working on the first element. Inside the first navigation element the first circle should be selected. But its not:
Image
This is the code:
{% for element in site.data.elements %}
{% capture number %}{{ forloop.length }}{% endcapture %}
<section id="spezial-{{forloop.index}}" {% assign imgIndex = {{forloop.index0}} %} class="spezial-img" style="background-image:url('{{ element.bild }}');">
<div class="container spezial-container">
<div class="sub-navi">
<ul>
{% for y in (1..number) %}
{% if imgIndex == naviIndex %}
<li></i></li>
{% else %}
<li></i></li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</section>
{% endfor %}

You're comparing two counter that are not working the same way.
{% assign imgIndex = {{forloop.index0}}
This will count from 0 to array.size-1
{% assign naviIndex = {{forloop.index}}
This will count from 1 to array.size
As your not in the same "time zone", for the first image you have
imgIndex == naviIndex
0 == 1 -> false
And then, starting from the second loop,one time in each loop you will reach an equality but not on the right element.
On the second imgIndex element, for example, the active class will be set on the first naviIndex element but it's wrong. And it's the same for all following elements.
Correct code can be :
{% for element in site.data.elements %}
{% capture number %}{{ forloop.length }}{% endcapture %}
{% assign imgIndex = {{forloop.index}} %}
<section id="spezial-{{imgIndex}}" class="spezial-img" style="background-image:url('{{ element.bild }}');">
<div class="container spezial-container">
<div class="sub-navi">
<ul>
{% for naviIndex in (1..number) %}
{% if imgIndex == naviIndex %}
<li></i></li>
{% else %}
<li></i></li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</section>
{% endfor %}

Related

How to create 2 columns using the batch filter in twig

Im trying to put Pictures into a gallery using the batch filter with twig. I want there to be 2 columns next to eachother, but the code seems not to create the second column. Everything goes into a single column.
{% extends "_bildlayout" %}
{% block content %}
{% for entry in craft.entries.section('bilder').limit(16)|batch(8) %}
<div class="column">
{% for value in entry %}
{% set bild = value.bild.one() %}
<img src="{{ bild.url }}" alt="{{ value.title }}">
{% endfor %}
</div>
{% endfor %}
{% endblock %}

Django, display certain hyperlinks based on user group

{% extends 'base.html' %}
{% block content %}
<p>Welcome to home page.</p>
<p>{% user.groups.all() %}</p>
{% endblock %}
At the moment I'm trying to figure out how I could even get all the user's groups to show on the page. This results in an error.... Invalid block tag on line 5: 'user.groups.all()', expected 'endblock'. Did you forget to register or load this tag?
I have tried to do if statements, but it seems break as soon as it meets one condition. For example if user is a part of test1 and test2 groups, I'd like for it to display test1 and test2, but it only displays test1.
{% extends 'base.html' %}
{% block content %}
<p>Welcome to home page.</p>
{% if user.groups.all.0.name == "test1" %}
<p>test1</p>
{% if user.groups.all.0.name == "test2" %}
<p>test2</p>
{% endif %}
{% endblock %}
In the first code, you should have used {{ }} instead. In order to access groups, do this:
{{ user.groups.all }}
and to check for a specific group:
{% if desired_group in user.groups.all %}
some html..
{% endif %}
if you want to output specific html for each group:
{% for group in user.groups.all %}
{% if group == desired_group %}
some html..
{% endif %}
..some more conditions..
{% endfor %}

blog tag produces error right after if statement

I am trying to render three columns for per row in my html file by using Django2.1 and Bootstrap4.
The piece of HTML code looks like following:
<main class="container" role="main">
{% for treasure in treasures %}
{% block row %}
<div class="col-sm-4 py-2">
<div class="card card-body h-100">
<h4 class="card-title">{{ treasure.name }} </h4>
<img class="card-img-bottom mw-100 mh-100" src="{{ treasure.img_url }}" alt="A Kind of Treasure">
</div>
</div>
{% if forloop.counter|divisibleby:3 %}
{% endblock %} {% block row %}
{% endif %}
{% endblock %}
{% endfor %}
</main>
The error I get is:
Invalid block tag on line 44: 'endblock', expected 'elif', 'else' or 'endif'. Did you forget to register or load this tag?
PS: Line 44 is {% endblock %} {% block row %}, so I get the error right after the if check. If I delete that line, it does not produce any error.
Your first {% endblock %} tag is overlapping with the {% if forloop.counter|divisibleby:3 %} tag.
You are basically doing the following:
{% block row %}
{% if forloop.counter|divisibleby:3 %}
{% endblock %}
{% block row %}
{% endif %}
{% endblock %}
Your if tag and endif tag are in two separate blocks, this is causing the error. You wil have to remove the block tags between the if tags.
Adding to the previous answer, you can rename your blocks, and for clarity, add the name in the endblock tag.
{% for treasure in treasures %}
{% block row %}
...
{% if forloop.counter|divisibleby:3 %}
{% block row2 %}
{% endblock row2 %} # add the name in endblock for clarity
{% endif %}
{% endblock row %} # add the name in endblock for clarity
{% endfor %}

How to set up related collection items rather than related posts in Jekyll?

I've successfully implemented related posts in my site by using site.related_posts with the following Liquid templating:
The code bellow returns 4 posts related by tags on every post page, so far so good, but what's the best approach to achieve something like this for Jekyll collections?
{% assign hasSimilar = '' %}
{% for post in site.related_posts %}
{% assign postHasSimilar = false %}
{% for tag in post.tags %}
{% for thisTag in page.tags %}
{% if postHasSimilar == false and hasSimilar.size < 4 and post != page and tag == thisTag %}
{% if hasSimilar.size == 0 %}
{% endif %}
<a href="{{ site.baseurl }}{{ post.url }}" class="entry">
<div class="entry-media">
<img src="{{ post.thumbnail | prepend: site.baseurl }}" alt="">
<p class="post-cat">{% for category in post.categories.last %}{{ category }}{% endfor %}</p>
</div>
<h6 class="entry-title">{{ post.title | truncatewords: 70, '...' }}</h6>
<p class="post-date">{{ post.date | date: "%d/%m/%Y" }}</p>{% if post.series %}(Series: {{ post.series }}){% endif %}
</a>
{% capture hasSimilar %}{{ hasSimilar }}*{% endcapture %}
{% assign postHasSimilar = true %}{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% if hasSimilar.size > 0 %}
{% endif %}
As per Jekyll's documentation, when you create a collection it becomes available via the site Liquid variable, much like site.pages and site.posts, so in order to create a related collection items for my portfolio collection I replicated the Liquid logic above and assigned site.portfolio as posts, see:
{% assign posts = site.portfolio | sort: "tags" %}
So I set tags: [tag1, tag2, tag3] on every "project.md" document's front-matter within my _portfolio collectionas, as I'd normally do with posts and the liquid logic above returns the related portfolio collection items.
Anyway, although I'm not sure if this is the right path to achieve such functionality, it works as intended. I couldn't find any references/ usage for site.related_posts when it come to collections.
I'd really appreciate any thoughts regarding this issue. Thanks in advance.
site.related_posts are the ten most recent posts.
So, your code is only looking for related in ten posts not all posts.
The following code will looks for tags related items for site.posts or any site.collection
{% assign pageTagsNumber = page.tags | size %}
{% assign related = "" | split: "/" %}<!-- create empty array -->
{% assign relatedCount = 0 %}
{% assign maxRelated = 4 %}<!-- maximum number of related items -->
{% assign minTagMatch = 4 %}<!-- minimum number of tag match to be a related -->
{% if minTagMatch > pageTagsNumber %}
{% assign minTagMatch = pageTagsNumber %}
{% endif %}
{% assign matchedComplete = false %}<!-- flag -->
<!--
numberOfTag to match to be in the related list
Will try to match all page tags, then page tags size - 1, -2, until reaching minTagMatch
-->
{% for numberOfTag in (minTagMatch...pageTagsNumber) reversed %}
<!-- Looping over site.posts or any site.mycollection -->
<!-- here you can do {% for item in site.mycollection %} -->
{% for item in site.posts %}
<!-- !!! ITEM SPECIFIC -->
<!-- for a collection change item.title == page.title if needed-->
{% if related contains item or item.title == page.title %}
<!--
Don't scan an item that is already in related
Don't scan an item if we are on his page
-->
{% continue %}<!-- go to next item -->
{% endif %}
{% assign itemTagsNumber = item.tags | size %}
{% if itemTagsNumber < numberOfTag %}
<!-- Not enough tags {{ itemTagsNumber }} -->
{% continue %}<!-- go to next item -->
{% endif %}
{% assign matchingTags = 0 %}<!-- tag match counter -->
{% for tag in page.tags %}
<!-- Comparing page tag "{{ tag }}" to {{ item.tags | join: ", " }} -->
{% if item.tags contains tag %}
<!-- one matching tag increment matchingTags counter-->
{% assign matchingTags = matchingTags | plus: 1 %}
<!-- We have a match and {{ matchingTags }} matching tags total -->
{% if matchingTags >= numberOfTag %}
<!-- we have enough matching tag, this is a related item -->
{% capture html %}
<li><a href="{{ site.baseurl }}{{ item.url }}">
{{ item.title }}
{% assign pageTagsNumber = item.tags | size %}
- has {{ pageTagsNumber }} tags
- match on {{ matchingTags }} tags
</a></li>
{% endcapture %}
{% assign related = related | push: html %}
{% assign relatedCount = related | size %}
{% if relatedCount >= maxRelated %}
<!-- if we have all our related set the matchedComplete flag to true -->
{% assign matchedComplete = true %}
{% endif %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
{% if matchedComplete == true %}
<!-- matchedComplete breaking item loop! -->
{% break %}
{% endif %}
{% endfor %}
{% if matchedComplete == true %}
<!-- matchedComplete breaking numberOfTag loop! -->
{% break %}
{% endif %}
{% endfor %}
{% if relatedCount > 0 %}
<!-- print related items -->
<ul>
{% for item in related %}
{{ item }}
{% endfor %}
</ul>
{% endif %}

Same for with different behavior in Django

I have a little question, and it's about for loop in Django template:
I want to do a for and in each iteration do something different for example
{% for object in objects %}
##### html code to put a div with object information in the left and one in the right ######
{% endfor %}
To print all my objects but one in the left and another one in the right.
Can anyone help me?
You want the cycle tag.
{% for object in objects %}
<li class="{% cycle "your-left-class" "your-right-class" %}">
{{object}}
</li>
{% endfor %}
{% for object in objects %}
<div class="
{% if forloop.counter % 2 == 0 %}
pull-left
{% else %}
pull-right
{% endif %}
">
{{object}}
</div>
{% endfor %}
Check the for loop in templates.