我一直在与Shopify商店达成共同请求,使用“Debut”主题为商店添加“添加到购物车按钮”。我们的目标是在点击“添加到购物车按钮”时自动更新购物车,而不会跳到购物车页面,以便在页面上保留客户,以方便使用。
现在通常这不是一个大问题,因为网上有很多关于这个主题的资料。我通常可以“google my way to freedom”
以下是我参考过的一些链接
将以下代码添加到 product-card-grid.liquid
时,“添加到购物车”按钮可正常工作 <form method="post" action="/cart/add">
<input type="hidden" name="id" value="{{ product.variants.first.id }}" />
<input min="1" type="number" id="quantity" name="quantity" value="1"/>
<input type="submit" value="Add to cart" class="btn" />
</form>
问题:
我遇到的问题是我的收藏页面使用侧边栏过滤器。代码无处不在,但在收集页面上。通过一些挖掘和一些检查,我发现这可能是因为侧栏/集合页面中的产品是从 theme.js 文件中的某些代码填充的。
现在这就是我绝对只是盲目飞行的地方,Javascript是我想要更熟悉的东西,但是就像花一些时间一样。
所以......通过仔细阅读theme.js文件我注意到的是,如果格式正确,可以将html添加到js。我能够插入它并获得“添加到购物车”按钮以显示在我的侧边栏/收藏页面中。小胜利!但是不太有用。
点击“添加到购物车”按钮后,我收到以下错误
“数组包含不允许的成员:id ”
以下是我希望可以修改的 theme.js 文件中的一些代码
function runFilter() {
typeFilter(typebxs);
vendorFilter(vendorbxs);
tagsFilter(tagbxs);
optionsFilter(optionsbxs);
colorFilter(colorbxs);
sizeFilter(sizebxs);
var has_price_filter = document.getElementById("sidebar-product-price").innerHTML;
if ( has_price_filter == "true" ) {
priceFilter(pricebxs);
} else {
passedpricefiltertest = "true";
}
if ( passedtagfiltertest == "true"
&& passedtypefiltertest == "true"
&& passedpricefiltertest == "true"
&& passedvendorfiltertest == "true"
&& passedoptionsfiltertest == "true"
&& passedcolorfiltertest == "true"
&& passedsizefiltertest == "true" ) {
var money_sign = document.getElementById("money-sign").innerHTML; money_sign = money_sign.replace("0.00", "");
if ( varaints_min_price != varaints_max_price ) { var price_string = money_sign + parseFloat((varaints_min_price)).toFixed(2) + "+" } else { var price_string = money_sign + parseFloat((varaints_min_price)).toFixed(2); }
var product_url = collection_url +"products/"+ val.handle;
var product_images_ratio = document.getElementById("product_images_ratio").innerHTML;
var product_image_url = val.images[0].src.replace(".jpg", "_600x600.jpg");
product_image_url = product_image_url.replace(".png", "_600x600.png");
if (val.variants[0].available == true) { var sold_out = ''; } else { var sold_out = ' product-price--sold-out grid-view-item--sold-out'; }
var string1 = '<div class="grid__item grid__item--' + sectionid + ' ' + grid_item_width + '"><div class="grid-view-item' + sold_out + '" data-section-id="section.id" data-section-type="collection-template"><div class="product-container"><div class="collection-product-overlay"><a class="grid-view-item__link" href="' + product_url + '">';
if (product_images_ratio == "none") { var string2 = '<div style="display:none;" id="product-image-align">false</div><div style="display:none;" id="product-image-ratio">' + product_images_ratio + '</div><img class="grid-view-item__image" src="' + product_image_url + '" alt="">'; } else { var string2 = '<div class="image-bar__item box ratio-container lazyload product-grid-image"data-bgset="' + product_image_url + '" data-sizes="auto" data-parent-fit="contain" style=" background-size: contain; background-color: transparent; background-attached:fixed; background-position: center; background-image: url("' + product_image_url + '");"></div><div style="display:none;" id="product-image-align">true</div><div style="display:none;" id="product-image-ratio">' + product_images_ratio + '</div>'; }
if (show_vendor == "true") { var string3 = '<div style="" class="h4 grid-view-item__title collection-title_wrapper">' + val.title + '</div><div class="grid-view-item__vendor collection-title_wrapper">' + val.vendor + '</div>'; } else { var string3 = '<div style="" class="h4 grid-view-item__title collection-title_wrapper">' + val.title + '</div>'; }
if ( val.variants[0].compare_at_price > val.variants[0].price ) { var string4 = '<div class="grid-view-item__meta collection-title_wrapper"><span class="visually-hidden">Regular price</span><s class="product-price__price" style="">' + money_sign + val.compare_at_price + '</s><span class="product-price__price product-price__sale" style="">' + price_string + '<span class="product-price__sale-label">Sale</span></span>'; } else { var string4 = '<div class="grid-view-item__meta collection-title_wrapper"><span class="product-price__price" style="">' + price_string + '</span>' + '<form class="addtocart"method="post" action="/cart/add"><input type="hidden" name="id" value="quantity" /><input min="1" type="number" id="{{ product.variants.first.id }}" name="quantity" value="1"/><input type="submit" value="Add to cart" class="btn" /></form>' ; }
if ( val.variants[0].available == true ) { var string5 = '</div></a></div></div></div></div>'; } else { var string5 = '<span class="product-price__sold-out" style="">Sold out</span></div></a></div></div></div>'; }
var string = string1 + string2 + string3 + string4 + string5;
filteredProducts.push(val.title+val.id);
productGrid[val.title+val.id] = [string];
if (total_json_pages == counter2) {
if (counter3 == collectionLength) {
circle.animate(1,{
duration: (100)
});
debouncedPagintor();
}
}
if ( product_images_ratio != "none" ) {
var width = $( ".product-grid-image" ).width();
width = parseInt(width) * parseFloat(product_images_ratio) ;
$( ".product-grid-image" ).css( "height", width );
}
} else {
if (total_json_pages == counter2) {
if (counter3 == collectionLength) {
debouncedPagintor();
}
}
}
}
runFilter();
}
}
$('.filter-update ~ .lbl, .filter-update ~ .cbx').unbind("click");
$('.filter-update ~ .lbl, .filter-update ~ .cbx').on( "click", function() {
debouncedfilterIt();
});
}
var debouncedfilterIt = function() {
filterIt();
}
var debouncedfilterIt = $.debounce( 250, false, debouncedfilterIt );
var needsFilter = document.getElementById('sb-master-input-format-1');
function grabCollection() {
var show_vendor = document.getElementById("show_vendor").innerHTML;
var grid_item_width = document.getElementById("grid_item_width").innerHTML;
var sectionid = sectionId;
var money_sign = document.getElementById("money-sign").innerHTML;
money_sign = money_sign.replace("0.00", "");
var filteredProducts = [];
var jsonDataString = "";
var jsonData = {};
if (masterString[jsonsrc + "1"] == undefined) {
if ( total_json_pages > 2 ) {
$( "#progress" ).show();
circle.animate(1,{
duration: ((total_json_pages)*200)
});
您可以看到我在哪里插入了html来加载收藏页面上的按钮。我做的唯一修改就是插入包含在“form”标签中的html位。
我相信这个问题很可能会在特别长的代码行中找到。
来自该文件
if ( val.variants[0].compare_at_price > val.variants[0].price ) { var string4 = '<div class="grid-view-item__meta collection-title_wrapper"><span class="visually-hidden">Regular price</span><s class="product-price__price" style="">' + money_sign + val.compare_at_price + '</s><span class="product-price__price product-price__sale" style="">' + price_string + '<span class="product-price__sale-label">Sale</span></span>'; } else { var string4 = '<div class="grid-view-item__meta collection-title_wrapper"><span class="product-price__price" style="">' + price_string + '</span>' + '<form class="addtocart"method="post" action="/cart/add"><input type="hidden" name="id" value="quantity" /><input min="1" type="number" id="{{ product.variants.first.id }}" name="quantity" value="1"/><input type="submit" value="Add to cart" class="btn" /></form>' ; }
这是我第一次发帖。如果我错过了为此论坛设置格式的简单方法,我深表歉意。
我希望这已经足够了。我快到了吗?这是一个简单的修复吗?信息不足?
感谢您的时间!我希望这是足够彻底的,而不是太复杂。
此致
Jeff J
修改
我快到了! (感谢Darshit Patel!)在 theme.js 中将"{{ product.variants.first.id }}"
更改为"'+ val.variants[0].id +'"
摆脱了“数组包含未经许可的成员:id”错误并更新购物车,但它带我到购物车页面,似乎没有与 ajaxify-cart.liquid
这是整个ajaxify-cart.liquid代码
<script>
/**
* Module to ajaxify all add to cart forms on the page.
*
* Copyright (c) 2015 Caroline Schnapp (11heavens.com)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
Shopify.AjaxifyCart = (function($) {
// Some configuration options.
// I have separated what you will never need to change from what
// you might change.
var _config = {
// What you might want to change
addToCartBtnLabel: 'Add to cart',
addedToCartBtnLabel: 'Thank you!',
addingToCartBtnLabel: 'Adding...',
soldOutBtnLabel: 'Sold Out',
howLongTillBtnReturnsToNormal: 1000, // in milliseconds.
cartCountSelector: '#CartCount, .cart-count, #cart-count a:first, #gocart p a, #cart .checkout em, .item-count',
cartTotalSelector: '#cart-price',
// 'aboveForm' for top of add to cart form,
// 'belowForm' for below the add to cart form, and
// 'nextButton' for next to add to cart button.
feedbackPosition: 'nextButton',
// What you will never need to change
addToCartBtnSelector: '[type="submit"]',
addToCartFormSelector: 'form[action="/cart/add"]',
shopifyAjaxAddURL: '/cart/add.js',
shopifyAjaxCartURL: '/cart.js'
};
// We need some feedback when adding an item to the cart.
// Here it is.
var _showFeedback = function(success, html, $addToCartForm) {
$('.ajaxified-cart-feedback').remove();
var feedback = '<p class="ajaxified-cart-feedback ' + success + '">' + html + '</p>';
switch (_config.feedbackPosition) {
case 'aboveForm':
$addToCartForm.before(feedback);
break;
case 'belowForm':
$addToCartForm.after(feedback);
break;
case 'nextButton':
default:
$addToCartForm.find(_config.addToCartBtnSelector).after(feedback);
break;
}
// If you use animate.css
// $('.ajaxified-cart-feedback').addClass('animated bounceInDown');
$('.ajaxified-cart-feedback').slideDown();
};
var _setText = function($button, label) {
if ($button.children().length) {
$button.children().each(function() {
if ($.trim($(this).text()) !== '') {
$(this).text(label);
}
});
}
else {
$button.val(label).text(label);
}
};
var _init = function() {
$(document).ready(function() {
$(_config.addToCartFormSelector).submit(function(e) {
e.preventDefault();
var $addToCartForm = $(this);
var $addToCartBtn = $addToCartForm.find(_config.addToCartBtnSelector);
_setText($addToCartBtn, _config.addingToCartBtnLabel);
$addToCartBtn.addClass('disabled').prop('disabled', true);
// Add to cart.
$.ajax({
url: _config.shopifyAjaxAddURL,
dataType: 'json',
type: 'post',
data: $addToCartForm.serialize(),
success: function(itemData) {
// Re-enable add to cart button.
$addToCartBtn.addClass('inverted');
_setText($addToCartBtn, _config.addedToCartBtnLabel);
_showFeedback('success','<i class="fa fa-check"></i> Added to cart! <a href="/cart">View cart</a> or <a href="/collections/all">continue shopping</a>.',$addToCartForm);
window.setTimeout(function(){
$addToCartBtn.prop('disabled', false).removeClass('disabled').removeClass('inverted');
_setText($addToCartBtn,_config.addToCartBtnLabel);
}, _config.howLongTillBtnReturnsToNormal);
// Update cart count and show cart link.
$.getJSON(_config.shopifyAjaxCartURL, function(cart) {
if (_config.cartCountSelector && $(_config.cartCountSelector).size()) {
var value = $(_config.cartCountSelector).html() || '0';
$(_config.cartCountSelector).html(value.replace(/[0-9]+/,cart.item_count)).removeClass('hidden-count');
}
if (_config.cartTotalSelector && $(_config.cartTotalSelector).size()) {
if (typeof Currency !== 'undefined' && typeof Currency.moneyFormats !== 'undefined') {
var newCurrency = '';
if ($('[name="currencies"]').size()) {
newCurrency = $('[name="currencies"]').val();
}
else if ($('#currencies span.selected').size()) {
newCurrency = $('#currencies span.selected').attr('data-currency');
}
if (newCurrency) {
$(_config.cartTotalSelector).html('<span class=money>' + Shopify.formatMoney(Currency.convert(cart.total_price, "{{ shop.currency }}", newCurrency), Currency.money_format[newCurrency]) + '</span>');
}
else {
$(_config.cartTotalSelector).html(Shopify.formatMoney(cart.total_price, "{{ shop.money_format | remove: "'" | remove: '"' }}"));
}
}
else {
$(_config.cartTotalSelector).html(Shopify.formatMoney(cart.total_price, "{{ shop.money_format | remove: "'" | remove: '"' }}"));
}
};
});
},
error: function(XMLHttpRequest) {
var response = eval('(' + XMLHttpRequest.responseText + ')');
response = response.description;
if (response.slice(0,4) === 'All ') {
_showFeedback('error', response.replace('All 1 ', 'All '), $addToCartForm);
$addToCartBtn.prop('disabled', false);
_setText($addToCartBtn, _config.soldOutBtnLabel);
$addToCartBtn.prop('disabled',true);
}
else {
_showFeedback('error', '<i class="fa fa-warning"></i> ' + response, $addToCartForm);
$addToCartBtn.prop('disabled', false).removeClass('disabled');
_setText($addToCartBtn, _config.addToCartBtnLabel);
}
}
});
return false;
});
});
};
return {
init: function(params) {
// Configuration
params = params || {};
// Merging with defaults.
$.extend(_config, params);
// Action
$(function() {
_init();
});
},
getConfig: function() {
return _config;
}
}
})(jQuery);
Shopify.AjaxifyCart.init();
</script>
{% comment %}
If you want to animate your feedback message.
{% endcomment %}
{% comment %}
{{ '//cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.0/animate.min.css' | stylesheet_tag }}
{% endcomment %}
{{ '//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.0.3/css/font-awesome.css' | stylesheet_tag }}
<style>
.ajaxified-cart-feedback {
display: block;
line-height: 36px;
font-size: 90%;
vertical-align: middle;
}
.ajaxified-cart-feedback.success {
color: #3D9970;
}
.ajaxified-cart-feedback.error {
color: #FF4136;
}
.ajaxified-cart-feedback a {
border-bottom: 1px solid;
}
</style>
我想知道是否有一个简单的解决方案。我不知所措。我会把这个问题作为一个新问题,但此时它似乎真的是“两个人”,因为它与我分享的所有信息有关。
再次,谢谢你的时间
干杯!
答案 0 :(得分:1)
来自theme.js的这行代码'id =“{{product.variants.first.id}}”'是确切的问题。当你在任何.js文件中添加此行时,它不会呈现为液体但是它会将其渲染为String。 Theme.js是简单的.js文件不是液体,所以这个液体线将呈现为String。您需要更改该行,您的问题将得到解决。 您只需要在整个theme.js中将“{{product.variants.first.id}}”替换为“val.variants [0] .id”。