123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- define("dojox/charting/widget/SelectableLegend", ["dojo/_base/lang", "dojo/_base/array", "dojo/_base/declare", "dojo/query", "dojo/_base/html",
- "dojo/_base/connect", "dojo/_base/Color", "./Legend", "dijit/form/CheckBox", "../action2d/Highlight",
- "dojox/lang/functional", "dojox/gfx/fx", "dojo/keys", "dojo/_base/event", "dojo/dom-construct",
- "dojo/dom-prop"],
- function(lang, arrayUtil, declare, query, html, hub, Color, Legend, CheckBox,
- Highlight, df, fx, keys, event, dom, domProp){
- /*=====
- var Legend = dojox.charting.widget.Legend;
- =====*/
- var FocusManager = declare(null, {
- // summary:
- // It will take legend as a tab stop, and using
- // cursor keys to navigate labels within the legend.
- constructor: function(legend){
- this.legend = legend;
- this.index = 0;
- this.horizontalLength = this._getHrizontalLength();
- arrayUtil.forEach(legend.legends, function(item, i){
- if(i > 0){
- query("input", item).attr("tabindex", -1);
- }
- });
- this.firstLabel = query("input", legend.legends[0])[0];
- hub.connect(this.firstLabel, "focus", this, function(){this.legend.active = true;});
- hub.connect(this.legend.domNode, "keydown", this, "_onKeyEvent");
- },
- _getHrizontalLength: function(){
- var horizontal = this.legend.horizontal;
- if(typeof horizontal == "number"){
- return Math.min(horizontal, this.legend.legends.length);
- }else if(!horizontal){
- return 1;
- }else{
- return this.legend.legends.length;
- }
- },
- _onKeyEvent: function(e){
- // if not focused
- if(!this.legend.active){
- return;
- }
- // lose focus
- if(e.keyCode == keys.TAB){
- this.legend.active = false;
- return;
- }
- // handle with arrow keys
- var max = this.legend.legends.length;
- switch(e.keyCode){
- case keys.LEFT_ARROW:
- this.index--;
- if(this.index < 0){
- this.index += max;
- }
- break;
- case keys.RIGHT_ARROW:
- this.index++;
- if(this.index >= max){
- this.index -= max;
- }
- break;
- case keys.UP_ARROW:
- if(this.index - this.horizontalLength >= 0){
- this.index -= this.horizontalLength;
- }
- break;
- case keys.DOWN_ARROW:
- if(this.index + this.horizontalLength < max){
- this.index += this.horizontalLength;
- }
- break;
- default:
- return;
- }
- this._moveToFocus();
- Event.stop(e);
- },
- _moveToFocus: function(){
- query("input", this.legend.legends[this.index])[0].focus();
- }
- });
-
- declare("dojox.charting.widget.SelectableLegend", Legend, {
- // summary:
- // An enhanced chart legend supporting interactive events on data series
-
- // theme component
- outline: false, // outline of vanished data series
- transitionFill: null, // fill of deselected data series
- transitionStroke: null, // stroke of deselected data series
-
- postCreate: function(){
- this.legends = [];
- this.legendAnim = {};
- this.inherited(arguments);
- },
- refresh: function(){
- this.legends = [];
- this.inherited(arguments);
- this._applyEvents();
- new FocusManager(this);
- },
- _addLabel: function(dyn, label){
- this.inherited(arguments);
- // create checkbox
- var legendNodes = query("td", this.legendBody);
- var currentLegendNode = legendNodes[legendNodes.length - 1];
- this.legends.push(currentLegendNode);
- var checkbox = new CheckBox({checked: true});
- dom.place(checkbox.domNode, currentLegendNode, "first");
- // connect checkbox and existed label
- var label = query("label", currentLegendNode)[0];
- domProp.set(label, "for", checkbox.id);
- },
- _applyEvents: function(){
- // summary:
- // Apply click-event on checkbox and hover-event on legend icon,
- // highlight data series or toggle it.
- // if the chart has not yet been refreshed it will crash here (targetData.group == null)
- if(this.chart.dirty){
- return;
- }
- arrayUtil.forEach(this.legends, function(legend, i){
- var targetData, shapes = [], plotName, seriesName;
- if(this._isPie()){
- targetData = this.chart.stack[0];
- shapes.push(targetData.group.children[i]);
- plotName = targetData.name;
- seriesName = this.chart.series[0].name;
- }else{
- targetData = this.chart.series[i];
- shapes = targetData.group.children;
- plotName = targetData.plot;
- seriesName = targetData.name;
- }
- var originalDyn = {
- fills : df.map(shapes, "x.getFill()"),
- strokes: df.map(shapes, "x.getStroke()")
- };
- // toggle action
- var legendCheckBox = query(".dijitCheckBox", legend)[0];
- hub.connect(legendCheckBox, "onclick", this, function(e){
- this._toggle(shapes, i, legend.vanished, originalDyn, seriesName, plotName);
- legend.vanished = !legend.vanished;
- e.stopPropagation();
- });
-
- // highlight action
- var legendIcon = query(".dojoxLegendIcon", legend)[0],
- iconShape = this._getFilledShape(this._surfaces[i].children);
- arrayUtil.forEach(["onmouseenter", "onmouseleave"], function(event){
- hub.connect(legendIcon, event, this, function(e){
- this._highlight(e, iconShape, shapes, i, legend.vanished, originalDyn, seriesName, plotName);
- });
- }, this);
- },this);
- },
- _toggle: function(shapes, index, isOff, dyn, seriesName, plotName){
- arrayUtil.forEach(shapes, function(shape, i){
- var startFill = dyn.fills[i],
- endFill = this._getTransitionFill(plotName),
- startStroke = dyn.strokes[i],
- endStroke = this.transitionStroke;
- if(startFill){
- if(endFill && (typeof startFill == "string" || startFill instanceof Color)){
- fx.animateFill({
- shape: shape,
- color: {
- start: isOff ? endFill : startFill,
- end: isOff ? startFill : endFill
- }
- }).play();
- }else{
- shape.setFill(isOff ? startFill : endFill);
- }
- }
- if(startStroke && !this.outline){
- shape.setStroke(isOff ? startStroke : endStroke);
- }
- }, this);
- },
- _highlight: function(e, iconShape, shapes, index, isOff, dyn, seriesName, plotName){
- if(!isOff){
- var anim = this._getAnim(plotName),
- isPie = this._isPie(),
- type = formatEventType(e.type);
- // highlight the label icon,
- var label = {
- shape: iconShape,
- index: isPie ? "legend" + index : "legend",
- run: {name: seriesName},
- type: type
- };
- anim.process(label);
- // highlight the data items
- arrayUtil.forEach(shapes, function(shape, i){
- shape.setFill(dyn.fills[i]);
- var o = {
- shape: shape,
- index: isPie ? index : i,
- run: {name: seriesName},
- type: type
- };
- anim.duration = 100;
- anim.process(o);
- });
- }
- },
- _getAnim: function(plotName){
- if(!this.legendAnim[plotName]){
- this.legendAnim[plotName] = new Highlight(this.chart, plotName);
- }
- return this.legendAnim[plotName];
- },
- _getTransitionFill: function(plotName){
- // Since series of stacked charts all start from the base line,
- // fill the "front" series with plotarea color to make it disappear .
- if(this.chart.stack[this.chart.plots[plotName]].declaredClass.indexOf("dojox.charting.plot2d.Stacked") != -1){
- return this.chart.theme.plotarea.fill;
- }
- return null;
- },
- _getFilledShape: function(shapes){
- // summary:
- // Get filled shape in legend icon which would be highlighted when hovered
- var i = 0;
- while(shapes[i]){
- if(shapes[i].getFill())return shapes[i];
- i++;
- }
- },
- _isPie: function(){
- return this.chart.stack[0].declaredClass == "dojox.charting.plot2d.Pie";
- }
- });
-
- function formatEventType(type){
- if(type == "mouseenter")return "onmouseover";
- if(type == "mouseleave")return "onmouseout";
- return "on" + type;
- }
- return dojox.charting.widget.SelectableLegend;
- });
|