Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
192
rated 0 times [  195] [ 3]  / answers: 1 / hits: 50123  / 12 Years ago, sat, may 26, 2012, 12:00:00

I'd like to:




  1. Find a style attribute for all elements in the page (for instance: all elements that have color:#333;)

  2. Change this attribute for all of them (for instance from color:#333 to color:#444).



Do you have any suggestion on doing so?


More From » css

 Answers
14

My suggestion is avoid doing this if at all remotely possible. Instead, use a class to assign the color value, and then you can look up the elements using the class, rather than the color value.



As far as I'm aware, there's no selector (not even in CSS3) that you can use to query a specific style value, which means looping through all elements (or it looks like you can restrict it to all elements with a style attribute) and looking at the element.style.color property. Now, the thing is, even though you write color: #333; in your style attribute, different browsers will echo it back to you in different ways. It might be #333, it might be #333333, it might be rgb(51, 51, 51), it might even be rgba(51, 51, 51, 0).



So on the whole, a very awkward exercise indeed.






Since you've said this is for a Chrome extension, you probably don't have to worry as much about multiple formats, although I'd throw in the ones that we've seen in the wild in case Chrome changes the format (perhaps to be consistent with some other browser, which has been known to happen).



But for instance:



(function() {

// Get all elements that have a style attribute
var elms = document.querySelectorAll(*[style]);

// Loop through them
Array.prototype.forEach.call(elms, function(elm) {
// Get the color value
var clr = elm.style.color || ;

// Remove all whitespace, make it all lower case
clr = clr.replace(/s/g, ).toLowerCase();

// Switch on the possible values we know of
switch (clr) {
case #333:
case #333333:
case rgb(51,51,51): // <=== This is the one Chrome seems to use
case rgba(51,51,51,0):
elm.style.color = #444;
break;
}
});
})();


Live example using red for clarity | source - Note that the example relies on ES5 features and querySelectorAll, but as this is Chrome, I know they're there.



Note that the above assumes inline style, because you talked about the style attribute. If you mean computed style, then there's nothing for it but to loop through all elements on the page calling getComputedStyle. Other than that, the above applies.



Final note: If you really meant a style attribute with precisely the value color: #333 and not the value color:#333 or color:#333333; or color: #333; font-weight: bold or any other string, your querySelectorAll could handle that: querySelectorAll('*[style=color: #333]'). But it would be very fragile.






From your comment below, it sounds like you're having to go through every element. If so, I wouldn't use querySelectorAll at all, I'd use recursive descent:



function walk(elm) {
var node;

// ...handle this element's `style` or `getComputedStyle`...

// Handle child elements
for (node = elm.firstChild; node; node = node.nextSibling) {
if (node.nodeType === 1) { // 1 == Element
walk(node);
}
}
}

// Kick it off starting with the `body` element
walk(document.body);


That way you don't build up large, unnecessary temporary structures. This is probably the most efficient way to walk the entire DOM of a document.


[#85332] Friday, May 25, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
jazminkyrap

Total Points: 631
Total Questions: 89
Total Answers: 109

Location: Finland
Member since Fri, Oct 21, 2022
2 Years ago
;