4Aug/1117
jQuery – copy style (copyCSS)
UPDATE: this is now available in the jQuery plugin repository: http://plugins.jquery.com/project/copyCSS
In response to the surprising popularity of my very simple getStyleObject method, here's a slight update, and another extension to simplify copying styles to another element.
First, the updated method to get back all styles (inherited, native, descended, inline, etc) of the invoking element:
$.fn.getStyleObject = function(){
var dom = this.get(0);
var style;
var returns = {};
if(window.getComputedStyle){
var camelize = function(a,b){
return b.toUpperCase();
};
style = window.getComputedStyle(dom, null);
for(var i = 0, l = style.length; i < l; i++){
var prop = style[i];
var camel = prop.replace(/\-([a-z])/g, camelize);
var val = style.getPropertyValue(prop);
returns[camel] = val;
};
return returns;
};
if(style = dom.currentStyle){
for(var prop in style){
returns[prop] = style[prop];
};
return returns;
};
if(style = dom.style){
for(var prop in style){
if(typeof style[prop] != 'function'){
returns[prop] = style[prop];
};
};
return returns;
};
return returns;
}
And the helper to copy (all styles of @source are passed to invoker):
$.fn.copyCSS = function(source){
var styles = $(source).getStyleObject();
this.css(styles);
}
Or all in one:
$.fn.copyCSS = function(source){
var dom = $(source).get(0);
var style;
var dest = {};
if(window.getComputedStyle){
var camelize = function(a,b){
return b.toUpperCase();
};
style = window.getComputedStyle(dom, null);
for(var i = 0, l = style.length; i < l; i++){
var prop = style[i];
var camel = prop.replace(/\-([a-z])/g, camelize);
var val = style.getPropertyValue(prop);
dest[camel] = val;
};
return this.css(dest);
};
if(style = dom.currentStyle){
for(var prop in style){
dest[prop] = style[prop];
};
return this.css(dest);
};
if(style = dom.style){
for(var prop in style){
if(typeof style[prop] != 'function'){
dest[prop] = style[prop];
};
};
};
return this.css(dest);
};
// usage...
// $('#my-element').copyCSS('#another-element');
// or...
// $('#my-element').copyCSS(someReferenceToAnElement);
[wrapping this in (function($){})(jQuery) does not count as writing a plugin - tsk tsk] :)
August 19th, 2011 - 09:19
Wowee!
that saved me much work! Would have saved me a whooole lot if I’d found it earlier, too! thanks for putting this together, it’s invlauable.
August 19th, 2011 - 13:29
Glad it helped!
September 30th, 2011 - 02:43
Hi,
I would like to use this in a project, but as we have strict rules around licences for snippets copied from blog posts etc at work, I need to know whether you’d consider releasing it under a permissible licence that would allow me to use it for commercial work (MIT or similar is fine).
PC
September 30th, 2011 - 03:40
Sure thing. Just link up this page in the comments.
February 3rd, 2012 - 21:53
Nice snippet, but it seems to mess up JQuery version 1.7.1
line 12: var camel = prop.replace(/\-([a-z])/g, camelize);
The above line causes an error: “prop.replace is not a function”
If you change it to: var camel = prop.toString().replace(/\-([a-z])/g, camelize);
It then removes the error but the errors occur in the JQuery’s file where .replace is used. Not sure if this is a JQuery error though
February 4th, 2012 - 09:35
Hmm.. Thanks for pointing that out – so toString suppresses the local error but doesn’t fix the problem? I’ll take a look – feel free to post back if you find a fix.
February 4th, 2012 - 10:04
I just ran a quick test on jsfiddle (http://jsfiddle.net/b9sN7/1/) and it seems to be working fine… I’m guessing that there was something else wrong with the script that produced the error you’re talking about (possibly an unmatched selector?). If you want to post the code, I’d be happy to take a look
February 7th, 2012 - 08:36
This is exactly what I’ve been looking for for the past 2 hours this morning. THANK YOU! Unfortunately, it looks like some overzealous DBA* has purged the Plugin site so your plugin doesn’t exist there at the moment. Are you planning on re-submitting?
* Not criticizing – I’ve done the same thing plenty of times.
February 7th, 2012 - 10:11
Glad it could help. AFAIK the plugin site is still down (I think they’re moving to a different CMS or host…) When it’s back up I’ll likely resubmit.
March 30th, 2012 - 11:48
=/
Since when are if() conditions made with single “=” ..its if (x == y)..
March 31st, 2012 - 09:55
actually, what’s posted is correct. if you used evaluation there (as you suggest), it’d fail. the concept demonstrated is pretty simple.
instead of saying:
var style = dom.currentStyle; if(style != null) { // ...you can condense it into a single line:
if(style = dom.currentStyle) { // ...This construct is used in many languages… You’ll see this in Java quite a bit, for example:
while((someVariable = someMethod()) != null) { // do stuff with someVariableApril 28th, 2012 - 05:17
anyway, you need to describe variable in local scope. so you must
var style;before you use style variable
April 28th, 2012 - 14:18
again, there’s no mistake here.
can be found on line 3.
May 17th, 2012 - 08:05
Opera seems to have a bit of trouble with the prop loop (0 length) and some inline properties (eg style=”float:right;” isn’t seen)..?
May 17th, 2012 - 11:07
Interesting, thanks for pointing that out. I don’t do much with Opera personally – if you have any suggested fixes, please post.
May 18th, 2012 - 06:16
Can’t say I use Opera much either, but it was in my test batch ;)
There’s 2 problems with Opera: the lenght of the style object is 0, and it doesn’t seem to support getPropertyValue (or it does but not like the other browsers do anyway).
So here’s a quick hack that that i’ve tested in FF, IE7-9, chrome/safari, opera. There’s probably a better way of writing it but it ‘just works’. line 10, replace:
for(var i = 0, l = style.length; i < l; i++){ var prop = style[i]; var camel = prop.replace(/\-([a-z])/g, camelize); var val = style.getPropertyValue(prop); dest[camel] = val; };With:
if (style.length) for(var i = 0, l = style.length; i < l; i++){ var prop = style[i]; var camel = prop.replace(/\-([a-z])/, camelize); var val = style.getPropertyValue(prop); returns[camel] = val; } else for(var prop in style){ var camel = prop.replace(/\-([a-z])/, camelize); var val = style.getPropertyValue(prop) || style[prop]; returns[camel] = val; }The first block is your code unchanged, and 2nd block is slightly modified for opera.
Your function has saved me a lot of time btw, thanks a lot for sharing!
May 18th, 2012 - 11:12
Very cool – thanks for the fix. I’ll try to integrate your changes in the next couple days.