如何在保留option_selection.js

时间:2019-12-17 22:44:00

标签: javascript shopify

我正在使用shopify,并希望在变量选择器下拉列表中显示变量价格。 Shopify使用名为option_selection.js的资产来实施变体选择功能。该资产是站点正常运行所必需的;但是,此资产将覆盖在product.liquid文件中创建的select标签。

不包括option_selection.js,您可以简单地将变量价格添加到product.liquid文件中的每个选项。像这样:

<div class="variants-wrapper clearfix {% if product.variants.size == 1 %}visuallyhidden{% endif %}"> 
    <select id="product-select" name="id">
        {% for variant in product.variants %}
            <option value="{{ variant.id }}">{{ variant.title | escape }} - {{ variant.price | money }}{% if variant.available == false %} - No Stock{% endif %}</option>
        {% endfor %}
    </select>
</div>

但是,在启用option_selection.js的情况下,此选择下拉列表将替换为仅包含变体标题而没有其他信息的另一个下拉列表。

经过反复试验,我发现我可以使用以下代码片段覆盖Shopify.Product.prototype.optionValues脚本标签之后的脚本标签中的option_selection.js

Shopify.Product.prototype.optionValues = function(o) {
  if (!Shopify.isDefined(this.variants)) return null;
  var t = Shopify.map(this.variants, function(t) {
    var e = "option" + (o + 1);
    if(t[e] == undefined) {
      return null
    } else {
      var value = t[e] + " - " + Shopify.formatMoney(t.price)
      if(!t.available) value += " - No Stock"
      return value
    }
  });
  return null == t[0] ? null : Shopify.uniq(t)
}

该代码段将覆盖以下代码段:

Shopify.Product.prototype.optionValues = function(o) {
    if (!Shopify.isDefined(this.variants)) return null;
    var t = Shopify.map(this.variants, function(t) {
        var e = "option" + (o + 1);
        return t[e] == undefined ? null : t[e]
    });
    return null == t[0] ? null : Shopify.uniq(t)
}

但是,这会使option_selection.js中实现的其余功能完全停止工作。我不明白为什么此更改会影响脚本的其余部分,但确实如此。

要对此进行测试,您可以创建一个具有两个变体的项目,一个可用,一个不可用。选择可用项目应启用“添加到购物车”按钮,而选择不可用选项则应禁用该按钮。这是option_selection.js实现的众多功能之一,一旦实施此尝试的修复,该功能就会失败。

如何在保留option_selection.js及其功能的同时,将变体价格包含在变体选择下拉列表中?


1 个答案:

答案 0 :(得分:0)

事实证明,尝试第二种解决方案的问题在于option_selection.js中的以下代码段:

Shopify.SingleOptionSelector = function(o, i, t, e) {
    this.multiSelector = o, this.values = e, this.index = i, this.name = t, this.element = document.createElement("select");
    for (var r = 0; r < e.length; r++) {
        var n = document.createElement("option");
        n.value = e[r], n.innerHTML = e[r], this.element.appendChild(n)
    }
    return this.element.setAttribute("class", this.multiSelector.selectorClass), this.element.setAttribute("data-option", "option" + (i + 1)), this.element.id = o.domIdPrefix + "-option-" + i, this.element.onchange = function(t, e) {
        e = e || {}, o.updateSelectors(i, e)
    }, !0
}

在此代码段中,.innerHTML属性被设置为与值相同。您实际上并不想更改该值,而只想更改innerHTML。为了达到此效果,我们将不得不在option_selection.js中进行一些更改。

复制shopify的option_selection.js并制作我们自己的副本更容易。为此,您可以阅读生成的页面源以查找脚本URL,然后将该源复制到文件名option_selection和扩展名.js的新资产中。接下来,将源(使用代码美化器将其粘贴到新创建的资产中)。然后,您只需将shopify_asset替换为asset,即可将shopify资产标签更改为常规资产标签。

在新资产中找到以下代码段:

Shopify.Product.prototype.optionValues = function(o) {
    if (!Shopify.isDefined(this.variants)) return null;
    var t = Shopify.map(this.variants, function(t) {
        var e = "option" + (o + 1);
        return t[e] == undefined ? null : t[e]
    });
    return null == t[0] ? null : Shopify.uniq(t)
}

然后在该代码段之后添加以下代码段:

Shopify.Product.prototype.optionTexts = function(o) {
  if (!Shopify.isDefined(this.variants)) return null;
  var t = Shopify.map(this.variants, function(t) {
    var e = "option" + (o + 1);
    if(t[e] == undefined) {
      return null
    } else {
      var value = t[e] + " - " + Shopify.formatMoney(t.price)
      if(!t.available) value += " - No Stock"
      return value
    }
  });
  return null == t[0] ? null : Shopify.uniq(t)
}

请注意,此函数有一个新名称.optionTexts,因为此函数只会创建要插入选项标签内的文本。

下一步找到以下行:

var e = new Shopify.SingleOptionSelector(this, t, this.product.optionNames()[t], this.product.optionValues(t));

然后将该行替换为以下行:

var e = new Shopify.SingleOptionSelector(this, t, this.product.optionNames()[t], this.product.optionValues(t), this.product.optionTexts(t));

在这里,我们正在调用新创建的text函数,并将结果与​​原始value函数一起传递。

接下来找到以下代码段:

Shopify.SingleOptionSelector = function(o, i, t, e) {
    this.multiSelector = o, this.values = e, this.index = i, this.name = t, this.element = document.createElement("select");
    for (var r = 0; r < e.length; r++) {
        var n = document.createElement("option");
        n.value = e[r], n.innerHTML = e[r], this.element.appendChild(n)
    }
    return this.element.setAttribute("class", this.multiSelector.selectorClass), this.element.setAttribute("data-option", "option" + (i + 1)), this.element.id = o.domIdPrefix + "-option-" + i, this.element.onchange = function(t, e) {
        e = e || {}, o.updateSelectors(i, e)
    }, !0
}

然后用以下代码段替换该代码段:

Shopify.SingleOptionSelector = function(o, i, t, e, texts) {
    this.multiSelector = o, this.values = e, this.index = i, this.name = t, this.element = document.createElement("select");
    for (var r = 0; r < e.length; r++) {
        var n = document.createElement("option");
        n.value = e[r], n.innerHTML = texts[r], this.element.appendChild(n)
    }
    return this.element.setAttribute("class", this.multiSelector.selectorClass), this.element.setAttribute("data-option", "option" + (i + 1)), this.element.id = o.domIdPrefix + "-option-" + i, this.element.onchange = function(t, e) {
        e = e || {}, o.updateSelectors(i, e)
    }, !0
}

在这里,我们接受先前传递的要插入选项标签的文本列表,并插入该列表而不是值列表。

这样,值保持不变,文本将更改为您想要的任何文本。