Allow to only purchase only one product # Shopify - javascript

We're looking for a solution to hide the add to cart button if a product is already in cart. So that the user can not order more than 1 of each product.
A Mentor from Codementor wrote a function which hides the Add to Cart button if a selected variant is in the cart:
var updateCartButtons = function () {
if (typeof (window.cartItems) === "undefined") {
window.cartItems = [];
}
var cartItemVariantID, selectedVariantID, selectedVariantName;
selectedVariantName = $('.swatch :radio:checked').val();
selectedVariantID = $('#product-select option').filter(function () {
return $(this).text() === selectedVariantName;
}).val();
$('.buymarginsecond').removeClass('addedToCart');
for (var i = 0, l = cartItems.length; i < l; i++) {
cartItemVariantID = cartItems[i].variant_id;
if (cartItemVariantID == selectedVariantID) {
$('.buymarginsecond').addClass('addedToCart');
break;
}
}
};
We'd like to change this function to the effect that the
button disappears as soon as the main product is in the cart.
So you can only order one of each product and not different variants of the product.

You can use this code in your product.liquid file where add to cart is button is show. It will loop through the titles in the cart and if found set the variable to yes. Then check if variable is no, not in cart and show add to cart.
{% assign in_cart = 'no' %}
{% for item in cart.items %}
{% if item.product.title == product.title %}
{% assign in_cart = 'yes' %}
{% endif %}
{% endfor %}
{% if in_cart == 'no' %}
// SHow Add to Cart
{% endif %}

Related

Select a variant on product page load Shopify

I wrote a piece of code that works in a way where once I select a variant on the product page, only media with the same alt text as the variant name, will display while the rest of the media is hidden. My only problem is when the product page loads it displays all the media, even if I go directly to the URL with variant ID in it. So a variant has to be selected, for my page to show only matching alt-text media. I'm wondering if there is a way to either change this or make it so that on the website load the first variant gets selected.
Here is the HTML & Liquid code I'm using:
{% unless product.has_only_default_variant %}
<variant-selector data-url="{{ product.url }}" data-section="{{ section.id }}">
{% for option in product.options_with_values %}
<label for="option-{{ section.id }}-{{ forloop.index0 }}">{{ option.name }}</label>
<select name="options[{{ option.name | escape }}]" id="option-{{ section.id }}-{{ forloop.index0 }}">
{% for value in option.values %}
<option value="{{ value | escape }}" {% if option.selected_value == value %} selected="selected" {% endif %}>{{ value }}</option>
{% endfor %}
</select>
<script type="application/json">
{{ product.variants | json }}
</script>
{% endfor %}
</variant-selector>
{% endunless %}
And here is the javascript code:
class VariantSelector extends HTMLElement {
constructor() {
super();
this.addEventListener("change", this.onVariantChange);
}
onVariantChange() {
this.getSelectedOptions();
this.getSelectedVariant();
this.updateMedia(this.currentVariant);
if (this.currentVariant) {
this.updateURL();
this.updateFormID();
this.updatePrice();
this.updateMedia();
}
}
getSelectedOptions() {
this.options = Array.from(this.querySelectorAll('select'), (select) => select.value);
console.log(this.options);
}
getVariantJSON() {
this.variantData = this.variantData || JSON.parse(this.querySelector('[type="application/json"]').textContent);
return this.variantData;
}
getSelectedVariant() {
this.currentVariant = this.getVariantJSON().find(variant => {
const findings = !variant.options.map((option, index) => {
return this.options[index] === option;
}).includes(false);
if (findings) return variant;
});
console.log(this.currentVariant);
}
updateURL() {
if (!this.currentVariant) return;
window.history.replaceState({}, '', `${this.dataset.url}?variant=${this.currentVariant.id}`);
}
updateFormID() {
const form_input = document.querySelector("#product-form").querySelector('input[name="id"]');
form_input.value = this.currentVariant.id;
}
updatePrice() {
fetch(`${this.dataset.url}?variant=${this.currentVariant.id}&section_id=${this.dataset.section}`)
.then((response) => response.text())
.then((responseText) => {
const id = `price-${this.dataset.section}`;
const html = new DOMParser().parseFromString(responseText, 'text/html');
const oldPrice = document.getElementById(id);
const newPrice = html.getElementById(id);
if (oldPrice && newPrice) oldPrice.innerHTML = newPrice.innerHTML;
});
}
updateMedia() {
if(this.currentVariant.featured_image !=null && this.currentVariant.featured_image.alt != null) {
$('[thumbnail-color]').hide();
var selected_color = this.currentVariant.featured_image.alt;
var thumbnail_selector = '[thumbnail-color="' + selected_color + '"]';
$(thumbnail_selector).show();
} else {
$('[thumbnail-color]').hide();
}
}
}
customElements.define("variant-selector", VariantSelector);

how to get values from views.py and use it in Javascript tag

This is my views.py
def list_note(request):
note_info = Note.objects.filter(id_teacher__exact=request.user.id).select_related()
actual_date = date.today()
for notes in note_info:
note_date = notes.remind.date()
tmp = actual_date + timedelta(days=3)
note_expired_list = []
if tmp == note_date:
print()
else:
note_expired_list.append(notes)
print(note_expired_list)
note_data = {
"note_details": note_info,
"note_expired_list_details": note_expired_list,
}
return render_to_response('list_note.html', note_data, context_instance=RequestContext(request))
I want use value note_expired_list_details in <scrpit> tag to display this in alert. How do this?
I try use {{ note_expired_list_details}} but in <script> tag not work.
This is a part of my templates (I try finding HTML element by Id in JS)
{% extends "base.html" %}
{% load staticfiles %}
{% block content %}
<div >
{% for details in note_expired_list_details %}
<p>{{ details }}</p>
{% endfor %}
<script>
var x = document.getElementsByTagName("p");
alert("Test\n" + x[1].childNodes.nodeValue + "\n");
</script>
</div>
{% endblock %}
Why not store value of {{ note_expired_list_details }} in a JS variable and then use it however you want?
<script>
var expiredList = '{{ note_expired_list_details }}';
alert(expiredList);
</script>

JavaScript within Python in HTML

I want to call on a JavaScript function within my Python code. How should I do that? Here, I want to parse my url to get the query and check whether it is the same as name of a greeting in my datastore.
{% for greeting in greetings %}
{% if greeting.person %}
<tr><th>{{ greeting.person.email }}
{% if %}getQueryVariable() {%== greeting.name %}
<th>{{greeting.name}}</th>
<th>{{greeting.place}}</th>
<th>{{greeting.time}}</th>
<th>{{greeting.rec}}</th>
<th>{{greeting.other}}</th>
{% endif %}
{% endif %}
{% endfor %}</tr>
<script>
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
</script>

How do I correctly load a specific jQuery script

I've been given a script by my e-commerce provider that will allow me to dynamically change the stock levels based on the product option selected by the user from a simple select element.
While the code seems strait forward, it will not run properly. As I am fairly new to jQuery, I'm assuming this is due to me not properly initializing the script within my html. The code itself is a default code that my e-commerce provider hands out, but does not support it in any way.
Here is the script
<script>
// <![CDATA[
var selectCallback = function(variant, selector) {
if (variant) {
if (variant.available) {
// Selected a valid variant that is available.
$('#add-to-cart').removeClass('disabled').removeAttr('disabled').val('Add to Cart').fadeTo(200,1);
} else {
// Variant is sold out.
$('#add-to-cart').val('Sold Out').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
}
// Whether the variant is in stock or not, we can update the price and compare at price.
if ( variant.compare_at_price > variant.price ) {
$('#product_price').html('<span class="product-price on-sale">'+ Shopify.formatMoney(variant.price, "") +'</span>'+' <s class="product-compare-price">'+Shopify.formatMoney(variant.compare_at_price, "")+ '</s>');
} else {
$('#product_price').html('<span class="product-price">'+ Shopify.formatMoney(variant.price, "") + '</span>' );
}
} else {
// variant doesn't exist.
$('#add-to-cart').val('Unavailable').addClass('disabled').attr('disabled', 'disabled').fadeTo(200,0.5);
}
}
// initialize multi selector for product
jQuery(function($) {
new Shopify.OptionSelectors("product-select", { product: , onVariantSelected: selectCallback });
});
// ]]>
</script>
Any ideas on why this might not be working? You can see this script live on my site:
http://www.yandasmusic.com/products/fender-american-standard-stratocaster?variant=1178632565
EDIT:
Upon further inspection, I have found a second piece of code that also calls up the product option selection box. I can tell that this code also serves the function of changing the currently shown product image based on the current option selected:
<script>
var selectCallback = function(variant, selector) {
if (variant && variant.available) {
jQuery('#add-to-cart').removeAttr('disabled').removeClass('disabled'); // remove unavailable class from add-to-cart button, and re-enable button
if(variant.price < variant.compare_at_price){
jQuery('#product_price .price').html('<span class="money">' + Shopify.formatMoney(variant.price, "{{ shop.money_format }}") + '</span><span class="money compare-at-price">' + Shopify.formatMoney(variant.compare_at_price, "{{ shop.money_format }}") + '</span>');
} else {
jQuery('#product_price .price').html('<span class="money">' + Shopify.formatMoney(variant.price, "{{ shop.money_format }}") + '</span>');
}
} else {
jQuery('#add-to-cart').addClass('disabled').attr('disabled', 'disabled'); // set add-to-cart button to unavailable class and disable button
var message = variant ? "Sold Out" : "Unavailable";
jQuery('#product_price .price').text(message);
}
// if (variant && variant.featured_image) {
// var originalImage = $(".zoomWrapper img");
// var newImage = variant.featured_image;
// var element = originalImage[0];
// Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
// $(element).parents('a').attr('href', newImageSizedSrc);
// $(element).attr('src', newImageSizedSrc);
// });
// };
if (variant && variant.featured_image) {
var originalImage = $("#elevatezoom_big");
var newImage = variant.featured_image;
var element = originalImage[0];
Shopify.Image.switchImage(newImage, element, function (newImageSizedSrc, newImage, element) {
$(element).attr('src', newImageSizedSrc);
$("#elevatezoom_gallery a").each(function(){
if ( $(this).attr('data-zoom-image') == newImageSizedSrc ) {
$(this).trigger('click')
};
});
});
};
};
jQuery(document).ready(function($){
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback, enableHistoryState: true });
// Add label if only one product option and it isn't 'Title'.
{% if product.options.size == 1 and product.options.first != 'Title' %}
$('.selector-wrapper:eq(0)').prepend('<label>{{ product.options.first }}</label>');
{% endif %}
// Auto-select first available variant on page load.
{% assign found_one_in_stock = false %}
{% for variant in product.variants %}
{% if variant.available and found_one_in_stock == false %}
{% assign found_one_in_stock = true %}
{% for option in product.options %}
$('.single-option-selector:eq({{ forloop.index0 }})').val({{ variant.options[forloop.index0] | json }}).trigger('change');
{% endfor %}
{% endif %}
{% endfor %}
});
</script>
If I run both scripts, the page shows two select boxes for the product options. Is it possible to combine them?
You have a JavaScript error on your page because of this line of code:
new Shopify.OptionSelectors("product-select", { product: , onVariantSelected: selectCallback });
According to this reference document: https://docs.shopify.com/manual/configuration/store-customization/advanced-navigation/linked-product-options, that line of code should actually look like this:
new Shopify.OptionSelectors("product-select", { product: {{ product | json }}, onVariantSelected: selectCallback });

Javascript not reading the keys and values of a dictionary in django template

I have a dictionary like:
dest = {2: [u'canada', u'A', 'Ottawa'], 5: [u'Malaysia', u'A', 'KualaLumpur'],...}
Then I tried to retrieve the keys and values from dest in django template using javascript:
function categorizeReports()
{
var a = [];
var b = [];
{% for i,v in dest %}
id = '{{i}}';
console.log('id', id)
values = '{{v}}';
console.log('values',values)
{% for name, type, cat in values %}
if(type=='A' && cat=='Ottawa')
{
a.push(id,name,type,cat)
}
if(type=='A' && cat=='KualaLumpur')
{
b.push(id,name,type,cat)
}
{% endfor %}
{% endfor %}
console.log(a)
console.log(b)
}
But both the Arrays are shown as 'an empty string' as well as id and values are too shown as 'an empty string', Please help!
Missing .items
Change
{% for i,v in dest %}
to
{% for i,v in dest.items %}

Categories