From 7ac2270853bffefa9fbca54f3ea3f8e0bc7b1a07 Mon Sep 17 00:00:00 2001 From: Mark Hoeber Date: Tue, 18 Mar 2014 13:36:56 -0400 Subject: [PATCH] Custom JavaScript Display and Grading DOC-105 --- docs/en_us/developers/source/change_log.rst | 16 ++ docs/en_us/developers/source/conf.py | 7 + .../source/extending_platform/extending.rst | 89 +++++++ .../source/extending_platform/index.rst | 9 + .../source/extending_platform/javascript.rst | 239 ++++++++++++++++++ .../source/images/JavaScriptInputExample.png | Bin 0 -> 22893 bytes docs/en_us/developers/source/index.rst | 4 +- 7 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 docs/en_us/developers/source/change_log.rst create mode 100644 docs/en_us/developers/source/extending_platform/extending.rst create mode 100644 docs/en_us/developers/source/extending_platform/index.rst create mode 100644 docs/en_us/developers/source/extending_platform/javascript.rst create mode 100644 docs/en_us/developers/source/images/JavaScriptInputExample.png diff --git a/docs/en_us/developers/source/change_log.rst b/docs/en_us/developers/source/change_log.rst new file mode 100644 index 0000000000..075a9d21ff --- /dev/null +++ b/docs/en_us/developers/source/change_log.rst @@ -0,0 +1,16 @@ + +********** +Change Log +********** + + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Date + - Change + * - 03/28/2014 + - Added the :ref:`Custom JavaScript Display and Grading` chapter. + + diff --git a/docs/en_us/developers/source/conf.py b/docs/en_us/developers/source/conf.py index d29abc1e72..6e590335c4 100644 --- a/docs/en_us/developers/source/conf.py +++ b/docs/en_us/developers/source/conf.py @@ -9,6 +9,8 @@ from path import path on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + + sys.path.append('../../../../') from docs.shared.conf import * @@ -23,6 +25,11 @@ templates_path.append('source/_templates') # so a file named "default.css" will overwrite the builtin "default.css". html_static_path.append('source/_static') +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/docs/en_us/developers/source/extending_platform/extending.rst b/docs/en_us/developers/source/extending_platform/extending.rst new file mode 100644 index 0000000000..ac9f969779 --- /dev/null +++ b/docs/en_us/developers/source/extending_platform/extending.rst @@ -0,0 +1,89 @@ + +.. _Options for Extending the edX Platform: + +########################################## +Options for Extending the edX Platform +########################################## + +There are several options for extending the Open edX Platform to provide useful +and innovative educational content in your courses. + +This section of the developers' documentation lists and explains the different ways to extend the platform, starting with the following table. Click the name of the extension type in the column header for more information. + +.. list-table:: + :widths: 10 10 10 10 10 10 + :header-rows: 1 + + * - + - :ref:`Custom JavaScript Display and Grading` + - LTI + - External Graders + - XBlocks + - Platform Customization + * - Development Cost + - Low + - Low + - Medium + - Medium + - High + * - Language + - JavaScript + - Any + - Any + - Python + - Python + * - Development Environment Needed + - No + - No + - Yes + - Yes + - Yes + * - Self-hosting Needed + - No + - Yes + - Yes + - No + - No + * - Need edX Involvement + - No + - No + - Yes + - Yes + - Yes + * - Clean UI Integration + - Yes + - No (see LTI) + - Yes + - Yes + - Yes + * - Mobile enabled + - Possibly + - Possibly + - Yes + - Yes + - Yes + * - Server Side Grading + - No (See JavaScript) + - Yes + - Yes + - Yes + - Yes + * - Usage Data + - No (See JavaScript) + - No + - Limited + - Yes + - Yes + * - Provision in Studio + - No + - No + - No + - Yes + - No + * - Privacy Loss Compared to Hosting Open edX + - No + - Possibly + - Possibly + - No + - No + diff --git a/docs/en_us/developers/source/extending_platform/index.rst b/docs/en_us/developers/source/extending_platform/index.rst new file mode 100644 index 0000000000..19459b9bea --- /dev/null +++ b/docs/en_us/developers/source/extending_platform/index.rst @@ -0,0 +1,9 @@ +########################### +Extending the edX Platform +########################### + +.. toctree:: + :maxdepth: 2 + + extending.rst + javascript \ No newline at end of file diff --git a/docs/en_us/developers/source/extending_platform/javascript.rst b/docs/en_us/developers/source/extending_platform/javascript.rst new file mode 100644 index 0000000000..88de3df08a --- /dev/null +++ b/docs/en_us/developers/source/extending_platform/javascript.rst @@ -0,0 +1,239 @@ + +.. _Custom JavaScript Display and Grading: + +########################################## +Custom JavaScript Display and Grading +########################################## + +Custom JavaScript display and grading problems (also called custom JavaScript +problems or JS Input problems) allow you to create a custom problem or tool that +uses JavaScript and then add the problem or tool directly into Studio. When you +create a JS Input problem, Studio embeds the problem in an inline frame (IFrame) +so that your students can interact with it in the LMS. You can grade your +students’ work using JavaScript and some basic Python, and the grading is +integrated into the edX grading system. + +Course staff should see `documentation on using custom JavaScript `_ and `Establishing a Grading Policy `_ in *Building and Running an edX Course*. + +The rest of this section provides more information for developers who are creating JavaScript applications for courses on the edX platform. + +.. note:: This section assumes proficiency with JavaScript and Python, and with how problems are constructed in edX Studio. + +******************************* +The Template Example +******************************* + +As referred to in `course staff documentation `_, there is a built-in template in Studio that uses a sample +JavaScript application. + +This sample application has students select two different shapes, a cone +and a cube. The correct state is when the cone is selected and the cube is not selected: + +.. image:: ../images/JavaScriptInputExample.png + :alt: Image of the sample JavaScript application, with the cone selected + +You can `download files for that application `_. You must upload these files in edX Studio to use them in a problem. + +The following information uses this example to explain what developers need to know to embed their JavaScript applications in an edX course. + +******************************* +Required JavaScript Functions +******************************* + +To enable grading of students' interactions, your JavaScript application must contain three global methods: + +* ``getState`` +* ``setState`` +* ``getGrade`` + +You reference these methods in the XML problem specification, as described below. + +==================== +getState() Function +==================== + +Your application must be able to return the state of objects on which grades will be based. + +In the template example, grading is based on the the state of the cylinder and cone objects. The state is initialized for the cylinder and cube in the ``WebGLDemo.js`` file: + +.. code-block:: javascript + + var state = { + 'selectedObjects': { + 'cylinder': false, + 'cube': false + } + } + +User interactions toggle the ``state`` values of the cylinder and cube between ``true`` and ``false``. + +Your application must contain a ``getState()`` function that is referenced in the XML problem specification and that returns the current state as a JSON string. + +The following is the ``getState()`` function in the sample application: + +.. code-block:: javascript + + function getState() { + return JSON.stringify(state); + } + + +==================== +setState() Function +==================== + +When a student clicks **Check** for the JavaScript problem, the application's state must be saved so that the student can later return to the application and find it in the same state. + +Your application must contain a ``setState()`` function that is referenced in the XML problem specification and that saves the current state. + +The following is the ``setState()`` function in the sample application: + +.. code-block:: javascript + + function setState() { + stateStr = arguments.length === 1 ? arguments[0] : arguments[1]; + state = JSON.parse(stateStr); + updateMaterials(); + } + +The ``updateMaterials()`` function called by ``setState()`` updates the state of the cylinder and cone with the user's current selections: + +.. code-block:: javascript + + function updateMaterials() { + if (state.selectedObjects.cylinder) { + cylinder.material = selectedMaterial; + } + else { + cylinder.material = unselectedMaterial; + } + + if (state.selectedObjects.cube) { + cube.material = selectedMaterial; + } + else { + cube.material = unselectedMaterial; + } + } + +==================== +getGrade() function +==================== + +The student's interactions with your application, and the resulting application state, must be able to be graded. + +Your application must contain a ``getGrade()`` function that is referenced in the XML problem specification and that returns the current state as a JSON string. + +The following is the ``getGrade()`` function in the sample application: + +.. code-block:: javascript + + function getGrade() { + return JSON.stringify(state['selectedObjects']); + } + +The returned JSON string is then used by the Python code defined in the problem to determine if the student's submission is correct or not, as described in the next section. + +******************************* +Grading the Student Response +******************************* + +The problem definition contains Python code that, when the student clicks **Check**, parses the JSON string returned by your application's ``getGrade()`` function and determines if the student's submission is correct or not. + +The following is the Python function ``vglcfn`` in the sample application: + +.. code-block:: python + + + +In this example, the ``ans`` parameter contains the JSON string returned by ``getGrade()``. The value is converted to a Python Unicode (?) structure in the variable ``par``. + +In the function's first option, object(s) the student selected are stored in the ``answer`` variable. If the student selected the cylinder and not the cube, the ``answer`` variable contains only ``cylinder``, and the function returns ``True``, which signifies a correct answer. Otherwise, it returns ``False`` and the answer is incorrect. + +In the function's second option, the objects' states are retrieved. If the cylinder is selected and not the cube, the function returns ``True``, which signifies a correct answer. Otherwise, it returns ``False`` and the answer is incorrect. + + +******************************* +XML Problem Structure +******************************* + +Following the Python code and any HTML content you want to precede the IFrame containing your JavaScript application, you define the XML for the problem. + +The XML problem for the sample template is: + +.. code-block:: xml + + + + + +As in this example, the JS Input problem is defined in a ```` element. + +The value of the ``cfn`` attribute is the name of the Python function in the problem that evaluates the submission's grade. + +The ```` element contains a ```` element, which defines how your JavaScript application is used in the course. + +Following are details about the attributes of the ```` element. + +=================== +jsinput attributes +=================== + +.. list-table:: + :widths: 10 80 10 + :header-rows: 1 + + * - Attribute + - Description + - Example + * - gradefn + - The function in your JavaScript application that returns the state of the objects to be evaluated as a JSON string. + - ``WebGLDemo.getGrade`` + * - get_statefun + - The function in your JavaScript application that returns the state of the objects. [NOT CLEAR TO ME WHY YOU NEED BOTH getGrade and setState] + - ``WebGLDemo.getState`` + * - set_statefun + - The function in your JavaScript application that saves the state of the objects. + - ``WebGLDemo.setState`` + * - width + - The width of the IFrame in which your JavaScript application will be displayed, in pixels. + - 400 + * - height + - The height of the IFrame in which your JavaScript application will be displayed, in pixels. + - 400 + * - html_file + - The name of the HTML file containing your JavaScript application that will be loaded in the IFrame. + - /static/webGLDemo.html + * - sop + - The same-origin policy (SOP), meaning that all elements have the same protocol, host, and port. To bypass the SOP, set to ``true``. + - false diff --git a/docs/en_us/developers/source/images/JavaScriptInputExample.png b/docs/en_us/developers/source/images/JavaScriptInputExample.png new file mode 100644 index 0000000000000000000000000000000000000000..1c9220de00e0fe1bbf6abf0101dead06febbd778 GIT binary patch literal 22893 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
UroY?O~;-+qz(?y5uv=ZDJwLjP=Y}Cxspb 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