aboutsummaryrefslogtreecommitdiff
path: root/js/controllers/styles-controller.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/controllers/styles-controller.js')
-rw-r--r--js/controllers/styles-controller.js159
1 files changed, 138 insertions, 21 deletions
diff --git a/js/controllers/styles-controller.js b/js/controllers/styles-controller.js
index 51b81204..a38984e7 100644
--- a/js/controllers/styles-controller.js
+++ b/js/controllers/styles-controller.js
@@ -171,7 +171,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
171 if(argType === 'string') { 171 if(argType === 'string') {
172 ruleText += '{' + declaration + '}'; 172 ruleText += '{' + declaration + '}';
173 } else if(argType === 'object') { 173 } else if(argType === 'object') {
174 ruleText += '{' + nj.cssFromObject(declaration) + '}'; 174 ruleText += '{' + this.cssFromObject(declaration) + '}';
175 } 175 }
176 176
177 stylesheet.insertRule(ruleText, index); 177 stylesheet.insertRule(ruleText, index);
@@ -203,25 +203,42 @@ var stylesController = exports.StylesController = Montage.create(Component, {
203 203
204 ///// Locally-scoped function to de-clutter variable declarations 204 ///// Locally-scoped function to de-clutter variable declarations
205 function getSelector(el, rule) { 205 function getSelector(el, rule) {
206
207 return this._getMostSpecificSelectorForElement(el, rule[this.CONST.SPECIFICITY_KEY]).selector; 206 return this._getMostSpecificSelectorForElement(el, rule[this.CONST.SPECIFICITY_KEY]).selector;
208 } 207 }
209 208
210 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride), 209 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride),
211 tokens = selectorToOverride.split(/\s/), 210 overrideData, rule;
212 newClass = this.generateClassName(element.nodeName), 211
213 lastToken, pseudoSplit, base, pseudo, newToken, newSelector, rule; 212 ///// Get the overriding selector and className
213 overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName);
214
215 ///// Create new rule with selector and insert it after the rule we're overriding
216 rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1);
217
218 return {
219 className : overrideData.className,
220 rule : rule
221 };
222
223 }
224 },
225
226 createOverrideSelector : {
227 value: function(selectorToOverride, classPrefix, className) {
228 var tokens = selectorToOverride.split(/\s/),
229 newClass = className || this.generateClassName(classPrefix, true),
230 lastToken, pseudoSplit, base, pseudo, newToken, newSelector;
214 231
215 ///// Creating an overriding selector by replacing the last 232 ///// Creating an overriding selector by replacing the last
216 ///// class, attribute or type selector in passed-in rule's selector 233 ///// class, attribute or type selector in passed-in rule's selector
217 234
218 ///// Grab the last token 235 ///// Grab the last token
219 lastToken = tokens[tokens.length-1]; 236 lastToken = tokens[tokens.length-1];
220 pseudoSplit = lastToken.split(':'); 237 pseudoSplit = lastToken.split(':');
221 ///// The last token can have pseudo class. Let's preserve it 238 ///// The last token can have pseudo class. Let's preserve it
222 base = pseudoSplit[0]; 239 base = pseudoSplit[0];
223 pseudo = (pseudoSplit[1]) ? ':'+pseudoSplit[1] : ''; 240 pseudo = (pseudoSplit[1]) ? ':'+pseudoSplit[1] : '';
224 241
225 ///// Now, all we want to do is replace the last token with a 242 ///// Now, all we want to do is replace the last token with a
226 ///// generated class name, except if the last token is an ID selector, 243 ///// generated class name, except if the last token is an ID selector,
227 ///// in which case we append the generated class name to the ID selector 244 ///// in which case we append the generated class name to the ID selector
@@ -235,18 +252,15 @@ var stylesController = exports.StylesController = Montage.create(Component, {
235 ///// Append the generated class 252 ///// Append the generated class
236 newToken += '.' + newClass + pseudo; 253 newToken += '.' + newClass + pseudo;
237 } 254 }
238 255
239 ///// Now we can build the new selector by replacing the last token 256 ///// Now we can build the new selector by replacing the last token
240 tokens[tokens.length-1] = newToken; 257 tokens[tokens.length-1] = newToken;
241 newSelector = tokens.join(' '); 258 newSelector = tokens.join(' ');
242 259
243 rule = this.addRule(newSelector + ' { }', this.getRuleIndex(ruleToOverride)+1);
244
245 return { 260 return {
246 className : newClass, 261 className : newClass,
247 rule : rule 262 selector : newSelector
248 }; 263 };
249
250 } 264 }
251 }, 265 },
252 266
@@ -374,7 +388,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
374 ///// from which an overriding rule can be created. 388 ///// from which an overriding rule can be created.
375 389
376 getDominantRuleForGroup : { 390 getDominantRuleForGroup : {
377 value : function(elements, property) { 391 value : function(elements, property, forceOverride) {
378 var selectorsToOverride = [], 392 var selectorsToOverride = [],
379 commonRules, dominantRules, useImportant; 393 commonRules, dominantRules, useImportant;
380 394
@@ -643,7 +657,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
643 }, 657 },
644 658
645 ///// Get Most Specific Selector For Element 659 ///// Get Most Specific Selector For Element
646 ///// Given a selector+specificty array, find the most specific 660 ///// Given a selector+specificity array, find the most specific
647 ///// selector for the passed-in element 661 ///// selector for the passed-in element
648 662
649 _getMostSpecificSelectorForElement : { 663 _getMostSpecificSelectorForElement : {
@@ -725,7 +739,11 @@ var stylesController = exports.StylesController = Montage.create(Component, {
725 ///// Calculate specificity 739 ///// Calculate specificity
726 ///// Returns the specificity value of passed-in selector 740 ///// Returns the specificity value of passed-in selector
727 ///// WARNING: Do not pass in grouped selectors! 741 ///// WARNING: Do not pass in grouped selectors!
728 ///// Helpful for determining precedence of style rules 742 ///// Helpful for determining precedence of style rules
743 ///// Calculation javascript code courtesy of Graham Bradley:
744 ///// http://gbradley.com/2009/10/02/css-specificity-in-javascript
745 ///// Used with author's permission
746
729 calculateSpecificity : { 747 calculateSpecificity : {
730 value : function(selector) { 748 value : function(selector) {
731 var s = selector.replace(/\([^\)]+\)/,''), 749 var s = selector.replace(/\([^\)]+\)/,''),
@@ -790,7 +808,34 @@ var stylesController = exports.StylesController = Montage.create(Component, {
790 return browserValues; 808 return browserValues;
791 } 809 }
792 }, 810 },
793 811
812 ///// Set Keyframe Style
813 ///// For a given CSSKeyframesRule, we may add a style to the keyframe at
814 ///// given index.
815
816 setKeyframeStyle : {
817 value : function(rule, keyframeIndex, property, value, useImportant) {
818 return this.setStyle(rule.cssRules[keyframeIndex], property, value, useImportant);
819 }
820 },
821
822 ///// Set Keyframe Styles
823 ///// For a given CSSKeyframesRule, we may add styles to the keyframe at
824 ///// given index.
825
826 setKeyframeStyle : {
827 value : function(rule, keyframeIndex, property, value, useImportant) {
828 return this.setStyles(rule.cssRules[keyframeIndex], property, value, useImportant);
829 }
830 },
831
832 insertKeyframe : {
833 value : function() {
834
835 }
836 },
837
838
794 ///// Delete style 839 ///// Delete style
795 ///// Removes the property from the style declaration/rule 840 ///// Removes the property from the style declaration/rule
796 ///// Returns the rule 841 ///// Returns the rule
@@ -926,6 +971,43 @@ var stylesController = exports.StylesController = Montage.create(Component, {
926 } 971 }
927 } 972 }
928 }, 973 },
974
975 setGroupStyles : {
976 value : function(elements, styles) {
977 var properties = Object.keys(styles),
978 newClass = this.generateClassName(null, true),
979 selectors;
980
981 ///// TODO: move this: Locally-scoped function to de-clutter variable declarations
982 function getSelector(el, rule) {
983 return this._getMostSpecificSelectorForElement(el, rule[this.CONST.SPECIFICITY_KEY]).selector;
984 }
985
986 selectors = elements.map(function(el) {
987 ///// for each element, we want to find the most specific selector
988 var matchingRules = this.getMatchingRules(el, true);
989
990 this.addClass(el, newClass);
991
992 if(matchingRules.length === 0) {
993 return null;
994 }
995
996 var mostSpecificRule = matchingRules[0], // TODO: iterate over properties to find most specific
997 selectorToOverride = getSelector.bind(this)(el, mostSpecificRule),
998 override = this.createOverrideSelector(selectorToOverride, null, newClass);
999
1000 return override.selector;
1001
1002 }, this);
1003
1004 selectors.filter(function(item) {
1005 return item !== null;
1006 });
1007
1008 this.addRule(selectors.join(', '), styles);
1009 }
1010 },
929 1011
930 ///// Get Element Style 1012 ///// Get Element Style
931 ///// Gets the style value that is currently applied to the element 1013 ///// Gets the style value that is currently applied to the element
@@ -1062,6 +1144,21 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1062 } 1144 }
1063 }, 1145 },
1064 1146
1147 ///// CSS From Object
1148 ///// Returns css text from object with key/value pairs