How to make a table tr into a link? - javascript

Here is my current solution:
<tr onclick="window.location = '/info/{{ match.login.id }}/'">
<td>{% if match.image %}<img src="{{ match.image|crop:'64x64' }}" alt="Match Avatar" />{% endif %}</td>
<td>{{ match.team_name }}</td>
<td>{{ model|distance_to:match }} {{ model.display_distance }}</td>
<td>{% for expertise in match.expertise_list %}
<span{% if expertise in model.expertise_list %} class="match"{% endif %}>{{ expertise }}</span><br />
{% endfor %}</td>
<td>{% if model|active_connection_with:match %}{{ model|status_with:match }}{% else %}Connect{% endif %}</td>
But the thing that is wrong with this is that I want to be able to right click and copy link etc. How can i accomplish this?

Right-click to copy a link only works on the A tag. You'd have to write your own right-click hander.

It's invalid markup (and doesn't work on browsers) when you have HTML elements between table elements (tr, td, th).
If your table cells are too complicated to mark up as a link, what you can do is have an invisible <a> element that covers each <td> that you want to link:
<table>
<tr>
<td>
Google
</td>
<td>
Yahoo
</td>
</tr>
</table>
td {
position: relative;
}
.overlay {
background-color: transparent;
position: absolute;
width: 100%;
height: 100%;
}
Demo: http://jsfiddle.net/waitinforatrain/puTbj/1/
The only downside is that users can't select the text under it.

Related

Conditionally changing the formatting of cells in a loop-generated table

My django app generates a table on the basis of the python dictionary "participants". To do that, it uses the HTML code below, which features a loop that run through all the *elements* of "participants". The table is generated without any problems.
Now I want to conditionally change the background color of the column with the value "balance", depending on whether that value is > 0, < 0, or = 0. To that purpose, I have inserted javascript at the bottom of the HTML body. But this has no effect whatsoever. How can the code be fixed?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Participants</title>
</head>
<body>
<h1>Participants</h1>
<table id="participants_table" border="1">
{% for x in participants %}
<tr>
<td>{{ x.firstName }}</td>
<td>{{ x.lastName }}</td>
<td class="balance">{{ x.balance }}</td>
</tr>
{% endfor %}
</table>
<script>
var balance = document.getElementById('participants_table').getElementsByClassName('balance');
if (balance.innerHTML > 0){
balance.style.backgroundColor='#003F87';
} else if (balance.innerHTML < 0) {
balance.style.backgroundColor='#0033H7';
} else {
balance.style.backgroundColor='#0093H7';
}
</script>
</body>
</html>
Theoretically this should work.
<td style=background-color: "{% if x.balance > 0 %}#003F87{% elif
x.balance < 0 %}#0033H7 {%else%)#0093H7{% endif %}">{{ x.balance
}}</td>
So I am using inline styling(not recommended) and conditionally rendering the bg color. If you're using something like Bootstrap, then it may be cleaner like this:
<td class="{% if x.balance > 0 %}bg-primary{% elif x.balance < 0
%}bg-warning{%else%)bg-secondary{% endif %}>{{ x.balance }}</td>

Liquid check if metafield exists

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 %}

Shopify Product Page to hide variant images

I am sort of new with Shopify and I´ve been playing around with it for the ast week or so without much success when trying to solve my issue.
I am currently using the Brooklyn template and the way they represent the Product Page doesn´t precisely give the best user experience. The way it´s representing the images by default is by having all the product variants images showed to the customer all the time even if he hasn´t actually picket that variant (i.e. a specific colour for the product). It also displays all the product images in a vertical way which makes navigation for the user quite frustrating if you have more than a couple of pictures per product variant.
I´ve found online a tutorial ( http://littlesnippets.ca/blogs/tutorials/15665261-grouping-images-with-variants )that addresses the part of my issue to hide the pictures of the variants that are not selected by the customer, and show them once the user click on it.(you can see an example of what I want here http://group-variant-images.myshopify.com/collections/frontpage/products/anson-chair ). This is more or less how it looks my site now (https://themes.shopify.com/themes/brooklyn/styles/brooklyn/preview).
The problem is that that tutorial is being applied to a website that is not using the exact theme/functionality that Ii do, although it´s similar.
I´ve failed to apply those changes to my theme, can anybody give me a hand?
This is my product.liquid piece of code at the moment:
<!-- /templates/product.liquid -->
<div itemscope itemtype="http://schema.org/Product">
<meta itemprop="url" content="{{ shop.url }}{{ product.url }}">
<meta itemprop="image" content="{{ product.featured_image.src | img_url: 'grande' }}">
{% assign current_variant = product.selected_or_first_available_variant %}
<div class="grid product-single">
<div class="grid__item large--seven-twelfths medium--seven-twelfths text-center">
<div class="product-single__photos">
{% assign featured_image = current_variant.featured_image | default: product.featured_image %}
{% comment %}
Display current variant image, or default first
{% endcomment %}
<div class="product-single__photo-wrapper">
<img class="product-single__photo" id="ProductPhotoImg" src="{{ featured_image | img_url: 'grande' }}" {% if settings.product_zoom_enable %}data-mfp-src="{{ featured_image | img_url: '1024x1024' }}"{% endif %} alt="{{ featured_image.alt | escape }}" data-image-id="{{ featured_image.id }}">
</div>
{% comment %}
Display rest of product images, not repeating the featured one
{% endcomment %}
{% for image in product.images %}
{% unless image contains featured_image %}
<div class="product-single__photo-wrapper">
<img class="product-single__photo" src="{{ image.src | img_url: 'grande' }}" {% if settings.product_zoom_enable %}data-mfp-src="{{ image.src | img_url: '1024x1024' }}"{% endif %} alt="{{ image.alt | escape }}" data-image-id="{{ image.id }}">
</div>
{% endunless %}
{% endfor %}
</div>
</div>
<div class="grid__item product-single__meta--wrapper medium--five-twelfths large--five-twelfths">
<div class="product-single__meta">
{% if settings.product_vendor_enable %}
<h2 class="product-single__vendor" itemprop="brand">{{ product.vendor }}</h2>
{% endif %}
<h1 class="product-single__title" itemprop="name">{{ product.title }}</h1>
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
{% comment %}
Optionally show the 'compare at' or original price of the product.
{% endcomment %}
{% if product.compare_at_price_max > product.price %}
<span class="product-single__price--wrapper">
<span class="visually-hidden">{{ 'products.general.regular_price' | t }}</span>
<span id="ComparePrice" class="product-single__price--compare-at">
{% if current_variant.compare_at_price > current_variant.price %}
{{ current_variant.compare_at_price | money }}
{% endif %}
</span>
<span class="visually-hidden">{{ 'products.general.sale_price' | t }}</span>
</span>
{% endif %}
<span id="ProductPrice" class="product-single__price{% if product.compare_at_price > product.price %} on-sale{% endif %}" itemprop="price">
{{ current_variant.price | money }}
</span>
<hr class="hr--small">
<meta itemprop="priceCurrency" content="{{ shop.currency }}">
<link itemprop="availability" href="http://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}">
<form action="/cart/add" method="post" enctype="multipart/form-data" class="product-single__form" id="AddToCartForm">
<select name="id" id="ProductSelect" class="product-single__variants">
{% for variant in product.variants %}
{% if variant.available %}
<option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} data-sku="{{ variant.sku }}" value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled="disabled">
{{ variant.title }} - {{ 'products.product.sold_out' | t }}
</option>
{% endif %}
{% endfor %}
</select>
{% comment %}
<div class="product-single__quantity">
<label for="Quantity" class="product-single__quantity-label js-quantity-selector">{{ 'products.product.quantity' | t }}</label>
<input type="number" hidden="hidden" id="Quantity" name="quantity" value="1" min="1" class="js-quantity-selector">
</div>
{% endcomment %}
<div class="product-single__add-to-cart">
<button type="submit" name="add" id="AddToCart" class="btn">
<span id="AddToCartText">{{ 'products.product.add_to_cart' | t }}</span>
</button>
</div>
</form>
</div>
<div class="product-single__description rte" itemprop="description">
{{ product.description }}
</div>
{% if settings.social_sharing_products %}
{% include 'social-sharing' %}
{% endif %}
</div>
</div>
</div>
{% if collection %}
<hr class="hr--clear">
<div class="text-center">
← {{ 'products.general.collection_return' | t: collection: collection.title }}
</div>
{% endif %}
</div>
{% comment %}
*IMPORTANT:*
This theme uses a customized version of `option_selection.js` to support using radio inputs for color and size variants. The custom version is in `variant_selection.js`.
If you wish to enable the default dropdowns for size and color
you can change the liquid asset tag below from:
{{ 'variant_selection.js' | asset_url | script_tag }}
to
{{ 'option_selection.js' | shopify_asset_url | script_tag }}
If you use the default `option_selection.js` the labels for the dropdowns will appear outside the dropdown.
You will also need to change `.radio-wrapper` to `.selector-wrapper` below.
{% endcomment %}
{{ 'variant_selection.js' | asset_url | script_tag }}
<script>
var selectCallback = function(variant, selector) {
timber.productPage({
money_format: "{{ shop.money_format }}",
variant: variant,
selector: selector,
translations: {
addToCart : {{ 'products.product.add_to_cart' | t | json }},
soldOut : {{ 'products.product.sold_out' | t | json }},
unavailable : {{ 'products.product.unavailable' | t | json }}
}
});
};
jQuery(function($) {
new Shopify.OptionSelectors('ProductSelect', {
product: {{ product | json }},
onVariantSelected: selectCallback,
enableHistoryState: true
});
// Add label if only one product option and it isn't 'Title'. Could be 'Size'.
{% if product.options.size == 1 and product.options.first != 'Title' %}
$('.radio-wrapper:eq(0)').prepend('<label for="ProductSelect-option-0" class="single-option-radio__label">{{ product.options.first | escape }} </label>');
{% endif %}
// Hide drop-down selectors if we only have 1 variant and its title contains 'Default'.
{% if product.variants.size == 1 and product.variants.first.title contains 'Default' %}
$('.selector-wrapper').hide();
{% endif %}
});
</script>
Shopify's admin interface only allows for one product image per variant. For this reason, to do what you are trying to do isn't as easy as you are hoping. Through the Shopify API you can add metafields to products and product variants and in these metafields you can store whatever information you want -- including links to additional images. Here is a link to the documentation for the metafields on variants: https://docs.shopify.com/api/reference/product_variant
Since the admin interface doesn't really give you the ability to modify the metafields directly, you have a couple of choices:
Spend the time and energy (or money) to hook up your own management tool to the API and modify it yourself.
Purchase an app from the Shopify app store that already does this for you. Here is a link to some of these apps that should guide you in the right direction: https://apps.shopify.com/search/query?utf8=%E2%9C%93&q=variant
Either way, you'll need to come up with some sort of property name convention so you know you're dealing with images because the metafields accept whatever you feel like dropping into them.
Once you are able to define the images for your product variants, then you'll need to update the logic in your liquid/javascript to accomplish the desired functionality. You can do this a few different ways, and different people will have different opinions based on SEO but my suggestion for the path of least resistance is to do something like this:
{% for v in product.variants %}
<div id="variant_{{ v.id }}">
{% for m in v.metafields %}
{% if m.key contains "WHATEVER_CONVENTION_YOU_USED_TO_DENOTE_IMAGES" %}
{% comment %}
OUTPUT THE IMAGE TAG - PROBABLY WRAPPED IN AN ANCHOR
{% endcomment %}
{% endif %}
{% endfor %}
</div>
{% endfor %}
You'll want to incorporate some logic to show and hide the div based on the variant. Note the <div id="variant_{{ v.id }}">
The reason for this approach rather than using the api to populate js objects is that your links are already in the DOM and you can create javascript handlers when the page loads. If you wait to populate your images and links until the user selects the variant, then you'll have to deal with the event handling of dynamically created nodes.
Hope all this guides you in a good direction. If you have questions or need help feel free to reach out to me via my profile.
Additional Note: Good software developers will note the O(n^2) time complexity in the code above. Shopify doesn't execute your backend code when the page loads, rather it is executed and cached when your theme is uploaded or modified. Because of this, the poor O(n^2) time complexity won't hurt your page load performance.
As a side fun fact, this is the reason Shopify cannot create Liquid tags for things like current_time or random. Their caching mechanism which keeps sites from crashing even when being presented on Shark Tank also relies on the fact that their liquid tags, filters, and blocks don't return variable results. So, they can cache the resulting HTML and serve it directly from their caching servers...thus tags like random or current_time would only ever have an opportunity to run once.
you can try variant-image-automator paid app. this hides unnecessary images from the product page.

Dynamically add or remove table rows with jQuery or Angular?

This is the code I have. I'm using Symfony/Twig to pass the variables and translation strings in (if anyone was unsure what the {{, }}, {% trans %} etc was for).
Please see the line where I have the glyphicon glyphicon-camera - what I want is for the user to be able to click this, and a new row appears directly below containing the contents of row.getPhoto() - the icon will only appear if row.getPhoto() is not null, so therefore clicking it will always mean there is content to show.
Likewise, clicking the photo icon again will make the row disappear.
How can I do this? I'm not sure if I should use jQuery or Angular (I am using both in other places in the project, so both are easily available for me). Any comments welcome, thank you.
<table class="table">
<tr>
<th width="10%">{% trans %} header.item {% endtrans %}</th>
<th width="60%">{% trans %} header.action {% endtrans %}</th>
<th width="10%">{% trans %} header.option1 {% endtrans %}</th>
<th width="10%">{% trans %} header.option2 {% endtrans %}</th>
<th width="10%">{% trans %} header.option3 {% endtrans %}</th>
</tr>
{% for row in showRows(allItems) %}
<tr>
<td>
{{ row.getItem() }}
</td>
<td>
{{ row.getAction() }} {% if row.getPhoto() is not null %} <span class="pull-right show-hide-photo glyphicon glyphicon-camera"></span>{% endif %}
</td>
<td>
{% if row.getOption1() %}<span class="glyphicon glyphicon-ok"></span>{% endif %}
</td>
<td>
{% if row.getOption2() %}<span class="glyphicon glyphicon-ok"></span>{% endif %}
</td>
<td>
{% if row.getOption3() %}<span class="glyphicon glyphicon-ok"></span>{% endif %}
</td>
</tr>
{% endfor %}
</table>
Only jQuery I have right now is this, to make the icon appear like a link when hovered over:
// Photo button
$('.show-hide-photo').css('cursor', 'pointer');
You can always pass symphony2 variables on javascript code, so you can have a scirpt with something along the lines of:
<scirpt>
$(.glyphicon).click(function(){
$(.Some-other-class).toggle()
});
</script>
You can have the .Some-other-class div element or td element starting as hidden and with variables in it (like you did in your static html code).
You don't need the css pointer in the js use it in a css class to have it when the page load not when the user click.
And for your click you can do something like this if you photo is a link then :
first use in your twig a <img src="{{row.photo}}" alt="" style="display:none;"/> whenever you want to put the images.
then inside your js in the click photo button
$('.show-hide-photo').on('click', function(){
$(this).closest('tr').find('img').toggle();
});
$(this) is your show-hide-photo button , closest('tr') will look for the tag which contain your button then find('img') will go find the tag inside that (row) in that case you wont need to bother with ids to select right row etc..

Hide table header if there is no row

I have a table with patients in which, for each row of table I can remove the row or do other operations, so when I remove all the rows I want my table header to be hidden or removed.
<table id ="results-table" class="table table-strip">
<thead>
<tr>
<th>Emri</th>
<th>Mbiemri</th>
<th>Numri personal</th>
<th>Vendi i lindjes</th>
<th>Data e diagnozës së parë</th>
<th>Data e raportimit</th>
<th>Mjeku raportues</th>
<th>Veprimet</th>
</tr>
</thead>
{% if patient_docs and patient_docs.collection.count() > 0 %}
<tbody id="patient-list">
{% for patient_doc in patient_docs %}
<tr>
{% if patient_doc.patient is defined %}
<td>{{ patient_doc.patient.emri }}</td>
<td>{{ patient_doc.patient.mbiemri }}</td>
<td>{{ patient_doc.patient.numri_personal }}</td>
<td>{{ patient_doc.patient.vendi_lindjes }}</td>{% endif %}
<td>{% if patient_doc.diagnosis is defined %}{{ patient_doc.diagnosis.data_diagnozes_se_pare }}{% endif %}</td>
<td>{% if patient_doc.treatment is defined %}{{ data_e_raportimit }}{% endif %}</td>
<td>{% if patient_doc.treatment is defined %}{{ patient_doc.treatment.mjeku_raportues }}{% endif %}</td>
</tr>
{% endfor %}
</tbody>
{% endif %}
</table>
So how can I do that using jQuery, so that if there is no row hide the header and and show a message there is no patient registered?
You can put the line
{% if patient_docs and patient_docs.collection.count() > 0 %}
before the "thead"
OR
with jquery in a document.ready, you can check the lenght
if ($('#results-table > tbody > tr').length == 0){
$('#results-table > thead > th').css('display','none');
}
everytime u remove a row u can count the number of rows left using
var rowCount = $('#myTable tbody tr').length;
if rowcount goes to 0 then just hide the table using .hide()
in your add and remove functions you can add method like renderBody which will be hide or show your tbody part:
function addRow() {
...
renderBody();
}
function removeRow() {
...
renderBody();
}
function renderBody() {
var $tbody = $('#patient-list');
if (patient_docs && patient_docs.collection.count() > 0) {
$tbody.show();
}
else {
$tbody.hide();
}
}
Noticed you actually want to basically hide the entire table (not just the header) and show a message saying that no patients are registered.
Easy way to do this would be to create a function, check if rows exist, if they do then hide message, show table, otherwise do the opposite
var $msg = $('#msgDivId');
function showMsgOnEmptyTable(target, msg){
var $target = $(target);
if( $target.find('tr') ){
$target.show( );
$msg.hide();
} else {
$target.hide();
$msg.show();
}
}
in html
<div id="msgDivId">
No Patients Registered
</div>
<table id="targetTable"> ... table stuff goes here ... </table>
And when ever you make changes to the table call
showMsgOnEmptyTable('#targetTable');

Categories

Resources