Displaying images based upon certain collection - html

I'm trying to find a way to get an image to appear form a collections featured image. I'm able to successfully display an image but unable to access the proper location of the image.
{% if template == 'index' %}
{% for frontpage in collections %}
<h2>{{ frontpage.title }} Collection</h2>
{% if frontpage.image %}
<img src="{{ frontpage.image.src | frontpage_img_url: 'medium' }}" />
{% else %}
<img src="{{ frontpage.collections.first.featured_image | product_img_url: 'large' }}" alt="{{ frontpage.title | escape }}" />
{% endif %}
{% endfor %}
{% else %}
{% endif %}
The image link appears as /collections/test-product.png I need it to appear as https://cdn.shopify.com/s/files/1/0593/8633/collections/test-product_small.png?v=1406487979. How can I get this to work?

This article on the Shopify wiki gives an example of how to display a collection's featured image:
{% if collection.image %}
{{ collection.image.src | collection_img_url: 'medium' | img_tag: collection.title }}
{% else %}
{{ collection.products.first.featured_image.src | product_img_url: 'medium' | img_tag: collection.title }}
{% endif %}
Also see the docs for collection.image:
Returns the collection image. Use the collection_img_url filter to link it to the image file on the Shopify CDN.
And collection.image.src:
Returns the relative URL to the collection image.
In your code, use collection_img_url instead of frontpage_img_url.
You should also try frontpage.products.first.featured_image.src instead of frontpage.collections.first.featured_image.

Related

Twig set reusable piece of html

I'm creating some templates with Twig and have an issue.
I'm trying to load a piece of html that is used several times troughout a webshop. So my idea is to create a reusable piece of code that I can load everytime when needed.
The problem I'm facing is that when I do a for loop and then include that piece of code I get an empty return. With other words my code doesn't recognize the data that need to be loaded for each product in the for loop. It returns empty info boxes.
To clarify:
I have a main template index.html which calls a snippet to include some products (don't look at rain extension!!):
{% if featured %}
{% include 'snippets/products.rain' with {'products': featured, 'type': 'grid'} %}
{% endif %}
My products.rain snippet looks like this:
{% if type %}
{% if type == 'grid' %}
{% for product in products %} {# Products in this case = feautured products #}
<li class="item clearfix">.... etc etc .... </li>
{% endfor %}
{% elseif type == 'other-layout' %}
<div class="item">.... etc etc .... </div>
{% endif %}
{% endif %}
In the for loop there's html that's for 95% the same as in each for loop. I want to place that code inside a block that can be included in the for loops.
So what I did was:
{% set product_html %}
.... a lot of html ....
<a href="{{ product.url | url }}" title="{{ product.fulltitle }}">
<img src="{{ product.image }}" width="100" height="100" alt="{{ product.fulltitle }}"/>
</a>
{% endset %}
And then included in the for loop, like so:
{% if type %}
{% if type == 'grid' %}
{% for product in products %} {# Products in this case = feautured products #}
<li class="item clearfix">{{ product_html | raw }}</li>
{% endfor %}
{% elseif type == 'other-layout' %}
<div class="item">{{ product_html | raw }}</div>
{% endif %}
{% endif %}
However this returns the html that is set however with empty product.image and empty product.fulltitle.
I tried the same with set block, but that has the same result.
Is there anything I'm doing wrong....??
When you are using {% set %}, content inside your variable is not dynamic, it will only use data in your current context, see it live.
You can achieve your goal using 2 ways: using include or using macros.
As your piece of code for a product is small and not reused somewhere else, I suggest you to use macros:
{% macro product_html(product) %}
Current product is: {{ product }}
{% endmacro %}
{% import _self as macros %}
{% for product in products %}
{{ macros.product_html(product) }}
{% endfor %}
See it live

In my Jekyll include file how do I get the markdown for a post?

Is there a way to get ahold of a posts markdown in an include file?
My include file has this code: {{workingPost.content}}
When I include this in a markdown file I get the HTML. I pass that to another include that expects markdown and instead this is passing HTML.
Is there a way to access the markdown instead of the HTML for the post?
As requested here are the code files. What they do is get a featured post for the right hand side of the site like this. In that link the code is static HTML. I want to update it to make it dynamic via the following code. I already have the first image grabbing code working when it receives markdown. I'd like to use that code to grab the first image from the post here too, but by the time the code gets it the markdown has been turned into HTML.
Include file timely.html
{% assign workingPost = nil %}
{% for page in site.posts %}
{% if page.title == 'We Convert All Dollars To Bitcoin' %}
{% assign workingPost = page %}
{% endif %}
{% endfor %}
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
<div class="panel-body">
<a href="{{workingPost.url}}">
{% assign workingPostContent = workingPost.content %}
{% include first-post-image-src2.html param=workingPostContent %}
<img src="{% include first-post-image-src2.html param=workingPostContent %}" alt="{{workingPost.title}}">
<p>{{workingPost.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p>
<br>
<br>
</a>
</div>
</div>
include file first-post-image-src2.html
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}
Yes translating from markdown to html is one of the first thinks made when Jekyll build. So, no way to grab the markdown in an include. The only way to bypass this limitation is to do it with a plugin. But it's not the subject.
Now back to you code. It's to complicated and fragile.
Jekyll has all the needed functionalities to do what you want to do. Don't try to do data processing with liquid. Use the tags and filters and you will not have to fear a Gem upgrade that will break your site and bring you to a really difficult debugging.
eg : somewhere in your code, you're processing a string with a | split:"/>" filter that rely on how kramdown is rendering ìmg tag. If one day they decide to remove this useless closing slash, your code will break.
The way you can go : put all the datas in your post, in the simplest form possible, and then use them with simple Jekyll tags and filter.
The idea is to use yaml Front Matter custom variables and Jekyll post or page excerpt functionalities.
In your _config.yml, define a new excerpt separator :
excerpt_separator: "<!-- excerpt end -->" # default is "\n\n" = two new lines
In all your posts :
---
excerpt_image_src: "/images/dollarsToBitcoins.jpg"
excerpt_image_alt: "Bitcoin Bulls converts dollars to bitcoins."
popular : true # I'll explain that latter
---
Bitcoin Bulls customers pay in USD but those dollars are all converted to bitcoin.
<!-- excerpt end -->
Bulls, I'm excited to announce...
In default.html
{% if page.is_post %}
<link rel="alternate" type="application/atom+xml" title="{{ site.name }} — Atom" href="{{ site.url }}/blog/feed.atom" />
<meta property="og:image" content="{{ site.url }}{{ page.excerpt_image_src | strip_newlines }}" />
<meta property="og:description" content="{{page.excerpt}}" />
{% else %}
In _includes/timely.html :
<div class="panel panel-default">
<div class="panel-heading text-center">
<h3 class="panel-title">Popular</h3>
</div>
{% for p in site.posts %}{% if p.popular == true %}
<div class="panel-body">
<a href="{{p.url}}">
<img src="{{p.excerpt_image_src}}" alt="{{excerpt_image_alt}}">
<p>{{p.excerpt}}</p>
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</div>
{% endif %}{% endfor %}
</div>
Note the {% if p.popular == true %} that filter posts with a front matter variable popular: true.
In _includes/blog-post.html :
<li>
<a href="{{ post.url }}">
<p>{{post.date | date: "%B %d, %Y" }}</p>
<img src="{{post.excerpt_image_src}}" alt="{{post.excerpt_image_alt}}">
<!-- No need to wrap excerpt in <p> tag, Jekyll does it.
If you want to put your own tag :
<div>{{ post.excerpt | strip_html }}</div> -->
{{ post.excerpt }}
<p class="btn btn-md btn-success" role="button">READ POST</p><br><br>
</a>
</li>
In _layouts/post.html :
<h1>{{page.title}}</h1>
<div style="color:#666;">by David Smith on {{page.date | date: "%B %d, %Y" }}</div>
{% if page.excerpt_image_src %}
<p><img src="{{page.excerpt_image_src}}" alt="{{page.excerpt_image_alt}}"></p>
{% endif %}
{{ page.content | remove: page.excerpt | markdownify }}
<br>
As you're not actually displaying post excerpt in post page, it's {{ page.content | remove: page.excerpt | markdownify }}. If you want to display excerpt it's : {{ page.content | markdownify }}
I don't know why but page.content return mardown and not html, so the filter | markdownify to transform markdown to html.
Et voila ! Long live Bitcoinbulls !
The markdown isn't available. It is rendered earlier and not available.
From this answer it sounds like the markdown isn't available.
In my case I made my first-post-image-src2.html include handle the case where it gets markdown or HTML like this:
{% capture result %}
{% assign htmlAgain= 'empty' %}
{% assign foundImageAgain = 0 %}
{% if include.param contains '![' %}
{% assign imagesAgain = include.param | split:"![" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains '](' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:"](" %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:")" | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% if foundImageAgain ==0 %}
{% assign imagesAgain = include.param | split:"<img" %}
{% for imageAgain in imagesAgain %}
{% if imageAgain contains 'src="' %}
{% if foundImageAgain == 0 %}
{% assign htmlAgain = imageAgain | split:'src="' %}
{% assign htmlAgain = htmlAgain[1] %}
{% assign htmlAgain = htmlAgain | split:'"' | first %}
{% assign foundImageAgain = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{%endcapture%}{{site.url}}{{htmlAgain|strip}}

In Jekyll How do I grab a post's first image?

In my index of blog posts I'd like to grab the first image from the post to display it in the index using just liquid so it works on github pages.
I have a feeling split is the way to go, but I'm not good with liquid.
I'd like to be able to get the image url and put it in a variable to style it.
The ideal solution would be something like:
{% for post in site.posts %}
<li>
{{post.content | first_image}}
</li>
{% endfor %}
Any ideas?
You can define a custom variable to your Front Matter called "image", so it's going to work like Wordpress's posts Featured Image:
---
image: featured-image.jpg
---
Note to remember where is your image saved. In my case, I created a directory called "imagens" (PT-BR here). Then, go to your index.html and add the image to your template, wherever you want. In my site it looks like this:
<ul class="post-list">
{% for post in site.posts %}
<li>
<h2>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
<span class="post-meta">{{ post.date | date: "%b %-d, %Y" }},</span>
<span class="post-meta">por</span>
<span class="post-meta">{{ post.author }}</span>
</li>
//IMAGE
<img src="{{ site.baseurl }}/imagens/{{ post.image }}">
//IMAGE
{{ post.excerpt }}
<a class="btn btn-default" href="{{ post.url | prepend: site.baseurl }}">Continuar lendo</a>
{% endfor %}
</ul>
That's it.
Some solutions to your problem :
1 - Use the Post Excerpt tag Documentation is here
Your post :
---
layout: post
title: Testing images
---
## Title
Intro Text
![Image alt]({{ site.baseurl }}/assets/img/image.jpg "image title")
More intro text
Some more text blah !
Your template :
<ul>
{% for post in site.posts %}
<li>
{{ post.title }}
{{ post.excerpt }}
</li>
{% endfor %}
</ul>
As your image tag appears before the excerpt_separator (\n\n = two newlines) it will be in the post excerpt.
2 - Use your post's Yaml front matter to store your image's datas
Post :
---
layout: post
title: Testing images
images:
- url: /assets/img/cypripedium-calceolum.jpg
alt: Cypripedium Calceolum
title: Cypripedium Calceolum
- url: /assets/img/hello-bumblebee.jpg
alt: Hello bumblebee !
title: Hello bumblebee !
---
Intro here yo ! <-- THIS IS THE EXCERPT
Post body begin, and first image not in excerpt
{% assign image = page.images[0] %} <-- first element of the array is zero
{% include image.html image=image %}
Some more text blah !
{% assign image = page.images[1] %}
{% include image.html image=image %}
_includes/image.html (centralized in an include for standardization, but can be in the template) :
<img src="{{ site.baseurl }}{{ include.image.url }}" alt="{{ include.image.alt }}" title="{{ include.image.title }}">
The index page :
<ul class="posts">
{% for post in site.posts %}
<li>
<span class="post-date">{{ post.date | date: "%b %-d, %Y" }}</span>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
{{ post.excerpt }}
{% assign image = post.images[0] %}
{% include image.html image=image %}
</li>
{% endfor %}
</ul>
Got it to work. Not sure how it will scale, but this liquid code loops through all the posts and grabs the source for the first image from a post and displays that post. I tested it with multiple images and it works as expected.
<ul>
{% for post in site.posts %}
<li>
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
<img {{ html }} />
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{{ post.title }}
</li>
{% endfor %}
</ul>
If you just need the image URL instead of the whole thing in img tag, you can use the following method.
Install Liquid filter match_regex:
gem install match_regex
Then add it to your Jekyll config:
plugins:
- match_regex
Create a capture snippet in your template:
{% capture post_first_image %}
{% assign hero_image = page.content | match_regex: '<img .*?src="([^"]+)"' %}
{% if hero_image == nil %}
{% assign hero_image = "/placeholder-image.png" | prepend: site_base %}
{% endif %}
{{ hero_image }}
{% endcapture %}
Template:
<meta property="og:image" content="{{ post_first_image | strip }}">
You can simply remove the if condition if you don't need placeholder image.
I've taken David's answer and found a way to get just the src attribute from the img tag.
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
{% assign tags = html | split:" " %}
{% for tag in tags %}
{% if tag contains 'src' %}
<img {{ tag }} />
{% endif %}
{% endfor %}
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}

Filter products through tags in Shopify

I am trying to pull only the products from a collection that have a certain tag. This is my way of creating sub-collections since Shopify doesn't do this. My code doesn't seem to be working, and I can't figure out why it isn't working. I am doing this on the collection.liquid page. It is just printing the headings to the screen, but not the list of products. Any ideas?
{% if collection.handle == "all" %}
<!-- All Collections -->
<div id="collections">
<h2>Brave Bracelets</h2>
<div class="product-list clearfix">
<h3>Cerulean</h3>
<ul>
{% for product in collections.brave-bracelets.products %}
{% capture alt_attr %}{{ product.title }} by The Brave Collection{% endcapture %}
{% if product.tags contains "cerulean" %}
<li>
<img src="{{ product.featured_image | product_img_url: 'compact' }}" alt="{{ alt_attr }}" />
<h3>{{ product.title }}</h3>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div><!-- #collections -->
{% endif %}
There is a minor mistake on your capture line, which should be:
{% capture alt_attr %}{{ product.title }} by The Brave Collection{% endcapture %}
But other than that, your code worked fine for me. I pasted it into collection.liquid and changed the collection "brave-bracelets" and tag "cerulean" to a collection and tag of my own, and it displayed the list of products as expected. Maybe double check that you do have products with the tag "cerulean" in the collection "brave-bracelets"...

Shopify tablerow loop exiting early

I'm looping through my collection of frontpage products and generating a table. In the last row, I need to put some static content in the first table cell. I've been able to do that, but for some reason, the loop stops after it does that. Does anyone know why?
{% tablerow product in collections.frontpage.products cols: 2 %}
{% if tablerowloop.col_first and tablerowloop.last %}
<img src="{{'box.png' | asset_url}}">
{% else %}
<div class='featured-product'>
<img src="{{ product.images[1] | product_img_url: 'medium' }}">
<p>{{ product.title }}</p>
</div>
{% endif %}
{% endtablerow %}
Here's the site: https://hodkiewicz-zieme-and-hirthe180.myshopify.com/
tablerowloop.last only returns true for the last cell of the table (i.e. last product of the collection), not for the last row. Instead you need to check if the index within cols of the end of the collection, such that it must be the last row if it is the first column.
{% tablerow product in collections.frontpage.products cols: 2 %}
{% assign x = tablerowloop.length | minus:2 %}
{% if tablerowloop.col_first and tablerowloop.index > x %}
<img src="{{'box.png' | asset_url}}">
{% else %}
<div class='featured-product'>
<img src="{{ product.images[1] | product_img_url: 'medium' }}">
<p>{{ product.title }}</p>
</div>
{% endif %}
{% endtablerow %}