source: Dev/trunk/src/client/dojox/charting/widget/SelectableLegend.js

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 7.9 KB
RevLine 
[483]1define(["dojo/_base/array", "dojo/_base/declare", "dojo/query",
2                "dojo/_base/connect", "dojo/_base/Color", "./Legend", "dijit/form/CheckBox", "../action2d/Highlight",
3                "dojox/lang/functional", "dojox/gfx/fx", "dojo/keys", "dojo/dom-construct",
4                "dojo/dom-prop"],
5        function(arrayUtil, declare, query, hub, Color, Legend, CheckBox,
6                         Highlight, df, fx, keys, dom, domProp){
7
8        var FocusManager = declare(null, {
9                // summary:
10                //              It will take legend as a tab stop, and using
11                //              cursor keys to navigate labels within the legend.
12                // tags:
13                //              private
14                constructor: function(legend){
15                        this.legend = legend;
16                        this.index = 0;
17                        this.horizontalLength = this._getHrizontalLength();
18                        arrayUtil.forEach(legend.legends, function(item, i){
19                                if(i > 0){
20                                        query("input", item).attr("tabindex", -1);
21                                }
22                        });
23                        this.firstLabel = query("input", legend.legends[0])[0];
24                        hub.connect(this.firstLabel, "focus", this, function(){this.legend.active = true;});
25                        hub.connect(this.legend.domNode, "keydown", this, "_onKeyEvent");
26                },
27                _getHrizontalLength: function(){
28                        var horizontal = this.legend.horizontal;
29                        if(typeof horizontal == "number"){
30                                return Math.min(horizontal, this.legend.legends.length);
31                        }else if(!horizontal){
32                                return 1;
33                        }else{
34                                return this.legend.legends.length;
35                        }
36                },
37                _onKeyEvent: function(e){
38                        //      if not focused
39                        if(!this.legend.active){
40                                return;
41                        }
42                        //      lose focus
43                        if(e.keyCode == keys.TAB){
44                                this.legend.active = false;
45                                return;
46                        }
47                        //      handle with arrow keys
48                        var max = this.legend.legends.length;
49                        switch(e.keyCode){
50                                case keys.LEFT_ARROW:
51                                        this.index--;
52                                        if(this.index < 0){
53                                                this.index += max;
54                                        }
55                                        break;
56                                case keys.RIGHT_ARROW:
57                                        this.index++;
58                                        if(this.index >= max){
59                                                this.index -= max;
60                                        }
61                                        break;
62                                case keys.UP_ARROW:
63                                        if(this.index - this.horizontalLength >= 0){
64                                                this.index -= this.horizontalLength;
65                                        }
66                                        break;
67                                case keys.DOWN_ARROW:
68                                        if(this.index + this.horizontalLength < max){
69                                                this.index += this.horizontalLength;
70                                        }
71                                        break;
72                                default:
73                                        return;
74                        }
75                        this._moveToFocus();
76                        Event.stop(e);
77                },
78                _moveToFocus: function(){
79                        query("input", this.legend.legends[this.index])[0].focus();
80                }
81        });
82                       
83        var SelectableLegend = declare("dojox.charting.widget.SelectableLegend", Legend, {
84                // summary:
85                //              An enhanced chart legend supporting interactive events on data series
86               
87                //      theme component
88                outline:                        false,  //      outline of vanished data series
89                transitionFill:         null,   //      fill of deselected data series
90                transitionStroke:       null,   //      stroke of deselected data series
91               
92                postCreate: function(){
93                        this.legends = [];
94                        this.legendAnim = {};
95                        this._cbs = [];
96                        this.inherited(arguments);
97                },
98                refresh: function(){
99                        this.legends = [];
100                        this._clearLabels();
101                        this.inherited(arguments);
102                        this._applyEvents();
103                        new FocusManager(this);
104                },
105                _clearLabels: function(){
106                        var cbs = this._cbs;
107                        while(cbs.length){
108                                cbs.pop().destroyRecursive();
109                        }
110                },
111                _addLabel: function(dyn, label){
112                        this.inherited(arguments);
113                        //      create checkbox
114                        var legendNodes = query("td", this.legendBody);
115                        var currentLegendNode = legendNodes[legendNodes.length - 1];
116                        this.legends.push(currentLegendNode);
117                        var checkbox = new CheckBox({checked: true});
118                        this._cbs.push(checkbox);
119                        dom.place(checkbox.domNode, currentLegendNode, "first");
120                        // connect checkbox and existed label
121                        var clabel = query("label", currentLegendNode)[0];
122                        domProp.set(clabel, "for", checkbox.id);
123                },
124                _applyEvents: function(){
125                        // summary:
126                        //              Apply click-event on checkbox and hover-event on legend icon,
127                        //              highlight data series or toggle it.
128                       
129                        // if the chart has not yet been refreshed it will crash here (targetData.group == null)
130                        if(this.chart.dirty){
131                                return;
132                        }
133                        arrayUtil.forEach(this.legends, function(legend, i){
134                                var targetData, shapes = [], plotName, seriesName;
135                                if(this._isPie()){
136                                        targetData = this.chart.stack[0];
137                                        shapes.push(targetData.group.children[i]);
138                                        plotName = targetData.name;
139                                        seriesName = this.chart.series[0].name;
140                                }else{
141                                        targetData = this.chart.series[i];
142                                        shapes = targetData.group.children;
143                                        plotName = targetData.plot;
144                                        seriesName = targetData.name;
145                                }
146                                var originalDyn = {
147                                        fills : df.map(shapes, "x.getFill()"),
148                                        strokes: df.map(shapes, "x.getStroke()")
149                                };
150                                //      toggle action
151                                var legendCheckBox = query(".dijitCheckBox", legend)[0];
152                                hub.connect(legendCheckBox, "onclick", this, function(e){
153                                        this._toggle(shapes, i, legend.vanished, originalDyn, seriesName, plotName);
154                                        legend.vanished = !legend.vanished;
155                                        e.stopPropagation();
156                                });
157                               
158                                //      highlight action
159                                var legendIcon = query(".dojoxLegendIcon", legend)[0],
160                                        iconShape = this._getFilledShape(this._surfaces[i].children);
161                                arrayUtil.forEach(["onmouseenter", "onmouseleave"], function(event){
162                                        hub.connect(legendIcon, event, this, function(e){
163                                                this._highlight(e, iconShape, shapes, i, legend.vanished, originalDyn, seriesName, plotName);
164                                        });
165                                }, this);
166                        },this);
167                },
168                _toggle: function(shapes, index, isOff, dyn, seriesName, plotName){
169                        arrayUtil.forEach(shapes, function(shape, i){
170                                var startFill = dyn.fills[i],
171                                        endFill = this._getTransitionFill(plotName),
172                                        startStroke = dyn.strokes[i],
173                                        endStroke = this.transitionStroke;
174                                if(startFill){
175                                        if(endFill && (typeof startFill == "string" || startFill instanceof Color)){
176                                                fx.animateFill({
177                                                        shape: shape,
178                                                        color: {
179                                                                start: isOff ? endFill : startFill,
180                                                                end: isOff ? startFill : endFill
181                                                        }
182                                                }).play();
183                                        }else{
184                                                shape.setFill(isOff ? startFill : endFill);
185                                        }
186                                }
187                                if(startStroke && !this.outline){
188                                        shape.setStroke(isOff ? startStroke : endStroke);
189                                }
190                        }, this);
191                },
192                _highlight: function(e, iconShape, shapes, index, isOff, dyn, seriesName, plotName){
193                        if(!isOff){
194                                var anim = this._getAnim(plotName),
195                                        isPie = this._isPie(),
196                                        type = formatEventType(e.type);
197                                //      highlight the label icon,
198                                var label = {
199                                        shape: iconShape,
200                                        index: isPie ? "legend" + index : "legend",
201                                        run: {name: seriesName},
202                                        type: type
203                                };
204                                anim.process(label);
205                                //      highlight the data items
206                                arrayUtil.forEach(shapes, function(shape, i){
207                                        shape.setFill(dyn.fills[i]);
208                                        var o = {
209                                                shape: shape,
210                                                index: isPie ? index : i,
211                                                run: {name: seriesName},
212                                                type: type
213                                        };
214                                        anim.duration = 100;
215                                        anim.process(o);
216                                });
217                        }
218                },
219                _getAnim: function(plotName){
220                        if(!this.legendAnim[plotName]){
221                                this.legendAnim[plotName] = new Highlight(this.chart, plotName);
222                                // calling this is marking the plot dirty however here this is a "fake" highlight action
223                                // we don't want to re-render the chart, _highlight is the in charge of running the animation
224                                this.chart.getPlot(plotName).dirty = false;
225                        }
226                        return this.legendAnim[plotName];
227                },
228                _getTransitionFill: function(plotName){
229                        // Since series of stacked charts all start from the base line,
230                        // fill the "front" series with plotarea color to make it disappear .
231                        if(this.chart.stack[this.chart.plots[plotName]].declaredClass.indexOf("dojox.charting.plot2d.Stacked") != -1){
232                                return this.chart.theme.plotarea.fill;
233                        }
234                        return null;
235                },
236                _getFilledShape: function(shapes){
237                        // summary:
238                        //              Get filled shape in legend icon which would be highlighted when hovered
239                        var i = 0;
240                        while(shapes[i]){
241                                if(shapes[i].getFill())return shapes[i];
242                                i++;
243                        }
244                        return null;
245                },
246                _isPie: function(){
247                        return this.chart.stack[0].declaredClass == "dojox.charting.plot2d.Pie";
248                },
249                destroy: function(){
250                        this._clearLabels();
251                        this.inherited(arguments);
252                }
253        });
254       
255        function formatEventType(type){
256                if(type == "mouseenter")return "onmouseover";
257                if(type == "mouseleave")return "onmouseout";
258                return "on" + type;
259        }
260
261        return SelectableLegend;
262});
Note: See TracBrowser for help on using the repository browser.