source: Dev/branches/rest-dojo-ui/client/dojox/charting/widget/SelectableLegend.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 7.5 KB
Line 
1define(["dojo/_base/lang", "dojo/_base/array", "dojo/_base/declare", "dojo/query", "dojo/_base/html",
2                "dojo/_base/connect", "dojo/_base/Color", "./Legend", "dijit/form/CheckBox", "../action2d/Highlight",
3                "dojox/lang/functional", "dojox/gfx/fx", "dojo/keys", "dojo/_base/event", "dojo/dom-construct",
4                "dojo/dom-prop"],
5        function(lang, arrayUtil, declare, query, html, hub, Color, Legend, CheckBox,
6                         Highlight, df, fx, keys, event, dom, domProp){
7/*=====
8var Legend = dojox.charting.widget.Legend;
9=====*/
10        var FocusManager = declare(null, {
11                //      summary:
12                //              It will take legend as a tab stop, and using
13                //              cursor keys to navigate labels within the legend.
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        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.inherited(arguments);
96                },
97                refresh: function(){
98                        this.legends = [];
99                        this.inherited(arguments);
100                        this._applyEvents();
101                        new FocusManager(this);
102                },
103                _addLabel: function(dyn, label){
104                        this.inherited(arguments);
105                        //      create checkbox
106                        var legendNodes = query("td", this.legendBody);
107                        var currentLegendNode = legendNodes[legendNodes.length - 1];
108                        this.legends.push(currentLegendNode);
109                        var checkbox = new CheckBox({checked: true});
110                        dom.place(checkbox.domNode, currentLegendNode, "first");
111                        // connect checkbox and existed label
112                        var label = query("label", currentLegendNode)[0];
113                        domProp.set(label, "for", checkbox.id);
114                },
115                _applyEvents: function(){
116                        // summary:
117                        //              Apply click-event on checkbox and hover-event on legend icon,
118                        //              highlight data series or toggle it.
119                        // if the chart has not yet been refreshed it will crash here (targetData.group == null)
120                        if(this.chart.dirty){
121                                return;
122                        }
123                        arrayUtil.forEach(this.legends, function(legend, i){
124                                var targetData, shapes = [], plotName, seriesName;
125                                if(this._isPie()){
126                                        targetData = this.chart.stack[0];
127                                        shapes.push(targetData.group.children[i]);
128                                        plotName = targetData.name;
129                                        seriesName = this.chart.series[0].name;
130                                }else{
131                                        targetData = this.chart.series[i];
132                                        shapes = targetData.group.children;
133                                        plotName = targetData.plot;
134                                        seriesName = targetData.name;
135                                }
136                                var originalDyn = {
137                                        fills : df.map(shapes, "x.getFill()"),
138                                        strokes: df.map(shapes, "x.getStroke()")
139                                };
140                                //      toggle action
141                                var legendCheckBox = query(".dijitCheckBox", legend)[0];
142                                hub.connect(legendCheckBox, "onclick", this, function(e){
143                                        this._toggle(shapes, i, legend.vanished, originalDyn, seriesName, plotName);
144                                        legend.vanished = !legend.vanished;
145                                        e.stopPropagation();
146                                });
147                               
148                                //      highlight action
149                                var legendIcon = query(".dojoxLegendIcon", legend)[0],
150                                        iconShape = this._getFilledShape(this._surfaces[i].children);
151                                arrayUtil.forEach(["onmouseenter", "onmouseleave"], function(event){
152                                        hub.connect(legendIcon, event, this, function(e){
153                                                this._highlight(e, iconShape, shapes, i, legend.vanished, originalDyn, seriesName, plotName);
154                                        });
155                                }, this);
156                        },this);
157                },
158                _toggle: function(shapes, index, isOff, dyn, seriesName, plotName){
159                        arrayUtil.forEach(shapes, function(shape, i){
160                                var startFill = dyn.fills[i],
161                                        endFill = this._getTransitionFill(plotName),
162                                        startStroke = dyn.strokes[i],
163                                        endStroke = this.transitionStroke;
164                                if(startFill){
165                                        if(endFill && (typeof startFill == "string" || startFill instanceof Color)){
166                                                fx.animateFill({
167                                                        shape: shape,
168                                                        color: {
169                                                                start: isOff ? endFill : startFill,
170                                                                end: isOff ? startFill : endFill
171                                                        }
172                                                }).play();
173                                        }else{
174                                                shape.setFill(isOff ? startFill : endFill);
175                                        }
176                                }
177                                if(startStroke && !this.outline){
178                                        shape.setStroke(isOff ? startStroke : endStroke);
179                                }
180                        }, this);
181                },
182                _highlight: function(e, iconShape, shapes, index, isOff, dyn, seriesName, plotName){
183                        if(!isOff){
184                                var anim = this._getAnim(plotName),
185                                        isPie = this._isPie(),
186                                        type = formatEventType(e.type);
187                                //      highlight the label icon,
188                                var label = {
189                                        shape: iconShape,
190                                        index: isPie ? "legend" + index : "legend",
191                                        run: {name: seriesName},
192                                        type: type
193                                };
194                                anim.process(label);
195                                //      highlight the data items
196                                arrayUtil.forEach(shapes, function(shape, i){
197                                        shape.setFill(dyn.fills[i]);
198                                        var o = {
199                                                shape: shape,
200                                                index: isPie ? index : i,
201                                                run: {name: seriesName},
202                                                type: type
203                                        };
204                                        anim.duration = 100;
205                                        anim.process(o);
206                                });
207                        }
208                },
209                _getAnim: function(plotName){
210                        if(!this.legendAnim[plotName]){
211                                this.legendAnim[plotName] = new Highlight(this.chart, plotName);
212                        }
213                        return this.legendAnim[plotName];
214                },
215                _getTransitionFill: function(plotName){
216                        // Since series of stacked charts all start from the base line,
217                        // fill the "front" series with plotarea color to make it disappear .
218                        if(this.chart.stack[this.chart.plots[plotName]].declaredClass.indexOf("dojox.charting.plot2d.Stacked") != -1){
219                                return this.chart.theme.plotarea.fill;
220                        }
221                        return null;
222                },
223                _getFilledShape: function(shapes){
224                        //      summary:
225                        //              Get filled shape in legend icon which would be highlighted when hovered
226                        var i = 0;
227                        while(shapes[i]){
228                                if(shapes[i].getFill())return shapes[i];
229                                i++;
230                        }
231                },
232                _isPie: function(){
233                        return this.chart.stack[0].declaredClass == "dojox.charting.plot2d.Pie";
234                }
235        });
236       
237        function formatEventType(type){
238                if(type == "mouseenter")return "onmouseover";
239                if(type == "mouseleave")return "onmouseout";
240                return "on" + type;
241        }
242
243        return dojox.charting.widget.SelectableLegend;
244});
Note: See TracBrowser for help on using the repository browser.