How do I correctly load a specific jQuery script - javascript

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 });

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);

Want to stop a function when a button is clicked in jQuery

I have written some code for my Shopify store with jQuery. The work is that when a customer will come to my shop he will see a product added to the cart already.
The code works perfectly but the problem is when he clicks the remove button to remove that product the product is not being removed. It's actually removing but it's added again to the cart.
Is there any solution for this? I have an idea that if someone clicks the remove button then the function will not run again. Please tell me what the code should be?
Shopify = Shopify || {};
Shopify.cart = {{ cart | json }};
if (Shopify.cart !=='undefined' && Shopify.cart.items.length === 0) {
jQuery.post('/cart/add.js', {
quantity: 1,
id: 36507787624610,
}).always(function(data){
window.location.reload();
})
}
I don't know what theme you are using but this what you can do with your theme. I used debut theme.
Add following data attribute in your remove button html
item-id="{{ item.id }}"
After adding the above line, in debut theme it will look like this.
<a href="/cart/change?line={{ forloop.index }}&quantity=0" item-id="{{ item.id }}" class="text-link text-link--accent" aria-label="{{ 'cart.label.remove' | t: product: item.title }}" data-cart-remove>{{ 'cart.general.remove' | t }}</a>
Add the JS code in your theme.jS file. (Change the Variant ID according to your product)
//Adding product in cart
$.getJSON('/cart.js',function( data ) {
$( data.items ).each(function( index, item ) {
//Replace the ID with your variantID
if(item.id == 30329455837287) {
localStorage.setItem("item_removed", "1");
}
});
});
$('a.text-link.text-link--accent').click(function(){
var variant_id = $(this).attr('item-id');
console.log(variant_id);
if(variant_id == 30329455837287){
localStorage.setItem("item_removed", "1");
}
});
setTimeout(function(){
if( localStorage.getItem("item_removed") == "0" || localStorage.getItem("item_removed") == null ) {
$.post('/cart/add.js', {
quantity: 1,
//Replace the ID with your variantID
id: 30329455837287
});
}
}, 500);
});

Javascript - Cannot read property 'style' of null - Problem when using onclick to post text to a table

When I click on a list item 'Add' button, I'm using button.onclick to send that item's text to fill out a table on the same html page. However, I keep getting a "Cannot read property 'style' of null" in the console whenever I click an item. This was working fine until recently. Something changed...somewhere, but I can't figure out why it's returning this error suddenly.
Here's the Javascript
function showPage(page) {
document.querySelectorAll('div').forEach(div => {
div.style.display = 'none';
})
document.querySelector(`#${page}`).style.display = 'block';
}
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('button').forEach(button => {
button.onclick = function() {
showPage(this.dataset.page);
}
});
});
function myFunction(txt) {
var myTxt = txt;
console.log(myTxt)
if (txt.includes('QB')) {
document.getElementById("id_QB").value = myTxt;
}
else if (txt.includes('RB')) {
document.getElementById("id_RB1").value = myTxt;
}
else if (txt.includes('WR')) {
document.getElementById("id_WR").value = myTxt;
}
else if (txt.includes('TE')) {
document.getElementById("id_TE").value = myTxt;
}
else if (txt.includes('K')) {
document.getElementById("id_K").value = myTxt;
}
}
</script>
Here's the html page which is displaying a django template (I've deleted the on-page script tags containing the Javascript above).
{% load static %}
{% block body %}
<form method="POST">
{% csrf_token %}
<table id="playerName">
{{ form.as_table }}
</table>
<input type="submit" value="Submit" >
</form>
<br>
{% for player_data in player_data %}
<li><p>Player ID: {{ player_data.player_id }}: {{ player_data.player_name }}, {{ player_data.team }}, {{ player_data.position }}</p></li> <button onclick="myFunction('{{ player_data.player_name }} {{ player_data.position }}')">Add</button>
{% endfor %}
{% endblock %} ```

Allow to only purchase only one product # Shopify

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

How do you put "if" statements in Twig templates?

So I'm using .get like this:
$.get(base_url+'assets/js/templates/gallery_comment.html', function(template, textStatus, jqXhr)
{
container.append(Mustache.render($(template).filter('#gallery_comment').html(), data));
});
To pull in the following Mustache template:
<script id="gallery_comment" type="text/html">
{{#has_gallery_comment}}
{{#gallery_comment}}
{{is_active}},
{{is_flagged}},
{{comment}},
{{/gallery_comment}}
{{/has_gallery_comment}}
{{^has_gallery_comment}}
<center><strong>Empty</strong></center>
{{/has_gallery_comment}}
</script>
You can see the first if in the template checks to see if there are any gallery_comments, which I set manually in JavaScript before making the GET for the template:
var data = new Array();
data[gallery_comments] = payload;
data['has_gallery_comments'] = (data.length > 0);
QUESTION:
How do I replace the {{is_flagged}} statement in the template with something like:
if(is_flagged == 1)
{
echo'is_flagged: YES';
}
else
{
echo'is_flagged: NO';
}
WHAT I HAVE TRIED ALREADY:
Putting this in the template does not work:
{% if is_flagged == 1 %}
is flagged: YES
{% else %}
is flagged: NO
{% endif %}

Categories