aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 afd298c9..21024125 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);
@@ -199,25 +199,42 @@ var stylesController = exports.StylesController = Montage.create(Component, {
199 199
200 ///// Locally-scoped function to de-clutter variable declarations 200 ///// Locally-scoped function to de-clutter variable declarations
201 function getSelector(el, rule) { 201 function getSelector(el, rule) {
202
203 return this._getMostSpecificSelectorForElement(el, rule[this.CONST.SPECIFICITY_KEY]).selector; 202 return this._getMostSpecificSelectorForElement(el, rule[this.CONST.SPECIFICITY_KEY]).selector;
204 } 203 }
205 204
206 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride), 205 var selectorToOverride = getSelector.bind(this)(element, ruleToOverride),
207 tokens = selectorToOverride.split(/\s/), 206 overrideData, rule;
208 newClass = this.generateClassName(element.nodeName), 207
209 lastToken, pseudoSplit, base, pseudo, newToken, newSelector, rule; 208 ///// Get the overriding selector and className
209 overrideData = this.createOverrideSelector(selectorToOverride, element.nodeName);
210
211 ///// Create new rule with selector and insert it after the rule we're overriding
212 rule = this.addRule(overrideData.selector + ' { }', this.getRuleIndex(ruleToOverride)+1);
213
214 return {
215 className : overrideData.className,
216 rule : rule
217 };
218
219 }
220 },
221
222 createOverrideSelector : {
223 value: function(selectorToOverride, classPrefix, className) {
224 var tokens = selectorToOverride.split(/\s/),
225 newClass = className || this.generateClassName(classPrefix, true),
226 lastToken, pseudoSplit, base, pseudo, newToken, newSelector;
210 227
211 ///// Creating an overriding selector by replacing the last 228 ///// Creating an overriding selector by replacing the last
212 ///// class, attribute or type selector in passed-in rule's selector 229 ///// class, attribute or type selector in passed-in rule's selector
213 230
214 ///// Grab the last token 231 ///// Grab the last token
215 lastToken = tokens[tokens.length-1]; 232 lastToken = tokens[tokens.length-1];
216 pseudoSplit = lastToken.split(':'); 233 pseudoSplit = lastToken.split(':');
217 ///// The last token can have pseudo class. Let's preserve it 234 ///// The last token can have pseudo class. Let's preserve it
218 base = pseudoSplit[0]; 235 base = pseudoSplit[0];
219 pseudo = (pseudoSplit[1]) ? ':'+pseudoSplit[1] : ''; 236 pseudo = (pseudoSplit[1]) ? ':'+pseudoSplit[1] : '';
220 237
221 ///// Now, all we want to do is replace the last token with a 238 ///// Now, all we want to do is replace the last token with a
222 ///// generated class name, except if the last token is an ID selector, 239 ///// generated class name, except if the last token is an ID selector,
223 ///// in which case we append the generated class name to the ID selector 240 ///// in which case we append the generated class name to the ID selector
@@ -231,18 +248,15 @@ var stylesController = exports.StylesController = Montage.create(Component, {
231 ///// Append the generated class 248 ///// Append the generated class
232 newToken += '.' + newClass + pseudo; 249 newToken += '.' + newClass + pseudo;
233 } 250 }
234 251
235 ///// Now we can build the new selector by replacing the last token 252 ///// Now we can build the new selector by replacing the last token
236 tokens[tokens.length-1] = newToken; 253 tokens[tokens.length-1] = newToken;
237 newSelector = tokens.join(' '); 254 newSelector = tokens.join(' ');
238 255
239 rule = this.addRule(newSelector + ' { }', this.getRuleIndex(ruleToOverride)+1);
240
241 return { 256 return {
242 className : newClass, 257 className : newClass,
243 rule : rule 258 selector : newSelector
244 }; 259 };
245
246 } 260 }
247 }, 261 },
248 262
@@ -370,7 +384,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
370 ///// from which an overriding rule can be created. 384 ///// from which an overriding rule can be created.
371 385
372 getDominantRuleForGroup : { 386 getDominantRuleForGroup : {
373 value : function(elements, property) { 387 value : function(elements, property, forceOverride) {
374 var selectorsToOverride = [], 388 var selectorsToOverride = [],
375 commonRules, dominantRules, useImportant; 389 commonRules, dominantRules, useImportant;
376 390
@@ -639,7 +653,7 @@ var stylesController = exports.StylesController = Montage.create(Component, {
639 }, 653 },
640 654
641 ///// Get Most Specific Selector For Element 655 ///// Get Most Specific Selector For Element
642 ///// Given a selector+specificty array, find the most specific 656 ///// Given a selector+specificity array, find the most specific
643 ///// selector for the passed-in element 657 ///// selector for the passed-in element
644 658
645 _getMostSpecificSelectorForElement : { 659 _getMostSpecificSelectorForElement : {
@@ -721,7 +735,11 @@ var stylesController = exports.StylesController = Montage.create(Component, {
721 ///// Calculate specificity 735 ///// Calculate specificity
722 ///// Returns the specificity value of passed-in selector 736 ///// Returns the specificity value of passed-in selector
723 ///// WARNING: Do not pass in grouped selectors! 737 ///// WARNING: Do not pass in grouped selectors!
724 ///// Helpful for determining precedence of style rules 738 ///// Helpful for determining precedence of style rules
739 ///// Calculation javascript code courtesy of Graham Bradley:
740 ///// http://gbradley.com/2009/10/02/css-specificity-in-javascript
741 ///// Used with author's permission
742
725 calculateSpecificity : { 743 calculateSpecificity : {
726 value : function(selector) { 744 value : function(selector) {
727 var s = selector.replace(/\([^\)]+\)/,''), 745 var s = selector.replace(/\([^\)]+\)/,''),
@@ -786,7 +804,34 @@ var stylesController = exports.StylesController = Montage.create(Component, {
786 return browserValues; 804 return browserValues;
787 } 805 }
788 }, 806 },
789 807
808 ///// Set Keyframe Style
809 ///// For a given CSSKeyframesRule, we may add a style to the keyframe at
810 ///// given index.
811
812 setKeyframeStyle : {
813 value : function(rule, keyframeIndex, property, value, useImportant) {
814 return this.setStyle(rule.cssRules[keyframeIndex], property, value, useImportant);
815 }
816 },
817
818 ///// Set Keyframe Styles
819 ///// For a given CSSKeyframesRule, we may add styles to the keyframe at
820 ///// given index.
821
822 setKeyframeStyle : {
823 value : function(rule, keyframeIndex, property, value, useImportant) {
824 return this.setStyles(rule.cssRules[keyframeIndex], property, value, useImportant);
825 }
826 },
827
828 insertKeyframe : {
829 value : function() {
830
831 }
832 },
833
834
790 ///// Delete style 835 ///// Delete style
791 ///// Removes the property from the style declaration/rule 836 ///// Removes the property from the style declaration/rule
792 ///// Returns the rule 837 ///// Returns the rule
@@ -922,6 +967,43 @@ var stylesController = exports.StylesController = Montage.create(Component, {
922 } 967 }
923 } 968 }
924 }, 969 },
970
971 setGroupStyles : {
972 value : function(elements, styles) {
973 var properties = Object.keys(styles),
974 newClass = this.generateClassName(null, true),
975 selectors;
976
977 ///// TODO: move this: Locally-scoped function to de-clutter variable declarations
978 function getSelector(el, rule) {
979 return this._getMostSpecificSelectorForElement(el, rule[this.CONST.SPECIFICITY_KEY]).selector;
980 }
981
982 selectors = elements.map(function(el) {
983 ///// for each element, we want to find the most specific selector
984 var matchingRules = this.getMatchingRules(el, true);
985
986 this.addClass(el, newClass);
987
988 if(matchingRules.length === 0) {
989 return null;
990 }
991
992 var mostSpecificRule = matchingRules[0], // TODO: iterate over properties to find most specific
993 selectorToOverride = getSelector.bind(this)(el, mostSpecificRule),
994 override = this.createOverrideSelector(selectorToOverride, null, newClass);
995
996 return override.selector;
997
998 }, this);
999
1000 selectors.filter(function(item) {
1001 return item !== null;
1002 });
1003
1004 this.addRule(selectors.join(', '), styles);
1005 }
1006 },
925 1007
926 ///// Get Element Style 1008 ///// Get Element Style
927 ///// Gets the style value that is currently applied to the element 1009 ///// Gets the style value that is currently applied to the element
@@ -1058,6 +1140,21 @@ var stylesController = exports.StylesController = Montage.create(Component, {
1058 } 1140 }
1059 }, 1141 },
1060 1142
1143 ///// CSS From Object
1144 ///// Returns css text from object with key/value pairs
1145 ///// representing css styles
1146
1147 cssFromObject : {
1148 value : function(obj) {
1149 var cssText = '';
1150 ///// For each key/value pair, create css text