• Stars
    star
    316
  • Rank 132,587 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 10 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A functional reactive model library for interactive data visualization.

model.js

Build Status

model.js is available on npm. To install it, type:

npm install model-js --save

A functional reactive model library - Model.js manages the execution flow of the data flow graphs you define. Kind of like Backbone and React, but simpler and designed specifically for making D3 easier to use. Also check out Chiasm, a visualization runtime engine built on Model.js.

Installable via Bower: bower install model.

Installable via JSPM: jspm install model=github:curran/model.

Usable as:

  • an AMD (RequireJS) module define(["model"], function(Model){ ... });
  • a CommonJS (Node) module var Model = require("model");
  • a browser global <script src="model.js"></script>

Also, check out this redesign of this library - reactive-model.

Public API

var model = Model([defaults]);

  • The model constructor function.
  • Using "new" is optional.
  • The optional defaults constructor argument is an object with default property values.
  • The returned model object can be treated as a plain JavaScript Object for setting and getting property values, e.g.
    • model.x = 5;
    • console.log(model.x);

var listener = model.when(properties, callback [, thisArg]);

  • Listens for changes to the given dependency properties.
  • properties Either an array of strings or a string. Specifies the dependency properties.
  • callback A callback function that is called:
    • with dependency property values as arguments,
    • only if all dependency properties have values,
    • once for initialization,
    • whenever one or more dependency properties change,
    • on the next tick of the JavaScript event loop after dependency properties change,
    • only once as a result of one or more changes to dependency properties.
  • thisArg An optional argument bound to this in the callback.
  • Returns a listener object that can be used to remove the callback.

model.cancel(listener)

  • Removes the listener returned by when. This means the callback will no longer be called when properties change.

model.on(property, callback(newValue, oldValue)[, thisArg])

  • Adds a change listener for the given property.
  • Kind of like on in Backbone

model.off(property, callback)

  • Removes a change listener for the given property.
  • Kind of like off in Backbone

model.set(values)

  • A convenience function for setting many model properties at once.
  • Assigns each property from the given values object to the model.
  • This function can be used to deserialize models, e.g.:
    • var json = JSON.stringify(model);
    • ... later on ..
    • model.set(JSON.parse(json));

Data Dependency Graphs

Setting model properties in when callbacks enables creating reactive data dependency graphs. . As a simple example, consider a fullName property that is computed from firstName and lastName.

model.when(['firstName', 'lastName'], function (firstName, lastName) {
  model.fullName = firstName + ' ' + lastName;
});

Here's a full working example that computes fullName and uses HTML forms.

The following example demonstrates construction of a data dependency graph in which the flow propagates two hops from x to y to z.

model.when('x', function (x) {
  model.y = x + 1;
});
model.when('y', function (y) {
  model.z = y * 2;
});

This pattern can be used to build up reactive data dependency graphs of arbitrary complexity.

Reactive Visualizations

As an example of how data dependency graphs can be used for creating visualizations, consider this bar chart.

Bar Chart

This is the reactive data flow graph of the bar chart.

Bar Chart Flow

The diagram was constructed using the reactive flow diagram renderer. Lambdas represent reactive functions, and labeled nodes represent model properties.

Though the entire reactive flow may seem complex, programming it is simple, because each reactive function is defined independently, only knowing about its direct dependencies and the properties that it changes. This is why functional reactive programming is so great.

Multiple reactive visualizations can be combined together to form visualization dashboards with multiple linked views. For example, take a look at the linked views example, which looks like this:

Brushing in the scatter plot causes the selected data to be aggregated and plotted in the bar chart ([run it!](http://curran.github.io/model/examples/d3LinkedViews/)).

See Also

Motivation

This library was created in order to cleanly define reactive model-driven data visualizations. When using Backbone and Underscore to define model-driven visualizations, there is a pattern that appears again and again for executing code that depends on multiple model properties. For example, consider a Backbone model that has a size property that contains the width and height of the visualization, and a data property that contains the array of data to be visualized. This is the code you want to write:

model.on('change:width change:height change:data', function (){
  var width = model.get('width'),
      height = model.get('height'),
      data = model.get('data');
  // Build the visualization using width, height and data.
});

However, with the above code, if only one or two of the properties are set, the function will be invoked before all properties are defined. Therefore a null check must be added for all properties as follows:

model.on('change:width change:height change:data', function (){
  var width = model.get('width'),
      height = model.get('height'),
      data = model.get('data');
  if(width && height && data) {
    // Build the visualization using width, height and data.
  }
});

The above code now does not break, but has another issue. When width and height are both updated, the function is invoked twice. Ideally, when width and height are updated in sequence (e.g. model.set('width', 50); model.set('height', 100);), the function should only be invoked once with the new values for both width and height. Also, multiple sequential updates to width or height (e.g. model.set('width', 0); model.set('width', 50);) should only result in a single recomputation of the visualization, using the last value (in this case 50). One way to accomplish this is to debounce the function as follows:

model.on('change:width change:height change:data', _.debounce(function (){
  var width = model.get('width'),
      height = model.get('height'),
      data = model.get('data');
  if(width && height && data) {
    // Build the visualization using width, height and data.
  }
}));

The above code behaves as desired - the visualization is only built when all properties are present, and only once when multiple properties change together. As this pattern is so common in developing model driven data visualizations, it would be useful to abstract it away into a reusable function. The model.when function does exactly that. Using model.when, the above code becomes:

model.when(['width', 'height', 'data'], function (width, height, data) {
  // Build the visualization using width, height and data.
});

As this was the only usage pattern I encountered with models when using Backbone for developing visualizations, I decided to introduce a new library that only contains the essential features needed from Backbone Models (in order to remove the Backbone dependency), and the when function, which appears in the world of Functional Reactive Programming and makes working with models for visualizations much nicer. This is why model.js was created.

Related Work

Inspired by

See also:

Contributing

Pull requests welcome! Potential contributions include:

By Curran Kelleher May 2015

More Repositories

1

screencasts

Code that goes along with my screencasts.
JavaScript
2,622
star
2

data

A collection of public data sets
HTML
473
star
3

dataviz-course-2018

Online course on data visualization analysis, design & construction with D3.js.
HTML
224
star
4

d3-component

A lightweight component abstraction for D3.js.
JavaScript
107
star
5

portfolio

Curran Kelleher's Portfolio
Java
78
star
6

d3-area-label

A library for placing labels in areas.
JavaScript
70
star
7

dataviz-course-archive

Archive of lesson material from an online course at Worcester Polytechnic Institute
HTML
66
star
8

d3-in-motion

Code examples and references for the course "D3.js in Motion"
HTML
38
star
9

HTML5Examples

Examples of HTML5 in action (best results in Chrome)
JavaScript
36
star
10

d3-bundler-ui

A Web application for defining custom d3 builds.
JavaScript
31
star
11

jspm-mocha-example

An example project that uses Mocha and JSPM.
JavaScript
19
star
12

google-diff-match-patch

Automatically exported from code.google.com/p/google-diff-match-patch
Python
17
star
13

data-reduction

A library for reducing the size of data sets for visualization.
JavaScript
13
star
14

phd

Curran Kelleher's Ph. D. work.
TeX
12
star
15

ticks

A utility for choosing nice tick marks or histogram intervals.
JavaScript
11
star
16

model-contrib

Open source visualizations built with ModelJS
JavaScript
10
star
17

nextjs-esm-example

An example that uses ESM with Next.js
JavaScript
10
star
18

dsv-dataset

A metadata specification and parsing library for data sets.
JavaScript
9
star
19

dataviz-project-template

A template project that uses Webpack and D3.
JavaScript
9
star
20

lambda

A Lambda Calculus interpreter
CoffeeScript
7
star
21

visEngine

A server side component for interactive data reduction queries.
JavaScript
7
star
22

mathematorium

A 3D graphing calculator and 3D particle simulator.
Java
6
star
23

d3-format-india

Indian Number System formatter
JavaScript
6
star
24

d3-rosetta

Maximize framework interoperability for interactive graphics
JavaScript
6
star
25

reactivis-old

Reusable Interactive D3 Data Visualizations
JavaScript
6
star
26

canvas-vis

A set of modules useful for information visualization using HTML5 Canvas.
JavaScript
5
star
27

scalatra-spark

A proof of concept integration serving Apache Spark services with Scalatra.
JavaScript
5
star
28

dataviz-project-template-proposal

A template for data visualization project proposals.
5
star
29

udcvis

The Universal Data Cube Visualization System
JavaScript
4
star
30

renderCyliner

A bit of OPENGL C code that renders a cylinder between two points.
C
4
star
31

dashboardScaffold

Plumbing for creating dashboards with D3.js
JavaScript
4
star
32

Fretboard

Fretboard is a Jack midi client which maps keystrokes to midi notes as though the keyboard were a fretted instrument.
4
star
33

old-d3-examples

A large dataset of source files for old D3 examples
JavaScript
3
star
34

stamen-dataviz-workshop

Material for a Data Visualization workshop at Stamen Design.
3
star
35

datacubesinfo

Content posted on datacubes.info. Mostly demos and proofs of concept.
JavaScript
3
star
36

Code-Hub

A database of code snippets with dependency management
JavaScript
3
star
37

LiquidMath

A 3D Graphing Calculator in Clojure using OpenGL
3
star
38

rollup-react-pwa-example

An example project setup with Rollup, server-side React rendering, and code splitting.
JavaScript
3
star
39

backboneComputedProperties

An implementation of computed properties for Backbone.js
JavaScript
3
star
40

unidirectional-data-flow

Unidirectional Data Flow for Vanilla JavaScript
TypeScript
2
star
41

crossCountry

A photo show of my cross country trip.
JavaScript
2
star
42

migrantDeathsVis

JavaScript
2
star
43

reactive-charts

Another charting library
2
star
44

simpleSynth

SimpleSynth is a JACK client which can synthesize and output enveloped sine waves from MIDI input.
C++
2
star
45

PublicDataSets

Scripts for downloading and processing public data sets
Shell
2
star
46

udc

The Universal Data Cube
JavaScript
2
star
47

example-viewer

A presentation tool and programming sandbox for code examples.
JavaScript
2
star
48

jyvis

A Java-based information visualization system with multiple linked views.
Java
2
star
49

graph

A directed graph implementation with depth first search.
JavaScript
2
star
50

udf-scatter-plot

Unidirectional Data Flow Scatter Plot Example
JavaScript
2
star
51

sharedb-snapshot

ShareDB library for fetching historical document snapshots.
JavaScript
2
star
52

streamgraph-explorer

An prototype interactive visualization for exploring flow timeseries data. Try it -->
JavaScript
2
star
53

get-it-right

Materials for the livestream series Get it Right in Black & White
HTML
1
star
54

setupHadoop

Shell scripts and instructions for setting up Hadoop on a cluster.
Shell
1
star
55

quadstream

Quadstream is a Java library for polygon simplification.
JavaScript
1
star
56

curran.github.io

Curran's Web Site
JavaScript
1
star
57

dashboardScaffoldExample

An example application using the dashboardScaffold framework.
JavaScript
1
star
58

world-alliances

A dataset about world alliances
1
star
59

evalIDE

A simple live coding environment for the Web.
CSS
1
star
60

IWSCourseProject

A group project for the course "Internet and Web Systems" at University of Massachusetts Lowell Fall 2011
JavaScript
1
star
61

JSProjectTemplate

Boilerplate structure for starting a JavaScript project.
JavaScript
1
star
62

gash

Graphical ASH - this code is a first attempt to create a graphics library for ASH.
Java
1
star
63

igf

Interactive Graphics Framework (IGF) is a minimal immediate mode graphics API that supports both Java 2D and OpenGL, inspired by Processing (processing.org).
Java
1
star
64

Dynamic-Graphics

A C# framework for interactive dynamic graphics
1
star
65

liquidglobe

A series of small HTML5 prototypes for smooth panning and zooming.
JavaScript
1
star
66

PDJava

A collection of noise-making prototypes linking Java to PureData over a socket, using Processing as a graphics and network library.
Pure Data
1
star
67

TickMarkUtils

A simple algorithm for computing the values to use for tick marks such that nice numbers are displayed (intervals of {1 or 2 or 5}X10^n)
Java
1
star
68

images

A place to store images referenced by other repos.
1
star
69

hot-server-rollup-poc

Proof of concept for hot reloading with ES module support.
HTML
1
star
70

forceDirected

A simple prototype of force directed graph layout using Canvas & CoffeeScript
JavaScript
1
star
71

vis2013Tutorial

Material I presented at IEEE Vis 2013 in a tutorial called "Mobile and cloud Web-based graphics and visualization".
JavaScript
1
star
72

rollup-swc-crash-reproduction

Minimal reproduction for Rollup #5379
JavaScript
1
star