Versi pendek 12 April 2017
Challenger muncul.
var getMatchedCSSRules = (el, css = el.ownerDocument.styleSheets) =>
[].concat(...[...css].map(s => [...s.cssRules||[]]))
.filter(r => el.matches(r.selectorText));
Garis /* 1 */membangun larik datar dari semua aturan.
Garis/* 2 */ membuang aturan yang tidak cocok.
Berdasarkan fungsinyacss(el) @SB di halaman yang sama.
Contoh 1
var div = iframedoc.querySelector("#myelement");
var rules = getMatchedCSSRules(div, iframedoc.styleSheets);
console.log(rules[0].parentStyleSheet.ownerNode, rules[0].cssText);
Contoh 2
var getMatchedCSSRules = (el, css = el.ownerDocument.styleSheets) =>
[].concat(...[...css].map(s => [...s.cssRules||[]]))
.filter(r => el.matches(r.selectorText));
function Go(big,show) {
var r = getMatchedCSSRules(big);
PrintInfo:
var f = (dd,rr,ee="\n") => dd + rr.cssText.slice(0,50) + ee;
show.value += "--------------- Rules: ----------------\n";
show.value += f("Rule 1: ", r[0]);
show.value += f("Rule 2: ", r[1]);
show.value += f("Inline: ", big.style);
show.value += f("Computed: ", getComputedStyle(big), "(…)\n");
show.value += "-------- Style element (HTML): --------\n";
show.value += r[0].parentStyleSheet.ownerNode.outerHTML;
}
Go(...document.querySelectorAll("#big,#show"));
.red {color: red;}
#big {font-size: 20px;}
<h3 id="big" class="red" style="margin: 0">Lorem ipsum</h3>
<textarea id="show" cols="70" rows="10"></textarea>
Kekurangan
- Tidak ada penanganan media, tidak
@import,@media .
- Tidak ada akses ke gaya yang dimuat dari stylesheet lintas domain.
- Tidak ada pengurutan berdasarkan “kekhususan” pemilih (urutan kepentingan).
- Tidak ada gaya yang diwarisi dari orang tua.
- Mungkin tidak berfungsi dengan browser lama atau yang belum sempurna.
- Tidak yakin bagaimana cara mengatasi pseudo-class dan pseudo-selector tetapi tampaknya berjalan dengan baik.
Mungkin saya akan membahas kekurangan ini suatu hari nanti.
Versi panjang 12 Agustus 2018
Berikut implementasi yang jauh lebih komprehensif yang diambil dari halaman GitHub seseorang
(bercabang dari kode asli ini , melalui Bugzilla ). Ditulis untuk Gecko dan IE, tetapi dikabarkan bekerja juga dengan Blink.
4 Mei 2017: Kalkulator kekhususan memiliki bug kritis yang sekarang telah saya perbaiki. (Saya tidak dapat memberi tahu penulis karena saya tidak memiliki akun GitHub.)
12 Agustus 2018: Pembaruan Chrome terbaru tampaknya telah memisahkan cakupan objek ( this) dari metode yang ditetapkan ke variabel independen. Oleh karena itu, permintaan matcher(selector)berhenti bekerja. Menggantinya dengan matcher.call(el, selector)telah menyelesaikannya.
if (typeof window.getMatchedCSSRules !== 'function') {
var ELEMENT_RE = /[\w-]+/g,
ID_RE = /#[\w-]+/g,
CLASS_RE = /\.[\w-]+/g,
ATTR_RE = /\[[^\]]+\]/g,
PSEUDO_CLASSES_RE = /\:(?!not)[\w-]+(\(.*\))?/g,
PSEUDO_ELEMENTS_RE = /\:\:?(after|before|first-letter|first-line|selection)/g;
function toArray(list) {
return [].slice.call(list);
}
function getSheetRules(stylesheet) {
var sheet_media = stylesheet.media && stylesheet.media.mediaText;
if ( stylesheet.disabled ) return [];
if ( sheet_media && sheet_media.length && ! window.matchMedia(sheet_media).matches ) return [];
return toArray(stylesheet.cssRules);
}
function _find(string, re) {
var matches = string.match(re);
return matches ? matches.length : 0;
}
function calculateScore(selector) {
var score = [0,0,0],
parts = selector.split(' '),
part, match;
while (part = parts.shift(), typeof part == 'string') {
match = _find(part, PSEUDO_ELEMENTS_RE);
score[2] += match;
match && (part = part.replace(PSEUDO_ELEMENTS_RE, ''));
match = _find(part, PSEUDO_CLASSES_RE);
score[1] += match;
match && (part = part.replace(PSEUDO_CLASSES_RE, ''));
match = _find(part, ATTR_RE);
score[1] += match;
match && (part = part.replace(ATTR_RE, ''));
match = _find(part, ID_RE);
score[0] += match;
match && (part = part.replace(ID_RE, ''));
match = _find(part, CLASS_RE);
score[1] += match;
match && (part = part.replace(CLASS_RE, ''));
score[2] += _find(part, ELEMENT_RE);
}
return parseInt(score.join(''), 10);
}
function getSpecificityScore(element, selector_text) {
var selectors = selector_text.split(','),
selector, score, result = 0;
while (selector = selectors.shift()) {
if (matchesSelector(element, selector)) {
score = calculateScore(selector);
result = score > result ? score : result;
}
}
return result;
}
function sortBySpecificity(element, rules) {
function compareSpecificity (a, b) {
return getSpecificityScore(element, b.selectorText) - getSpecificityScore(element, a.selectorText);
}
return rules.sort(compareSpecificity);
}
function matchesSelector(el, selector) {
var matcher = el.matchesSelector || el.mozMatchesSelector ||
el.webkitMatchesSelector || el.oMatchesSelector || el.msMatchesSelector;
return matcher.call(el, selector);
}
window.getMatchedCSSRules = function (element ) {
var style_sheets, sheet, sheet_media,
rules, rule,
result = [];
style_sheets = toArray(window.document.styleSheets);
while (sheet = style_sheets.shift()) {
rules = getSheetRules(sheet);
while (rule = rules.shift()) {
if (rule.styleSheet) {
rules = getSheetRules(rule.styleSheet).concat(rules);
continue;
}
else if (rule.media) {
rules = getSheetRules(rule).concat(rules);
continue
}
if (matchesSelector(element, rule.selectorText)) {
result.push(rule);
}
}
}
return sortBySpecificity(element, result);
};
}
Memperbaiki bug
= match → += match
return re ? re.length : 0; → return matches ? matches.length : 0;
_matchesSelector(element, selector) → matchesSelector(element, selector)
matcher(selector) → matcher.call(el, selector)