95 lines
2.5 KiB
JavaScript
95 lines
2.5 KiB
JavaScript
var Slick = require('./slick/Source/slick').Slick;
|
|
var CSS = require('./sheet.js/Source/SheetParser.CSS').SheetParser.CSS;
|
|
|
|
function calculateSpecificity(expression){
|
|
var specificity = 0;
|
|
for (var i = 0, l = expression.length; i < l; i++){
|
|
var part = expression[i];
|
|
if (part.id) specificity += 10000;
|
|
if (part.classes) specificity += part.classes.length * 1000;
|
|
if (part.pseudos) specificity += part.pseudos.length * 1000;
|
|
if (part.attributes) specificity += part.attributes.length * 1000;
|
|
if (part.tag && part.tag != '*') specificity += 100;
|
|
}
|
|
return specificity;
|
|
};
|
|
|
|
function sortRules(rules){
|
|
rules.sort(function(a,b){
|
|
if (a.specificity < b.specificity)
|
|
return -1;
|
|
else if (a.specificity > b.specificity)
|
|
return 1;
|
|
return 0;
|
|
});
|
|
};
|
|
|
|
function nodeContent(node){
|
|
var n = node.firstChild, text = '';
|
|
while (n){
|
|
text += n.nodeValue;
|
|
n = n.nextSibling;
|
|
}
|
|
return text;
|
|
}
|
|
|
|
var SheetCascade = function(){
|
|
this.rules = [];
|
|
this.cssRules = [];
|
|
};
|
|
|
|
SheetCascade.prototype = {
|
|
|
|
addSheet: function(sheet){
|
|
var rules = sheet.cssRules || CSS.parse(sheet.innerHTML || nodeContent(sheet) || sheet);
|
|
for (var i = 0, l = rules.length; i < l; i++){
|
|
var rule = rules[i];
|
|
this.cssRules.push(rule);
|
|
this.addRule(rule.selectorText, rule.style);
|
|
}
|
|
},
|
|
|
|
addRule: function(selector, style){
|
|
var parsed = Slick.parse(selector);
|
|
if (!parsed) return;
|
|
var expressions = parsed.expressions;
|
|
for (var i = 0, l = expressions.length; i < l; i++){
|
|
var expression = expressions[i],
|
|
specificity = calculateSpecificity(expression) + this.rules.length;
|
|
this.rules.push({
|
|
specificity: specificity,
|
|
expression: expression,
|
|
style: style
|
|
});
|
|
}
|
|
this.sorted = false;
|
|
},
|
|
|
|
getStyle: function(node){
|
|
var style = {};
|
|
this.applyStyle(node, style);
|
|
return style;
|
|
},
|
|
|
|
applyStyle: function(node, targetStyle){
|
|
var rules = this.rules;
|
|
if (!this.sorted){ sortRules(rules); this.sorted = true; }
|
|
|
|
for (var i = 0, l = rules.length; i < l; i++){
|
|
var rule = rules[i];
|
|
if (Slick.match(node, { Slick: true, expressions: [rule.expression] })){
|
|
var ruleStyle = rule.style;
|
|
for (var name in ruleStyle) targetStyle[name] = ruleStyle[name];
|
|
}
|
|
}
|
|
|
|
var cssText = node.getAttribute('style');
|
|
if (cssText){
|
|
var inlineStyle = CSS.parse(cssText);
|
|
for (var name in inlineStyle) targetStyle[name] = inlineStyle[name];
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
exports.SheetCascade = SheetCascade; |