Parent Directory
|
Revision Log
CONTRIB-497 Cleaned up some of the code for report/visual and the flex based application for viewing the visualizations. Improved the UI of the visualization. Added documentation to both the php and actionscript 3 (flex) code. Removed some unneeded files. TODO: *Add more visualizations. *Add printer firendly version. *Make flex appplications settings less hardcoded and loaded from moodle. *Load lang files from moodle to flex for full language support. *Add a settings page for the report.
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://moodle.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* This is the flex with flare based visualizer for the Moodle 2.x visual
* grade book plug-in. This should load the grade book data for a given
* visualization from the report/visual plug-in based on a set of flashvars
* passed to it from Moodle and display a visual repersenation.
*/
package {
//Flare imports
import flare.animate.Transitioner;
import flare.data.DataSet;
import flare.data.DataSource;
import flare.display.TextSprite;
import flare.vis.Visualization;
import flare.vis.controls.HoverControl;
import flare.vis.data.Data;
import flare.vis.data.DataSprite;
import flare.vis.legend.Legend;
import flare.vis.legend.LegendItem;
import flare.vis.operator.encoder.ColorEncoder;
import flare.vis.operator.encoder.ShapeEncoder;
import flare.vis.operator.layout.AxisLayout;
import flare.vis.scale.ScaleType;
import flare.vis.util.Filters;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.geom.Rectangle;
import flash.net.URLLoader;
import flash.text.TextFormat;
[SWF(width="800", height="600", backgroundColor="#ffffff", frameRate="30")]
/**
* Main class for handling grade book data and greatating a visualization.
*/
public class flare_visualization extends Sprite
{
/**
* The visualization object to be used in creating the visualization.
*/
private var vis:Visualization;
/**
* A refernce to the currently displayed dialog box. If null no dialog
* box is currently being displayed.
*/
private var lastBox:Sprite = null;
/**
* A refernce to the data sprite witch contains the data for witch the
* currently displayed dialog box is based on and a child of.
*/
private var lastBoxData:DataSprite = null;
/**
* The data feild the X axis is based on.
* @default data.student
*/
private var axisX:String = "data.student";
/**
* The data field the Y axis is based on.
* @default data.grade
*/
private var axisY:String = "data.grade";
/**
* A container for the legends witch will be displayed on the righ hand
* side.
*/
private var legends:Sprite;
/**
* The hover control for the dialog box.
*/
private var boxhc:HoverControl = new HoverControl();
/**
* The constucter for the flare_visualization class.
* Calls on harvest_data and sets up the varibles from the flashvars.
*/
public function flare_visualization()
{
// Call harvest_data, loading needed visualization data from moodle.
// The Moodle wwwroot, course id, users sessionid, users session cookie
// and session test data are needed to get the data from moodle are
// loaded threw flashvars.
harvest_data(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']));
//harvest_data('http://localhost/moodle/grade/report/visual/data.php?id=3&sessioncookie=&sessionid=ebb79f5984c0fa4c9b0d85814c573a81&sessiontest=jHKFJhsOPf');
}
/**
* Harvests the data from Moodle and calls on buildVis to build the
* visualization once the data has been loaded.
* TODO: Add a loading bar and more feed back about the loading process.
* @param url The url from witch to load the tab formated data for the visualization.
*/
public function harvest_data(url:String):void
{
var ds:DataSource = new DataSource(url, "tab");
var loader:URLLoader = ds.load();
loader.addEventListener(Event.COMPLETE, function(evt:Event):void {
var ds:DataSet = loader.data as DataSet;
buildVis(Data.fromDataSet(ds));
});
}
/**
* Find the max width between a container and all of it's decendence
* This dose not find the width of a container but the greatest width
* of an invdual component in it's decenedences.
* @param d The display container to find the max width of.
* @return the max width value of the display objects.
*/
private function getMaxWidth(d:DisplayObjectContainer):int {
var max:int = d.width;
for(var k:uint = 0; k < d.numChildren; k++ ) {
var width:int = 0;
if(d.getChildAt(k) is DisplayObjectContainer) {
width = getMaxWidth(DisplayObjectContainer(d.getChildAt(k)));
} else {
width = d.getChildAt(k).width;
}
if(width > max) {
max = width;
}
}
return max;
}
/**
* Simple function to retrun the greatest of two ints.
* @param num1 the first number to test
* @param num2 the second number to test
* @return the largest value between num1 and num2.
*/
private function max(num1:int, num2:int):int {
if(num1 > num2) {
return num1;
} else {
return num2;
}
}
/**
* Find the max height between a container and all of it's decendence
* This dose not find the width of a container but the greatest height
* of an invdual component in it's decenedences.
* @param d The display container to find the max height of.
* @return the max height value of the display objects.
*/
private function getMaxHeight(d:DisplayObjectContainer):int {
var max:int = d.height;
for(var k:uint = 0; k < d.numChildren; k++ ) {
var height:int = 0;
if(d.getChildAt(k) is DisplayObjectContainer) {
height = getMaxHeight(DisplayObjectContainer(d.getChildAt(k)));
} else {
height = d.getChildAt(k).height;
}
if(height > max) {
max = height;
}
}
return max;
}
/**
* Builds the visualization based on the loaded data.
* Also sets up the legends, buttons and controls.
* @param data The data that was loaded in from moodle.
*/
private function buildVis(data:Data):void
{
vis = new Visualization(data);
legends = new Sprite();
// Set the functions to be called when a dialog box is hovered over.
boxhc.onRollOver = boxRollOver;
boxhc.onRollOut = boxRollOut;
// Set up the encoders and layout
var colorEncoder:ColorEncoder = new ColorEncoder("data.item", Data.NODES, "lineColor", ScaleType.CATEGORIES);
var shapeEncoder:ShapeEncoder = new ShapeEncoder("data.group");
var al:AxisLayout = new AxisLayout(axisX, axisY);
// Add the encoders and layout to the visualization.
vis.operators.add(al);
vis.operators.add(colorEncoder);
vis.operators.add(shapeEncoder);
// Set up the layout of the axes.
vis.xyAxes.xAxis.horizontalAnchor = TextSprite.LEFT;
vis.xyAxes.xAxis.verticalAnchor = TextSprite.MIDDLE;
vis.xyAxes.xAxis.labelAngle = Math.PI / 2;
vis.xyAxes.xAxis.fixLabelOverlap = false;
vis.xyAxes.yAxis.fixLabelOverlap = false;
// Update the visualization so the widths and other values are correct.
vis.update();
// Initalize the X and Y axis labels and the visualizations title.
var labelX:TextSprite = new TextSprite("Student", new TextFormat("mono", 20));
var labelY:TextSprite = new TextSprite("Grade", new TextFormat("mono", 20));
var title:TextSprite = new TextSprite("Normalized Grades vs Students", new TextFormat("mono", 25));
// Find the largest width out of the X axis labels so it can used for positing sprites.
var xLabelsHeight:int = getMaxHeight(vis.xyAxes.xAxis.labels);
var yLabelsWidth:int = getMaxWidth(vis.xyAxes.yAxis.labels);
// Position the visualization.
vis.y = title.height + 10;
vis.x = labelY.height + -vis.xyAxes.yAxis.labelOffsetX + yLabelsWidth;
// Set up the legends.
var itemLegend:Legend = new Legend("data.item", colorEncoder.scale, colorEncoder.colors, null, null);
var groupLegend:Legend = new Legend("data.group", shapeEncoder.scale, null, shapeEncoder.shapes, null);
// Set the bounds of the visualization based on the hieght and width of the flash application,
// and the other components so the visualization is takes up the unused space.
vis.bounds = new Rectangle(0, 0, loaderInfo.width - (max(itemLegend.width, groupLegend.width) + 15 + vis.x), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
// Add the visualization to the main sprite.
addChild(vis);
// Set up the properitys of the data sprites and add a eventlistener to check for
// clicks on them.
vis.data.visit(function(d:DataSprite):void {
d.fillColor = 0x018888ff;
d.fillAlpha = 0.2;
d.lineWidth = 2;
d.addEventListener(MouseEvent.CLICK, mouseClicked);
});
// Position the legends.
legends.x = vis.bounds.width + 10;
itemLegend.x = 0;
itemLegend.y = 0;
groupLegend.x = 0;
groupLegend.y = itemLegend.y + itemLegend.height;
// Add a listener for mouse clicks on the legends.
itemLegend.items.addEventListener(MouseEvent.CLICK, legendClick);
groupLegend.items.addEventListener(MouseEvent.CLICK, legendClick);
// Add the legends to the legends container.
legends.addChild(itemLegend);
legends.addChild(groupLegend);
// Set up and add a hover control to each legend.
var itemHC:HoverControl = new HoverControl(itemLegend.items);
itemHC.onRollOver = legendRollOver;
itemHC.onRollOut = legendRollOut;
var groupHC:HoverControl = new HoverControl(groupLegend.items);
groupHC.onRollOver = legendRollOver;
groupHC.onRollOut = legendRollOut;
// Position and add the labels and title to the axes.
labelX.x = vis.bounds.width/2 - labelX.width/2;
labelX.y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + xLabelsHeight;
vis.xyAxes.xAxis.addChild(labelX);
labelY.x = -vis.x;
labelY.y = vis.bounds.height/2 - labelY.width/2;
labelY.rotation = -90;
vis.xyAxes.yAxis.addChild(labelY);
title.x = vis.bounds.width/2 - title.width/2;
title.y = -vis.y;
vis.xyAxes.addChild(title);
// Add the legeneds container to the visualization.
vis.addChild(legends);
// Set up the hovercontrol for the marks on the chart
var hc:HoverControl = new HoverControl(vis, Filters.isDataSprite);
hc.onRollOver = rollOver;
hc.onRollOut = rollOut;
// Set up the buttons and a container for them.
var controls:Sprite = new Sprite();
var bInvert:Button = new Button("Invert Axes");
var bHideAxis:Button = new Button("Hide Axes");
var bHideXLabel:Button = new Button("Hide X Labels");
var bHideYLabel:Button = new Button("Hide Y Labels");
var hideXLabelTransitioner:Transitioner = new Transitioner(2);
bHideXLabel.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
if(!hideXLabelTransitioner.running) {
hideXLabelTransitioner.reset();
if(bHideXLabel.text == "Show X Labels") {
bHideXLabel.text = "Hide X Labels";
vis.xyAxes.xAxis.showLabels = true;
vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + vis.x), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
} else {
bHideXLabel.text = "Show X Labels";
vis.xyAxes.xAxis.showLabels = false;
vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + vis.x), loaderInfo.height - (vis.y + labelX.height));
}
hideXLabelTransitioner.$(labelY).x = -vis.x;
hideXLabelTransitioner.$(labelY).y = vis.bounds.height/2 - labelY.height/2;
vis.update(hideXLabelTransitioner).play();
}
});
var hideYLabelTransitioner:Transitioner = new Transitioner(2);
bHideYLabel.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
if(!hideYLabelTransitioner.running) {
var t:Transitioner = new Transitioner(2);
var newX:int;
hideYLabelTransitioner.reset();
if(bHideYLabel.text == "Show Y Labels") {
bHideYLabel.text = "Hide Y Labels";
vis.xyAxes.yAxis.showLabels = true;
newX = labelY.width + -vis.xyAxes.yAxis.labelOffsetX + yLabelsWidth;
} else {
bHideYLabel.text = "Show Y Labels";
vis.xyAxes.yAxis.showLabels = false;
newX = labelY.width;
}
t.$(vis).x = newX;
vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + newX), loaderInfo.height - (vis.y + xLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
// Reposition the labels and title.
t.$(title).x = vis.bounds.width/2 - title.width/2;
t.$(labelX).x = vis.bounds.width/2 - labelX.width/2;
t.$(labelX).y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + xLabelsHeight;
t.$(labelY).x = -newX;
t.$(labelY).y = vis.bounds.height/2 - labelY.height/2;
// Keep the legends in there place.
t.$(legends).x = vis.bounds.width + 10;
t.play();
vis.update(hideYLabelTransitioner).play();
}
});
// Set up the transitioner to be used when inverting the axes
var updateTransitioner:Transitioner = new Transitioner(2);
updateTransitioner.onEnd = function():void {
updateMarkVisiblity();
vis.xyAxes.xAxis.labels.visible = true;
vis.xyAxes.yAxis.labels.visible = true;
};
updateTransitioner.onStart = function():void {
updateMarkVisiblity();
vis.xyAxes.xAxis.labels.visible = false;
vis.xyAxes.yAxis.labels.visible = false;
}
// The function to invert the axes.
bInvert.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
// If we are not allready in the process of inverting the axes.
if(!updateTransitioner.running) {
var t:Transitioner = new Transitioner(2);
var tempText:String = labelX.text;
var tempOffset:int = vis.xyAxes.xAxis.labelOffsetX;
var tempWidth:uint = vis.bounds.width;
var tempLabels:int = xLabelsHeight;
var currentXLabelsHeight:int = getMaxWidth(vis.xyAxes.yAxis.labels);
var tempShowLabels:Boolean = vis.xyAxes.xAxis.showLabels;
// Rest the transitioner for a clean transition.
updateTransitioner.reset();
// Flip the axis feilds.
al.xField = axisY;
al.yField = axisX;
axisX = al.xField;
axisY = al.yField;
xLabelsHeight = yLabelsWidth;
yLabelsWidth = tempLabels;
vis.xyAxes.xAxis.showLabels = vis.xyAxes.yAxis.showLabels;
vis.xyAxes.yAxis.showLabels = tempShowLabels;
if(vis.xyAxes.yAxis.showLabels) {
bHideYLabel.text = "Hide Y Labels";
} else {
bHideYLabel.text = "Show Y Labels";
}
if(vis.xyAxes.xAxis.showLabels) {
bHideXLabel.text = "Hide X Labels";
} else {
bHideXLabel.text = "Show X Labels";
}
// Flip the labels
labelX.text = labelY.text;
labelY.text = tempText;
// Find the new X value for the visualization.
var newX:int = labelY.width + vis.xyAxes.xAxis.labelOffsetY + getMaxHeight(vis.xyAxes.xAxis.labels);
// Reposition and set the bounds of the visualization.
t.$(vis).x = newX;
vis.bounds = new Rectangle(0, 0, loaderInfo.width - (legends.width + 15 + newX), loaderInfo.height - (vis.y + currentXLabelsHeight + labelX.height + vis.xyAxes.xAxis.labelOffsetY));
// Reposition the labels and title.
t.$(title).x = vis.bounds.width/2 - title.width/2;
t.$(labelX).x = vis.bounds.width/2 - labelX.width/2;
t.$(labelX).y = vis.bounds.height + vis.xyAxes.xAxis.labelOffsetY + currentXLabelsHeight;
t.$(labelY).x = -newX;
t.$(labelY).y = vis.bounds.height/2 - labelY.width/2;
// Keep the legends in there place.
t.$(legends).x = vis.bounds.width + 10;
//Play the transition.
t.play();
vis.update(updateTransitioner).play();
}
});
// Set up the transitioner for the hide axes button.
var hideAxisTrans:Transitioner = new Transitioner(1);
// Function for hidding the axes.
bHideAxis.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void {
// If we are not allready in the process of hidding the axes
if(!hideAxisTrans.running) {
// Reset the transitoner for a clean transiton.
hideAxisTrans.reset();
// Hide or show the axes.
if(bHideAxis.text == "Show Axes") {
hideAxisTrans.$(bHideAxis).text = "Hide Axes";
al.showAxes(hideAxisTrans).play();
} else {
hideAxisTrans.$(bHideAxis).text = "Show Axes";
al.hideAxes(hideAxisTrans).play();
}
}
});
// Position the buttons inside there container.
bHideXLabel.x = 0;
bHideXLabel.y = 0;
bHideAxis.x = legends.width - bHideAxis.width - 5;
bHideAxis.y = bHideXLabel.y;
bInvert.x = legends.width - bInvert.width - 5;
bInvert.y = bHideXLabel.y + bHideXLabel.height + 2;
bHideYLabel.x = 0;
bHideYLabel.y = bHideXLabel.y + bHideXLabel.height + 2;
// Poistion the buttons container.
controls.x = legends.x + vis.x;
controls.y = legends.y + legends.height + vis.y + 20;
// Add the buttons to the container and the container to the main sprite.
controls.addChild(bInvert);
controls.addChild(bHideAxis);
controls.addChild(bHideXLabel);
controls.addChild(bHideYLabel);
addChild(controls);
// Set the marks on the chart to the higest deepth.
vis.setChildIndex(vis.marks, vis.numChildren - 1);
// Update.
vis.update();
updateMarkVisiblity();
}
/**
* Roll over function witch makes the object 0.5 units bigger and adds a glow filter.
* @param ob the object witch was rolled over.
*/
private function rollOver(ob:Object):void {
ob.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
ob.size += 0.5;
}
/**
* Roll out function witch removes the filters and makes the object 0.5 units smaller.
* @param ob the object witch was rolled out of.
*/
private function rollOut(ob:Object):void {
ob.filters = null;
ob.size -= 0.5;
}
/**
* Roll over function for the dialog box.
* Adds a glow filter to the curently active dialog box.
* @param ob a child of the dialog box.
*/
private function boxRollOver(ob:Object):void {
if(lastBoxData != null) {
lastBoxData.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
}
}
/**
* Roll out function for the dialog box.
* Removes filters on the curently active dialog box.
* @param ob a child of the dialog box.
*/
private function boxRollOut(ob:Object):void {
if(lastBoxData != null) {
lastBoxData.filters = null;
}
}
/**
* Finds the Legend belonging to the LegendItem passed.
* TODO: See if this can be replaced by a .parent call.
* @param item a LegendItem to find the Legend of.
* @return the Legend that contains the passed LegendItem.
*/
private function findLegendByItem(item:LegendItem):Legend {
for(var i:uint = 0; i < legends.numChildren; i++ ) {
if(Legend(legends.getChildAt(i)).items.contains(item)) {
return Legend(legends.getChildAt(i));
}
}
return null;
}
/**
* Roll over function for legends.
* Adds a glow filter to the legend's item aswell as all the markers on the chart
* that are realted to the legend item and incrases there size by 1 unit.
* @param ob the LegendItem being rolled over.
*/
private function legendRollOver(ob:LegendItem):void {
var legend:Legend = findLegendByItem(ob);
var dataName:String = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
ob.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
vis.data.visit(function(d:DataSprite):void {
if(d.data.hasOwnProperty(dataName) && ob.value == d.data[dataName]) {
d.filters = [new GlowFilter(0xFFFF55, 0.8, 6, 6, 10)];
d.size += 1;
}
}, 3, Filters.isDataSprite);
}
/**
* Roll out function for legends.
* Removes filters to the legend's item aswell as all the markers on the chart
* that are realted to the legend item and decrases there size by 1 unit.
* @param ob the LegendItem being rolled out of.
*/
private function legendRollOut(ob:LegendItem):void {
var legend:Legend = findLegendByItem(ob);
var dataName:String = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
ob.filters = null;
vis.data.visit(function(d:DataSprite):void {
if(d.data.hasOwnProperty(dataName) && ob.value == d.data[dataName]) {
d.filters = null;
d.size -= 1;
}
}, 3, Filters.isDataSprite);
}
/**
* Creates and returns a dialog box containing information on the passed data sprite.
* @param data the DataSprite containing the information to display.
* @returns the Sprite containing the dialog box.
*/
private function dataDialogBox(data:DataSprite):Sprite {
var box:Sprite = new Sprite;
var backGround:Sprite = new Sprite;
backGround.graphics.beginFill(0x7777ff, 0.60);
backGround.graphics.lineStyle(3, 0x0000ff, 0.3);
var text:Sprite = new Sprite;
var x:int = 5;
var y:int = 0;
for(var property:Object in data.data) {
var temp:TextSprite = new TextSprite(property.toString() + ": " + data.data[property], new TextFormat("mono", 12, null, true));
temp.x = x;
temp.y = y;
text.addChild(temp);
y += temp.height;
}
/*var name:TextSprite = new TextSprite(data.data.student, new TextFormat("mono", 20, null, true));
var item:TextSprite = new TextSprite("Item: " + data.data.item, new TextFormat("mono", 12, null, true));
var grade:TextSprite = new TextSprite("Grade: " + data.data.grade + "%", new TextFormat("mono", 12, null, true));
var group:TextSprite = new TextSprite("Group: " + data.data.group, new TextFormat("mono", 12, null, true));
text.addChild(name);
text.addChild(item);
text.addChild(group);
text.addChild(grade);
name.x = text.width/2 - name.width/2;
item.x = 5;
grade.x = 5;
group.x = 5;
name.y = 0;
item.y = name.y + name.height;
group.y = item.y + item.height;
grade.y = group.y + group.height;*/
backGround.graphics.drawRoundRect(0, 0, text.width + 10, text.height, 30, 30);
box.addChild(backGround);
box.addChild(text);
return box;
}
/**
* Check if a mark on the chart is visible based on the related LegendItems states.
* @param d the DataSprite to check the visiblility of.
* @returns true if the mark is visible.
*/
private function markIsVisible(d:DataSprite):Boolean {
var items:Array = getLegendItems(d);
for each(var item:LegendItem in items) {
if(item.alpha != 1) {
return false;
}
}
return true;
}
/**
* Gets all LegenedItems realted to a given DataSprite/mark.
* @params d the DataSprite on the chart.
* @returns Array of LegendItems that are realted to the given DataSprite.
*/
private function getLegendItems(d:DataSprite):Array {
var items:Array = new Array();
for(var i:uint = 0; i < legends.numChildren; i++) {
var legend:Legend = Legend(legends.getChildAt(i));
for(var k:uint = 0; k < legend.items.numChildren; k++) {
var item:LegendItem = LegendItem(legend.items.getChildAt(k));
if(d.data[legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1)] == item.value) {
items.push(item);
break;
}
}
}
return items;
}
/**
* Sets the visible atrubute of the marks/DataSprites based on the status of the LegendItems realted to it.
* @param item if set, only updates marks for that LegendItem. Otherwise updates all marks.
*/
private function updateMarkVisiblity(item:LegendItem=null):void {
var legend:Legend;
var dataName:String;
if(item != null) {
legend = findLegendByItem(item);
dataName = legend.dataField.substr(legend.dataField.lastIndexOf('.') + 1);
}
vis.data.visit(function(d:DataSprite):void {
if(item == null || (d.data.hasOwnProperty(dataName) && item.value == d.data[dataName])) {
if(markIsVisible(d)) {
//d.alpha = 1.0;
d.visible = true;
} else {
//d.alpha = 0.0;
d.visible = false;
}
}
}, 3, Filters.isDataSprite);
}
/**
* Function to be called when a LegendItem is clicked.
* Changes the legendItems alpah value and updates mark visiblity.
* @param evt the mouse event.
*/
private function legendClick(evt:MouseEvent):void {
var item:LegendItem = LegendItem(evt.target);
if(item.alpha == 1) {
item.alpha = 0.4;
} else {
item.alpha = 1.0;
}
updateMarkVisiblity(item);
}
/**
* Function called when a click happens on a mark on the chart.
* Creates and adds a dialog box for that mark/DataSprite when clicked or removes the dialog box if
* the mark allready has one.
* @param the mouse event.
*/
private function mouseClicked(evt:MouseEvent):void {
if(DisplayObject(evt.target).parent == vis.marks) {
if(lastBox != null && lastBoxData != null) {
lastBoxData.removeChild(lastBox);
boxhc.detach();
}
if(evt.target != lastBoxData) {
lastBox = dataDialogBox(DataSprite(evt.target));
lastBoxData = DataSprite(evt.target);
Sprite(evt.target).addChild(lastBox);
vis.marks.setChildIndex(Sprite(evt.target), vis.marks.numChildren - 1);
boxhc.attach(Sprite(evt.target));
} else {
lastBoxData = null;
lastBox = null;
}
}
}
}
}
| Moodle CVS Admin | ViewVC Help |
| Powered by ViewVC 1.0.7 |