ฉบับย่อ12 เมษายน 2560
ชาเลนเจอร์ปรากฏขึ้น
var getMatchedCSSRules = (el, css = el.ownerDocument.styleSheets) =>
[].concat(...[...css].map(s => [...s.cssRules||[]]))
.filter(r => el.matches(r.selectorText));
Line /* 1 */
สร้างอาร์เรย์แบบแบนของกฎทั้งหมด
ไลน์/* 2 */
ละทิ้งกฎที่ไม่ตรงกัน
ขึ้นอยู่กับฟังก์ชันcss(el)
โดย @SB ในหน้าเดียวกัน
ตัวอย่าง 1
var div = iframedoc.querySelector("#myelement");
var rules = getMatchedCSSRules(div, iframedoc.styleSheets);
console.log(rules[0].parentStyleSheet.ownerNode, rules[0].cssText);
ตัวอย่าง 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>
ข้อบกพร่อง
- ไม่มีการจัดการสื่อไม่
@import
,@media
,
- ไม่มีการเข้าถึงสไตล์ที่โหลดจากสไตล์ชีตข้ามโดเมน
- ไม่มีการจัดเรียงตามตัวเลือก "ความจำเพาะ" (ลำดับความสำคัญ)
- ไม่มีรูปแบบที่สืบทอดมาจากผู้ปกครอง
- อาจใช้ไม่ได้กับเบราว์เซอร์เก่าหรือเบราว์เซอร์พื้นฐาน
- ไม่แน่ใจว่ามันจัดการกับคลาสหลอกและตัวเลือกหลอกได้อย่างไร แต่ดูเหมือนว่าจะไม่เป็นไร
บางทีฉันอาจจะแก้ไขข้อบกพร่องเหล่านี้ในวันหนึ่ง
ฉบับยาว12 สิงหาคม 2561
นี่คือการใช้งานที่ครอบคลุมมากขึ้นซึ่งนำมาจากหน้า GitHub ของใครบางคน
(แยกจากรหัสเดิมนี้ผ่านทางBugzilla ) เขียนขึ้นสำหรับ Gecko และ IE แต่มีข่าวลือว่าจะทำงานร่วมกับ Blink
4 พฤษภาคม 2017:เครื่องคำนวณความจำเพาะมีจุดบกพร่องที่สำคัญซึ่งตอนนี้ฉันได้แก้ไขแล้ว (ฉันไม่สามารถแจ้งผู้เขียนได้เนื่องจากฉันไม่มีบัญชี GitHub)
12 สิงหาคม 2018:การอัปเดต Chrome ล่าสุดดูเหมือนว่าจะมีการแยกขอบเขตออบเจ็กต์ ( this
) ออกจากวิธีการที่กำหนดให้กับตัวแปรอิสระ ดังนั้นการร้องขอmatcher(selector)
จึงหยุดทำงาน การแทนที่โดยmatcher.call(el, selector)
ได้แก้ไขแล้ว
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);
};
}
แก้ไขข้อบกพร่อง
= match
→ += match
return re ? re.length : 0;
→ return matches ? matches.length : 0;
_matchesSelector(element, selector)
→ matchesSelector(element, selector)
matcher(selector)
→ matcher.call(el, selector)