Skip to content

Creating Tutorials

nbriz edited this page Jan 10, 2021 · 17 revisions

NOTE: OUTDATED ---- NEEDS UPDATING ONCE THIS SECTION HAS BEEN REFACTORED

Within the context of netnet.stuio, a "tutorial" is a directory which consists of a metadata.json file, as well as a JavaScript file with the tutorial's content (the "steps" and any necessary widgets) as well as any other accompanying assets (images, videos, etc). netnet's TutorialManager.js (instantiated globally in main.js as NNT) is responsible for much of the internal tutorial logic. It can load tutorial data by passing a tutorial name (or URL) into it's .load() method, for example:

// loading an internal tutorial
NNT.load('example')

// loading an externally hosted tutorial
const url = 'https://raw.githubusercontent.com/netizenorg/netnet.studio/master/www/tutorials/example/'
NNT.load(url)

It can also launch a tutorial on page load by passing netnet a tutorial URL parameter, ex: http://netnet.studio/?tutorial=name-or-url.

metadata

In the root directory of a tutorial, we need to define all the meta data in a json file named metadata.json which should look like this:

{
  "main": "main.js",
  "title": "New Media Art",
  "subtitle": "understanding digital art as a metamedia",
  "author": {
    "name": "Nick Briz",
    "preferred": "Nick",
    "url": "http://nickbriz.com"
  },
  "description": "Lorem ipsum dolor sit amet",
  "keywords": ["art", "metamedia", "html"],
  "checkpoints": {
    "defining new media": "intro",
    "new media as a metamedium": "metamedia",
    "taxonomies && properties": "tax-and-props",
    "new media as a cultural movement": "movement",
    "new media as an ecology": "ecology"
  },
  "references": [
    {
      "note": "'Murray, Janet H.\"Inventing the Medium\" The New Media Reader. Ed. Noah Wardrip-Fruin & Nick Montfort. MIT Press, 2003.",
      "url": "http://www.newmediareader.com/book_samples/nmr-intro-murray-excerpt.pdf"
    },
    {
      "note": "Kay, Alan & Adele Goldberg. \"Personal Dynamic Computer\" Computer 10(3):31-41. March 1977",
      "url": "http://www.newmediareader.com/book_samples/nmr-26-kay.pdf"
    }
  ]
}

main should be a path to the js file containing our tutorial data.

keywords is an optional array of tags/keywords used by netnet's search bar

checkpoints is an optional object netnet uses to create the sections menu (think "table of contents" or "list of chapters"), the values for which should be id names from the associated steps (ie. where those "chapters" begin) or their index value (if the step doesn't have an id, for example in the case of linear tutorials).

references sources for any external references or sources for claims made throughout the tutorial.

main js file

The main js file should include a single global variable called TUTORIAL which should be an object with at least a steps array (collection of objects representing the data for each "step" in the tutorial). If the tutorial makes use of any custom widgets, those can be defined in the optional widgets property (itself an object).

window.TUTORIAL = {
  steps: [/* array of "step" objects */],
  widgets: {} // optional widgets created/used during tutorial
}

a "step" object

A "step", is the object representing the data for that part of the tutorial (stored in the steps array). It needs to have at the very least a content property containing the info we want showing up in netnet's speech bubble at that step:

{ content: 'content to display in text bubble' }

It can, however, contain much more data than that, here's a verbose example:

{
  id: 'defining new media', // id of step for non-linear tutorials
  content: 'content to display in text bubble',
  options: {/*  custom buttons to appear in text bubble */}
  code: '<h1>code to be injected into netitor at this step</h1>',
  edit: false, // should netitor be editable during this step
  highlight: { // highlight code in the editor for this step
    startLine: 10, // the line to start highlighting on
    startCol: 16, // the column on that line to start on
    endLine: 10, // the line to end highlighting on
    endCol: 22, // the column on that line to end on
    color: 'rgba(0, 255, 0, 0.5)' // highlight color
  },
  layout: 'dock-left', // change layout at this step
  opacity: 0.5, // change opacity at this step
}

The highlight property could also just be a number if/when we want to highlight the entire line with a default color, ex: highlight: 10

the "steps" array

Her's an example of a simple (but totally functional) main.js file

window.TUTORIAL = {
  steps: [
    { content: 'HTML isn\'t the only type of markup language.' },
    { content: 'Others include MathML and even SVG.' },
    { content: 'Artists like the Graffiti Research Lab have even made their own.' },
    { content: 'It\'s called GML or Graffiti Markup Language.'}
  ]
}

netnet dialogue

linear tutorials

The previous example and the following are examples of "linear tutorials". If none of the steps have an id property the TutorialManager will assume they should be displayed linearly. Additionally, if a step doesn't include an options property it takes the liberty of creating "next" and "previous" buttons to navigate each step, as well as an "ok" button at the last step to complete the tutorial. We can of course overide these default buttons at any step by creating our own options property. In a linear tutorial an example options object could look like:

//...
  options: {
    'go on to the next step': (e) => { e.next() },
    'wait, go back a step': (e) => { e.prev() }
  }
//...

the .next() and .prev() methods are simply shorter alias of the STORE.dispatch('TUTORIAL_NEXT_STEP') and STORE.dispatch('TUTORIAL_PREV_STEP') (we could also just as simply call these). Similarly there's a .end() alias for STORE.dispatch('TUTORIAL_FINISHED') and .hide() for STORE.dispatch('HIDE_TUTORIAL_TEXT')

Here's an example of a functioning linear steps array with custom options:

[
  {
    content: 'HTML isn\'t the only type of markup language.',
    options: {
      'oh no? what others are there?': (e) => e.next()
    }
  },
  {
    content: 'There\'s <a href="https://developer.mozilla.org/en-US/docs/Web/MathML" target="_blank">MathML</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/SVG" target="_blank">SVG</a>.',
    options: {
      'you don\'t say! Are there more?': (e) => e.next(),
      'wait a sec, go back.': (e) => e.prev()
    }
  },
  {
    content: 'Oh yes! Artists like the Graffiti Research Lab have even made their own.',
    options: {
      'really? What\'s it called?': (e) => e.next(),
      'wait a sec, go back.': (e) => e.prev()
    }
  },
  {
    content: 'It\'s called GML or <a href="https://en.wikipedia.org/wiki/Graffiti_Markup_Language" target="_blank">Graffiti Markup Language</a>.',
    options: {
      'wait a sec, go back.': (e) => e.prev(),
      'cool thnx for the info!': (e) => e.end()
    }
  }
]

netnet dialogue

using widgets

We can of course add other buttons to trigger other behavior, like opening up a custom widget, this can be done using .open('widget name') an alias for STORE.dispatch('OPEN_WIDGET', 'name'). There's also .close('widget name') an alias for STORE.dispatch('CLOSE_WIDGET', 'name')

Here's another simple (but totally functional) example:

window.TUTORIAL = {
  widgets: {
    'color wheel': new Widget({
      title: 'color wheel',
      innerHTML: `<img src="https://cdn.sparkfun.com/assets/learn_tutorials/7/1/0/TertiaryColorWheel_Chart.png" alt="color wheel" style="width: 400px">`
    })
  },
  steps: [
    {
      content: 'Take a look at this line of code, notice anything?',
      highlight: 10
    },
    {
      content: 'We\'ve changed the way we\'re defining colors.'
    },
    {
      content: 'There are even more ways to specify colors in CSS.',
      options: {
        'launch color widget': () => e.open('color wheel'),
        'cool, i\'m done': (e) => e.fin() // an alias for e.end() (^___^)
      }
    }
  ]
}

netnet dialogue

non-linear tutorials

What if we want to have a non-linear conversation with netnet? Where the user's choice determines which step they see next? In these instances we need to give our step objects an additional id property, which can be any string (but need to be unique to other id's in the array). We can then use the TutorialManager's internal .goTo('id') method (an alias for STORE.dispatch('TUTORIAL_GOTO', 'id')) in the option's callback functions by passing in the id of the step we want netnet to switch to when the user picks that option.

[
  {
    id: 'begin',
    content: 'Would you like to experiment a bit more?',
    options: {
      'yes please': (e) => e.goTo('more-experimenting'),
      'naw, i\'m good': (e) => e.goTo('last')
    }
  },
  {
    id: 'more-experimenting',
    content: 'Ok great, dont\'t forget about the helpful widgets!',
    options: {
      'open color widget': (e) => e.open('color picker'),
      'ok, i\'m done': (e) => e.goTo('last')
    }
  },
  {
    id: 'last',
    content: 'Great! hope you had a good time!',
    options: {
      'i did, thnx': (e) => e.end()
    }
  },
]

netnet dialogue

onload method

TODO: add hyper video tutorial functionality

Clone this wiki locally