views:

90

answers:

4

I've developed a few jQuery plugins before which follow the format of either $('#something').myPlugin() or $.myPlugin().

I know you can also write your own selectors.

What I was wondering if I could write a plugin that changes how the css() method works, that is, if I request a shorthand CSS attribute (such as padding) I could return something like this

return $(this).css('padding-top') + ' ' + $(this).css('padding-right') + ' ' + $(this).css('padding-bottom') + ' ' + $(this).css('padding-left');

Is this possible? How would I do it if so?

Thanks

A: 

You can override the default jQuery methods by creating plugins with the same name.

There's some more info about this over at Ask Ben.

jQuery is such a well thought out, powerful Javascript library, that it actually uses itself to build itself. What I mean by that is that many of the methods provided by the jQuery library are actually built internally as plugins to the jQuery architecture. When you start to think about the methods in this way, it is a small leap to see that we can override a given jQuery method by simply creating a new plugin of the same name.

Jamie Dixon
+1  A: 

Essentially, you would need to replace the jQuery method. Extreme caution advised, as you could break many things that rely on this method. Best off to choose a different name.

Consider this concept:

jQuery.fn.css_orig = jQuery.fn.css

jQuery.fn.css = function(arg1, arg2) {
    if(arg1 == 'what-I-want')
    { 
        return my_thing;
    } 
    else
    {
        return this.css_orig(arg1, arg2);
    }
};

In the case of .css, I think you could (if you were very careful) retain 100% of the functionality of the .css method, while adding your functionality on top.

Cool idea, none the less!

gahooa
That's really not safe. If any other (plugin) method is relying on the `css` method returning an empty string for invalid properties and you start defining those properties, you're going to break other people's code.
Justin Johnson
@Justin Johnson: He asked how, and I advised him how (along with a good dose of warning). Of course it's not a "good idea".
gahooa
A: 

Why not create a user defined function in your application namespace that does what you want (your custom business rules)?

By the example, I don't see many use of this function outside your current application...

My 2 cents

EDIT: Hi Alex, does the already built-in function could help you?

Shorthand CSS properties (e.g. margin, background, border) are not supported. For example, if you want to retrieve the rendered margin, use: $(elem).css('marginTop') and $(elem).css('marginRight'), and so on.

I guess you could do the same with the padding?

http://docs.jquery.com/CSS/css#name

Mike Gleason jr Couturier
I would of thought getting CSS shorthand could be handy to some people besides me?
alex
@alex It could be, just as a separate plugin
Justin Johnson
+2  A: 

It is possible, but its use in production should be avoided at all costs.

Changing the core functionality of a library that is so often used in tandem with multiple plugins is a bad, dangerous, and bad-and-dangerous idea.

It may be possible for you to cause the overwritten method to interface and behave in its original way and to only behave differently for a subset of parameters; however, in subsequent releases of the library, if this core method changes, you may, in short, be screwed and have to revisit the overwritten method.

It's best to use a different method name. Perhaps, for your uses, you can use style , xCss, cssExt, or something along those lines.

If you're looking for one method to combine the functionality of both your method and the core method, then it is best to take the opposite approach. Instead of overwriting the core method, wrap it with additional functionality, and of course, a new name.

jQuery.fn.xCss = (function() {
    var compoundProperties = {
        'padding':    ['padding-top', 'padding-right' ...],
        'border':     ['border-width', 'border-style', ...],
        'background': ['background-color', ...],
        ...
    };

    return function(property, value) {
        // Use plugin functionality
        if ( compoundProperties.hasOwnPropery(property) ) { 
            // Get value
            if ( !value ) {
                var propertySet = compoundProperties[property],
                    result      = [];

                for ( var i=0, l=propertySet.length; i<l; ++i ) {
                    result.push( this.css(propertySet[i]) );
                }

                return result.join(" ");
            }

            // Set value
            ...
            return this;
        }

        // Use core functionality
        return this.css.apply(this, arguments);
    };
})();

* Code not tested or complete.

Justin Johnson