Skip to content

Latest commit

 

History

History
222 lines (185 loc) · 13.1 KB

week07.md

File metadata and controls

222 lines (185 loc) · 13.1 KB

Week 7

Topics

  • Event-driven UI elements
  • d3-brush
  • Customizing d3-brush

Events and Event Listeners

  • Introduction to Events -- MDN
  • Web Events -- MDN
    • JavaScript Events are "fired" to notify code of "interesting changes" that may affect code execution.
    • These may be associated with user interactions (using a mouse or resizing a window) or other things.
    • The MDN reference (above) has an extensive list of Events
    • Each event is represented by an object that implements the Event interface
    • DEMO -- Use <a> element's "click" listener to trigger an action
      • Event Listeners
      • In section "1. Hypertext Literal" change the href attribute from href="#" to href="#click"
        • This change makes it easier to see what happens when you click on a link
      • Every time you click a link in the list, you see the name change in the associated input element
      • No big surprise here.
  • You can trigger the "click" event programmatically
    • DEMO -- programmatic UI events
      • Again in section "1. Hypertext Literal", add a unique id to each <a> tag
html `<ul>${names.map((name, i) => html`
  <li>My name is ${name}! <a id=${"my" + i} href="#click" onclick=${() => click(name)}>Pick me.</a></li>
`)}</ul>`
  • Note that we create the unique id by adding the index i (second argument) of the anonymous function call
  • Then run the next line and watch the appropriate name appear in the input element
  • d3.select("#my0").node().dispatchEvent(new CustomEvent("click"))
  • This demo shows how to trigger a UI event programmatically
    • that event causes the listener function to be invoked
    • that listener function then changes the value of an input element
    • Notice that if you change the event type from "click" to something else (say, "input"), then it stops working
    • That's because the listening element (an <a> tag) is listening for a "click" event
  • DEMO -- MDN documentation has a mousemove event demo in vanilla JavaScript
    • mousemove Event -- MDN
    • the canvas drawing example shows how to create multiple event listeners
    • get the location of the mouse/touch event from the event object
    • use the locations to draw on a canvas element
  • There are other ways to trigger events with vanilla JavaScript, but D3 and Observablehq make things simpler

Views

  • "In Observable, a view is a user interface element that directly controls a value in the notebook.
  • A view consists of two parts:
    • The view, which is typically an interactive DOM element.
    • The value, which is any JavaScript value.
  • Reference: Introduction to Views -- observablehq
    • This notebook has several examples
    • A Brief Introduction to Viewov discusses the viewof keyword in Observable
    • On the one hand, Observable Inputs make it super easy to create views with standard UI elements
    • But views can be any kind of visual element
      • See Introduction to views
      • This notebook shows how to create views that trigger reevaluation of any cell that references the views value
      • To trigger the re-evaluation of any cell that references a view’s value, the view must emit an input event.
  • viewof stroke recreate the canvas drawing demo
    • It's worth looking at this example in some detail
  • viewof point uses a map as an interactive view
    • the red dot confirms appropriate relocation of the mousedown or mousemove events
    • the location coordinates of the mouse on the canvas are convered to [longitude, latitude]
    • the geographic coordinates are made available as the value of the map
    • the geographic coordinates are then reprojected back onto the map as a red circle

Exercise 1

Modify a viewof demo in Introduction to Views

d3-brush

  • d3-brush -- collection
    • It's worth investigating some demo from this remarkable collection of notebooks

Exercise 2

Turn a brush into a view

Exercise 3

Same as above, but without D3.

Mutable

  • mutable values
  • This notebook has a brief demo of mutable reporting on internal cell state with a button click

Exercise 4

Report events with a mutable

STOPPED HERE ON MONDAY

Range Slider

Range slider -- history and current state

  • Observable inputs -- the history
    • Inputs by jashkenas
    • Inputs by tmcw (adds a "cautious" option)
  • Input: Range -- current state
    • Good: Input elements based entirely on web standards
    • Not so good: Built-in styling is browser-dependent
    • Not so good: There is no easy way to adjust both the minimum & maximum values in a single input element
  • Range slider -- min & max
    • Good: Adjustable min & max of range in a single slider with optional styling
    • Not so good: CSS styling mimics browser-dependent styles and behavior
    • Not so good: Customizing CSS is a huge challenge
    • Not so good: You need to do more work if you want to mimic browser-dependent styling of built-in input elements
  • QUESTION: Could you customize Empty Brush Selection and turn it into a 2-handle range slider?
    • What sort of interactive functionality would you need? HINT: See Exercise 5 (below)
    • How would you style it? How hard would it be? HINT: See Exercise 6 (below)

:hover

  • :hover -- MDN
    • The :hover CSS pseudo-class matches when the user interacts with an element with a pointing device,
    • But a :hover event does not necessarily activate the element.
  • The <style> element
    • In-line styles take precedence over external CSS style sheets
    • style attributes override even in-line styles.
  • Multiple style elements
    • Multiple <style> and <link> elements are applied to the DOM in the order they are included in the document.
    • This example shows how conflicting styles are resolved (last one wins)
  • Look at the styling and behavior or Input: Range
    • Color changes during hover and selection.
    • Need to distinguish the handle and the channel
  • Styling hovered elements
    • We can select hovered elements using the CSS ":hover" selector
    • This allows us to identify hovered elements of the brush
    • Note the order in which they're placed in the SVG.
    • Thing is, we want to change the color of elements underneath that we're using to visualize the slider"
      • So we do it with a little JavaScript
  • d3-brush events -- github
    • There are several types of "brush events"
    • Listeners for these events are registered when you invoke selection.call(brush, callback)
  • brush(group) API reference describes what happens.
    • IMPORTANT: the brush creates the SVG elements necessary for display and to receive input events for interaction.
    • The SVG elements can be modified, removed, styled, etc.
    • As you can see from Empty Brush Selection, "mousemove" add "mouseout" are being used to change the pointer style

Empty Brush Selection

How it works

Exercise 5

Report mouse events and hover:ed elements.

Exercise 6

Custom brush styling.

  • EXERCISE: Adapt the Empty Brush Selection so that it looks like a 2-handle range slider.
    • Hint: First remove the data and axes, then add the blue & gray slider channels.
    • Note: This is worth doing in class -- debugging errors encountered in the solution could be informative.
  • SOLUTION: Solution to Exercise 6