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.js80
1 files changed, 64 insertions, 16 deletions
diff --git a/js/controllers/styles-controller.js b/js/controllers/styles-controller.js
index 2ff3e235..c8b9376e 100755
--- a/js/controllers/styles-controller.js
+++ b/js/controllers/styles-controller.js
@@ -83,6 +83,11 @@ var stylesController = exports.StylesController = Montage.create(Component, {
83 ///// If the document is null set default stylesheets to null 83 ///// If the document is null set default stylesheets to null
84 84
85 if(!document) { 85 if(!document) {
86 this._activeDocument = null;
87 this._stageStylesheet = null;
88 this.defaultStylesheet = null;
89 this.userStyleSheets = [];
90 this.clearDirtyStyleSheets();
86 return false; 91 return false;
87 } 92 }
88 93
@@ -94,11 +99,18 @@ var stylesController = exports.StylesController = Montage.create(Component, {
94 // Returns null if sheet not found (as in non-ninja projects) 99 // Returns null if sheet not found (as in non-ninja projects)
95 // Setter will handle null case 100 // Setter will handle null case
96 this.defaultStylesheet = this.getSheetFromElement(this.CONST.DEFAULT_SHEET_ID); 101 this.defaultStylesheet = this.getSheetFromElement(this.CONST.DEFAULT_SHEET_ID);
97 102
98 //debugger; 103 this.userStyleSheets = nj.toArray(document._document.styleSheets).filter(function(sheet) {
104 return sheet !== this._stageStylesheet;
105 }, this);
106
107 NJevent('styleSheetsReady', this);
99 }, 108 },
100 enumerable : false 109 enumerable : false
101 }, 110 },
111 userStyleSheets : {
112 value : null
113 },
102 _stageStylesheet : { 114 _stageStylesheet : {
103 value : null 115 value : null
104 }, 116 },
@@ -113,7 +125,10 @@ var stylesController = exports.StylesController = Montage.create(Component, {
113 if(sheet) { 125 if(sheet) {
114 this._defaultStylesheet = sheet; 126 this._defaultStylesheet = sheet;
115 } else { 127 } else {
116 128 if(sheet === null) {
129 this._defaultStylesheet = null;
130 return false;
131 }
117 ///// Use the last stylesheet in the document as the default 132 ///// Use the last stylesheet in the document as the default
118 133
119 var sheets = this._activeDocument._document.styleSheets, 134 var sheets = this._activeDocument._document.styleSheets,
@@ -183,6 +198,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
183 ///// attach specificity to rule object 198 ///// attach specificity to rule object
184 ///// if rule is css keyframes, return rule and don't attach specificity 199 ///// if rule is css keyframes, return rule and don't attach specificity
185 if (rule instanceof WebKitCSSKeyframesRule) { 200 if (rule instanceof WebKitCSSKeyframesRule) {
201
186 return rule; 202 return rule;
187 } 203 }
188 rule[this.CONST.SPECIFICITY_KEY] = this.getSpecificity(rule.selectorText); 204 rule[this.CONST.SPECIFICITY_KEY] = this.getSpecificity(rule.selectorText);
@@ -209,10 +225,12 @@ var stylesController = exports.StylesController = Montage.create(Component, {
209 } 225 }
210 226
211 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride), 227 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride),
212 overrideData, rule; 228 overrideData, rule, isRuleLocked;
229
230 isRuleLocked = this.isSheetLocked(ruleToOverride.parentStyleSheet);
213 231
214 ///// Get the overriding selector and className 232 ///// Get the overriding selector and className
215 overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName); 233 overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName, isRuleLocked);
216 234
217 ///// Create new rule with selector and insert it after the rule we're overriding 235 ///// Create new rule with selector and insert it after the rule we're overriding
218 rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1); 236 rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1);
@@ -226,7 +244,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
226 }, 244 },
227 245
228 createOverrideSelector : { 246 createOverrideSelector : {
229 value: function(selectorToOverride, classPrefix, className) { 247 value: function(selectorToOverride, classPrefix, increaseSpecificity, className) {
230 var tokens = selectorToOverride.split(/\s/), 248 var tokens = selectorToOverride.split(/\s/),
231 newClass = className || this.generateClassName(classPrefix, true), 249 newClass = className || this.generateClassName(classPrefix, true),
232 lastToken, pseudoSplit, base, pseudo, newToken, newSelector; 250 lastToken, pseudoSplit, base, pseudo, newToken, newSelector;
@@ -247,10 +265,19 @@ var stylesController = exports.StylesController = Montage.create(Component, {
247 if(base.indexOf('#') !== -1) { 265 if(base.indexOf('#') !== -1) {
248 newToken = base + '.' + newClass + pseudo; 266 newToken = base + '.' + newClass + pseudo;
249 } else { 267 } else {
250 ///// Replace last class or attribute selector 268 if(increaseSpecificity) {
251 ///// Get everything right before the last class or attribute selector 269 ///// Increases specificity by one class selector
252 ///// to support compound selector values: (i.e. .firstClass.secondClass) 270 ///// We'll do a direct append to the base class
253 newToken = base.substring(0, Math.max(base.lastIndexOf('.'), base.lastIndexOf('['))); 271 ///// if we want to increase the specificity
272 newToken = base;
273 } else {
274 ///// Maintains original specificity
275 ///// Replace last class or attribute selector
276 ///// Get everything right before the last class or attribute selector
277 ///// to support compound selector values: (i.e. .firstClass.secondClass)
278 newToken = base.substring(0, Math.max(base.lastIndexOf('.'), base.lastIndexOf('[')));
279 }
280
254 ///// Append the generated class 281 ///// Append the generated class
255 newToken += '.' + newClass + pseudo; 282 newToken += '.' + newClass + pseudo;
256 } 283 }
@@ -971,12 +998,13 @@ var stylesController = exports.StylesController = Montage.create(Component, {
971 var doc = element.ownerDocument, 998 var doc = element.ownerDocument,
972 useImportant = false, 999 useImportant = false,
973 cache = this._getCachedRuleForProperty(element, property), 1000 cache = this._getCachedRuleForProperty(element, property),
974 dominantRule, override, className, browserValue; 1001 dominantRule, override, className, browserValue, cacheMatchesMany;
975 1002
976 if(cache) { 1003 if(cache) {
977 ///// We've cached the rule for this property! 1004 ///// We've cached the rule for this property!
978 //console.log('Styles Controller :: setElementStyle - We found the cached rule!'); 1005 //console.log('Styles Controller :: setElementStyle - We found the cached rule!');
979 dominantRule = cache; 1006 dominantRule = cache;
1007 cacheMatchesMany = this.matchesMultipleElements(dominantRule, doc);
980 } else { 1008 } else {
981 ///// Use Dominant Rule logic to find the right place to add the style 1009 ///// Use Dominant Rule logic to find the right place to add the style
982 ///// Pass "true" to method to return an override object, which 1010 ///// Pass "true" to method to return an override object, which
@@ -984,7 +1012,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
984 dominantRule = this.getDominantRuleForElement(element, property, true, isStageElement); 1012 dominantRule = this.getDominantRuleForElement(element, property, true, isStageElement);
985 1013
986 } 1014 }
987 1015
988 ///// Did we find a dominant rule? 1016 ///// Did we find a dominant rule?
989 if(!dominantRule) { 1017 if(!dominantRule) {
990 ///// No. This means there was no rule with this property, and no 1018 ///// No. This means there was no rule with this property, and no
@@ -1002,6 +1030,13 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1002 useImportant = dominantRule.useImportant; 1030 useImportant = dominantRule.useImportant;
1003 dominantRule = override.rule; 1031 dominantRule = override.rule;
1004 this.addClass(element, override.className); 1032 this.addClass(element, override.className);
1033 } else if(cacheMatchesMany) {
1034 ///// Only happens when the cached rule applies to multiple
1035 ///// elements - we must create override
1036 override = this.createOverrideRule(dominantRule, element);
1037 useImportant = !!dominantRule.style.getPropertyPriority(property);
1038 dominantRule = override.rule;
1039 this.addClass(element, override.className);
1005 } 1040 }
1006 1041
1007 1042
@@ -1009,7 +1044,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1009 browserValue = this.setStyle(dominantRule, property, value, useImportant); 1044 browserValue = this.setStyle(dominantRule, property, value, useImportant);
1010 1045
1011 ///// Only cache the dominant rule if the style value was valid, and not already cached 1046 ///// Only cache the dominant rule if the style value was valid, and not already cached
1012 if(browserValue && !cache) { 1047 if(browserValue && (!cache || cacheMatchesMany)) {
1013 this._setCachedRuleForProperty(element, property, dominantRule); 1048 this._setCachedRuleForProperty(element, property, dominantRule);
1014 } 1049 }
1015 1050
@@ -1244,8 +1279,12 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1244 doc.head.appendChild(sheetElement); 1279 doc.head.appendChild(sheetElement);
1245 sheet = this.getSheetFromElement(sheetElement, doc); 1280 sheet = this.getSheetFromElement(sheetElement, doc);
1246 1281
1282 this.userStyleSheets.push(sheet);
1283
1247 this.styleSheetModified(sheet); 1284 this.styleSheetModified(sheet);
1248 1285
1286 NJevent('newStyleSheet', sheet);
1287
1249 return sheet; 1288 return sheet;
1250 } 1289 }
1251 }, 1290 },
@@ -1268,6 +1307,12 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1268 } 1307 }
1269 }, 1308 },
1270 1309
1310 isSheetLocked : {
1311 value: function(sheet) {
1312 return !!sheet.ownerNode.dataset['ninjaFileReadOnly'];
1313 }
1314 },
1315
1271 ///// Style Sheet Modified 1316 ///// Style Sheet Modified
1272 ///// Method to call whenever a stylesheet change is made 1317 ///// Method to call whenever a stylesheet change is made
1273 ///// Dispatches an event, and keeps list of dirty style sheets 1318 ///// Dispatches an event, and keeps list of dirty style sheets
@@ -1278,6 +1323,9 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1278 return sheetObj.stylesheet === sheet; 1323 return sheetObj.stylesheet === sheet;
1279 }); 1324 });
1280 1325
1326 ///// Dispatch modified event
1327 NJevent('styleSheetModified', eventData);
1328
1281 ///// If the sheet doesn't already exist in the list of modified 1329 ///// If the sheet doesn't already exist in the list of modified
1282 ///// sheets, dispatch dirty event and add the sheet to the list