toloframework
Version:
Javascript/HTML/CSS compiler for Firefox OS or nodewebkit apps using modules in the nodejs style.
207 lines (176 loc) • 7.83 kB
JavaScript
;
/**
* Manage material design like CSS styles.
*/
exports.register = registerTheme;
exports.apply = applyTheme;
//################################################################################
const Color = require( "tfw.color" );
const
THEME_COLOR_NAMES = [ "0", "1", "2", "3", "P", "PD", "PL", "S", "SD", "SL" ],
THEMES = {
css: {},
current: null
};
function registerTheme( themeName, style ) {
style = completeWithDefaultValues( style );
var codeCSS = codeVariables( themeName, style );
codeCSS += codeBackground( themeName, style );
codeCSS += codeElevation( themeName, style );
codeCSS += codeText( themeName, style );
var styleElement = THEMES.css[ themeName ];
if ( !styleElement ) {
styleElement = document.createElement( "style" );
document.getElementsByTagName( 'head' )[ 0 ].appendChild( styleElement );
THEMES.css[ themeName ] = styleElement;
}
styleElement.textContent = codeCSS;
return this;
}
function codeText( themeName, style ) {
var codeCSS = '';
for ( var depth = 1; depth <= 10; depth++ ) {
THEME_COLOR_NAMES.forEach( function ( colorName ) {
var bgClass = ".thm-bg" + colorName;
var fgClass = ".thm-fg" + colorName;
for ( var position = 1; position <= depth; position++ ) {
var piecesFG = [];
var piecesSVG = [];
var piecesBG = [];
for ( var index = 1; index <= depth; index++ ) {
piecesBG.push( position === index ? bgClass : '*' );
piecesSVG.push( position === index ? bgClass : '*' );
piecesFG.push( position === index ? fgClass : '*' );
if ( index === depth ) {
piecesBG.push( piecesBG.pop() + ".thm-fg" );
piecesFG.push( piecesFG.pop() + fgClass );
}
}
codeCSS += "body.dom-theme-" + themeName + " " +
piecesBG.join( " > " ) +
" { color: " + style[ 'fg' + colorName ] + " }\n";
codeCSS += "body.dom-theme-" + themeName + " " +
piecesFG.join( " > " ) +
" { color: " + style[ 'bg' + colorName ] + " }\n";
codeCSS += "body.dom-theme-" + themeName + " " +
piecesSVG.join( " > " ) +
" .thm-svg-fill0" +
" { fill: " + style[ 'fg' + colorName ] + " }\n";
codeCSS += "body.dom-theme-" + themeName + " " +
piecesSVG.join( " > " ) +
" .thm-svg-stroke0" +
" { stroke: " + style[ 'fg' + colorName ] + " }\n";
}
} );
}
return codeCSS;
}
function codeVariables( themeName, style ) {
var codeCSS = "body.dom-theme-" + themeName + '{\n';
THEME_COLOR_NAMES.forEach( function ( colorName ) {
codeCSS += " --thm-bg" + colorName + ": " + style[ 'bg' + colorName ] + ";\n";
} );
codeCSS += "}\n";
return codeCSS;
}
function codeBackground( themeName, style ) {
var codeCSS = '';
THEME_COLOR_NAMES.forEach( function ( colorName ) {
codeCSS += "body.dom-theme-" + themeName + ".thm-bg" + colorName +
" { background-color: " + style[ 'bg' + colorName ] + " }\n";
codeCSS += "body.dom-theme-" + themeName + " .thm-fg" + colorName +
" { color: " + style[ 'fg' + colorName ] + " }\n";
codeCSS += "body.dom-theme-" + themeName + " .thm-bg" + colorName +
" { background-color: " + style[ 'bg' + colorName ] + " }\n";
codeCSS += "body.dom-theme-" + themeName + " .thm-bg" + colorName + "-bottom" +
" { background: linear-gradient(to top," +
style[ 'bg' + colorName ] + ",transparent) }\n";
codeCSS += "body.dom-theme-" + themeName + " .thm-bg" + colorName + "-top" +
" { background: linear-gradient(to bottom," +
style[ 'bg' + colorName ] + ",transparent) }\n";
codeCSS += "body.dom-theme-" + themeName + " .thm-bg" + colorName + "-left" +
" { background: linear-gradient(to right," +
style[ 'bg' + colorName ] + ",transparent) }\n";
codeCSS += "body.dom-theme-" + themeName + " .thm-bg" + colorName + "-right" +
" { background: linear-gradient(to left," +
style[ 'bg' + colorName ] + ",transparent) }\n";
if ( !isNaN( parseInt( colorName ) ) ) return;
codeCSS += "body.dom-theme-" + themeName + " .thm-svg-fill" + colorName +
" { fill: " +
style[ 'bg' + colorName ] + " }\n";
codeCSS += "body.dom-theme-" + themeName + " .thm-svg-stroke" + colorName +
" { stroke: " +
style[ 'bg' + colorName ] + " }\n";
} );
return codeCSS;
}
function codeElevation( themeName, style ) {
var luminance = Color.luminance( style.bg2 );
var elevationColor = luminance < .6 ?
addAlpha( style.white, Math.ceil( 10 * luminance ) ) : addAlpha( style.black, '6' );
var codeCSS = '';
[ 0, 1, 2, 3, 4, 6, 8, 9, 12, 16, 24 ].forEach( function ( elevation ) {
codeCSS += "body.dom-theme-" + themeName + " .thm-ele" + elevation + " {\n" +
" box-shadow: 0 " + elevation + "px " + ( 2 * elevation ) + "px " + elevationColor + "\n" +
"}\n";
} );
return codeCSS;
}
function applyTheme( name, target ) {
if ( typeof target === 'undefined' ) target = document.body;
if ( !THEMES.css[ name ] ) {
console.error( "This theme has not been registered: ", name );
return;
}
var body = document.body;
if ( typeof THEMES.current === 'string' ) {
this.removeClass( body, "dom-theme-" + THEMES.current );
}
THEMES.current = name;
this.addClass( body, "dom-theme-" + THEMES.current );
}
function completeWithDefaultValues( style ) {
if ( typeof style === 'undefined' ) style = {};
if ( typeof style.bg0 !== 'string' ) style.bg0 = "#E0E0E0";
if ( typeof style.bg1 !== 'string' ) style.bg1 = "#F5F5F5";
if ( typeof style.bg2 !== 'string' ) style.bg2 = "#FAFAFA";
if ( typeof style.bg3 !== 'string' ) style.bg3 = "#FFF";
if ( typeof style.bgP !== 'string' ) style.bgP = "#3E50B4";
if ( typeof style.bgPD !== 'string' ) style.bgPD = dark( style.bgP );
if ( typeof style.bgPL !== 'string' ) style.bgPL = light( style.bgP );
if ( typeof style.bgS !== 'string' ) style.bgS = "#FF3F80";
if ( typeof style.bgSD !== 'string' ) style.bgSD = dark( style.bgS );
if ( typeof style.bgSL !== 'string' ) style.bgSL = light( style.bgS );
if ( typeof style.white === 'undefined' ) style.white = '#fff';
if ( typeof style.black === 'undefined' ) style.black = '#000';
THEME_COLOR_NAMES.forEach( function ( name ) {
var bg = style[ 'bg' + name ];
var luminance = Color.luminance( bg );
style[ 'fg' + name ] = luminance < .6 ? style.white : style.black;
} );
return style;
}
function dark( color ) {
var percent = .25;
var darkColor = new Color( color );
darkColor.rgb2hsl();
darkColor.L *= 1 - percent;
darkColor.hsl2rgb();
return darkColor.stringify();
}
function light( color ) {
var percent = .4;
var lightColor = new Color( color );
lightColor.rgb2hsl();
lightColor.L = percent + ( 1 - percent ) * lightColor.L;
lightColor.hsl2rgb();
return lightColor.stringify();
}
/**
* @param {string} color - RGB color in format #xxx or #xxxxxx.
* @param {string} alpha - Single char between 0 and F.
*/
function addAlpha( color, alpha ) {
if ( color.length < 5 ) return color + alpha;
return color + alpha + alpha;
}