dojox/charting/Theme.js

  • Provides:

    • dojox.charting.Theme
  • Requires:

    • dojox.color in common
    • dojox.color.Palette in common
    • dojox.lang.utils in common
    • dojox.gfx.gradutils in common
  • dojox.charting.Theme

    • type
      Function
    • summary
      Initialize a theme using the keyword arguments.  Note that the arguments
      look like the example (above), and may include a few more parameters.
    • description
      While you can set up style definitions on a chart directly (usually through the various add methods
      on a dojox.charting.Chart2D object), a Theme simplifies this manual setup by allowing you to
      pre-define all of the various visual parameters of each element in a chart.
      
      Most of the properties of a Theme are straight-forward; if something is line-based (such as
      an axis or the ticks on an axis), they will be defined using basic stroke parameters.  Likewise,
      if an element is primarily block-based (such as the background of a chart), it will be primarily
      fill-based.
      
      In addition (for convenience), a Theme definition does not have to contain the entire JSON-based
      structure.  Each theme is built on top of a default theme (which serves as the basis for the theme
      "GreySkies"), and is mixed into the default theme object.  This allows you to create a theme based,
      say, solely on colors for data series.
      
      Defining a new theme is relatively easy; see any of the themes in dojox.charting.themes for examples
      on how to define your own.
      
      When you set a theme on a chart, the theme itself is deep-cloned.  This means that you cannot alter
      the theme itself after setting the theme value on a chart, and expect it to change your chart.  If you
      are looking to make alterations to a theme for a chart, the suggestion would be to create your own
      theme, based on the one you want to use, that makes those alterations before it is applied to a chart.
      
      Finally, a Theme contains a number of functions to facilitate rendering operations on a chart--the main
      helper of which is the ~next~ method, in which a chart asks for the information for the next data series
      to be rendered.
      
      A note on colors:
      The Theme constructor was on the use of dojox.color.Palette (in general) for creating a visually distinct
      set of colors for usage in a chart.  A palette is usually comprised of 5 different color definitions, and
      no more.  If you have a need to render a chart with more than 5 data elements, you can simply "push"
      new color definitions into the theme's .color array.  Make sure that you do that with the actual
      theme object from a Chart, and not in the theme itself (i.e. either do that before using .setTheme
      on a chart).
    • example
      The default theme (and structure) looks like so:
      
      	// all objects are structs used directly in dojox.gfx
      	chart:{
      		stroke: null,
      		fill: "white",
      		pageStyle: null // suggested page style as an object suitable for dojo.style()
      	},
      	plotarea:{
      		stroke: null,
      		fill: "white"
      	},
      	axis:{
      		stroke:	{ // the axis itself
      			color: "#333",
      			width: 1
      		},
      		tick: {	// used as a foundation for all ticks
      			color:     "#666",
      			position:  "center",
      			font:      "normal normal normal 7pt Tahoma",	// labels on axis
      			fontColor: "#333"								// color of labels
      		},
      		majorTick:	{ // major ticks on axis, and used for major gridlines
      			width:  1,
      			length: 6
      		},
      		minorTick:	{ // minor ticks on axis, and used for minor gridlines
      			width:  0.8,
      			length: 3
      		},
      		microTick:	{ // minor ticks on axis, and used for minor gridlines
      			width:  0.5,
      			length: 1
      		}
      	},
      	series: {
      		stroke:  {width: 1.5, color: "#333"},		// line
      		outline: {width: 0.1, color: "#ccc"},		// outline
      		//shadow:  {dx: 1, dy: 1, width: 2, color: [0, 0, 0, 0.3]},
      		shadow: null,								// no shadow
      		fill:    "#ccc",							// fill, if appropriate
      		font:    "normal normal normal 8pt Tahoma",	// if there's a label
      		fontColor: "#000"							// color of labels
      		labelWiring: {width: 1, color: "#ccc"},		// connect marker and target data item(slice, column, bar...)
      	},
      	marker: {	// any markers on a series
      		symbol:  "m-3,3 l3,-6 3,6 z",				// symbol
      		stroke:  {width: 1.5, color: "#333"},		// stroke
      		outline: {width: 0.1, color: "#ccc"},		// outline
      		shadow: null,								// no shadow
      		fill:    "#ccc",							// fill if needed
      		font:    "normal normal normal 8pt Tahoma",	// label
      		fontColor: "#000"
      	}
    • example
      Defining a new theme is pretty simple:
      
      	dojox.charting.themes.Grasslands = new dojox.charting.Theme({
      		colors: [ "#70803a", "#dde574", "#788062", "#b1cc5d", "#eff2c2" ]
      	});
      
      	myChart.setTheme(dojox.charting.themes.Grasslands);
    • parameters:
      • kwArgs: (typeof )
    • source: [view]
        kwArgs = kwArgs || {};


        // populate theme with defaults updating them if needed
        var def = dojox.charting.Theme.defaultTheme;
        dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(name){
         this[name] = dojo.delegate(def[name], kwArgs[name]);
        }, this);


        // personalize theme
        if(kwArgs.seriesThemes && kwArgs.seriesThemes.length){
         this.colors = null;
         this.seriesThemes = kwArgs.seriesThemes.slice(0);
        }else{
         this.seriesThemes = null;
         this.colors = (kwArgs.colors || dojox.charting.Theme.defaultColors).slice(0);
        }
        this.markerThemes = null;
        if(kwArgs.markerThemes && kwArgs.markerThemes.length){
         this.markerThemes = kwArgs.markerThemes.slice(0);
        }
        this.markers = kwArgs.markers ? dojo.clone(kwArgs.markers) : dojo.delegate(dojox.charting.Theme.defaultMarkers);


        // set flags
        this.noGradConv = kwArgs.noGradConv;
        this.noRadialConv = kwArgs.noRadialConv;
        if(kwArgs.reverseFills){
         this.reverseFills();
        }


        // private housekeeping
        this._current = 0;
        this._buildMarkerArray();
  • dojox.charting.Theme.shapeSpaces

    • type
      Object
    • summary
  • dojox.charting.Theme.clone

    • type
      Function
    • source: [view]
        var theme = new dojox.charting.Theme({
         // theme components
         chart: this.chart,
         plotarea: this.plotarea,
         axis: this.axis,
         series: this.series,
         marker: this.marker,
         // individual arrays
         colors: this.colors,
         markers: this.markers,
         seriesThemes: this.seriesThemes,
         markerThemes: this.markerThemes,
         // flags
         noGradConv: this.noGradConv,
         noRadialConv: this.noRadialConv
        });
        // copy custom methods
        dojo.forEach(
         ["clone", "clear", "next", "skip", "addMixin", "post", "getTick"],
         function(name){
          if(this.hasOwnProperty(name)){
           theme[name] = this[name];
          }
         },
         this
        );
        return theme; // dojox.charting.Theme
    • summary
      Clone the current theme.
    • return_summary
      dojox.charting.Theme
      The cloned theme; any alterations made will not affect the original.
    • returns
      dojox.charting.Theme
  • dojox.charting.Theme.clear

    • type
      Function
    • source: [view]
        this._current = 0;
    • summary
      Clear and reset the internal pointer to start fresh.
  • dojox.charting.Theme.next

    • type
      Function
    • parameters:
      • elementType: (typeof String)
        An optional element type (for use with series themes)
      • mixin: (typeof Object)
        An optional object to mix into the theme.
      • doPost: (typeof Boolean)
        A flag to post-process the results.
    • source: [view]
        var merge = dojox.lang.utils.merge, series, marker;
        if(this.colors){
         series = dojo.delegate(this.series);
         marker = dojo.delegate(this.marker);
         var color = new dojo.Color(this.colors[this._current % this.colors.length]), old;
         // modify the stroke
         if(series.stroke && series.stroke.color){
          series.stroke = dojo.delegate(series.stroke);
          old = new dojo.Color(series.stroke.color);
          series.stroke.color = new dojo.Color(color);
          series.stroke.color.a = old.a;
         }else{
          series.stroke = {color: color};
         }
         if(marker.stroke && marker.stroke.color){
          marker.stroke = dojo.delegate(marker.stroke);
          old = new dojo.Color(marker.stroke.color);
          marker.stroke.color = new dojo.Color(color);
          marker.stroke.color.a = old.a;
         }else{
          marker.stroke = {color: color};
         }
         // modify the fill
         if(!series.fill || series.fill.type){
          series.fill = color;
         }else{
          old = new dojo.Color(series.fill);
          series.fill = new dojo.Color(color);
          series.fill.a = old.a;
         }
         if(!marker.fill || marker.fill.type){
          marker.fill = color;
         }else{
          old = new dojo.Color(marker.fill);
          marker.fill = new dojo.Color(color);
          marker.fill.a = old.a;
         }
        }else{
         series = this.seriesThemes ?
          merge(this.series, this.seriesThemes[this._current % this.seriesThemes.length]) :
          this.series;
         marker = this.markerThemes ?
          merge(this.marker, this.markerThemes[this._current % this.markerThemes.length]) :
          series;
        }


        var symbol = marker && marker.symbol || this._markers[this._current % this._markers.length];


        var theme = {series: series, marker: marker, symbol: symbol};

        
        // advance the counter
        ++this._current;


        if(mixin){
         theme = this.addMixin(theme, elementType, mixin);
        }
        if(doPost){
         theme = this.post(theme, elementType);
        }


        return theme; // Object
    • summary
      Get the next color or series theme.
    • return_summary
      Object
      An object of the structure { series, marker, symbol }
    • returns
      Object
  • dojox.charting.Theme.skip

    • type
      Function
    • source: [view]
        ++this._current;
    • summary
      Skip the next internal color.
  • dojox.charting.Theme.addMixin

    • type
      Function
    • parameters:
      • theme: (typeof dojox.charting.Theme)
        The theme to mixin to.
      • elementType: (typeof String)
        The type of element in question. Can be "line", "bar" or "circle"
      • mixin: (typeof Object|Array)
        The object or objects to mix into the theme.
      • doPost: (typeof Boolean)
        If true, run the new theme through the post-processor.
    • source: [view]
        if(dojo.isArray(mixin)){
         dojo.forEach(mixin, function(m){
          theme = this.addMixin(theme, elementType, m);
         }, this);
        }else{
         var t = {};
         if("color" in mixin){
          if(elementType == "line" || elementType == "area"){
           dojo.setObject("series.stroke.color", mixin.color, t);
           dojo.setObject("marker.stroke.color", mixin.color, t);
          }else{
           dojo.setObject("series.fill", mixin.color, t);
          }
         }
         dojo.forEach(["stroke", "outline", "shadow", "fill", "font", "fontColor", "labelWiring"], function(name){
          var markerName = "marker" + name.charAt(0).toUpperCase() + name.substr(1),
           b = markerName in mixin;
          if(name in mixin){
           dojo.setObject("series." + name, mixin[name], t);
           if(!b){
            dojo.setObject("marker." + name, mixin[name], t);
           }
          }
          if(b){
           dojo.setObject("marker." + name, mixin[markerName], t);
          }
         });
         if("marker" in mixin){
          t.symbol = mixin.marker;
         }
         theme = dojox.lang.utils.merge(theme, t);
        }
        if(doPost){
         theme = this.post(theme, elementType);
        }
        return theme; // dojox.charting.Theme
    • summary
      Add a mixin object to the passed theme and process.
    • return_summary
      dojox.charting.Theme
      The new theme.
    • returns
      dojox.charting.Theme
  • dojox.charting.Theme.post

    • type
      Function
    • parameters:
      • theme: (typeof dojox.charting.Theme)
        The theme to post process with.
      • elementType: (typeof String)
        The type of element being filled.  Can be "bar" or "circle".
    • source: [view]
        var fill = theme.series.fill, t;
        if(!this.noGradConv && this.shapeSpaces[fill.space] && fill.type == "linear"){
         if(elementType == "bar"){
          // transpose start and end points
          t = {
           x1: fill.y1,
           y1: fill.x1,
           x2: fill.y2,
           y2: fill.x2
          };
         }else if(!this.noRadialConv && fill.space == "shape" && (elementType == "slice" || elementType == "circle")){
          // switch to radial
          t = {
           type: "radial",
           cx: 0,
           cy: 0,
           r: 100
          };
         }
         if(t){
          return dojox.lang.utils.merge(theme, {series: {fill: t}});
         }
        }
        return theme; // dojox.charting.Theme
    • summary
      Process any post-shape fills.
    • return_summary
      dojox.charting.Theme
      The post-processed theme.
    • returns
      dojox.charting.Theme
  • dojox.charting.Theme.getTick

    • type
      Function
    • parameters:
      • name: (typeof String)
        Tick name, can be "major", "minor", or "micro".
      • mixin: (typeof Object)
        Optional object to mix in to the tick.
    • source: [view]
        var tick = this.axis.tick, tickName = name + "Tick";
         merge = dojox.lang.utils.merge;
        if(tick){
         if(this.axis[tickName]){
          tick = merge(tick, this.axis[tickName]);
         }
        }else{
         tick = this.axis[tickName];
        }
        if(mixin){
         if(tick){
          if(mixin[tickName]){
           tick = merge(tick, mixin[tickName]);
          }
         }else{
          tick = mixin[tickName];
         }
        }
        return tick; // Object
    • summary
      Calculates and merges tick parameters.
    • returns
      Object
  • dojox.charting.Theme.inspectObjects

    • type
      Function
    • parameters:
      • f: (typeof )
    • source: [view]
        dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(name){
         f(this[name]);
        }, this);
        if(this.seriesThemes){
         dojo.forEach(this.seriesThemes, f);
        }
        if(this.markerThemes){
         dojo.forEach(this.markerThemes, f);
        }
    • summary
  • dojox.charting.Theme.reverseFills

    • type
      Function
    • source: [view]
        this.inspectObjects(function(o){
         if(o && o.fill){
          o.fill = dojox.gfx.gradutils.reverse(o.fill);
         }
        });
    • summary
  • dojox.charting.Theme.addMarker

    • summary
  • dojox.charting.Theme.setMarkers

    • summary
  • dojox.charting.Theme._buildMarkerArray

    • type
      Function
    • source: [view]
        this._markers = [];
        for(var p in this.markers){
         this._markers.push(this.markers[p]);
        }
    • summary
  • dojox.charting.Theme.shapeSpaces.shape

    • summary
  • dojox.charting.Theme.shapeSpaces.shapeX

    • summary
  • dojox.charting.Theme.shapeSpaces.shapeY

    • summary
  • dojox.charting.Theme._current

    • summary
  • dojox.charting.Theme._markers

    • summary
  • dojox.charting.Theme.colors

    • summary
  • dojox.charting.Theme.seriesThemes

    • summary
  • dojox.charting.Theme.markerThemes

    • summary
  • dojox.charting.Theme.markers

    • summary
  • dojox.charting.Theme.noGradConv

    • summary
  • dojox.charting.Theme.noRadialConv

    • summary
  • dojox.charting.Theme.__DefineColorArgs

    • type
      Function
    • parameters:
      • num: (typeof Number)
        The number of colors to generate.  Defaults to 5.
      • colors: (typeof String[]|dojo.Color[])
        A pre-defined set of colors; this is passed through to the Theme directly.
      • hue: (typeof Number)
        A hue to base the generated colors from (a number from 0 - 359).
      • saturation: (typeof Number)
        If a hue is passed, this is used for the saturation value (0 - 100).
      • low: (typeof Number)
        An optional value to determine the lowest value used to generate a color (HSV model)
      • high: (typeof Number)
        An optional value to determine the highest value used to generate a color (HSV model)
      • base: (typeof String|dojo.Color)
        A base color to use if we are defining colors using dojox.color.Palette
      • generator: (typeof String)
        The generator function name from dojox.color.Palette.
    • source: [view]
       this.num = num;
       this.colors = colors;
       this.hue = hue;
       this.saturation = saturation;
       this.low = low;
       this.high = high;
       this.base = base;
       this.generator = generator;
    • summary
      The arguments object that can be passed to define colors for a theme.
  • dojox.charting.Theme.__DefineColorArgs.num

    • type
      Number?
    • summary
      The number of colors to generate.  Defaults to 5.
  • dojox.charting.Theme.__DefineColorArgs.colors

    • type
      String[]|dojo.Color[]?
    • summary
      A pre-defined set of colors; this is passed through to the Theme directly.
  • dojox.charting.Theme.__DefineColorArgs.hue

    • type
      Number?
    • summary
      A hue to base the generated colors from (a number from 0 - 359).
  • dojox.charting.Theme.__DefineColorArgs.saturation

    • type
      Number?
    • summary
      If a hue is passed, this is used for the saturation value (0 - 100).
  • dojox.charting.Theme.__DefineColorArgs.low

    • type
      Number?
    • summary
      An optional value to determine the lowest value used to generate a color (HSV model)
  • dojox.charting.Theme.__DefineColorArgs.high

    • type
      Number?
    • summary
      An optional value to determine the highest value used to generate a color (HSV model)
  • dojox.charting.Theme.__DefineColorArgs.base

    • type
      String|dojo.Color?
    • summary
      A base color to use if we are defining colors using dojox.color.Palette
  • dojox.charting.Theme.__DefineColorArgs.generator

    • type
      String?
    • summary
      The generator function name from dojox.color.Palette.
  • dojox.charting.Theme.defaultMarkers

    • type
      Object
    • summary
  • dojox.charting.Theme.defaultMarkers.CIRCLE

    • summary
  • dojox.charting.Theme.defaultMarkers.SQUARE

    • summary
  • dojox.charting.Theme.defaultMarkers.DIAMOND

    • summary
  • dojox.charting.Theme.defaultMarkers.CROSS

    • summary
  • dojox.charting.Theme.defaultMarkers.X

    • summary
  • dojox.charting.Theme.defaultMarkers.TRIANGLE

    • summary
  • dojox.charting.Theme.defaultMarkers.TRIANGLE_INVERTED

    • summary
  • dojox.charting.Theme.defaultColors

    • summary
  • dojox.charting.Theme.defaultTheme

    • type
      Object
    • summary
  • dojox.charting.Theme.defaultTheme.chart

    • summary
  • dojox.charting.Theme.defaultTheme.fill

    • summary
  • dojox.charting.Theme.defaultTheme.pageStyle

    • summary
  • dojox.charting.Theme.defaultTheme.titleGap

    • summary
  • dojox.charting.Theme.defaultTheme.titlePos

    • summary
  • dojox.charting.Theme.defaultTheme.titleFont

    • summary
  • dojox.charting.Theme.defaultTheme.titleFontColor

    • summary
  • dojox.charting.Theme.defineColors

    • type
      Function
    • parameters:
      • kwArgs: (typeof dojox.charting.Theme.__DefineColorArgs)
        The arguments object used to define colors.
    • source: [view]
        kwArgs = kwArgs || {};
        var c = [], n = kwArgs.num || 5; // the number of colors to generate
        if(kwArgs.colors){
         // we have an array of colors predefined, so fix for the number of series.
         var l = kwArgs.colors.length;
         for(var i = 0; i < n; i++){
          c.push(kwArgs.colors[i % l]);
         }
         return c; // dojo.Color[]
        }
        if(kwArgs.hue){
         // single hue, generate a set based on brightness
         var s = kwArgs.saturation || 100; // saturation
         var st = kwArgs.low || 30;
         var end = kwArgs.high || 90;
         // we'd like it to be a little on the darker side.
         var l = (end + st) / 2;
         // alternately, use "shades"
         return dojox.color.Palette.generate(
          dojox.color.fromHsv(kwArgs.hue, s, l), "monochromatic"
         ).colors;
        }
        if(kwArgs.generator){
         // pass a base color and the name of a generator
         return dojox.color.Palette.generate(kwArgs.base, kwArgs.generator).colors;
        }
        return c; // dojo.Color[]
    • summary
      Generate a set of colors for the theme based on keyword
      arguments.
    • return_summary
      dojo.Color[]
      An array of colors for use in a theme.
    • returns
      dojo.Color[]
    • example
      
      	var colors = dojox.charting.Theme.defineColors({
      		base: "#369",
      		generator: "compound"
      	});
    • example
      
      	var colors = dojox.charting.Theme.defineColors({
      		hue: 60,
      		saturation: 90,
      		low: 30,
      		high: 80
      	});
  • dojox.charting.Theme.generateGradient

    • type
      Function
    • parameters:
      • fillPattern: (typeof )
      • colorFrom: (typeof )
      • colorTo: (typeof )
    • source: [view]
        var fill = dojo.delegate(fillPattern);
        fill.colors = [
         {offset: 0, color: colorFrom},
         {offset: 1, color: colorTo}
        ];
        return fill;
    • summary
  • dojox.charting.Theme.generateHslColor

    • type
      Function
    • parameters:
      • color: (typeof )
      • luminance: (typeof )
    • source: [view]
        color = new dojox.color.Color(color);
        var hsl = color.toHsl(),
         result = dojox.color.fromHsl(hsl.h, hsl.s, luminance);
        result.a = color.a; // add missing opacity
        return result;
    • summary
  • dojox.charting.Theme.generateHslGradient

    • type
      Function
    • parameters:
      • color: (typeof )
      • fillPattern: (typeof )
      • lumFrom: (typeof )
      • lumTo: (typeof )
    • source: [view]
        color = new dojox.color.Color(color);
        var hsl = color.toHsl(),
         colorFrom = dojox.color.fromHsl(hsl.h, hsl.s, lumFrom),
         colorTo = dojox.color.fromHsl(hsl.h, hsl.s, lumTo);
        colorFrom.a = colorTo.a = color.a; // add missing opacity
        return dojox.charting.Theme.generateGradient(fillPattern, colorFrom, colorTo); // Object
    • returns
      Object
    • summary
  • dojox.charting

    • type
      Object
    • summary
  • dojox

    • type
      Object
    • summary