Extending Core Magento Javascript Files – Don’t overwrite

Magento’s front end javascript files are written using Prototype as the base for functionality.
While many of us are far more comfortable with jQuery, Prototype comes with many functions and features that allows us to easily extend Magento’s JS files rather than modify it, or worse, overwrite it.

For those who aren’t familiar with Prototype, the library offers an impressive amount of extended functionalities for easy Class building, inheritance, and basic functionalities that extend on top of the basic Javascript library. Because it uses the “$” symbol for selecting elements by id (it’s somewhat similar to using getElementbyId(”)), it usually causes quite a bit of frustration when it comes to trying to use the jQuery library on top of the existing platform.

So, before diving in, one quick note:

Use jQuery.noConflict() after you include your jQuery scripts to avoid having prototype scream into your console, figuratively speaking.

Let’s dive in!

Why Alter Magento’s JS?

One of the more common reasons developers need to alter Magento’s JS is to add their own validation functions for fields. Validation with prototype in Magento is done by adding a class to the field being validated. For example, you’ll find the class “validate-postcode” applied to the billing:postcode field in a checkout form.

<div class="field">
    <label for="billing:postcode" class="required"><em>*</em><?php echo $this->__('Zip/Postal Code') ?></label>
    <div class="input-box">
        <input type="text" title="<?php echo $this->__('Zip/Postal Code') ?>" name="billing[postcode]" id="billing:postcode" value="<?php echo $this->htmlEscape($this->getAddress()->getPostcode()) ?>" class="input-text validate-postcode required-entry" />
    </div>
</div>

Without going too much into detail about how this works (You’ll find an article here by one of our developers: Benefits of Using Default Magento Forms, what if we wanted to add our own validator?

The Wrong method

A few poor searches on Google would accidentally lead a few developers to take the validation.js file under /js/ and copy it over to their own skin folders for extending. Some people skip this step altogether and add their code directly into the validation.js file. Don’t do this.

The Correct method

Thanks to the nature of Prototype, methods can actually be added directly to the class using .addMethod (or with Object.extend, the Magento way).
In the context of the class Validator, we already have a method defined to adding new validators (add or addAllThese for multiple validators).

    add : function(className, error, test, options) {
        var nv = {};
        nv[className] = new Validator(className, error, test, options);
        Object.extend(Validation.methods, nv);
    },
    addAllThese : function(validators) {
        var nv = {};
        $A(validators).each(function(value) {
                nv[value[0]] = new Validator(value[0], value[1], value[2], (value.length > 3 ? value[3] : {}));
            });
        Object.extend(Validation.methods, nv);
    }

I personally prefer to use addAllThese as it provides room for adding newer validators later rather than having to add one validator at a time.
For the context of this tutorial, I’m going to add a new validator that simply returns true no matter what. (Just as an example)
Let’s start by creating our own javascript file in our skin folder.

Navigate to /skin/frontend/yourpackage/yourtheme/js/
Create a new file: (e.g. myvalidator.js)

In it, we can directly reference the Validator object, add our own validator to it.

Validator.addAllThese([
['validate-yourvalidatorname', 'This is the error message.  But we never return false, so you'll never see it.', function(v) {
        //Add your own validation code here
        return true; //For now, we'll just return true
    }]
]);

In /app/design/frontend/yourpackage/yourtheme/layout/local.xml (if you don’t have one, create one), add your new js file in the “head” block.

Now in any fields you’d like to use your validator in, you just add the class “validate-yourvalidatorname” to it and Validator will automatically validate your field using your new validation method.

The best part? Your new js file can be re-added or removed without causing any issues to the core Magento code.
Enjoy!