Brian
Brian

Reputation: 25834

Detecting if a style is a user style

After calling window.getComputedStyle, how can I tell whether a style a style is from the page itself (rather than being from the browser)? I'm interested in doing so in pure javascript, though I would settle for a solution which ran in the context of an add-on.

Upvotes: 0

Views: 156

Answers (2)

Wladimir Palant
Wladimir Palant

Reputation: 57681

You will have a hard time figuring out where the rules that getComputedStyle gives you came from. Note that the code provided by MaxArt isn't a complete solution - there are also inherited styles so one would have to repeat everything for parent nodes. The simpler approach would be using inIDOMUtils.getCSSStyleRules(), along these lines:

function isPageStyle(styleSheet)
{
  if (styleSheet.ownerNode)
    return true;

  if (styleSheet.ownerRule instanceof Components.interfaces.nsIDOMCSSImportRule)
    return isPageStyle(styleSheet.parentStyleSheet);

  return false;
}

var domUtils = Components.classes["@mozilla.org/inspector/dom-utils;1"]
                         .getService(Components.interfaces.inIDOMUtils);
var rules = domUtils.getCSSStyleRules(element);
for (var i = 0; i < rules.Count(); i++)
{
  var rule = rules.GetElementAt(i);
  if (isPageStyle(rule.parentStyleSheet))
    alert(rule.cssText);
}

You will have to do it for the parent nodes as well. For a complete example you can look at the implementation of the Inspector feature in Firefox (isPageStyle function in my answer shamelessly "borrowed" from here).

Upvotes: 1

MaxArt
MaxArt

Reputation: 22637

Unless you want to parse every stylesheet in the document, you can't. If you have issues with the style every browser applies to the elements by default, you can rely on something like Reset CSS.

If you want to parse the stylesheets, anyway, you can do something like this:

function isDefaultStyle(element, property) {
    if (element.style[property]) return false;
    for (var i = 0; i < document.styleSheets.length; i++) {
        for (var j = 0, r; j < document.styleSheets[i].cssRules.length; j++) {
            r = document.styleSheets[i].cssRules[j];
            if (element.matchesSelector(r.selectorText) && r[property]) return false;
        }
    }
    return true;
}

matchesSelector is an element method that isn't actually supported by any browsers, which actually support namespaced functions like webkitMatchesSelector, mozMatchesSelector, oMatchesSelector and even msMatchesSelector (IE9+). Sadly, for IE8 you have to emulate it and I couldn't find anything better than checking if the elements is contained in document.querySelectorAll(r.selectorText), which can be very slow for large DOM trees.

In this last case, you also obviously have to use rules instead of cssRules.

Upvotes: 0

Related Questions