覆盖/扩展Magento核心javascript文件

14

最近,由于客户的投诉和与我们市场团队的讨论,我收到了一个请求,要求更改可配置产品选项的默认行为。他们要求我从选项下拉菜单中删除 + $xx.xx 显示的价格,因为这使得客户/访问者感到困惑,只显示可用选项而不显示价格更改。从他们的角度来看是合理的,但我认为从开发人员的角度来看有些棘手。该站点正在运行 Magento CE 1.6.2,并且我们需要覆盖/更改的文件是 /public_html/js/varien/configurable.js。我们需要更改其中的 getOptionLabel 函数,以便它不显示价格变化。 所以我的问题是:在不触及核心 JavaScript 文件的情况下,正确的 Magento 更改此文件的方式是什么? 谢谢。


JavaScript不支持覆盖。 但是请参见以下链接: https://dev59.com/22035IYBdhLWcg3wc_sm - Guerra
@Guerra 你确定 prototype 有一种优雅地包装()东西的方法吗? - Anton S
在我看来,这是一种模拟面向对象编程中重写(override)的方法,但它能够正常工作。 - Guerra
3个回答

30

请参考原型手册,您可以包装任何对象方法,甚至是调用“parent”(父类)函数。以下是一个伪代码示例:

//where Product.Config is the object/class you need to "override"
Product.Config.prototype.getOptionLabel  = Product.Config.prototype.getOptionLabel.wrap(function(parentMethod){
    //replace the original method here with your own stuff
    //or call parentMethod(); if conditions don't match
});

非常感谢 Anton 给出的提示。我明天会试着操作一下,看看效果如何。 - Milen Petrov
对于Magento 1.7,这个代码可以运行:Product.Config.prototype.getOptionLabel = Product.Config.prototype.getOptionLabel.wrap - Kevin
猜测这取决于方法的命名方式。 - Anton S
我正在尝试找出覆盖核心文件的JS文件最佳放置位置。在我的情况下,它是js/prototype/validation.js,并且我看到Mage中可能有5到10个对该.js文件的不同引用。并非所有引用都是布局xml。 - kalenjordan
你可以在原文件加载后添加到任何文件中。我会添加自己的文件并将其放置在那里。 - Anton S
这与1.9.2.1无关,但涉及到prototypejs库的功能。 - Anton S

26

补充@anton-s绝对正确的答案,你还可以进行“完整的”类重写:

// Create the original class
var ClassA = Class.create();
ClassA.prototype = {
    initialize: function(config) {
        this.config = config;
    },
    test: function(msg) {
        console.log('Hi from class A with message ' + msg);
    }
};

// Create new class extending the original class
var ClassB = Class.create(ClassA, {
    // $super is a reference to the original method
    test: function($super, msg) {
        console.log('Hi from class B');
        console.log('this.config is accessible in class B: ' + this.config);
        $super(msg + ' ...')
    }
});


// To make the extend an override, you can do this:
ClassA = ClassB;
// ClassA now is ClassB overriding the original ClassA
var a = new ClassA('some config data');
a.test('Call A 1');

因为所有这些仅适用于原型类,而不是已实例化的对象,我还会提供这个hack,它几乎就是wrap()所做的事情:

// Overriding a method of an already instantiated object
// There are many ways to do this more elegantly thanks to the amazing JS scoping magic
a.origTest = a.test;
a.test = function(msg) {
    console.log('Hi from the patched method');
    this.origTest(msg);
}
a.test('Call A 2');

请记住,wrap()方法更加优雅,并且也可以用于类定义或具体实例。

// Wrap method of concrete instance
spConfig.getOptionLabel = spConfig.getOptionLabel.wrap(function(parentMethod, option, price) {
    return parentMethod(option, price);
});

// Wrap method of class declaration
Product.Config.prototype.getOptionLabel = Product.Config.prototype.getOptionLabel.wrap(function(parentMethod, option, price) {
    return parentMethod(option, price);
});

2
非常感谢Vinai和Anton S提供的宝贵提示。我们已经改变了我们的临时js hack,现在按照正确的Magento方式完成了。你们太棒了! - Milen Petrov
@MilenPetrov 接受那个能帮助你改善其他人在搜索类似问题时的 Stack Overflow(SO)体验的答案。 - Anton S
@Anton S - 真的很抱歉我忘了做那件事。 - Milen Petrov

0

如何在Magento 1.9 EE中覆盖\js\varien\configurable.js并添加新的数据属性

创建文件\js\jsoverride\configurable.js:

    Product.Config.prototype.reloadOptionLabels = Product.Config.prototype.reloadOptionLabels.wrap(function (parentMethod, element) {
    var selectedPrice;
    if (element.options[element.selectedIndex].config && !this.config.stablePrices) {
        selectedPrice = parseFloat(element.options[element.selectedIndex].config.price);
    } else {
        selectedPrice = 0;
    }
    for (var i = 0; i < element.options.length; i++) {
        if (element.options[i].config) {
            element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price - selectedPrice);
            element.options[i].setAttribute('data-in-stock', element.options[i].config.in_stock);
        }
    }
});

创建或使用文件:\app\design\frontend\enterprise\YOUR_THEME\layout\local.xml,并添加以下行:
<?xml version="1.0"?>
<layout version="0.1.0">
  <catalog_product_view>
    <reference name="head">
      <action method="addJs"><script>jsoverride/configurable.js</script></action>
    </reference>
  </catalog_product_view>
</layout>

注意,在文件中填充数据到element.options[i].config.in_stock。

app\design\frontend\enterprise\YOUR_THEME\template\catalog\product\view\type\options\configurable.phtml

下一行

var spConfig = new Product.Config(UPDATED JSON WITH NEW ATTRIBUTE);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接