diff options
Diffstat (limited to 'js/controllers')
-rwxr-xr-x | js/controllers/styles-controller.js | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/js/controllers/styles-controller.js b/js/controllers/styles-controller.js index 2ff3e235..cbc00676 100755 --- a/js/controllers/styles-controller.js +++ b/js/controllers/styles-controller.js | |||
@@ -94,11 +94,18 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
94 | // Returns null if sheet not found (as in non-ninja projects) | 94 | // Returns null if sheet not found (as in non-ninja projects) |
95 | // Setter will handle null case | 95 | // Setter will handle null case |
96 | this.defaultStylesheet = this.getSheetFromElement(this.CONST.DEFAULT_SHEET_ID); | 96 | this.defaultStylesheet = this.getSheetFromElement(this.CONST.DEFAULT_SHEET_ID); |
97 | 97 | ||
98 | //debugger; | 98 | this.userStyleSheets = nj.toArray(document._document.styleSheets).filter(function(sheet) { |
99 | return sheet !== this._stageStylesheet; | ||
100 | }, this); | ||
101 | |||
102 | NJevent('styleSheetsReady', this); | ||
99 | }, | 103 | }, |
100 | enumerable : false | 104 | enumerable : false |
101 | }, | 105 | }, |
106 | userStyleSheets : { | ||
107 | value : null | ||
108 | }, | ||
102 | _stageStylesheet : { | 109 | _stageStylesheet : { |
103 | value : null | 110 | value : null |
104 | }, | 111 | }, |
@@ -183,6 +190,7 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
183 | ///// attach specificity to rule object | 190 | ///// attach specificity to rule object |
184 | ///// if rule is css keyframes, return rule and don't attach specificity | 191 | ///// if rule is css keyframes, return rule and don't attach specificity |
185 | if (rule instanceof WebKitCSSKeyframesRule) { | 192 | if (rule instanceof WebKitCSSKeyframesRule) { |
193 | |||
186 | return rule; | 194 | return rule; |
187 | } | 195 | } |
188 | rule[this.CONST.SPECIFICITY_KEY] = this.getSpecificity(rule.selectorText); | 196 | rule[this.CONST.SPECIFICITY_KEY] = this.getSpecificity(rule.selectorText); |
@@ -209,10 +217,12 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
209 | } | 217 | } |
210 | 218 | ||
211 | var selectorToOverride = getSelector.bind(this)(element, ruleToOverride), | 219 | var selectorToOverride = getSelector.bind(this)(element, ruleToOverride), |
212 | overrideData, rule; | 220 | overrideData, rule, isRuleLocked; |
221 | |||
222 | isRuleLocked = this.isSheetLocked(ruleToOverride.parentStyleSheet); | ||
213 | 223 | ||
214 | ///// Get the overriding selector and className | 224 | ///// Get the overriding selector and className |
215 | overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName); | 225 | overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName, isRuleLocked); |
216 | 226 | ||
217 | ///// Create new rule with selector and insert it after the rule we're overriding | 227 | ///// Create new rule with selector and insert it after the rule we're overriding |
218 | rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1); | 228 | rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1); |
@@ -226,7 +236,7 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
226 | }, | 236 | }, |
227 | 237 | ||
228 | createOverrideSelector : { | 238 | createOverrideSelector : { |
229 | value: function(selectorToOverride, classPrefix, className) { | 239 | value: function(selectorToOverride, classPrefix, increaseSpecificity, className) { |
230 | var tokens = selectorToOverride.split(/\s/), | 240 | var tokens = selectorToOverride.split(/\s/), |
231 | newClass = className || this.generateClassName(classPrefix, true), | 241 | newClass = className || this.generateClassName(classPrefix, true), |
232 | lastToken, pseudoSplit, base, pseudo, newToken, newSelector; | 242 | lastToken, pseudoSplit, base, pseudo, newToken, newSelector; |
@@ -247,10 +257,19 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
247 | if(base.indexOf('#') !== -1) { | 257 | if(base.indexOf('#') !== -1) { |
248 | newToken = base + '.' + newClass + pseudo; | 258 | newToken = base + '.' + newClass + pseudo; |
249 | } else { | 259 | } else { |
250 | ///// Replace last class or attribute selector | 260 | if(increaseSpecificity) { |
251 | ///// Get everything right before the last class or attribute selector | 261 | ///// Increases specificity by one class selector |
252 | ///// to support compound selector values: (i.e. .firstClass.secondClass) | 262 | ///// We'll do a direct append to the base class |
253 | newToken = base.substring(0, Math.max(base.lastIndexOf('.'), base.lastIndexOf('['))); | 263 | ///// if we want to increase the specificity |
264 | newToken = base; | ||
265 | } else { | ||
266 | ///// Maintains original specificity | ||
267 | ///// Replace last class or attribute selector | ||
268 | ///// Get everything right before the last class or attribute selector | ||
269 | ///// to support compound selector values: (i.e. .firstClass.secondClass) | ||
270 | newToken = base.substring(0, Math.max(base.lastIndexOf('.'), base.lastIndexOf('['))); | ||
271 | } | ||
272 | |||
254 | ///// Append the generated class | 273 | ///// Append the generated class |
255 | newToken += '.' + newClass + pseudo; | 274 | newToken += '.' + newClass + pseudo; |
256 | } | 275 | } |
@@ -971,12 +990,13 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
971 | var doc = element.ownerDocument, | 990 | var doc = element.ownerDocument, |
972 | useImportant = false, | 991 | useImportant = false, |
973 | cache = this._getCachedRuleForProperty(element, property), | 992 | cache = this._getCachedRuleForProperty(element, property), |
974 | dominantRule, override, className, browserValue; | 993 | dominantRule, override, className, browserValue, cacheMatchesMany; |
975 | 994 | ||
976 | if(cache) { | 995 | if(cache) { |
977 | ///// We've cached the rule for this property! | 996 | ///// We've cached the rule for this property! |
978 | //console.log('Styles Controller :: setElementStyle - We found the cached rule!'); | 997 | //console.log('Styles Controller :: setElementStyle - We found the cached rule!'); |
979 | dominantRule = cache; | 998 | dominantRule = cache; |
999 | cacheMatchesMany = this.matchesMultipleElements(dominantRule, doc); | ||
980 | } else { | 1000 | } else { |
981 | ///// Use Dominant Rule logic to find the right place to add the style | 1001 | ///// Use Dominant Rule logic to find the right place to add the style |
982 | ///// Pass "true" to method to return an override object, which | 1002 | ///// Pass "true" to method to return an override object, which |
@@ -984,7 +1004,7 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
984 | dominantRule = this.getDominantRuleForElement(element, property, true, isStageElement); | 1004 | dominantRule = this.getDominantRuleForElement(element, property, true, isStageElement); |
985 | 1005 | ||
986 | } | 1006 | } |
987 | 1007 | ||
988 | ///// Did we find a dominant rule? | 1008 | ///// Did we find a dominant rule? |
989 | if(!dominantRule) { | 1009 | if(!dominantRule) { |
990 | ///// No. This means there was no rule with this property, and no | 1010 | ///// No. This means there was no rule with this property, and no |
@@ -1002,6 +1022,13 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
1002 | useImportant = dominantRule.useImportant; | 1022 | useImportant = dominantRule.useImportant; |
1003 | dominantRule = override.rule; | 1023 | dominantRule = override.rule; |
1004 | this.addClass(element, override.className); | 1024 | this.addClass(element, override.className); |
1025 | } else if(cacheMatchesMany) { | ||
1026 | ///// Only happens when the cached rule applies to multiple | ||
1027 | ///// elements - we must create override | ||
1028 | override = this.createOverrideRule(dominantRule, element); | ||
1029 | useImportant = !!dominantRule.style.getPropertyPriority(property); | ||
1030 | dominantRule = override.rule; | ||
1031 | this.addClass(element, override.className); | ||
1005 | } | 1032 | } |
1006 | 1033 | ||
1007 | 1034 | ||
@@ -1009,7 +1036,7 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
1009 | browserValue = this.setStyle(dominantRule, property, value, useImportant); | 1036 | browserValue = this.setStyle(dominantRule, property, value, useImportant); |
1010 | 1037 | ||
1011 | ///// Only cache the dominant rule if the style value was valid, and not already cached | 1038 | ///// Only cache the dominant rule if the style value was valid, and not already cached |
1012 | if(browserValue && !cache) { | 1039 | if(browserValue && (!cache || cacheMatchesMany)) { |
1013 | this._setCachedRuleForProperty(element, property, dominantRule); | 1040 | this._setCachedRuleForProperty(element, property, dominantRule); |
1014 | } | 1041 | } |
1015 | 1042 | ||
@@ -1244,8 +1271,12 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
1244 | doc.head.appendChild(sheetElement); | 1271 | doc.head.appendChild(sheetElement); |
1245 | sheet = this.getSheetFromElement(sheetElement, doc); | 1272 | sheet = this.getSheetFromElement(sheetElement, doc); |
1246 | 1273 | ||
1274 | this.userStyleSheets.push(sheet); | ||
1275 | |||
1247 | this.styleSheetModified(sheet); | 1276 | this.styleSheetModified(sheet); |
1248 | 1277 | ||
1278 | NJevent('newStyleSheet', sheet); | ||
1279 | |||
1249 | return sheet; | 1280 | return sheet; |
1250 | } | 1281 | } |
1251 | }, | 1282 | }, |
@@ -1268,6 +1299,12 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
1268 | } | 1299 | } |
1269 | }, | 1300 | }, |
1270 | 1301 | ||
1302 | isSheetLocked : { | ||
1303 | value: function(sheet) { | ||
1304 | return !!sheet.ownerNode.dataset['ninjaFileReadOnly']; | ||
1305 | } | ||
1306 | }, | ||
1307 | |||
1271 | ///// Style Sheet Modified | 1308 | ///// Style Sheet Modified |
1272 | ///// Method to call whenever a stylesheet change is made | 1309 | ///// Method to call whenever a stylesheet change is made |
1273 | ///// Dispatches an event, and keeps list of dirty style sheets | 1310 | ///// Dispatches an event, and keeps list of dirty style sheets |
@@ -1308,11 +1345,10 @@ var stylesController = exports.StylesController = Montage.create(Component, { | |||
1308 | this.dirtyStyleSheets.length = 0; | 1345 | this.dirtyStyleSheets.length = 0; |
1309 | 1346 | ||
1310 | if(doc) { | 1347 | if(doc) { |
1311 | var stillDirty = this.dirtyStyleSheets.filter(function(sheet) { | 1348 | this.dirtyStyleSheets = null; |
1349 | this.dirtyStyleSheets = this.dirtyStyleSheets.filter(function(sheet) { | ||
1312 | return sheet.document !== doc; | 1350 | return sheet.document !== doc; |
1313 | }); | 1351 | }); |
1314 | this.dirtyStyleSheets = null; | ||
1315 | this.dirtyStyleSheets = stillDirty; | ||
1316 | } | 1352 | } |
1317 | 1353 | ||
1318 | 1354 | ||