Difference between revisions of "Simple example"
Line 99: | Line 99: | ||
var appletName = "PointGraph"; |
var appletName = "PointGraph"; |
||
− | var applet_loaded = 1; // applet does not need to |
+ | var applet_loaded = 1; // applet does not need to |
− | // |
+ | // load additional files |
+ | // it is ready as soon as the applet |
||
+ | // itself is loaded |
||
function isActive() { |
function isActive() { |
||
Line 106: | Line 106: | ||
} |
} |
||
− | // can be used to proactively report to the webwork question that |
||
+ | // <code> reportAppletLoaded </code>can be used |
||
+ | // to proactively report to the webwork question that |
||
// the applet is loaded. (Call with <code>loaded=1</code>) |
// the applet is loaded. (Call with <code>loaded=1</code>) |
||
Revision as of 19:09, 4 April 2009
Before and After Flash Applet
We take a "stand alone" graphing applet and customize it for use in WW in a few easy steps.
ActionScript code for stand-alone (no WW) version:
On the stage should be an input textbox called txtFun for this version. Hitting the "enter" key after editing this box will update the screen. The ww version will get the expression to graph through a call to the config function, so we will be deleting this input textbox in the subsequent version.
import flashandmath.as3.tools.SimpleGraph; var sxMin:String = "-5"; var sxMax:String = "5"; var syMin:String = "-5"; var syMax:String = "5"; var sFun:String = txtFun.text; var g:SimpleGraph = new SimpleGraph(480,360); g.x = 20; g.y = 40; addChild(g); var spPoint:Sprite = new Sprite(); spPoint.x = 5; spPoint.y = 5; spPoint.graphics.lineStyle(1,0); spPoint.graphics.beginFill(0xAA0000); spPoint.graphics.drawEllipse(-5,-5,10,10); spPoint.graphics.endFill(); spPoint.addEventListener(MouseEvent.MOUSE_DOWN, pointClicked) g.addChildToBoard(spPoint); stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); function keyPressed(kevt:KeyboardEvent):void { if (kevt.keyCode == Keyboard.ENTER) { sFun = txtFun.text; drawGraph(); } } function drawGraph():void { g.setWindow(sxMin, sxMax, syMin, syMax); g.board.drawAxes(); g.board.drawTicks(); g.board.drawGrid(); g.board.addLabels(); g.graphRectangular(sFun,"x",1,2,0x0000CC); } drawGraph(); function pointClicked(mevt:MouseEvent):void { stage.addEventListener(MouseEvent.MOUSE_MOVE, pointMoved); stage.addEventListener(MouseEvent.MOUSE_UP, pointReleased); } function pointMoved(mevt:MouseEvent):void { spPoint.x = goodX(g.mouseX); spPoint.y = goodY(g.mouseY); mevt.updateAfterEvent(); } function pointReleased(mevt:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_MOVE, pointMoved); stage.removeEventListener(MouseEvent.MOUSE_UP, pointReleased); } function goodX(nx:Number):Number { if (nx > 480) { return 480; } if (nx < 0) { return 0; } return nx; } function goodY(ny:Number):Number { if (ny > 360) { return 360; } if (ny < 0) { return 0; } return ny; }
ActionScript code for WW version:
Everything discussed below will go into the code above below the initial import statement. We will have to edit the existing code a very small amount to accommodate the fact that the txtFun input textbox is omitted from this version.
First. We add the external interface calls so that WW can communicate with our applet.
ExternalInterface.addCallback("sendData", sendData); ExternalInterface.addCallback("getXML", getXML); ExternalInterface.addCallback("setXML", setXML); ExternalInterface.addCallback("setConfig", setConfig); ExternalInterface.addCallback("isActive", isActive); ExternalInterface.addCallback("debug", set_debug);
Second. We need functions and variables that will allow WW to test that the applet is loaded and ready before trying to send data to it. This can be copied verbatim with the applet_name matching the applet name specified in the WW problem file.
var appletName = "PointGraph"; var applet_loaded = 1; // applet does not need to // load additional files // it is ready as soon as the applet // itself is loaded function isActive() { return(applet_loaded); }
//reportAppletLoaded
can be used // to proactively report to the webwork question that // the applet is loaded. (Call withloaded=1
) function reportAppletLoaded(appletName, loaded) { ExternalInterface.call("applet_loaded", appletName, loaded); }
Third. We need functions and variables that will allow WW to interact with the applet while in debug mode. The applet does not have to incorporate any independent debug features, but the set_debug
function/variable must be in place.
We have also added a text window which can receive debugging messages placed with the feedback
function. Typically these messages
simply indicate whether a subroutine is being executed. This can be very
useful in determining whether messages from the webwork question are
coming through to the applet.
var debugMode:Boolean = false; function set_debug(n:Number) { debugMode = (n)? true:false; }
// create error reporting window for use in debug mode var txtFeedback:TextArea = new TextArea(); txtFeedback.text ="no message yet"; txtFeedback.move(100,0); txtFeedback.setSize(400,100); txtFeedback.visible = debugMode; // visible in debugMode only function feedback(str:String):void{ if (debugMode) { txtFeedback.appendText( "\n" + str); } }
Fourth. The functions config, getXML, setXML, and sendData are instrumental in the communication between the applet and WW for normal interaction by students. The most important things about these functions is (a) consistency between getXML and setXML, and (2) documentation of config and sendData within the WW problem file. Each function is explained a little more with comments below:
/* Data string that initializes the applet problem should have the form <xml expr='expression in x' /> */ function setConfig(str:String) { var xmlData:XML = XML( str ); feedback("received xml string "+xmlData.toString() ); //debug check spPoint.x = 5; spPoint.y = 5; if (str == "") { sFun = "0"; return; } sFun = xmlData.@expr.toString(); drawGraph(); } // setXML takes the xml string from the webwork question and uses it to initialize the applet function setXML(str:String):void { var xmlData:XML = XML( str ); if (str == "") { spPoint.x = 5; spPoint.y = 5; return; } spPoint.x = g.board.xtoPix(Number(xmlData.pt.@xval.toString())); spPoint.y = g.board.ytoPix(Number(xmlData.pt.@yval.toString())); } // getXML gets the xml string that describes the applet state function getXML():String { var xmlString:String; xmlString = "<xml> <pt xval = '" + String(g.board.xfromPix(spPoint.x)) + "' yval = '" + String(g.board.yfromPix(spPoint.y)) + "' /> </xml>"; return xmlString; } // The getAnswer function produces the user-friendly data to be copied into the answer box, eventually to be graded function getAnswer():String { return ("(" + String(g.board.xfromPix(spPoint.x)) + "," + String(g.board.yfromPix(spPoint.y)) + ")" ); }
Finally. You will have to edit the original example to remove the ability of changing the expression in the input text box and consequently the need to have the "enter" key trigger a new graph. For completeness, we include the entire remaining (shorter) code:
var sxMin:String = "-5"; var sxMax:String = "5"; var syMin:String = "-5"; var syMax:String = "5"; var sFun:String; var g:SimpleGraph = new SimpleGraph(480,360); g.x = 20; g.y = 40; addChild(g); g.setWindow(sxMin, sxMax, syMin, syMax); var spPoint:Sprite = new Sprite(); spPoint.x = 5; spPoint.y = 5; spPoint.graphics.lineStyle(1,0); spPoint.graphics.beginFill(0xAA0000); spPoint.graphics.drawEllipse(-5,-5,10,10); spPoint.graphics.endFill(); g.addChildToBoard(spPoint); function drawGraph():void { g.setWindow(sxMin, sxMax, syMin, syMax); g.board.drawAxes(); g.board.drawTicks(); g.board.drawGrid(); g.board.addLabels(); g.graphRectangular(sFun,"x",1,2,0x0000CC); } //////////////////////////////////////////////////// spPoint.addEventListener(MouseEvent.MOUSE_DOWN, pointClicked); function pointClicked(mevt:MouseEvent):void { stage.addEventListener(MouseEvent.MOUSE_MOVE, pointMoved); stage.addEventListener(MouseEvent.MOUSE_UP, pointReleased); } function pointMoved(mevt:MouseEvent):void { spPoint.x = goodX(g.mouseX); spPoint.y = goodY(g.mouseY); mevt.updateAfterEvent(); } function pointReleased(mevt:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_MOVE, pointMoved); stage.removeEventListener(MouseEvent.MOUSE_UP, pointReleased); } function goodX(nx:Number):Number { if (nx > 480) { return 480; } if (nx < 0) { return 0; } return nx; } function goodY(ny:Number):Number { if (ny > 360) { return 360; } if (ny < 0) { return 0; } return ny; }