Skip to content

Creating Widgets

nbriz edited this page Aug 17, 2020 · 16 revisions

Widgets are multi-purpose independent windows. They can be used during tutorials to open up other media types (images, videos, gifs, audio, texts, 3D objects, etc). Widgets can also be there own miscellaneous utilities. For example we could create a widget that explains some concept using interactive graphics. Widgets can also be GUIs that interact with the netitor, for example a CSS generator that outputs to the line where the user's cursor is currently positioned. The sky's the limit!

netnet widgets

Basic Widget

The Widget class can be used to instantiate new widgets. A widget is a window styled to match netnet's current theme. This includes shadows that respond to the mouse's position. If the window manager update's netnet's theme all widgets will automatically update their themes to match. (for more info on NNW.updateTheme() and other window manager methods refer to the nnw section in the Project Architecture wiki page)

To instantiate a new widget:

const w = new Widget({
  title: 'settings',
  innerHTML: element
})

Where the value of the innerHTML property can either be an string (including an html string like <h1>Hello World!</h1>) or an instance of HTMLElement (ie. a DOM element, const element = document.createElement('h1')). If we'd like to instantiate the widget at a particular location and/or at a particular size we can use these optional properties:

const w = new Widget({
  title: 'settings', // required
  innerHTML: element,  // optional
  x: 20,             // optional
  y: 20,             // optional
  z: 100,            // optional
  width: 500,        // optional
  height: 500        // optional
})

We can pass these properties a number or a CSS string, like x: '50vw' and width: '100%' and y: '100px'.

Widget properties

All the properties passed in the constructor's options argument can also be accessed/updated via the instance's properties, for example:

w.title = 'layout settings'
w.innerHTML = '<h1>these are the options</h1>'

w.x = innerWidth / 2
w.y = '50vh'
w.z = 101
w.width = '100%'
w.height = '1080px'

Widget Methods

It's important to note that instantiating the widget creates it in memory, but it does not visually present it to the user. In order to display the widget we need to use the instance's .open() method. There's also the .close() method for hiding the widget (while maintaining it in memory) as well as methods for resizing and positioning:

w.position(x, y, z)     // update position
w.resize(width, height) // update size
w.open()                // display
w.close()               // hide

That said, if you want the StateManager to keep track of the Widget instance you should call STORE.dispatch('LOAD_WIDGETS', { name: w }) assuming w is an instance of the Widget class and 'name' is a unique key to be stored in the global WIDGETS object. This has the added benefit of ensuring the widget shows up in the main menu's widgets sub-menu. For more info see the State Management Wiki

Extending a Widget's Functionality

The basic widget class is great for doing things like loading up images or videos, but for more interesting/complicated widgets we can create our own widget classes by extending the base widget class, for example:

class RandomColor extends Widget {
  constructor (opts) {
    super(opts)
    this.alpha = opts.alpha || false
    this.title = 'Random Color'
    this.innerHTML = `<button>insert color</button>`
    this.$('button').onclick = () => { this.click() }
  }

  click () {
    const r = Math.floor(Math.random() * 255)
    const g = Math.floor(Math.random() * 255)
    const b = Math.floor(Math.random() * 255)
    const a = (this.alpha) ? Math.round(Math.random() * 10) / 10 : 1
    const code = `rgba(${r}, ${g}, ${b}, ${a})`
    NNE.cm.replaceSelection(code)
  }

  exampleMethod () {
    /* another example */
  }
}
const rc = new RandomColor({ x: 100, y: 20, alpha: true })
rc.open()
rc.exampleMethod()

The window manager handles loading all of netnet's widget classes when the page loads. In order for the window manager to find the widgets they need be saved in the www/widgets directory. The directory also has an ExampleWidget.js file which can be copied and used as a template or starting point.

Clone this wiki locally