Last days as a result of some customer complains and discussion with our marketing guys I've got a request to change the default behavior of the configurable products options. They asked me to remove the + $xx.xx from the options drop-down as it is confusing the customers/visitors and just leave the available options without displaying the price change. Fair enough from their point of view, but it is a bit tricky from developers point of view I think. The site is running Magento CE 1.6.2, and the file which we need to override/change is /public_html/js/varien/configurable.js. We need to change the getOptionLabel function in it so that it does not display the price change. So my question is: what is the right Magento way to change this file and not touch the core javascript file? Thanks in advance.
-
javascript dont suport overrides. but see that http://stackoverflow.com/questions/5409428/how-to-override-a-javascript-function – Guerra Aug 13 '12 at 20:14
-
@Guerra are you sure prototype has a way to wrap() things nicely – Anton S Aug 13 '12 at 20:30
-
IMO this is a hack to simulate OOP overrides, but work's fine – Guerra Aug 13 '12 at 20:39
3 Answers
See this from prototype manual http://prototypejs.org/doc/latest/language/Function/prototype/wrap/ you can wrap whatever object method and even call "parent" if needed and here's a pseudo sample:
//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
});

- 3,655
- 24
- 29

- 12,750
- 2
- 35
- 37
-
Thanks a lot Anton for your hint. I will play with it in the morning and see how it performs. – Milen Petrov Aug 13 '12 at 20:53
-
For Magento 1.7 this works: Product.Config.prototype.getOptionLabel = Product.Config.prototype.getOptionLabel.wrap – Kevin Oct 04 '12 at 14:47
-
-
I'm trying to figure out where the best place would be to place the JS file that overrides the core file. In my case, it's js/prototype/validation.js, and I see probably 5 to 10 different references to that .js file throughout Mage. And not all of them are layout xml. – kalenjordan Mar 12 '13 at 00:02
-
you can add to whatever file loaded after the original file. I'd add my own file and place it there. – Anton S Mar 12 '13 at 06:40
-
this has nothing to do with 1.9.2.1 but features on prototypejs library – Anton S Sep 25 '15 at 09:03
Just to add to @anton-s's absolutely correct answer, you can also do "full" class rewrites:
// 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');
Since all this only works on prototype classes, not on already instantiated objects, I'll also throw in this hack, which is pretty much what wrap() does, too:
// 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');
Keep in mind though that the wrap()
method is nicer, and can also be used on on class definitions or on concrete instances.
// 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);
});

- 14,162
- 2
- 49
- 69
-
2Thanks a lot Vinai and Anton S for your valuable hints. We've changed our temporary js hack and now it is done in the right Magento way. You're rocks! – Milen Petrov Aug 14 '12 at 11:51
-
@MilenPetrov accept the answer that helps you out to improve the SO experience for others who search the similar – Anton S Aug 14 '12 at 12:31
-
How to override \js\varien\configurable.js in Magento 1.9 EE and add new data attribute
Create file \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);
}
}
});
Create or use file: \app\design\frontend\enterprise\YOUR_THEME\layout\local.xml and add next rows:
<?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>
Note, filling data to element.options[i].config.in_stock in file
app\design\frontend\enterprise\YOUR_THEME\template\catalog\product\view\type\options\configurable.phtml
with next row
var spConfig = new Product.Config(UPDATED JSON WITH NEW ATTRIBUTE);

- 53
- 1
- 7