Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
feat(colors): mdTheme integration
Browse files Browse the repository at this point in the history
- If `md-theme` directive is somewhere up the DOM tree we inject the theme before each color value

 ### example
```html
<div md-theme="myTheme">
  <div md-colors="{background: 'primary-600'}">
    <span md-colors="{background: 'mySecondTheme-accent-200'}">Color demo</span>
  </div>
</div>
```
 `'primary-600'` will be `'myTheme-primary-600'`,
but `'mySecondTheme-accent-200'` will stay the same cause it has a theme prefix

fixes #8407
  • Loading branch information
EladBezalel committed May 19, 2016
1 parent c26842a commit 92cad9f
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 21 deletions.
98 changes: 78 additions & 20 deletions src/components/colors/colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
// Publish service instance
return {
applyThemeColors: applyThemeColors,
getThemeColor: getThemeColor
getThemeColor: getThemeColor,
hasTheme: hasTheme
};

// ********************************************
Expand Down Expand Up @@ -80,7 +81,7 @@
try {
// Assign the calculate RGBA color values directly as inline CSS
element.css(interpolateColors(colorExpression));
} catch( e ) {
} catch (e) {
$log.error(e.message);
}

Expand Down Expand Up @@ -154,6 +155,16 @@
return rgbColors;
}

/**
* Check if expression has defined theme
* e.g.
* 'myTheme-primary' => true
* 'red-800' => false
*/
function hasTheme(expression) {
return angular.isDefined($mdTheming.THEMES[expression.split('-')[0]]);
}

/**
* For the evaluated expression, extract the color parts into a hash map
*/
Expand Down Expand Up @@ -198,7 +209,7 @@
var themeColors = $mdTheming.THEMES[theme].colors;

if (parts[1] === 'hue') {
var hueNumber = parseInt(parts.splice(2, 1)[0],10);
var hueNumber = parseInt(parts.splice(2, 1)[0], 10);

if (hueNumber < 1 || hueNumber > 3) {
throw new Error($mdUtil.supplant('mdColors: \'hue-{hueNumber}\' is not a valid hue, can be only \'hue-1\', \'hue-2\' and \'hue-3\'', {hueNumber: hueNumber}));
Expand Down Expand Up @@ -260,24 +271,71 @@
function MdColorsDirective($mdColors, $mdUtil, $log, $parse) {
return {
restrict: 'A',
require: ['^?mdTheme'],
compile: function (tElem, tAttrs) {
var shouldWatch = shouldColorsWatch();

return function (scope, element, attrs) {
var colorExpression = function () {
// Json.parse() does not work because the keys are not quoted;
// use $parse to convert to a hash map
return $parse(attrs.mdColors)(scope);
return function (scope, element, attrs, ctrl) {
var mdThemeController = ctrl[0];

var parseColors = function (theme) {
/**
* Json.parse() does not work because the keys are not quoted;
* use $parse to convert to a hash map
*/
var colors = $parse(attrs.mdColors)(scope);

/**
* If mdTheme is defined up the DOM tree
* we add mdTheme theme to colors who doesn't specified a theme
*
* # example
* <hljs lang="html">
* <div md-theme="myTheme">
* <div md-colors="{background: 'primary-600'}">
* <span md-colors="{background: 'mySecondTheme-accent-200'}">Color demo</span>
* </div>
* </div>
* </hljs>
*
* 'primary-600' will be 'myTheme-primary-600',
* but 'mySecondTheme-accent-200' will stay the same cause it has a theme prefix
*/
if (mdThemeController) {
Object.keys(colors).forEach(function (prop) {
var color = colors[prop];
if (!$mdColors.hasTheme(color)) {
colors[prop] = (theme || mdThemeController.$mdTheme) + '-' + color;
}
});
}

return colors;
};

/**
* Registering for mgTheme changes and asking mdTheme controller run our callback whenever a theme changes
*/
var unregisterChanges = angular.noop;

if (mdThemeController) {
unregisterChanges = mdThemeController.registerChanges(function (theme) {
$mdColors.applyThemeColors(element, parseColors(theme));
});
}

scope.$on('destroy', function () {
unregisterChanges();
});

try {
if (shouldWatch) {
scope.$watch(colorExpression, angular.bind(this,
scope.$watch(parseColors, angular.bind(this,
$mdColors.applyThemeColors, element
), true);
}
else {
$mdColors.applyThemeColors(element, colorExpression());
$mdColors.applyThemeColors(element, parseColors());
}

}
Expand All @@ -288,19 +346,19 @@
};

function shouldColorsWatch() {
// Simulate 1x binding and mark mdColorsWatch == false
var rawColorExpression = tAttrs.mdColors;
var bindOnce = rawColorExpression.indexOf('::') > -1;
var isStatic = bindOnce ? true : STATIC_COLOR_EXPRESSION.test(tAttrs.mdColors);
// Simulate 1x binding and mark mdColorsWatch == false
var rawColorExpression = tAttrs.mdColors;
var bindOnce = rawColorExpression.indexOf('::') > -1;
var isStatic = bindOnce ? true : STATIC_COLOR_EXPRESSION.test(tAttrs.mdColors);

// Remove it for the postLink...
tAttrs.mdColors = rawColorExpression.replace('::','');
// Remove it for the postLink...
tAttrs.mdColors = rawColorExpression.replace('::', '');

var hasWatchAttr = angular.isDefined(tAttrs.mdColorsWatch);
var hasWatchAttr = angular.isDefined(tAttrs.mdColorsWatch);

return (bindOnce || isStatic) ? false :
hasWatchAttr ? $mdUtil.parseAttributeBoolean(tAttrs.mdColorsWatch) : true;
}
return (bindOnce || isStatic) ? false :
hasWatchAttr ? $mdUtil.parseAttributeBoolean(tAttrs.mdColorsWatch) : true;
}
}
};

Expand Down
49 changes: 49 additions & 0 deletions src/components/colors/colors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,55 @@ describe('md-colors', function () {
expect(element[0].style.background).toContain( expectedRGB );
});
});

describe('mdColors integration', function () {
/**
* <div md-theme="myTheme">
* <div md-colors="{background: 'primary'}" >
* </div>
*/
it('should automatically inject myTheme as the theme prefix', function () {

var type = 'primary';
var paletteName = $mdTheming.THEMES['myTheme'].colors[type].name;
var color = $mdColorPalette[paletteName]['500'].value;
var expectedRGB = supplant('rgb({0}, {1}, {2})', [color[0], color[1], color[2]]);


var markup = '<div md-theme="myTheme"><div md-colors="{background: \'primary\'}" ></div></div>';
var element = $compile( markup )(scope);

expect(element.children()[0].style.background).toContain( expectedRGB );
});

/**
* <div md-theme="{{theme}}">
* <div md-colors="{background: 'primary'}" >
* </div>
*/
it('should register for theme changes and inject myTheme as the theme prefix', function () {

var type = 'primary';
var paletteName = $mdTheming.THEMES['myTheme'].colors[type].name;
var color = $mdColorPalette[paletteName]['500'].value;
var expectedRGB = supplant('rgb({0}, {1}, {2})', [color[0], color[1], color[2]]);

scope.theme = 'myTheme';
var markup = '<div md-theme="{{theme}}"><div md-colors="{background: \'primary\'}" ></div></div>';
var element = $compile( markup )(scope);

expect(element.children()[0].style.background).toContain( expectedRGB );

paletteName = $mdTheming.THEMES['default'].colors[type].name;
color = $mdColorPalette[paletteName]['500'].value;
expectedRGB = supplant('rgb({0}, {1}, {2})', [color[0], color[1], color[2]]);

scope.theme = 'default';
scope.$apply();

expect(element.children()[0].style.background).toContain( expectedRGB );
});
})
});

describe('watched values', function () {
Expand Down
22 changes: 21 additions & 1 deletion src/core/services/theming/theming.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,32 @@ function ThemingDirective($mdTheming, $interpolate, $log) {
priority: 100,
link: {
pre: function(scope, el, attrs) {
var registeredCallbacks = [];
var ctrl = {
$setTheme: function(theme) {
registerChanges: function (cb, context) {
if (context) {
cb = angular.bind(context, cb);
}

registeredCallbacks.push(cb);

return function () {
var index = registeredCallbacks.indexOf(cb);

if (index > -1) {
registeredCallbacks.splice(index, 1);
}
}
},
$setTheme: function (theme) {
if (!$mdTheming.registered(theme)) {
$log.warn('attempted to use unregistered theme \'' + theme + '\'');
}
ctrl.$mdTheme = theme;

registeredCallbacks.forEach(function (cb) {
cb();
})
}
};
el.data('$mdThemeController', ctrl);
Expand Down

0 comments on commit 92cad9f

Please sign in to comment.