Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Drag and drop question type flash development: Difference between revisions

From MoodleDocs
(7 intermediate revisions by the same user not shown)
Line 3: Line 3:
I have a project where the need has arisen to be able to define drop targets for this question type which are not just rectangular - ellipses and polygonal targets are also needed.
I have a project where the need has arisen to be able to define drop targets for this question type which are not just rectangular - ellipses and polygonal targets are also needed.


After much discussion, we decided this was going to be far too hard to do in Javascript and we should use flash instead.  The default for this module will still be the plain javascript version, with a toggle to use the flash version.
After much discussion, we decided this was going to be far too hard to do in Javascript and we should use flash instead.  After initially planning to add a flash only mode to the existing drag & drop question type, I decided to write a new flash only one from scratch.


The teacher will be given a flash object to define the drop targets and the mappings between them and the drag targets, and the student will be presented with a similar interface.
The teacher will be given a flash object to define the drop targets and the mappings between them and the drag targets, and the student will be presented with a similar interface.


==Functional Requirements==
==Flash requirements==


===Teacher defining===
There are three different modes for the Flash movie, documented below in further depth in the technical section


* Add an option in the first form in the module to use an advanced flash only version (with appropriate warning about additional software needing to be installed)
===Teacher defines a question (new or editing existing)===


* If this button is not clicked, show the standard currently existing form and the positioning window.
The flash object must load the background image previously selected by the teacher, and allow them to create and position hotspots on it.


* If this button '''is''' clicked - don't show the current form, or the positioning window, but instead launch a window with a flash object to create the drop targets and the mappings.
The hotspots must be either made with a polygon tool, allowing them to draw lines until the shape is completed, or an ellipsis tool, which is either a circle or an ellipse.


==Technical Details==
The teacher must then define mappings between the drag targets (previously selected by the teacher) and the hotspots they have created, and define an optional 'snap point' if this configuration item has been selected.
 
Because Moodle requires question definition data to be in a $mform (Moodle form), the flash object must read from and write to the DOM to communicate. This is dtetailed further in the javascript section.
 
===Student attempts a question===
 
When the student is attempting the quiz, the flash movie will be loaded, and they will be able to drag the drag items onto hotspots on the background image.  Depending on config, the drag items will snap to points or not.  The flash movie must again use javascript to read from and write to the DOM.


===Database changes===
===Teacher or student view student's attempt===


====Summary====
Given a list of hotspot definitions, the drag items, and the student's mappings, the flash object must present a rastered version of the student's attempt.


The database changes needed are:
==Technical Details==


* a flag as to whether flash should be used (once this is set, it cannot be unset) on the question_dragdrop table.
===Database changes===
* removing the existing dimension columns from the hotspot table and moving them into the polygon table (rectangles are just polygons)
* the creation of new tables to hold polygon points, and ellipses x and y (should this be top left, or middle?) and both radii
* a new table to map hotspots to media, and the removal of the 'hotspot' column in the media table.
* TODO what is 'primary' hotspot column in media table?


====Tables====
====Tables====


=====mdl_question_dragdrop_hotspot=====
=====question_flashdd=====


{| class="nicetable"
{| class="nicetable"
Line 44: Line 46:
|-
|-
|questionid
|questionid
|fk to mdl_question
|fk to question
|-
|snaptopoints
|boolean
|-
|-
|shape
|backgroundpath
|polygon or ellipsis
|path to use (coursefiles url - this will change to an fk to file in 2.0)
|-
|-
|}
|}


=====mdl_question_dragdrop_hotspot_ellipsis=====
=====question_flashdd_hotspot=====


{| class="nicetable"
{| class="nicetable"
Line 61: Line 66:
|sequence
|sequence
|-
|-
|hotspotid
|questionid
|fk to mdl_question_dragdrop_hotspot
|fk to mdl_question
|-
|-
|x
|shape
|top left x
|polygon or ellipse
|-
|-
|y
|geometry
|top left y
|Blob of serialised data
|-
|-
|rv
|snapx (nullable)
|vertical radius
|x point to snap to
|-
|-
|rh
|snapy (nullable)
|horizontal radius
|y point to snap to
|-
|-
|}
|}


=====mdl_question_dragdrop_hotspot_polygon=====
=====question_flashdd_media=====


{| class="nicetable"
{| class="nicetable"
Line 88: Line 93:
|sequence
|sequence
|-
|-
|hotspotid
|questionid
|fk to mdl_question_dragdrop_hotspot
|fk to question
|-
|filepath
|coursefiles (will be upgraded to file id in 2.0)
|-
|-
|points
|alttext
|comma separated list of points **
|optional alt text to display
|-
|-
|}
|}


=====mdl_question_dragdrop_mapping=====
=====question_flashdd_mapping=====


{| class="nicetable"
{| class="nicetable"
Line 107: Line 115:
|-
|-
|questionid
|questionid
|fk to mdl_question
|fk to question
|-
|-
|hotspotid
|hotspotid
|fk to mdl_question_dragdrop_hotspot
|fk to question_flashdd_hotspot
|-
|-
|mediaid
|mediaid
|fk to mdl_question_dragdrop_media
|fk to question_flashdd_media
|-
|-
|primary
|matches the old primaryhotspot table on the media table.
|}
|}


  ** Not sure about this, or whether the table should be renamed mdl_question_dragdrop_hotspot_polygon_point and just contain many rows per entry.
===Flash/Javascript communication===
 
====Rationale====
 
I had originally thought that the best way to communicate between the Flash
object and Moodle would be the use of XMLHttp Requests, but after writing the
Matrix Question type and having a better understanding of the Question API, I
realise that this is not really the best approach, or even a particularly sound
one.  For an example of why not, imagine the case of creating a new question.
The question record gets inserted by the question API rather than the question
type - which means that the XMLHttp handler would be faced with the situation of
being sent hotspot and media mapping data before the question is actually saved
into the database.
 
Thus, it makes a lot more sense to just use forms as Moodle expects, and get
Flash to read from, and write to, hidden form fields.
 
There are three different modes the Flash object must behave in:
 
* Definition mode (teacher defining where the hotspots are and which items drag to them)
* Test mode (student attempting question)
* Review mode (student or teacher reviewing a rendered version in read only mode)
 
=====Example Javascript=====
 
<code javascript>
 
var formname = null; // set by inline JS in the form definition
 
/**
* add a new hotspot to the list
*
* @param int id new unique id for this hotspot (not persistent - will be replaced by moodle on save)
* @param string shape currently just ellipse or polygon
* @param string geometry whatever data needs to be saved to define the hotspot - will just be saved as is and passed back to flash in this form next time
*
* @return boolean success or failure
*/
function addHotspot(id, shape, geometry, snapx, snapy) { }
 
 
/**
* update an existing hotspot definition
*
* @param int id new unique id for this hotspot (not persistent - will be replaced by moodle on save)
* @param string shape currently just ellipse or polygon
* @param string geometry whatever data needs to be saved to define the hotspot - will just be saved as is and passed back to flash in this form next time
*
* @return boolean success or failure
*/
function updateHotspot(id, shape, geometry, snapx, snapy) { }
 
 
/**
* delete a hotspot from the list
*
* @param int id the id of the hotspot to be deleted - this is whatever was added with addHotspot, or read with getHotspots
*
* @return boolean success or failure
*/
function deleteHotspot(id) { }
 
 
/**
* adds a new mapping to the list of dragitems to hotspots
*
* @param integer dragitemid
* @param integer hotspotid
*
* @return boolean success or failure
*/
function addMapping(dragitemid, hotspotid) { }


====Upgrades====


Upgrading from the old drag and drop module to the new one involves:
/**
* delete an existing hotspot mapping from the list
*
* @param integer dragitemid
* @param integer hotspotid
*
* @return boolean success or failure
*/
function deleteMapping(dragitemid, hotspotid) { }


* Creating the new tables and columns '''first'''
/**
* Creating records in the mapping table to match mdl_question_dragdrop_media.hotspots
* adds a new mapping to the list of dragitems to hotspots
* Removal of mdl_question_dragdrop_media.hotspots column
*
* Creating records in the polygon table to match mdl_question_dragdrop_hotspot.x,y,width&height and updating the new shape field to 'polygon'
* @param integer dragitemid
* Removal of mdl_question_dragdrop_hotspot.x,y,width&height columns
* @param integer hotspotid (can be 0 if the student has dragged the item somewhere that isn't on a hotspot)
* @param integer x the actual point the student put the item on the x axis
* @param integer y the actual point the student put the item on the y axix
*
* @return boolean success or failure
*/
function addStudentMapping(dragitemid, hotspotid, x, y) { }


===XML definition for communication between PHP and Flash===


There are five different times that data needs to be sent between PHP and
/**
Flash. Each point in the following list, data needs to flow in both
  * delete an existing hotspot mapping from the list
directions. XML will be used for both directions.  Flash will make a HTTP POST
  *
to PHP, with one post var, 'xml' containing the data. For Flash to get data
* @param integer dragitemid
from PHP, it will make an HTTP GET request and the body of the response data
* @param integer hotspotid (can be 0 if the student has dragged the item somewhere that isn't on a hotspot)
will be the XML data.
* @param integer x the actual point the student put the item on the x axis
* @param integer y the actual point the student put the item on the y axix
*
* @return boolean success or failure
*/
function deleteStudentMapping(dragitemid, hotspotid, x, y) { }


====Teacher defines a new question====
/**
* Fetch the path to the background image to use
*
* @return string full url to use to render the image
*/
function getBackground() { }
 
/**
* Fetch the option about whether to snap to points
*
* @return boolean on or off
*/
function getSnapOption() { }
 
/**
* Get the list of all the defined items to drag
* This will return an array of hashes like this:
    var dragitems = Array(
        { 'id': 6, 'filepath': 'fullurl', 'alttext': 'optional hint on hover' },
        { 'id': 7, 'filepath': 'fullurl', 'alttext': 'optional hint on hover' },
        { 'id': 8, 'filepath': 'fullurl', 'alttext': 'optional hint on hover' }
    );
* The serialized form of this (that is stored in the form field) looks like:
* id:6|filepath:path/to/file|alttext:some content here||id:7|filepath:path/to/file|alttext:some content here
* that is, items are separated by ||, fields are separated by | and each field/value pair are split with :
* Some values might include : but we just match the first one and take the rest of the string as the value.
*/
function getDragItems() { }
 
/**
* Get the list of hotspots that are currently defined and saved in Moodle.
* This will return an array of hashes like this:
    var hotspots = Array(
        { 'id': 6, 'shape': 'ellipse', 'geometry': '1,4,6,6', 'snapx': 6, 'snapy', 7 }, // circle
        { 'id': 7, 'shape': 'ellipse', 'geometry': '1,4,6,8' }, // ellipse
        { 'id': 8, 'shape': 'polygon', 'geometry': '1,4,6,6' }, // square
        { 'id': 8, 'shape': 'polygon', 'geometry': '1,4,6,6,8,9,0,5,2' } // totally whatck shaped polygon
    );
* The serialised form of this (that is stored in the form field) looks like:
* id:6|shape:ellipse|geometry:1,4,6,6|snapx:6|snapy:7||id:7|shape:ellipse|geometry:1,4,6,8
* In a very similar form to the other serialized forms.
*/
function getHotspots() { }
 
/**
* Get the list of mappings that currently exist between Drag items and Hotspots
* This will return an array of hashes like this:
    var mappings = Array(
        { 'hotspotid': 6, 'mediaid': 8 },
        { 'hotspotid': 7, 'mediaid': 9 },
        { 'hotspotid': 8, 'mediaid': 10 },
        { 'hotspotid': 9, 'mediaid': 11 },
    );
* The serialised form of this (that is stored in the form field) looks like:
* hotspotid:6|mediaid:8||hotspotid:7|mediaid:9
* In a very similar form to the other serialized forms.
*/
function getMappings() { }


=====Data from PHP to Flash=====


* filename and filepath of background image
/**
* an array of information about the draggable objects, filename and filepath of reach
* Get the list of student mappings that currently exist between Drag items and Hotspots
* configdata (eg whether the snap flag is set)
* This will return an array of hashes like this:
    var mappings = Array(
        { 'hotspotid': 6, 'mediaid': 8, 'x': 12, 'y': 13 },
        { 'hotspotid': 7, 'mediaid': 9 , 'x': 14, 'y': 15},
        { 'hotspotid': 8, 'mediaid': 10 , 'x': 16, 'y': 17},
        { 'hotspotid': 9, 'mediaid': 11 , 'x': 18, 'y': 19},
    );
* The serialised form of this (that is stored in the form field) looks like:
* hotspotid:6|mediaid:8|x:12|y:13||hotspotid:7|mediaid:9|x:14|y:15
* In a very similar form to the other serialized forms.
*/
function getStudentMappings() { }


Example XML:


<code xml>
<xml>
    <defdata>
        <background>
            <filename>stuff.jpg</filename>
            <url>http://moodle.domain.com/file.php?path=course/1/stuff.jpg</url>
        </background>
        <dragobjects>
            <dragobject id="1">
                <filename>smallobject1.jpg</filename>
                <url>http://moodle.domain.com/file.php?path=course/1/smallobject1.jpg</url>
            </dragobject>
            <dragobject>
                ...
            </dragobject>
        <configdata>
            <snap>true</snap>
        </configdata>
    </defdata>
</xml>
</code>
</code>


=====Data from Flash to PHP=====
====Teacher defines a new question====


* The definitions of the hotspots
Flash needs filepaths and alt text of all the media used in this question, as
* The matching of drag objects to hotspots
well as information about the bavckground image, and some config data.


Example XML:
These items will all be already present in the form, and just need to be read.


<code xml>
I will write javascript methods to interface with the DOM that Flash can call to
<xml>
get and set properties of the form.
    <defdata>
        <hotspots>
            <hotspot id="somethinguniquegeneratedbyflash">
                <type>(polygon|ellipsis)</type>
                <coords>x,y,x,y,x,y,x,y</coords> <!-- for polygons -->
                <radii>3,6</radii> <!-- for circles or ellipses -->
            </hotspot>
            <hotspot>
                ...
            </hotspot>
        </hotspots>
        <mappings>
            <mapping>
                <hotspot id="somethingunique" />
                <dragobject id="1" />
        </mappings>
    </defdata>
</xml>
</code>


====Teacher edits the definition of an existing question====
Everytime a new hotspot is added, or a drag item mapped to it, Flash must update
the hidden fields in the question definition form, and it will do this by
calling javascript methods I write that can write to the form.


This is exactly the same as the above case, except that the <hotspots> and <mappings> sections are also included in the data from PHP to Flash.
Note: it's possible that the teacher can trigger a reload of the Flash object
after they've already started defining hotspots.  This means that it must always
read not just the media definitions, but also check for existing hotspot and
mapping definitions on load, even when adding a new question.  Actually this
simplifies things on the Flash side, because it means there's no difference
between edit and add code.


====Student attempting a question====
=====Methods Used=====


=====Data from PHP to Flash=====
* addHotspot
* updateHotspot
* deleteHotspot
* addMapping
* deleteMapping
* getBackground
* getSnapOption
* getDragItems
* getHotspots
* getMappings


This has no new data from the above two examples, but does not include the <mappings> section.


=====Data from Flash to PHP=====
====Teacher edits an existing question====


Flash just needs to send back the mappings that the student has selected.
Exactly the same as the previous point.


Example XML
=====Student attempting a question=====


<code xml>
This will use a subset of the available methods.
<xml>
    <defdata>
        <mappings>
            <mapping>
            <hotspot id="6" />
            <dragobject id="7" />
        <mappings>
    </defdata>
</xml>
</code>


====Student feedback====
This can either be editing an attempt, or starting a new one, so the existing
mapping definitions must be observed.


We may need to generate a report for the student that does one of two things:
=====Methods Used=====


* Shows them their generated image, with color indicators to show correctness
* addStudentMapping
* Shows them the image with the correct answers placed
* deleteStudentMapping
* getBackground
* getSnapOption
* getDragItems
* getHotspots
* getStudentMappings


In both cases, the entire definition needs to be sent from PHP to Flash, with one addition in the <mapping> section:
====Student feedback====


<code xml>
A read-only rendered version of the final results with the drag items marked to
<xml>
their places
    <defdata>
        ....
        <mappings>
            <mapping>
            <hotspot id="6" />
            <dragobject id="7" />
            <correct>true</correct>
        <mappings>
    </defdata>
</xml>
</code>


====Teacher reporting of student attempt====
=====Methods Used=====


This is exactly the same as the above case.
* getBackground
* getSnapOption
* getDragItems
* getHotspots
* getStudentMappings


====Notes====
====Teacher reporting of student attempt====


* The first time the <hotspot> tag is sent is from Flash to PHP and will include the ID generated by Flash.  All subsequent communication will include the ID that Moodle generates (an auto-increment database ID)
Exactly the same as the previous point

Revision as of 12:07, 6 May 2009

Preamble

I have a project where the need has arisen to be able to define drop targets for this question type which are not just rectangular - ellipses and polygonal targets are also needed.

After much discussion, we decided this was going to be far too hard to do in Javascript and we should use flash instead. After initially planning to add a flash only mode to the existing drag & drop question type, I decided to write a new flash only one from scratch.

The teacher will be given a flash object to define the drop targets and the mappings between them and the drag targets, and the student will be presented with a similar interface.

Flash requirements

There are three different modes for the Flash movie, documented below in further depth in the technical section

Teacher defines a question (new or editing existing)

The flash object must load the background image previously selected by the teacher, and allow them to create and position hotspots on it.

The hotspots must be either made with a polygon tool, allowing them to draw lines until the shape is completed, or an ellipsis tool, which is either a circle or an ellipse.

The teacher must then define mappings between the drag targets (previously selected by the teacher) and the hotspots they have created, and define an optional 'snap point' if this configuration item has been selected.

Because Moodle requires question definition data to be in a $mform (Moodle form), the flash object must read from and write to the DOM to communicate. This is dtetailed further in the javascript section.

Student attempts a question

When the student is attempting the quiz, the flash movie will be loaded, and they will be able to drag the drag items onto hotspots on the background image. Depending on config, the drag items will snap to points or not. The flash movie must again use javascript to read from and write to the DOM.

Teacher or student view student's attempt

Given a list of hotspot definitions, the drag items, and the student's mappings, the flash object must present a rastered version of the student's attempt.

Technical Details

Database changes

Tables

question_flashdd
field notes
id sequence
questionid fk to question
snaptopoints boolean
backgroundpath path to use (coursefiles url - this will change to an fk to file in 2.0)
question_flashdd_hotspot
field notes
id sequence
questionid fk to mdl_question
shape polygon or ellipse
geometry Blob of serialised data
snapx (nullable) x point to snap to
snapy (nullable) y point to snap to
question_flashdd_media
field notes
id sequence
questionid fk to question
filepath coursefiles (will be upgraded to file id in 2.0)
alttext optional alt text to display
question_flashdd_mapping
field notes
id sequence
questionid fk to question
hotspotid fk to question_flashdd_hotspot
mediaid fk to question_flashdd_media

Flash/Javascript communication

Rationale

I had originally thought that the best way to communicate between the Flash object and Moodle would be the use of XMLHttp Requests, but after writing the Matrix Question type and having a better understanding of the Question API, I realise that this is not really the best approach, or even a particularly sound one. For an example of why not, imagine the case of creating a new question. The question record gets inserted by the question API rather than the question type - which means that the XMLHttp handler would be faced with the situation of being sent hotspot and media mapping data before the question is actually saved into the database.

Thus, it makes a lot more sense to just use forms as Moodle expects, and get Flash to read from, and write to, hidden form fields.

There are three different modes the Flash object must behave in:

  • Definition mode (teacher defining where the hotspots are and which items drag to them)
  • Test mode (student attempting question)
  • Review mode (student or teacher reviewing a rendered version in read only mode)
Example Javascript

var formname = null; // set by inline JS in the form definition

/**

* add a new hotspot to the list
*
* @param int id new unique id for this hotspot (not persistent - will be replaced by moodle on save)
* @param string shape currently just ellipse or polygon
* @param string geometry whatever data needs to be saved to define the hotspot - will just be saved as is and passed back to flash in this form next time
*
* @return boolean success or failure
*/

function addHotspot(id, shape, geometry, snapx, snapy) { }


/**

* update an existing hotspot definition
*
* @param int id new unique id for this hotspot (not persistent - will be replaced by moodle on save)
* @param string shape currently just ellipse or polygon
* @param string geometry whatever data needs to be saved to define the hotspot - will just be saved as is and passed back to flash in this form next time
*
* @return boolean success or failure
*/

function updateHotspot(id, shape, geometry, snapx, snapy) { }


/**

* delete a hotspot from the list
*
* @param int id the id of the hotspot to be deleted - this is whatever was added with addHotspot, or read with getHotspots
*
* @return boolean success or failure
*/

function deleteHotspot(id) { }


/**

* adds a new mapping to the list of dragitems to hotspots
*
* @param integer dragitemid
* @param integer hotspotid
*
* @return boolean success or failure
*/

function addMapping(dragitemid, hotspotid) { }


/**

* delete an existing hotspot mapping from the list
*
* @param integer dragitemid
* @param integer hotspotid
*
* @return boolean success or failure
*/

function deleteMapping(dragitemid, hotspotid) { }

/**

* adds a new mapping to the list of dragitems to hotspots
*
* @param integer dragitemid
* @param integer hotspotid (can be 0 if the student has dragged the item somewhere that isn't on a hotspot)
* @param integer x the actual point the student put the item on the x axis
* @param integer y the actual point the student put the item on the y axix
*
* @return boolean success or failure
*/

function addStudentMapping(dragitemid, hotspotid, x, y) { }


/**

* delete an existing hotspot mapping from the list
*
* @param integer dragitemid
* @param integer hotspotid (can be 0 if the student has dragged the item somewhere that isn't on a hotspot)
* @param integer x the actual point the student put the item on the x axis
* @param integer y the actual point the student put the item on the y axix
*
* @return boolean success or failure
*/

function deleteStudentMapping(dragitemid, hotspotid, x, y) { }

/**

* Fetch the path to the background image to use
*
* @return string full url to use to render the image
*/

function getBackground() { }

/**

* Fetch the option about whether to snap to points
*
* @return boolean on or off
*/

function getSnapOption() { }

/**

* Get the list of all the defined items to drag
* This will return an array of hashes like this:
   var dragitems = Array(
       { 'id': 6, 'filepath': 'fullurl', 'alttext': 'optional hint on hover' },
       { 'id': 7, 'filepath': 'fullurl', 'alttext': 'optional hint on hover' },
       { 'id': 8, 'filepath': 'fullurl', 'alttext': 'optional hint on hover' }
   );
* The serialized form of this (that is stored in the form field) looks like:
* id:6|filepath:path/to/file|alttext:some content here||id:7|filepath:path/to/file|alttext:some content here
* that is, items are separated by ||, fields are separated by | and each field/value pair are split with :
* Some values might include : but we just match the first one and take the rest of the string as the value.
*/

function getDragItems() { }

/**

* Get the list of hotspots that are currently defined and saved in Moodle.
* This will return an array of hashes like this:
   var hotspots = Array(
       { 'id': 6, 'shape': 'ellipse', 'geometry': '1,4,6,6', 'snapx': 6, 'snapy', 7 }, // circle
       { 'id': 7, 'shape': 'ellipse', 'geometry': '1,4,6,8' }, // ellipse
       { 'id': 8, 'shape': 'polygon', 'geometry': '1,4,6,6' }, // square
       { 'id': 8, 'shape': 'polygon', 'geometry': '1,4,6,6,8,9,0,5,2' } // totally whatck shaped polygon
   );
* The serialised form of this (that is stored in the form field) looks like:
* id:6|shape:ellipse|geometry:1,4,6,6|snapx:6|snapy:7||id:7|shape:ellipse|geometry:1,4,6,8
* In a very similar form to the other serialized forms.
*/

function getHotspots() { }

/**

* Get the list of mappings that currently exist between Drag items and Hotspots
* This will return an array of hashes like this:
   var mappings = Array(
       { 'hotspotid': 6, 'mediaid': 8 },
       { 'hotspotid': 7, 'mediaid': 9 },
       { 'hotspotid': 8, 'mediaid': 10 },
       { 'hotspotid': 9, 'mediaid': 11 },
   );
* The serialised form of this (that is stored in the form field) looks like:
* hotspotid:6|mediaid:8||hotspotid:7|mediaid:9
* In a very similar form to the other serialized forms.
  • /

function getMappings() { }


/**

* Get the list of student mappings that currently exist between Drag items and Hotspots
* This will return an array of hashes like this:
   var mappings = Array(
       { 'hotspotid': 6, 'mediaid': 8, 'x': 12, 'y': 13 },
       { 'hotspotid': 7, 'mediaid': 9 , 'x': 14, 'y': 15},
       { 'hotspotid': 8, 'mediaid': 10 , 'x': 16, 'y': 17},
       { 'hotspotid': 9, 'mediaid': 11 , 'x': 18, 'y': 19},
   );
* The serialised form of this (that is stored in the form field) looks like:
* hotspotid:6|mediaid:8|x:12|y:13||hotspotid:7|mediaid:9|x:14|y:15
* In a very similar form to the other serialized forms.
  • /

function getStudentMappings() { }


Teacher defines a new question

Flash needs filepaths and alt text of all the media used in this question, as well as information about the bavckground image, and some config data.

These items will all be already present in the form, and just need to be read.

I will write javascript methods to interface with the DOM that Flash can call to get and set properties of the form.

Everytime a new hotspot is added, or a drag item mapped to it, Flash must update the hidden fields in the question definition form, and it will do this by calling javascript methods I write that can write to the form.

Note: it's possible that the teacher can trigger a reload of the Flash object after they've already started defining hotspots. This means that it must always read not just the media definitions, but also check for existing hotspot and mapping definitions on load, even when adding a new question. Actually this simplifies things on the Flash side, because it means there's no difference between edit and add code.

Methods Used
  • addHotspot
  • updateHotspot
  • deleteHotspot
  • addMapping
  • deleteMapping
  • getBackground
  • getSnapOption
  • getDragItems
  • getHotspots
  • getMappings


Teacher edits an existing question

Exactly the same as the previous point.

Student attempting a question

This will use a subset of the available methods.

This can either be editing an attempt, or starting a new one, so the existing mapping definitions must be observed.

Methods Used
  • addStudentMapping
  • deleteStudentMapping
  • getBackground
  • getSnapOption
  • getDragItems
  • getHotspots
  • getStudentMappings

Student feedback

A read-only rendered version of the final results with the drag items marked to their places

Methods Used
  • getBackground
  • getSnapOption
  • getDragItems
  • getHotspots
  • getStudentMappings

Teacher reporting of student attempt

Exactly the same as the previous point