I have built this code snippet for my shopify store to display more information in the dropdown field. With the change, the status is now also displayed next to the size selection. Available or Sold Out. Unfortunately I can't get it solved that if the stock quantity on a variant is less than 2, that the system then displays the text. Only 1 available.
<select id="product-select-{{ product.id }}" name="id" class="main_select">
{% for variant in product.variants %}
{% if variant.available %}
<option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} value="{{ variant.id }}">{{ variant.title }} <span>Verfügbar: {{ variant.inventory_quantity}}</span></option>
{% else %}
<option disabled="disabled">
{{ variant.title }} - {{'products.product.sold_out' | t }}
</option>
{% endif %}
{% endfor %}
</select>
Current
You should be able to add another if statement within the option itself, like this:
<select id="product-select-{{ product.id }}" name="id" class="main_select">
{% for variant in product.variants %}
{% if variant.available %}
<option
{% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %}
value="{{ variant.id }}"
>
{{ variant.title }} <span>Verfügbar {% if variant.inventory_quantity < 2 %}: ONLY 1 AVAILABLE{% endif %}</span>
</option>
{% else %}
<option disabled="disabled">
{{ variant.title }} - {{'products.product.sold_out' | t }}
</option>
{% endif %}
{% endfor %}
</select>
Related
EDIT:
As several of you pointed out, the "submit" type reloads the page each time, so a running count is not maintained. I fixed this by using sessionStorage to store the number. Here's the fixed code:
function addItem(){
window.sessionStorage.setItem('count',Number(window.sessionStorage.getItem('count'))+1);
/*if(currentItems>3){
currentItems=3;
}*/
console.log("Item added");
update();
}
function removeItem(){
window.sessionStorage.setItem('count',Number(window.sessionStorage.getItem('count'))-1);
/*if(currentItems<0){
currentItems=0;
}*/
console.log("Item removed");
update();
}
function update(){
console.log(Number(window.sessionStorage.getItem('count')));
}
Original Question:
I don't have much experience in JS so forgive me if this is a silly question. I created the following script to count the number of items added to a bundle of products:
var currentItems=0;
function addItem(){
++currentItems;
/*if(currentItems>3){
currentItems=3;
}*/
console.log("Item added");
update();
}
function removeItem(){
--currentItems;
/*if(currentItems<0){
currentItems=0;
}*/
console.log("Item removed");
update();
}
function update(){
console.log(currentItems);
}
The addItem and removeItem events are triggered by "onclick" tags on certain buttons. When I check the console, it correctly shows the "Item added" and "Item removed" messages, but it displays the wrong number for currentItems. When I click a button that should trigger addItems, the console displays 1 regardless of how many items I've added. Similarly, when I click a button that triggers removeItems, the console displays -1. It seems like the variable is starting from 0 each time I click. Any ideas on how to fix this?
EDIT:
Here's the full code. I'm building a custom template within the Bundle Builder Shopify App, so everything aside from the CSS styling and my script are default.
<style type="text/css">
.product-box {
display: flex;
width: 50%;
float: left;
margin-left:15%;
}
.product {
display: flex;
flex-direction: column;
}
.note-field--container {
display: flex;
flex-direction: column;
}
.bundle-content{
width:20%;
float:left;
margin-right:5%;
}
#outside-progress{
background-color:grey;
width: 30%;
}
#inside-progress{
background-color:#202945;
height:30px;
}
</style>
<script type="text/javascript">
const selectedVariants = new Map();
function setAddDisabled(form) {
const variantId = form.querySelector('[name="variant"]').value;
const sectionId = form.querySelector('[name="section"]').value;
const canAdd = window.BundleBuilder.canAddVariant(variantId, sectionId);
form.querySelector('[type="submit"]').disabled = !canAdd;
}
/* Change variant price after variant change */
Array.prototype.forEach.call(
document.querySelectorAll('.bundle-builder--add-to-bundle-form select[name="variant"]'),
function (select) {
select.addEventListener('change', function (e) {
const variantId = e.target.value;
selectedVariants.set(e.target.id, variantId);
const price = e.target.querySelector('option[value="' + variantId + '"]').dataset.price;
e.target.parentNode.querySelector('.variant-price').textContent = price;
const form = e.target.parentElement;
setAddDisabled(form);
});
}
);
function render() {
selectedVariants.forEach(function (variantId, selectId) {
const select = document.getElementById(selectId);
if (select) {
select.value = variantId;
}
});
Array.prototype.forEach.call(
document.querySelectorAll('.bundle-builder--add-to-bundle-form'),
setAddDisabled,
);
}
/* Change variant to what was selected last */
document.body.addEventListener('bundlebuilder:render', render);
render()
</script>
{% if bundle.published %}
<h1>{{ bundle.current_section.name }}</h1>
<div id="outside-progress">
<div id="inside-progress"></div>
</div>
<div class="product-box">
{% for product in bundle.current_section.products %}
<div class="product">
<h2>{{ product.title }}</h2>
<img src="{{ product.image.src }}" />
{% add_to_bundle_form bundle.current_section %}
{% if product.available_variants.size > 1 %}
<select name="variant" id="select-{{ bundle.current_section.index }}-{{ product.id }}">
{% for variant in product.available_variants %}
<option value="{{ variant.id }}" data-price={{ variant.price | money }}>
{{ variant.title }}{% if variant.available_count %} (available: {{ variant.available_count }}){% endif %}
</option>
{% endfor %}
</select>
{% else %}
<input type="hidden" name="variant" value="{{ product.available_variants[0].id }}" />
{{ product.available_variants[0].title }}{% if product.available_variants[0].available_count %} (available: {{ product.available_variants[0].available_count }}){% endif %}
{% endif %}
<span class="variant-price">{{ product.available_variants[0].price | money }}</span>
<button type="submit" style="color:#ffffff; background-color:#202945;" onclick="addItem()">Add</button>
{% end_add_to_bundle_form %}
{% for variant in product.variants_in_bundle %}
{% change_quantity_form %}
{% comment %}{{ variant.title }}{% endcomment %}
<input type="hidden" name="variant" value="{{ variant.id }}" />
<input type="hidden" name="section" value="{{ bundle.current_section.index }}" />
<button type="submit" name="remove" onClick="removeItem()">-</button>
{{ variant.count }}
<button type="submit" name="add" onclick="addItem()">+</button>
{% end_change_quantity_form %}
{% endfor %}
</div>
{% endfor %}
</div>
{% if bundle.has_next_section %}
{% section_switch_form %}
<input type="hidden" name="section" value="{{ bundle.current_section.index | plus: 1 }}" />
<button type="submit" style="color:#ffffff; background-color:#202945;">Next</button>
{% end_section_switch_form %}
{% endif %}
{% if bundle.has_prev_section %}
{% section_switch_form %}
<input type="hidden" name="section" value="{{ bundle.current_section.index | plus: -1 }}" />
<button type="submit" style="color:#ffffff; background-color:#202945;">Previous</button>
{% end_section_switch_form %}
{% endif %}
{% if bundle.errors.size > 0 %}
<ul>
{% for error in bundle.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<div class="bundle-content">
{% if bundle.content.items.size == 0 %}
<span>Your bundle is empty</span>
{% else %}
<table>
<tr>
<th>Product</th>
<th>Variant</th>
<th>Price</th>
<th></th>
</tr>
{% for item in bundle.content.items %}
<tr>
<td>{{ item.variant.product.title }}</td>
<td>{{ item.variant.title }}</td>
<td>{{ item.variant.price | money }}</td>
<td>
{% unless item.is_required %}
{% remove_from_bundle_form item %}
<button type="submit" style="color:#ffffff; background-color:#202945;" name="remove" onclick="removeItem()">Remove</button>
{% end_remove_from_bundle_form %}
{% endunless %}
</td>
</tr>
{% endfor %}
{% if bundle.content.price < bundle.content.compare_at_price %}
<tr>
<th colspan="2">Discount</th>
<th>
<span>{{ bundle.content.price | minus: bundle.content.compare_at_price | money }}</span>
</th>
<th></th>
</tr>
{% endif %}
<tr>
<th colspan="2">Total</th>
<th>
<span>{{ bundle.content.price | money }}</span>
</th>
<th></th>
</tr>
</table>
{% if settings.note_enabled %}
<div class="note-field--container">
<label>{{ settings.note_label }}{% if settings.note_required %} (required){% endif %}</label>
{% note_field %}{{ settings.note_text }}{% end_note_field %}
</div>
{% if settings.note_prompt_visible %}
<div class="note-field--error-message">
<p>Note required before adding to cart.</p>
</div>
{% endif %}
{% endif %}
{% add_to_cart_form %}
{% if bundle.subscription_type == 'optional' and bundle.subscription_frequencies.size > 0 %}
<label>
<input type="radio" name="subscription-enabled" value="0" />
One-time purchase
</label>
<label>
<input type="radio" name="subscription-enabled" value="1" />
Subscribe
</label>
{% endif %}
{% if bundle.subscription_type == 'required' or bundle.subscription_enabled %}
{% for frequency in bundle.subscription_frequencies %}
<ul>
<li>
<label>
<input type="radio" name="subscription-frequency" value="{{ frequency.id }}" />
{{ frequency.frequency }} {{ frequency.unit }}
</label>
</li>
</ul>
{% endfor %}
Email: <input type="email" required name="subscription-email" value="{{ settings.subscription_email }}" />
{% endif %}
<button type="submit"{% unless bundle.can_add_to_cart %} disabled="disabled"{% endunless %} style="color:#ffffff; background-color:#202945;">
{% if bundle.adding_to_cart %}
Processing...
{% else %}
Add bundle to cart
{% endif %}
</button>
{% end_add_to_cart_form %}
{% endif %}
</div>
{% else %}
<p>Sorry, this bundle is currently unavailable.</p>
{% endif %}
<script type="text/javascript">
/* Custom Progress Bar */
const progress = document.getElementById("inside-progress");
var currentItems=0;
function addItem(){
++currentItems;
/*if(currentItems>3){
currentItems=3;
}*/
console.log("Item added");
update();
}
function removeItem(){
--currentItems;
/*if(currentItems<0){
currentItems=0;
}*/
console.log("Item removed");
update();
}
function update(){
console.log(currentItems);
}
</script>
function addItem(){
window.sessionStorage.setItem('count',Number(window.sessionStorage.getItem('count'))+1);
/*if(currentItems>3){
currentItems=3;
}*/
console.log("Item added");
update();
}
function removeItem(){
window.sessionStorage.setItem('count',Number(window.sessionStorage.getItem('count'))-1);
/*if(currentItems<0){
currentItems=0;
}*/
console.log("Item removed");
update();
}
function update(){
console.log(Number(window.sessionStorage.getItem('count')));
}
I'm trying to detect changes in a Form to change the following parameters depending on the previous one.
Concretely when I change id_send_to(Client) it shows a list of companies from the client.
I think that this should be done with Ajax Call.
This is the code and when I check in the inspector I cannot see the console.log
{% extends "helpdesk/base.html" %}
{% load i18n bootstrap %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#id_send_to").change(function () {
console.log( $(this).val() );
});
});
</script>
Any Idea ?
<form method='post' action='./' enctype='multipart/form-data'>
<fieldset>
{{ form|bootstrap }}
{% comment %}
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
<dt><label for='id_{{ field.name }}'>{% trans field.label %}</label>{% if not field.field.required %} <span class='form_optional'>{% trans "(Optional)" %}</span>{% endif %}</dt>
<dd>{{ field }}</dd>
{% if field.errors %}<dd class='error'>{{ field.errors }}</dd>{% endif %}
{% if field.help_text %}<dd class='form_help_text'>{% trans field.help_text %}</dd>{% endif %}
{% endif %}
{% endfor %}
{% endcomment %}
<div class='buttons form-group'>
<input type='submit' class="btn btn-primary" value='{% trans "Submit
Ticket" %}' />
</div>
</fieldset>
{% csrf_token %}</form>
I can change the "checkbox" to "radio" but it still allows more than one to be selected. What can I do to only allow a single selection? Here's the site: https://winkdiapers.com/product/os-pocket-diaper
<div class="clearfix">
{% for index, extra in product.extras %}
<div class="extra">
<label class="title" for="{{ 'extra-'~index }}">
{% if extra.enabled %}
<input type="checkbox" id="{{ 'extra-'~index }}" {{ checkbox_state(postedExtras[extra.id], extra.id) }} name="extras[{{ extra.id }}]" data-ajax-handler="shop:product" data-ajax-update="#product-page=shop-product">
{% else %}
<input type="checkbox" disabled="disabled">
{% endif %}
{{ extra.name }} ({{ extra.price|currency }})</label>
</div>
{% endfor %}
</div>
{% endif %}
I use select2 and have this layout
Original code(using Twig):
<select id="workerId" name="workerId" class="form-control select2 text">
<option value="0">-- Не указано --</option>
{% for worker_one in workerList %}
<option data-position="{{ worker_one.position_list }}" value="{{ worker_one.id }}"
{% if worker_one.status != 3 %}
{% if sampleActs.worker_id %}
{% if worker_one.id == sampleActs.worker_id %}
selected
{% endif %}
{% else %}
{% if worker_one.id == areaCore.worker_id %}
selected
{% endif %}
{% endif %}
{% else %}
disabled
{% endif %}
>{{ worker_one.name }}
</option>
{% endfor %}
</select>
$('.select2').select2();
<select name="name">
<option disabled>Vasia</option>
<option>Petia</option>
<option>Stas</option>
</select>
When $("[name='name'").select2() init in dropdown list I still can select option options with disabled attribute. How I can fix this?
Thanks.
Seems to work fine here:
$("[name='name'").select2()
select {
width: 100px;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.min.js"></script>
<select name="name">
<option disabled>Vasia</option>
<option>Petia</option>
<option>Stas</option>
</select>
So your issue is not related to your HTML
Set an ID for all the option and then, on page load, maybe in the onload of the body tag, you can set this:
<select name="name">
<option id="vasia">Vasia</option>
<option id="petia">Petia</option>
<option id="stas">Stas</option>
</select>
Then
<body onload="document.getElementById('vasia').disabled = true;">
Hope it helps
Working with one variant in Shopify on the product page dropdown, and would like it grayed out when not available (sold out).
Here's the code I have so far: (for the entire page)
{% include 'buyx-product' with product %}
{% include 'buyx-price-min' with product %}
{% assign option_to_match = settings.option_to_match %}
{% assign option_index = 0 %}
{% for option in product.options %}
{% if option == option_to_match %}
{% assign option_index = forloop.index0 %}
{% endif %}
{% endfor %}
{% if buyx_product_available %}
<form action="/cart/add" method="post" class="clearfix product_form" data-money-format="{{ shop.money_format }}" data-option-index="{{ option_index }}" id="product-form-{{ product.id }}">
{% if product.options.size > 1 and (product.options[1] != "BuyXDiscount") %}
<div class="select">
<select id="product-select-{{ product.id }}" name='id'>
{% for variant in product.variants %}
{% unless variant.title contains '% Off' %}
<option value="{{ variant.id }}">{{ variant.title }}</option>
{% endunless %}
{% endfor %}
</select>
</div>
{% elsif buyx_select_one_option and (product.variants.size > 1 or product.options[0] != "Title" or product.options.first != 'BuyXDiscount') %}
<div class="select">
<label>{{ product.options[0] }}:</label>
<select id="product-select-{{ product.id }}" name='id'>
{% for variant in product.variants %}
{% unless variant.title contains '% Off' %}
<option value="{{ variant.id }}">{{ variant.title }}</option>
{% endunless %}
{% endfor %}
</select>
</div>
{% else %}
<input type="hidden" name="id" value="{{ product.variants.first.id }}" />
{% endif %}
{% include 'swatch' with 'Color' %}
{% if settings.display_product_quantity %}
<div class="left">
<label for="quantity">Quantity:</label>
<input type="number" min="1" size="2" class="quantity" name="quantity" id="quantity" value="1" />
</div>
{% endif %}
<div class="purchase clearfix {% if settings.display_product_quantity %}inline_purchase{% endif %}">
{% if settings.cart_return == 'back' %}
<input type="hidden" name="return_to" value="back" />
{% endif %}
<input type="submit" name="add" value="Add to Cart" class="action_button add_to_cart" />
</div>
<script data-product="{{ product | json | escape }}" id="out-of-stock" src="http://setup.shopapps.io/out-of-stock/script/nisolo.js"></script>
</form>
{% if buyx_product_variants_size > 1 %}
<script type="text/javascript">
// <![CDATA[
$(function() {
function buyx_product_json(product) {
var variants = []
//does it have BuyXDiscount option?
var option_position = -1
for (var oi = 0, olen = product.options.length; oi < olen; oi++) {
if (product.options[oi] == "BuyXDiscount") {
option_position = oi+1
break
}
}
if (option_position == -1) {
return product
}
if (product.options.length > 1) {
product.options.splice(option_position-1, 1)
} else {
product.options[0] = "Title"
}
option_position = "option" + option_position
product.available = false
for (var vi = 0, vlen = product.variants.length; vi < vlen; vi++) {
if (product.variants[vi][option_position] == "Default") {
product.variants[vi][option_position] = ""
variants.push(product.variants[vi])
product.available = product.available || product.variants[vi].available
}
}
product.variants = variants
return product
}
<strong>$product = $('#product-' + {{ product.id }});
// if($('.single-option-selector', $product).length == 0) {
new Shopify.OptionSelectors("product-select-{{ product.id }}", { product: buyx_product_json({{ product | json }}), onVariantSelected: selectCallback });
{% if product.available %}
{% assign found_one_in_stock = true %}
{% for variant in product.variants %}
{% if variant.available == false %}
jQuery('.single-option-selector option:eq({{ forloop.index0 }})').attr('disabled', 'disabled');
{% endif %}
{% endfor %}
{% endif %}</strong>
//}
});
// ]]>
</script>
{% endif %}
{% endif %}
Unfortunately, what's happening is that instead of the product with 0 inventory being grayed out, the product prior to the product with 0 inventory is being grayed out. For example, in the screenshot below, size 9.5 is the size with zero inventory, but size 9 is showing as grayed out.
When I say manually, I mean something like this...
<select>
{% for variant in product.variants %}
{% if variant.available %}
<option value="{{variant.id}}">{{variant.title}}</option>
{% else %}
<option value="{{variant.id}}" disabled>{{variant.title}}</option>
{% endif %}
{% endfor %}
</select>
Perhaps instead of using the for loop index, you could select the option with the corresponding variant title or id? Something like this:
{% unless variant.available %}
jQuery('.single-option-selector option[value="{{ variant.title }}"]').attr('disabled', 'disabled');
{% endunless %}
This answer might also be useful:
jQuery('.single-option-selector option:contains({{ variant.title | json }})')...
although option:contains may not work in your situation where you have sizes like 9 and 9.5.
EDIT:
From the link you provided, it looks like Size is option2, so try this:
jQuery('.single-option-selector option[value="{{ variant.option2 }}"]').attr('disabled', 'disabled');