Hi All,
Inspired by Christian's revamping of the JSXGraph extension, I decided to rewrite a question I'd created a little while ago using the Geogebra extension.
So far, rewriting the question using the JSXGraph extension has been reasonably straightforward. The sticking point has been in enabling two-way communication between Numbas variables/user input and the JSXGraph visualisation.
Also, I have wanted to steer well clear of the problems I've encountered using Geogebra-driven questions that were not created using Numbas variables. (On this score, Christian notes in the JSXGraph
docs that "You should create the board in a question variable, so that its state can be saved and restored in case the student leaves and resumes their attempt.".)
I have read Christian's
blog post outlining his improvements to the extension and looked - I believe comprehensively - at the demos he has created. This all looks great and is probably enough to switch my default extension from Geogebra to JSXGraph for the development of interactive Numbas questions.
But I have been unable, using either the JME or JessieCode approach, to replicate all of the features I need (or want) for the movable syringe graphic.
Below is the JavaScript code used to create the graphic.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'
JXG.Options.grid.gridX=1;
JXG.Options.grid.gridY=0.2;
JXG.Options.point.snapSizeX = 0.2;
var div = Numbas.extensions.jsxgraph.makeBoard('1000px','250px',
{boundingBox: [-1,2.5,250,0.5],
axis: false,
showNavigation: false,
grid: false
});
var board = div.board;
var im = board.create('image', ['resources/question-resources/1mLSyringeImage_no_plunger_end.svg', [-0.1,1],[132.87,-1]]);
// remove highlighting of image
im.hasPoint = function(){return false;}
var pcl = board.create('line', [[132.4,1.5],[232.4,1.5]], {straightFirst:false, straightLast:false, strokeWidth: 0, highlightStrokeWidth: 0});
var mp = board.create('glider', [132.4+100*initialVol,1.5,pcl], {snapToGrid: true, withLabel:false, showInfobox: false, size: 4, fillColor: '#00F', strokeWidth: 0, highlightStrokeWidth: 0, highlightFillColor: '#99ccff', highlightStrokeColor: '#99ccff', highlightFillOpacity: 1, highlightStrokeOpacity: 1}); // var mp = board.create('point', [132.3, 1.5]);
var pel = board.create('line', [[function(){ return mp.X()-120.4;},1.3],[function(){ return mp.X()-120.4;},1.7]], {straightFirst:false, straightLast:false, strokeColor: '#000', strokeWidth: 1.0, highlightStrokeWidth: 0, highlightFillColor: '#000', highlightStrokeColor: '#000', highlightFillOpacity: 1, highlightStrokeOpacity: 1});
// Rectangular region of syringe containing fluid
var rp1 = board.create('point', [12,1.3],{visible: false}),
rp2 = board.create('point', [function(){ return mp.X()-120.3;},1.3],{visible: false}),
rp3 = board.create('point', [function(){ return mp.X()-120.3;},1.7],{visible: false}),
rp4 = board.create('point', [12,1.7],{visible: false}),
rrect = board.create('polygon',[rp1,rp2,rp3,rp4],{fillColor: '#ff99ff', fillOpacity: 0.25, highlightFillColor: '#ff99ff', highlightFillOpacity: 0.25, highlightStrokeColor: '#000', highlightStrokeOpacity: 1, borders: {strokeWidth: 0, highlightStrokeWidth: 0}});
// Rectangular region at 'open' end of plunger
var repp1 = board.create('point', [function(){ return mp.X()-0.4;},1.28],{visible: false}),
repp2 = board.create('point', [function(){ return mp.X()+0.4;},1.28],{visible: false}),
repp3 = board.create('point', [function(){ return mp.X()+0.4;},1.72],{visible: false}),
repp4 = board.create('point', [function(){ return mp.X()-0.4;},1.72],{visible: false}),
eprect = board.create('polygon',[repp1,repp2,repp3,repp4],{fillColor: '#fff', fillOpacity: 0, highlightFillColor: '#fff', highlightFillOpacity: 0, borders: {color: '#000',strokeWidth: 0.5, highlightStrokeWidth: 0, highlightStrokeColor: '#000'}});
var poutlinelower = board.create('line', [[123,1.43],[function(){ return mp.X()-0.4;},1.43]], {straightFirst:false, straightLast:false, strokeColor: '#000', strokeWidth: 1.0, highlightStrokeWidth: 0, highlightFillColor: '#000', highlightStrokeColor: '#000', highlightFillOpacity: 1, highlightStrokeOpacity: 1});
var poutlineupper = board.create('line', [[123,1.57],[function(){ return mp.X()-0.4;},1.57]], {straightFirst:false, straightLast:false, strokeColor: '#000', strokeWidth: 1.0, highlightStrokeWidth: 0, highlightFillColor: '#000', highlightStrokeColor: '#000', highlightFillOpacity: 1, highlightStrokeOpacity: 1});
var pinlinelower = board.create('line', [[function(){ return mp.X()-120.4;},1.43],[122,1.43]], {straightFirst:false, straightLast:false, strokeColor: '#000', strokeWidth: 1.0, highlightStrokeWidth: 0, strokeOpacity: 0.15, highlightFillColor: '#000', highlightStrokeColor: '#000', highlightFillOpacity: 1, highlightStrokeOpacity: 0.15});
var pinlineupper = board.create('line', [[function(){ return mp.X()-120.4;},1.57],[122,1.57]], {straightFirst:false, straightLast:false, strokeColor: '#000', strokeWidth: 1.0, highlightStrokeWidth: 0, strokeOpacity: 0.15, highlightFillColor: '#000', highlightStrokeColor: '#000', highlightFillOpacity: 1, highlightStrokeOpacity: 0.15});
return div;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
There are features in here that I cannot work out how to replicate using the JME or JessieCode approach - eg switching off the image highlighting using im.hasPoint = function(){return false;}.
So so my question is: is it possible to create a JSXGraph in the robust way using a Numbas variable (what I'm calling the JME or JessieCode approach) that preserves access to all of JSXGraph's commands and functionality?
I'm thinking something like an object passed as a string to JSXGraph, eg (heuristically) 'disable_image_highlighting': [eval('im.hasPoint = function(){return false;}'].
Any help or advice is much appreciated.
Cheers,
Jim