Liquid check if metafield exists - javascript

I want to check if a metafield (created with metafields Guru) exists on a product or not and based on that change a variable to show or hide the div holding the metafield.
I got this:
{% assign display = "inline-block" %}
{% if product.metafields.energielabel.energie.value == blank %}
{% assign display = "none" %}
{% endif %}
<div id="energielabel-container"><img class="label" src="https://cdn.shopify.com/s/files/1/0619/8034/4516/{{ product.metafields.energielabel.energie.value }}" /></div>
<style>
#energielabel-container {
width: 80px;
display: {{ display }};
}
</style>
When I just add some example letters into to the if condition it´s working as it should (empty metafield = shows the exaple letters ), but redefining the variable doesn´t work...

<img class="label" src="https://cdn.shopify.com/s/files/1/0619/8034/4516/{{product.metafields.energielabel.energie.value}}" />
The line above is questionable. you should store the whole url instead;
using your method will create extra code and errors; the img tag will still fetch the url that does not exist. So just check with if tag and put all code inside.
{% if product.metafields.energielabel.energie.value %}
<style>
#energielabel-container {
width: 80px;
display: inline-block;
}
</style>
<div id="energielabel-container">
<img class="label" src="https://cdn.shopify.com/s/files/1/0619/8034/4516/{{product.metafields.energielabel.energie.value}}" />
</div>
{% endif %}

Your if statement checks if metafield is blank using == operator. What you want is to check if it's not blank (if it exists)
Try:
{% if product.metafields.energielabel.energie.value != blank %}
{% assign display = "none" %}
{% endif %}

Related

How can I set a variable width in my CSS or Tailwind class?

I am getting the width from my Django View, but I do not know if I can make it variable in CSS.
I’ve been trying to set the Tailwind, but I imagine that it is not the right thing to do:
{% for movie in movies %}
<div id="bar" class="w-[{movie.score}]"
style="transition: 1s">
{{movie.score}}
</div>
{% endfor %}
However, I am also trying to do it directly in CSS, but the style does not accept a variable as:
{% for movie in movies %}
<div id="bar" style="transition: 1s; width: {{movie.score}}; ">
{{movie.score}}
</div>
{% endfor %}
I’ve also tried to change it using JavaScript, but I have to select multiple elements because there will be various bars. So, this just not worked. I receive messages that the movies were declared before if I use let, but using var nothing changes.
def get_context_data(self, **kwargs):
context = super(MoviesRatePage, self).get_context_data(**kwargs)
context['movies'] = movies
return context
{% block javascript %}
<script type="text/javascript">
var movies = "{{movies}}";
for (let i = 0; i < movies.length; i++) {
document.querySelectorAll("#bar")[i].style.width = `${movies[i].score}%`;
}
</script>
{% endblock javascript %}
Thus, I want to make the bar width the same as the movie’s score.
The second solution - with setting width directly via style attribute should technically work. The only missing thing is unit for width. Append px and it should be fine:
{% for movie in movies %}
<div id="bar" style="transition: 1s; width: {{movie.score}}px; ">
{{movie.score}}
</div>
{% endfor %}

Changing elements' CSS using jQuery after another element is changed with AJAX

I have a custom button in the a header next to a "cart" link. Website uses AJAX cart. When an item is added to cart, the cart link enlarges to include nr of items in cart. This causes the cart link to overflow and overlap the custom button next to it. Essentially what I'm trying to achieve is to add a margin to the custom button when an item is added to cart and the cart link is expanded. My first thought was to wrap both in a div and use CSS flex to adjust the sizing of both, however, and please correct me if I'm wrong, I thought it would be quicker to just write a script that would add a margin to my custom button. Definitely didn't turn out to be the quicker way as I've been stuck on it for hours now - any help would be greatly appreciated. I've browsed through similar posts and couldn't find a result that I want - any help would be greatly appreciated (I'm still new to JS and jQuery but learning). Below is the code and some of the things that I've tried.
HTML - header
<div class="header--menu">
<div class="custom-btn-container">
Quick Order
</div>
{%
render 'framework--x-menu',
js_class: 'XMenu',
align: menu_alignment,
overlap_parent: 1,
handle: menu
%}
</div>
{% endif %}
<div class="header--cart">
{% render 'snippet-cart', cart_icon: cart_icon %}
</div>
</div>
HTML - cart
{% if settings.cart--type == 'drawer' %}
<div
class="cart--open-right off-canvas--open"
data-off-canvas--open="right-sidebar"
data-off-canvas--view="cart"
aria-haspopup=”menu”
>
{% endif %}
<a
class="header--cart-link"
data-item="accent-text"
href="{{ routes.cart_url }}"
aria-label="{{ 'layout.header.cart' | t }}"
>
{% if cart_icon == 'text' %}
{{ 'layout.header.cart' | t }}
{% elsif cart_icon == 'bag' %}
{% render 'framework--icons', icon: 'bag' %}
{% else %}
{% render 'framework--icons', icon: 'cart' %}
{% endif %}
<span class="header--cart-number" data-item-count="{{ cart.item_count }}">
(<span class="cart--external--total-items">{{ cart.item_count }}</span>)
</span>
</a>
{% if settings.cart--type == 'drawer' %}
</div>
{% endif %}
And these are some of the scripts that I've tried:
window.onload = () => {
if (jQuery('.header--cart-number').data('item-count') != '0') {
$(".custom-button").css('margin-right', '10px');
}
}
The above is nearly what I'm after, but only works after refreshing the page.
document.ajaxComplete = () => {
if (jQuery('.header--cart-number').data('item-count') != '0') {
$(".custom-button").css('margin-right', '10px');
}
}
similar story
$(document).ajaxSuccess(function() {
if (jQuery('.header--cart-number').data('item-count') != '0') {
$(".custom-button").css('margin-right', '10px');
}
}
This didn't do anything whatsoever.
I'm sure I'm missing something small, but it's driving me mad. Again, any help will be greatly appreciated!
Best,
J

Show and hide text of different posts

I have several posts each of them composed of three parts : a title, a username/date and a body. What I want to do is to show the body when I click on either the title or the username/date and hide it if I click on it again. What I've done so far works but not as expected because when I have two or more posts, it only shows the body of the last post even if I click on another post than the last one. So my goal is only to show the hidden text body corresponding to the post I'm clicking on. Here is my code:
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Test page{% endblock %}</h1>
<a class="action" href="{{ url_for('main_page.create') }}">New</a>
{% endblock %}
{% block content %}
{% for post in posts %}
<article class="post">
<header>
<script language="JavaScript">
function showhide(newpost)
{var div = document.getElementById(newpost);
if (div.style.display !== "block")
{div.style.display = "block";}
else {div.style.display = "none";}}
</script>
<div onclick="showhide('newpost')">
<h1>{{ post['title'] }}</h1>
<div class="about">by {{ post['username'] }} on {{ post['created'].strftime('%d-%m-%Y') }}</div>
</div>
</header>
<div id="newpost">
<p class="body">{{ post['body'] }}</p>
</div>
</article>
{% if not loop.last %}
<hr>
{% endif %}
{% endfor %}
{% endblock %}
Of course I looked for a solution as much as I could but I'm kind of stuck plus I'm a complete beginner in HTML/JS/CSS. And one last thing, I'm currently using Python's framework Flask. Thank you by advance.
You need to give each of your posts a unique id for your approach to work.
Change your code to
<div id="{{post_id}}">
<p class="body">{{ post['body'] }}</p
</div>
where post_id is that post's unique id e.g. its id in the database you are using that you pass to the template in your view. Then, change the call to the onclick event handler to
<div onclick="showhide('{{post_id}}')">
If you don't have a unique id you can also use the for loop's index: replace all post_id instances above with loop.index. See Jinja's for loop docs for more information.

How do I populate dynamically a StringField with the value of a SelectField in Wtforms

in a wtforms, I would like my SelectField to fill up with its selected value a StringField.
I use flask, bootstrap, and python 3.7
My HTML code is as follow:
{% block body %}
<h3>Edit Bloomberg ticker details</h3>
{% from "includes/forms/_form_helpers.html" import render_field %}
<div class="form-group" id="company_id" onchange="myFunction(event)">
{{render_field(form.company_names, class_="form-control")}}
</div>
<div class="form-group" id="isin_id">
{{render_field(form.isin_id, class_="form-control")}}
</div>
<script>
function myFunction(e) {
document.getElementById("isin_id").value = e.target.value
}
</script>
{% endblock %}
And the pyhon behind is as follow:
class DefTickerForm(_Form):
choices_companies = [(1,'Facebook'), (2, 'Google') ]
company_names = _SelectField(label='Company names:', choices=choices_companies, coerce=int)
isin_id = _StringField(label='isin_id', validators=[_validators.DataRequired], default=-1)
I would like that when the user select 'Facebook', the isin SelectField to be equal to 1. But so far it does nothing.
Note that if if code:
alert(e.target.value)
I get the wanted value. so issue is to set the TextField value.
my render field code is as followed (from a youtube tutorial):
{% macro render_field(field) %}
{{ field.label }}
{{ field(**kwargs)|safe }}
{% if field.errors %}
{% for error in field.errors %}
<span class="help-inline"> {{ error }}</span>
{% endfor %}
{% endif %}
{% endmacro %}
Any help would be much apreciated as google isn't so good on these.
Best
apparently TextField only accepts strings (I guess obvious if you are used to javascript)
so code working is as follow in case someone get he same problem:
<div class="form-group" onchange="myFunction(event)">
{{render_field(form.company_names, class_="form-control")}}
</div>
<div class="form-group">
{{render_field(form.isin_id, class_="form-control")}}
</div>
<script>
function myFunction(e) {
var x = e.target.value;
alert(x);
document.getElementById("isin_id").value = x.toString();
}
</script>
As a note, Jinja or anyway my render, use the fields names as default IDs (wich i realised using Chrome inpector. Meaning I didn't have to add an id for each Div. Anyway that is the thoughts of a beginenr in Javascripts.

Using javascript variables in Shopify liquid

I am trying to use a javascript variable inside the image tag but it is not working.
I want to create a filter for my collection in a developing project, where I can filter products by the textures of products. I have coded the following:
<div class="collection-filter-navbar-nav">
{% assign tags = 'white, yellow, golden' | split: ',' %}
<ul class="fabric-filter">
<li><a href="javascript:void(0);" >All</a></li>
{% for t in tags %}
{% assign tag = t | strip %}
{% if current_tags contains tag %}
<li><a href="javascript:void(0);" data-value="{{ tag | handle }}" >{{ tag }}</a></li>
{% elsif collection.all_tags contains tag %}
<li>{{ tag }}</li>
{% endif %}
{% endfor %}
</ul>
</div>
The html is showing in the front end, but what I need, I want to add a texture image in each tag in reference to the tag name.
So I scripted :
jQuery(document).ready(function(){
var filter_tabs = jQuery('.fabric-filter > li > a.filter-lists');
jQuery.each( filter_tabs, function(index, element){
var data_value = jQuery(this).data('value');
{% assign value = data_value %}
var img_append = '<img src="{{ 'f1-'+value+'.png' | asset_url }}">'
jQuery(img_append).appendTo(jQuery(this));
console.log(data_value);
});
});
But it is showing error. I know this can be done by css, but I am using javascript just for dynamism.
You won't be able to do this as the liquid code all runs before the jquery code.
By the time you are running the jquery liquid has already outputted the line {% assign value = data_value %}

Categories

Resources