Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Booking Form allowing units, and updating qty with number of units * days
{% comment %}
Instructions:
1. Add a hidden quantity field for BTA products in the booking-form.liquid snippet:
<input type="hidden" id="quantity" name="quantity" value="1" />
2. Make sure the normal quantity input is not rendered for BTA products (e.g. in sections/product-template.liquid).
For example, this is how it should look on the Debut theme:
{% if section.settings.show_quantity_selector %}
{% unless product.metafields.bookthatapp.config %}
<div class="product-form__item product-form__item--quantity">
<label for="Quantity">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="Quantity" name="quantity" value="1" min="1" class="product-form__input" pattern="[0-9]*">
</div>
{% endunless %}
{% endif %}
3. Add the input for units:
<input type="number" id="units" name="properties[Units]" value="1" min="1" pattern="[0-9]*" />
Note: this is just a regular line item property with the name 'Units'.
It should go just after <div class="booking-form">
You will probably need to copy the markup/CSS classes so that it looks nice. Here is how it should look for Debut:
<input type="hidden" id="quantity" name="quantity" value="1" />
<div class="product-form__item product-form__item--quantity">
<label for="Quantity">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="units" name="properties[Units]" value="1" min="1" class="product-form__input" pattern="[0-9]*" />
</div>
4. Copy the ProductRental Javascript from below to the booking form snippet.
5. Update cart.liquid as per the cart template section below
6. If the theme shows a count of items in the cart header update it per the cart count section below
{% endcomment %}
{% if product.metafields.bookthatapp.config %}
<div class="booking-form">
<div>
{% capture attribute %}booking-start{% endcapture %}
<label for="{{ attribute }}-{{ product.handle }}">From:</label>
<input id="{{ attribute }}-{{ product.handle }}" type="text" name="properties[From]" size="12" class="datepicker bta required bta-load-enable bta-dp-start" disabled="disabled"
data-handle="{{ product.handle }}" data-variant="{{ product.selected_or_first_available_variant.id }}"
data-bta-product-config="{{ product.metafields.bookthatapp.config }}"
data-bta-variant-config="{% for variant in product.variants %}{{ variant.id }}:{{ variant.metafields.bookthatapp.config }}{% unless forloop.last %},{% endunless %}{% endfor %}"
data-bta-range-partner-id="#booking-finish-{{ product.handle }}"
data-bta-range-days-max="0" data-bta-range-days-min="0" />
</div>
<div>
{% capture attribute %}booking-finish{% endcapture %}
<label for="{{ attribute }}-{{ product.handle }}">To:</label>
<input id="{{ attribute }}-{{ product.handle }}" type="text" name="properties[To]" size="12" class="datepicker bta required bta-load-enable bta-dp-finish" disabled="disabled"
data-bta-range-partner-id="#booking-start-{{ product.handle }}" />
</div>
<div class="quantity">
<label for="quantity">Quantity:</label>
{% comment %}
<div class="rental-summary">
Days: <span class="rental-days"></span><br>
Total: <span class="rental-total"></span>
</div>
{% endcomment %}
<input type="number" id="units" name="properties[Units]" value="1" min="1" pattern="[0-9]*" />
</div>
<div class="bta-validation-messages" style="display:none">
<p class="bta-validation-date-missing">Please select a date</p>
</div>
<input type="hidden" id="quantity" name="quantity" value="1" />
</div>
<script>
// rental product behaviour
var ProductRental = function() {
_this = this;
this.configs = {};
this.durations = [];
this.init = function() {
'{{ product.metafields.bookthatapp.config }}'.replace(new RegExp("([^?=&]+)(=([^&]*))?", "g"), function($0, $1, $2, $3) {_this.configs[$1] = $3;});
_this.durations = JSON.parse(unescape(_this.configs.durations)).sort(function(a, b) {
return a.position - b.position;
});
_this.hideDurationOptionSelect();
_this.initFormListeners();
};
this.initFormListeners = function() {
var form = $('form[action="/cart/add"]');
form.on('bta.dataLoaded, bta.datetimeChange', function(event, form) {
_this.updateQuantity();
});
form.on('click', '.js-qty__adjust', function() {
_this.updateQuantity();
});
$('#units').change(function() {
_this.updateQuantity();
});
};
this.updateQuantity = function() {
var form = $('form[action="/cart/add"]').data('bta.bookingForm'),
start = form.getStartDateTime(),
finish = form.getFinishDateTime();
$('.rental-summary .rental-total').text('-');
$('.rental-summary .rental-days').text('-');
if (start && finish) {
var days = form.rangeCount();
// total rent = number of units * number of days * variant.price
var variantId = bta.findSelectedVariantId(),
units = parseInt($('#units').val(), 10),
variant = _this.findVariant(variantId),
total = variant.price * units * days;
$('#quantity').val(units * days);
$('.rental-summary .rental-days').text(days);
$('.rental-summary .rental-total').text(_this.formatMoney(total));
}
};
this.findVariant = function(id) {
for (var i = 0; i < _this.product.variants.length; i++) {
if (_this.product.variants[i].id == id) {
return _this.product.variants[i];
}
}
};
this.hideDurationOptionSelect = function() {
// hide option for duration (bypass .selector-wrapper inside booking form)
$('.selector-wrapper:nth-child(' + _this.configs['duration_option_position'] + ')').filter(function(index) {
return $(this).parents('.booking-form').length == 0;
}).hide();
};
this.formatMoney = function(total) {
return Shopify.formatMoney(total, '{{ shop.money_format }}')
};
this.product = {{ product | json }};
}
document.addEventListener("DOMContentLoaded", function(event) {
new ProductRental().init();
});
var bta = {
productId: {{ product.id }}
}
</script>
{% endif %}
// ============ Cart Template =============
1. Display line item property dates:
{% if item.product.metafields.bookthatapp.config %}
<p>{{ item.properties.From }} - {{ item.properties.To }}</p>
{% else %}
// ususal guff
{% endif %}
2. Show units for quantity
{% if item.product.metafields.bookthatapp.config %}
{{ item.quantity | divided_by: item.properties.Units }} days x {{ item.properties.Units }}
<input type="hidden" name="updates[]" id="Updates_{{ item.id }}" value="{{ item.quantity }}" data-line="{{ forloop.index }}">
<a href="/cart/change?line={{ forloop.index }}&quantity=0">Remove</a>
{% else %}
<input type="number" name="updates[]" id="updates_{{ item.id }}" value="{{ item.quantity }}" min="0" data-line="{{ forloop.index }}">
{% endif %}
// ============ Cart Count (Header) =============
{% assign cart_count = 0 %}
{% for item in cart.items %}
{% if item.product.metafields.bookthatapp.config %}
{% assign cart_count = cart_count | plus: item.properties.Units %}
{% else %}
{% assign cart_count = item.quantity %}
{% endif %}
{% endfor %}
<span class="icon-cart"></span> {{ 'layout.general.cart' | t }} (<span class="cart_count">{{ cart_count }}</span>)
// ============ CSS ============
/* BookThatApp */
.booking-form {
display: -ms-flex;
display: -webkit-flex;
display: flex;
> div {
padding: 10px 0;
margin-right: 20px;
}
> div:last-child {
margin-right: 0px;
}
#units {min-width: 50px}
}
@gterrill

This comment has been minimized.

Copy link
Owner Author

gterrill commented Feb 2, 2019

Please contact us at support@zetya.com if you need help with this or would like a quote to have us install it for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.