addMethods

addMethods([methods])
addMethods(tagName, methods)

Takes a hash of methods and makes them available as methods of extended elements and of the Element object. The second usage form is for targeting a specific HTML element.

Element.addMethods makes it possible to mix in your own methods to the Element object, which you can later use as methods of extended elements - those returned by the $() utility, for example - or as methods of Element.


$(element).myOwnMethod([args...]);

Note that this will also works:


Element.myOwnMethod(element|id[, args...]);

To add new methods, simply feed Element.addMethods with a hash of methods. Note that each method's first argument has to be element. Inside each method, remember to pass element to $() and to return it to allow for method chaining if appropriate.

Here's what your hash should look like:


var myVeryOwnElementMethods = {
  myFirstMethod: function(element[, args...]){
    element = $(element);
    // do something
    return element;
  },

  mySecondMethod: function(element[, args...]){
    element = $(element);
    // do something else
    return element;
  }
};

Extending only specific elements (available since v1.5.1)

If you call Element.addMethods with 2 arguments, it will use the first argument for the tag name of the HTML element you want your methods to be applied to.


Element.addMethods('DIV', my_div_methods);
// the methods from the given hash are now available on DIV elements

You can also pass an array of tag names as the first argument:


Element.addMethods(['DIV', 'SPAN'], my_div_methods);
// DIV and SPAN now share the same extensions

Tag names in this first argument are really case-insensitive, but we're writing them in uppercase in these examples to put some weight on them. :)

One last warning before you pursue: Element.addMethods has a built in security which prevents you from overriding native element methods or properties (like getAttribute or innerHTML for instance), but nothing prevents you from overriding one of the frameworks' methods. Prototype uses a lot of its methods internally, so watch where you step!

Examples

Want clean, semantic markup, but need that extra <div> around your element, why not create an Element.wrap('tagName') method which encloses element in the provided tagName and returns the wrapper?


Element.addMethods({
  wrap: function(element, tagName) {
    element = $(element);
    var wrapper = document.createElement('tagName');
    element.parentNode.replaceChild(wrapper, element);
    wrapper.appendChild(element);
    return Element.extend(wrapper);
  }
});

which you'll be able to use like this:


// Before:
<p id="first">Some content...</p>

$(element).wrap('div');
// -> HTMLElement (div)

// After:
<div><p id="first">Some content...</p></div>

As you have thoughtfully decided that your Element.wrap method would return the newly created <div>, ready for prime time thanks to Element.extend, you can immediately chain a new method to it:


$(element).wrap('div').setStyle({backgroundImage: 'url(images/rounded-corner-top-left.png) top left'});

Are you using Ajax.Updater quite a bit around your web application to update DOM elements? Would you want a quick and nifty solution to cut down on the amount of code you are writing ? Try this:


Element.addMethods({
  ajaxUpdate: function(element, url, options){
    element = $(element);
    element.update('<img src="/images/spinner.gif" alt="loading..." />');
    new Ajax.Updater(element, url, options);
    return element;
  }
});

Now, whenever you wish to update the content of an element just do:


$(element).ajaxUpdate('/new/content');
// -> HTMLElement

This method will first replace the content of element with one of those nifty Ajax activity indicator. It will then create a new Ajax.Updater, which in turn will update the content of element with its request result, removing the spinner as it does.

Using Element.addMethods with no argument

There's a last dirty little secret to Element.addMethods. You can can call it without passing it an argument. What happens then? Well, it simply iterates over all of Element.Methods, Element.Methods.Simulated, Form.Methods and Form.Element.Methods and adds them to the relevant DOM elements (Form.Methods only gets added to, well the form element while input, select and textarea elements get extended with Form.Element.Methods).

When could that be usefull?

Imagine that you wish to add a method that deactivates a submit button and replaces its text with something like "Please wait...". You wouldn't want such a method to be applied to any element, would you? So here is how you would go about doing that:


Form.Element.Methods.processing = function(element, text) {
  element = $(element);
  if (element.tagName.toLowerCase() == 'input' && ['button', 'submit'].include(element.type))
    element.value = (text === undefined ? 'Please wait...' : text);
  return element.disable();
};

Element.addMethods();