nntrn
9/27/2019 - 3:28 AM

Fetching an Elements' Declared Styles Demo

Fetching an Elements' Declared Styles Demo

Fetching an Elements' Declared Styles Demo

A Pen by Rob Gravelle on CodePen.

License.

<div>
  <h1>Fetching an Elements Declared Styles Demo</h1>
</div>
<hr/>
<div id="container">
  <p id="lorem" style="line-height: 20px;">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mi velit, pulvinar in pellentesque vel, commodo vel tortor. Maecenas quis risus fringilla, sodales eros at, fringilla lorem. Vivamus ultricies turpis non est varius, vel commodo purus ultrices.
    Aliquam suscipit neque libero, sed vehicula ex aliquam sed. Aliquam sollicitudin risus ut leo venenatis molestie. Phasellus rhoncus pellentesque tellus vitae consectetur. Suspendisse a maximus ex, sit amet tincidunt erat. Phasellus fermentum porttitor
    felis nec hendrerit. Aenean a purus vel diam malesuada tempor sed ut lorem. Duis congue sagittis rhoncus. Aliquam tempor condimentum malesuada. Curabitur euismod dolor lacus, eget aliquam purus auctor sodales.
  </p>
</div>
<hr/>
<hr/>
<div>
  <button id="showStyles" type="button">Show me styles on `p`</button>
  <br/>
  <code id="code">
    </code>
</div>
document.getElementById('showStyles').onclick = function () {
  const $lorem = document.getElementById('lorem')
  const $code = document.getElementById('code')
  const rules = MEJSX.getCustomCssRulesOnElement($lorem)
  console.log(rules)

  for (let i = 0; i < rules.length; i++) {
    $code.innerText += `\n\n//Order: ${rules[i].order
    } | Media:${rules[i].media}\n${
      rules[i].content}`
  }
}

const MEJSX = (function () {
  const getCustomCssRulesOnElement = function (elm) {
    const elementRules = []
    const slice = Function.call.bind(Array.prototype.slice)

    const isCssMediaRule = function (cssRule) {
      return cssRule.type === cssRule.MEDIA_RULE // cssRule.getName() === 'CSSMediaRule';
    }

    const mediaRuleMatchesDocument = function (cssRule) {
      const match = window.matchMedia(cssRule.media.mediaText).matches
      if (!match) console.log(`${cssRule.media.mediaText} does not apply to doc.`)
      return match
    }

    const isCssStyleRule = function (cssRule) {
      return cssRule.type === cssRule.STYLE_RULE // cssRule.getName() === 'CSSStyleRule';
    }

    // Here we get the cssRules across all the stylesheets in one array
    let cssRules = slice(document.styleSheets).reduce((rules, styleSheet) => rules.concat(slice(styleSheet.cssRules)), [])

    const mediaRules = cssRules.filter(isCssMediaRule)
      .filter(mediaRuleMatchesDocument)

    cssRules = cssRules.filter(isCssStyleRule)
    cssRules = cssRules.concat(slice(mediaRules).reduce((rules, mediaRule) => rules.concat(slice(mediaRule.cssRules)), []))

    console.log(cssRules)

    // get only the css rules that matches that element
    const rulesOnElement = cssRules.filter(isElementMatchWithCssRule.bind(null, elm))
    const elementRule = function (order, content, media) {
      if (media === undefined || media == null || media == '') {
        media = 'all'
      }
      this.order = order
      this.content = content
      this.media = media
    }
    if (rulesOnElement.length) {
      for (let i = 0; i < rulesOnElement.length; i++) {
        const e = rulesOnElement[i]
        const order = i
        const content = e.cssText
        const media = !(e.parentRule && e.parentStyleSheet) && 'all' || (e.parentStyleSheet.media.mediaText || e.parentRule.media.mediaText)

        let _elementRule = new elementRule(order, content, media)
        elementRules.push(_elementRule)
      }
    }

    if (elm.getAttribute('style')) {
      const _elementRule = new elementRule(rulesOnElement.length, `style {${elm.getAttribute('style')}}`)
      elementRules.push(_elementRule)
    }
    return elementRules
  }

  const isElementMatchWithCssRule = function (element, cssRule) {
    const proto = Element.prototype
    const matches = Function.call.bind(proto.matchesSelector
      || proto.mozMatchesSelector || proto.webkitMatchesSelector
      || proto.msMatchesSelector || proto.oMatchesSelector)
    return matches(element, cssRule.selectorText)
  }

  return {
    getCustomCssRulesOnElement(element) {
      return getCustomCssRulesOnElement(element)
    },
  }
}())


function showStyles(element) {
  const rules = MEJSX.getCustomCssRulesOnElement(element)
  console.log(rules)
}

showStyles(document.getElementById("container"))
console.log(showStyles(document.body))
 p {
   color: #cccccc;
 }
 
 #lorem {
   font-weight: bold;
 }
 
 @media (min-width: 300px),
 (min-device-width: 350px) {
   p {
     margin: 0;
   }
   #lorem {
     border: 1px solid #000000;
   }
   h1 {
     color: #000000;
   }
 }

@media (max-width: 600px) {
  #lorem {
     border: 1px solid #000000;
   }
}