CDOT-EDX / Project

1 stars 3 forks source link

last updated on Jan 7/2016

new option on slideContent - "playAudio" works only for CSVs and doesn't build content if option is specified (uses altMediaFiles)

new option on slideContent - "hideNext"

new option on slideContent - "noAdvanceByMedia"

new option on slideContent - "clearEvents" is available, this clears all events on that media or actionable

experimental conditional version, needs test ing

new option on slideContent - "slideEnd": true is available to trigger slideEnd event for sure

new option "studentGraph": true is available to show students KC scores at the end of a Snap

new option "instructorGraph": true is available to show students KC scores at the end of a Snap

new option "evaluate": true is available on advanceWith to let the frontend know that this advanceWith is marked

Can enable the panel Overlay with panelOverlay: true

When you need the off Flag you can call it with offFlag: true

Aviation Project

This branch is for combining front-end libraries and features used in the edX/Aviation project at CDOT

References to works used in this project and

JavaScript and jQuery libraries required by this library:

SlickQuiz: https://github.com/pkuzhel/SlickQuiz
    Original library: https://github.com/jewlofthelotus/SlickQuiz
TimerJS: https://github.com/pkuzhel/timer.js
    Original library: https://github.com/husa/timer.js
PopcornJS: http://cdn.popcornjs.org/code/dist/popcorn.min.js || https://github.com/mozilla/popcorn-js
jQuery Flight Indicators: https://github.com/uw-ray/Skyhawk-Flight-Instruments
    Continued from: https://github.com/echanna/jQuery-Flight-Indicators/tree/cdot_with_turn_coordinator
        Original: https://github.com/sebmatton/jQuery-Flight-Indicators
JS CSV Parser (PapaParse): http://papaparse.com/
Resize Detection (CSS Element Queries): https://github.com/marcj/css-element-queries
jQuery Pulse Animation Plugin: https://github.com/jsoverson/jquery.pulse.js

Slide Creation Library for the internal use of the edX team at CDOT

In order to have this version of the createSlide library working you will need the following files: (these files should be already organized inside Project/aviation/)

CDOT-EDX/Project/library/static/js/content/createSlide.js
CDOT-EDX/Project/library/statis/js/*
CDOT-EDX/Project/library/statis/css/*

createSlide now supports one options object being passed versus multiples...

therefore use: var anySlide = new AVIATION.Slide( options ) (if ComplexHTML xblock isn't being used)

NOTE: The example below doesn't use a properly formatted JSON, make sure to use proper JSON

This can be validated easily using a tool such as: http://jsonlint.com/

Acceptable options and defaults are as follows:

    patternQuiz:        false, // are there quizzes that need to be answered during a pattern scan?
    patternQuizzes:     0,  // number of quizzes that need to be answered throughout the pattern scan
    serverBaseUrl:      window.location.protocol + "//" + window.location.host + "/",
    apacheServerBaseUrl:window.location.protocol + "//" + window.location.host + ":25080/",
    setPanel:           false, // makes the first line of the first CSV set panel before CSV plays
    parentSlide:        {},
    development         false, // if running inside a devstack set to true
    showAvatars:        false,
    showSlideControls:  true,
    showStatus:         true,
    showRemediationOnSuccess: true, //show all remediations on Correct answer
    showRemediationOnFail: true, //show all remediations on inCorrect answer
    showRemediationOne: true, //will show remediation for selected answer (showRemediationOnSuccess or showRemediationOnFail must be set to true) !!can only be used only with showRemediationOnSuccess or showRemediationOnFail
    showControls:       true,
    showBorder:         true, // this applies to the border around the content
    autoplay:           true, // proceeds to the next AUDIO automatically after current is finished
    autoRedirect:       false, // proceeds to the next SLIDE automatically after current is finished
    noAudio:            false, // in case the slide doesn't have any audio content to control the content creation
    noCSV:              false, // indicates that the instrument panel should build even if a csv file isn't specified in media object
    enableModals:       false,
    enableHighlights:   false,
    hiddenHighlights:   false,
    enableButtons:      true,
    enableSlider:       false,
    enablePanel:        false, // enable full panel unless "panelType" option is set
    panelType:          { "attitude": "attitude" }, // object that lists 1 or more instruments to display (if not set, full panel)
    panelOverlay:       false,
    offFlag:            false,
    readOnlySlider:     true,
    container:          "#slideContainer", // where should we look for the slideContainer?
    statusId:           "#statusBar", // whats the id that we should create for statusBar?
    headerId:           "#header",
    footerId:           "#footer",
    bodyId:             "#body",
    headerId:           "#slideHeader",
    footerId:           "#slideFooter",
    quizId:             "#slideQuiz",   // id of div that contains all quizzes
    quizContainerClass: "cdot_quiz_container", // class thats appended to each individual quiz

    // new optinal+experimental additions below
    panelId: "#flightInstruments",
    panelHighlightsId: "#panelHighlightContainer",
    instStatusId1: "#instStatus1",
    instStatusId2: "#instStatus2",
    scanningPatternArray: [ 1, 0, 1, 2, 1, 5, 1, 4, 1, 3 ],
    minScan: 1,
    pulseCorrectProp: {
      borderWidth: '5px',
      borderColor: 'green',
      borderRadius: '5px'
    },
    pulseWrongProp: {
      borderWidth: '5px',
      borderColor: 'red',
      borderRadius: '5px'
    },
    pulseInstrumentSettings: {
      duration: 500,
      pulses: 1
    },
    pulseProperties: {
      backgroundColor: "#D0FAEE",
      borderRadius: "10px"
    },
    pulseSettings: {
      duration: 3000,
      pulses: 1
    },

    // both options below are used to pull audio/images/csvs from the correct server without running into cross-origin restrictions
    serverBaseUrl: window.location.protocol + "//" + window.location.host + "/", //can be overwritten by a string of the host url
    apacheServerBaseUrl: window.location.protocol + "//" + window.location.host + ":25080/",

    **possibly deprecated and moved inside slideContent:
    **  advanceWith:        "audio", // other options -> "highlight", "timer", "button", "instruments"

    continueId:         "", // string specifying the next id to redirect to
    backId:             "", // string specifying the previous id to redirect to

    panelOptions: { // options passed on to flightInstruments library
        size : 200,             // Sets the size in pixels of the indicator (square)
        showBox : true,         // Sets the visibility of the box behind the instruments
        showScrews: true,       // Sets the visibility of the four screws around the instruments
        airspeed: 0,            // Air speed in knots for an air speed indicator
        roll : 0,               // Roll angle in degrees for an attitude indicator
        pitch : 0,              // Pitch angle in degrees for an attitude indicator
        off_flag: false         // Off flag for an attitude indicator
        altitude: 0,            // Altitude in feets for an altimeter indicator
        pressure: 30,           // Pressure in inHg for an altimeter indicator
        turn: 0,                // Turn direction for turn coordinator
        slip: 0,                // Slip ball position for turn coordinator (0 to 1; 0.5 is middle)
        heading: 0,             // Heading angle in degrees for an heading indicator
        beaconone: 0,           // Angle of first beacon on the heading indicator
        beacononeshow: true,    // Sets the visibility of the first beacon on the heading indicator
        beacontwo: 0,           // Angle of second beacon on heading indicator
        beacontwoshow: true,    // Sets the visibility of the second beacon on the heading indicator
        vario: 0,               // Variometer in 1000 feets/min for the variometer indicator
        img_directory : 'img/'  // The directory where the images are saved to
    },

    quizzes: [ // options passed on to the slickQuiz library
    // most explanations to these can be found at: https://github.com/jewlofthelotus/SlickQuiz
      {
        json: {
          "info": {
            "name":    "Answer the following questions to the best of your ability.",
            "main":    "",
            "results": "",
            "level1":  "",
            "level2":  "",
            "level3":  "",
            "level4":  "",
            "level5":  "" // no comma here
          },
          "questions": [
            { // Question 1 - Multiple Choice, Single True Answer
              "q": "Now speak the correct clearance: >>AS12, I read back",
              "a": [
                {"option": "Climb on runway heading to 3000 ft, turning right onto 125 degrees", "correct": "", "reason": ""},
                {"option": "Climb on 135 degrees to 1500 ft, then climb to 3000 ft", "correct": "",  "reason": ""},
                {"option": "Climb on runway heading to 1500 ft, turning right onto 125 degrees", "correct": "",  "reason": ""},
                {"option": "Climb on runway heading to 1500 ft, turning right onto 135 degrees. Continue climb to 3000 feet to complete the correct read back.",  "correct": "",  "reason": ""} // no comma here
              ],
              "correct": "<p><span>Control, correct, AS12 is clear to take-off</span></p>",
              "incorrect": "<p><span>That's not correct.  Ask for the clearance to be repeated.</span></p>",
              "incorrectMaxAttempts": "<p>Incorrect, but you've had enough. Next...</p>"
            }
          ],
        },
        // not mentioned on SlickQuiz page but added by edX CDOT team
        "showRemediationOnSuccess": true,
        "showRemediationOnFail": true,
        "attemptsBeforeRemediation": 1 // how many attempts does the user have until remediations show and
        // the quiz is skipped and user goes on to the next content ** Gordon's request
        "animationCallbacks": {
          "checkAnswer": (function(){
            console.log("do something");
            $(anySlide).trigger("completedQuiz");
          })
        }
      }
    ],
    avatars:
    {
      tom: {
        ~~open: "//online.cdot.senecacollege.ca:25080/aviation/img/tomOpen.png",~~
        ~~close: "//online.cdot.senecacollege.ca:25080/aviation/img/tomClose.png"~~
        // since server url options have been added, we can give relative locations to resources
        open: "aviation/img/tomOpen.png",
        close: "aviation/img/tomClose.png"
      },
      jane: {
        open: "aviation/img/janeOpen.png",
        close: "aviation/img/janeClose.png"
      }
    },

    highlights:
    [
      {
        id: "asi",
        orderNumber: 0,
        name: "Airspeed Indicator (ASI)",
        height: "50%",
        classes: ["col-xs-4"],
        border : "7px ridge yellow",
        parent: 'panel',
        "hasModal": false // the default when no modals with the same id present
        // but can be used to prevent content from advancing
        // if a modal with same id is found, defaults to True
        // use modal.advanceOnClose instead to advance slideContent
      },
      {
        id: "ai",
        orderNumber: 1,
        name: "Attitude Indicator (AI)",
        height: "50%",
        classes: ["col-xs-4"],
        border : "7px ridge yellow",
        parent: 'panel'
      },
      {
        id: "alt",
        orderNumber: 2,
        name: "Altimeter (ALT)",
        height: "50%",
        classes: ["col-xs-4"],
        border : "7px ridge yellow",
        parent: 'panel'
      },
      {
        id: "tc",
        orderNumber: 3,
        name: "Turn Coordinator (TC)",
        height: "50%",
        classes: ["col-xs-4"],
        border : "7px ridge yellow",
        parent: 'panel'
      },
      {
        id: "hi",
        orderNumber: 4,
        name: "Heading Indicator (HI)",
        height: "50%",
        classes: ["col-xs-4"],
        border : "7px ridge yellow",
        parent: 'panel'
      },
      {
        id: "vsi",
        orderNumber: 5,
        name: "Vertical Speed Indicator (VSI)",
        height: "50%",
        classes: ["col-xs-4"],
        border : "7px ridge yellow",
        parent: 'panel'
      },
    ],
    },
    // This is for buttons that we want to use on the slide
    buttons: [
        {
          "id": "btn0",
          "title": 'I am a button',
          "classes": ["btn", "btn-default"],
          "orderNumber": 0,
          "action": "(function(){ console.log('button of someId is executing'); })"
        },
        {
          "id": "btn1",
          title: 'another button',
          "orderNumber": 1
        },
        {
          "id": "topple",
          "title": "TOPPLE",
          "mediaIndex": 3 // mediaIndex will invoke "play" on mediaFile at index 3 once button is clicked
        }
    ],
    slideContent: [{
        title: {html: "No content provided", classes: ["col-md-12"] },
        content: {html: "<p<Check your <b>slideContent</b> object</p>", classes: ["text-center"] },
        image: {src: "/someSource/image.png", classes: ["imageClass"] },
        highlights: [
                        0 ,
                        { index: 2, onclick: (function(){ console.log("highlight onclick");}) },
                        5
        ],
        // this is to hide / show buttons just like we do with highlights
        buttons: [
                    0 ,
                    { "index": 2, "disable": true, "onclick": "(function(){ console.log('button onclick');})" },
                    3
        ],
        // set slider to any throttle possition from 0-4
        slider: 2,
        "media":{
            "type": "audio", // could be csv/button/highlight/quiz
            "index": 0,
            "second" 10
        },
        callback: (function(){ console.log("this is a callback function"); }),
        "advanceWith": {
            "action": "pattern",
            "evaluate": true,
            // for both properties below, anything to do with the contentIndex will only rebuild the content for that
            // index and not replay the media associated with the content
            // BUT, anything to do with mediaIndex, will restart the media and run all of the content associated with that media again
            // "<-"/previous btn and "->"/forward btn on the slides skip mediaIndices NOT contentIndices
            "onSuccess": { ** optional if needed and currently under development
                "status": "Good job, let's move on...",
                // if onSuccess content is not the next slideContent....
                "contentIndex": 3 // optional, which index should we jump to in slideContent OR use mediaIndex instead
                "mediaIndex": 2 // mediaIndex will jump to the beginning of a media at set index and run all the content from that
                "callback": "(function(){ console.log('You did smth right'); })" // optional
            },
            "onFail": { ** optional if needed and currently under development
                "reviewId": "", //
                "showChoices": true, //
                "maxFails": 1, //
                "index": 2, // which altMediaFile should be played (currently sound only),

                "status": "That's not correct. Let's try this again", // what msg should we display in the status bar?
                "resetContentIndex": 0 // which slideContent index do we need show as altMedia starts to play?
                "resetMediaIndex": 0 // which media index do we need to play after altMedia?
            },
            "noAdvanceByMedia": false // set to true when next audio/csv shouldn't play automatically
            "content": true // if there is content to that should be triggered during the scanning pattern
        }
    },
    {
        "media":{
            "type": "timer",
            "index": 1,
            "second" 1 // timer is a count down , starts at 10 and ends at 1
        },
        "buttons": [0],
        "content": {
       "html": "UH OH, Press that button yo!"
        },
        "advanceWith": {"type": "button", "index": 0}
    },
    {
        //... another slide content can go here to be triggered at a different time of the audio
        title: {html: "This is a different title / slide"},
        slider: 3,
        "media": {
            "type": "csv",
            "line": 100,
            "index": 2
        },
        "playAudio": {
          "index": 0, // altMediaIndex
          "resetMediaIndex": 3, // optional
          "resetContentIndex": 6 // optional
        },
        // only has been tested for CSVs
        "clearEvents": {
          "type": "media", // or actionable
          "index": 3
        },
        "advanceWith": {
            "type": "button", // highlight, audio, csv
            "index": 0,
            "onFail": {
                "index": 0,
                "resetIndex": 1
            }
        }
    },
    // PAUSE / PLAY example for CSV
    {
        "media":{
            "index": 2,
            "type": "csv",
            "line": 1000,
        },
        "action": {
          "type": "pause",
          "index": 2
        },
        "advanceWith": {
            "type": "button",
            "index": 1
        },
    },
    {
        "media": {
          "type": "button",
          "index": 1
        },
        "action":{
          "type": "play",
          "index": 2 // can only be a mediaIndex (not contentIndex)
          "line": 1001 // in this case its a csv
          // OR
          "line": "paused" // to resume from a previously paused animation by user
          // in the case of an audio we can specify "second": 10.1 and not 'line'
        }
    },
    // PAUSE / PLAY example for AUDIO
    {
        "media":{
            "index": 2,
            "type": "audio",
            "second": 7,
        },
        "action": {
          "type": "pause",
          "index": 2
        },
        "advanceWith": {
            "type": "button",
            "index": 1
        },
    },
    {
        "slideEnd": true,
        "media": {
          "type": "button",
          "index": 1
        },
        "action":{            "advanceWith": {
                "type": "highlight",
                "index": [0, 1]
            }
can only be a mediaIndex (not contentIndex)
          "second": 7.1 // in this case its an audio
        }
    }],
    // default models that we want to be set-up in the background
    modals: [{
              "id": "ai",
              "title": "Attitude Indicator",
              "content": {"html": "This is the MODAL custom HTML" },
              "buttons": [],
              "highlights": [],
              "largeModal": false, // defaults to false
            },
            {
              "id": "alt",
              "title": "Altimeter",
              "advanceOnClose": true
            }
    ],
    // these audioFiles are for the slide only
    mediaFiles: [
        // since server url options have been added, we can give relative locations to resources omitting the https://online...../
        {type: "audio", src: "someRelativeURL/toAudioFile"},
        {type: "audio", src: "anotherURL/toOtherFile"},
        {type: "csv", src: "someURL/flightData"},
        {type: "timer", "duration": 10}
    ],
    altMediaFiles: [ // media files that will be used in alternative content (in case a student answered a question wrong)
        {type: "audio", src: "someURL/toAudioFile"},
        {type: "audio", src: "anotherURL/toOtherFile", "silent": true}, // silent makes sure that altMedia doesn't fire an "end" event
    ]

The rest of this README is being edited at this moment More options and capabilities are being added all the time Everything below is just notes of the developer for the developer

Syntax and actions available for content

content - can include any custom html if needed
    html (string/html)
    classes (string array)
    action (string) - available actions: remove, replace, append **replace is default**

Global Events available for triggering

play(playWhat, whichIndex)
    - with no parameters passed, will start playing slide audios (and stop all other audios)
    - with "modal" passed, will start playing the modal audio
    - with "extra" passed, will start playing the extra audio within slides

next

previous

pause

stop

replay

Slide class methods:

    new Slide(options, slideContent, audioFiles)
    create( options )
    destroy()
    constructor()
    _initSimple()
    buildHeader( parent, content, callback, clearTitle)
    buildSlide()
    buildAvatars(parent, avatar, callback)
    buildContent( correctAudio, index, outerIndex, clearContent )
    buildSlideControls()
    insertLineBreak(parent)
    buildSlideAudios(modalAudios, parent, modalIndex)
    buildStatusBar()
    buildFooter()
    buildCourseControls()
    buildHighlights(index, modalHighlight)
    buildModals()
    activateTimer()
    resetTimer()
    playCurrent()
    pauseCurrent()
    playPrevious()
    playNext()
    replayAll()
    replayCurrent()
    buttonOnClickEvents()
    initButtonEvents()
    initAudioEvents()
    checkSlideControlButtons()
    activateTimer( seconds, isAuto )
    initCourseButtonEvents()
    initAudioEvents()
    checkSlideControlPlayButtons( action );
    setStatus ( action ) - set status bar depending on action: play, pause, or display the actual "action"
    activateSlide()
    resetSlide()
    redirectToPage( pageId ) - use instead of "jump_to_id"

Slide class properties:

    type
        (string) - simple/highlights)
    options
        development (if running inside a devstack, set to true)
        autoplay (boolean)
        showAvatars (boolean)
        showSlideControls (boolean)
        showStatus (boolean)
        showControls (boolean)
        showBorder (boolean)
        continueId (string)
        backId (string)
        noAudio (boolean)
        enableHighlights (boolean)
        hiddenHighlights (boolean)
        enableModals (boolean)
    activeIndex
        (integer which keeps track of the active audio of the slide)
    slideContent (object array)
        avatar (object array)
            type (string) - available avatars: [open, close, ...]
            position - left / right / hide
            character - Tom / Jane
        title - can include any custom html if needed
            html (string/html)
            classes (string array)
            action (string) - available actions: remove
            ** if a title is sent in without an action, the default action will be **replace**
        content - can include any custom html if needed
            html (string/html)
            classes (string array)
            action (string) - available actions: remove, replace, append **replace is default**

        //classes (string)
        image
            classes (string array)
            src (string)
        second (integer)
        audio (integer starting at index 0)
        callback (custom function to call at end of audio or on specified second)
        highlights (integer array specifying the index/indices of highlight(s) to show,
                    OR object/integer array)
            index - highlight index that this applies to
            onclick - function to execute on "click" event
            *** or simply specify the index without any properties if there is no need for
            *** onclick event. if a modal is present the onclick is mapped automatically
        ...
    audioFiles
        (string array)
    slideAudios
        (Popcorn obj array / html audio element array)
    slideHasListened
        (bool array)
    modalData (Modal obj array)
        modalAudios (Popcorn obj array)
        modalHasListened (bool array)
    slideElements
        content
            title ("#slideTitle")
            innerContent ("#slideInner")
            ...
        slideControls
            previous
            play
            pause
            replay
            next
        courseControls
            back
            continue
        statusBar
        highlightElements (jquery object array)
    _timer // keeps track of the autoplay (no need to configure this variable)
    slideTimer // keeps track of available time for student to complete a task
    avatars (key : value pairs of string) // detailed description in defaults
        /************************************************
        modalHighlights (highlights objs 2D array)
            top
            left
            width
            height
            border
            audio
            second
            callback
            highlights (modal obj array)
            id
            name
            image
            modalAudio
            top
            left
            width
            height
            border
            audio
            second
            onclick
            //callback
        modalButtons
            callback (action)
            title
            relatedHighlight / or related instrument if we only working with instruments
            // back to instrument
        highlights
            id
            orderNumber
            //name
            top
            left
            width
            height
            border
        modals
            id
            name

        **********************************/
Default values:

      showAvatars: false
      showSlideControls: true
      showStatus: true
      showControls: true
      showBorder: true
      autoplay: true
      avatars: {
          tom: {
              open: "tomOpen.png",
              close: "tompClose.png"
          },
          jane: {
              open: "janeOpen.png",
              close: "janeClose.png"
          }
      }
      noAudio: false
      highlights: [

      ]