[moodle] / contrib / plugins / grade / report / visual / flare_visualization / flare_visualization.as Repository:

Annotation of /contrib/plugins/grade/report/visual/flare_visualization/flare_visualization.as

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (view) (download)

1 : dservos 1.2 ///////////////////////////////////////////////////////////////////////////
2 :     // //
3 :     // NOTICE OF COPYRIGHT //
4 :     // //
5 :     // Moodle - Modular Object-Oriented Dynamic Learning Environment //
6 :     // http://moodle.org //
7 :     // //
8 :     // Copyright (C) 1999 onwards Martin Dougiamas http://moodle.com //
9 :     // //
10 :     // This program is free software; you can redistribute it and/or modify //
11 :     // it under the terms of the GNU General Public License as published by //
12 :     // the Free Software Foundation; either version 2 of the License, or //
13 :     // (at your option) any later version. //
14 :     // //
15 :     // This program is distributed in the hope that it will be useful, //
16 :     // but WITHOUT ANY WARRANTY; without even the implied warranty of //
17 :     // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
18 :     // GNU General Public License for more details: //
19 :     // //
20 :     // http://www.gnu.org/copyleft/gpl.html //
21 :     // //
22 :     ///////////////////////////////////////////////////////////////////////////
23 :    
24 :     /**
25 :     * This is the flex with flare based visualizer for the Moodle 2.x visual
26 :     * grade book plug-in. This should load the grade book data for a given
27 :     * visualization from the report/visual plug-in based on a set of flashvars
28 :     * passed to it from Moodle and display a visual repersenation.
29 :     */
30 : dservos 1.1 package {
31 : dservos 1.2 //Flare imports
32 : dservos 1.1 import flare.animate.Transitioner;
33 :     import flare.data.DataSet;
34 :     import flare.data.DataSource;
35 :     import flare.display.TextSprite;
36 :     import flare.vis.Visualization;
37 :     import flare.vis.controls.HoverControl;
38 :     import flare.vis.data.Data;
39 :     import flare.vis.data.DataSprite;
40 :     import flare.vis.legend.Legend;
41 : dservos 1.2 import flare.vis.legend.LegendItem;
42 : dservos 1.1 import flare.vis.operator.encoder.ColorEncoder;
43 : dservos 1.3 import flare.vis.operator.encoder.Encoder;
44 : dservos 1.1 import flare.vis.operator.encoder.ShapeEncoder;
45 : dservos 1.3 import flare.vis.operator.encoder.SizeEncoder;
46 : dservos 1.1 import flare.vis.operator.layout.AxisLayout;
47 : dservos 1.3 import flare.vis.operator.layout.CircleLayout;
48 :     import flare.vis.operator.layout.DendrogramLayout;
49 :     import flare.vis.operator.layout.ForceDirectedLayout;
50 :     import flare.vis.operator.layout.IndentedTreeLayout;
51 :     import flare.vis.operator.layout.Layout;
52 :     import flare.vis.operator.layout.NodeLinkTreeLayout;
53 :     import flare.vis.operator.layout.PieLayout;
54 :     import flare.vis.operator.layout.RadialTreeLayout;
55 :     import flare.vis.operator.layout.RandomLayout;
56 :     import flare.vis.operator.layout.StackedAreaLayout;
57 :     import flare.vis.operator.layout.TreeMapLayout;
58 :     import flare.vis.scale.Scale;
59 : dservos 1.1 import flare.vis.util.Filters;
60 :    
61 :     import flash.display.DisplayObject;
62 :     import flash.display.DisplayObjectContainer;
63 :     import flash.display.Sprite;
64 : dservos 1.3 import flash.errors.IOError;
65 : dservos 1.1 import flash.events.Event;
66 : dservos 1.3 import flash.events.IOErrorEvent;
67 : dservos 1.1 import flash.events.MouseEvent;
68 :     import flash.filters.GlowFilter;
69 :     import flash.geom.Rectangle;
70 :     import flash.net.URLLoader;
71 : dservos 1.3 import flash.net.URLRequest;
72 :     import flash.text.TextField;
73 : dservos 1.1 import flash.text.TextFormat;
74 :    
75 :     [SWF(width="800", height="600", backgroundColor="#ffffff", frameRate="30")]
76 : dservos 1.2 /**
77 :     * Main class for handling grade book data and greatating a visualization.
78 :     */
79 : dservos 1.1 public class flare_visualization extends Sprite
80 :     {
81 : dservos 1.2 /**
82 :     * The visualization object to be used in creating the visualization.
83 :     */
84 : dservos 1.1 private var vis:Visualization;
85 : dservos 1.2
86 :     /**
87 :     * A refernce to the currently displayed dialog box. If null no dialog
88 :     * box is currently being displayed.
89 :     */
90 : dservos 1.1 private var lastBox:Sprite = null;
91 : dservos 1.2
92 :     /**
93 :     * A refernce to the data sprite witch contains the data for witch the
94 :     * currently displayed dialog box is based on and a child of.
95 :     */
96 : dservos 1.1 private var lastBoxData:DataSprite = null;
97 : dservos 1.2
98 :     /**
99 :     * A container for the legends witch will be displayed on the righ hand
100 :     * side.
101 :     */
102 :     private var legends:Sprite;
103 :    
104 :     /**
105 :     * The hover control for the dialog box.
106 :     */
107 :     private var boxhc:HoverControl = new HoverControl();
108 :    
109 : dservos 1.3 private var settings:XML = new XML();
110 :    
111 :     private var dataURL:String;
112 :    
113 :     private var settingsURL:String;
114 :    
115 :     private var loadingMessage:TextSprite;
116 :    
117 : dservos 1.2 /**
118 :     * The constucter for the flare_visualization class.
119 :     * Calls on harvest_data and sets up the varibles from the flashvars.
120 :     */
121 : dservos 1.1 public function flare_visualization()
122 :     {
123 : dservos 1.3 loadingMessage = new TextSprite("Loading....", new TextFormat("monospace", 20, 0x0000FF, true));
124 :     addChild(loadingMessage);
125 :    
126 : dservos 1.2 // Call harvest_data, loading needed visualization data from moodle.
127 :     // The Moodle wwwroot, course id, users sessionid, users session cookie
128 :     // and session test data are needed to get the data from moodle are
129 :     // loaded threw flashvars.
130 : dservos 1.3 loaderInfo.addEventListener(Event.COMPLETE, function(evt:Event):void {
131 :     dataURL = loaderInfo.parameters['wwwroot'] + '/grade/report/visual/data.php?id=' + escape(loaderInfo.parameters['courseid']) + '&sessioncookie=' + escape(loaderInfo.parameters['sessioncookie']) + '&sessionid=' + escape(loaderInfo.parameters['sessionid']) + '&sessiontest=' + escape(loaderInfo.parameters['sessiontest']) + '&visid=' + escape(loaderInfo.parameters['visid']);
132 :     settingsURL = loaderInfo.parameters['wwwroot'] + '/grade/report/visual/visual_settings.php?id=' + escape(loaderInfo.parameters['courseid']) + '&visid=' + escape(loaderInfo.parameters['visid']);
133 :    
134 :     //dataURL = 'http://localhost/moodle/grade/report/visual/data.php?id=3&sessioncookie=&sessionid=ec7b77fa297d0454fa45367b42761d07&sessiontest=iqw4nC9hc7&visid=grade_distribution';
135 :     //settingsURL = 'http://localhost/moodle/grade/report/visual/visual_settings.php?id=3&visid=grade_distribution';
136 :    
137 :     harvest_data();
138 :     });
139 : dservos 1.1 }
140 :    
141 : dservos 1.2 /**
142 :     * Harvests the data from Moodle and calls on buildVis to build the
143 :     * visualization once the data has been loaded.
144 :     * TODO: Add a loading bar and more feed back about the loading process.
145 :     * @param url The url from witch to load the tab formated data for the visualization.
146 :     */
147 : dservos 1.3 public function harvest_data():void
148 : dservos 1.1 {
149 : dservos 1.3 loadingMessage.text ="Loading Settings....";
150 :     loadingMessage.x = loaderInfo.width/2 - loadingMessage.width/2;
151 :     loadingMessage.y = loaderInfo.height/2 - loadingMessage.height/2;
152 :    
153 :    
154 :     try{
155 :     var ds:DataSource = new DataSource(dataURL, "tab");
156 :     var settingsRequest:URLRequest = new URLRequest(settingsURL);
157 :     var settingsLoader:URLLoader = new URLLoader(settingsRequest);
158 :    
159 :     settingsLoader.addEventListener(IOErrorEvent.IO_ERROR, function(evt:IOErrorEvent):void {
160 :     error("Loading", evt.text);
161 :     });
162 :    
163 :     settingsLoader.addEventListener(Event.COMPLETE, function(evt:Event):void {
164 :     try{
165 :     settings = XML(settingsLoader.data);
166 :     loadingMessage.text = "Loading Data....";
167 :    
168 :     var dataLoader:URLLoader = ds.load();
169 :    
170 :     dataLoader.addEventListener(IOErrorEvent.IO_ERROR, function(evt:IOErrorEvent):void {
171 :     error("Loading", evt.text);
172 :     });
173 :    
174 :     dataLoader.addEventListener(Event.COMPLETE, function(evt:Event):void {
175 :     removeChild(addChild(loadingMessage));
176 :     var data:DataSet = dataLoader.data as DataSet;
177 :     buildVis(Data.fromDataSet(data));
178 :     });
179 :     } catch(e:Error) {
180 :     error("", e.message);
181 :     }
182 :     });
183 :     } catch(e:IOError) {
184 :     error("IO", e.message);
185 :     } catch(e:Error) {
186 :     error("", e.message)
187 :     }
188 :     }
189 :    
190 :     private function error(type:String = "", text:String = ""):void {
191 :     trace(type + " Error: " + text);
192 :    
193 :     var textfield:TextField = new TextSprite(type + " Error: " + text, new TextFormat("monospace", 12, 0xFF0000, true)).textField;
194 :     textfield.wordWrap = true;
195 :    
196 :     addChild(textfield);
197 : dservos 1.1 }
198 :    
199 : dservos 1.2 /**
200 :     * Find the max width between a container and all of it's decendence
201 :     * This dose not find the width of a container but the greatest width
202 :     * of an invdual component in it's decenedences.
203 :     * @param d The display container to find the max width of.
204 :     * @return the max width value of the display objects.
205 :     */
206 : dservos 1.1 private function getMaxWidth(d:DisplayObjectContainer):int {
207 :     var max:int = d.width;
208 :    
209 : dservos 1.2 for(var k:uint = 0; k < d.numChildren; k++ ) {
210 : dservos 1.1 var width:int = 0;
211 :    
212 :     if(d.getChildAt(k) is DisplayObjectContainer) {
213 :     width = getMaxWidth(DisplayObjectContainer(d.getChildAt(k)));
214 :     } else {
215 :     width = d.getChildAt(k).width;
216 :     }
217 :    
218 :     if(width > max) {
219 :     max = width;
220 :     }
221 :     }
222 :    
223 :     return max;
224 :     }
225 :    
226 : dservos 1.2 /**
227 :     * Simple function to retrun the greatest of two ints.
228 :     * @param num1 the first number to test
229 :     * @param num2 the second number to test
230 :     * @return the largest value between num1 and num2.
231 :     */
232 : dservos 1.1 private function max(num1:int, num2:int):int {
233 :     if(num1 > num2) {
234 :     return num1;
235 :     } else {
236 :     return num2;
237 :     }
238 :     }
239 :    
240 : dservos 1.2 /**
241 :     * Find the max height between a container and all of it's decendence
242 :     * This dose not find the width of a container but the greatest height
243 :     * of an invdual component in it's decenedences.
244 :     * @param d The display container to find the max height of.
245 :     * @return the max height value of the display objects.
246 :     */
247 : dservos 1.1 private function getMaxHeight(d:DisplayObjectContainer):int {
248 :     var max:int = d.height;
249 :    
250 : dservos 1.2 for(var k:uint = 0; k < d.numChildren; k++ ) {
251 : dservos 1.1 var height:int = 0;
252 :    
253 :     if(d.getChildAt(k) is DisplayObjectContainer) {
254 :     height = getMaxHeight(DisplayObjectContainer(d.getChildAt(k)));
255 :     } else {
256 :     height = d.getChildAt(k).height;
257 :     }
258 :    
259 :     if(height > max) {
260 :     max = height;
261 :     }
262 :     }
263 :    
264 :     return max;
265 :     }
266 :    
267 : dservos 1.3 private function nullify(o:*):* {
268 :     if(isnull(o)) {
269 :     return null;
270 :     } else {
271 :     return o;
272 :     }
273 :     }
274 :    
275 :     private function isnull(o:*):Boolean {
276 :     if(o == null || o.length == 0 || String(o).length == 0) {
277 :     return true;
278 :     } else {
279 :     return false;
280 :     }
281 :     }
282 :    
283 :     private function booleanify(o:*):* {
284 :     var ob:Object = nullify(o);
285 :    
286 :     if(String(ob).toLocaleLowerCase() == "false") {
287 :     return false;
288 :     } else if (String(ob).toLocaleLowerCase() == "true") {
289 :     return true;
290 :     }
291 :    
292 :     return ob;
293 :     }
294 :    
295 :     private function passSettings(theClass:Class, XMLSettings:XMLList, ... args):* {
296 :     var params:Array = new Array();
297 :    
298 :     for each(var arg:* in args) {
299 :     params.push(arg);
300 :     }
301 :    
302 :     for each(var param:* in XMLSettings) {
303 :     var cleanParam:* = booleanify(param);
304 :     if(cleanParam != null) {
305 :     params.push(cleanParam);
306 :     }
307 :     }
308 :    
309 :     switch(params.length) {
310 :     case 1: return new theClass(params[0]);
311 :     case 2: return new theClass(params[0], params[1]);
312 :     case 3: return new theClass(params[0], params[1], params[2]);
313 :     case 4: return new theClass(params[0], params[1], params[2], params[3]);
314 :     case 5: return new theClass(params[0], params[1], params[2], params[3], params[4]);
315 :     case 6: return new theClass(params[0], params[1], params[2], params[3], params[4], params[5]);
316 :     case 7: return new theClass(params[0], params[1], params[2], params[3], params[4], params[5], params[6]);
317 :     case 8: return new theClass(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7]);
318 :     case 9: return new theClass(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8]);
319 :     case 10: return new theClass(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9]);
320 :     default: return new theClass();
321 :     }
322 :     }
323 :    
324 :     private function toStringArray(xmllist:XMLList):Object {
325 :     if(xmllist.length() > 1) {
326 :     var array:Array = new Array;
327 :    
328 :     for each(var element:XML in xmllist) {
329 :     array.push(String(element));
330 :     }
331 :    
332 :     return array;
333 :     } else {
334 :     return String(xmllist);
335 :     }
336 :     }
337 :    
338 :     private function toNumberArray(xmllist:XMLList):Object {
339 :     if(xmllist.length() > 1) {
340 :     var array:Array = new Array;
341 :    
342 :     for each(var element:XML in xmllist) {
343 :     array.push(Number(element));
344 :     }
345 :    
346 :     return array;
347 :     } else {
348 :     return Number(xmllist);
349 :     }
350 :     }
351 :    
352 : dservos 1.2 /**
353 :     * Builds the visualization based on the loaded data.
354 :     * Also sets up the legends, buttons and controls.
355 :     * @param data The data that was loaded in from moodle.
356 :     */
357 : dservos 1.1 private function buildVis(data:Data):void
358 :     {
359 : dservos 1.3 if(!isnull(settings.edge)) {
360 :     for each(var edge:XML in settings.edge) {
361 :     data.createEdges(toStringArray(edge.sortby), toStringArray(edge.groupby));
362 :     }
363 :     }
364 :    
365 : dservos 1.1 vis = new Visualization(data);
366 : dservos 1.2 legends = new Sprite();
367 :    
368 :     // Set the functions to be called when a dialog box is hovered over.
369 :     boxhc.onRollOver = boxRollOver;
370 :     boxhc.onRollOut = boxRollOut;
371 : dservos 1.1
372 : dservos 1.3 // Set up the layout
373 :     var layout:Layout = new AxisLayout(settings.layout.xaxis.field, settings.layout.yaxis.field);
374 :     switch(int(settings.layout.type)) {
375 :     case 1: layout = passSettings(AxisLayout, settings.layout.setting, settings.layout.xaxis.field, settings.layout.yaxis.field);
376 :     break;
377 :     case 2: layout = passSettings(CircleLayout, settings.layout.setting);
378 :     break;
379 :     case 3: layout = passSettings(DendrogramLayout, settings.layout.setting);
380 :     break;
381 :     case 4: layout = passSettings(ForceDirectedLayout, settings.layout.setting);
382 :     break;
383 :     case 5: layout = passSettings(IndentedTreeLayout, settings.layout.setting);
384 :     break;
385 :     case 6: layout = passSettings(NodeLinkTreeLayout, settings.layout.setting);
386 :     break;
387 :     case 7: layout = passSettings(PieLayout, settings.layout.setting);
388 :     break;
389 :     case 8: layout = passSettings(RadialTreeLayout, settings.layout.setting);
390 :     break;
391 :     case 9: layout = new RandomLayout();
392 :     break;
393 :     case 10: layout = passSettings(StackedAreaLayout, settings.layout.setting);
394 :     break;
395 :     case 11: layout = new TreeMapLayout();
396 :     break;
397 :     default: layout = passSettings(AxisLayout, settings.layout.setting, settings.layout.xaxis.field, settings.layout.yaxis.field);
398 :     break;
399 :     }
400 :     vis.operators.add(layout);
401 :    
402 :     // Set up the encoders
403 :     var encoders:Array = new Array(settings.encoder.length);
404 :     for each(var encoder:XML in settings.encoder) {
405 :     var e:Encoder;
406 :    
407 :     switch(int(encoder.type)) {
408 :     case 1: e = passSettings(ColorEncoder, encoder.setting, encoder.datafield);
409 :     break;
410 :     case 2: e = passSettings(ShapeEncoder, encoder.setting, encoder.datafield);
411 :     break;
412 :     case 3: e = passSettings(SizeEncoder, encoder.setting, encoder.datafield);
413 :     break;
414 :     default: e = passSettings(ColorEncoder, encoder.setting, encoder.datafield);
415 :     break;
416 :     }
417 :    
418 :     encoders[encoder.id] = e;
419 :     vis.operators.add(e);
420 :     }
421 : dservos 1.1
422 : dservos 1.2 // Set up the layout of the axes.
423 : dservos 1.1 vis.xyAxes.xAxis.horizontalAnchor = TextSprite.LEFT;
424 :     vis.xyAxes.xAxis.verticalAnchor = TextSprite.MIDDLE;
425 :     vis.xyAxes.xAxis.labelAngle = Math.PI / 2;
426 :     vis.xyAxes.xAxis.fixLabelOverlap = false;
427 :     vis.xyAxes.yAxis.fixLabelOverlap = false;
428 :    
429 : dservos 1.3 if(!isnull(settings.layout.yaxis.labelformat)) {
430 :     vis.xyAxes.yAxis.labelFormat = settings.layout.yaxis.labelformat;
431 :     } else {
432 :     vis.xyAxes.yAxis.labelFormat = "0";
433 :     }
434 :    
435 :     if(!isnull(settings.layout.xaxis.labelformat)) {
436 :     vis.xyAxes.xAxis.labelFormat = settings.layout.xaxis.labelformat;
437 :     } else {
438 :     vis.xyAxes.xAxis.labelFormat = "0";
439 :     }
440 :    
441 :     if(!isnull(settings.layout.xaxis.min)) {
442 :     vis.xyAxes.xAxis.axisScale.min = settings.layout.xaxis.min;
443 :     vis.xyAxes.xAxis.axisScale.flush = true;
444 :     }
445 :    
446 :     if(!isnull(settings.layout.xaxis.max)) {
447 :     vis.xyAxes.xAxis.axisScale.max = settings.layout.xaxis.max;
448 :     vis.xyAxes.xAxis.axisScale.flush = true;
449 :     }
450 :    
451 :     if(!isnull(settings.layout.yaxis.min)) {
452 :     vis.xyAxes.yAxis.axisScale.min = settings.layout.yaxis.min;
453 :     }
454 :    
455 :     if(!isnull(settings.layout.yaxis.max)) {
456 :     vis.xyAxes.yAxis.axisScale.max = settings.layout.yaxis.max;
457 :     }
458 :    
459 :     if(!isnull(settings.layout.yaxis.yoffset)) {
460 :     vis.xyAxes.yAxis.labelOffsetY = settings.layout.yaxis.yoffset;
461 :     }
462 :    
463 :     if(!isnull(settings.layout.yaxis.xoffset)) {
464 :     vis.xyAxes.yAxis.labelOffsetX = settings.layout.yaxis.xoffset;
465 :     }
466 :    
467 :     if(!isnull(settings.layout.xaxis.yoffset)) {
468 :     vis.xyAxes.xAxis.labelOffsetY = settings.layout.xaxis.yoffset;
469 :     }
470 :    
471 :     if(!isnull(settings.layout.xaxis.xoffset)) {
472 :     vis.xyAxes.xAxis.labelOffsetX = settings.layout.xaxis.xoffset;
473 :     }
474 :    
475 :    
476 : dservos 1.2 // Update the visualization so the widths and other values are correct.
477 : dservos 1.1 vis.update();
478 :    
479 : dservos 1.2 // Initalize the X and Y axis labels and the visualizations title.
480 : dservos 1.3 var labelX:TextSprite = new TextSprite(settings.labels.xaxis, new TextFormat(settings.style.text.font, settings.style.text.size));
481 :     var labelY:TextSprite = new TextSprite(settings.labels.yaxis, new TextFormat(settings.style.text.font, settings.style.text.size));
482 :     var title:TextSprite = new TextSprite(settings.labels.title, new TextFormat(settings.style.text.font, int(settings.style.text.size) + 5));
483 : dservos 1.1
484 : dservos 1.2 // Find the largest width out of the X axis labels so it can used for positing sprites.
485 :     var xLabelsHeight:int = getMaxHeight(vis.xyAxes.xAxis.labels);
486 :     var yLabelsWidth:int = getMaxWidth(vis.xyAxes.yAxis.labels);
487 :    
488 :     // Position the visualization.
489 : dservos 1.1 vis.y = title.height + 10;
490 : dservos 1.2 vis.x = labelY.height + -vis.xyAxes.yAxis.labelOffsetX + yLabelsWidth;
491 : dservos 1.1
492 : dservos 1.2 // Set up the legends.
493 : dservos 1.3 var nextLegendY:int = 0;
494 :     for each(var legend:XML in settings.legend) {
495 :     var en:Encoder = encoders[legend.encoderid];
496 :     var l:Legend;
497 :    
498 :     switch(int(settings.encoder.(id == int(legend.encoderid)).type)) {
499 :     case 1: l = new Legend(en.source, en.scale, ColorEncoder(en).colors);
500 :     break;
501 :     case 2: l = new Legend(en.source, en.scale, null, ShapeEncoder(en).shapes);
502 :     break;
503 :     case 3: l = new Legend(en.source, en.scale, null, null, SizeEncoder(en).sizes);
504 :     break;
505 :     default: l = new Legend(en.source, en.scale, ColorEncoder(en).colors);
506 :     break;
507 :     }
508 :    
509 :     l.x = 0;
510 :     l.y = nextLegendY;
511 :     nextLegendY += l.height;
512 :    
513 :     l.items.addEventListener(MouseEvent.CLICK, legendClick);
514 :    
515 :     var lhc:HoverControl = new HoverControl(l.items);
516 :     lhc.onRollOver = legendRollOver;
517 :     lhc.onRollOut = legendRollOut;
518 :    
519 :     legends.addChild(l);
520 :     }
521 :    
522 : dservos 1.2 // Set the bounds of the visualization based on the hieght and width of the flash application,
523 :     // and the other components so the visualization is takes up the unused space.
524 : dservos 1.3 vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + vis.x), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
525 : dservos 1.2
526 :     // Add the visualization to the main sprite.
527 : dservos 1.1 addChild(vis);
528 :    
529 : dservos 1.2 // Set up the properitys of the data sprites and add a eventlistener to check for
530 :     // clicks on them.
531 : dservos 1.3 vis.data.nodes.visit(function(d:DataSprite):void {
532 :     if(!isnull(settings.style.nodeshape)) {
533 :     d.shape = settings.style.nodeshape;
534 :     }
535 : dservos 1.1 d.fillColor = 0x018888ff;
536 :     d.fillAlpha = 0.2;
537 :     d.lineWidth = 2;
538 :     d.addEventListener(MouseEvent.CLICK, mouseClicked);
539 : dservos 1.3
540 :     });
541 :    
542 :     vis.data.edges.visit(function(d:DataSprite):void {
543 :     if(!isnull(settings.style.edgeshape)) {
544 :     d.shape = settings.style.edgeshape;
545 :     }
546 :     d.lineWidth = 2;
547 :     d.fillAlpha = 1;
548 : dservos 1.1 });
549 :    
550 : dservos 1.2 // Position the legends.
551 :     legends.x = vis.bounds.width + 10;
552 :    
553 :     // Position and add the labels and title to the axes.
554 : dservos 1.1 labelX.x = vis.bounds.width/2 - labelX.width/2;
555 :     labelX.y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + xLabelsHeight;
556 :     vis.xyAxes.xAxis.addChild(labelX);
557 :    
558 : dservos 1.3 labelY.rotation = -90;
559 : dservos 1.1 labelY.x = -vis.x;
560 : dservos 1.3 labelY.y = (vis.bounds.height/2) + (labelY.height/2);
561 : dservos 1.1 vis.xyAxes.yAxis.addChild(labelY);
562 :    
563 :     title.x = vis.bounds.width/2 - title.width/2;
564 :     title.y = -vis.y;
565 :     vis.xyAxes.addChild(title);
566 :    
567 : dservos 1.2 // Add the legeneds container to the visualization.
568 :     vis.addChild(legends);
569 : dservos 1.1
570 : dservos 1.2 // Set up the hovercontrol for the marks on the chart
571 : dservos 1.1 var hc:HoverControl = new HoverControl(vis, Filters.isDataSprite);
572 :     hc.onRollOver = rollOver;
573 :     hc.onRollOut = rollOut;
574 :    
575 : dservos 1.2 // Set up the buttons and a container for them.
576 :     var controls:Sprite = new Sprite();
577 : dservos 1.3 var bInvert:Button = new Button(settings.lang.invertaxes, settings.style.button);
578 :     var bHideAxis:Button = new Button(settings.lang.hide + " " + settings.lang.axes, settings.style.button);
579 :     var bHideXLabel:Button = new Button(settings.lang.hide + " " + settings.lang.xlabels, settings.style.button);
580 :     var bHideYLabel:Button = new Button(settings.lang.hide + " " + settings.lang.ylabels, settings.style.button);
581 : dservos 1.2
582 :     var hideXLabelTransitioner:Transitioner = new Transitioner(2);
583 : dservos 1.3 hideXLabelTransitioner.onEnd = updateMarkVisiblity;
584 :     hideXLabelTransitioner.onStart = updateMarkVisiblity;
585 :    
586 : dservos 1.2 bHideXLabel.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
587 :     if(!hideXLabelTransitioner.running) {
588 :     hideXLabelTransitioner.reset();
589 :    
590 : dservos 1.3 if(bHideXLabel.text == settings.lang.show + " " + settings.lang.xlabels) {
591 :     bHideXLabel.text = settings.lang.hide + " " + settings.lang.xlabels;
592 : dservos 1.2 vis.xyAxes.xAxis.showLabels = true;
593 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + vis.x), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
594 :     } else {
595 : dservos 1.3 bHideXLabel.text = settings.lang.show + " " + settings.lang.xlabels;
596 : dservos 1.2 vis.xyAxes.xAxis.showLabels = false;
597 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + vis.x), loaderInfo.height - (vis.y + labelX.height));
598 :     }
599 :    
600 :     hideXLabelTransitioner.$(labelY).x = -vis.x;
601 :     hideXLabelTransitioner.$(labelY).y = vis.bounds.height/2 - labelY.height/2;
602 :    
603 :     vis.update(hideXLabelTransitioner).play();
604 :     }
605 :     });
606 :    
607 :     var hideYLabelTransitioner:Transitioner = new Transitioner(2);
608 : dservos 1.3 hideYLabelTransitioner.onEnd = updateMarkVisiblity;
609 :     hideYLabelTransitioner.onStart = updateMarkVisiblity;
610 :    
611 : dservos 1.2 bHideYLabel.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
612 :     if(!hideYLabelTransitioner.running) {
613 :     var t:Transitioner = new Transitioner(2);
614 :     var newX:int;
615 :    
616 :     hideYLabelTransitioner.reset();
617 :    
618 : dservos 1.3 if(bHideYLabel.text == settings.lang.show + " " + settings.lang.ylabels) {
619 :     bHideYLabel.text = settings.lang.hide + " " + settings.lang.ylabels;
620 : dservos 1.2 vis.xyAxes.yAxis.showLabels = true;
621 :     newX = labelY.width + -vis.xyAxes.yAxis.labelOffsetX + yLabelsWidth;
622 :     } else {
623 : dservos 1.3 bHideYLabel.text = settings.lang.show + " " + settings.lang.ylabels;
624 : dservos 1.2 vis.xyAxes.yAxis.showLabels = false;
625 :     newX = labelY.width;
626 :     }
627 :    
628 :     t.$(vis).x = newX;
629 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + newX), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
630 :    
631 :     // Reposition the labels and title.
632 :     t.$(title).x = vis.bounds.width/2 - title.width/2;
633 :     t.$(labelX).x = vis.bounds.width/2 - labelX.width/2;
634 :     t.$(labelX).y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + xLabelsHeight;
635 :     t.$(labelY).x = -newX;
636 :     t.$(labelY).y = vis.bounds.height/2 - labelY.height/2;
637 :    
638 :     // Keep the legends in there place.
639 :     t.$(legends).x = vis.bounds.width + 10;
640 :    
641 :     t.play();
642 :     vis.update(hideYLabelTransitioner).play();
643 :     }
644 :     });
645 :    
646 :     // Set up the transitioner to be used when inverting the axes
647 :     var updateTransitioner:Transitioner = new Transitioner(2);
648 :     updateTransitioner.onEnd = function():void {
649 :     updateMarkVisiblity();
650 :     vis.xyAxes.xAxis.labels.visible = true;
651 :     vis.xyAxes.yAxis.labels.visible = true;
652 :     };
653 :     updateTransitioner.onStart = function():void {
654 :     updateMarkVisiblity();
655 :     vis.xyAxes.xAxis.labels.visible = false;
656 :     vis.xyAxes.yAxis.labels.visible = false;
657 :     }
658 :    
659 :     // The function to invert the axes.
660 : dservos 1.1 bInvert.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
661 : dservos 1.2 // If we are not allready in the process of inverting the axes.
662 :     if(!updateTransitioner.running) {
663 :     var t:Transitioner = new Transitioner(2);
664 :     var tempText:String = labelX.text;
665 :     var tempOffset:int = vis.xyAxes.xAxis.labelOffsetX;
666 :     var tempWidth:uint = vis.bounds.width;
667 : dservos 1.3 var tempLabelFormat:String = vis.xyAxes.xAxis.labelFormat;
668 : dservos 1.2 var tempLabels:int = xLabelsHeight;
669 : dservos 1.3 var tempScale:Scale = vis.xyAxes.xAxis.axisScale;
670 :     var tempLabelOffsetY:Number = vis.xyAxes.xAxis.labelOffsetY;
671 :     var tempLabelOffsetX:Number = vis.xyAxes.xAxis.labelOffsetX;
672 : dservos 1.2 var currentXLabelsHeight:int = getMaxWidth(vis.xyAxes.yAxis.labels);
673 :    
674 :     var tempShowLabels:Boolean = vis.xyAxes.xAxis.showLabels;
675 : dservos 1.1
676 : dservos 1.2 // Rest the transitioner for a clean transition.
677 :     updateTransitioner.reset();
678 :    
679 : dservos 1.3 vis.xyAxes.xAxis.axisScale = vis.xyAxes.yAxis.axisScale;
680 :     vis.xyAxes.yAxis.axisScale = tempScale;
681 :     vis.xyAxes.yAxis.axisScale.flush = true;
682 :     vis.xyAxes.xAxis.axisScale.flush = true
683 :    
684 : dservos 1.2 // Flip the axis feilds.
685 : dservos 1.3 if(settings.layout.type == 1) {
686 :     AxisLayout(layout).xField = settings.layout.yaxis.field;
687 :     AxisLayout(layout).yField = settings.layout.xaxis.field;
688 :     settings.layout.xaxis.field = AxisLayout(layout).xField;
689 :     settings.layout.yaxis.field = AxisLayout(layout).yField;
690 :    
691 :     var tempStack:Boolean = AxisLayout(layout).xStacked;
692 :     AxisLayout(layout).xStacked = AxisLayout(layout).yStacked;
693 :     AxisLayout(layout).yStacked = tempStack;
694 :     }
695 :    
696 :     vis.xyAxes.xAxis.labelFormat = vis.xyAxes.yAxis.labelFormat;
697 :     vis.xyAxes.yAxis.labelFormat = tempLabelFormat;
698 :    
699 :    
700 :     vis.xyAxes.xAxis.labelOffsetX = vis.xyAxes.yAxis.labelOffsetY * -1;
701 :     vis.xyAxes.yAxis.labelOffsetY = tempLabelOffsetX * -1;
702 :     vis.xyAxes.xAxis.labelOffsetY = vis.xyAxes.yAxis.labelOffsetX * -1;
703 :     vis.xyAxes.yAxis.labelOffsetX = tempLabelOffsetY * -1;
704 :    
705 :    
706 : dservos 1.2 xLabelsHeight = yLabelsWidth;
707 :     yLabelsWidth = tempLabels;
708 :    
709 : dservos 1.3
710 : dservos 1.2 vis.xyAxes.xAxis.showLabels = vis.xyAxes.yAxis.showLabels;
711 :     vis.xyAxes.yAxis.showLabels = tempShowLabels;
712 :    
713 :     if(vis.xyAxes.yAxis.showLabels) {
714 : dservos 1.3 bHideYLabel.text = settings.lang.hide + " " + settings.lang.ylabels;
715 : dservos 1.2 } else {
716 : dservos 1.3 bHideYLabel.text = settings.lang.show + " " + settings.lang.ylabels;
717 : dservos 1.2 }
718 :    
719 :     if(vis.xyAxes.xAxis.showLabels) {
720 : dservos 1.3 bHideXLabel.text = settings.lang.hide + " " + settings.lang.xlabels;
721 : dservos 1.2 } else {
722 : dservos 1.3 bHideXLabel.text = settings.lang.show + " " + settings.lang.xlabels;
723 : dservos 1.2 }
724 :    
725 :     // Flip the labels
726 :     labelX.text = labelY.text;
727 :     labelY.text = tempText;
728 :    
729 :     // Find the new X value for the visualization.
730 :     var newX:int = labelY.width + vis.xyAxes.xAxis.labelOffsetY + getMaxHeight(vis.xyAxes.xAxis.labels);
731 :    
732 :     // Reposition and set the bounds of the visualization.
733 :     t.$(vis).x = newX;
734 :     vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + newX), loaderInfo.height - (vis.y + currentXLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
735 :    
736 :     // Reposition the labels and title.
737 :     t.$(title).x = vis.bounds.width/2 - title.width/2;
738 :     t.$(labelX).x = vis.bounds.width/2 - labelX.width/2;
739 :     t.$(labelX).y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + currentXLabelsHeight;
740 :     t.$(labelY).x = -newX;
741 : dservos 1.3 t.$(labelY).y = vis.bounds.height/2 + labelY.height/2;
742 : dservos 1.2
743 :     // Keep the legends in there place.
744 :     t.$(legends).x = vis.bounds.width + 10;
745 :    
746 :     //Play the transition.
747 :     t.play();
748 :     vis.update(updateTransitioner).play();
749 :     }
750 :     });
751 :    
752 :     // Set up the transitioner for the hide axes button.
753 :     var hideAxisTrans:Transitioner = new Transitioner(1);
754 :    
755 :     // Function for hidding the axes.
756 :     bHideAxis.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
757 :     // If we are not allready in the process of hidding the axes
758 :     if(!hideAxisTrans.running) {
759 :     // Reset the transitoner for a clean transiton.
760 :     hideAxisTrans.reset();
761 :    
762 :     // Hide or show the axes.
763 : dservos 1.3 if(bHideAxis.text == settings.lang.show + " " + settings.lang.axes) {
764 :     hideAxisTrans.$(bHideAxis).text = settings.lang.hide + " " + settings.lang.axes;
765 :     layout.showAxes(hideAxisTrans).play();
766 : dservos 1.2 } else {
767 : dservos 1.3 hideAxisTrans.$(bHideAxis).text = settings.lang.show + " " + settings.lang.axes;
768 :     layout.hideAxes(hideAxisTrans).play();
769 : dservos 1.2 }
770 :     }
771 : dservos 1.1 });
772 :    
773 : dservos 1.2 // Position the buttons inside there container.
774 :     bHideXLabel.x = 0;
775 :     bHideXLabel.y = 0;
776 :    
777 :     bHideAxis.x = legends.width - bHideAxis.width - 5;
778 :     bHideAxis.y = bHideXLabel.y;
779 :    
780 :     bInvert.x = legends.width - bInvert.width - 5;
781 :     bInvert.y = bHideXLabel.y + bHideXLabel.height + 2;
782 :    
783 :     bHideYLabel.x = 0;
784 :     bHideYLabel.y = bHideXLabel.y + bHideXLabel.height + 2;
785 :    
786 :     // Poistion the buttons container.
787 :     controls.x = legends.x + vis.x;
788 :     controls.y = legends.y + legends.height + vis.y + 20;
789 :    
790 :     // Add the buttons to the container and the container to the main sprite.
791 :     controls.addChild(bInvert);
792 :     controls.addChild(bHideAxis);
793 :     controls.addChild(bHideXLabel);
794 :     controls.addChild(bHideYLabel);
795 :     addChild(controls);
796 :    
797 :     // Set the marks on the chart to the higest deepth.
798 :     vis.setChildIndex(vis.marks, vis.numChildren - 1);
799 :    
800 :     // Update.
801 : dservos 1.1 vis.update();
802 : dservos 1.2 updateMarkVisiblity();
803 : dservos 1.1 }
804 :    
805 : dservos 1.2 /**
806 :     * Roll over function witch makes the object 0.5 units bigger and adds a glow filter.
807 :     * @param ob the object witch was rolled over.
808 :     */
809 : dservos 1.1 private function rollOver(ob:Object):void {
810 :     ob.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
811 : dservos 1.2 ob.size += 0.5;
812 : dservos 1.1 }
813 :    
814 : dservos 1.2 /**
815 :     * Roll out function witch removes the filters and makes the object 0.5 units smaller.
816 :     * @param ob the object witch was rolled out of.
817 :     */
818 : dservos 1.1 private function rollOut(ob:Object):void {
819 :     ob.filters = null;
820 : dservos 1.2 ob.size -= 0.5;
821 : dservos 1.1 }
822 :    
823 : dservos 1.2 /**
824 :     * Roll over function for the dialog box.
825 :     * Adds a glow filter to the curently active dialog box.
826 :     * @param ob a child of the dialog box.
827 :     */
828 : dservos 1.1 private function boxRollOver(ob:Object):void {
829 :     if(lastBoxData != null) {
830 :     lastBoxData.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
831 :     }
832 :     }
833 :    
834 : dservos 1.2 /**
835 :     * Roll out function for the dialog box.
836 :     * Removes filters on the curently active dialog box.
837 :     * @param ob a child of the dialog box.
838 :     */
839 : dservos 1.1 private function boxRollOut(ob:Object):void {
840 :     if(lastBoxData != null) {
841 :     lastBoxData.filters = null;
842 :     }
843 :     }
844 :    
845 : dservos 1.2 /**
846 :     * Finds the Legend belonging to the LegendItem passed.
847 :     * TODO: See if this can be replaced by a .parent call.
848 :     * @param item a LegendItem to find the Legend of.
849 :     * @return the Legend that contains the passed LegendItem.
850 :     */
851 :     private function findLegendByItem(item:LegendItem):Legend {
852 :     for(var i:uint = 0; i < legends.numChildren; i++ ) {
853 :     if(Legend(legends.getChildAt(i)).items.contains(item)) {
854 :     return Legend(legends.getChildAt(i));
855 :     }
856 :     }
857 :    
858 :     return null;
859 :     }
860 :    
861 :     /**
862 :     * Roll over function for legends.
863 :     * Adds a glow filter to the legend's item aswell as all the markers on the chart
864 :     * that are realted to the legend item and incrases there size by 1 unit.
865 :     * @param ob the LegendItem being rolled over.
866 :     */
867 :     private function legendRollOver(ob:LegendItem):void {
868 :     var legend:Legend = findLegendByItem(ob);
869 :     var dataName:String = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
870 :    
871 :     ob.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
872 :    
873 :     vis.data.visit(function(d:DataSprite):void {
874 :     if(d.data.hasOwnProperty(dataName) && ob.value == d.data[dataName]) {
875 :     d.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
876 :     d.size += 1;
877 :     }
878 :     }, 3, Filters.isDataSprite);
879 :     }
880 :    
881 :     /**
882 :     * Roll out function for legends.
883 :     * Removes filters to the legend's item aswell as all the markers on the chart
884 :     * that are realted to the legend item and decrases there size by 1 unit.
885 :     * @param ob the LegendItem being rolled out of.
886 :     */
887 :     private function legendRollOut(ob:LegendItem):void {
888 :     var legend:Legend = findLegendByItem(ob);
889 :     var dataName:String = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
890 :    
891 :     ob.filters = null;
892 :    
893 :     vis.data.visit(function(d:DataSprite):void {
894 :     if(d.data.hasOwnProperty(dataName) && ob.value == d.data[dataName]) {
895 :     d.filters = null;
896 :     d.size -= 1;
897 :     }
898 :     }, 3, Filters.isDataSprite);
899 :     }
900 :    
901 :     /**
902 :     * Creates and returns a dialog box containing information on the passed data sprite.
903 :     * @param data the DataSprite containing the information to display.
904 :     * @returns the Sprite containing the dialog box.
905 :     */
906 : dservos 1.1 private function dataDialogBox(data:DataSprite):Sprite {
907 :     var box:Sprite = new Sprite;
908 :    
909 :     var backGround:Sprite = new Sprite;
910 : dservos 1.3 backGround.graphics.beginFill(parseInt(settings.style.popup.bgcolor, 16), settings.style.popup.alpha);
911 :     backGround.graphics.lineStyle(settings.style.popup.line.size, parseInt(settings.style.popup.line.color, 16), settings.style.popup.line.alpha);
912 : dservos 1.1
913 :     var text:Sprite = new Sprite;
914 : dservos 1.2 var x:int = 5;
915 :     var y:int = 0;
916 :    
917 :     for(var property:Object in data.data) {
918 : dservos 1.3 var temp:TextSprite = new TextSprite(property.toString() + ": " + data.data[property], new TextFormat(settings.style.popup.text.font, settings.style.popup.text.size, null, true));
919 : dservos 1.2 temp.x = x;
920 :     temp.y = y;
921 :     text.addChild(temp);
922 :     y += temp.height;
923 :     }
924 : dservos 1.1
925 : dservos 1.2 backGround.graphics.drawRoundRect(0, 0, text.width + 10, text.height, 30, 30);
926 : dservos 1.1
927 :     box.addChild(backGround);
928 :     box.addChild(text);
929 :    
930 :     return box;
931 :     }
932 :    
933 : dservos 1.2 /**
934 :     * Check if a mark on the chart is visible based on the related LegendItems states.
935 :     * @param d the DataSprite to check the visiblility of.
936 :     * @returns true if the mark is visible.
937 :     */
938 :     private function markIsVisible(d:DataSprite):Boolean {
939 :     var items:Array = getLegendItems(d);
940 :    
941 :     for each(var item:LegendItem in items) {
942 :     if(item.alpha != 1) {
943 :     return false;
944 :     }
945 :     }
946 :    
947 :     return true;
948 :     }
949 :    
950 :     /**
951 :     * Gets all LegenedItems realted to a given DataSprite/mark.
952 :     * @params d the DataSprite on the chart.
953 :     * @returns Array of LegendItems that are realted to the given DataSprite.
954 :     */
955 :     private function getLegendItems(d:DataSprite):Array {
956 :     var items:Array = new Array();
957 :    
958 :     for(var i:uint = 0; i < legends.numChildren; i++) {
959 :     var legend:Legend = Legend(legends.getChildAt(i));
960 :    
961 :     for(var k:uint = 0; k < legend.items.numChildren; k++) {
962 :     var item:LegendItem = LegendItem(legend.items.getChildAt(k));
963 :    
964 :     if(d.data[legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1)] == item.value) {
965 :     items.push(item);
966 :     break;
967 :     }
968 :     }
969 :     }
970 :    
971 :     return items;
972 :     }
973 :    
974 :     /**
975 :     * Sets the visible atrubute of the marks/DataSprites based on the status of the LegendItems realted to it.
976 :     * @param item if set, only updates marks for that LegendItem. Otherwise updates all marks.
977 :     */
978 :     private function updateMarkVisiblity(item:LegendItem=null):void {
979 :     var legend:Legend;
980 :     var dataName:String;
981 :    
982 :     if(item != null) {
983 :     legend = findLegendByItem(item);
984 :     dataName = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
985 :     }
986 :    
987 :     vis.data.visit(function(d:DataSprite):void {
988 :     if(item == null || (d.data.hasOwnProperty(dataName) && item.value == d.data[dataName])) {
989 :     if(markIsVisible(d)) {
990 :     //d.alpha = 1.0;
991 :     d.visible = true;
992 :     } else {
993 :     //d.alpha = 0.0;
994 :     d.visible = false;
995 :     }
996 :     }
997 :     }, 3, Filters.isDataSprite);
998 :     }
999 :    
1000 :     /**
1001 :     * Function to be called when a LegendItem is clicked.
1002 :     * Changes the legendItems alpah value and updates mark visiblity.
1003 :     * @param evt the mouse event.
1004 :     */
1005 :     private function legendClick(evt:MouseEvent):void {
1006 :     var item:LegendItem = LegendItem(evt.target);
1007 :    
1008 :     if(item.alpha == 1) {
1009 :     item.alpha = 0.4;
1010 :     } else {
1011 :     item.alpha = 1.0;
1012 :     }
1013 :    
1014 :     updateMarkVisiblity(item);
1015 : dservos 1.3 vis.update();
1016 : dservos 1.2 }
1017 :    
1018 :     /**
1019 :     * Function called when a click happens on a mark on the chart.
1020 :     * Creates and adds a dialog box for that mark/DataSprite when clicked or removes the dialog box if
1021 :     * the mark allready has one.
1022 :     * @param the mouse event.
1023 :     */
1024 : dservos 1.1 private function mouseClicked(evt:MouseEvent):void {
1025 :     if(DisplayObject(evt.target).parent == vis.marks) {
1026 :     if(lastBox != null && lastBoxData != null) {
1027 :     lastBoxData.removeChild(lastBox);
1028 : dservos 1.2 boxhc.detach();
1029 : dservos 1.1 }
1030 :    
1031 :     if(evt.target != lastBoxData) {
1032 :     lastBox = dataDialogBox(DataSprite(evt.target));
1033 :     lastBoxData = DataSprite(evt.target);
1034 :     Sprite(evt.target).addChild(lastBox);
1035 :     vis.marks.setChildIndex(Sprite(evt.target), vis.marks.numChildren - 1);
1036 : dservos 1.2 boxhc.attach(Sprite(evt.target));
1037 : dservos 1.1 } else {
1038 :     lastBoxData = null;
1039 :     lastBox = null;
1040 :     }
1041 :     }
1042 :     }
1043 :     }
1044 :     }

Moodle CVS Admin
ViewVC Help
Powered by ViewVC 1.0.7