GithubHelp home page GithubHelp logo

amp-up-io / qti3-item-player Goto Github PK

View Code? Open in Web Editor NEW
14.0 4.0 3.0 1.21 MB

The qti3-item-player component ("QTI 3 Player") is a 100% JavaScript component that aims to encapsulate the best practices and behaviors of the IMS Global QTI 3 Assessment Item specification.

Home Page: https://qti.amp-up.io/#about

License: MIT License

JavaScript 20.82% HTML 1.03% Vue 76.09% CSS 2.05%
qti3 webcomponents assessment-item scoring adaptive javascript

qti3-item-player's Introduction

Amp-up.io QTI 3 Player Component

MIT License

1EdTech Certified

The Amp-up.io QTI 3 Player Component ("QTI 3 Player") is a 100% JavaScript component that aims to encapsulate the best practices and behaviors of the IMS Global/1EdTech QTI 3 Assessment Item specification. A conforming QTI 3 authoring or exporting system can construct a QTI 3 Item XML solution that will "play" authentically and reliably in the QTI 3 Player - according to the Best Practices Implementation Guide which can be found here:

1EdTech QTI v3 Best Practices and Implementation Guide

QTI 3 Player has achieved both QTI 3 Basic and QTI 3 Advanced "Delivery" Conformance Certification from 1EdTech. Furthermore, QTI 3 Player supports many so-called "Elective" capabilities that go beyond Advanced delivery conformance.

For a complete list of the QTI3 XML elements supported by the QTI 3 Player component, please refer to the QTI 3 Player Item Reference.

About The Project

The QTI 3 Player has API's, interfaces, and capabilities which are optimized for formative or classroom assessment settings. Such settings typically require sophisticated QTI features such as adaptive items, item templating (sometimes called item "cloning"), template processing, and full response processing; i.e., scoring. The QTI 3 Player implements the full expressive QTI 3 Item XML vocabulary according to best practices. Consequently, you don't have to know anything about QTI. Just install the component in your project, inject XML, and go! In the following demo, a "TestRunner" application embeds the QTI 3 Player component for Item Rendering.

View TestRunner Demo

Thumbnails of Items/Rendering

(back to top)

Getting Started

1. Clone the repo

git clone https://github.com/amp-up-io/qti3-item-player.git

2. Install Node.js >= 16

QTI 3 Player was originally built and tested with Node v16.14. As of November 2023, QTI 3 Player has been built and tested with Node v20.9.0.

3. Installation

npm install

3. Compiles and hot-reloads for development

npm run serve

If you encounter an error about digital envelope routines::unsupported, this error was introduced in Node version >= 17 which changes the crypto hashing function. There are a number of easy workarounds for this. For example:

On Windows systems -

set NODE_OPTIONS=--openssl-legacy-provider

On Linux-like systems (Mac OS, Linux, Git bash, etc.) -

export NODE_OPTIONS=--openssl-legacy-provider

4. Compiles, minifies, creates package

npm run build:npm

(back to top)

Usage

The Demo TestRunner is a good way to get familiar with QTI 3 Player usage. Specifically, please see the TestRunner.vue sub-component.

1. Import QTI 3 Player and QTI 3 Player CSS

// The Qti3Player component and built-in CSS
import Qti3Player from 'qti3-item-player'
import 'qti3-item-player/dist/qti3Player.css'

(back to top)

2. Load the QTI 3 Player component in your Page or Template

<Qti3Player
  ref="qti3player"
  :container-class="containerClass"
  :container-padding-class="containerPaddingClass"
  :color-class="colorClass"
  suppress-alert-messages
  suppress-invalid-response-messages
  @notifyQti3PlayerReady="handlePlayerReady"
  @notifyQti3ItemReady="handleItemReady"
  @notifyQti3SuspendAttemptCompleted="handleSuspendAttemptCompleted"
  @notifyQti3EndAttemptCompleted="handleEndAttemptCompleted"
  @notifyQti3ScoreAttemptCompleted="handleScoreAttemptCompleted"
  @notifyQti3ItemAlertEvent="displayItemAlertEvent"
  @notifyQti3ItemCatalogEvent="handleItemCatalogEvent"
/>

(back to top)

3. Listen for the QTI 3 Player 'notifyQti3PlayerReady' event

This event signifies that the QTI 3 Player component is loaded and ready for action. The following snippet is a sample handler for the notifyQti3PlayerReady event. QTI 3 Player hands itself as an argument to the notifyQti3PlayerReady event, thus simplifying further QTI 3 Player API calls.

/**
 * @description Event handler for the QTI 3 Player component's 'notifyQti3PlayerReady'
 * event.  This event is fired upon mounting of QTI 3 Player.
 *
 * The Qti3Player is now ready for loading XML.
 * @param {Component} qti3Player - the QTI 3 Player component itself
 */
handlePlayerReady (qti3Player) {
  this.qti3Player = qti3Player
}

(back to top)

4. Load a QTI 3 Item into QTI 3 Player

Once QTI 3 Player is loaded and ready (see #3 above), QTI 3 Item XML can be loaded directly into QTI 3 Player via the Player's loadItemFromXML method which takes two arguments xml {String} and configuration {Object}.

// Load item XML with a configuration.  Use the 'this.qti3Player' reference
// saved in the notifyQti3PlayerReady event handler.
this.qti3Player.loadItemFromXml(xml, configuration)

4a) About a Configuration

The configuration object is used to specify runtime context to QTI 3 Player during the item session loaded in loadItemFromXml. A configuration object has the following structure:

configuration: {
  guid: <{String} identifier used to track item state>,
  pnp: <{Object} used to define Personal Needs and Preferences>,
  status: <{String} use to define Item Lifecycle Status>,
  sessionControl: <{Object} used to define Item Session Control>,
  state: <{Object} used to RESTORE prior state saved from a prior Item Session>
}

4b) Constructing a Configuration

The following snippet is an example of how an application can construct a configuration.

// Intialize
const configuration = {}

// Stamp an item's tracking guid (if any) onto the configuration
configuration.guid = myItemTrackingGuid

// QTI 3 Player includes a helper class called 'PnpFactory' which can be used
// to build a Personal Needs and Preferences definition.
// The Default pnp object in the PnpFactory is:
const pnp = {
  textAppearance: {
    colorStyle: 'qti3-player-color-default'
  },
  // Glossary is universal support turned on (true) by default
  glossaryOnScreen: true,
  // Keyword translation is off ('') by default
  keywordTranslationLanguage: '',
  // Custom SBAC Illustrated Glossary is off (false) by default
  extSbacGlossaryIllustration: false,
  layoutSingleColumn: false // unsupported - see Roadmap (Simplified Layout)
}

// Set the configuration's 'pnp' property
configuration.pnp = pnp

// OPTIONAL
// Use 'status' to reflect the current QTI Item Lifecycle Status, which is an 
// enumerated vocabulary from the set of:
// { 'initial' | 'interacting' | 'closed' | 'review' | 'solution'}
configuration.status = 'interacting'

// Set 'status' to 'review' in order to disable interactions; i.e., interactions
// can no longer be altered.
// configuration.status = 'review'

// QTI 3 Player includes a helper class called 'SessionControlFactory' which can be
// used to build an Item Session Control definition.
// The Default sessionControl object in the SessionControlFactory is:
const defaultItemSessionControl = {
  max_attempts: 0, // no limit
  show_feedback: false,
  validate_responses: false
}

// Set the configuration's 'sessionControl' property
configuration.sessionControl = defaultItemSessionControl

// OPTIONAL
// If a 'state' property is in a configuration then QTI 3 Player will
// use this to restore a prior item state - including all
// template, context, outcome, and response variables.
const state = testController.getTestStateItemState(myItemTrackingGuid)
if (typeof state !== 'undefined') configuration.state = state

In the absence of a pnp property, QTI 3 Player will use defaults, or previous settings, for presentation and accessibility supports. In the absence of a sessionControl property, QTI 3 Player will use defaults, or previous settings, for the Item Session Control definition.

(back to top)

5. Listen for the QTI 3 Player 'notifyQti3ItemReady' Event

QTI 3 Player triggers a notifyQti3ItemReady event upon completion of the Player's loadItemFromXML method. The following snippet is a sample handler for the notifyQti3ItemReady event.

/**
 * @description Event handler for the QTI3Player component's 'notifyQti3ItemReady'
 * event.  This event is fired upon completion of the qti-assessment-item
 * component's loading of XML.
 */
handleItemReady () {
  console.log('QTI 3 Item XML is loaded and rendered!  The latest "attempt" has officially begun.')
}

(back to top)

6. Retrieving Item State

After item XML is loaded and an attempt has begun, a test controller may retrieve the item's current state via two methods:

  • endAttempt

    This performs response validation (if validateResponses=true), ends the attempt, executes response processing, and produces the state of all item variables. Typical use is when submissionMode: "individual", or when you want to generate a raw score from the responses and the response processing. Note that Feedback (inline, block, modal) is also displayed if showFeedback: true.

    QTI 3 Player supports the full QTI 3 response processing expression vocabulary.

  • suspendAttempt

    This performs response validation (if validateResponses: true) and produces the state of all item variables. No response processing is executed. Typical use is when submissionMode: "simultaneous".

The endAttempt and suspendAttempt methods may take a considerable amount of time to complete. QTI 3 Player triggers the notifyQti3EndAttemptCompleted and notifyQti3SuspendAttemptCompleted events, respectively, upon completion of an endAttempt or a suspendAttempt method call.

6a) Calling endAttempt and handling the notifyQti3EndAttemptCompleted event

// Call the endAttempt method, passing a string/target action that will be
// echoed back in the notifyQti3EndAttemptCompleted event payload.
this.qti3Player.endAttempt('navigateNextItem')
/**
 * @description Example event handler for the QTI3Player component's 'notifyQti3EndAttemptCompleted'
 * event.  This event is fired upon completion of the endAttempt method.
 * @param {Object} data - the item's state, including outcomes from response processing
 */
handleEndAttemptCompleted (data) {
  // 'data' contains the item state, including any validation messages,
  // response variable values, outcome variable values, template variable values,
  // and context variable values.
  // ... do something ...
}

6b) Calling suspendAttempt and handling the notifyQti3SuspendAttemptCompleted event

// Call the suspendAttempt method, passing a string/target action that will be
// echoed back in the notifyQti3SuspendAttemptCompleted event payload.
this.qti3Player.suspendAttempt('navigateNextItem')
/**
 * @description Example event handler for the QTI3Player component's 'notifyQti3SuspendAttemptCompleted'
 * event.  This event is fired upon completion of the suspendAttempt method.
 * @param {Object} data - the item's state
 */
handleSuspendAttemptCompleted (data) {
  // 'data' contains the item state, including any validation messages,
  // response variable values, outcome variable values, template variable values,
  // and context variable values.
  // ... do something ...
}

(back to top)

7. About Item State

Item State Object Structure

The endAttempt, suspendAttempt, and scoreAttempt methods produce a state object with the following properties/structure:

"state": {
  "identifier": "<qti-assessment-item identifier>",
  "guid": "<tracking guid passed in the configuration>",
  "contextVariables": [ <built-in and declared context variables> ],
  "responseVariables": [ <built-in and declared response variables> ],
  "outcomeVariables": [ <built-in and declared outcome variables> ],
  "templateVariables": [ <declared template variables> ],
  "validationMessages": [ <validation messages (if validateResponses: true, and response constraints not met)> ]
}

Full Item State Example Payload

In this item, there are two qti-choice-interaction's, each with single cardinality. This item is not adaptive; i.e., adaptive="false", and the item's XML contains no response processing that changes the original value of completionStatus.

{
  "state": {
    "identifier": "q2-choice-interaction-single-sv-4a",
    "guid": "0000-0002-0001",
    "contextVariables": [
      {
        "identifier": "QTI_CONTEXT",
        "cardinality": "record",
        "value": {}
      }
    ],
    "responseVariables": [
      {
        "identifier": "numAttempts",
        "cardinality": "single",
        "value": 1,
        "state": null
      },
      {
        "identifier": "duration",
        "cardinality": "single",
        "value": 0,
        "state": null
      },
      {
        "identifier": "RESPONSE1",
        "cardinality": "single",
        "value": "ChoiceA",
        "state": {
          "order": [
            "ChoiceA",
            "ChoiceB",
            "ChoiceC"
          ]
        },
        "correctResponse": null
      },
      {
        "identifier": "RESPONSE2",
        "cardinality": "single",
        "value": "ChoiceB",
        "state": {
          "order": [
            "ChoiceA",
            "ChoiceB",
            "ChoiceC"
          ]
        },
        "correctResponse": null
      }
    ],
    "outcomeVariables": [
      {
        "identifier": "SCORE",
        "cardinality": "single",
        "value": 0
      },
      {
        "identifier": "completionStatus",
        "cardinality": "single",
        "value": "not_attempted"
      }
    ],
    "templateVariables": [],
    "validationMessages": []
  },
  "target": "navigateNextItem"
}

(back to top)

8. Scoring API

There are scenarios where an encapsulating application may load item XML - along with a provided Item State - into QTI 3 Player and then score the Item State by executing response processing. Such a scenario exists when a Test Part's submission-mode is set to simultaneous. Another use-case is when a scoring system is batch-scoring a collection of items and a candidate's Item States from a submitted Test. For these scenarios, use the scoreAttempt method:

  • scoreAttempt

    Given an Item State, executes response processing with the item's XML, and produces the state of all item variables upon completion of response processing. No response validation is performed. Typical use is when submissionMode: "simultaneous", or when you want to generate a raw score from the responses and the response processing without invoking the endAttempt method (which has some side-effects - such as incrementing the numAttempts variable - that may be undesirable when simply trying to get a machine score from the given Item State).

    QTI 3 Player supports the full QTI 3 response processing expression vocabulary.

The scoreAttempt method may take a considerable amount of time to complete. QTI 3 Player triggers the notifyQti3ScoreAttemptCompleted event upon completion of a scoreAttempt method invocation.

<Qti3Player
  ref="qti3player"
  @notifyQti3ScoreAttemptCompleted="handleScoreAttemptCompleted"
/>

8a) Calling scoreAttempt and handling the notifyQti3ScoreAttemptCompleted event

// Call the scoreAttempt method, passing a string/target action that will be
// echoed back in the notifyQti3ScoreAttemptCompleted event payload.
this.qti3Player.scoreAttempt('itemScoreReady')
/**
 * @description Example event handler for the QTI3Player component's 'notifyQti3ScoreAttemptCompleted'
 * event.  This event is fired upon completion of the scoreAttempt method.
 * @param {Object} data - the item's state, including outcomes from response processing
 */
handleScoreAttemptCompleted (data) {
  // 'data' contains the item state in a 'state' property, including response variable values, 
  // outcome variable values, template variable values, and context variable values.
  // 'data' also has a 'target' property that echos the value (if any) of the target string
  // parameter passed into the originaging scoreAttempt call.
  // ... do something ...
  console.log('SCORE ATTEMPT OUTCOMES', data.state)
  const itemState = data.state
  const target = data.target
  // Echo all Outcome variables in the Item State
  itemState.outcomeVariables.forEach((outcomeVariable) => {
    console.log(`[Outcome][${outcomeVariable.identifier}][Value=${outcomeVariable.value}]`)
  })
}

(back to top)

9. Item Session 'Alert' Messages and the notifyQti3ItemAlertEvent

An item session 'alert' message is triggered by QTI 3 Player when a person exceeds an interaction's max-choices or max-associations threshold. QTI 3 Player uses a built-in messaging/toast component to display such alerts to the candidate.

An encapsulating application may instrument the QTI 3 Player to not display alert messages by specifying the boolean attribute suppress-alert-messages. Example:

<Qti3Player
  ref="qti3player"
  suppress-alert-messages
  @notifyQti3ItemAlertEvent="displayItemAlertEvent"
/>

An encapsulating application should implement a handler for the notifyQti3ItemAlertEvent when instrumenting QTI 3 Player to suppress its internal alert message display. Example:

/**
 * @description Handler for QTI item alert messages such as max selections messages.
 * @param {Object} event - object containing an icon property and a message property
 */
displayItemAlertEvent (event) {
  // This example uses the sweetalert component to display messages as toasts
  Swal.fire({
    toast: true,
    position: 'top-end',
    icon: event.icon,
    html: event.message,
    showConfirmButton: false,
    showCloseButton: true,
    timer: 3000,
    timerProgressBar: true
  })
}

(back to top)

10. Item Session 'Invalid Response' Messages

An item session 'invalid response' message is triggered by QTI 3 Player when,

  • SessionControl.validateResponses=true, and
  • A response validity requirement is not met on an interaction in the loaded item

As with item session 'alert' messages, QTI 3 Player uses a built-in messaging/toast component to display such 'invalid response' messages to the candidate.

An encapsulating application may instrument the QTI 3 Player to not display invalid response messages by specifying the boolean attribute suppress-invalid-response-messages. Example:

<Qti3Player
  ref="qti3player"
  suppress-invalid-response-messages
/>

All violations of response validity are reported in the validationMessages property of the state object returned to the notifyQti3EndAttemptCompleted and notifyQti3SuspendAttemptCompleted event handlers.

"state": {
  "identifier": "<qti-assessment-item identifier>",
  "guid": "<tracking guid passed in the configuration>",
  "contextVariables": [ <built-in and declared context variables> ],
  "responseVariables": [ <built-in and declared response variables> ],
  "outcomeVariables": [ <built-in and declared outcome variables> ],
  "templateVariables": [ <declared template variables> ],
  "validationMessages": [
    {
      "identifier": "RESPONSE3",
      "message": "Not enough selected! Please select at least two."
    }
  ]
}

This permits an encapsulating application to handle and display validation messages using its own UX.

(back to top)

11. Item 'Catalog' Events

An item 'catalog' event is triggered by QTI 3 Player when a user selects a control (such as a highlighted term) within the item's presentation that is bound to an item's catalog. As of QTI 3 Player version 0.3.1, the only supported catalog event () is a 'glossary' event. QTI 3 Player will display its own Catalog Glossary Dialog component when a user selects a control within the item's presentation that is bound to a 'glossary' event.

Example of QTI 3 Player Glossary Dialog

An encapsulating application may instrument the QTI 3 Player to not display its internal Catalog Dialog component by specifying the boolean attribute suppress-catalog-messages. When instrumenting QTI 3 Player to suppress its internal catalog message display, an application should implement a handler for the notifyQti3ItemCatalogEvent. This permits an application to handle and display catalog event messages using its own UX. Example:

<Qti3Player
  ref="qti3player"
  suppress-catalog-messages
  @notifyQti3ItemCatalogEvent="handleItemCatalogEvent"
/>
    /**
     * @description Handler for QTI item catalog events such as 'glossary' events.
     * @param {Object} event - object containing a catalog event payload
     * Sample event schema:
     * {
     *   type: "glossary",
     *   term: "acronym",
     *   catalogIdRef: "glosscat",
     *   data: [
     *     {
     *       support: "glossary-on-screen",
     *       card: {
     *         content: ""<p>An abbreviation.</p>"",
     *         properties: {
     *           name: "qti-html-content"
     *         }
     *       }
     *     }
     *     ... additional Card supports in Catalog based on PNP ...
     *   ]
     * }
     */
    handleItemCatalogEvent (event) {
      console.log('[ItemCatalogEvent][Type: ' + event.type + ']', event)
      switch (event.type) {
        case 'glossary':
          // Do something!
          break
        default:
      }
    },

Supported Keyword Translation Language Codes

QTI 3 Player groups PNP 'glossary-on-screen', 'keyword-translation', and 'ext:sbac-glossary-illustration' supports into 'glossary' events that will trigger a Catalog event of type 'glossary'.

As of the 0.3.4 release, QTI 3 Player supports the following IS0 639 language codes for keyword translations:

{ ar | cmn | de | en | es | fr | hmn | it | ja | ko | my | nl | pa | ru | so | tl | uk | vi | yue | zh }

(back to top)

12. About Dynamic Catalog Rebinding

Under most use-cases, a PNP is passed into QTI 3 Player as part of the configuration (see 4b Constructing a Configuration) as an item's XML is loaded. However, after an item is loaded, an encapsulating application may update PNP settings and then force a catalog rebinding with the updated PNP settings. QTI 3 Player implements a bindCatalog API method for this use-case.

// 1) Use the PnpFactory helper class to build an updated PNP.
let pnpFactory = new PnpFactory()
// Example: turn off glossary
pnpFactory.setGlossaryOnScreen(false)
// Example: turn on Spanish keyword translations
pnpFactory.setKeywordTranslationLanguage('es')
// Example: turn on ext:sbac-glossary-illustration
pnpFactory.setExtSbacGlossaryIllustration(true)

// 2) Set QTI 3 Player's current PNP to our new PNP constructed in 1) above.
this.qti3Player.setItemContextPnp(pnpFactory.getPnp())

// 3) Even with a new Item Context PNP (step 2) above, QTI 3 Player will not
// automatically rebind the PNP + Catalog.  
// Force QTI3 Player to bind (rebind) the Catalog.
this.qti3Player.bindCatalog()

(back to top)

QTI 3 Player Presentation Attributes

QTI 3 Player has several attributes to instrument presentation within an encapsulating application/web page. These attributes are container-class, container-padding-class, and color-class

container-class

Container classes are used to contain and pad content within them. QTI 3 Player comes with built-in support for two container classes: qti3-player-container-fluid and qti3-player-container.

  • qti3-player-container-fluid DEFAULT

    This container is a width=100%, padding=0 container at all widths.

  • qti3-player-container

    This container has responsive breakpoints at screen widths of 1200px, 980px, and 768px.

Experiment with the Container Class Note: Click the "Settings" menu in the top-right corner of the TestRunner application.

container-padding-class

Container padding classes are for setting the padding between the QTI 3 Player container and the qti-assessment-item rendered content. QTI 3 Player comes with built-in support for six container padding classes.

  • qti3-player-container-padding-0 { padding: 0; } DEFAULT
  • qti3-player-container-padding-1 { padding: 0.25rem; }
  • qti3-player-container-padding-2 { padding: 0.5rem; }
  • qti3-player-container-padding-3 { padding: 1rem; }
  • qti3-player-container-padding-4 { padding: 1.5rem; }
  • qti3-player-container-padding-5 { padding: 3rem; }

Experiment with the Container Padding Class Note: Click the "Settings" menu in the top-right corner of the TestRunner application.

color-class

QTI 3 Player has built-in support for 14 foreground / background color combinations (a.k.a. color "themes") in accordance with best practices for many forms of color blindness or other visual impairments. In addition to setting a colorClass in a PNP, color settings may also be applied dynamically.

  • qti3-player-color-default DEFAULT
  • qti3-player-color-defaultreverse (Default - Reverse Polarity)
  • qti3-player-color-blackwhite (High Contrast - foreground color: black, background color: white)
  • qti3-player-color-whiteblack (High Contrast - foreground color: white, background color: black)
  • qti3-player-color-blackrose (foreground color: black, background color: rose)
  • qti3-player-color-roseblack (foreground color: rose, background color: black)
  • qti3-player-color-dgraymgray (foreground color: dark gray, background color: medium gray)
  • qti3-player-color-mgraydgray (foreground color: medium gray, background color: dark gray)
  • qti3-player-color-yellowblue (foreground color: yellow, background color: blue)
  • qti3-player-color-blueyellow (foreground color: blue, background color: yellow)
  • qti3-player-color-blackcyan (foreground color: black, background color: lblue)
  • qti3-player-color-cyanblack (foreground color: lblue, background color: black)
  • qti3-player-color-blackcream (foreground color: black, background color: lemonchiffon)
  • qti3-player-color-creamblack (foreground color: lemonchiffon, background color: black)

Experiment with the Color Class Note: Click the "Settings" menu in the top-right corner of the TestRunner application.

(back to top)

Roadmap

The QTI3 Item Player 2022-2023 development roadmap includes all features and capabilities included in QTI 3 Delivery System "Basic" and "Advanced" conformance + PCI support.

  • Support for the 14 Standard Color Combinations/Themes
  • Support for Template Processing and all Template Rules
  • Support for Template Math Variables
  • Support for Response Processing and all Response Processing Rules
  • Support for Smarter Balanced-style Choice Interaction
  • Support for Smarter Balanced-style Audio player
  • Support for Adaptive Items and QtiEndAttemptInteraction
  • Catalog Support for Glossary and Keyword Translation
  • Catalog Support for Smarter Balanced Illustrated Glossary
  • Rubric Block Support
  • QtiStylesheet Support
  • Shared Stimulus Support
  • QtiMatch Interaction Support
  • QtiGapMatch Interaction Support
  • QtiGraphicGapMatch Interaction Support
  • QtiHottext Interaction Support
  • QtiHotspot Interaction Support
  • QtiOrder Interaction Support
  • QtiPortableCustom Interaction Support
  • Scoring API Examples
  • Support for Interaction "Review" Status
  • Improved Audio Player
  • Improved Video Player

(back to top)

License

Distributed under the MIT License. See LICENSE for more information.

(back to top)

Built With

The QTI3 Item Player is built with the Vue.js (v2.6) framework.

(back to top)

Contact

Paul Grudnitski - [email protected]

Project Link: https://github.com/amp-up-io/qti3-item-player

(back to top)

Acknowledgments

This component would not be possible were it not for a fortuitous decision by the aQTI Task Force (the original name of the QTI 3 Working Group) - meeting at CITO headquarters in Arnhem, NE, January 2015 - to make the aQTI / QTI 3 specification "web component friendly".

(back to top)

qti3-item-player's People

Contributors

paulgrudnitski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

qti3-item-player's Issues

npm warnings and errors

I tried to install qti3-item-player on my Windows 10 PC,
which has npm 8.19.2.

First, "npm audit" returns some error message.

N:\QTI\qti3-item-player-main\qti3-item-player-main>npm audit
# npm audit report

quill  <=1.3.7
Severity: moderate
Cross-site Scripting in quill - https://github.com/advisories/GHSA-4943-9vgg-gr5r
No fix available
node_modules/quill

sweetalert2  >=11.4.9
sweetalert2 v11.4.9 and above contains hidden functionality - https://github.com/advisories/GHSA-qq6h-5g6j-q3cm
fix available via `npm audit fix`
node_modules/sweetalert2

2 vulnerabilities (1 low, 1 moderate)

Second, "npm install" returns this error message.

N:\QTI\qti3-item-player-main\qti3-item-player-main>npm install
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: @vue/[email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/eslint
npm ERR!   dev eslint@"^6.7.2" from the root project
npm ERR!   peer eslint@">= 4.12.1" from [email protected]
npm ERR!   node_modules/babel-eslint
npm ERR!     dev babel-eslint@"^10.1.0" from the root project
npm ERR!   2 more (eslint-plugin-vue, vue-eslint-parser)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer eslint@">=7.5.0" from @vue/[email protected]
npm ERR! node_modules/@vue/cli-plugin-eslint
npm ERR!   dev @vue/cli-plugin-eslint@"^5.0.8" from the root project
npm ERR!
npm ERR! Conflicting peer dependency: [email protected]
npm ERR! node_modules/eslint
npm ERR!   peer eslint@">=7.5.0" from @vue/[email protected]
npm ERR!   node_modules/@vue/cli-plugin-eslint
npm ERR!     dev @vue/cli-plugin-eslint@"^5.0.8" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

Third, "npm run serve" reports errors.

> [email protected] serve
> vue-cli-service serve

 ERROR  ValidationError: Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
         - options[0] misses the property 'patterns'. Should be:
           [non-empty string | object { from, to?, context?, globOptions?, filter?, transformAll?, toType?, force?, priority?, info?, transform?, transformPath?, noErrorOnMissing? }, ...] (should not have fewer than 1 item)
ValidationError: Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.
 - options[0] misses the property 'patterns'. Should be:
   [non-empty string | object { from, to?, context?, globOptions?, filter?, transformAll?, toType?, force?, priority?, info?, transform?, transformPath?, noErrorOnMissing? }, ...] (should not have fewer than 1 item)
    at validate (N:\QTI\qti3-item-player-main\qti3-item-player-main\node_modules\copy-webpack-plugin\node_modules\schema-utils\dist\validate.js:105:11)
    at new CopyPlugin (N:\QTI\qti3-item-player-main\qti3-item-player-main\node_modules\copy-webpack-plugin\dist\index.js:34:31)
    at Object.<anonymous> (N:\QTI\qti3-item-player-main\qti3-item-player-main\vue.config.js:8:7)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Module.require (node:internal/modules/cjs/loader:1061:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at exports.loadModule (N:\QTI\qti3-item-player-main\qti3-item-player-main\node_modules\@vue\cli-shared-utils\lib\module.js:86:14)

Is this a Vue component or web component?

I somewhere read that the QT3 Item Player is a web component library. But I could not find any examples on how to use as a web component library. I am struggling a bit trying to integrate this to our react app.

Can you integrate this into a React JS app or Angular app? Any sample code? I run into error:
Unknown custom element: <catalog-dialog> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

Multiple "Qti3Player" instances with multiple PCI message and resize listeners which are not removed when beforeDestroy() lifecycle called

Not sure if i should post this in qti3-item-player-controller repo, sorry for that.

I am using QTI 3 player controller, normally when using it everything is fine, now I need a print function, i've created new view "PrintRunner" which basically calls multiple Qti3Player instances (each per item count) and renders them, then I can print the results using CTRL+P.

Problem is, the "store" has methods "initializePciMessageListener" and "removePciMessageListener" functions, as the store is global, the variables "pciMessageHandler" and "windowResizeHandler" (which are callbacks for the PCI api) are overriden each time the player is loaded. Now I am having a problem when I go to the "PrintRunner" and it has alot of PCI components, the window listeners "message" and "resize" are being added, but when I go back to my "TestRunner" it only removes the last listener of variables "pciMessageHandler" and "windowResizeHandler" in the removePciMessageListener function and now my PCI in "TestRunner" keep duplicating.

Sorry if it's hard to understand, please let me know if so, i'll try to explain better!

Also if you think I'm doing the "PrintRunner" wrong (by using multiple Qti3Player components to render the xml's) please let me know.

Thanks!

Also how I solved that: (had to interfere with source code btw)

store.js:

  resizeListeners: [],
  messageListeners: [],


  initializePciMessageListener () {
    // Keep a handle on the Window Resize Handler and
    // the PCI PostMessage Handler
    this.pciMessageHandler = this.PciMessageListener.bind(this)
    this.windowResizeHandler = this.WindowResize.bind(this)

    window.addEventListener('message', this.pciMessageHandler)
    window.addEventListener('resize', this.windowResizeHandler)

    this.resizeListeners.push( this.windowResizeHandler );
    this.messageListeners.push( this.pciMessageHandler );
  },

  removePciMessageListener() {
    this.resizeListeners.forEach((listener, index) => {
        window.removeEventListener('resize', listener)
        this.resizeListeners.splice(index, 1);
    });
    this.messageListeners.forEach((listener, index) => {
        window.removeEventListener('message', listener)
        this.messageListeners.splice(index, 1);
    });
  },

EDIT: I'm using vue-router to go from "TestRunner" and "PrintRunner" back and forth, no page reloading

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.