jekyll page.url doesn't work as it should be - jekyll

Lets say it's the code snippet:
<ul>
{% assign navigation = site.data.nav %}
{% for link in navigation %}
{% assign active = nil %}
{% for sublink in link.submenu %}
{% if page.url contains sublink.url %}
{% assign active = 'active' %}
{% endif %}
{% endfor %}
{% if page.url contains link.url %}
{% assign active = 'active' %}
{% endif %}
<li class="{{ active }}>
{{ link.text }}
{% if link.submenu %}
<ul>
{% for sublink in link.submenu %}
<li {% if page.url contains sublink.url %}class="active"{% endif %}>
{{ sublink.text }}
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
The nav.yml file looks like this:
- text: First Menu
url: /modules/some text/introduction/
- text: Second Menu
url: /modules/some more text/intro-text/
submenu:
- text: Level Two First
url: /modules/level two first/intro-text/
- text: Level Two Second
url: /modules/level two second/intro-text/
So, every menu item renders and also works fine as it should be. But the only issue i'm getting here is the variable active isn't getting updated according to those if rather staying nil. Also the following line isn't getting that active class rendered even if the page.url contains sublink.url or link.url
<li {% if page.url contains sublink.url %}class="active"{% endif %}>
What might be the issue??

Related

How to ad different navigation menus to shopify Debut theme?

So I am trying to create different navigation menus for different customer. So when I give a customer a specific tag in shopify (e.g. wholesale) he will see another menu bar than other visitors. Thsi will only happen after he logs into his account.
Now I tried to find the following snippet:
{% for link in linklists.main-menu.links %}
to replace it with the following code:
{% assign menu_handle = 'main-menu' %}
{% if customer %}
{% if customer.tags contains 'wholesale' %}
{% assign menu_handle = 'main-menu-wholesale' %}
{% endif %}
{% endif %}
{% for link in linklists[menu_handle].links %}
But I couldn't find that snippet in the debut code that looks like this:
{% comment %}
Renders a list of menu items
Accepts:
- linklist: {Object} Linklist Liquid object (required)
- wrapper_class: {String} CSS wrapper class for the navigation (optional)
Usage:
{% include 'site-nav', linklist: section.settings.main_linklist, wrapper_class: 'site-nav--centered' %}
{% endcomment %}
<ul class="site-nav list--inline{% if wrapper_class != blank %} {{ wrapper_class }}{% endif %}" id="SiteNav">
{% for link in linklists[linklist].links %}
{%- assign child_list_handle = link.title | handleize -%}
{% comment %}
Check if third-level nav exists on each parent link.
{% endcomment %}
{%- assign three_level_nav = false -%}
{% if link.links != blank %}
{% if link.levels == 2 %}
{%- assign three_level_nav = true -%}
{% endif %}
{% endif %}
{% if link.links != blank %}
<li class="site-nav--has-dropdown{% if three_level_nav %} site-nav--has-centered-dropdown{% endif %}{% if link.active %} site-nav--active{% endif %}" data-has-dropdowns>
<button class="site-nav__link site-nav__link--main site-nav__link--button{% if link.child_active %} site-nav__link--active{% endif %}" type="button" aria-expanded="false" aria-controls="SiteNavLabel-{{ child_list_handle }}">
<span class="site-nav__label">{{ link.title | escape }}</span>{% include 'icon-chevron-down' %}
</button>
<div class="site-nav__dropdown{% if three_level_nav %} site-nav__dropdown--centered{% endif %} critical-hidden" id="SiteNavLabel-{{ child_list_handle }}">
{% if three_level_nav %}
<div class="site-nav__childlist">
<ul class="site-nav__childlist-grid">
{% if link.links != blank %}
{% for childlink in link.links %}
<li class="site-nav__childlist-item">
<a href="{{ childlink.url }}"
class="site-nav__link site-nav__child-link site-nav__child-link--parent"
{% if childlink.current %} aria-current="page"{% endif %}
>
<span class="site-nav__label">{{ childlink.title | escape }}</span>
</a>
{% if childlink.links != blank %}
<ul>
{% for grandchildlink in childlink.links %}
<li>
<a href="{{ grandchildlink.url }}"
class="site-nav__link site-nav__child-link"
{% if grandchildlink.current %} aria-current="page"{% endif %}
>
<span class="site-nav__label">{{ grandchildlink.title | escape }}</span>
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
{% endif %}
</ul>
</div>
{% else %}
<ul>
{% for childlink in link.links %}
<li>
<a href="{{ childlink.url }}"
class="site-nav__link site-nav__child-link{% if forloop.last %} site-nav__link--last{% endif %}"
{% if childlink.current %} aria-current="page"{% endif %}
>
<span class="site-nav__label">{{ childlink.title | escape }}</span>
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</li>
{% else %}
<li {% if link.active %} class="site-nav--active"{% endif %}>
<a href="{{ link.url }}"
class="site-nav__link site-nav__link--main{% if link.active %} site-nav__link--active{% endif %}"
{% if link.current %} aria-current="page"{% endif %}
>
<span class="site-nav__label">{{ link.title | escape }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
Is there another way to add this code snippet into the debut code? How would that code look like?
Every hint is appreciated!
I think you need to find the code this one {% include 'site-nav', linklist: section.settings.main_linklist, wrapper_class: 'site-nav--centered' %}
and after the changes, your code looks like
{% assign menu_handle = 'main-menu' %}
{% if customer %}
{% if customer.tags contains 'wholesale' %}
{% assign menu_handle = 'main-menu-wholesale' %}
{% endif %}
{% endif %}
{% include 'site-nav', linklist: menu_handle, wrapper_class: 'site-nav--centered' %}
Update: Here I am changing the menu listing over debut theme latest versions.
in the header.liquid file I have made an update and add the snippets that check for customer and customer tags if the customer is login and tags contain wholesale.
Register as a new user and from the admin, backend assign tag wholesale to the new user account.
Here is the frontend of the non-login users and log in as a wholesale tagged customer.

How to get "Shop" link active in main navigation in Shopify Debut theme?

This is in regards to the Shopify Debut theme!
So my main nav has two links, About us and Shop. When one clicks on Shop, one is directed to "https://myshop.com/collections". At this stage the Shop link gets the class site-nav--active and changes color to be visibly active.
My problem:
The moment I click on a collection I am directed to https://myshop.com/collections/collection-name, but the Shop link for some reason does not stay active. How can I change that? I need to the Shop link be active the moment the URL has collections in it, and also when on the cart page. Any ideas?
I think i need to change something in this block of code in the site-nav.liquid file.
{% comment %}
Renders a list of menu items
Accepts:
- linklist: {Object} Linklist Liquid object (required)
- wrapper_class: {String} CSS wrapper class for the navigation (optional)
Usage:
{% include 'site-nav', linklist: section.settings.main_linklist, wrapper_class: 'site-nav--centered' %}
{% endcomment %}
<ul class="site-nav list--inline{% if wrapper_class != blank %} {{ wrapper_class }}{% endif %}" id="SiteNav">
{% for link in linklists[linklist].links %}
{%- assign child_list_handle = link.title | handleize -%}
{% comment %}
Check if third-level nav exists on each parent link.
{% endcomment %}
{%- assign three_level_nav = false -%}
{% if link.links != blank %}
{% if link.levels == 2 %}
{%- assign three_level_nav = true -%}
{% endif %}
{% endif %}
{% if link.links != blank %}
<li class="site-nav--has-dropdown{% if three_level_nav %} site-nav--has-centered-dropdown{% endif %}{% if link.active %} site-nav--active{% endif %}" data-has-dropdowns>
<button class="site-nav__link site-nav__link--main site-nav__link--button{% if link.child_active %} site-nav__link--active{% endif %}" type="button" aria-expanded="false" aria-controls="SiteNavLabel-{{ child_list_handle }}">
<span class="site-nav__label">{{ link.title | escape }}</span>{% include 'icon-chevron-down' %}
</button>
<div class="site-nav__dropdown{% if three_level_nav %} site-nav__dropdown--centered{% endif %}" id="SiteNavLabel-{{ child_list_handle }}">
{% if three_level_nav %}
<div class="site-nav__childlist">
<ul class="site-nav__childlist-grid">
{% if link.links != blank %}
{% for childlink in link.links %}
<li class="site-nav__childlist-item">
<a href="{{ childlink.url }}"
class="site-nav__link site-nav__child-link site-nav__child-link--parent"
{% if childlink.current %} aria-current="page"{% endif %}
>
<span class="site-nav__label">{{ childlink.title | escape }}</span>
</a>
{% if childlink.links != blank %}
<ul>
{% for grandchildlink in childlink.links %}
<li>
<a href="{{ grandchildlink.url }}"
class="site-nav__link site-nav__child-link"
{% if grandchildlink.current %} aria-current="page"{% endif %}
>
<span class="site-nav__label">{{ grandchildlink.title | escape }}</span>
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
{% endif %}
</ul>
</div>
{% else %}
<ul>
{% for childlink in link.links %}
<li>
<a href="{{ childlink.url }}"
class="site-nav__link site-nav__child-link{% if forloop.last %} site-nav__link--last{% endif %}"
{% if childlink.current %} aria-current="page"{% endif %}
>
<span class="site-nav__label">{{ childlink.title | escape }}</span>
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</li>
{% else %}
<li {% if link.active %} class="site-nav--active"{% endif %}>
<a href="{{ link.url }}"
class="site-nav__link site-nav__link--main{% if link.active %} site-nav__link--active{% endif %}"
{% if link.current %} aria-current="page"{% endif %}>
<span class="site-nav__label">{{ link.title | escape }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
Below are two screenshot, which I hope will help you understand my problem.
Shop link active:
Shop link not active
The link.active
Returns true if the link object is active, or false if the link object is inactive.
So the current page URL needs to match the URL in that link.
In your case:
I need to the Shop link be active the moment the URL has collections in it, and also when on the cart page.
This should do the trick:
{%
if link.active or
request.page_type == "collection" or
request.page_type == "cart"
%}
{% assign link_active_class = "site-nav--active" %}
{% endif %}
<li class="{{ link_active_class }}">
<a href="{{ link.url }}"
class="site-nav__link site-nav__link--main{% if link.active %} site-nav__link--active{% endif %}"
{% if link.current %} aria-current="page"{% endif %}>
<span class="site-nav__label">{{ link.title | escape }}</span>
</a>
</li>
This code expand on what you had before, so if the exact "Shop" link is active OR the page type is a "collection" or "cart", the link is going to be active. If none of the conditions are met the link_active_class won't be defined and class will be empty class="".
Just make sure that this code is only applied to the "Shop" link otherwise all links will be active on collections or the cart page.
Add this code
{% assign link_active_class = "" %}
{% liquid
if link.active
assign link_active_class = "site-nav--active"
elsif link.title == "shop" and request.page_type == "collection"
assign link_active_class = "site-nav--active"
elsif link.title == "shop" and request.page_type == "cart"
assign link_active_class = "site-nav--active"
endif
%}
If link is active then it's business as usual, if not
We check if the link title is "shop" and the current page type is of the desired types then we add the active class.
Make sure that the link title case matches the case of the string we are checking against, in our case "shop", if it's "Shop", adjust the code, for the sake of simplicity I didn't want to add a filter to adjust the link.title case.
We should be able to merge the elsif lines into one line, however for the sake of readability and clarity I left them as two lines.
Above this line of code
<li class="site-nav--has-dropdown{% if three_level_nav %} site-nav--has-centered-dropdown{% endif %}{% if link.active %} site-nav--active{% endif %}" data-has-dropdowns>
Replace {% if link.active %} site-nav--active{% endif %} in the line above, with {{ link_active_class }}.
Now, it should look like this
<li class="site-nav--has-dropdown{% if three_level_nav %} site-nav--has-centered-dropdown{% endif %} {{ link_active_class }}" data-has-dropdowns>
I didn't test this however in theory it should do the trick!

Jekyll. Liquid: Specify active/current state for exceptional nav item

Website has multiple backgrounds. To make navigation more intuitive additional class (in this example in CSS will target .active.projects) needs to be added to one of the nav items (in this case, /projects/).
My take which does not work is the 2nd elsif.
/ is used for homepage.
{% assign links = site.data.navigation %}
{% for link in links %}
{% assign class = nil %}
{% if page.url == link.url %}
{% assign class = 'active' %}
{% elsif link.url != '/' and page.url contains link.url %}
{% assign class = 'active' %}
{% elsif link.url == '/projects/' and page.url contains link.url %}
{% assign class = 'active projects' %}
{% endif %}
<li class="{{ class }}">
{{ link.name }}
</li>
{% endfor %}
navigation.yml
- name: Home
url: /
- name: Blog
url: /blog/
- name: Projects
url: /projects/
- name: About
url: /about/
How to specify active state for exceptional nav item?
Change the order:
{% assign links = site.data.navigation %}
{% for link in links %}
{% assign class = nil %}
{% if page.url == link.url and link.url != '/projects/' %}
{% assign class = 'active' %}
{% elsif link.url == '/projects/' and page.url contains link.url %}
{% assign class = 'active projects' %}
{% elsif link.url != '/' and page.url contains link.url %}
{% assign class = 'active' %}
{% endif %}
{% endfor %}

Single Index Blog Post for Multiple Series Posts in Jekyll

I have several blog posts that fall under one umbrella blog post. For example, I have several posts about SQL Zoo tutorials, but I want to be able to link them all up to one "umbrella" post so that I only have one SQL Zoo post on the index page of my blog. I got this idea from: https://codeasashu.github.io/implement-series-post-jekyll-part-2/ and tried to follow the instructions, but now my series post does not show up on my index page. I have the following code in a file called post-series.html located in my _includes folder:
{% assign seriesarray = '|' | split : '|' %}
{% assign seriestitle = '' %}
{% assign serieslabel = '' %}
{% assign sortedposts = (site.posts | sort: 'date') %}
{% for post in sortedposts %}
{% if post.series and page.series_slug != nil and post.series == page.series_slug %}
{% capture postitem %} <li> {{ post.title }} </li> {% endcapture %}
{% assign seriesarray = seriesarray | push: postitem %}
{% assign seriestitle = 'Posts in this series' %}
{% assign serieslabel = 'Series Post' %}
{% elsif post.series != nil and page.series != nil and page.series == post.series %}
{% assign pageurl = page.url | split:'/' | last %}
{% assign posturl = post.url | split:'/' | last %}
{% if pageurl != posturl %}
{% capture postitem %} <li> {{ post.title }} </li> {% endcapture %}
{% else %}
{% capture postitem %} <li> {{ post.title }} </li> {% endcapture %}
{% endif %}
{% assign seriesarray = seriesarray | push: postitem %}
{% endif %}
{% if post.series_slug != nil and page.series != nil and page.series == post.series_slug %}
{% capture series_title %} {{ post.title }} {% endcapture %}
{% assign seriestitle = 'This posts is part of series - ' | append: series_title %}
{% assign serieslabel = 'This posts is part of series - ' | append: series_title %}
{% endif %}
{% endfor %}
{% capture serieslayout %}
{% if seriesarray.size > 0 %}
<hr />
<div class="panel">
<div class="panel-body">
<h4> {{ seriestitle }} </h4>
<ul id="post-series-list">
{% endif %}
{% for post in seriesarray %} {{ post }} {% endfor %}
{% if seriesarray.size > 0 %} </ul> </div> </div> {% endif %}
{% endcapture %}
and the following code from my index.html file in the root of my directory:
---
layout: index
---
<div id="home">
<h1>{{ site.title }}</h1>
<hr />
<ol class="posts">
{% for post in paginator.posts %}
{% assign seriesPost = nil %}
{% if post.series == nil %}
{% if post.series_slug != nil %} {% assign seriesPost = '(Series)' %} {% endif %}
<li class="post-listing">
<img class="post__image" src="/static/img/{{ post.cover_image}}" alt="{{ post.cover_alt }}" />
<div class="post__text">
<a class="post__title" href="{{ post.url }}">{{ post.title }}</a><br>
<span>
{{ post.date | date_to_string }} •
{% assign words = post.content | number_of_words %}
{% if words < 360 %}
1 min read
{% else %}
{{ words | divided_by:180 }} min read
{% endif %}
</span>
{{ post.excerpt }}
</div>
</li>
{% endif %}
{% endfor %}
</ol>
<!-- <div class="sidebar-right sidebar"></div> -->
<!-- <ul>
{% for post in paginator.posts %}
<li>
{{ post.title }}
{{ post.excerpt }}
</li>
{% endfor %}
</ul> -->
<!-- Pagination links -->
{% if paginator.total_pages > 1 %}
<ul class="pagination pagination-sm">
{% if paginator.previous_page %}
<li>«</li>
{% else %}
<li class="disabled"><span aria-hidden="true">«</span></li>
{% endif %}
<li>First</li>
{% for page in (1..paginator.total_pages) %}
{% if page == paginator.page %}
<li class="active"><a>{{ page }}<span class="sr-only">(current)</span></a></li>
{% elsif page == 1 %}
<li>{{ page }}</li>
{% else %}
<li>{{ page }}</li>
{% endif %}
{% endfor %}
<li>Last</li>
{% if paginator.next_page %}
<li>»</li>
{% else %}
<li class="disabled"><span>»</span></li>
{% endif %}
</ul>
{% endif %}
</div><!-- end #home -->
My full repo can be found here: https://github.com/thedatasleuth/thedatasleuth.github.io
In your index.html, {% if post.series == nil %} simply bares posts containing a series: someserie front matter variable to be printed.
For the second problem (note that on SO, you are supposed to ask one question at a time) :
Umbrella post always have series_slug: "My serie slug" in front
matter.
Serie's posts always have series: "My serie slug" in front
matter, and this must be strictly equal to umbrella page series_slug. (eg : you have a post with published: false and series: "SQL Zoology" that will not appear in SQL Zoo serie if you publish it.)
In _layouts/post.html remove {% include series.html %}.
In _includes/post-series.html replace all your code by the following :
{% comment %} #### On an umbrella page {% endcomment %}
{% if page.series_slug != nil %}
{% assign key = page.series_slug %}
{% assign title = page.title %}
{% assign url = page.url %}
{% assign sentence = "All posts in this serie :" %}
{% endif %}
{% comment %} #### On a serie page {% endcomment %}
{% if page.series != nil %}
{% assign key = page.series %}
{% assign umbrella_page = site.posts | where: 'series_slug', key | first %}
{% assign title = umbrella_page.title %}
{% assign url = umbrella_page.url %}
{% assign series_posts = site.posts | where: "series", key %}
{% for post in series_posts %}
{% if post.url == page.url %}
{% assign idx = forloop.index %}
{% endif %}
{% endfor %}
{% capture sentence %}
This article is <strong>Part {{ idx }}</strong> in a <strong>{{ series_posts.size }}-Part</strong> in {{ title }} serie
{% endcapture %}
{% endif %}
{% if page.series_slug != nil or page.series != nil %}
{% assign series_posts = site.posts | where: "series", key %}
<hr />
<div class="panel">
<div class="panel-body">
{% if page.series_slug != nil %}
{% assign key = page.series_slug %}
{% assign title = page.title %}
{% assign url = page.url %}
{% endif %}
<h4>{{ sentence }}</h4>
<ul id="post-series-list">
{% for post in series_posts %}
<li>
{% if page.url == post.url %}
This post : {{ post.title }} - part {{ forloop.index }}
{% else %}
{{ post.title }} - part {{ forloop.index }}
{% endif %}
</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
The problem you are facing
You forgot to add the series and series_slug YML variables. That is why it is not working in your case. You seem to not fully understand how the code works, probably due to the complexity of the solution. Therefore, I added another (much simpler) solution, that might fit your needs equally well.
A better/simpler solution
Simply add a YML variable called group: groupname to each post you want in a group. Do NOT skip any of the posts during pagination. Next, list the posts with the same group on the footer of each post (in your page/post layout) with the code below. Finally, add 'part 1', 'part 2', etc. to the post names in the series.
{% if post.group != nil %}
<ul>
{% for post in site.posts %}
{% if post.group == page.group %}
<li>{{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
PS. If you really want to skip some posts in the pagination, I would create an universal solution. Add a skip_pagination boolean to the Front Matter (YML) and see if it is true in the pagination loop. This enables you to skip any post in the paginator.

Filter subpages and add classes in Jekyll

I'm using node sorting to determine pages within a subfolder in Jekyll. This image shows my folder structure:
So let's say I have a page at http://localhost/grain/ahvsuperb/ (shown below as index.html). Navigating to this page would show the class on added to that link. That works fine.
Where I'm running into trouble is when I navigate to a page such as http://localhost/grain/ahvsuperb/features/. When I navigate to that page, both index AND features have the on class added to them. Any insight as to how to filter that out with Liquid?
<div class="content_nav">
<ul class="content_nav">
{% assign sorted_pages = site.pages | sort: 'weight' %}
{% for node in sorted_pages %}
{% if node.title != nil and node.url != '/' %}
{% capture nodediff %}{{ page.url | remove:node.url }}{% endcapture %}
<li><a {% if nodediff != page.url %}class="on" {% endif %}href="{{node.url}}">{{node.title}}</a></li>
{% endif %}
{% endfor %}
<li style="float:right"><a class="brochured" href="javascript:void(0);" rel="#brochuredl">Brochure</a></li>
<li style="float:right"><a class="quoted" href="#">Get a Quote</a></li>
</ul>
</div>
Thanks!
Your {% capture nodediff %}{{ page.url | remove:node.url }}{% endcapture %} then {% if nodediff != page.url %} are not returning expected page determination.
This will do the job :
<div class="content-nav">
<ul class="content-nav">
{% assign sorted_pages = site.pages | sort: 'weight' %}
{% for node in sorted_pages %}
{% if node.title != nil and node.url != '/' %}
<li><a {% if node.url == page.url %}class="on" {% endif %}href="{{node.url}}">{{node.title}}</a></li>
{% endif %}
{% endfor %}
<li style="float:right"><a class="brochured" href="javascript:void(0);" rel="#brochuredl">Brochure</a></li>
<li style="float:right"><a class="quoted" href="#">Get a Quote</a></li>
</ul>
</div>