aboutsummaryrefslogtreecommitdiff
path: root/js/controllers/styles-controller.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/controllers/styles-controller.js')
-rwxr-xr-xjs/controllers/styles-controller.js121
1 files changed, 100 insertions, 21 deletions
diff --git a/js/controllers/styles-controller.js b/js/controllers/styles-controller.js
index ae504f0e..00d67b89 100755
--- a/js/controllers/styles-controller.js
+++ b/js/controllers/styles-controller.js
@@ -82,6 +82,11 @@ var stylesController = exports.StylesController = Montage.create(Component, {
82 ///// If the document is null set default stylesheets to null 82 ///// If the document is null set default stylesheets to null
83 83
84 if(!document) { 84 if(!document) {
85 this._activeDocument = null;
86 this._stageStylesheet = null;
87 this.defaultStylesheet = null;
88 this.userStyleSheets = [];
89 this.clearDirtyStyleSheets();
85 return false; 90 return false;
86 } 91 }
87 92
@@ -93,11 +98,18 @@ var stylesController = exports.StylesController = Montage.create(Component, {
93 // Returns null if sheet not found (as in non-ninja projects) 98 // Returns null if sheet not found (as in non-ninja projects)
94 // Setter will handle null case 99 // Setter will handle null case
95 this.defaultStylesheet = this.getSheetFromElement(this.CONST.DEFAULT_SHEET_ID); 100 this.defaultStylesheet = this.getSheetFromElement(this.CONST.DEFAULT_SHEET_ID);
96 101
97 //debugger; 102 this.userStyleSheets = nj.toArray(document._document.styleSheets).filter(function(sheet) {
103 return sheet !== this._stageStylesheet;
104 }, this);
105
106 NJevent('styleSheetsReady', this);
98 }, 107 },
99 enumerable : false 108 enumerable : false
100 }, 109 },
110 userStyleSheets : {
111 value : null
112 },
101 _stageStylesheet : { 113 _stageStylesheet : {
102 value : null 114 value : null
103 }, 115 },
@@ -112,7 +124,10 @@ var stylesController = exports.StylesController = Montage.create(Component, {
112 if(sheet) { 124 if(sheet) {
113 this._defaultStylesheet = sheet; 125 this._defaultStylesheet = sheet;
114 } else { 126 } else {
115 127 if(sheet === null) {
128 this._defaultStylesheet = null;
129 return false;
130 }
116 ///// Use the last stylesheet in the document as the default 131 ///// Use the last stylesheet in the document as the default
117 132
118 var sheets = this._activeDocument._document.styleSheets, 133 var sheets = this._activeDocument._document.styleSheets,
@@ -158,13 +173,17 @@ var stylesController = exports.StylesController = Montage.create(Component, {
158 173
159 addRule : { 174 addRule : {
160 value : function(selector, declaration, stylesheet, index) { 175 value : function(selector, declaration, stylesheet, index) {
161 //console.log("Add rule"); 176 stylesheet = stylesheet || this._defaultStylesheet;
177
178 if(stylesheet === null) {
179 stylesheet = this.defaultStylesheet = this.createStylesheet();
180 }
181
162 var rulesLength = this._defaultStylesheet.rules.length, 182 var rulesLength = this._defaultStylesheet.rules.length,
163 argType = (typeof declaration), 183 argType = (typeof declaration),
164 ruleText = selector, 184 ruleText = selector,
165 stylesheet = stylesheet || this._defaultStylesheet, 185 rule;
166 property, rule; 186
167
168 index = index || (argType === 'number') ? declaration : rulesLength; 187 index = index || (argType === 'number') ? declaration : rulesLength;
169 188
170 if(argType === 'string') { 189 if(argType === 'string') {
@@ -182,6 +201,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
182 ///// attach specificity to rule object 201 ///// attach specificity to rule object
183 ///// if rule is css keyframes, return rule and don't attach specificity 202 ///// if rule is css keyframes, return rule and don't attach specificity
184 if (rule instanceof WebKitCSSKeyframesRule) { 203 if (rule instanceof WebKitCSSKeyframesRule) {
204
185 return rule; 205 return rule;
186 } 206 }
187 rule[this.CONST.SPECIFICITY_KEY] = this.getSpecificity(rule.selectorText); 207 rule[this.CONST.SPECIFICITY_KEY] = this.getSpecificity(rule.selectorText);
@@ -208,10 +228,12 @@ var stylesController = exports.StylesController = Montage.create(Component, {
208 } 228 }
209 229
210 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride), 230 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride),
211 overrideData, rule; 231 overrideData, rule, isRuleLocked;
232
233 isRuleLocked = this.isSheetLocked(ruleToOverride.parentStyleSheet);
212 234
213 ///// Get the overriding selector and className 235 ///// Get the overriding selector and className
214 overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName); 236 overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName, isRuleLocked);
215 237
216 ///// Create new rule with selector and insert it after the rule we're overriding 238 ///// Create new rule with selector and insert it after the rule we're overriding
217 rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1); 239 rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1);
@@ -225,7 +247,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
225 }, 247 },
226 248
227 createOverrideSelector : { 249 createOverrideSelector : {
228 value: function(selectorToOverride, classPrefix, className) { 250 value: function(selectorToOverride, classPrefix, increaseSpecificity, className) {
229 var tokens = selectorToOverride.split(/\s/), 251 var tokens = selectorToOverride.split(/\s/),
230 newClass = className || this.generateClassName(classPrefix, true), 252 newClass = className || this.generateClassName(classPrefix, true),
231 lastToken, pseudoSplit, base, pseudo, newToken, newSelector; 253 lastToken, pseudoSplit, base, pseudo, newToken, newSelector;
@@ -246,10 +268,19 @@ var stylesController = exports.StylesController = Montage.create(Component, {
246 if(base.indexOf('#') !== -1) { 268 if(base.indexOf('#') !== -1) {
247 newToken = base + '.' + newClass + pseudo; 269 newToken = base + '.' + newClass + pseudo;
248 } else { 270 } else {
249 ///// Replace last class or attribute selector 271 if(increaseSpecificity) {
250 ///// Get everything right before the last class or attribute selector 272 ///// Increases specificity by one class selector
251 ///// to support compound selector values: (i.e. .firstClass.secondClass) 273 ///// We'll do a direct append to the base class
252 newToken = base.substring(0, Math.max(base.lastIndexOf('.'), base.lastIndexOf('['))); 274 ///// if we want to increase the specificity
275 newToken = base;
276 } else {
277 ///// Maintains original specificity
278 ///// Replace last class or attribute selector
279 ///// Get everything right before the last class or attribute selector
280 ///// to support compound selector values: (i.e. .firstClass.secondClass)
281 newToken = base.substring(0, Math.max(base.lastIndexOf('.'), base.lastIndexOf('[')));
282 }
283
253 ///// Append the generated class 284 ///// Append the generated class
254 newToken += '.' + newClass + pseudo; 285 newToken += '.' + newClass + pseudo;
255 } 286 }
@@ -794,7 +825,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
794 ///// method to apply/test the new value 825 ///// method to apply/test the new value
795 dec.setProperty(property, value, priority); 826 dec.setProperty(property, value, priority);
796 827
797 if(rule.parentStyleSheet) { 828 if(rule.type !== 'inline' && rule.parentStyleSheet) {
798 this.styleSheetModified(rule.parentStyleSheet); 829 this.styleSheetModified(rule.parentStyleSheet);
799 } 830 }
800 831
@@ -970,12 +1001,13 @@ var stylesController = exports.StylesController = Montage.create(Component, {
970 var doc = element.ownerDocument, 1001 var doc = element.ownerDocument,
971 useImportant = false, 1002 useImportant = false,
972 cache = this._getCachedRuleForProperty(element, property), 1003 cache = this._getCachedRuleForProperty(element, property),
973 dominantRule, override, className, browserValue; 1004 dominantRule, override, className, browserValue, cacheMatchesMany;
974 1005
975 if(cache) { 1006 if(cache) {
976 ///// We've cached the rule for this property! 1007 ///// We've cached the rule for this property!
977 //console.log('Styles Controller :: setElementStyle - We found the cached rule!'); 1008 //console.log('Styles Controller :: setElementStyle - We found the cached rule!');
978 dominantRule = cache; 1009 dominantRule = cache;
1010 cacheMatchesMany = this.matchesMultipleElements(dominantRule, doc);
979 } else { 1011 } else {
980 ///// Use Dominant Rule logic to find the right place to add the style 1012 ///// Use Dominant Rule logic to find the right place to add the style
981 ///// Pass "true" to method to return an override object, which 1013 ///// Pass "true" to method to return an override object, which
@@ -983,7 +1015,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
983 dominantRule = this.getDominantRuleForElement(element, property, true, isStageElement); 1015 dominantRule = this.getDominantRuleForElement(element, property, true, isStageElement);
984 1016
985 } 1017 }
986 1018
987 ///// Did we find a dominant rule? 1019 ///// Did we find a dominant rule?
988 if(!dominantRule) { 1020 if(!dominantRule) {
989 ///// No. This means there was no rule with this property, and no 1021 ///// No. This means there was no rule with this property, and no
@@ -1001,6 +1033,13 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1001 useImportant = dominantRule.useImportant; 1033 useImportant = dominantRule.useImportant;
1002 dominantRule = override.rule; 1034 dominantRule = override.rule;
1003 this.addClass(element, override.className); 1035 this.addClass(element, override.className);
1036 } else if(cacheMatchesMany) {
1037 ///// Only happens when the cached rule applies to multiple
1038 ///// elements - we must create override
1039 override = this.createOverrideRule(dominantRule, element);
1040 useImportant = !!dominantRule.style.getPropertyPriority(property);
1041 dominantRule = override.rule;
1042 this.addClass(element, override.className);
1004 } 1043 }
1005 1044
1006 1045
@@ -1008,7 +1047,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1008 browserValue = this.setStyle(dominantRule, property, value, useImportant); 1047 browserValue = this.setStyle(dominantRule, property, value, useImportant);
1009 1048
1010 ///// Only cache the dominant rule if the style value was valid, and not already cached 1049 ///// Only cache the dominant rule if the style value was valid, and not already cached
1011 if(browserValue && !cache) { 1050 if(browserValue && (!cache || cacheMatchesMany)) {
1012 this._setCachedRuleForProperty(element, property, dominantRule); 1051 this._setCachedRuleForProperty(element, property, dominantRule);
1013 } 1052 }
1014 1053
@@ -1245,11 +1284,42 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1245 doc.head.appendChild(sheetElement); 1284 doc.head.appendChild(sheetElement);
1246 sheet = this.getSheetFromElement(sheetElement, doc); 1285 sheet = this.getSheetFromElement(sheetElement, doc);
1247 1286