├── .gitignore
├── icon.png
├── src
├── viz
│ ├── methods
│ │ ├── style.coffee
│ │ ├── dev.coffee
│ │ ├── depth.coffee
│ │ ├── background.coffee
│ │ ├── error.coffee
│ │ ├── descs.coffee
│ │ ├── timing.coffee
│ │ ├── width.coffee
│ │ ├── aggs.coffee
│ │ ├── height.coffee
│ │ ├── history.coffee
│ │ ├── order.coffee
│ │ ├── type.coffee
│ │ ├── total.coffee
│ │ ├── temp.coffee
│ │ ├── id.coffee
│ │ ├── cols.js
│ │ ├── focus.coffee
│ │ ├── text.coffee
│ │ ├── axes.coffee
│ │ ├── active.coffee
│ │ ├── attrs.coffee
│ │ ├── nodes.coffee
│ │ ├── container.coffee
│ │ ├── zoom.js
│ │ ├── icon.coffee
│ │ ├── messages.coffee
│ │ ├── time.coffee
│ │ ├── legend.coffee
│ │ ├── timeline.coffee
│ │ ├── shape.coffee
│ │ ├── links.coffee
│ │ ├── labels.coffee
│ │ ├── footer.coffee
│ │ ├── coords.coffee
│ │ ├── size.coffee
│ │ ├── font.coffee
│ │ ├── data.js
│ │ ├── tooltip.coffee
│ │ ├── color.coffee
│ │ ├── ui.coffee
│ │ ├── margin.coffee
│ │ ├── format.coffee
│ │ ├── draw.js
│ │ ├── title.coffee
│ │ ├── csv.coffee
│ │ └── edges.js
│ ├── types
│ │ ├── helpers
│ │ │ └── graph
│ │ │ │ ├── draw.coffee
│ │ │ │ ├── stack.coffee
│ │ │ │ ├── nest.coffee
│ │ │ │ ├── dataTicks.coffee
│ │ │ │ └── includes
│ │ │ │ └── buffer.coffee
│ │ ├── deprecated
│ │ │ └── chart.coffee
│ │ ├── geo_map.coffee
│ │ ├── line.coffee
│ │ ├── pie.coffee
│ │ ├── scatter.coffee
│ │ ├── tree_map.coffee
│ │ ├── stacked.coffee
│ │ └── bar.coffee
│ └── helpers
│ │ ├── zoom
│ │ ├── propagation.coffee
│ │ ├── transform.coffee
│ │ ├── direction.coffee
│ │ ├── labels.js
│ │ ├── mouse.coffee
│ │ ├── bounds.js
│ │ └── controls.js
│ │ ├── shapes
│ │ ├── style.coffee
│ │ ├── color.coffee
│ │ ├── cross.js
│ │ ├── diamond.js
│ │ ├── triangle_up.js
│ │ ├── triangle_down.js
│ │ ├── check.js
│ │ └── arc.coffee
│ │ ├── types
│ │ └── run.coffee
│ │ ├── focus
│ │ └── tooltip.coffee
│ │ ├── container.coffee
│ │ └── svg
│ │ └── update.js
├── form
│ ├── methods
│ │ ├── depth.coffee
│ │ ├── dev.coffee
│ │ ├── timing.coffee
│ │ ├── color.coffee
│ │ ├── hover.coffee
│ │ ├── type.coffee
│ │ ├── width.coffee
│ │ ├── height.coffee
│ │ ├── history.coffee
│ │ ├── open.coffee
│ │ ├── active.coffee
│ │ ├── search.coffee
│ │ ├── remove.coffee
│ │ ├── order.coffee
│ │ ├── alt.coffee
│ │ ├── keywords.coffee
│ │ ├── select.coffee
│ │ ├── selectAll.coffee
│ │ ├── id.coffee
│ │ ├── text.coffee
│ │ ├── container.coffee
│ │ ├── focus.coffee
│ │ ├── font.coffee
│ │ ├── title.coffee
│ │ ├── ui.coffee
│ │ ├── icon.coffee
│ │ ├── margin.coffee
│ │ ├── format.coffee
│ │ ├── data.js
│ │ └── draw.js
│ └── types
│ │ ├── auto.js
│ │ ├── button
│ │ ├── functions
│ │ │ ├── style.js
│ │ │ ├── mouseevents.js
│ │ │ └── color.js
│ │ └── button.js
│ │ ├── drop
│ │ └── functions
│ │ │ ├── selector.js
│ │ │ ├── list.js
│ │ │ ├── arrow.js
│ │ │ ├── active.js
│ │ │ ├── height.js
│ │ │ ├── element.js
│ │ │ ├── window.js
│ │ │ ├── button.js
│ │ │ ├── items.coffee
│ │ │ └── width.js
│ │ └── toggle.js
├── libs.coffee
├── textwrap
│ ├── methods
│ │ ├── dev.coffee
│ │ ├── resize.coffee
│ │ ├── size.coffee
│ │ ├── width.coffee
│ │ ├── height.coffee
│ │ ├── shape.coffee
│ │ ├── text.coffee
│ │ ├── container.coffee
│ │ ├── format.coffee
│ │ └── draw.coffee
│ ├── helpers
│ │ ├── flow.coffee
│ │ ├── getSize.coffee
│ │ ├── getText.coffee
│ │ ├── getDimensions.coffee
│ │ ├── foreign.coffee
│ │ └── wrap.coffee
│ └── textwrap.coffee
├── client
│ ├── ie.js
│ ├── rtl.coffee
│ ├── touch.coffee
│ ├── css.coffee
│ ├── prefix.coffee
│ ├── pointer.coffee
│ └── scrollbar.coffee
├── color
│ ├── lighter.coffee
│ ├── legible.coffee
│ ├── random.coffee
│ ├── sort.coffee
│ ├── text.coffee
│ ├── mix.coffee
│ ├── scale.coffee
│ └── validate.coffee
├── core
│ ├── methods
│ │ ├── filter.coffee
│ │ ├── font
│ │ │ ├── transform.coffee
│ │ │ ├── decoration.coffee
│ │ │ ├── position.coffee
│ │ │ ├── family.coffee
│ │ │ └── align.coffee
│ │ ├── rendering.coffee
│ │ ├── process
│ │ │ ├── icon.coffee
│ │ │ ├── detect.coffee
│ │ │ └── data.coffee
│ │ ├── reset.coffee
│ │ └── rejected.coffee
│ ├── locale
│ │ └── locale.coffee
│ ├── font
│ │ └── tester.coffee
│ ├── data
│ │ ├── group.coffee
│ │ ├── keys.js
│ │ ├── color.js
│ │ └── load.coffee
│ ├── fetch
│ │ ├── sort.coffee
│ │ ├── color.coffee
│ │ └── text.js
│ ├── parse
│ │ ├── nodes.js
│ │ └── edges.js
│ └── console
│ │ ├── wiki.coffee
│ │ └── print.coffee
├── util
│ ├── buckets.coffee
│ ├── closest.coffee
│ ├── d3selection.coffee
│ ├── child.coffee
│ ├── dataURL.coffee
│ ├── copy.coffee
│ └── uniques.coffee
├── array
│ ├── contains.coffee
│ ├── sort.coffee
│ ├── update.coffee
│ └── comparator.coffee
├── object
│ ├── validate.coffee
│ └── merge.coffee
├── network
│ └── distances.coffee
├── tooltip
│ └── remove.coffee
├── string
│ ├── title.coffee
│ ├── list.coffee
│ ├── format.js
│ └── strip.js
├── font
│ ├── sizes.coffee
│ └── validate.coffee
├── data
│ ├── mad.coffee
│ ├── lof.coffee
│ └── bestRegress.coffee
├── geom
│ ├── path2poly.coffee
│ └── offset.coffee
└── number
│ └── format.js
├── docs
├── assets
│ ├── css
│ │ ├── logo.png
│ │ └── external-small.png
│ ├── favicon.png
│ ├── img
│ │ └── spinner.gif
│ ├── index.html
│ ├── js
│ │ ├── yui-prettify.js
│ │ └── api-filter.js
│ └── vendor
│ │ └── prettify
│ │ └── prettify-min.css
└── api.js
├── lib
└── font-awesome-4.2.0
│ └── fonts
│ ├── FontAwesome.otf
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.ttf
│ └── fontawesome-webfont.woff
├── gulp
├── error.coffee
├── docs.coffee
├── server.coffee
├── rebuild.coffee
└── compile.coffee
├── gulpfile.js
├── bower.json
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /tests/
2 | /node_modules/
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/icon.png
--------------------------------------------------------------------------------
/src/viz/methods/style.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | value: false
3 |
--------------------------------------------------------------------------------
/src/form/methods/depth.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Number]
3 | value: 0
4 |
--------------------------------------------------------------------------------
/src/libs.coffee:
--------------------------------------------------------------------------------
1 | window.d3 = require "d3"
2 | window.topojson = require "topojson"
3 |
--------------------------------------------------------------------------------
/docs/assets/css/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/docs/assets/css/logo.png
--------------------------------------------------------------------------------
/docs/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/docs/assets/favicon.png
--------------------------------------------------------------------------------
/src/form/methods/dev.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/form/methods/timing.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | mouseevents: 60
3 | ui: 200
4 |
--------------------------------------------------------------------------------
/src/viz/methods/dev.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/form/methods/color.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [String]
3 | value: "color"
4 |
--------------------------------------------------------------------------------
/src/textwrap/methods/dev.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/textwrap/methods/resize.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/viz/methods/depth.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Function, Number]
3 | value: 0
4 |
--------------------------------------------------------------------------------
/docs/assets/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/docs/assets/img/spinner.gif
--------------------------------------------------------------------------------
/src/textwrap/methods/size.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Array, false]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/textwrap/methods/width.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/viz/methods/background.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [String]
3 | value: "#ffffff"
4 |
--------------------------------------------------------------------------------
/src/viz/methods/error.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean, String]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/form/methods/hover.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number, String]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/textwrap/methods/height.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/textwrap/methods/shape.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: ["circle", "square"]
3 | value: false
4 |
--------------------------------------------------------------------------------
/src/viz/methods/descs.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Function, Object]
3 | value: false
4 |
--------------------------------------------------------------------------------
/docs/assets/css/external-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/docs/assets/css/external-small.png
--------------------------------------------------------------------------------
/src/client/ie.js:
--------------------------------------------------------------------------------
1 | // Determines if the current browser is Internet Explorer.
2 | module.exports = /*@cc_on!@*/false
3 |
--------------------------------------------------------------------------------
/src/form/methods/type.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: (vars) -> d3.keys vars.types
3 | value: "auto"
4 |
--------------------------------------------------------------------------------
/src/viz/methods/timing.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | mouseevents: 60
3 | transitions: 600
4 | ui: 200
5 |
--------------------------------------------------------------------------------
/src/form/methods/width.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number]
3 | secondary: false
4 | value: false
5 |
--------------------------------------------------------------------------------
/lib/font-awesome-4.2.0/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/lib/font-awesome-4.2.0/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/src/client/rtl.coffee:
--------------------------------------------------------------------------------
1 | # Detects right-to-left text direction on the page.
2 | module.exports = d3.select("html").attr("dir") is "rtl"
3 |
--------------------------------------------------------------------------------
/src/form/methods/height.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number]
3 | max: 600
4 | secondary: false
5 | value: false
6 |
--------------------------------------------------------------------------------
/src/viz/methods/width.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number]
3 | secondary: false
4 | small: 200
5 | value: false
6 |
--------------------------------------------------------------------------------
/lib/font-awesome-4.2.0/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/lib/font-awesome-4.2.0/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/lib/font-awesome-4.2.0/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/lib/font-awesome-4.2.0/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/lib/font-awesome-4.2.0/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tkh44/d3plus/master/lib/font-awesome-4.2.0/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/src/viz/methods/aggs.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Object]
3 | deprecated: "nesting_aggs"
4 | objectAccess: false
5 | value: {}
6 |
--------------------------------------------------------------------------------
/src/form/methods/history.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | back: ->
3 | @states.pop()() if @states.length
4 | return
5 | chain: []
6 | states: []
7 |
--------------------------------------------------------------------------------
/src/form/methods/open.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean]
3 | flipped:
4 | accepted: [Boolean]
5 | value: false
6 | value: false
7 |
--------------------------------------------------------------------------------
/src/viz/methods/height.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number]
3 | max: 600
4 | secondary: false
5 | small: 200
6 | value: false
7 |
--------------------------------------------------------------------------------
/gulp/error.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | title: "D3plus"
3 | subtitle: "Build Error"
4 | message: "Error: <%= error.message %>"
5 | icon: __dirname + "/../icon.png"
6 |
--------------------------------------------------------------------------------
/src/form/methods/active.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Array, Function, Number, String]
5 | value: false
6 |
--------------------------------------------------------------------------------
/src/form/methods/search.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: ["auto", Boolean]
3 | process: (value) ->
4 | @enabled = value if typeof value is "Boolean"
5 | value
6 | value: "auto"
7 |
--------------------------------------------------------------------------------
/src/form/methods/remove.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: undefined
3 | process: (value, vars) ->
4 | vars.container.value.remove() if @initialized
5 | return
6 | value: undefined
7 |
--------------------------------------------------------------------------------
/src/viz/methods/history.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean]
3 | back: ->
4 | @states.pop()() if @states.length
5 | return
6 | chain: []
7 | states: []
8 | value: true
9 |
--------------------------------------------------------------------------------
/src/client/touch.coffee:
--------------------------------------------------------------------------------
1 | # Detects is the current browser supports touch events
2 | module.exports = if ("ontouchstart" of window) or window.DocumentTouch and document instanceof DocumentTouch then true else false
3 |
--------------------------------------------------------------------------------
/src/color/lighter.coffee:
--------------------------------------------------------------------------------
1 | # Lightens a color
2 | module.exports = (color, increment) ->
3 | increment = 0.5 if increment is undefined
4 | c = d3.hsl(color)
5 | c.l += (1 - c.l) * increment
6 | c.toString()
7 |
--------------------------------------------------------------------------------
/src/core/methods/filter.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (g) ->
2 |
3 | g = false unless g
4 |
5 | accepted: [false, Array, Function, Number, Object, String]
6 | global: g
7 | process: Array
8 | value: []
9 |
--------------------------------------------------------------------------------
/src/core/methods/font/transform.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (transform) ->
2 |
3 | transform = "none" unless transform
4 |
5 | accepted: ["capitalize", "lowercase", "none", "uppercase"]
6 | value: transform
7 |
--------------------------------------------------------------------------------
/src/form/methods/order.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Function, String]
3 | sort:
4 | accepted: ["asc", "desc"]
5 | deprecates: ["sort"]
6 | value: "asc"
7 | value: false
8 |
--------------------------------------------------------------------------------
/src/viz/methods/order.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Function, String]
3 | deprecates: ["sort"]
4 | sort:
5 | accepted: ["asc", "desc"]
6 | value: "asc"
7 | value: false
8 |
--------------------------------------------------------------------------------
/src/core/methods/font/decoration.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (decoration) ->
2 |
3 | decoration = "none" unless decoration
4 |
5 | accepted: ["line-through", "none", "overline", "underline"]
6 | value: decoration
7 |
--------------------------------------------------------------------------------
/src/core/locale/locale.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | en_US: require "./languages/en_US.coffee"
3 | mk_MK: require "./languages/mk_MK.js"
4 | pt_BR: require "./languages/pt_BR.js"
5 | zh_CN: require "./languages/zh_CN.js"
6 |
--------------------------------------------------------------------------------
/src/util/buckets.coffee:
--------------------------------------------------------------------------------
1 | # Expands a min/max into a specified number of buckets
2 | module.exports = (arr, n) ->
3 |
4 | buckets = []
5 | step = 1 / (n - 1) * (arr[1] - arr[0])
6 |
7 | d3.range arr[0], arr[1]+step, step
8 |
--------------------------------------------------------------------------------
/src/viz/methods/type.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: (vars) -> d3.keys vars.types
3 | mode:
4 | accepted: (vars) -> vars.types[vars.type.value].modes or [false]
5 | value: false
6 | value: "tree_map"
7 |
--------------------------------------------------------------------------------
/src/color/legible.coffee:
--------------------------------------------------------------------------------
1 | # Darkens a color if it's too light to appear on white
2 | module.exports = (color) ->
3 | hsl = d3.hsl color
4 | if hsl.l > .45
5 | hsl.s = 0.8 if hsl.s > .8
6 | hsl.l = 0.45
7 | hsl.toString()
8 |
--------------------------------------------------------------------------------
/src/form/methods/alt.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 | module.exports =
3 | accepted: [false, Array, Function, Object, String]
4 | mute: filter true
5 | solo: filter true
6 | value: "alt"
7 |
--------------------------------------------------------------------------------
/src/color/random.coffee:
--------------------------------------------------------------------------------
1 | defaultScale = require("./scale.coffee")
2 |
3 | # Returns a random color
4 | module.exports = (x, scale) ->
5 | rand_int = x or Math.floor(Math.random() * 20)
6 | scale = scale or defaultScale
7 | scale rand_int
8 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require("gulp");
2 | require('coffee-script/register');
3 | require("require-dir")("./gulp");
4 |
5 | gulp.task("default", ["server", "rebuild"]);
6 |
7 | gulp.task("release", ["compile", "docs"], function() { process.exit(); });
8 |
--------------------------------------------------------------------------------
/src/form/methods/keywords.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Array, Function, Object, String]
5 | mute: filter(true)
6 | solo: filter(true)
7 | value: "keywords"
8 |
--------------------------------------------------------------------------------
/src/textwrap/helpers/flow.coffee:
--------------------------------------------------------------------------------
1 | foreign = require "./foreign.coffee"
2 | tspan = require "./tspan.js"
3 |
4 | # Flows the text into the container
5 | module.exports = (vars) ->
6 | if vars.text.html.value then foreign vars else tspan vars
7 | return
8 |
--------------------------------------------------------------------------------
/src/util/closest.coffee:
--------------------------------------------------------------------------------
1 | # Finds closest numeric value in array
2 | module.exports = (arr, value) ->
3 |
4 | closest = arr[0]
5 |
6 | arr.forEach (p) ->
7 | closest = p if Math.abs(value - p) < Math.abs(value - closest)
8 |
9 | closest
10 |
--------------------------------------------------------------------------------
/src/form/methods/select.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [String]
3 | chainable: false
4 | process: (value, vars) ->
5 | container = vars.container.value
6 | if container and value then container.select(value) else value
7 | value: undefined
8 |
--------------------------------------------------------------------------------
/src/color/sort.coffee:
--------------------------------------------------------------------------------
1 | # Sorts 2 colors based on hue.
2 | module.exports = (a, b) ->
3 | aHSL = d3.hsl a
4 | bHSL = d3.hsl b
5 | a = if aHSL.s is 0 then 361 else aHSL.h
6 | b = if bHSL.s is 0 then 361 else bHSL.h
7 | if a is b then aHSL.l - bHSL.l else a - b
8 |
--------------------------------------------------------------------------------
/src/form/methods/selectAll.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [String]
3 | chainable: false
4 | process: (value, vars) ->
5 | container = vars.container.value
6 | if container and value then container.selectAll(value) else value
7 | value: undefined
8 |
--------------------------------------------------------------------------------
/src/array/contains.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (arr, value) ->
2 | if arr instanceof Array
3 | constructor = if value is undefined then value else value.constructor
4 | arr.indexOf(value) >= 0 or (value isnt undefined and arr.indexOf(constructor) >= 0)
5 | else false
6 |
--------------------------------------------------------------------------------
/src/core/methods/rendering.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (rendering) ->
2 |
3 | accepted = ["auto", "optimizeSpeed", "crispEdges", "geometricPrecision"]
4 | rendering = "crispEdges" unless accepted.indexOf(rendering) >= 0
5 |
6 | accepted: accepted
7 | value: rendering
8 |
--------------------------------------------------------------------------------
/src/util/d3selection.coffee:
--------------------------------------------------------------------------------
1 | ie = require "../client/ie.js"
2 |
3 | # Cross-browser detect for D3 element
4 | module.exports = (elem) ->
5 | if ie then typeof elem is "object" and elem instanceof Array and "size" of elem and "select" of elem else elem instanceof d3.selection
6 |
--------------------------------------------------------------------------------
/src/viz/methods/total.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Function, Object, String]
5 | deprecates: ["total_var"]
6 | mute: filter(true)
7 | solo: filter(true)
8 | value: false
9 |
--------------------------------------------------------------------------------
/src/viz/methods/temp.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Function, Object, String]
5 | deprecates: ["else_var", "else"]
6 | mute: filter(true)
7 | solo: filter(true)
8 | value: false
9 |
--------------------------------------------------------------------------------
/docs/assets/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Redirector
5 |
6 |
7 |
8 | Click here to redirect
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/form/methods/id.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [Array, String]
5 | dataFilter: true
6 | mute: filter(true)
7 | nesting: ["value"]
8 | solo: filter(true)
9 | value: "value"
10 |
--------------------------------------------------------------------------------
/src/core/methods/process/icon.coffee:
--------------------------------------------------------------------------------
1 | stylesheet = require "../../../client/css.coffee"
2 |
3 | module.exports = (value, vars, method) ->
4 | if value is false or value.indexOf("fa-") < 0 or (value.indexOf("fa-") is 0 and stylesheet("font-awesome"))
5 | value
6 | else
7 | method.fallback
8 |
--------------------------------------------------------------------------------
/src/color/text.coffee:
--------------------------------------------------------------------------------
1 | # Returns appropriate text color based off of a given color
2 | module.exports = (color) ->
3 | rgbColor = d3.rgb(color)
4 | r = rgbColor.r
5 | g = rgbColor.g
6 | b = rgbColor.b
7 | yiq = (r * 299 + g * 587 + b * 114) / 1000
8 | if yiq >= 128 then "#444444" else "#f7f7f7"
9 |
--------------------------------------------------------------------------------
/src/viz/methods/id.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [Array, String]
5 | dataFilter: true
6 | deprecates: ["id_var", "nesting"]
7 | mute: filter(true)
8 | nesting: ["id"]
9 | solo: filter(true)
10 | value: "id"
11 |
--------------------------------------------------------------------------------
/src/viz/methods/cols.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "accepted": [Array, Function, String],
3 | "index": {
4 | "accepted": [Boolean],
5 | "value": true
6 | },
7 | "process": function(value, vars) {
8 | if (typeof value === "string") value = [value]
9 | return value
10 | },
11 | "value": false
12 | }
13 |
--------------------------------------------------------------------------------
/src/viz/methods/focus.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Array, Function, Number, String]
3 | deprecates: "highlight"
4 | process: (value) -> if value is false then [] else if value instanceof Array then value else [value]
5 | tooltip:
6 | accepted: [Boolean]
7 | value: true
8 | value: []
9 |
--------------------------------------------------------------------------------
/src/viz/methods/text.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [Array, Boolean, Function, Object, String]
5 | deprecates: ["name_array", "text_var"]
6 | nesting: true
7 | mute: filter(true)
8 | solo: filter(true)
9 | value: false
10 |
--------------------------------------------------------------------------------
/src/core/methods/font/position.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (position) ->
2 |
3 | position = "bottom" unless position
4 |
5 | accepted: ["top", "middle", "bottom"]
6 | mapping:
7 | top: "0ex"
8 | middle: "0.5ex"
9 | bottom: "1ex"
10 | process: (value) ->
11 | @text = value
12 | @mapping[value]
13 | value: position
14 |
--------------------------------------------------------------------------------
/src/form/methods/text.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [false, String]
5 | nesting: true
6 | mute: filter(true)
7 | solo: filter(true)
8 | secondary:
9 | accepted: [false, String]
10 | nesting: true
11 | value: false
12 | value: false
13 |
--------------------------------------------------------------------------------
/src/viz/methods/axes.coffee:
--------------------------------------------------------------------------------
1 | rendering = require "../../core/methods/rendering.coffee"
2 |
3 | module.exports =
4 | background:
5 | color: "#fafafa"
6 | rendering: rendering()
7 | stroke:
8 | color: "#ccc"
9 | width: 1
10 | mirror:
11 | accepted: [Boolean]
12 | deprecates: ["mirror_axis", "mirror_axes"]
13 | value: false
14 |
--------------------------------------------------------------------------------
/src/core/methods/font/family.coffee:
--------------------------------------------------------------------------------
1 | validate = require "../../../font/validate.coffee"
2 | helvetica = ["Helvetica Neue", "HelveticaNeue", "Helvetica", "Arial", "sans-serif"]
3 |
4 | # Constructs font family property using the validate function
5 | module.exports = (family) ->
6 |
7 | family = helvetica unless family
8 |
9 | process: validate
10 | value: family
11 |
--------------------------------------------------------------------------------
/src/viz/methods/active.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Function, Object, String]
5 | deprecates: "active_var"
6 | mute: filter true
7 | solo: filter true
8 | spotlight:
9 | accepted: [Boolean]
10 | deprecates: "spotlight"
11 | value: false
12 | value: false
13 |
--------------------------------------------------------------------------------
/src/viz/methods/attrs.coffee:
--------------------------------------------------------------------------------
1 | process = require "../../core/methods/process/data.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Array, Object, String]
5 | delimiter:
6 | accepted: String
7 | value: "|"
8 | filetype:
9 | accepted: [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"]
10 | value: false
11 | process: process
12 | value: false
13 |
--------------------------------------------------------------------------------
/src/textwrap/methods/text.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Array, Number, String]
3 | html:
4 | accepted: [Boolean]
5 | value: false
6 | init: (vars) ->
7 | s = @split.value
8 | @break = new RegExp "[^\\s\\" + s.join("\\") + "]+\\" + s.join("?\\") + "?", "g"
9 | false
10 | split:
11 | accepted: [Array]
12 | value: ["-", "/", ";", ":", "&"]
13 |
--------------------------------------------------------------------------------
/src/viz/methods/nodes.coffee:
--------------------------------------------------------------------------------
1 | process = require "../../core/methods/process/data.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Array, Function, String]
5 | delimiter:
6 | accepted: [String]
7 | value: "|"
8 | filetype:
9 | accepted: [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"]
10 | value: false
11 | overlap: 0.6
12 | process: process
13 | value: false
14 |
--------------------------------------------------------------------------------
/src/core/methods/font/align.coffee:
--------------------------------------------------------------------------------
1 | rtl = require "../../../client/rtl.coffee"
2 |
3 | module.exports = (align) ->
4 |
5 | align = "left" unless align
6 |
7 | accepted: ["left", "center", "right"]
8 | process: (value) ->
9 | if rtl
10 | if value is "left"
11 | "right"
12 | else
13 | if value is "right"
14 | "left"
15 | else value
16 | else value
17 | value: align
18 |
--------------------------------------------------------------------------------
/src/core/methods/reset.coffee:
--------------------------------------------------------------------------------
1 | validObject = require("../../object/validate.coffee")
2 |
3 | # Resets certain keys in global variables.
4 | reset = (obj, method) ->
5 | obj.changed = false if obj.changed
6 | if method is "draw"
7 | obj.frozen = false
8 | obj.update = true
9 | obj.first = false
10 | for o of obj
11 | reset obj[o], o if validObject(obj[o])
12 | return
13 |
14 | module.exports = reset
15 |
--------------------------------------------------------------------------------
/src/viz/types/helpers/graph/draw.coffee:
--------------------------------------------------------------------------------
1 | axes = require "./includes/axes.coffee"
2 | draw = require "./includes/svg.coffee"
3 | mouse = require "./includes/mouse.coffee"
4 | plot = require "./includes/plot.coffee"
5 |
6 | module.exports = (vars, opts) ->
7 | opts = {} if opts is undefined
8 | axes vars, opts
9 | plot vars, opts
10 | draw vars, opts
11 | vars.mouse = if opts.mouse is true then mouse else false
12 | return
13 |
--------------------------------------------------------------------------------
/src/viz/methods/container.coffee:
--------------------------------------------------------------------------------
1 | d3selection = require("../../util/d3selection.coffee")
2 |
3 | module.exports =
4 | accepted: [false, Array, Object, String]
5 | id: "default"
6 | process: (value) ->
7 | if value is false
8 | false
9 | else if d3selection(value)
10 | value
11 | else if value instanceof Array
12 | d3.select value[0][0]
13 | else
14 | d3.select value
15 | value: false
16 |
--------------------------------------------------------------------------------
/src/color/mix.coffee:
--------------------------------------------------------------------------------
1 | # Mixes 2 colors with optional opacities
2 | module.exports = (c1, c2, o1, o2) ->
3 | o1 = 1 unless o1
4 | o2 = 1 unless o2
5 | c1 = d3.rgb(c1)
6 | c2 = d3.rgb(c2)
7 | r = (o1 * c1.r + o2 * c2.r - o1 * o2 * c2.r) / (o1 + o2 - o1 * o2)
8 | g = (o1 * c1.g + o2 * c2.g - o1 * o2 * c2.g) / (o1 + o2 - o1 * o2)
9 | b = (o1 * c1.b + o2 * c2.b - o1 * o2 * c2.b) / (o1 + o2 - o1 * o2)
10 | d3.rgb(r, g, b).toString()
11 |
--------------------------------------------------------------------------------
/src/color/scale.coffee:
--------------------------------------------------------------------------------
1 | # Default D3plus color scale
2 | module.exports = d3.scale.ordinal().range([
3 | "#b22200",
4 | "#EACE3F",
5 | "#282F6B",
6 |
7 | "#B35C1E",
8 | "#224F20",
9 | "#5F487C",
10 |
11 | "#759143",
12 | "#419391",
13 | "#993F88",
14 |
15 | "#e89c89",
16 | "#ffee8d",
17 | "#afd5e8",
18 |
19 | "#f7ba77",
20 | "#a5c697",
21 | "#c5b5e5",
22 |
23 | "#d1d392",
24 | "#bbefd0",
25 | "#e099cf"
26 | ])
27 |
--------------------------------------------------------------------------------
/src/viz/helpers/zoom/propagation.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (vars, event) ->
2 |
3 | zoom = vars.zoom
4 | event = d3.event unless event
5 |
6 | zoomed = zoom.scale > zoom.behavior.scaleExtent()[0]
7 | enabled = vars.types[vars.type.value].zoom and zoom.value and zoom.scroll.value
8 | zoomable = event.touches and event.touches.length > 1 and enabled
9 |
10 | event.stopPropagation() if not zoomable and not zoomed
11 | return
12 |
--------------------------------------------------------------------------------
/src/textwrap/methods/container.coffee:
--------------------------------------------------------------------------------
1 | d3selection = require("../../util/d3selection.coffee")
2 |
3 | module.exports =
4 | accepted: [false, Array, Object, String]
5 | element: false
6 | id: "default"
7 | process: (value) ->
8 | if value is false
9 | false
10 | else if d3selection(value)
11 | value
12 | else if value instanceof Array
13 | d3.select value[0][0]
14 | else
15 | d3.select value
16 | value: false
17 |
--------------------------------------------------------------------------------
/gulp/docs.coffee:
--------------------------------------------------------------------------------
1 | gulp = require "gulp"
2 | project = require "../package.json"
3 | rimraf = require "gulp-rimraf"
4 | yuidoc = require "gulp-yuidoc"
5 |
6 | gulp.task "docs", ->
7 |
8 | gulp.src("./docs/files/*.*", {read: false}).pipe rimraf()
9 |
10 | scan "js"
11 | scan "coffee"
12 |
13 | scan = (type) ->
14 | gulp.src("./src/**/*."+type).pipe(yuidoc(
15 | project: project
16 | syntaxtype: type
17 | ))
18 | .pipe gulp.dest("./docs")
19 |
--------------------------------------------------------------------------------
/src/textwrap/helpers/getSize.coffee:
--------------------------------------------------------------------------------
1 | # Fetches text if not specified, and formats text to array.
2 | module.exports = (vars) ->
3 |
4 | size = vars.container.value.attr "font-size" or vars.container.value.style "font-size"
5 | vars.container.fontSize = size
6 |
7 | unless vars.size.value
8 | size = parseFloat(size, 10)
9 | if vars.resize.value
10 | vars.self.size [size, size * 2]
11 | else
12 | vars.self.size [size / 2, size]
13 |
14 | return
15 |
--------------------------------------------------------------------------------
/src/util/child.coffee:
--------------------------------------------------------------------------------
1 | d3selection = require "./d3selection.coffee"
2 |
3 | # Checks to see if element is inside of another element
4 | module.exports = (parent, child) ->
5 |
6 | return false if not parent or not child
7 |
8 | parent = parent.node() if d3selection(parent)
9 | child = child.node() if d3selection(parent)
10 | node = child.parentNode
11 |
12 | while node isnt null
13 | return true if node is parent
14 | node = node.parentNode
15 |
16 | false
17 |
--------------------------------------------------------------------------------
/src/client/css.coffee:
--------------------------------------------------------------------------------
1 | # Checks to see if a stylesheet is loaded
2 | sheet = (name) ->
3 |
4 | tested = sheet.tested
5 | return tested[name] if name of tested
6 | i = 0
7 | returnBoolean = false
8 |
9 | while i < document.styleSheets.length
10 | css = document.styleSheets[i]
11 | if css.href and css.href.indexOf(name) >= 0
12 | returnBoolean = true
13 | break
14 | i++
15 | returnBoolean
16 |
17 | sheet.tested = {}
18 |
19 | module.exports = sheet
20 |
--------------------------------------------------------------------------------
/src/form/methods/container.coffee:
--------------------------------------------------------------------------------
1 | d3selection = require("../../util/d3selection.coffee")
2 |
3 | module.exports =
4 | accepted: [false, Array, Object, String]
5 | element: false
6 | id: "default"
7 | process: (value) ->
8 | if value is false
9 | d3.select("body")
10 | else if d3selection(value)
11 | value
12 | else if value instanceof Array
13 | d3.select value[0][0]
14 | else
15 | d3.select value
16 | value: d3.select("body")
17 |
--------------------------------------------------------------------------------
/src/object/validate.coffee:
--------------------------------------------------------------------------------
1 | ###*
2 | # This function returns true if the variable passed is a literal javascript keyed Object. It's a small, simple function, but it catches some edge-cases that can throw off your code (such as Arrays and `null`).
3 | # @method d3plus.object.validate
4 | # @for d3plus.object
5 | # @param obj {Object} The object to validate.
6 | # @return {Boolean}
7 | ###
8 | module.exports = (obj) ->
9 | obj isnt null and typeof obj is "object" and (obj not instanceof Array)
10 |
--------------------------------------------------------------------------------
/src/viz/methods/zoom.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "accepted" : [ Boolean ],
3 | "behavior" : d3.behavior.zoom().scaleExtent([ 1 , 1 ]),
4 | "click" : {
5 | "accepted" : [ Boolean ],
6 | "value" : true
7 | },
8 | "pan" : {
9 | "accepted" : [ Boolean ],
10 | "value" : true
11 | },
12 | "scroll" : {
13 | "accepted" : [ Boolean ],
14 | "deprecates" : "scroll_zoom",
15 | "value" : true
16 | },
17 | "value" : true
18 | }
19 |
--------------------------------------------------------------------------------
/src/viz/helpers/zoom/transform.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (vars, timing) ->
2 |
3 | timing = vars.timing.transitions if typeof timing isnt "number"
4 | translate = vars.zoom.translate
5 | scale = vars.zoom.scale
6 |
7 | if timing
8 | vars.g.viz.transition().duration(timing)
9 | .attr "transform", "translate(" + translate + ")scale(" + scale + ")"
10 | else
11 | vars.g.viz
12 | .attr "transform", "translate(" + translate + ")scale(" + scale + ")"
13 |
14 | return
15 |
--------------------------------------------------------------------------------
/src/array/sort.coffee:
--------------------------------------------------------------------------------
1 | comparator = require "./comparator.coffee"
2 | fetchSort = require "../core/fetch/sort.coffee"
3 |
4 | # Sorts an array of objects
5 | module.exports = (arr, keys, sort, colors, vars, depth) ->
6 |
7 | if not arr or arr.length <= 1 or not keys
8 | arr or []
9 | else
10 |
11 | if vars
12 | for d in arr
13 | d.d3plus.sortKeys = fetchSort(vars, d, keys, colors, depth) if d.d3plus
14 |
15 | arr.sort (a, b) -> comparator a, b, keys, sort, colors, vars, depth
16 |
--------------------------------------------------------------------------------
/src/viz/methods/icon.coffee:
--------------------------------------------------------------------------------
1 | process = require "../../core/methods/process/icon.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Array, Function, Object, String]
5 | back:
6 | accepted: [false, String]
7 | fallback: "❮"
8 | opacity: 1
9 | process: process
10 | rotate: 0
11 | value: "fa-angle-left"
12 | deprecates: "icon_var"
13 | style:
14 | accepted: [Object, String]
15 | deprecates: "icon_style"
16 | value: "default"
17 | value: "icon"
18 |
--------------------------------------------------------------------------------
/src/viz/methods/messages.coffee:
--------------------------------------------------------------------------------
1 | decoration = require "../../core/methods/font/decoration.coffee"
2 | family = require "../../core/methods/font/family.coffee"
3 | transform = require "../../core/methods/font/transform.coffee"
4 |
5 | module.exports =
6 | accepted: [Boolean, String]
7 | font:
8 | color: "#444"
9 | decoration: decoration()
10 | family: family()
11 | size: 16
12 | transform: transform()
13 | weight: 200
14 | padding: 5
15 | value: true
16 |
--------------------------------------------------------------------------------
/src/viz/methods/time.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [Array, Boolean, Function, Object, String]
5 | dataFilter: true
6 | deprecates: ["year", "year_var"]
7 | fixed:
8 | accepted: [Boolean]
9 | deprecates: ["static_axis", "static_axes"]
10 | value: true
11 | format:
12 | accepted: [false, String]
13 | value: false
14 | mute: filter(false)
15 | solo: filter(false)
16 | value: false
17 |
--------------------------------------------------------------------------------
/src/core/methods/process/detect.coffee:
--------------------------------------------------------------------------------
1 | copy = require("../../../util/copy.coffee")
2 | update = require("../../../array/update.coffee")
3 |
4 | # Process object's value
5 | module.exports = (vars, object, value) ->
6 |
7 | if object.process is Array
8 | update copy(object.value), value
9 | else if typeof object.process is "object" and typeof value is "string"
10 | object.process[value]
11 | else if typeof object.process is "function"
12 | object.process value, vars, object
13 | else
14 | value
15 |
--------------------------------------------------------------------------------
/src/client/prefix.coffee:
--------------------------------------------------------------------------------
1 | # Calculates the correct CSS vendor prefix based on the current browser.
2 | prefix = ->
3 |
4 | if "-webkit-transform" of document.body.style
5 | val = "-webkit-"
6 | else if "-moz-transform" of document.body.style
7 | val = "-moz-"
8 | else if "-ms-transform" of document.body.style
9 | val = "-ms-"
10 | else if "-o-transform" of document.body.style
11 | val = "-o-"
12 | else
13 | val = ""
14 |
15 | prefix = -> val
16 |
17 | val
18 |
19 | module.exports = prefix
20 |
--------------------------------------------------------------------------------
/src/util/dataURL.coffee:
--------------------------------------------------------------------------------
1 | # Creates a Base-64 Data URL from and Image URL
2 | module.exports = (url, callback) ->
3 |
4 | img = new Image()
5 | img.src = url
6 | img.crossOrigin = "Anonymous"
7 | img.onload = ->
8 | canvas = document.createElement("canvas")
9 | canvas.width = @width
10 | canvas.height = @height
11 | context = canvas.getContext("2d")
12 | context.drawImage this, 0, 0
13 | callback.call this, canvas.toDataURL("image/png")
14 | canvas = null
15 | return
16 |
17 | return
18 |
--------------------------------------------------------------------------------
/src/viz/methods/legend.coffee:
--------------------------------------------------------------------------------
1 | family = require "../../core/methods/font/family.coffee"
2 |
3 | module.exports =
4 | accepted: [Boolean]
5 | align: "middle"
6 | font:
7 | align: "middle"
8 | color: "#444444"
9 | family: family()
10 | size: 10
11 | weight: 200
12 | gradient:
13 | height: 10
14 | order:
15 | accepted: ["color", "id", "size", "text"]
16 | sort:
17 | accepted: ["asc", "desc"]
18 | value: "asc"
19 | value: "color"
20 | size: [8,30]
21 | value: true
22 |
--------------------------------------------------------------------------------
/src/util/copy.coffee:
--------------------------------------------------------------------------------
1 | objectMerge = require "../object/merge.coffee"
2 | objectValidate = require "../object/validate.coffee"
3 |
4 | # Clones a variable
5 | copy = (variable) ->
6 |
7 | # Object Logic
8 | if objectValidate(variable)
9 | objectMerge variable
10 |
11 | # Array Logic
12 | else if variable instanceof Array
13 | ret = []
14 | variable.forEach (o) ->
15 | ret.push copy(o)
16 | ret
17 |
18 | # Everything else just returns itself
19 | else
20 | variable
21 |
22 | module.exports = copy
23 |
--------------------------------------------------------------------------------
/src/viz/methods/timeline.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Boolean]
3 | align: "middle"
4 | hover:
5 | accepted: ["all-scroll", "col-resize", "crosshair", "default", "grab", "grabbing", "move", "pointer"]
6 | value: "pointer"
7 | handles:
8 | accepted: [Boolean]
9 | color: "#e5e5e5"
10 | hover: "#cccccc"
11 | opacity: 1
12 | size: 2
13 | stroke: "#818181"
14 | value: true
15 | height:
16 | accepted: [Number]
17 | value: 23
18 | tick: "#818181"
19 | value: true
20 |
--------------------------------------------------------------------------------
/src/color/validate.coffee:
--------------------------------------------------------------------------------
1 | # Tests if a string is a valid color
2 | module.exports = (color) ->
3 | color = color + ""
4 | color = color.replace(RegExp(" ", "g"), "")
5 | color = color.split("(")[1].split(")")[0].split(",").slice(0, 3).join(",") if color.indexOf("rgb") is 0
6 | color = color.split(",")[2].split(")")[0] if color.indexOf("hsl") is 0
7 | testColor = d3.rgb(color).toString()
8 | blackColors = [ "black", "#000", "#000000", "0%", "0,0,0" ]
9 | userBlack = blackColors.indexOf(color) >= 0
10 | testColor isnt "#000000" or userBlack
11 |
--------------------------------------------------------------------------------
/src/viz/methods/shape.coffee:
--------------------------------------------------------------------------------
1 | rendering = require "../../core/methods/rendering.coffee"
2 |
3 | module.exports =
4 | accepted: (vars) ->
5 | list = vars.types[vars.type.value].shapes
6 | list = [list] if list and !(list instanceof Array)
7 | if list.length then list else ["square"]
8 | interpolate:
9 | accepted: ["basis", "basis-open", "cardinal", "cardinal-open", "linear", "monotone", "step", "step-before", "step-after"]
10 | deprecates: "stack_type"
11 | value: "linear"
12 | rendering: rendering()
13 | value: false
14 |
--------------------------------------------------------------------------------
/src/form/types/auto.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | // Determines form type based on data length.
3 | //------------------------------------------------------------------------------
4 | module.exports = function( vars ) {
5 |
6 | var dataLength = vars.data.value.length
7 |
8 | if ( dataLength === 1 ) {
9 | vars.self.type("button").draw()
10 | }
11 | else if ( dataLength < 5 ) {
12 | vars.self.type("toggle").draw()
13 | }
14 | else {
15 | vars.self.type("drop").draw()
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/docs/assets/js/yui-prettify.js:
--------------------------------------------------------------------------------
1 | YUI().use('node', function(Y) {
2 | var code = Y.all('.prettyprint.linenums');
3 | if (code.size()) {
4 | code.each(function(c) {
5 | var lis = c.all('ol li'),
6 | l = 1;
7 | lis.each(function(n) {
8 | n.prepend('');
9 | l++;
10 | });
11 | });
12 | var h = location.hash;
13 | location.hash = '';
14 | h = h.replace('LINE_', 'LINENUM_');
15 | location.hash = h;
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/src/viz/methods/links.coffee:
--------------------------------------------------------------------------------
1 | decoration = require "../../core/methods/font/decoration.coffee"
2 | family = require "../../core/methods/font/family.coffee"
3 | transform = require "../../core/methods/font/transform.coffee"
4 |
5 | module.exports =
6 | font:
7 | color: "#444444"
8 | decoration: decoration()
9 | family: family()
10 | transform: transform()
11 | weight: 200
12 | hover:
13 | color: "#444444"
14 | decoration: decoration()
15 | family: family()
16 | transform: transform()
17 | weight: 200
18 |
--------------------------------------------------------------------------------
/src/viz/methods/labels.coffee:
--------------------------------------------------------------------------------
1 | decoration = require "../../core/methods/font/decoration.coffee"
2 | family = require "../../core/methods/font/family.coffee"
3 | transform = require "../../core/methods/font/transform.coffee"
4 |
5 | module.exports =
6 | accepted: [Boolean]
7 | align: "middle"
8 | font:
9 | decoration: decoration()
10 | family: family()
11 | size: 11
12 | transform: transform()
13 | weight: 200
14 | padding: 7
15 | resize:
16 | accepted: [Boolean]
17 | value: true
18 | segments: 2
19 | value: true
20 |
--------------------------------------------------------------------------------
/src/array/update.coffee:
--------------------------------------------------------------------------------
1 | # Updates an array, either overwriting it with a new array, removing an entry
2 | module.exports = (arr, x) ->
3 |
4 | # Return an empty array if the user has passed `false`
5 | return [] if x is false
6 |
7 | # If the user has passed an array, just use that.
8 | return x if x instanceof Array
9 |
10 | # Create an empty Array if none has been passed
11 | arr = [] unless arr instanceof Array
12 |
13 | # Remove or add the value
14 | if arr.indexOf(x) >= 0 then arr.splice arr.indexOf(x), 1 else arr.push x
15 |
16 | # Return the array
17 | arr
18 |
--------------------------------------------------------------------------------
/src/client/pointer.coffee:
--------------------------------------------------------------------------------
1 | ie = require "./ie.js"
2 | touch = require "./touch.coffee"
3 |
4 | # Creates custom mouse events based on IE and Touch Devices.
5 | if touch
6 | module.exports =
7 | click: "click"
8 | down: "touchstart"
9 | up: "touchend"
10 | over: "touchstart"
11 | out: "touchend"
12 | move: "touchmove"
13 | else
14 | module.exports =
15 | click: "click"
16 | down: "mousedown"
17 | up: "mouseup"
18 | over: if ie then "mouseenter" else "mouseover"
19 | out: if ie then "mouseleave" else "mouseout"
20 | move: "mousemove"
21 |
--------------------------------------------------------------------------------
/src/viz/helpers/zoom/direction.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (data, vars) ->
2 |
3 | max_depth = vars.id.nesting.length - 1
4 | current_depth = vars.depth.value
5 | restricted = vars.types[vars.type.value].nesting is false
6 |
7 | if restricted
8 | 0
9 | else if data.d3plus.merged or current_depth < max_depth and (not data or vars.id.nesting[vars.depth.value + 1] of data)
10 | 1
11 | else if (current_depth is max_depth or (data and (vars.id.nesting[vars.depth.value + 1] not of data))) and (vars.small or not vars.tooltip.html.value)
12 | -1
13 | else
14 | 0
15 |
--------------------------------------------------------------------------------
/src/viz/methods/footer.coffee:
--------------------------------------------------------------------------------
1 | family = require "../../core/methods/font/family.coffee"
2 | decoration = require "../../core/methods/font/decoration.coffee"
3 | transform = require "../../core/methods/font/transform.coffee"
4 |
5 | module.exports =
6 | accepted: [false, Number, String]
7 | font:
8 | align: "center"
9 | color: "#444"
10 | decoration: decoration()
11 | family: family()
12 | size: 11
13 | transform: transform()
14 | weight: 200
15 | link: false
16 | padding: 0
17 | position: "bottom"
18 | value: false
19 |
--------------------------------------------------------------------------------
/src/core/methods/process/data.coffee:
--------------------------------------------------------------------------------
1 | d3selection = require "../../../util/d3selection.coffee"
2 |
3 | # Function to process data by url or element.
4 | module.exports = (value, vars, method) ->
5 |
6 | if typeof value isnt "string" and not d3selection(value)
7 | value
8 | else
9 | maybeURL = value.indexOf("/") >= 0
10 | if not maybeURL and d3selection(value)
11 | return value
12 | else
13 | if not maybeURL and not d3.selectAll(value).empty()
14 | return d3.selectAll(value)
15 | else
16 | method.url = value
17 | return []
18 | []
19 |
--------------------------------------------------------------------------------
/src/core/font/tester.coffee:
--------------------------------------------------------------------------------
1 | # Creates an invisible test element to populate
2 | module.exports = (type) ->
3 |
4 | type = "div" if [ "div", "svg" ].indexOf(type) < 0
5 | styles =
6 | position: "absolute"
7 | left: "-9999px"
8 | top: "-9999px"
9 | visibility: "hidden"
10 | display: "block"
11 |
12 | attrs = if type is "div" then {} else
13 | position: "absolute"
14 |
15 | tester = d3.select("body").selectAll(type + ".d3plus_tester").data([0])
16 | tester.enter().append(type).attr("class", "d3plus_tester")
17 | .style(styles).attr(attrs)
18 |
19 | tester
20 |
--------------------------------------------------------------------------------
/docs/api.js:
--------------------------------------------------------------------------------
1 | YUI.add("yuidoc-meta", function(Y) {
2 | Y.YUIDoc = { meta: {
3 | "classes": [
4 | "d3plus",
5 | "d3plus.array",
6 | "d3plus.client",
7 | "d3plus.color",
8 | "d3plus.data",
9 | "d3plus.font",
10 | "d3plus.form",
11 | "d3plus.geom",
12 | "d3plus.network",
13 | "d3plus.number",
14 | "d3plus.object",
15 | "d3plus.string",
16 | "d3plus.textwrap",
17 | "d3plus.tooltip",
18 | "d3plus.util",
19 | "d3plus.viz"
20 | ],
21 | "modules": [],
22 | "allModules": []
23 | } };
24 | });
--------------------------------------------------------------------------------
/src/network/distances.coffee:
--------------------------------------------------------------------------------
1 | # Returns distances of all objects in array
2 | module.exports = (arr, accessor) ->
3 |
4 | distances = []
5 | checked = []
6 |
7 | arr.forEach (node1) ->
8 | n1 = (if accessor then accessor(node1) else [ node1.x, node1.y ])
9 | checked.push node1
10 | arr.forEach (node2) ->
11 | if checked.indexOf(node2) < 0
12 | n2 = (if accessor then accessor(node2) else [ node2.x, node2.y ])
13 | xx = Math.abs(n1[0] - n2[0])
14 | yy = Math.abs(n1[1] - n2[1])
15 | distances.push Math.sqrt((xx * xx) + (yy * yy))
16 |
17 | distances.sort (a, b) -> a - b
18 |
--------------------------------------------------------------------------------
/src/viz/types/deprecated/chart.coffee:
--------------------------------------------------------------------------------
1 | print = require("../../../core/console/print.coffee")
2 |
3 | chart = (vars) ->
4 |
5 | types =
6 | circle: "scatter"
7 | donut: "scatter"
8 | line: "line"
9 | square: "scatter"
10 | area: "stacked"
11 |
12 | type = types[vars.shape.value]
13 | print.warning "The \"chart\" visualization type has been deprecated and will be removed in version 2.0. Please use the \"" + type + "\" visualization type."
14 | vars.self.type(type).draw()
15 |
16 | return
17 |
18 | chart.shapes = ["circle", "donut", "line", "square", "area"]
19 | module.exports = chart
20 |
--------------------------------------------------------------------------------
/gulp/server.coffee:
--------------------------------------------------------------------------------
1 | express = require "express"
2 | gulp = require "gulp"
3 | gutil = require "gulp-util"
4 | livereload = require "gulp-livereload"
5 | lr = require("tiny-lr")()
6 | path = require "path"
7 |
8 | gulp.task "server", ->
9 |
10 | app = express()
11 | app.use require("connect-livereload")(hostname: "0.0.0.0")
12 | app.use express.static("./")
13 | app.listen 4000
14 |
15 | gulp.watch ["./tests/**/*.*"], (evt) ->
16 |
17 | fileName = path.relative("./", evt.path)
18 | gutil.log gutil.colors.cyan(fileName), "changed"
19 | gulp.src(evt.path, read: false).pipe livereload(lr)
20 |
--------------------------------------------------------------------------------
/src/viz/methods/coords.coffee:
--------------------------------------------------------------------------------
1 | filter = require("../../core/methods/filter.coffee")
2 | process = require("../../core/methods/process/data.coffee")
3 |
4 | module.exports =
5 | accepted: [false, Array, Function, Object, String]
6 | center: [0,0]
7 | filetype:
8 | accepted: ["json"]
9 | value: "json"
10 | fit:
11 | accepted: ["auto", "height", "width"]
12 | value: "auto"
13 | mute: filter false
14 | padding: 20
15 | process: process
16 | projection:
17 | accepted: ["mercator", "equirectangular"]
18 | value: "mercator"
19 | solo: filter false
20 | threshold: 0.1
21 | value: false
22 |
--------------------------------------------------------------------------------
/src/tooltip/remove.coffee:
--------------------------------------------------------------------------------
1 | # Destroy Tooltips
2 | module.exports = (id) ->
3 |
4 | # If an ID is specified, only remove that tooltip
5 | if id
6 |
7 | # First remove the background curtain, if the tooltip has one
8 | d3.selectAll("div#d3plus_tooltip_curtain_" + id).remove()
9 |
10 | # Finally, remove the tooltip itself
11 | d3.selectAll("div#d3plus_tooltip_id_" + id).remove()
12 |
13 | # If no ID is given, remove ALL d3plus tooltips
14 | else
15 |
16 | # First remove all background curtains on the page
17 | d3.selectAll("div.d3plus_tooltip_curtain").remove()
18 |
19 | # Finally, remove all tooltip
20 | d3.selectAll("div.d3plus_tooltip").remove()
21 |
--------------------------------------------------------------------------------
/docs/assets/vendor/prettify/prettify-min.css:
--------------------------------------------------------------------------------
1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
--------------------------------------------------------------------------------
/src/textwrap/helpers/getText.coffee:
--------------------------------------------------------------------------------
1 | # Fetches text if not specified, and formats text to array.
2 | module.exports = (vars) ->
3 |
4 | unless vars.text.value
5 | text = vars.container.value.text()
6 | if text
7 | if text.indexOf("tspan") >= 0
8 | text.replace /\<\/tspan\>\/g, " "
9 | text.replace /\<\/tspan\>/g, ""
10 | text.replace /\/g, ""
11 | vars.self.text text
12 |
13 | if vars.text.value instanceof Array
14 | vars.text.phrases = vars.text.value.filter (t) -> ["string", "number"].indexOf(typeof t) >= 0
15 | else
16 | vars.text.phrases = [vars.text.value + ""]
17 |
18 | vars.container.value.text ""
19 |
20 | return
21 |
--------------------------------------------------------------------------------
/src/form/types/button/functions/style.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | //
3 | //------------------------------------------------------------------------------
4 | module.exports = function ( elem , vars ) {
5 |
6 | elem
7 | .style("position","relative")
8 | .style("margin",vars.ui.margin+"px")
9 | .style("display",vars.ui.display.value)
10 | .style("border-style","solid")
11 | .style("border-width",vars.ui.border+"px")
12 | .style("font-family",vars.font.family.value)
13 | .style("font-size",vars.font.size+"px")
14 | .style("font-weight",vars.font.weight)
15 | .style("letter-spacing",vars.font.spacing+"px")
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/style.coffee:
--------------------------------------------------------------------------------
1 | color = require "./color.coffee"
2 |
3 | # Fill style for all shapes
4 | module.exports = (nodes, vars) ->
5 |
6 | nodes
7 | .attr "fill", (d) ->
8 | if d.d3plus and d.d3plus.spline then "none" else color d, vars
9 | .style "stroke", (d) ->
10 | if d.d3plus and d.d3plus.stroke
11 | d.d3plus.stroke
12 | else
13 | c = if d.values then color(d.values[0], vars) else color(d, vars)
14 | d3.rgb(c).darker 0.7
15 | .style "stroke-width", (d) ->
16 | mod = if d.d3plus.shape is "line" then 2 else 1
17 | vars.data.stroke.width * mod
18 | .attr "opacity", vars.data.opacity
19 | .attr "vector-effect", "non-scaling-stroke"
20 |
--------------------------------------------------------------------------------
/src/viz/methods/size.coffee:
--------------------------------------------------------------------------------
1 | filter = require "../../core/methods/filter.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Function, Number, Object, String]
5 | dataFilter: true
6 | deprecates: ["value", "value_var"]
7 | mute: filter(true)
8 | scale:
9 | accepted: [Function]
10 | deprecates: "size_scale"
11 | max:
12 | accepted: [Function, Number]
13 | value: (vars) ->
14 | Math.floor d3.max [d3.min([vars.width.viz,vars.height.viz])/15, 6]
15 | min:
16 | accepted: [Function, Number]
17 | value: 3
18 | value: d3.scale.sqrt()
19 | solo: filter(true)
20 | threshold:
21 | accepted: [Boolean, Function, Number]
22 | value: true
23 | value: false
24 |
--------------------------------------------------------------------------------
/src/form/methods/focus.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [false, Number, String]
3 | deprecates: "highlight"
4 | process: (value, vars) ->
5 |
6 | element = vars.data.element.value
7 |
8 | if element and ["string","number"].indexOf(typeof value) >= 0
9 |
10 | elementTag = element.node().tagName.toLowerCase()
11 | elementType = element.attr("type")
12 |
13 | if elementTag is "select"
14 | for d, i in element.selectAll("option")
15 | element.node().selectedIndex = i if d and d[vars.id.value] is value
16 | else if elementTag is "input" and elementType is "radio"
17 | for d in element
18 | @checked = d and d[vars.id.value] is value
19 |
20 | value
21 | value: false
22 |
--------------------------------------------------------------------------------
/src/form/methods/font.coffee:
--------------------------------------------------------------------------------
1 | family = require "../../core/methods/font/family.coffee"
2 | align = require "../../core/methods/font/align.coffee"
3 | decoration = require "../../core/methods/font/decoration.coffee"
4 | transform = require "../../core/methods/font/transform.coffee"
5 |
6 | module.exports =
7 | align: align()
8 | color: "#444444"
9 | decoration: decoration()
10 | family: family()
11 | secondary:
12 | align: align()
13 | color: "#444444"
14 | decoration: decoration()
15 | family: family()
16 | size: 12
17 | spacing: 0
18 | transform: transform()
19 | weight: 200
20 | size: 12
21 | spacing: 0
22 | transform: transform()
23 | weight: 200
24 |
--------------------------------------------------------------------------------
/src/textwrap/methods/format.coffee:
--------------------------------------------------------------------------------
1 | locale = require "../../core/locale/locale.coffee"
2 | mergeObject = require "../../object/merge.coffee"
3 |
4 | module.exports =
5 | accepted: [Function, String]
6 | locale:
7 | accepted: -> d3.keys locale
8 | process: (value) ->
9 | defaultLocale = "en_US"
10 | returnObject = locale[defaultLocale]
11 | returnObject = mergeObject(returnObject, locale[value]) if value isnt defaultLocale
12 | @language = value
13 | returnObject
14 | value: "en_US"
15 | process: (value, vars) ->
16 | if @initialized and typeof value is "string"
17 | vars.self.format locale: value
18 | else return value if typeof value is "function"
19 | @value
20 | value: "en_US"
21 |
--------------------------------------------------------------------------------
/src/viz/methods/font.coffee:
--------------------------------------------------------------------------------
1 | align = require "../../core/methods/font/align.coffee"
2 | decoration = require "../../core/methods/font/decoration.coffee"
3 | family = require "../../core/methods/font/family.coffee"
4 | transform = require "../../core/methods/font/transform.coffee"
5 |
6 | module.exports =
7 | align: align()
8 | color: "#444444"
9 | decoration: decoration()
10 | family: family()
11 | secondary:
12 | align: align()
13 | color: "#444444"
14 | decoration: decoration()
15 | family: family()
16 | size: 12
17 | spacing: 0
18 | transform: transform()
19 | weight: 200
20 | size: 12
21 | spacing: 0
22 | transform: transform()
23 | weight: 200
24 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/selector.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | // Creates and styles the div that holds the search box and item list.
3 | //------------------------------------------------------------------------------
4 | module.exports = function ( vars ) {
5 |
6 | vars.container.selector = vars.container.ui
7 | .selectAll("div.d3plus_drop_selector")
8 | .data(["selector"])
9 |
10 | vars.container.selector.enter().append("div")
11 | .attr("class","d3plus_drop_selector")
12 | .style("position","absolute")
13 | .style("top","0px")
14 | .style("z-index","-1")
15 | .style("overflow","hidden")
16 |
17 | vars.container.selector
18 | .style("padding",vars.ui.border+"px")
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/string/title.coffee:
--------------------------------------------------------------------------------
1 | defaultLocale = require "../core/locale/languages/en_US.coffee"
2 |
3 | module.exports = (text, key, vars) ->
4 |
5 | return "" unless text
6 |
7 | locale = if "locale" of this then @locale.value else defaultLocale
8 |
9 | # If it's a sentence, just capitalize the first letter.
10 | return text.charAt(0).toUpperCase() + text.substr(1) if text.charAt(text.length - 1) is "."
11 |
12 | smalls = locale.lowercase
13 | bigs = locale.uppercase
14 |
15 | text.replace /\S*/g, (txt, i) ->
16 | if bigs.indexOf(txt.toLowerCase()) >= 0
17 | return txt.toUpperCase()
18 | else return txt.toLowerCase() if smalls.indexOf(txt.toLowerCase()) >= 0 and i isnt 0 and i isnt text.length - 1
19 | txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
20 |
--------------------------------------------------------------------------------
/src/form/methods/title.coffee:
--------------------------------------------------------------------------------
1 | decoration = require "../../core/methods/font/decoration.coffee"
2 | family = require "../../core/methods/font/family.coffee"
3 | transform = require "../../core/methods/font/transform.coffee"
4 |
5 | stringStrip = require "../../string/strip.js"
6 |
7 | module.exports =
8 | accepted: [false, Function, String]
9 | font:
10 | align: "center"
11 | color: "#444444"
12 | decoration: decoration()
13 | family: family()
14 | size: 16
15 | transform: transform()
16 | weight: 400
17 | link: false
18 | process: (value, vars) ->
19 | if vars.container.id.indexOf("default") is 0 and value
20 | id = stringStrip(value).toLowerCase()
21 | vars.self.container id: id
22 | value
23 | value: false
24 |
--------------------------------------------------------------------------------
/src/string/list.coffee:
--------------------------------------------------------------------------------
1 | format = require "./format.js"
2 | locale = require("../core/locale/languages/en_US.coffee").ui
3 |
4 | # Converts an array of strings into a string list using commas and "and".
5 | module.exports = (list, andText, max, moreText) ->
6 | unless list instanceof Array
7 | return list
8 | else
9 | list = list.slice(0)
10 | andText = locale.and unless andText
11 | moreText = locale.moreText unless moreText
12 | if list.length is 2
13 | list.join " " + andText + " "
14 | else
15 | if max and list.length > max
16 | amount = list.length - max + 1
17 | list = list.slice(0, max - 1)
18 | list[max - 1] = format(moreText, amount)
19 | list[list.length - 1] = andText + " " + list[list.length - 1] if list.length > 1
20 | list.join ", "
21 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/list.js:
--------------------------------------------------------------------------------
1 | var print = require("../../../../core/console/print.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Creates and populates the dropdown list of items.
4 | //------------------------------------------------------------------------------
5 | module.exports = function ( vars ) {
6 |
7 | if ( vars.dev.value ) print.time("populating list")
8 |
9 | vars.container.list = vars.container.selector.selectAll("div.d3plus_drop_list")
10 | .data(["list"])
11 |
12 | vars.container.list.enter().append("div")
13 | .attr("class","d3plus_drop_list")
14 | .attr("id","d3plus_drop_list_"+vars.container.id)
15 | .style("overflow-y","auto")
16 | .style("overflow-x","hidden")
17 |
18 | if ( vars.dev.value ) print.timeEnd("populating list")
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/textwrap/methods/draw.coffee:
--------------------------------------------------------------------------------
1 | print = require "../../core/console/print.coffee"
2 |
3 | module.exports =
4 | accepted: [undefined]
5 | process : (value, vars) ->
6 |
7 | return value if this.initialized is false
8 |
9 | if vars.container.value is false
10 | str = vars.format.locale.value.dev.setContainer
11 | print.warning str, "container"
12 | else if vars.container.value.empty()
13 | str = vars.format.locale.value.dev.noContainer
14 | print.warning stringFormat(str, "\"" + vars.container.value + "\""), "container"
15 | else
16 | if vars.dev.value
17 | if vars.methodGroup
18 | vars.methodGroup = "wait"
19 | print.groupEnd()
20 | print.time "total draw time"
21 |
22 | vars.container.value.call vars.self
23 |
24 | value
25 | value: undefined
26 |
--------------------------------------------------------------------------------
/src/font/sizes.coffee:
--------------------------------------------------------------------------------
1 | fontTester = require "../core/font/tester.coffee"
2 |
3 | module.exports = (words, style, parent) ->
4 |
5 | tester = parent or fontTester("svg").append("text")
6 | style = style or {}
7 | sizes = []
8 | words = [ words ] unless words instanceof Array
9 | tspans = tester.selectAll("tspan").data(words)
10 | attr =
11 | x: 0
12 | y: 0
13 |
14 | tspans.enter().append("tspan")
15 | .text String
16 | .attr "position", "absolute"
17 | .attr "top", "0px"
18 | .attr "left", "0px"
19 | .style style
20 | .attr attr
21 | .each (d) ->
22 | sizes.push
23 | height: @offsetHeight or @getBoundingClientRect().height or @.parentNode.getBBox().height
24 | text: d
25 | width: @getComputedTextLength()
26 |
27 | tspans.remove()
28 | tester.remove() unless parent
29 | sizes
30 |
--------------------------------------------------------------------------------
/src/client/scrollbar.coffee:
--------------------------------------------------------------------------------
1 | # Detects scrollbar width for current browser.
2 | scrollbar = ->
3 |
4 | inner = document.createElement "p"
5 | inner.style.width = "100%"
6 | inner.style.height = "200px"
7 |
8 | outer = document.createElement "div"
9 | outer.style.position = "absolute"
10 | outer.style.top = "0px"
11 | outer.style.left = "0px"
12 | outer.style.visibility = "hidden"
13 | outer.style.width = "200px"
14 | outer.style.height = "150px"
15 | outer.style.overflow = "hidden"
16 |
17 | outer.appendChild inner
18 | document.body.appendChild outer
19 | w1 = inner.offsetWidth
20 | outer.style.overflow = "scroll"
21 | w2 = inner.offsetWidth
22 | w2 = outer.clientWidth if w1 is w2
23 | document.body.removeChild outer
24 | val = w1 - w2
25 |
26 | scrollbar = -> val
27 |
28 | val
29 |
30 | module.exports = scrollbar
31 |
--------------------------------------------------------------------------------
/src/core/data/group.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../fetch/value.js"
2 | # Groups data into groups to use with D3 layouts. Helps prevent key name mismatches (parent, child, value, etc).
3 | module.exports = (vars, data, nesting) ->
4 |
5 | groupedData = d3.nest()
6 | nesting = vars.id.nesting if nesting is undefined
7 |
8 | for n, i in nesting
9 | if i < vars.depth.value
10 | key = n
11 | groupedData.key (d) -> fetchValue vars, d.d3plus, key
12 |
13 | strippedData = []
14 | for d in data
15 |
16 | val = if vars.size.value then fetchValue vars, d, vars.size.value else 1
17 |
18 | if val and typeof val is "number" and val > 0
19 |
20 | delete d.d3plus.r
21 | delete d.d3plus.x
22 | delete d.d3plus.y
23 |
24 | strippedData.push
25 | d3plus: d
26 | id: d[vars.id.value]
27 | value: val
28 |
29 | groupedData.entries(strippedData)
30 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/arrow.js:
--------------------------------------------------------------------------------
1 | var print = require("../../../../core/console/print.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Toggles the state of the dropdown menu.
4 | //------------------------------------------------------------------------------
5 | module.exports = function ( vars ) {
6 |
7 | if ( vars.dev.value ) print.time("rotating arrow")
8 |
9 | var offset = vars.icon.drop.value === "❯" ? 90 : 0
10 |
11 | if (vars.open.value != vars.open.flipped.value) {
12 | var rotate = 180 + offset
13 | }
14 | else {
15 | var rotate = offset
16 | }
17 |
18 | vars.container.button
19 | .icon({
20 | "select": {
21 | "opacity": vars.open.value ? 0.5 : 1,
22 | "rotate": rotate
23 | }
24 | })
25 | .draw()
26 |
27 | if ( vars.dev.value ) print.timeEnd("rotating arrow")
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/viz/methods/data.js:
--------------------------------------------------------------------------------
1 | var process = require("../../core/methods/process/data.coffee")
2 |
3 | module.exports = {
4 | "accepted" : [ false , Array , Function , String ],
5 | "cache" : {},
6 | "delimiter" : {
7 | "accepted" : [ String ],
8 | "value" : "|"
9 | },
10 | "donut" : {
11 | "size" : 0.35
12 | },
13 | "filetype" : {
14 | "accepted" : [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"],
15 | "value" : false
16 | },
17 | "filters" : [],
18 | "mute" : [],
19 | "large" : 400,
20 | "opacity" : 0.9,
21 | "process" : function(value, vars) {
22 |
23 | if ( vars.container.id === "default" && value.length ) {
24 | vars.self.container({"id": "default"+value.length})
25 | }
26 |
27 | return process(value, vars, this)
28 | },
29 | "solo" : [],
30 | "stroke" : {
31 | "width" : 1
32 | },
33 | "value" : false
34 | }
35 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/active.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | // Checks to see if a given variable is allowed to be selected.
3 | //------------------------------------------------------------------------------
4 | module.exports = function ( vars , value , active ) {
5 |
6 | var ret = []
7 | , active = active || vars.active.value
8 |
9 | if ( active instanceof Array ) {
10 |
11 | for (var i = 0; i < active.length; i++) {
12 | ret.push(this(vars,value,active[i]))
13 | }
14 |
15 | }
16 | else {
17 |
18 | var t = typeof active
19 |
20 | if (t === "number") {
21 | ret.push(vars.depth.value === active)
22 | }
23 | else if (t === "function") {
24 | ret.push(active(value))
25 | }
26 | else {
27 | ret.push(value === active)
28 | }
29 |
30 | }
31 |
32 | return ret.indexOf(true) >= 0
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/array/comparator.coffee:
--------------------------------------------------------------------------------
1 | colorSort = require "../color/sort.coffee"
2 |
3 | module.exports = (a, b, keys, sort, colors, vars, depth) ->
4 |
5 | sort = "asc" unless sort
6 | colors = [colors] unless colors instanceof Array
7 | keys = [keys] unless keys instanceof Array
8 | depth = vars.id.nesting.indexOf(depth) if vars and depth isnt undefined and typeof depth isnt "number"
9 |
10 | retVal = 0
11 | i = 0
12 |
13 | while i < keys.length
14 |
15 | k = keys[i]
16 |
17 | a = if vars and a.d3plus and a.d3plus.sortKeys then a.d3plus.sortKeys[k] else a[k]
18 | b = if vars and b.d3plus and b.d3plus.sortKeys then b.d3plus.sortKeys[k] else b[k]
19 |
20 | if vars and colors.indexOf(k) >= 0
21 | retVal = colorSort a, b
22 | else
23 | retVal = if a < b then -1 else 1
24 |
25 | break if retVal isnt 0 or i is keys.length - 1
26 | i++
27 |
28 | if sort is "asc" then retVal else -retVal
29 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/height.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | // Calculates the height and orientation of the dropdown list, based on
3 | // available screen space.
4 | //------------------------------------------------------------------------------
5 | module.exports = function ( vars ) {
6 |
7 | var button = vars.container.button.container().node().getBoundingClientRect()
8 |
9 | vars.height.secondary = window.innerHeight - button.bottom - vars.ui.margin
10 | - vars.ui.padding*2 - vars.ui.border*2
11 |
12 | if ( vars.height.secondary < button.height*3 ) {
13 | vars.height.secondary = button.top-10
14 | vars.self.open({"flipped": true})
15 | }
16 | else {
17 | vars.self.open({"flipped": false})
18 | }
19 |
20 | var scrolling = false
21 | if (vars.height.secondary > vars.height.max) {
22 | vars.height.secondary = vars.height.max
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/util/uniques.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../core/fetch/value.js"
2 | objectValidate = require "../object/validate.coffee"
3 |
4 | # Returns list of unique values
5 | module.exports = (data, value, vars) ->
6 |
7 | return [] if data is undefined
8 |
9 | if value is undefined
10 | return data.reduce (p, c) ->
11 | p.push c if p.indexOf(c) < 0
12 | p
13 | , []
14 |
15 | data = [ data ] unless data instanceof Array
16 | vals = []
17 | lookups = []
18 |
19 | for d in data
20 | if objectValidate d
21 | if typeof value is "function"
22 | val = value d
23 | else if vars
24 | val = fetchValue vars, d, value
25 | else
26 | val = d[value]
27 | lookup = if [ "number", "string" ].indexOf(typeof val) >= 0 then val else JSON.stringify(val)
28 | if lookup isnt undefined and lookups.indexOf(lookup) < 0
29 | vals.push val
30 | lookups.push lookup
31 |
32 | vals.sort (a, b) -> a - b
33 |
--------------------------------------------------------------------------------
/src/viz/methods/tooltip.coffee:
--------------------------------------------------------------------------------
1 | family = require "../../core/methods/font/family.coffee"
2 | transform = require "../../core/methods/font/transform.coffee"
3 |
4 | module.exports =
5 | accepted: [false, Array, Function, Object, String]
6 | anchor: "top center"
7 | background: "#ffffff"
8 | children:
9 | accepted: [Boolean]
10 | value: true
11 | connections:
12 | accepted: [Boolean]
13 | value: true
14 | curtain:
15 | color: "#ffffff"
16 | opacity: 0.8
17 | deprecates: "tooltip_info"
18 | font:
19 | color: "#444"
20 | family: family()
21 | size: 12
22 | transform: transform()
23 | weight: 200
24 | html:
25 | accepted: [false, Function, String]
26 | deprecates: "click_function"
27 | value: false
28 | large: 250
29 | share:
30 | accepted: [Boolean]
31 | value: true
32 | size:
33 | accepted: [Boolean]
34 | value: true
35 | small: 225
36 | value: false
37 |
--------------------------------------------------------------------------------
/src/core/fetch/sort.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "./value.js"
2 | fetchColor = require "./color.coffee"
3 | fetchText = require "./text.js"
4 |
5 | module.exports = (vars, d, keys, colors, depth) ->
6 |
7 | keys = [keys] unless keys instanceof Array
8 | colors = [colors] unless colors instanceof Array
9 | depth = vars.id.nesting.indexOf(depth) if vars and depth isnt undefined and typeof depth isnt "number"
10 |
11 | obj = {}
12 | i = 0
13 |
14 | while i < keys.length
15 |
16 | key = keys[i]
17 |
18 | if vars
19 | if colors.indexOf(key) >= 0
20 | value = fetchColor vars, d, depth
21 | else
22 | value = if key is vars.text.value then fetchText vars, d, depth else fetchValue vars, d, key, depth
23 | else
24 | value = d[key]
25 |
26 | value = value[0] if value instanceof Array
27 | value = if typeof value is "string" then value.toLowerCase() else value
28 |
29 | obj[key] = value
30 |
31 | i++
32 |
33 | obj
34 |
--------------------------------------------------------------------------------
/src/viz/methods/color.coffee:
--------------------------------------------------------------------------------
1 | filter = require("../../core/methods/filter.coffee")
2 | scale = require("../../color/scale.coffee")
3 |
4 | module.exports =
5 | accepted: [false, Array, Function, Object, String]
6 | deprecates: "color_var"
7 | focus: "#444444"
8 | heatmap: ["#282F6B", "#419391", "#AFD5E8", "#EACE3F", "#B35C1E", "#B22200"]
9 | missing: "#eeeeee"
10 | mute: filter true
11 | primary: "#d74b03"
12 | range: ["#B22200", "#FFEE8D", "#759143"]
13 | scale:
14 | accepted: [Array, Function, "d3plus", "category10", "category20", "category20b", "category20c"]
15 | process: (value) ->
16 | if value instanceof Array
17 | d3.scale.ordinal().range value
18 | else if value is "d3plus"
19 | scale
20 | else if typeof value is "string"
21 | d3.scale[value]()
22 | else
23 | value
24 | value: "d3plus"
25 | solo: filter true
26 | secondary: "#e5b3bb"
27 | value: false
28 |
--------------------------------------------------------------------------------
/src/string/format.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | // Formats a string similar to Python's "format"
3 | //------------------------------------------------------------------------------
4 | module.exports = function() {
5 |
6 | var args = Array.prototype.slice.call(arguments)
7 | , str = args.shift()
8 |
9 | str.unkeyed_index = 0;
10 | return str.replace(/\{(\w*)\}/g, function(match, key) {
11 | if (key === '') {
12 | key = str.unkeyed_index;
13 | str.unkeyed_index++
14 | }
15 | if (key == +key) {
16 | return args[key] !== 'undefined'
17 | ? args[key]
18 | : match;
19 | } else {
20 | for (var i = 0; i < args.length; i++) {
21 | if (typeof args[i] === 'object' && typeof args[i][key] !== 'undefined') {
22 | return args[i][key];
23 | }
24 | }
25 | return match;
26 | }
27 | }.bind(str));
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/textwrap/helpers/getDimensions.coffee:
--------------------------------------------------------------------------------
1 | # Checks width and height, and gets it if needed.
2 | module.exports = (vars) ->
3 |
4 | if not vars.width.value or not vars.height.value
5 |
6 | parent = d3.select vars.container.value.node().parentNode
7 | rect = parent.select "rect"
8 | circle = parent.select "circle"
9 |
10 | unless rect.empty()
11 | unless vars.width.value
12 | width = rect.attr "width" or rect.style "width"
13 | vars.self.width parseFloat width, 10
14 | unless vars.height.value
15 | height = rect.attr "height" or rect.style "height"
16 | vars.self.height parseFloat height, 10
17 | else unless circle.empty()
18 | radius = circle.attr "r"
19 | vars.self.width parseFloat radius * 2, 10 unless vars.width.value
20 | vars.self.height parseFloat radius * 2, 10 unless vars.height.value
21 | else
22 | vars.self.width 500 unless vars.width.value
23 | vars.self.height 500 unless vars.height.value
24 |
25 | return
26 |
--------------------------------------------------------------------------------
/src/textwrap/helpers/foreign.coffee:
--------------------------------------------------------------------------------
1 | # Flows the text as a foreign element.
2 | module.exports = (vars) ->
3 |
4 | text = vars.container.value
5 | family = text.attr("font-family") or text.style("font-family")
6 | anchor = text.attr("text-anchor") or text.style("text-anchor")
7 | color = text.attr("fill") or text.style("fill")
8 | opacity = text.attr("opacity") or text.style("opacity")
9 | anchor = if anchor is "end" then "right" else (if anchor is "middle" then "center" else "left")
10 |
11 | d3.select(text.node().parentNode).append "foreignObject"
12 | .attr "width" , vars.width.value + "px"
13 | .attr "height", vars.height.value + "px"
14 | .attr "x" , "0px"
15 | .attr "y" , "0px"
16 | .append "xhtml:div"
17 | .style "font-family", family
18 | .style "font-size" , vars.size.value[1]+"px"
19 | .style "color" , color
20 | .style "text-align" , anchor
21 | .style "opacity" , opacity
22 | .text vars.text.current
23 |
24 | return
25 |
--------------------------------------------------------------------------------
/src/data/mad.coffee:
--------------------------------------------------------------------------------
1 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | # Finds outliers in 1-dim data by computing the median absolute deviation for each point
3 | # See:
4 | # http://eurekastatistics.com/using-the-median-absolute-deviation-to-find-outliers
5 | # http://en.wikipedia.org/wiki/Median_absolute_deviation
6 | #------------------------------------------------------------------------------
7 |
8 | # points is an array of numbers (1-dim points).
9 |
10 | # Returns an array of [index, deviation] tuples, where index is the index of the point in the original array
11 | # and deviation is the distance from the median in MAD units for that point. The array is ordered by
12 | # descreasing order of deviation so the outliers are in the beginning of the array.
13 | module.exports = (points) ->
14 |
15 | median = d3.median points
16 | mad = d3.median points.map (p) -> Math.abs(p-median)
17 | result = points.map (p, i) -> [i, Math.abs(p-median)/mad]
18 |
19 | result.sort (a,b) -> b[1] - a[1]
20 |
--------------------------------------------------------------------------------
/src/object/merge.coffee:
--------------------------------------------------------------------------------
1 | d3selection = require "../util/d3selection.coffee"
2 | validate = require "./validate.coffee"
3 |
4 | ###*
5 | # Given any two objects, this method will merge the two objects together, returning a new third object. The values of the second object always overwrite the first.
6 | # @method d3plus.object.merge
7 | # @for d3plus.object
8 | # @param obj1 {Object} The primary object.
9 | # @param obj2 {Object} The secondary object to merge into the first.
10 | # @return {Object}
11 | ###
12 | module.exports = (obj1, obj2) ->
13 |
14 | copyObject = (obj, ret) ->
15 | for a of obj
16 | unless typeof obj[a] is "undefined"
17 | if validate(obj[a])
18 | ret[a] = {} if typeof ret[a] isnt "object"
19 | copyObject obj[a], ret[a]
20 | else if not d3selection(obj[a]) and obj[a] instanceof Array
21 | ret[a] = obj[a].slice(0)
22 | else
23 | ret[a] = obj[a]
24 |
25 | obj3 = {}
26 |
27 | copyObject obj1, obj3 if obj1
28 | copyObject obj2, obj3 if obj2
29 |
30 | obj3
31 |
--------------------------------------------------------------------------------
/src/form/methods/ui.coffee:
--------------------------------------------------------------------------------
1 | family = require "../../core/methods/font/family.coffee"
2 | align = require "../../core/methods/font/align.coffee"
3 | decoration = require "../../core/methods/font/decoration.coffee"
4 | transform = require "../../core/methods/font/transform.coffee"
5 |
6 | module.exports =
7 | align: align("center")
8 | border: 1
9 | color:
10 | primary:
11 | process: (value, vars) ->
12 | primary = @value
13 | secondary = vars.ui.color.secondary.value
14 | vars.ui.color.secondary.value = d3.rgb(value).darker(2).toString() if not secondary or secondary is d3.rgb(primary).darker(2).toString()
15 | value
16 | value: "#ffffff"
17 | secondary:
18 | value: false
19 | display:
20 | acceped: ["block", "inline-block"]
21 | value: "inline-block"
22 | font:
23 | align: align("center")
24 | color: "#444"
25 | decoration: decoration()
26 | family: family()
27 | size: 11
28 | transform: transform()
29 | weight: 200
30 | margin: 5
31 | padding: 5
32 |
--------------------------------------------------------------------------------
/src/viz/types/geo_map.coffee:
--------------------------------------------------------------------------------
1 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | # Geo Map
3 | #------------------------------------------------------------------------------
4 | geo_map = (vars) ->
5 |
6 | topojson.presimplify vars.coords.value
7 |
8 | coords = vars.coords.value
9 | key = d3.keys(coords.objects)[0]
10 | topo = topojson.feature coords, coords.objects[key]
11 | features = topo.features
12 |
13 | solo = vars.coords.solo.value
14 | mute = vars.coords.mute.value
15 |
16 | features = features.filter (f) ->
17 | f[vars.id.value] = f.id
18 | if solo.length then solo.indexOf(f.id) >= 0 else if mute.length then mute.indexOf(f.id) < 0 else true
19 |
20 | features
21 |
22 |
23 | # Visualization Settings and Helper Functions
24 | geo_map.libs = ["topojson"]
25 | geo_map.nesting = false
26 | geo_map.requirements = ["color", "coords"]
27 | geo_map.scale = 1
28 | geo_map.shapes = ["coordinates"]
29 | geo_map.tooltip = "follow"
30 | geo_map.zoom = true
31 |
32 | module.exports = geo_map
33 |
--------------------------------------------------------------------------------
/gulp/rebuild.coffee:
--------------------------------------------------------------------------------
1 | browserify = require "browserify"
2 | error = require "./error.coffee"
3 | gulp = require "gulp"
4 | livereload = require "gulp-livereload"
5 | lr = require("tiny-lr")()
6 | notify = require "gulp-notify"
7 | source = require "vinyl-source-stream"
8 | timer = require "gulp-duration"
9 | watchify = require "watchify"
10 |
11 | gulp.task "rebuild", ->
12 |
13 | # fileList = glob.sync files, {nosort: true}
14 |
15 | bundler = browserify watchify.args
16 | .add "./src/init.coffee"
17 | .transform "coffeeify"
18 |
19 | bundler = watchify(bundler)
20 |
21 | rebundle = ->
22 | bundler.bundle()
23 | .on("error", notify.onError(error))
24 | .pipe(source("d3plus.js"))
25 | .pipe(gulp.dest("./"))
26 | .pipe(timer("Total Build Time"))
27 | .pipe(notify(
28 | title: "D3plus"
29 | message: "New Build Compiled"
30 | icon: __dirname + "/../icon.png"
31 | ))
32 | .pipe(livereload(lr))
33 | .on "error", notify.onError(error)
34 |
35 | bundler.on "update", rebundle
36 |
37 | rebundle()
38 |
--------------------------------------------------------------------------------
/src/geom/path2poly.coffee:
--------------------------------------------------------------------------------
1 | offset = require "../geom/offset.coffee"
2 |
3 | module.exports = (path) ->
4 |
5 | path = path.slice(1).slice(0,-1).split(/L|A/)
6 | poly = []
7 |
8 | for p in path
9 | p = p.split(" ")
10 | if p.length is 1
11 | poly.push p[0].split(",").map (d) -> parseFloat d
12 | else
13 | prev = poly[poly.length-1]
14 | last = p.pop().split(",").map (d) -> parseFloat d
15 | radius = parseFloat p.shift().split(",")[0]
16 | width = Math.sqrt( Math.pow(last[0]-prev[0],2) + Math.pow(last[1]-prev[1],2) )
17 | angle = Math.acos((radius*radius+radius*radius-width*width)/(2*radius*radius))
18 | obtuse = p[1].split(",")[0] is "1"
19 | angle = Math.PI*2 - angle if obtuse
20 | length = angle/(Math.PI*2) * (radius*Math.PI*2)
21 | segments = length/5
22 | start = Math.atan2(-prev[1],-prev[0]) - Math.PI
23 | step = angle/segments
24 | i = step
25 | while i < angle
26 | o = offset start + i, radius
27 | poly.push [o.x,o.y]
28 | i += step
29 | poly.push last
30 |
31 | poly
32 |
--------------------------------------------------------------------------------
/src/form/methods/icon.coffee:
--------------------------------------------------------------------------------
1 | process = require "../../core/methods/process/icon.coffee"
2 |
3 | module.exports =
4 | accepted: [false, Array, Function, Object, String]
5 | back:
6 | accepted: [false, String]
7 | fallback: "❮"
8 | opacity: 1
9 | process: process
10 | rotate: 0
11 | value: "fa-angle-left"
12 | button:
13 | accepted: [false, String]
14 | fallback: false
15 | opacity: 1
16 | process: process
17 | rotate: 0
18 | value: false
19 | drop:
20 | accepted: [false, String]
21 | fallback: "❯"
22 | opacity: 1
23 | process: process
24 | rotate: 0
25 | value: "fa-angle-down"
26 | next:
27 | accepted: [false, String]
28 | fallback: "❯"
29 | opacity: 1
30 | process: process
31 | rotate: 0
32 | value: "fa-angle-right"
33 | select:
34 | accepted: [false, String]
35 | fallback: "✓"
36 | opacity: 1
37 | process: process
38 | rotate: 0
39 | value: "fa-check"
40 | style:
41 | accepted: [Object, String]
42 | value: "default"
43 | value: "icon"
44 |
--------------------------------------------------------------------------------
/src/viz/helpers/types/run.coffee:
--------------------------------------------------------------------------------
1 | print = require "../../../core/console/print.coffee"
2 |
3 | module.exports = (vars) ->
4 |
5 | # Set vars.group to the app's specific group element
6 | vars.group = vars.g.apps[vars.type.value]
7 |
8 | # Reset mouse events for the app to use
9 | vars.mouse = {}
10 |
11 | visualization = vars.types[vars.type.value]
12 | requirements = visualization.requirements or []
13 | dataRequired = requirements.indexOf("data") >= 0
14 | drawable = not dataRequired or (dataRequired and vars.data.viz.length)
15 |
16 | if not vars.internal_error and drawable
17 | app = vars.format.locale.value.visualization[vars.type.value]
18 | print.time "running " + app if vars.dev.value
19 | returned = visualization(vars)
20 | print.timeEnd "running " + app if vars.dev.value
21 | else
22 | returned = null
23 |
24 | vars.returned =
25 | nodes: []
26 | edges: null
27 |
28 | if returned instanceof Array
29 | vars.returned.nodes = returned
30 | else if returned
31 | vars.returned.nodes = returned.nodes if returned.nodes
32 | vars.returned.edges = returned.edges if returned.edges
33 |
34 | return
35 |
--------------------------------------------------------------------------------
/src/viz/helpers/zoom/labels.js:
--------------------------------------------------------------------------------
1 | var print = require("../../../core/console/print.coffee")
2 |
3 | // Sets label opacity based on zoom
4 | module.exports = function(vars) {
5 |
6 | var max_scale = vars.zoom.behavior.scaleExtent()[1]
7 |
8 | if ( vars.dev.value ) print.time("determining label visibility")
9 |
10 | if (vars.draw.timing) {
11 |
12 | vars.g.viz.selectAll("text.d3plus_label")
13 | .transition().duration(vars.draw.timing)
14 | .attr("opacity",function(d){
15 | if (!d) var d = {"scale": max_scale}
16 | var size = parseFloat(d3.select(this).attr("font-size"),10)
17 | d.visible = size/d.scale*vars.zoom.scale >= 7
18 | return d.visible ? 1 : 0
19 | })
20 |
21 | }
22 | else {
23 |
24 | vars.g.viz.selectAll("text.d3plus_label")
25 | .attr("opacity",function(d){
26 | if (!d) var d = {"scale": max_scale}
27 | var size = parseFloat(d3.select(this).attr("font-size"),10)
28 | d.visible = size/d.scale*vars.zoom.scale >= 7
29 | return d.visible ? 1 : 0
30 | })
31 |
32 | }
33 |
34 | if ( vars.dev.value ) print.timeEnd("determining label visibility")
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/element.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | // Overrides keyboard behavior of the original input element.
3 | //------------------------------------------------------------------------------
4 | module.exports = function ( vars ) {
5 |
6 | if (vars.data.element.value) {
7 |
8 | vars.data.element.value.on("focus."+vars.container.id,function(){
9 | vars.self.draw({"update":false}).draw()
10 | })
11 |
12 | vars.data.element.value.on("blur."+vars.container.id,function(){
13 |
14 | var search = vars.search.enabled
15 | ? d3.event.relatedTarget != vars.container.value.select("input").node()
16 | : true
17 |
18 | if (search) {
19 | vars.self.draw({"update":false}).draw()
20 | }
21 |
22 | })
23 |
24 | vars.data.element.value.on("change."+vars.container.id,function(){
25 | vars.self.focus(this.value).draw()
26 | })
27 |
28 | vars.data.element.value.on("keydown.cancel_"+vars.container.id,function(){
29 | var key = d3.event.keyCode
30 | if (key != 9) {
31 | d3.event.preventDefault()
32 | }
33 | })
34 |
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/viz/methods/ui.coffee:
--------------------------------------------------------------------------------
1 | family = require "../../core/methods/font/family.coffee"
2 | align = require "../../core/methods/font/align.coffee"
3 | decoration = require "../../core/methods/font/decoration.coffee"
4 | transform = require "../../core/methods/font/transform.coffee"
5 |
6 | module.exports =
7 | accepted: [Array, Boolean]
8 | align: align("center")
9 | border: 1
10 | color:
11 | primary:
12 | process: (value, vars) ->
13 | primary = @value
14 | secondary = vars.ui.color.secondary.value
15 | vars.ui.color.secondary.value = d3.rgb(value).darker(2).toString() if not secondary or secondary is d3.rgb(primary).darker(2).toString()
16 | value
17 | value: "#ffffff"
18 | secondary:
19 | value: false
20 | display:
21 | acceped: ["block", "inline-block"]
22 | value: "inline-block"
23 | font:
24 | align: "center"
25 | color: "#444"
26 | decoration: decoration()
27 | family: family()
28 | size: 11
29 | transform: transform()
30 | weight: 200
31 | margin: 5
32 | padding: 5
33 | position:
34 | accepted: ["top", "right", "bottom", "left"]
35 | value: "bottom"
36 | value: false
37 |
--------------------------------------------------------------------------------
/src/core/data/keys.js:
--------------------------------------------------------------------------------
1 | var validObject = require("../../object/validate.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Get Key Types from Data
4 | //------------------------------------------------------------------------------
5 | module.exports = function( vars , type ) {
6 |
7 | if ( vars.dev.value ) {
8 | var timerString = type + " key analysis"
9 | console.time( timerString )
10 | }
11 |
12 | vars[type].keys = {}
13 |
14 | function get_keys( arr ) {
15 | if (arr instanceof Array) {
16 | arr.forEach(function(d) {
17 | get_keys( d )
18 | })
19 | }
20 | else if ( validObject(arr) ) {
21 | for (var d in arr) {
22 | if ( validObject(arr[d]) ) {
23 | get_keys( arr[d] )
24 | }
25 | else if (!(d in vars[type].keys) && d in arr) {
26 | vars[type].keys[d] = typeof arr[d]
27 | }
28 | }
29 | }
30 | }
31 |
32 | if ( validObject(vars[type].value) ) {
33 | for ( var a in vars[type].value ) {
34 | get_keys(vars[type].value[a])
35 | }
36 | }
37 | else {
38 | get_keys(vars[type].value)
39 | }
40 |
41 | if ( vars.dev.value ) console.time( timerString )
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/form/types/button/functions/mouseevents.js:
--------------------------------------------------------------------------------
1 | var events = require("../../../../client/pointer.coffee"),
2 | ie = require("../../../../client/ie.js")
3 |
4 | module.exports = function ( elem , vars , color ) {
5 |
6 | elem
7 | .on(events.over,function(d,i){
8 |
9 | vars.self.hover(d[vars.id.value])
10 |
11 | if ( ie || !vars.draw.timing ) {
12 |
13 | d3.select(this).style("cursor","pointer")
14 | .call( color , vars )
15 |
16 | }
17 | else {
18 |
19 | d3.select(this).style("cursor","pointer")
20 | .transition().duration(vars.timing.mouseevents)
21 | .call( color , vars )
22 | }
23 |
24 | })
25 | .on(events.out,function(d){
26 |
27 | vars.self.hover(false)
28 |
29 | if ( ie || !vars.draw.timing ) {
30 | d3.select(this).style("cursor","auto")
31 | .call( color , vars )
32 | }
33 | else {
34 | d3.select(this).style("cursor","auto")
35 | .transition().duration(vars.timing.mouseevents)
36 | .call( color , vars )
37 | }
38 |
39 | })
40 | .on(events.click,function(d){
41 |
42 | if ( vars.id.value in d ) {
43 |
44 | vars.self.focus(d[vars.id.value]).draw()
45 |
46 | }
47 |
48 | })
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/textwrap/textwrap.coffee:
--------------------------------------------------------------------------------
1 | attach = require "../core/methods/attach.coffee"
2 | dimensions = require "./helpers/getDimensions.coffee"
3 | size = require "./helpers/getSize.coffee"
4 | text = require "./helpers/getText.coffee"
5 | wrap = require "./helpers/wrap.coffee"
6 |
7 | # Word wraps SVG text
8 | module.exports = ->
9 |
10 | # Main drawing function
11 | vars =
12 | self: (selection) ->
13 |
14 | selection.each ->
15 |
16 | dimensions vars
17 | size vars
18 |
19 | if vars.size.value[0] <= vars.height.value
20 | text vars
21 | wrap vars
22 |
23 | return
24 |
25 | vars.self
26 |
27 |
28 | # Define methods and expose public variables.
29 | attach vars,
30 | container: require "./methods/container.coffee"
31 | dev: require "./methods/dev.coffee"
32 | draw: require "./methods/draw.coffee"
33 | format: require "./methods/format.coffee"
34 | height: require "./methods/height.coffee"
35 | resize: require "./methods/resize.coffee"
36 | text: require "./methods/text.coffee"
37 | shape: require "./methods/shape.coffee"
38 | size: require "./methods/size.coffee"
39 | width: require "./methods/width.coffee"
40 |
41 | vars.self
42 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/color.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../../core/fetch/value.js"
2 | fetchColor = require "../../../core/fetch/color.coffee"
3 | lighter = require "../../../color/lighter.coffee"
4 |
5 | # Returns the correct fill color for a node
6 | module.exports = (d, vars) ->
7 |
8 | shape = d.d3plus.shape or vars.shape.value
9 |
10 | if vars.shape.value is "line" and shape isnt "circle"
11 | return "none"
12 | else if vars.shape.value is "area" or shape is "active" or vars.shape.value is "line"
13 | return fetchColor(vars, d)
14 | else if shape is "temp"
15 | return "url(#d3plus_hatch_" + d.d3plus.id + ")"
16 | else if d.d3plus.static
17 | return lighter fetchColor(vars, d), .75
18 |
19 | active = if vars.active.value then fetchValue(vars, d, vars.active.value) else d.d3plus.active
20 | temp = if vars.temp.value then fetchValue(vars, d, vars.temp.value) else d.d3plus.temp
21 | total = if vars.total.value then fetchValue(vars, d, vars.total.value) else d.d3plus.total
22 |
23 | if (not vars.active.value and not vars.temp.value) or active is true or (active and total and active is total and not temp) or (active and not total)
24 | fetchColor vars, d
25 | else if vars.active.spotlight.value
26 | "#eee"
27 | else
28 | lighter fetchColor(vars, d), .75
29 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/window.js:
--------------------------------------------------------------------------------
1 | var child = require("../../../../util/child.coffee")
2 |
3 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 | // Recursive function that applies a click event to all parent windows that
5 | // will close the dropdown if it is open.
6 | //------------------------------------------------------------------------------
7 | var windowEvents = function ( vars , elem ) {
8 |
9 | if ( elem === undefined ) {
10 | var elem = window
11 | }
12 |
13 | d3.select(elem).on("click."+vars.container.id,function(){
14 |
15 | var element = d3.event.target || d3.event.toElement
16 | , parent = element.parentNode
17 |
18 | if ( parent && ["d3plus_node","d3plus_drop_title"].indexOf(parent.className) >= 0 ) {
19 | element = parent.parentNode
20 | }
21 |
22 | if (element && parent && !child(vars.container.ui, element) && vars.open.value) {
23 | vars.self.open(!vars.open.value).draw()
24 | }
25 |
26 | })
27 |
28 | try {
29 | var same_origin = window.parent.location.host === window.location.host;
30 | }
31 | catch (e) {
32 | var same_origin = false
33 | }
34 |
35 | if (same_origin) {
36 | if (elem.self !== window.top) {
37 | windowEvents( vars , elem.parent )
38 | }
39 | }
40 |
41 | }
42 |
43 | module.exports = windowEvents
44 |
--------------------------------------------------------------------------------
/src/string/strip.js:
--------------------------------------------------------------------------------
1 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | // Removes all non ASCII characters
3 | //------------------------------------------------------------------------------
4 | module.exports = function(str) {
5 |
6 | var removed = [ "!","@","#","$","%","^","&","*","(",")",
7 | "[","]","{","}",".",",","/","\\","|",
8 | "'","\"",";",":","<",">","?","=","+"]
9 |
10 | var diacritics = [
11 | [/[\300-\306]/g, "A"],
12 | [/[\340-\346]/g, "a"],
13 | [/[\310-\313]/g, "E"],
14 | [/[\350-\353]/g, "e"],
15 | [/[\314-\317]/g, "I"],
16 | [/[\354-\357]/g, "i"],
17 | [/[\322-\330]/g, "O"],
18 | [/[\362-\370]/g, "o"],
19 | [/[\331-\334]/g, "U"],
20 | [/[\371-\374]/g, "u"],
21 | [/[\321]/g, "N"],
22 | [/[\361]/g, "n"],
23 | [/[\307]/g, "C"],
24 | [/[\347]/g, "c"],
25 | ];
26 |
27 | str += ""
28 |
29 | return ""+str.replace(/[^A-Za-z0-9\-_]/g, function(chr) {
30 |
31 | if (" " == chr) {
32 | return "_"
33 | }
34 | else if (removed.indexOf(chr) >= 0) {
35 | return ""
36 | }
37 |
38 | var ret = ""
39 |
40 | for ( var d in diacritics ) {
41 |
42 | if (diacritics[d][0].test(chr)) {
43 | ret = diacritics[d][1]
44 | break;
45 | }
46 |
47 | }
48 |
49 | return ret;
50 |
51 | });
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/gulp/compile.coffee:
--------------------------------------------------------------------------------
1 | browserify = require "browserify"
2 | error = require "./error.coffee"
3 | es = require "event-stream"
4 | gulp = require "gulp"
5 | notify = require "gulp-notify"
6 | rename = require "gulp-rename"
7 | source = require "vinyl-source-stream"
8 | streamify = require "gulp-streamify"
9 | timer = require "gulp-duration"
10 | uglify = require "gulp-uglify"
11 |
12 | gulp.task "compile", ->
13 |
14 | normal = browserify(["./src/init.coffee"])
15 | .transform("coffeeify")
16 | .bundle()
17 | .on("error", notify.onError(error))
18 | .pipe(source("d3plus.js"))
19 | .pipe(gulp.dest("./"))
20 | .pipe(rename("d3plus.min.js"))
21 | .pipe(streamify(uglify()))
22 | .pipe(gulp.dest("./"))
23 | .on("error", notify.onError(error))
24 |
25 | full = browserify(["./src/libs.coffee", "./src/init.coffee"])
26 | .transform("coffeeify")
27 | .bundle()
28 | .on("error", notify.onError(error))
29 | .pipe(source("d3plus.full.js"))
30 | .pipe(gulp.dest("./"))
31 | .pipe(rename("d3plus.full.min.js"))
32 | .pipe(streamify(uglify()))
33 | .pipe(gulp.dest("./"))
34 | .pipe(timer("Total Build Time"))
35 | .pipe(notify(
36 | title: "D3plus"
37 | message: "Production Builds Compiled"
38 | icon: __dirname + "/../icon.png"
39 | ))
40 | .on("error", notify.onError(error))
41 |
42 | es.merge normal, full
43 |
--------------------------------------------------------------------------------
/src/viz/methods/margin.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Number, Object, String]
3 | process: (value) ->
4 |
5 | self = this
6 | sides = ["top", "right", "bottom", "left"]
7 |
8 | value = self.value if value is undefined
9 | userValue = value
10 |
11 | if typeof value is "string"
12 |
13 | value = value.split(" ")
14 |
15 | for v, i in value
16 | value[i] = parseFloat(v, 10)
17 |
18 | if value.length is 1
19 | value = value[0]
20 | else if value.length is 2
21 | value =
22 | top: value[0]
23 | right: value[1]
24 | bottom: value[0]
25 | left: value[1]
26 | else if value.length is 3
27 | value =
28 | top: value[0]
29 | right: value[1]
30 | bottom: value[2]
31 | left: value[1]
32 | else if value.length is 4
33 | value =
34 | top: value[0]
35 | right: value[1]
36 | bottom: value[2]
37 | left: value[3]
38 | else
39 | value = 0
40 |
41 | if typeof value is "number"
42 | for side in sides
43 | self[side] = value
44 | else
45 | for side of value
46 | sideIndex = sides.indexOf(side)
47 | if sideIndex >= 0
48 | sides.splice sideIndex, 1
49 | self[side] = value[side]
50 | for k in sides
51 | self[k] = 0
52 |
53 | userValue
54 | value: 0
55 |
--------------------------------------------------------------------------------
/src/core/parse/nodes.js:
--------------------------------------------------------------------------------
1 | var print = require("../console/print.coffee")
2 |
3 | // Calculates node positions, if needed for network.
4 | module.exports = function(vars) {
5 |
6 | if ( vars.dev.value ) {
7 | var timerString = "analyzing node positions"
8 | print.time( timerString )
9 | }
10 |
11 | var set = vars.nodes.value.filter(function(n){
12 | return typeof n.x == "number" && typeof n.y == "number"
13 | }).length
14 |
15 | if (set == vars.nodes.value.length) {
16 | vars.nodes.positions = true
17 | }
18 | else {
19 |
20 | var force = d3.layout.force()
21 | .size([vars.width.viz,vars.height.viz])
22 | .nodes(vars.nodes.value)
23 | .links(vars.edges.value)
24 |
25 | var strength = vars.edges.strength.value
26 | if (strength) {
27 | if (typeof strength === "string") {
28 | force.linkStrength(function(e){
29 | return e[strength]
30 | })
31 | }
32 | else {
33 | force.linkStrength(strength)
34 | }
35 | }
36 |
37 | var iterations = 50,
38 | threshold = 0.01;
39 |
40 | force.start(); // Defaults to alpha = 0.1
41 | for (var i = iterations; i > 0; --i) {
42 | force.tick();
43 | if(force.alpha() < threshold) {
44 | break;
45 | }
46 | }
47 | force.stop();
48 |
49 | vars.nodes.positions = true
50 |
51 | }
52 |
53 | if ( vars.dev.value ) print.timeEnd( timerString )
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/form/methods/margin.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | accepted: [Number, Object, String]
3 | process: (value) ->
4 |
5 | self = this
6 | sides = ["top", "right", "bottom", "left"]
7 |
8 | value = self.value if value is undefined
9 | userValue = value
10 |
11 | if typeof value is "string"
12 |
13 | value = value.split(" ")
14 |
15 | for v, i in value
16 | value[i] = parseFloat(v, 10)
17 |
18 | if value.length is 1
19 | value = value[0]
20 | else if value.length is 2
21 | value =
22 | top: value[0]
23 | right: value[1]
24 | bottom: value[0]
25 | left: value[1]
26 | else if value.length is 3
27 | value =
28 | top: value[0]
29 | right: value[1]
30 | bottom: value[2]
31 | left: value[1]
32 | else if value.length is 4
33 | value =
34 | top: value[0]
35 | right: value[1]
36 | bottom: value[2]
37 | left: value[3]
38 | else
39 | value = 0
40 |
41 | if typeof value is "number"
42 | for side in sides
43 | self[side] = value
44 | else
45 | for side of value
46 | sideIndex = sides.indexOf(side)
47 | if sideIndex >= 0
48 | sides.splice sideIndex, 1
49 | self[side] = value[side]
50 | for k in sides
51 | self[k] = 0
52 |
53 | userValue
54 | value: 0
55 |
--------------------------------------------------------------------------------
/src/core/methods/rejected.coffee:
--------------------------------------------------------------------------------
1 | contains = require "../../array/contains.coffee"
2 | format = require "../../string/format.js"
3 | list = require "../../string/list.coffee"
4 | print = require "../console/print.coffee"
5 |
6 | module.exports = (vars, accepted, value, method, text) ->
7 |
8 | accepted = accepted(vars) if typeof accepted is "function"
9 | accepted = [accepted] if accepted not instanceof Array
10 |
11 | # Check to see if the given value is allowed.
12 | allowed = contains accepted, value
13 |
14 | # If value is not allowed, show an error message in the console.
15 | if allowed is false and value isnt undefined
16 |
17 | recs = []
18 | val = JSON.stringify(value)
19 | val = "\"" + val + "\"" if typeof value isnt "string"
20 |
21 | for a in accepted
22 | if typeof a is "string"
23 | recs.push "\"" + a + "\""
24 | else if typeof a is "function"
25 | recs.push a.toString().split("()")[0].substring(9)
26 | else
27 | recs.push a.toString()
28 |
29 | recs = list recs, vars.format.locale.value.ui.or
30 |
31 | if vars.type and ["mode", "shape"].indexOf(method) >= 0
32 | str = vars.format.locale.value.error.accepted
33 | app = vars.format.locale.value.visualization[vars.type.value] || vars.type.value
34 | print.warning format(str, val, method, app, recs), method
35 | else
36 | str = vars.format.locale.value.dev.accepted
37 | print.warning format(str, val, text, recs), method
38 |
39 | not allowed
40 |
--------------------------------------------------------------------------------
/src/viz/types/line.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../core/fetch/value.js"
2 | graph = require "./helpers/graph/draw.coffee"
3 | dataTicks = require "./helpers/graph/dataTicks.coffee"
4 | nest = require "./helpers/graph/nest.coffee"
5 | stack = require "./helpers/graph/stack.coffee"
6 |
7 | # Line Plot
8 | line = (vars) ->
9 |
10 | graph vars,
11 | buffer: vars.axes.opposite
12 | mouse: true
13 |
14 | data = nest vars
15 |
16 | # Assign x and y to each data point
17 | for point in data
18 | for d in point.values
19 | d.d3plus.x = vars.x.scale.viz fetchValue(vars, d, vars.x.value)
20 | d.d3plus.x += vars.axes.margin.left
21 |
22 | d.d3plus.y = vars.y.scale.viz fetchValue(vars, d, vars.y.value)
23 | d.d3plus.y += vars.axes.margin.top
24 |
25 | d.d3plus.r = 2
26 |
27 | dataTicks vars
28 |
29 | if vars.axes.stacked then stack vars, data else data
30 |
31 | # Visualization Settings and Helper Functions
32 | line.requirements = ["data", "x", "y"]
33 | line.setup = (vars) ->
34 | vars.self.x scale: "discrete" unless vars.axes.discrete
35 | y = vars[vars.axes.opposite].value
36 | size = vars.size
37 | if (not y.value and size.value) or (size.changed and size.previous is y.value)
38 | vars.self[vars.axes.opposite] size.value
39 | else if (not size.value and y.value) or (y.changed and y.previous is size.value)
40 | vars.self.size y.value
41 | return
42 | line.shapes = ["line"]
43 | line.tooltip = "static"
44 |
45 | module.exports = line
46 |
--------------------------------------------------------------------------------
/src/viz/types/helpers/graph/stack.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../../../core/fetch/value.js"
2 |
3 | module.exports = (vars, data) ->
4 |
5 | stacked = vars.axes.stacked
6 | flip = vars[stacked].scale.viz 0
7 | scale = vars[stacked].scale.value
8 | opposite = if stacked is "x" then "y" else "x"
9 | margin = if stacked is "y" then vars.axes.margin.top else vars.axes.margin.left
10 | offset = if scale is "share" then "expand" else "zero"
11 |
12 | stack = d3.layout.stack()
13 | .values (d) -> d.values
14 | .offset offset
15 | .x (d) -> d.d3plus[opposite]
16 | .y (d) -> flip - vars[stacked].scale.viz fetchValue vars, d, vars[stacked].value
17 | .out (d, y0, y) ->
18 |
19 | value = fetchValue vars, d, vars[stacked].value
20 | negative = value < 0
21 |
22 | if scale is "share"
23 | d.d3plus[stacked+"0"] = (1 - y0) * flip
24 | d.d3plus[stacked] = d.d3plus[stacked+"0"] - (y * flip)
25 | else
26 | d.d3plus[stacked+"0"] = flip - y0
27 | d.d3plus[stacked] = d.d3plus[stacked+"0"] - y
28 |
29 | d.d3plus[stacked] += margin
30 | d.d3plus[stacked+"0"] += margin
31 |
32 | positiveData = data.filter (d) ->
33 | fetchValue(vars, d, vars[stacked].value) > 0
34 | negativeData = data.filter (d) ->
35 | fetchValue(vars, d, vars[stacked].value) < 0
36 |
37 | positiveData = stack positiveData if positiveData.length
38 | negativeData = stack negativeData if negativeData.length
39 |
40 | positiveData.concat(negativeData)
41 |
--------------------------------------------------------------------------------
/src/font/validate.coffee:
--------------------------------------------------------------------------------
1 | fontTester = require("../core/font/tester.coffee")
2 |
3 | # Given a single font or a list of font, determines which can be rendered
4 | validate = (fontList) ->
5 |
6 | fontList = fontList.split(",") unless fontList instanceof Array
7 | font.trim() for font in fontList
8 |
9 | # Check if the fontList has already been validated.
10 | fontString = fontList.join(", ")
11 | completed = validate.complete
12 | return completed[fontString] if fontString of completed
13 |
14 | testElement = (font) ->
15 | tester.append("span")
16 | .style "font-family", font
17 | .style "font-size", "32px"
18 | .style "padding", "0px"
19 | .style "margin", "0px"
20 | .text "abcdefghiABCDEFGHI_!@#$%^&*()_+1234567890"
21 |
22 | testWidth = (font, control) ->
23 | elem = testElement(font)
24 | width1 = elem.node().offsetWidth
25 | width2 = control.node().offsetWidth
26 | elem.remove()
27 | width1 isnt width2
28 |
29 | tester = fontTester("div")
30 | monospace = testElement("monospace")
31 | proportional = testElement("sans-serif")
32 |
33 | for family in fontList
34 |
35 | valid = testWidth(family + ",monospace", monospace)
36 | valid = testWidth(family + ",sans-serif", proportional) unless valid
37 |
38 | if valid
39 | valid = family
40 | break
41 |
42 | valid = "sans-serif" unless valid
43 |
44 | monospace.remove()
45 | proportional.remove()
46 |
47 | completed[fontString] = valid
48 | valid
49 |
50 | validate.complete = {}
51 |
52 | module.exports = validate
53 |
--------------------------------------------------------------------------------
/src/form/methods/format.coffee:
--------------------------------------------------------------------------------
1 | formatNumber = require "../../number/format.js"
2 | locale = require "../../core/locale/locale.coffee"
3 | mergeObject = require "../../object/merge.coffee"
4 | titleCase = require "../../string/title.coffee"
5 |
6 | module.exports =
7 | accepted: [Function, String]
8 | deprecates: ["number_format", "text_format"]
9 | locale:
10 | accepted: -> d3.keys locale
11 | process: (value) ->
12 | defaultLocale = "en_US"
13 | returnObject = locale[defaultLocale]
14 | returnObject = mergeObject(returnObject, locale[value]) if value isnt defaultLocale
15 | @language = value
16 | returnObject
17 | value: "en_US"
18 | number:
19 | accepted: [false, Function]
20 | value: false
21 | process: (value, vars) ->
22 | if typeof value is "string"
23 | vars.self.format locale: value
24 | else return value if typeof value is "function"
25 | @value
26 | text:
27 | accepted: [false, Function]
28 | value: false
29 | value: (value, key, vars) ->
30 | vars = {} unless vars
31 | if vars.time and vars.time.value and key is vars.time.value
32 | f = vars.time.format.value or vars.data.time.format
33 | v = (if value.constructor is Date then value else new Date(value))
34 | f v
35 | else if typeof value is "number"
36 | f = @number.value or formatNumber
37 | f value, key, vars
38 | else if typeof value is "string"
39 | f = @text.value or titleCase
40 | f value, key, vars
41 | else
42 | JSON.stringify value
43 |
--------------------------------------------------------------------------------
/src/viz/methods/format.coffee:
--------------------------------------------------------------------------------
1 | formatNumber = require "../../number/format.js"
2 | locale = require "../../core/locale/locale.coffee"
3 | mergeObject = require "../../object/merge.coffee"
4 | titleCase = require "../../string/title.coffee"
5 |
6 | module.exports =
7 | accepted: [Function, String]
8 | deprecates: ["number_format", "text_format"]
9 | locale:
10 | accepted: -> d3.keys locale
11 | process: (value) ->
12 | defaultLocale = "en_US"
13 | returnObject = locale[defaultLocale]
14 | returnObject = mergeObject(returnObject, locale[value]) if value isnt defaultLocale
15 | @language = value
16 | returnObject
17 | value: "en_US"
18 | number:
19 | accepted: [false, Function]
20 | value: false
21 | process: (value, vars) ->
22 | if typeof value is "string"
23 | vars.self.format locale: value
24 | else return value if typeof value is "function"
25 | @value
26 | text:
27 | accepted: [false, Function]
28 | value: false
29 | value: (value, key, vars) ->
30 | vars = {} unless vars
31 | if vars.time and vars.time.value and key is vars.time.value
32 | f = vars.time.format.value or vars.data.time.format
33 | v = (if value.constructor is Date then value else new Date(value))
34 | f v
35 | else if typeof value is "number"
36 | f = @number.value or formatNumber
37 | f value, key, vars
38 | else if typeof value is "string"
39 | f = @text.value or titleCase
40 | f value, key, vars
41 | else
42 | JSON.stringify value
43 |
--------------------------------------------------------------------------------
/src/viz/types/helpers/graph/nest.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../../../core/fetch/value.js"
2 | stringStrip = require "../../../../string/strip.js"
3 | uniqueValues = require "../../../../util/uniques.coffee"
4 |
5 | module.exports = (vars, data) ->
6 |
7 | data = vars.data.viz unless data
8 | discrete = vars[vars.axes.discrete]
9 | opposite = vars[vars.axes.opposite]
10 | ticks = discrete.ticks.values
11 | offsets =
12 | x: vars.axes.margin.left
13 | y: vars.axes.margin.top
14 |
15 | d3.nest()
16 | .key (d) ->
17 | id = fetchValue vars, d, vars.id.value
18 | depth = if "depth" of d.d3plus then d.d3plus.depth else vars.depth.value
19 | "line_"+stringStrip(id)+"_"+depth
20 | .rollup (leaves) ->
21 |
22 | availables = uniqueValues leaves, discrete.value
23 | timeVar = availables[0].constructor is Date
24 | availables = availables.map((t) -> t.getTime()) if timeVar
25 |
26 | for tick, i in ticks
27 |
28 | tester = if timeVar then tick.getTime() else tick
29 |
30 | if availables.indexOf(tester) < 0 and discrete.zerofill.value
31 |
32 | obj = {d3plus: {}}
33 | obj[vars.id.value] = leaves[0][vars.id.value]
34 | obj[discrete.value] = tick
35 | obj[opposite.value] = opposite.scale.viz.domain()[1]
36 |
37 | leaves.push obj
38 |
39 | return leaves.sort (a, b) ->
40 | xsort = a[discrete.value] - b[discrete.value]
41 | ysort = a[opposite.value] - b[opposite.value]
42 | if xsort then xsort else ysort
43 |
44 | .entries data
45 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3plus",
3 | "main": "d3plus.js",
4 | "version": "1.6.2",
5 | "moduleType": ["node"],
6 | "homepage": "https://github.com/alexandersimoes/d3plus",
7 | "description": "Data visualization made easy. A javascript library that extends the popular D3.js to enable fast and beautiful visualizations.",
8 | "authors": [
9 | "Dave Landry ",
10 | "Alexander Simoes ",
11 | "Daniel Smilkov "
12 | ],
13 | "dependencies": {
14 | "d3": "^3.4.12",
15 | "heap": "^0.2.4",
16 | "numeric": "^1.2.6",
17 | "simplify-js": "git@github.com:mourner/simplify-js.git"
18 | "static-kdtree": "git@github.com:mikolalysenko/static-kdtree.git#ce6e639c333fbab310fa44a3587b4bfdf10dbd4b"
19 | "topojson": "^1.6.18"
20 | },
21 | "devDependencies": {
22 | "browserify": "^6.0.2",
23 | "coffee-script": "^1.8.0",
24 | "coffeeify": "^0.7.0",
25 | "connect-livereload": "^0.4.0",
26 | "event-stream": "^3.1.7",
27 | "express": "^4.9.5",
28 | "gulp": "^3.8.7",
29 | "gulp-duration": "^0.0.0",
30 | "gulp-livereload": "^2.1.0",
31 | "gulp-notify": "^2.0.0",
32 | "gulp-rename": "^1.2.0",
33 | "gulp-rimraf": "^0.1.0",
34 | "gulp-streamify": "^0.0.5",
35 | "gulp-uglify": "^1.0.1",
36 | "gulp-util": "^3.0.0",
37 | "gulp-yuidoc": "^0.1.2",
38 | "require-dir": "^0.1.0",
39 | "tiny-lr": "^0.1.4",
40 | "vinyl-source-stream": "^1.0.0",
41 | "watchify": "^2.0.0"
42 | },
43 | "keywords": ["charts", "d3", "d3plus", "data", "visualization"],
44 | "license": "MIT"
45 | }
46 |
--------------------------------------------------------------------------------
/src/viz/helpers/focus/tooltip.coffee:
--------------------------------------------------------------------------------
1 | createTooltip = require "../tooltip/create.js"
2 | fetchValue = require "../../../core/fetch/value.js"
3 | print = require "../../../core/console/print.coffee"
4 | removeTooltip = require "../../../tooltip/remove.coffee"
5 |
6 | # Creates focus tooltip, if applicable
7 | module.exports = (vars) ->
8 |
9 | focus = vars.focus
10 |
11 | if not vars.internal_error and focus.value.length is 1 and focus.value.length and not vars.small and focus.tooltip.value
12 |
13 | print.time "drawing focus tooltip" if vars.dev.value
14 | data = vars.data.pool.filter (d) ->
15 | fetchValue(vars, d, vars.id.value) is focus.value[0]
16 |
17 | if data.length >= 1
18 | data = data[0]
19 | else
20 | data = {}
21 | data[vars.id.value] = focus.value[0]
22 |
23 | offset = vars.labels.padding
24 |
25 | createTooltip
26 | anchor: "top left"
27 | arrow: false
28 | data: data
29 | fullscreen: false
30 | id: "visualization_focus"
31 | length: "long"
32 | maxheight: vars.height.viz - offset * 2
33 | mouseevents: true
34 | offset: 0
35 | vars: vars
36 | width: vars.tooltip.large
37 | x: vars.width.value - vars.margin.right - offset
38 | y: vars.margin.top + offset
39 |
40 | vars.width.viz -= (vars.tooltip.large + offset * 2) unless d3.select("div#d3plus_tooltip_id_visualization_focus").empty()
41 |
42 | print.timeEnd "drawing focus tooltip" if vars.dev.value
43 |
44 | else
45 | removeTooltip "visualization_focus"
46 |
47 | return
48 |
--------------------------------------------------------------------------------
/docs/assets/js/api-filter.js:
--------------------------------------------------------------------------------
1 | YUI.add('api-filter', function (Y) {
2 |
3 | Y.APIFilter = Y.Base.create('apiFilter', Y.Base, [Y.AutoCompleteBase], {
4 | // -- Initializer ----------------------------------------------------------
5 | initializer: function () {
6 | this._bindUIACBase();
7 | this._syncUIACBase();
8 | },
9 | getDisplayName: function(name) {
10 |
11 | Y.each(Y.YUIDoc.meta.allModules, function(i) {
12 | if (i.name === name && i.displayName) {
13 | name = i.displayName;
14 | }
15 | });
16 |
17 | return name;
18 | }
19 |
20 | }, {
21 | // -- Attributes -----------------------------------------------------------
22 | ATTRS: {
23 | resultHighlighter: {
24 | value: 'phraseMatch'
25 | },
26 |
27 | // May be set to "classes" or "modules".
28 | queryType: {
29 | value: 'classes'
30 | },
31 |
32 | source: {
33 | valueFn: function() {
34 | var self = this;
35 | return function(q) {
36 | var data = Y.YUIDoc.meta[self.get('queryType')],
37 | out = [];
38 | Y.each(data, function(v) {
39 | if (v.toLowerCase().indexOf(q.toLowerCase()) > -1) {
40 | out.push(v);
41 | }
42 | });
43 | return out;
44 | };
45 | }
46 | }
47 | }
48 | });
49 |
50 | }, '3.4.0', {requires: [
51 | 'autocomplete-base', 'autocomplete-highlighters', 'autocomplete-sources'
52 | ]});
53 |
--------------------------------------------------------------------------------
/src/viz/helpers/zoom/mouse.coffee:
--------------------------------------------------------------------------------
1 | labels = require "./labels.js"
2 | transform = require "./transform.coffee"
3 |
4 | module.exports = (vars) ->
5 |
6 | translate = d3.event.translate
7 | scale = d3.event.scale
8 | limits = vars.zoom.bounds
9 | xoffset = (vars.width.viz - (vars.zoom.size.width * scale)) / 2
10 | xmin = (if xoffset > 0 then xoffset else 0)
11 | xmax = (if xoffset > 0 then vars.width.viz - xoffset else vars.width.viz)
12 | yoffset = (vars.height.viz - (vars.zoom.size.height * scale)) / 2
13 | ymin = (if yoffset > 0 then yoffset else 0)
14 | ymax = (if yoffset > 0 then vars.height.viz - yoffset else vars.height.viz)
15 |
16 | # Auto center visualization
17 | if translate[0] + limits[0][0] * scale > xmin
18 | translate[0] = -limits[0][0] * scale + xmin
19 | else if translate[0] + limits[1][0] * scale < xmax
20 | translate[0] = xmax - (limits[1][0] * scale)
21 |
22 | if translate[1] + limits[0][1] * scale > ymin
23 | translate[1] = -limits[0][1] * scale + ymin
24 | else if translate[1] + limits[1][1] * scale < ymax
25 | translate[1] = ymax - (limits[1][1] * scale)
26 |
27 | vars.zoom.behavior.translate(translate).scale scale
28 |
29 | vars.zoom.translate = translate
30 | vars.zoom.scale = scale
31 |
32 | if d3.event.sourceEvent.type is "wheel"
33 | delay = (if vars.draw.timing then 100 else 250)
34 | clearTimeout vars.zoom.wheel
35 | vars.zoom.wheel = setTimeout( ->
36 | labels vars
37 | , delay)
38 | else
39 | labels vars
40 |
41 | if d3.event.sourceEvent.type is "dblclick"
42 | transform vars, vars.timing.transitions
43 | else
44 | transform vars, 0
45 |
--------------------------------------------------------------------------------
/src/viz/types/pie.coffee:
--------------------------------------------------------------------------------
1 | comparator = require "../../array/comparator.coffee"
2 | dataThreshold = require("../../core/data/threshold.js")
3 | fetchValue = require("../../core/fetch/value.js")
4 | groupData = require("../../core/data/group.coffee")
5 |
6 | order = {}
7 |
8 | pie = (vars) ->
9 |
10 | pieLayout = d3.layout.pie()
11 | .value (d) -> d.value
12 | .sort (a, b) ->
13 | if vars.order.value
14 | comparator a.d3plus, b.d3plus, [vars.order.value], vars.order.sort.value, [], vars
15 | else
16 | aID = fetchValue vars, a.d3plus, vars.id.value
17 | order[aID] = a.value if order[aID] is undefined
18 | bID = fetchValue vars, b.d3plus, vars.id.value
19 | order[bID] = b.value if order[bID] is undefined
20 | if order[bID] < order[aID] then -1 else 1
21 |
22 | groupedData = groupData vars, vars.data.viz, []
23 | pieData = pieLayout groupedData
24 | returnData = []
25 |
26 | radius = d3.min([vars.width.viz, vars.height.viz])/2 - vars.labels.padding * 2
27 |
28 | for d in pieData
29 |
30 | item = d.data.d3plus
31 | item.d3plus.startAngle = d.startAngle
32 | item.d3plus.endAngle = d.endAngle
33 | item.d3plus.r = radius
34 | item.d3plus.x = vars.width.viz/2
35 | item.d3plus.y = vars.height.viz/2
36 |
37 | returnData.push item
38 |
39 | returnData
40 |
41 | # Visualization Settings and Helper Functions
42 | pie.filter = dataThreshold
43 | pie.requirements = ["data", "size"]
44 | pie.shapes = ["arc"]
45 | pie.threshold = (vars) -> (40 * 40) / (vars.width.viz * vars.height.viz)
46 | pie.tooltip = "follow"
47 | module.exports = pie
48 |
--------------------------------------------------------------------------------
/src/viz/types/scatter.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../core/fetch/value.js"
2 | graph = require "./helpers/graph/draw.coffee"
3 | print = require "../../core/console/print.coffee"
4 | sort = require "../../array/sort.coffee"
5 | ticks = require "./helpers/graph/dataTicks.coffee"
6 |
7 | # Scatterplot
8 | scatter = (vars) ->
9 |
10 | # Calculate X and Y domains, using "size" as a buffer
11 | graph vars,
12 | buffer: "size"
13 | mouse: true
14 |
15 | # Assign x, y, and radius to each data point
16 | for d in vars.data.viz
17 | d.d3plus.x = vars.x.scale.viz fetchValue(vars, d, vars.x.value)
18 | d.d3plus.x += vars.axes.margin.left
19 |
20 | d.d3plus.y = vars.y.scale.viz fetchValue(vars, d, vars.y.value)
21 | d.d3plus.y += vars.axes.margin.top
22 |
23 | if typeof vars.size.value is "number" or !vars.size.value
24 | d.d3plus.r = vars.axes.scale 0
25 | else
26 | d.d3plus.r = vars.axes.scale fetchValue(vars, d, vars.size.value)
27 |
28 | # Create data ticks
29 | ticks vars
30 |
31 | # Return the data, sorted
32 | sort vars.data.viz, vars.order.value or vars.size.value or vars.id.value,
33 | if vars.order.sort.value is "desc" then "asc" else "desc",
34 | vars.color.value or [], vars
35 |
36 | # Visualization Settings and Helper Functions
37 | scatter.fill = true
38 | scatter.requirements = ["data", "x", "y"]
39 | scatter.scale = 1.1
40 | scatter.setup = (vars) ->
41 | vars.self.x scale: "discrete" if vars.x.value is vars.time.value
42 | vars.self.y scale: "discrete" if vars.y.value is vars.time.value
43 | scatter.shapes = ["circle", "square", "donut"]
44 | scatter.tooltip = "static"
45 |
46 | module.exports = scatter
47 |
--------------------------------------------------------------------------------
/src/viz/methods/draw.js:
--------------------------------------------------------------------------------
1 | var print = require("../../core/console/print.coffee"),
2 | stringFormat = require("../../string/format.js")
3 |
4 | module.exports = {
5 | "accepted" : [ undefined , Function ],
6 | "first" : true,
7 | "frozen" : false,
8 | "process" : function (value, vars) {
9 |
10 | if ( this.initialized === false ) {
11 | this.initialized = true
12 | return value
13 | }
14 |
15 | if ( value === undefined && typeof this.value === "function" ) {
16 | value = this.value
17 | }
18 |
19 | if ( vars.container.value === false ) {
20 |
21 | var str = vars.format.locale.value.dev.setContainer
22 | print.warning( str , "container" )
23 |
24 | }
25 | else if ( vars.container.value.empty() ) {
26 |
27 | var str = vars.format.locale.value.dev.noContainer
28 | print.warning( stringFormat(str,"\""+vars.container.value+"\"") , "container" )
29 |
30 | }
31 | else {
32 |
33 | if ( vars.dev.value ) {
34 | if ( vars.methodGroup ) {
35 | vars.methodGroup = "wait"
36 | print.groupEnd()
37 | }
38 | print.time("total draw time")
39 | }
40 |
41 | vars.container.value.call(vars.self)
42 |
43 | }
44 |
45 | if ( typeof value === "function" && vars.history.chain.length ) {
46 |
47 | var changesObject = {}
48 | changes.forEach(function(c){
49 | var method = c.method
50 | delete c.method
51 | changesObject[method] = c
52 | })
53 |
54 | value(changesObject)
55 |
56 | vars.history.chain = []
57 |
58 | }
59 |
60 | return value
61 |
62 | },
63 | "update" : true,
64 | "value" : undefined
65 | }
66 |
--------------------------------------------------------------------------------
/src/viz/methods/title.coffee:
--------------------------------------------------------------------------------
1 | decoration = require "../../core/methods/font/decoration.coffee"
2 | family = require "../../core/methods/font/family.coffee"
3 | transform = require "../../core/methods/font/transform.coffee"
4 |
5 | stringStrip = require "../../string/strip.js"
6 |
7 | module.exports =
8 | accepted: [false, Function, String]
9 | font:
10 | align: "center"
11 | color: "#444444"
12 | decoration: decoration()
13 | family: family()
14 | size: 16
15 | transform: transform()
16 | weight: 400
17 | height: false
18 | link: false
19 | padding: 2
20 | position: "top"
21 | process: (value, vars) ->
22 | if vars.container.id.indexOf("default") is 0 and value
23 | id = stringStrip(value).toLowerCase()
24 | vars.self.container id: id
25 | value
26 | sub:
27 | accepted: [false, String]
28 | deprecates: "sub_title"
29 | font:
30 | align: "center"
31 | color: "#444444"
32 | decoration: decoration()
33 | family: family()
34 | size: 12
35 | transform: transform()
36 | weight: 200
37 | link: false
38 | padding: 1
39 | position: "top"
40 | value: false
41 | total:
42 | accepted: [Boolean, Object]
43 | deprecates: "total_bar"
44 | font:
45 | align: "center"
46 | color: "#444444"
47 | decoration: decoration()
48 | family: family()
49 | size: 12
50 | transform: transform()
51 | weight: 200
52 | value: false
53 | link: false
54 | padding: 1
55 | position: "top"
56 | value: false
57 | width: false
58 | value: false
59 |
--------------------------------------------------------------------------------
/src/number/format.js:
--------------------------------------------------------------------------------
1 | var defaultLocale = require("../core/locale/languages/en_US.coffee")
2 |
3 | // Formats numbers to look "pretty"
4 | module.exports = function( number , key , vars ) {
5 |
6 | if ( vars && key && vars.x && vars.y && (
7 | ( key === vars.x.value && vars.x.scale.value === "log" ) ||
8 | ( key === vars.y.value && vars.y.scale.value === "log" ) ) ) {
9 |
10 | var superscript = "⁰¹²³⁴⁵⁶⁷⁸⁹"
11 | , formatPower = function(d) {
12 | return (d + "").split("").map(function(c) {
13 | return superscript[c]
14 | }).join("")
15 | }
16 |
17 | return 10 + " " + formatPower( Math.round(Math.log(number) / Math.LN10) )
18 |
19 | }
20 |
21 | if ( "locale" in this ) {
22 | var time = this.locale.value.time
23 | }
24 | else {
25 | var time = defaultLocale.time
26 | }
27 |
28 | if ( vars && vars.time && typeof vars.time.value === "string") {
29 | time.push(vars.time.value)
30 | }
31 |
32 | if (typeof key === "string" && time.indexOf(key.toLowerCase()) >= 0) {
33 | return number
34 | }
35 | else if (number < 10 && number > -10) {
36 | return d3.round(number,2)
37 | }
38 | else if (number.toString().split(".")[0].length > 4) {
39 | var symbol = d3.formatPrefix(number).symbol
40 | symbol = symbol.replace("G", "B") // d3 uses G for giga
41 |
42 | // Format number to precision level using proper scale
43 | number = d3.formatPrefix(number).scale(number)
44 | number = parseFloat(d3.format(".3g")(number))
45 | return number + symbol;
46 | }
47 | else if (key == "share") {
48 | return d3.format(".2f")(number)
49 | }
50 | else {
51 | return d3.format(",f")(number)
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/core/fetch/color.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "./value.js"
2 | randomColor = require "../../color/random.coffee"
3 | validColor = require "../../color/validate.coffee"
4 | validObject = require "../../object/validate.coffee"
5 |
6 | # Finds an object's color and returns random if it cannot be found
7 | module.exports = (vars, id, level) ->
8 |
9 | return id.d3plus.color if id.d3plus and id.d3plus.color
10 |
11 | getRandom = (c) ->
12 | c = fetchValue(vars, c, level) if validObject(c)
13 | c = c[0] if c instanceof Array
14 | randomColor c, vars.color.scale.value
15 |
16 | level = vars.id.value unless level
17 | level = vars.id.nesting[level] if typeof level is "number"
18 |
19 | unless vars.color.value
20 | getRandom id
21 | else
22 |
23 | colors = []
24 | i = vars.id.nesting.indexOf(level)
25 | getColor = (color) ->
26 | unless color
27 | return vars.color.valueScale(0) if vars.color.value and typeof vars.color.valueScale is "function"
28 | getRandom id
29 | else unless vars.color.valueScale
30 | if validColor(color) then color else getRandom(color)
31 | else
32 | vars.color.valueScale color
33 |
34 | while i >= 0
35 | colorLevel = vars.id.nesting[i]
36 | if validObject(id)
37 | o = (unless (colorLevel of id) then fetchValue(vars, id, colorLevel) else id)
38 | value = fetchValue(vars, o, vars.color.value, colorLevel)
39 | else
40 | value = id
41 | if value isnt undefined and value isnt null
42 | color = getColor(value)
43 | colors.push color if colors.indexOf(color) < 0
44 | i--
45 |
46 | if colors.length is 1 then colors[0] else vars.color.missing
47 |
--------------------------------------------------------------------------------
/src/viz/helpers/zoom/bounds.js:
--------------------------------------------------------------------------------
1 | var transform = require("./transform.coffee")
2 |
3 | module.exports = function( vars , b , timing ) {
4 |
5 | if (!b) {
6 | var b = vars.zoom.bounds
7 | }
8 |
9 | if (typeof timing !== "number") {
10 | var timing = vars.timing.transitions
11 | }
12 |
13 | vars.zoom.size = {
14 | "height": b[1][1]-b[0][1],
15 | "width": b[1][0]-b[0][0]
16 | }
17 |
18 | var fit = vars.coords.fit.value
19 | if (fit == "auto" || vars.types[vars.type.value].requirements.indexOf("coords") < 0) {
20 | var aspect = d3.max([vars.zoom.size.width/vars.width.viz,vars.zoom.size.height/vars.height.viz])
21 | }
22 | else {
23 | var aspect = vars.zoom.size[fit]/vars["app_"+fit]
24 | }
25 |
26 | var min = d3.min([vars.width.viz,vars.height.viz])
27 |
28 | var padding = vars.types[vars.type.value].zoom ? vars.coords.padding*2 : 0
29 |
30 | var scale = ((min-padding) / min) / aspect
31 |
32 | var extent = vars.zoom.behavior.scaleExtent()
33 |
34 | if (extent[0] == extent[1] || b == vars.zoom.bounds) {
35 | vars.zoom.behavior.scaleExtent([scale,scale*16])
36 | }
37 |
38 | var max_scale = vars.zoom.behavior.scaleExtent()[1]
39 | if (scale > max_scale) {
40 | scale = max_scale
41 | }
42 | vars.zoom.scale = scale
43 |
44 | var translate = []
45 |
46 | translate[0] = vars.width.viz/2-(vars.zoom.size.width*scale)/2-(b[0][0]*scale)
47 | translate[1] = vars.height.viz/2-(vars.zoom.size.height*scale)/2-(b[0][1]*scale)
48 |
49 | vars.zoom.translate = translate
50 | vars.zoom.behavior.translate(translate).scale(scale)
51 |
52 | vars.zoom.size = {
53 | "height": vars.zoom.bounds[1][1]-vars.zoom.bounds[0][1],
54 | "width": vars.zoom.bounds[1][0]-vars.zoom.bounds[0][0]
55 | }
56 |
57 | transform(vars,timing)
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/viz/types/tree_map.coffee:
--------------------------------------------------------------------------------
1 | dataThreshold = require("../../core/data/threshold.js")
2 | groupData = require("../../core/data/group.coffee")
3 | mergeObject = require("../../object/merge.coffee")
4 |
5 | tree_map = (vars) ->
6 |
7 | groupedData = groupData(vars, vars.data.viz)
8 |
9 | # Pass data through the D3js .treemap() layout.
10 | data = d3.layout.treemap()
11 | .mode vars.type.mode.value
12 | .round true
13 | .size [vars.width.viz, vars.height.viz]
14 | .children (d) -> d.values
15 | .padding 1
16 | .sort (a, b) ->
17 | sizeDiff = a.value - b.value
18 | if sizeDiff is 0 then a.id < b.id else sizeDiff
19 | .nodes
20 | name: "root"
21 | values: groupedData
22 | .filter (d) -> not d.values and d.area
23 |
24 | # If the "data" array has entries...
25 | if data.length
26 |
27 | # Create the "root" node to use when calculating share percentage.
28 | root = data[0]
29 | root = root.parent while root.parent
30 |
31 | # Calculate the position, size, and share percentage of each square.
32 | returnData = []
33 | for d in data
34 |
35 | d.d3plus.d3plus = mergeObject d.d3plus.d3plus,
36 | x: d.x + d.dx / 2
37 | y: d.y + d.dy / 2
38 | width: d.dx
39 | height: d.dy
40 | share: d.value / root.value
41 |
42 | returnData.push d.d3plus
43 |
44 | # Return the data array.
45 | returnData
46 |
47 | # Visualization Settings and Helper Functions
48 | tree_map.filter = dataThreshold
49 | tree_map.modes = ["squarify", "slice", "dice", "slice-dice"]
50 | tree_map.requirements = ["data", "size"]
51 | tree_map.shapes = ["square"]
52 | tree_map.threshold = (vars) -> (40 * 40) / (vars.width.viz * vars.height.viz)
53 | tree_map.tooltip = "follow"
54 |
55 | module.exports = tree_map
56 |
--------------------------------------------------------------------------------
/src/form/methods/data.js:
--------------------------------------------------------------------------------
1 | var d3selection = require("../../util/d3selection.coffee"),
2 | process = require("../../core/methods/process/data.coffee")
3 |
4 | module.exports = {
5 | "accepted" : [ false , Array , Function , String ],
6 | "delimiter" : {
7 | "accepted" : [ String ],
8 | "value" : "|"
9 | },
10 | "element": {
11 | "process": function(value, vars) {
12 |
13 | if ( d3selection(value) ) {
14 | var element = value
15 | }
16 | else if (typeof value === "string" && !d3.select(value).empty()) {
17 | var element = d3.select(value)
18 | }
19 | else {
20 | var element = false
21 | }
22 |
23 | if (element) {
24 |
25 | vars.self.container(d3.select(element.node().parentNode))
26 |
27 | element
28 | .style("position","absolute","important")
29 | .style("clip","rect(1px 1px 1px 1px)","important")
30 | .style("clip","rect(1px, 1px, 1px, 1px)","important")
31 | .style("width","1px","important")
32 | .style("height","1px","important")
33 | .style("margin","-1px","important")
34 | .style("padding","0","important")
35 | .style("border","0","important")
36 | .style("overflow","hidden","important")
37 |
38 | }
39 |
40 | return element
41 |
42 | },
43 | "value": false
44 | },
45 | "filetype" : {
46 | "accepted" : [false, "json", "xml", "html", "csv", "dsv", "tsv", "txt"],
47 | "value" : false
48 | },
49 | "filters" : [],
50 | "mute" : [],
51 | "process" : function(value, vars) {
52 |
53 | if ( vars.container.id === "default" && value.length ) {
54 | vars.self.container({"id": "default"+value.length})
55 | }
56 |
57 | return process(value, vars, this)
58 | },
59 | "solo" : [],
60 | "value" : false
61 | }
62 |
--------------------------------------------------------------------------------
/src/viz/methods/csv.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../core/fetch/value.js"
2 | ie = require "../../client/ie.js"
3 | stringStrip = require "../../string/strip.js"
4 |
5 | module.exports =
6 | accepted: [undefined, Array, String]
7 | chainable: false
8 | data: []
9 | process: (value, vars) ->
10 |
11 | return [] if vars.returned is undefined
12 |
13 | value = value or vars.cols.value
14 |
15 | if value instanceof Array
16 | columns = value
17 | else if typeof value is "string"
18 | columns = [value]
19 |
20 | csv_to_return = []
21 | titles = []
22 | title = stringStrip vars.title.value or "My D3plus App Data"
23 |
24 | unless columns
25 | columns = [vars.id.value]
26 | columns.push vars.time.value if vars.time.value
27 | columns.push vars.size.value if vars.size.value
28 | columns.push vars.text.value if vars.text.value
29 |
30 | for c in columns
31 | titles.push vars.format.value(c)
32 |
33 | csv_to_return.push titles
34 | for n in vars.returned.nodes.forEach
35 | arr = []
36 | for c in columns
37 | arr.push fetchValue(vars, n, c)
38 | csv_to_return.push arr
39 |
40 | csv_data = "data:text/csv;charset=utf-8,"
41 | for c, i in csv_to_return
42 | dataString = c.join(",")
43 | csv_data += (if i < csv_to_return.length then dataString + "\n" else dataString)
44 |
45 | if ie
46 | blob = new Blob [csv_data], {type: "text/csv;charset=utf-8;"}
47 | navigator.msSaveBlob blob, title + ".csv"
48 | else
49 | encodedUri = encodeURI(csv_data)
50 | link = document.createElement("a")
51 | link.setAttribute "href", encodedUri
52 | link.setAttribute "download", title + ".csv"
53 | link.click()
54 |
55 | @data = csv_to_return
56 | columns
57 | value: undefined
58 |
--------------------------------------------------------------------------------
/src/core/data/color.js:
--------------------------------------------------------------------------------
1 | var buckets = require("../../util/buckets.coffee"),
2 | fetchValue = require("../fetch/value.js"),
3 | print = require("../console/print.coffee")
4 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 | // Sets color range of data, if applicable
6 | //-------------------------------------------------------------------
7 | module.exports = function(vars) {
8 |
9 | if ( vars.dev.value ) print.time("getting color data range")
10 |
11 | var data_range = []
12 | vars.data.pool.forEach(function(d){
13 | var val = parseFloat(fetchValue(vars,d,vars.color.value))
14 | if (typeof val == "number" && !isNaN(val) && data_range.indexOf(val) < 0) data_range.push(val)
15 | })
16 |
17 | if ( vars.dev.value ) print.timeEnd("getting color data range")
18 |
19 | if (data_range.length > 1) {
20 |
21 | var data_domain = null
22 |
23 | if ( vars.dev.value ) print.time("calculating color scale")
24 |
25 | data_range = d3.extent(data_range)
26 |
27 | if (data_range[0] < 0 && data_range[1] > 0) {
28 | var color_range = vars.color.range
29 | if (color_range.length == 3) {
30 | data_range.push(data_range[1])
31 | data_range[1] = 0
32 | }
33 | }
34 | else if (data_range[1] > 0 && data_range[0] >= 0) {
35 | var color_range = vars.color.heatmap
36 | data_range = buckets(data_range,color_range.length)
37 | }
38 | else {
39 | var color_range = vars.color.range.slice(0)
40 | if (data_range[0] < 0) {
41 | color_range.pop()
42 | }
43 | else {
44 | color_range.shift()
45 | }
46 | }
47 |
48 | vars.color.valueScale = d3.scale.sqrt()
49 | .domain(data_range)
50 | .range(color_range)
51 | .interpolate(d3.interpolateRgb)
52 |
53 | if ( vars.dev.value ) print.timeEnd("calculating color scale")
54 |
55 | }
56 | else {
57 | vars.color.valueScale = null
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/core/console/wiki.coffee:
--------------------------------------------------------------------------------
1 | module.exports =
2 | active: "Segmenting-Data#active"
3 | aggs: "Custom-Aggregations"
4 | alt: "Alt-Text-Parameters"
5 | attrs: "Attribute-Data#axes"
6 | axes: "Axis-Parameters"
7 | background: "Background"
8 | color: "Color-Parameters"
9 | container: "Container-Element"
10 | coords: "Geography-Data"
11 | csv: "CSV-Export"
12 | data: "Data-Points"
13 | depth: "Visible-Depth"
14 | descs: "Value-Definitions"
15 | dev: "Verbose-Mode"
16 | draw: "Draw"
17 | edges: "Edges-List"
18 | error: "Custom-Error-Message"
19 | focus: "Focus-Element"
20 | font: "Font-Styles"
21 | footer: "Custom-Footer"
22 | format: "Value-Formatting"
23 | height: "Height"
24 | history: "User-History"
25 | hover: "Hover-Element"
26 | icon: "Icon-Parameters"
27 | id: "Unique-ID"
28 | keywords: "Keyword-Parameters"
29 | labels: "Data-Labels"
30 | legend: "Legend"
31 | links: "Link-Styles"
32 | margin: "Outer-Margins"
33 | messages: "Status-Messages"
34 | method: "Methods"
35 | nodes: "Node-Positions"
36 | open: "Open"
37 | order: "Data-Ordering"
38 | remove: "Remove"
39 | search: "Search-Box"
40 | select: "Selecting-Elements#select"
41 | selectAll: "Selecting-Elements#selectall"
42 | shape: "Data-Shapes"
43 | size: "Size-Parameters"
44 | temp: "Segmenting-Data#temp"
45 | text: "Text-Parameters"
46 | time: "Time-Parameters"
47 | timeline: "Timeline"
48 | timing: "Animation-Timing"
49 | title: "Custom-Titles"
50 | tooltip: "Tooltip-Parameters"
51 | total: "Segmenting-Data#total"
52 | type: "Output-Type"
53 | ui: "Custom-Interface"
54 | width: "Width"
55 | x: "Axis-Parameters"
56 | y: "Axis-Parameters"
57 | zoom: "Zooming"
58 |
--------------------------------------------------------------------------------
/src/data/lof.coffee:
--------------------------------------------------------------------------------
1 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | # Finds outliers in n-dim data using the Local Outlier Factor algorithm
3 | # See:
4 | # http://en.wikipedia.org/wiki/Local_outlier_factor
5 | #------------------------------------------------------------------------------
6 |
7 | kdtree = require 'static-kdtree'
8 |
9 | # points is an array of n-dimensional points. Each point is an array of length n
10 |
11 | # K is the number of nearest neighbors to look for when comparing densities. Default value is 10
12 |
13 | # Returns an array of [index, lof] tuples, where index is the index of the point in the original array
14 | # and lof is the local outlier factor for that point. The array is ordered by descreasing order of LOF
15 | # so the outliers are in the beginning of the array.
16 |
17 | module.exports = (points, K=10) ->
18 | tree = kdtree points # construct a kd-tree
19 | neighbors = (tree.knn(p, K+1)[1...] for p in points) # get the k nearest neighbors for each point
20 |
21 | # calculate the squared euclidean distance between points p1 and p2
22 | sqDist = (i, j) ->
23 | A = points[i]
24 | B = points[j]
25 | dist = 0
26 | for i in [0...A.length]
27 | delta = A[i] - B[i]
28 | dist += delta * delta
29 | return dist
30 |
31 | # pre-compute kdist for all points
32 | kdists = (sqDist i, neighbors[i][K-1] for i in [0...points.length])
33 |
34 | # reachability distance
35 | reachDist = (i, j) -> Math.max sqDist(i, j), kdists[j]
36 |
37 | # local reachability density
38 | ldr = (i) ->
39 | rDist = 0
40 | rDist += reachDist i, j for j in neighbors[i]
41 | return K / rDist
42 |
43 | # pre-compute lrd for all points
44 | ldrs = (ldr i for i in [0...points.length])
45 |
46 | result = for i in [0...points.length]
47 | avg_lrd = 0
48 | avg_lrd += ldrs[j] for j in neighbors[i]
49 | avg_lrd /= K
50 | [i, avg_lrd / ldrs[i]]
51 |
52 | result.sort (a,b) -> b[1] - a[1]
53 |
--------------------------------------------------------------------------------
/src/form/methods/draw.js:
--------------------------------------------------------------------------------
1 | var d3selection = require("../../util/d3selection.coffee"),
2 | parseElement = require("../../core/parse/element.js"),
3 | print = require("../../core/console/print.coffee"),
4 | stringFormat = require("../../string/format.js")
5 |
6 | module.exports = {
7 | "accepted" : [ undefined , Function ],
8 | "first" : true,
9 | "frozen" : false,
10 | "process" : function (value, vars) {
11 |
12 | if ( this.initialized === false ) {
13 | this.initialized = true
14 | return value
15 | }
16 |
17 | if (vars.data.value && (!(vars.data.value instanceof Array) || d3selection(vars.data.value))) {
18 | vars.data.value = parseElement( vars )
19 | }
20 |
21 | if ( value === undefined && typeof this.value === "function" ) {
22 | value = this.value
23 | }
24 |
25 | if ( vars.container.value === false ) {
26 |
27 | var str = vars.format.locale.value.dev.setContainer
28 | print.warning( str , "container" )
29 |
30 | }
31 | else if ( vars.container.value.empty() ) {
32 |
33 | var str = vars.format.locale.value.dev.noContainer
34 | print.warning( stringFormat(str,"\""+vars.container.value+"\"") , "container" )
35 |
36 | }
37 | else {
38 |
39 | if ( vars.dev.value ) {
40 | if ( vars.methodGroup ) {
41 | vars.methodGroup = "wait"
42 | print.groupEnd()
43 | }
44 | print.time("total draw time")
45 | }
46 |
47 | vars.container.value.call(vars.self)
48 |
49 | }
50 |
51 | if ( typeof value === "function" && vars.history.chain.length ) {
52 |
53 | var changesObject = {}
54 | changes.forEach(function(c){
55 | var method = c.method
56 | delete c.method
57 | changesObject[method] = c
58 | })
59 |
60 | value(changesObject)
61 |
62 | vars.history.chain = []
63 |
64 | }
65 |
66 | return value
67 |
68 | },
69 | "update" : true,
70 | "value" : undefined
71 | }
72 |
--------------------------------------------------------------------------------
/src/geom/offset.coffee:
--------------------------------------------------------------------------------
1 | # Gives X and Y offset based off angle and shape
2 | module.exports = (radians, distance, shape) ->
3 |
4 | coords =
5 | x: 0
6 | y: 0
7 |
8 | radians = Math.PI * 2 + radians if radians < 0
9 |
10 | if shape is "square"
11 | diagonal = 45 * (Math.PI / 180)
12 | if radians <= Math.PI
13 | if radians < (Math.PI / 2)
14 | if radians < diagonal
15 | coords.x += distance
16 | oppositeLegLength = Math.tan(radians) * distance
17 | coords.y += oppositeLegLength
18 | else
19 | coords.y += distance
20 | adjacentLegLength = distance / Math.tan(radians)
21 | coords.x += adjacentLegLength
22 | else
23 | if radians < (Math.PI - diagonal)
24 | coords.y += distance
25 | adjacentLegLength = distance / Math.tan(Math.PI - radians)
26 | coords.x -= adjacentLegLength
27 | else
28 | coords.x -= distance
29 | oppositeLegLength = Math.tan(Math.PI - radians) * distance
30 | coords.y += oppositeLegLength
31 | else
32 | if radians < (3 * Math.PI / 2)
33 | if radians < (diagonal + Math.PI)
34 | coords.x -= distance
35 | oppositeLegLength = Math.tan(radians - Math.PI) * distance
36 | coords.y -= oppositeLegLength
37 | else
38 | coords.y -= distance
39 | adjacentLegLength = distance / Math.tan(radians - Math.PI)
40 | coords.x -= adjacentLegLength
41 | else
42 | if radians < (2 * Math.PI - diagonal)
43 | coords.y -= distance
44 | adjacentLegLength = distance / Math.tan(2 * Math.PI - radians)
45 | coords.x += adjacentLegLength
46 | else
47 | coords.x += distance
48 | oppositeLegLength = Math.tan(2 * Math.PI - radians) * distance
49 | coords.y -= oppositeLegLength
50 | else
51 | coords.x += distance * Math.cos(radians)
52 | coords.y += distance * Math.sin(radians)
53 |
54 | coords
55 |
--------------------------------------------------------------------------------
/src/form/types/button/functions/color.js:
--------------------------------------------------------------------------------
1 | var legible = require("../../../../color/legible.coffee"),
2 | lighter = require("../../../../color/lighter.coffee"),
3 | textColor = require("../../../../color/text.coffee")
4 |
5 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6 | // Defines button color
7 | //------------------------------------------------------------------------------
8 | module.exports = function ( elem , vars ) {
9 |
10 | elem
11 | .style("background-color",function(d){
12 |
13 | if ( vars.focus.value !== d[vars.id.value] ) {
14 |
15 | if ( vars.hover.value === d[vars.id.value] ) {
16 | return lighter(vars.ui.color.secondary.value,.25)
17 | }
18 | else {
19 | return vars.ui.color.secondary.value
20 | }
21 |
22 | }
23 | else {
24 |
25 | if ( vars.hover.value === d[vars.id.value] ) {
26 | return d3.rgb(vars.ui.color.primary.value).darker(0.15).toString()
27 | }
28 | else {
29 | return vars.ui.color.primary.value
30 | }
31 |
32 | }
33 |
34 | })
35 | .style("color",function(d){
36 |
37 | var image = d[vars.icon.value] && vars.data.viz.length < vars.data.large
38 |
39 | if ( vars.focus.value === d[vars.id.value] ) {
40 | var opacity = 1
41 | }
42 | else {
43 | var opacity = 0.75
44 | }
45 |
46 | if ( vars.focus.value === d[vars.id.value] && d[vars.color.value] && !image ) {
47 | var color = legible(d[vars.color.value])
48 | }
49 | else if ( vars.focus.value === d[vars.id.value] ) {
50 | var color = textColor(vars.ui.color.primary.value)
51 | }
52 | else {
53 | var color = textColor(vars.ui.color.secondary.value)
54 | }
55 |
56 | var color = d3.rgb(color)
57 |
58 | return "rgba("+color.r+","+color.g+","+color.b+","+opacity+")"
59 |
60 | })
61 | .style("border-color",vars.ui.color.secondary.value)
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/viz/types/helpers/graph/dataTicks.coffee:
--------------------------------------------------------------------------------
1 | color = require "../../../../core/fetch/color.coffee"
2 | legible = require "../../../../color/legible.coffee"
3 |
4 | module.exports = (vars) ->
5 |
6 | data = if vars.axes.stacked then [] else vars.data.viz
7 |
8 | style = (line, axis) ->
9 | line
10 | .attr "x1", (d) ->
11 | if axis is "y" then -2 else d.d3plus.x - vars.axes.margin.left
12 | .attr "x2", (d) ->
13 | if axis is "y" then -8 else d.d3plus.x - vars.axes.margin.left
14 | .attr "y1", (d) ->
15 | if axis is "x" then vars.axes.height + 2 else d.d3plus.y - vars.axes.margin.top
16 | .attr "y2", (d) ->
17 | if axis is "x" then vars.axes.height + 8 else d.d3plus.y - vars.axes.margin.top
18 | .style "stroke", (d) -> legible color vars, d
19 | .style "stroke-width", vars.data.stroke.width
20 | .attr "shape-rendering", vars.shape.rendering.value
21 |
22 | ticks = vars.group.select("g#d3plus_graph_plane").selectAll "g.d3plus_data_tick"
23 | .data data, (d) ->
24 | mod = if vars.axes.discrete then "_"+d.d3plus[vars.axes.discrete] else ""
25 | "tick_" + d[vars.id.value] + "_" + d.d3plus.depth + mod
26 |
27 | ticks.enter().append "g"
28 | .attr "class", "d3plus_data_tick"
29 | .attr "opacity", 0
30 |
31 | for axis in ["x","y"]
32 |
33 | axisData = if axis isnt vars.axes.discrete then data else []
34 |
35 | tick = ticks.selectAll "line.d3plus_data_"+axis
36 | .data axisData, (d) ->
37 | mod = if vars.axes.discrete then "_"+d.d3plus[vars.axes.discrete] else ""
38 | "tick_" + d[vars.id.value] + "_" + d.d3plus.depth + mod
39 |
40 | tick.enter().append("line")
41 | .attr "class","d3plus_data_"+axis
42 | .call style, axis
43 |
44 | tick.transition().duration vars.draw.timing
45 | .call style, axis
46 |
47 | ticks.transition().duration vars.draw.timing
48 | .attr("opacity",1)
49 |
50 | ticks.exit().transition().duration vars.draw.timing
51 | .attr("opacity",0).remove()
52 |
53 | return
54 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "d3plus",
3 | "version": "1.6.2",
4 | "description": "Data visualization made easy. A javascript library that extends the popular D3.js to enable fast and beautiful visualizations.",
5 | "main": "d3plus.js",
6 | "devDependencies": {
7 | "browserify": "^6.0.2",
8 | "coffee-script": "^1.8.0",
9 | "coffeeify": "^0.7.0",
10 | "connect-livereload": "^0.4.0",
11 | "event-stream": "^3.1.7",
12 | "express": "^4.9.5",
13 | "gulp": "^3.8.7",
14 | "gulp-duration": "^0.0.0",
15 | "gulp-livereload": "^2.1.0",
16 | "gulp-notify": "^2.0.0",
17 | "gulp-rename": "^1.2.0",
18 | "gulp-rimraf": "^0.1.0",
19 | "gulp-streamify": "^0.0.5",
20 | "gulp-uglify": "^1.0.1",
21 | "gulp-util": "^3.0.0",
22 | "gulp-yuidoc": "^0.1.2",
23 | "require-dir": "^0.1.0",
24 | "tiny-lr": "^0.1.4",
25 | "vinyl-source-stream": "^1.0.0",
26 | "watchify": "^2.0.0"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "https://github.com/alexandersimoes/d3plus.git"
31 | },
32 | "keywords": [
33 | "charts",
34 | "d3",
35 | "d3plus",
36 | "data",
37 | "visualization"
38 | ],
39 | "author": {
40 | "name": "Dave Landry",
41 | "email": "landry.dave@gmail.com",
42 | "url": "http://www.dave-landry.com"
43 | },
44 | "contributors": [
45 | {
46 | "name": "Alexander Simoes",
47 | "email": "alexandersimoes@gmail.com",
48 | "url": "http://www.alexandersimoes.com"
49 | },
50 | {
51 | "name": "Daniel Smilkov",
52 | "email": "dsmilkov@gmail.com",
53 | "url": "http://smilkov.com"
54 | }
55 | ],
56 | "license": "MIT",
57 | "bugs": {
58 | "url": "https://github.com/alexandersimoes/d3plus/issues",
59 | "email": "landry.dave@gmail.com"
60 | },
61 | "homepage": "http://www.d3plus.org",
62 | "dependencies": {
63 | "d3": "^3.4.12",
64 | "heap": "^0.2.4",
65 | "numeric": "^1.2.6",
66 | "simplify-js": "^1.2.1",
67 | "static-kdtree": "^1.0.1",
68 | "topojson": "^1.6.18"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/viz/methods/edges.js:
--------------------------------------------------------------------------------
1 | var process = require("../../core/methods/process/data.coffee")
2 |
3 | module.exports = {
4 | "accepted": [false, Array, Function, String],
5 | "arrows": {
6 | "accepted": [ Boolean , Number ],
7 | "direction": {
8 | "accepted": [ "source" , "target" ],
9 | "value": "target"
10 | },
11 | "value": false
12 | },
13 | "color": "#d0d0d0",
14 | "connections": function(focus,id,objects) {
15 |
16 | var self = this
17 |
18 | if (!self.value) {
19 | return []
20 | }
21 |
22 | if (!id) var id = "id"
23 |
24 | var edges = self.restricted || self.value,
25 | targets = []
26 |
27 | if (!focus) {
28 | return edges
29 | }
30 |
31 | var connections = edges.filter(function(edge){
32 |
33 | var match = false
34 |
35 | if (edge[self.source][id] == focus) {
36 | match = true
37 | if (objects) {
38 | targets.push(edge[self.target])
39 | }
40 | }
41 | else if (edge[self.target][id] == focus) {
42 | match = true
43 | if (objects) {
44 | targets.push(edge[self.source])
45 | }
46 | }
47 |
48 | return match
49 |
50 | })
51 |
52 | return objects ? targets : connections
53 |
54 | },
55 | "delimiter": {
56 | "accepted": [ String ],
57 | "value": "|"
58 | },
59 | "filetype": {
60 | "accepted": [false, "json", "xml","html", "csv", "dsv", "tsv", "txt"],
61 | "value": false
62 | },
63 | "interpolate": {
64 | "accepted": ["basis", "cardinal", "linear", "monotone", "step"],
65 | "value": "basis"
66 | },
67 | "label": false,
68 | "large": 100,
69 | "limit": {
70 | "accepted": [false, Function, Number],
71 | "value": false
72 | },
73 | "opacity": 1,
74 | "process": process,
75 | "size": false,
76 | "source": "source",
77 | "strength": {
78 | "accepted": [false, Function, Number, String],
79 | "value": false
80 | },
81 | "target": "target",
82 | "value": false,
83 | "width": 1
84 | }
85 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/cross.js:
--------------------------------------------------------------------------------
1 | var shapeStyle = require("./style.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Draws "square" and "circle" shapes using svg:rect
4 | //------------------------------------------------------------------------------
5 | module.exports = function(vars,selection,enter,exit) {
6 |
7 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | // Initialize check scale on enter and exit.
9 | //----------------------------------------------------------------------------
10 | function init(paths){
11 | paths.attr("d", d3.svg.symbol().type("cross").size(10))
12 | }
13 |
14 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | // Change scale of check on update.
16 | //---------------------------------------------------------------------------
17 | function update(paths){
18 | paths.attr("d", d3.svg.symbol().type("cross").size(function(d){
19 | var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
20 | return d3.scale.pow().exponent(2)(smaller_dim/2);
21 | }))
22 | }
23 |
24 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25 | // "paths" Enter
26 | //----------------------------------------------------------------------------
27 | enter.append("path").attr("class","d3plus_data")
28 | .call(init)
29 | .call(shapeStyle,vars)
30 |
31 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 | // "paths" Update
33 | //----------------------------------------------------------------------------
34 | selection.selectAll("path.d3plus_data")
35 | .data(function(d) {
36 | return [d];
37 | })
38 |
39 | if (vars.draw.timing) {
40 | selection.selectAll("path.d3plus_data")
41 | .transition().duration(vars.draw.timing)
42 | .call(update)
43 | .call(shapeStyle,vars)
44 | }
45 | else {
46 | selection.selectAll("path.d3plus_data")
47 | .call(update)
48 | .call(shapeStyle,vars)
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/core/data/load.coffee:
--------------------------------------------------------------------------------
1 | print = require "../console/print.coffee"
2 | validObject = require "../../object/validate.coffee"
3 |
4 | # Load Data using JSON
5 | module.exports = (vars, key, next) ->
6 |
7 | print.time "loading " + key if vars.dev.value
8 |
9 | url = vars[key].url
10 |
11 | unless vars[key].filetype.value
12 |
13 | fileType = url.slice(url.length - 5).split(".")
14 |
15 | if fileType.length > 1
16 | fileType = fileType[1]
17 | else
18 | fileType = false
19 |
20 | if fileType
21 | fileType = "text" if fileType is "txt"
22 | fileType = "json" if vars[key].filetype.accepted.indexOf(fileType) < 0
23 | else
24 | fileType = "json"
25 |
26 | else
27 | fileType = vars[key].filetype.value
28 |
29 | if fileType is "dsv"
30 | parser = d3.dsv(vars[key].delimiter.value, "text/plain")
31 | else
32 | parser = d3[fileType]
33 |
34 | parser url, (error, data) ->
35 |
36 | if not error and data
37 |
38 | if typeof vars[key].callback is "function"
39 | ret = vars[key].callback(data)
40 | if ret
41 | if validObject(ret) and key of ret
42 | for k of ret
43 | vars[k].value = ret[k] if k of vars
44 | else
45 | vars[key].value = ret
46 | else
47 | vars[key].value = data
48 |
49 | if [ "json" ].indexOf(fileType) < 0
50 | vars[key].value.forEach (d) ->
51 | for k of d
52 | unless isNaN(d[k])
53 | d[k] = parseFloat(d[k])
54 | else if d[k].toLowerCase() is "false"
55 | d[k] = false
56 | else if d[k].toLowerCase() is "true"
57 | d[k] = true
58 | else if d[k].toLowerCase() is "null"
59 | d[k] = null
60 | else d[k] = undefined if d[k].toLowerCase() is "undefined"
61 |
62 | vars[key].changed = true
63 | vars[key].loaded = true
64 |
65 | else
66 | vars.internal_error = "Could not load data from: \"" + url + "\""
67 |
68 | print.time "loading " + key if vars.dev.value
69 | next()
70 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/diamond.js:
--------------------------------------------------------------------------------
1 | var shapeStyle = require("./style.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Draws "square" and "circle" shapes using svg:rect
4 | //------------------------------------------------------------------------------
5 | module.exports = function(vars,selection,enter,exit) {
6 |
7 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | // Initialize check scale on enter and exit.
9 | //----------------------------------------------------------------------------
10 | function init(paths){
11 | paths.attr("d", d3.svg.symbol().type("diamond").size(10))
12 | }
13 |
14 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | // Change scale of check on update.
16 | //---------------------------------------------------------------------------
17 | function update(paths){
18 | paths.attr("d", d3.svg.symbol().type("diamond").size(function(d){
19 | var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
20 | return d3.scale.pow().exponent(2)(smaller_dim/2);
21 | }))
22 | }
23 |
24 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25 | // "paths" Enter
26 | //----------------------------------------------------------------------------
27 | enter.append("path").attr("class","d3plus_data")
28 | .call(init)
29 | .call(shapeStyle,vars)
30 |
31 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 | // "paths" Update
33 | //----------------------------------------------------------------------------
34 | selection.selectAll("path.d3plus_data")
35 | .data(function(d) {
36 | return [d];
37 | })
38 |
39 | if (vars.draw.timing) {
40 | selection.selectAll("path.d3plus_data")
41 | .transition().duration(vars.draw.timing)
42 | .call(update)
43 | .call(shapeStyle,vars)
44 | }
45 | else {
46 | selection.selectAll("path.d3plus_data")
47 | .call(update)
48 | .call(shapeStyle,vars)
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/triangle_up.js:
--------------------------------------------------------------------------------
1 | var shapeStyle = require("./style.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Draws "square" and "circle" shapes using svg:rect
4 | //------------------------------------------------------------------------------
5 | module.exports = function(vars,selection,enter,exit) {
6 |
7 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | // Initialize check scale on enter and exit.
9 | //----------------------------------------------------------------------------
10 | function init(paths){
11 | paths.attr("d", d3.svg.symbol().type("triangle-up").size(10))
12 | }
13 |
14 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | // Change scale of check on update.
16 | //---------------------------------------------------------------------------
17 | function update(paths){
18 | paths.attr("d", d3.svg.symbol().type("triangle-up").size(function(d){
19 | var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
20 | return d3.scale.pow().exponent(2)(smaller_dim/2);
21 | }))
22 | }
23 |
24 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25 | // "paths" Enter
26 | //----------------------------------------------------------------------------
27 | enter.append("path").attr("class","d3plus_data")
28 | .call(init)
29 | .call(shapeStyle,vars)
30 |
31 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 | // "paths" Update
33 | //----------------------------------------------------------------------------
34 | selection.selectAll("path.d3plus_data")
35 | .data(function(d) {
36 | return [d];
37 | })
38 |
39 | if (vars.draw.timing) {
40 | selection.selectAll("path.d3plus_data")
41 | .transition().duration(vars.draw.timing)
42 | .call(update)
43 | .call(shapeStyle,vars)
44 | }
45 | else {
46 | selection.selectAll("path.d3plus_data")
47 | .call(update)
48 | .call(shapeStyle,vars)
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/triangle_down.js:
--------------------------------------------------------------------------------
1 | var shapeStyle = require("./style.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Draws "square" and "circle" shapes using svg:rect
4 | //------------------------------------------------------------------------------
5 | module.exports = function(vars,selection,enter,exit) {
6 |
7 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | // Initialize check scale on enter and exit.
9 | //----------------------------------------------------------------------------
10 | function init(paths){
11 | paths.attr("d", d3.svg.symbol().type("triangle-down").size(10))
12 | }
13 |
14 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | // Change scale of check on update.
16 | //---------------------------------------------------------------------------
17 | function update(paths){
18 | paths.attr("d", d3.svg.symbol().type("triangle-down").size(function(d){
19 | var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
20 | return d3.scale.pow().exponent(2)(smaller_dim/2);
21 | }))
22 | }
23 |
24 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25 | // "paths" Enter
26 | //----------------------------------------------------------------------------
27 | enter.append("path").attr("class","d3plus_data")
28 | .call(init)
29 | .call(shapeStyle,vars)
30 |
31 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 | // "paths" Update
33 | //----------------------------------------------------------------------------
34 | selection.selectAll("path.d3plus_data")
35 | .data(function(d) {
36 | return [d];
37 | })
38 |
39 | if (vars.draw.timing) {
40 | selection.selectAll("path.d3plus_data")
41 | .transition().duration(vars.draw.timing)
42 | .call(update)
43 | .call(shapeStyle,vars)
44 | }
45 | else {
46 | selection.selectAll("path.d3plus_data")
47 | .call(update)
48 | .call(shapeStyle,vars)
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/textwrap/helpers/wrap.coffee:
--------------------------------------------------------------------------------
1 | flow = require "./flow.coffee"
2 | fontSizes = require "../../font/sizes.coffee"
3 | flow = require "./flow.coffee"
4 |
5 | # Flows the text into the container
6 | wrap = (vars) ->
7 |
8 | if vars.text.phrases.length
9 |
10 | vars.text.current = vars.text.phrases.shift() + ""
11 | vars.text.words = vars.text.current.match vars.text.break
12 |
13 | if vars.resize.value then resize vars else flow vars
14 |
15 | return
16 |
17 | module.exports = wrap
18 |
19 | # Logic to determine the best size for text
20 | resize = (vars) ->
21 |
22 | words = []
23 | i = 0
24 |
25 | while i < vars.text.words.length
26 | addon = (if i is vars.text.words.length - 1 then "" else " ")
27 | words.push vars.text.words[i] + addon
28 | i++
29 |
30 | # Start by trying the largest font size
31 | sizeMax = Math.floor(vars.size.value[1])
32 | lineWidth = if vars.shape.value is "circle" then vars.width.value * 0.785 else vars.width.value
33 | sizes = fontSizes words, {"font-size": sizeMax + "px"}, vars.container.value
34 | maxWidth = d3.max sizes, (d) -> d.width
35 | areaMod = 1.165 + (vars.width.value / vars.height.value * 0.037)
36 | textArea = d3.sum(sizes, (d) -> d.width * d.height) * areaMod
37 |
38 | if vars.shape.value is "circle"
39 | boxArea = Math.PI * Math.pow(vars.width.value / 2, 2)
40 | else
41 | boxArea = lineWidth * vars.height.value
42 |
43 | if maxWidth > lineWidth or textArea > boxArea
44 | areaRatio = Math.sqrt(boxArea / textArea)
45 | widthRatio = lineWidth / maxWidth
46 | sizeRatio = d3.min [areaRatio, widthRatio]
47 | sizeMax = d3.max [vars.size.value[0], Math.floor(sizeMax * sizeRatio)]
48 |
49 | heightMax = Math.floor(vars.height.value * 0.8)
50 | sizeMax = heightMax if sizeMax > heightMax
51 |
52 | if maxWidth * (sizeMax / vars.size.value[1]) <= lineWidth
53 | if sizeMax isnt vars.size.value[1]
54 | vars.self.size [vars.size.value[0], sizeMax]
55 | vars.container.value.attr "font-size", vars.size.value[1] + "px"
56 | flow vars
57 | else
58 | wrap vars
59 |
60 | return
61 |
--------------------------------------------------------------------------------
/src/viz/helpers/container.coffee:
--------------------------------------------------------------------------------
1 | # If placing into a new container, remove it's contents
2 | # and check text direction.
3 | #
4 | # Also initialized app width and height.
5 | module.exports = (vars) ->
6 |
7 | vars.container.value
8 | .style "position", () ->
9 | current = d3.select(this).style("position")
10 | remain = ["absolute","fixed"].indexOf(current) >= 0
11 | if remain then current else "relative"
12 | .html ""
13 |
14 | # Get overall width and height, if not defined
15 | for s in ["width","height"]
16 |
17 | unless vars[s].value
18 |
19 | checkParent = (element) ->
20 |
21 | if element.tagName is undefined or ["BODY","HTML"].indexOf(element.tagName) >= 0
22 |
23 | val = window["inner"+s.charAt(0).toUpperCase()+s.slice(1)]
24 | elem = if document isnt element then d3.select(element) else false
25 |
26 | if elem
27 | if s is "width"
28 | val -= parseFloat elem.style("margin-left"), 10
29 | val -= parseFloat elem.style("margin-right"), 10
30 | val -= parseFloat elem.style("padding-left"), 10
31 | val -= parseFloat elem.style("padding-right"), 10
32 | else
33 | val -= parseFloat elem.style("margin-top"), 10
34 | val -= parseFloat elem.style("margin-bottom"), 10
35 | val -= parseFloat elem.style("padding-top"), 10
36 | val -= parseFloat elem.style("padding-bottom"), 10
37 |
38 | vars[s].value = if val <= 20 then vars[s].small else val
39 |
40 | else
41 |
42 | val = parseFloat d3.select(element).style(s), 10
43 | if typeof val is "number" and val > 0
44 | vars[s].value = val
45 | else if element.tagName isnt "BODY"
46 | checkParent element.parentNode
47 |
48 | checkParent vars.container.value.node()
49 |
50 | d3.select("body").style("overflow","hidden") if d3.selectAll("body > *:not(script)").size() is 1
51 |
52 | vars.container.value
53 | .style "width", vars.width.value+"px"
54 | .style "height", vars.height.value+"px"
55 |
56 | return
57 |
--------------------------------------------------------------------------------
/src/data/bestRegress.coffee:
--------------------------------------------------------------------------------
1 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 | # Finds the best regression model that fits the data using Bayesian Information Criteria
3 | #---------------------------------------------------------------------------------------
4 |
5 | # data is an array of two-dimensional arrays in the format of [x, y]
6 |
7 | # options is a dictionary of options with attributes
8 | # maxDegree; maximum possible degree of the polynomial. Default is 10.
9 |
10 | # Returns the model with the best BIC score as a triple [degrees, betaHat, yHat]
11 | # where degrees is an array containing the degrees of each term in the polynomial.
12 | # and betaHat contains the coefficients for each term
13 | # and yHat contains the regressed output for each input term.
14 |
15 | numeric = require 'numeric'
16 |
17 | module.exports = (data, options) ->
18 | if not options? then options = {}
19 | if not options.maxDegree? then options.maxDegree = 5 # try to fit a polynomial up to this degree
20 | N = data.length
21 | # choose the model that has minimum BIC (penalty)
22 | prevBIC = Number.MAX_VALUE
23 | bestResult = null
24 |
25 | # construct the matrix X
26 | Xfulltr = ((Math.pow(point[0], degree) for point in data) for degree in [1...options.maxDegree+1])
27 | y = (point[1] for point in data)
28 | for i in [0...1< 0
33 | Xtr.push Xfulltr[j]
34 | degrees.push j+1
35 | #console.log Xtr
36 | X = numeric.transpose Xtr
37 | k = degrees.length # degrees of freedom
38 | beta_hat = numeric.dot(numeric.dot(numeric.inv(numeric.dot(Xtr, X)), Xtr), y)
39 | y_hat = numeric.dot(X, beta_hat)
40 | residual = numeric.sub y, y_hat
41 | sse = numeric.dot residual, residual
42 | # compute sigma2
43 | sigma2 = sse / (N - k)
44 | # compute log-likelihood
45 | loglike = -0.5*N*Math.log(2*Math.PI)-0.5*N*Math.log(sigma2)-sse/(2*sigma2)
46 | bic = -2*loglike + k*(Math.log(N)-Math.log(2*Math.PI))
47 | if bic < prevBIC
48 | prevBIC = bic
49 | bestResult = [degrees, beta_hat, y_hat]
50 | bestResult
51 |
--------------------------------------------------------------------------------
/src/viz/helpers/svg/update.js:
--------------------------------------------------------------------------------
1 | var print = require("../../../core/console/print.coffee")
2 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 | // Updating Elements
4 | //------------------------------------------------------------------------------
5 | module.exports = function(vars) {
6 |
7 | if ( vars.dev.value ) print.time("updating SVG elements")
8 |
9 | if ( vars.draw.timing ) {
10 |
11 | // Update Parent Element
12 | vars.container.value.transition().duration(vars.draw.timing)
13 | .style("width",vars.width.value+"px")
14 | .style("height",vars.height.value+"px")
15 |
16 | // Update SVG
17 | vars.svg.transition().duration(vars.draw.timing)
18 | .attr("width",vars.width.value)
19 | .attr("height",vars.height.value)
20 |
21 | // Update Background Rectangle
22 | vars.g.bg.transition().duration(vars.draw.timing)
23 | .attr("width",vars.width.value)
24 | .attr("height",vars.height.value)
25 |
26 | // Update App Clipping Rectangle
27 | vars.g.clipping.select("rect").transition().duration(vars.draw.timing)
28 | .attr("width",vars.width.viz)
29 | .attr("height",vars.height.viz)
30 |
31 | // Update Container Groups
32 | vars.g.container.transition().duration(vars.draw.timing)
33 | .attr("transform","translate("+vars.margin.left+","+vars.margin.top+")")
34 |
35 | }
36 | else {
37 |
38 | // Update Parent Element
39 | vars.container.value
40 | .style("width",vars.width.value+"px")
41 | .style("height",vars.height.value+"px")
42 |
43 | // Update SVG
44 | vars.svg
45 | .attr("width",vars.width.value)
46 | .attr("height",vars.height.value)
47 |
48 | // Update Background Rectangle
49 | vars.g.bg
50 | .attr("width",vars.width.value)
51 | .attr("height",vars.height.value)
52 |
53 | // Update App Clipping Rectangle
54 | vars.g.clipping.select("rect")
55 | .attr("width",vars.width.viz)
56 | .attr("height",vars.height.viz)
57 |
58 | // Update Container Groups
59 | vars.g.container
60 | .attr("transform","translate("+vars.margin.left+","+vars.margin.top+")")
61 |
62 | }
63 |
64 | if ( vars.dev.value ) print.timeEnd("updating SVG elements")
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/viz/helpers/zoom/controls.js:
--------------------------------------------------------------------------------
1 | var events = require("../../../client/pointer.coffee")
2 |
3 | module.exports = function() {
4 |
5 | d3.select("#d3plus.utilsts.zoom_controls").remove()
6 |
7 | if (!vars.small) {
8 | // Create Zoom Controls
9 | var zoom_enter = vars.container.value.append("div")
10 | .attr("id","d3plus.utilsts.zoom_controls")
11 | .style("top",(vars.margin.top+5)+"px")
12 |
13 | zoom_enter.append("div")
14 | .attr("id","zoom_in")
15 | .attr("unselectable","on")
16 | .on(events.click,function(){ vars.zoom("in") })
17 | .text("+")
18 |
19 | zoom_enter.append("div")
20 | .attr("id","zoom_out")
21 | .attr("unselectable","on")
22 | .on(events.click,function(){ vars.zoom("out") })
23 | .text("-")
24 |
25 | zoom_enter.append("div")
26 | .attr("id","zoom_reset")
27 | .attr("unselectable","on")
28 | .on(events.click,function(){
29 | vars.zoom("reset")
30 | vars.draw.update()
31 | })
32 | .html("\↺")
33 | }
34 |
35 | /* Old Styles
36 |
37 | #zoom_controls {
38 | position: absolute;
39 | top: 5px;
40 | left: 5px;
41 | z-index: 50;
42 | }
43 |
44 | #zoom_in, #zoom_out, #zoom_reset {
45 | background-color: #ffffff;
46 | background-position: 50% 50%;
47 | background-repeat: no-repeat;
48 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
49 | -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
50 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
51 | color: #333333;
52 | display: block;
53 | height: 18px;
54 | margin-bottom: 5px;
55 | opacity: 0.75;
56 | text-align: center;
57 | width: 18px;
58 | -webkit-text-size-adjust: none;
59 | -webkit-user-select: none;
60 | -moz-user-select: none;
61 | }
62 |
63 | #zoom_in:hover, #zoom_out:hover, #zoom_reset:hover {
64 | opacity: 1;
65 | }
66 |
67 | #zoom_in {
68 | cursor: pointer;
69 | font: normal 18px/20px Arial, Helvetica, sans-serif;
70 | }
71 |
72 | #zoom_out {
73 | cursor: pointer;
74 | font: normal 22px/16px Tahoma, Verdana, sans-serif;
75 | }
76 |
77 | #zoom_reset {
78 | cursor: pointer;
79 | font: bold 15px/19px Arial, Helvetica, sans-serif;
80 | }
81 |
82 | */
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/viz/types/stacked.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../core/fetch/value.js"
2 | graph = require "./helpers/graph/draw.coffee"
3 | nest = require "./helpers/graph/nest.coffee"
4 | sort = require "../../array/sort.coffee"
5 | stack = require "./helpers/graph/stack.coffee"
6 | threshold = require "../../core/data/threshold.js"
7 |
8 | # Stacked Area Chart
9 | stacked = (vars) ->
10 |
11 | graph vars,
12 | buffer: vars.axes.opposite
13 |
14 | data = nest vars
15 |
16 | # Assign x and y to each data point
17 | for point in data
18 | point.d3plus = {} unless point.d3plus
19 | for d in point.values
20 |
21 | d.d3plus.x = vars.x.scale.viz fetchValue vars, d, vars.x.value
22 | d.d3plus.x += vars.axes.margin.left
23 |
24 | d.d3plus.y = vars.y.scale.viz fetchValue vars, d, vars.y.value
25 | d.d3plus.y += vars.axes.margin.top
26 |
27 | if d.d3plus.merged instanceof Array
28 | point.d3plus.merged = [] unless point.d3plus.merged
29 | point.d3plus.merged = point.d3plus.merged.concat(d.d3plus.merged)
30 | point.d3plus.text = d.d3plus.text if d.d3plus.text and !point.d3plus.text
31 |
32 | data = stack vars, data
33 | order = vars.order.value or vars.size.value or vars.id.value
34 | sortOrder = if vars.order.sort.value is "desc" then "asc" else "desc"
35 |
36 | # Return the data, sorted
37 | sort data, order, sortOrder, vars.color.value or [], vars
38 |
39 | # Visualization Settings and Helper Functions
40 | stacked.filter = (vars, data) ->
41 | threshold vars, data, vars.x.value
42 | stacked.requirements = ["data", "x", "y"]
43 | stacked.setup = (vars) ->
44 |
45 | vars.self.x scale: "discrete" unless vars.axes.discrete
46 |
47 | vars.self[vars.axes.discrete]
48 | zerofill: true
49 | vars.self[vars.axes.opposite]
50 | stacked: true
51 |
52 | y = vars[vars.axes.opposite]
53 | size = vars.size
54 |
55 | if (not y.value and size.value) or (size.changed and size.previous is y.value)
56 | vars.self[vars.axes.opposite] size.value
57 | else if (not size.value and y.value) or (y.changed and y.previous is size.value)
58 | vars.self.size y.value
59 | return
60 |
61 | stacked.shapes = ["area"]
62 | stacked.threshold = (vars) -> 20 / vars.height.viz
63 | stacked.tooltip = "static"
64 | module.exports = stacked
65 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/check.js:
--------------------------------------------------------------------------------
1 | var fetchText = require("../../../core/fetch/text.js"),
2 | fontSizes = require("../../../font/sizes.coffee"),
3 | largestRect = require("../../../geom/largestRect.coffee"),
4 | shapeStyle = require("./style.coffee")
5 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6 | // Draws "square" and "circle" shapes using svg:rect
7 | //------------------------------------------------------------------------------
8 | module.exports = function(vars,selection,enter,exit) {
9 |
10 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11 | // Initialize check scale on enter and exit.
12 | //----------------------------------------------------------------------------
13 | function init(paths){
14 | paths.attr("transform", "scale(1)")
15 | }
16 |
17 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18 | // Change scale of check on update.
19 | //---------------------------------------------------------------------------
20 | function update(paths){
21 | paths.attr("transform", function(d){
22 | var smaller_dim = Math.min(d.d3plus.width, d.d3plus.height);
23 | var scale = Math.floor(smaller_dim / 16);
24 | return "scale("+scale+")";
25 | })
26 | }
27 |
28 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29 | // "paths" Enter
30 | //----------------------------------------------------------------------------
31 | enter.append("path").attr("class","d3plus_data")
32 | .attr("d", "M5-6.844L3.594-5.407L-2,0.188l-1.594-1.594L-5-2.844L-7.844,0l1.438,1.406l3,3L-2,5.843l1.406-1.438l7-7L7.844-4L5-6.844z")
33 | .call(init)
34 | .call(shapeStyle,vars)
35 |
36 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 | // "paths" Update
38 | //----------------------------------------------------------------------------
39 | selection.selectAll("path.d3plus_data")
40 | .data(function(d) {
41 | return [d];
42 | })
43 |
44 | if (vars.draw.timing) {
45 | selection.selectAll("path.d3plus_data")
46 | .transition().duration(vars.draw.timing)
47 | .call(update)
48 | .call(shapeStyle,vars)
49 | }
50 | else {
51 | selection.selectAll("path.d3plus_data")
52 | .call(update)
53 | .call(shapeStyle,vars)
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/core/fetch/text.js:
--------------------------------------------------------------------------------
1 | var fetchValue = require("./value.js"),
2 | validObject = require("../../object/validate.coffee"),
3 | uniqueValues = require("../../util/uniques.coffee")
4 |
5 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6 | // Get array of available text values
7 | //------------------------------------------------------------------------------
8 | module.exports = function(vars,obj,depth) {
9 |
10 | if ( typeof depth !== "number" ) var depth = vars.depth.value
11 |
12 | var key = vars.id.nesting[depth]
13 |
14 | if ( vars.text.nesting && validObject(vars.text.nesting) ) {
15 | if ( vars.text.nesting[key] ) {
16 | var textKeys = vars.text.nesting[key]
17 | }
18 | else {
19 | var textKeys = vars.text.value
20 | }
21 | }
22 | else {
23 | var textKeys = []
24 | if (vars.text.value && depth === vars.depth.value) textKeys.push(vars.text.value)
25 | textKeys.push(key)
26 | }
27 |
28 | if ( !(textKeys instanceof Array) ) {
29 | textKeys = [ textKeys ]
30 | }
31 |
32 | var names = []
33 |
34 | if (validObject(obj) && "d3plus" in obj && obj.d3plus.text) {
35 | names.push(obj.d3plus.text.toString())
36 | names.push(vars.format.value(obj.d3plus.text.toString(), undefined, vars))
37 | }
38 | else {
39 |
40 | var ids = validObject(obj) && key in obj ? obj[key] : fetchValue(vars, obj, key)
41 | if (!(ids instanceof Array)) ids = [ids]
42 | else if (validObject(ids[0])) {
43 | ids = uniqueValues(ids,key)
44 | }
45 |
46 | textKeys.forEach(function( t ){
47 |
48 | var name = []
49 | ids.forEach(function(i){
50 | var n = fetchValue(vars,i,t,key)
51 | if (n) {
52 | if (n instanceof Array && validObject(n[0])) {
53 | n = uniqueValues(n,t)
54 | }
55 | name = name.concat(n)
56 | }
57 | })
58 |
59 | if ( name.length ) {
60 | name = name.map(function(n){
61 | if (n instanceof Array) {
62 | return n.map(function(nn){
63 | return vars.format.value(nn.toString(),t, vars)
64 | })
65 | }
66 | else if (n) {
67 | return vars.format.value(n.toString(),t, vars)
68 | }
69 | })
70 | if (name.length === 1) name = name[0]
71 | names.push(name)
72 | }
73 |
74 | })
75 |
76 | }
77 |
78 | return names
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/form/types/toggle.js:
--------------------------------------------------------------------------------
1 | var form = require("../form.js")
2 |
3 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4 | // Creates a set of Toggle Buttons
5 | //------------------------------------------------------------------------------
6 | module.exports = function( vars ) {
7 |
8 | if ( !("buttons" in vars.container) ) {
9 |
10 | vars.container.buttons = form()
11 | .container(vars.container.ui)
12 | .type("button")
13 |
14 | }
15 |
16 | var dataLength = vars.data.viz.length
17 | , buttonWidth = vars.width.value
18 | ? vars.width.value/dataLength
19 | : false
20 |
21 | var toggles = vars.container.ui.selectAll("div.d3plus_toggle")
22 | .data(vars.data.viz,function(d){
23 | return d[vars.id.value]
24 | })
25 |
26 | toggles.enter().append("div")
27 | .attr("class","d3plus_toggle")
28 | .style("display","inline-block")
29 | .style("vertical-align","top")
30 |
31 | toggles.order()
32 | .each(function(d){
33 |
34 | if (!("form" in d.d3plus)) {
35 | d.d3plus.form = form().container(d3.select(this))
36 | }
37 |
38 | var id = vars.id.nesting.length > vars.depth.value ? vars.id.nesting[vars.depth.value+1] : vars.id.value
39 |
40 | if (d[id] instanceof Array) {
41 | d.d3plus.form
42 | .container({"id": vars.container.id+"_"+d[vars.id.value]})
43 | .data(d[id])
44 | .id(vars.id.nesting.slice(1))
45 | .type("drop")
46 | }
47 | else {
48 | d.d3plus.form
49 | .data([d])
50 | .id(vars.id.value)
51 | .type("button")
52 | }
53 |
54 | d.d3plus.form
55 | .color(vars.color)
56 | .focus(vars.focus.value,function(value){
57 |
58 | if (value !== vars.focus.value) {
59 | vars.self.focus(value).draw()
60 | }
61 |
62 | })
63 | .icon({
64 | "select": false,
65 | "value": vars.icon.value
66 | })
67 | .font(vars.font)
68 | .format(vars.format)
69 | .order(vars.order)
70 | .text(vars.text.value)
71 | .ui({
72 | "border": vars.ui.border,
73 | "color": vars.ui.color,
74 | "display": "inline-block",
75 | "margin": 0,
76 | "padding": vars.ui.padding
77 | })
78 | .width(buttonWidth)
79 | .draw()
80 |
81 | })
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/src/core/parse/edges.js:
--------------------------------------------------------------------------------
1 | var print = require("../console/print.coffee"),
2 | stringFormat = require("../../string/format.js")
3 |
4 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 | // Cleans edges list and populates nodes list if needed
6 | //-------------------------------------------------------------------
7 | module.exports = function( vars ) {
8 |
9 | if ( vars.dev.value ) {
10 | var timerString = "analyzing edges list"
11 | print.time( timerString )
12 | }
13 |
14 | var appReqs = vars.types[vars.type.value].requirements
15 | if (!(appReqs instanceof Array)) appReqs = [appReqs]
16 | var createNodes = appReqs.indexOf("nodes") >= 0 && !vars.nodes.value
17 |
18 | if ( createNodes ) {
19 | vars.nodes.value = []
20 | var placed = []
21 | vars.nodes.changed = true
22 | }
23 |
24 | vars.edges.value.forEach(function(e){
25 |
26 | if (typeof e[vars.edges.source] !== "object") {
27 | var obj = {}
28 | obj[vars.id.value] = e[vars.edges.source]
29 | e[vars.edges.source] = obj
30 | }
31 | if (typeof e[vars.edges.target] !== "object") {
32 | var obj = {}
33 | obj[vars.id.value] = e[vars.edges.target]
34 | e[vars.edges.target] = obj
35 | }
36 |
37 | if (!("keys" in vars.data)) {
38 | vars.data.keys = {}
39 | }
40 |
41 | if (!(vars.id.value in vars.data.keys)) {
42 | vars.data.keys[vars.id.value] = typeof e[vars.edges.source][vars.id.value]
43 | }
44 |
45 | if ( createNodes ) {
46 | if (placed.indexOf(e[vars.edges.source][vars.id.value]) < 0) {
47 | placed.push(e[vars.edges.source][vars.id.value])
48 | vars.nodes.value.push(e[vars.edges.source])
49 | }
50 | if (placed.indexOf(e[vars.edges.target][vars.id.value]) < 0) {
51 | placed.push(e[vars.edges.target][vars.id.value])
52 | vars.nodes.value.push(e[vars.edges.target])
53 | }
54 | }
55 |
56 | })
57 |
58 | vars.edges.value = vars.edges.value.filter(function(e){
59 |
60 | var source = e[vars.edges.source][vars.id.value]
61 | , target = e[vars.edges.target][vars.id.value]
62 |
63 | if ( source === target ) {
64 | var str = vars.format.locale.value.dev.sameEdge
65 | print.warning(stringFormat(str,"\""+source+"\"") , "edges" )
66 | return false
67 | }
68 | else {
69 | return true
70 | }
71 |
72 | })
73 |
74 | vars.edges.linked = true
75 |
76 | if ( vars.dev.value ) print.timeEnd( timerString )
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/button.js:
--------------------------------------------------------------------------------
1 | var copy = require("../../../../util/copy.coffee"),
2 | events = require("../../../../client/pointer.coffee"),
3 | form = require("../../../form.js"),
4 | print = require("../../../../core/console/print.coffee")
5 |
6 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7 | // Creates and styles the main drop button.
8 | //------------------------------------------------------------------------------
9 | module.exports = function ( vars ) {
10 |
11 | if ( !("button" in vars.container) ) {
12 |
13 | if ( vars.dev.value ) print.time("creating main button")
14 |
15 | vars.container.button = form()
16 | .container(vars.container.ui)
17 | .type("button")
18 | .ui({
19 | "margin": 0
20 | })
21 |
22 | if ( vars.dev.value ) print.timeEnd("creating main button")
23 |
24 | }
25 |
26 | if ( vars.focus.changed || vars.data.changed || vars.depth.changed ) {
27 |
28 | var depth = vars.depth.value
29 |
30 | var buttonData = copy(vars.data.value.filter(function(d){
31 | var match = false
32 | for ( var i = 0 ; i < vars.id.nesting.length ; i++ ) {
33 | var level = vars.id.nesting[i]
34 | match = level in d && d[level] === vars.focus.value
35 | if (match) {
36 | depth = i
37 | break
38 | }
39 | }
40 | return match
41 | })[0])
42 |
43 | if ( !buttonData ) {
44 | buttonData = vars.container.button.data()[0] || vars.data.viz[0]
45 | }
46 |
47 | vars.container.button
48 | .data([buttonData])
49 | .id( vars.id.nesting )
50 | .depth(depth)
51 |
52 | }
53 |
54 | vars.container.button
55 | .draw({
56 | "update": vars.draw.update
57 | })
58 | .focus(vars.focus.value)
59 | .font( vars.font )
60 | .icon({
61 | "button": vars.icon.drop.value,
62 | "select": vars.icon.drop.value,
63 | "value": vars.icon.value
64 | })
65 | .text( vars.text.value )
66 | .timing({
67 | "ui": vars.draw.timing
68 | })
69 | .ui({
70 | "color": vars.ui.color,
71 | "padding": vars.ui.padding
72 | })
73 | .width(vars.width.value)
74 | .draw()
75 |
76 | var button = vars.container.button.container(Object).ui
77 |
78 | vars.margin.top += button.node().offsetHeight || button.node().getBoundingClientRect().height
79 |
80 | button.on(events.click,function(){
81 | vars.self.open(!vars.open.value).draw()
82 | })
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/viz/types/bar.coffee:
--------------------------------------------------------------------------------
1 | fetchValue = require "../../core/fetch/value.js"
2 | graph = require "./helpers/graph/draw.coffee"
3 | nest = require "./helpers/graph/nest.coffee"
4 | stack = require "./helpers/graph/stack.coffee"
5 |
6 | # Line Plot
7 | bar = (vars) ->
8 |
9 | discrete = vars.axes.discrete
10 | h = if discrete is "x" then "height" else "width"
11 | w = if discrete is "x" then "width" else "height"
12 | opposite = vars.axes.opposite
13 | cMargin = if discrete is "x" then "left" else "top"
14 | oMargin = if discrete is "x" then "top" else "left"
15 |
16 | data = vars.data.viz.filter (d) -> fetchValue vars, d, vars[opposite].value
17 |
18 | return [] unless data.length
19 |
20 | graph vars,
21 | buffer: true
22 | zero: vars.axes.opposite
23 |
24 | nested = nest vars, data
25 |
26 | stack vars, nested if vars.axes.stacked
27 |
28 | space = vars.axes[w] / vars[vars.axes.discrete].ticks.values.length
29 |
30 | if vars.axes.stacked
31 | maxSize = space - vars.labels.padding * 4
32 | else
33 | maxSize = space / nested.length
34 | maxSize -= vars.labels.padding * 2
35 | offset = space/2 - maxSize/2 - vars.labels.padding * 2
36 |
37 | x = d3.scale.linear()
38 | .domain [0, nested.length-1]
39 | .range [-offset, offset]
40 |
41 | for point, i in nested
42 | mod = if vars.axes.stacked then 0 else x(i)
43 | for d in point.values
44 |
45 | d.d3plus[discrete] = vars[discrete].scale.viz fetchValue(vars, d, vars[discrete].value)
46 | d.d3plus[discrete] += vars.axes.margin[cMargin] + mod
47 |
48 | if vars.axes.stacked
49 | base = d.d3plus[opposite+"0"]
50 | value = d.d3plus[opposite]
51 | length = base - value
52 | else
53 | base = vars[opposite].scale.viz(0)
54 | value = vars[opposite].scale.viz fetchValue(vars, d, vars[opposite].value)
55 | length = base - value
56 |
57 | d.d3plus[opposite] = base - length/2
58 | d.d3plus[opposite] += vars.axes.margin[oMargin] unless vars.axes.stacked
59 |
60 | d.d3plus[w] = maxSize
61 | d.d3plus[h] = Math.abs length
62 | d.d3plus.init = {}
63 | d.d3plus.init[opposite] = vars[opposite].scale.viz(0) - d.d3plus[opposite] + vars.axes.margin[oMargin]
64 | d.d3plus.init[w] = d.d3plus[w]
65 |
66 | d.d3plus.label = false
67 |
68 | data
69 |
70 | # Visualization Settings and Helper Functions
71 | bar.requirements = ["data", "x", "y"]
72 | bar.setup = (vars) -> vars.self.x scale: "discrete" unless vars.axes.discrete
73 | bar.shapes = ["square"]
74 | bar.tooltip = "static"
75 |
76 | module.exports = bar
77 |
--------------------------------------------------------------------------------
/src/core/console/print.coffee:
--------------------------------------------------------------------------------
1 | ie = require "../../client/ie.js"
2 | wiki = require "./wiki.coffee"
3 |
4 | # Custom styling and behavior for browser console statements.
5 | print = (type, message, style) ->
6 | style = style or ""
7 | if ie or typeof InstallTrigger isnt 'undefined'
8 | console.log "[ D3plus ] " + message
9 | else if type is "groupCollapsed"
10 | if window.chrome and navigator.onLine
11 | console[type] "%c%c " + message, "padding:3px 10px;line-height:25px;background-size:20px;background-position:top left;background-image:url('http://d3plus.org/assets/img/favicon.ico');", "font-weight:200;" + style
12 | else
13 | console[type] "%cD3plus%c " + message, "line-height:25px;font-weight:800;color:#b35c1e;margin-left:0px;", "font-weight:200;" + style
14 | else
15 | console[type] "%c" + message, style + "font-weight:200;"
16 | return
17 |
18 | print.comment = (message) ->
19 | this "log", message, "color:#aaa;"
20 | return
21 |
22 | print.error = (message, url) ->
23 | this "groupCollapsed", "ERROR: " + message, "font-weight:800;color:#D74B03;"
24 | @stack()
25 | @wiki url
26 | @groupEnd()
27 | return
28 |
29 | print.group = (message) ->
30 | this "group", message, "color:#888;"
31 | return
32 |
33 | print.groupCollapsed = (message) ->
34 | this "groupCollapsed", message, "color:#888;"
35 | return
36 |
37 | print.groupEnd = ->
38 | console.groupEnd() unless ie
39 | return
40 |
41 | print.log = (message) ->
42 | this "log", message, "color:#444444;"
43 | return
44 |
45 | print.stack = ->
46 | unless ie
47 | err = new Error()
48 | if err.stack
49 | stack = err.stack.split("\n")
50 | stack = stack.filter((e) ->
51 | e.indexOf("Error") isnt 0 and e.indexOf("d3plus.js:") < 0 and e.indexOf("d3plus.min.js:") < 0
52 | )
53 | if stack.length and stack[0].length
54 | splitter = (if window.chrome then "at " else "@")
55 | url = stack[0].split(splitter)[1]
56 | stack = url.split(":")
57 | stack.pop() if stack.length is 3
58 | line = stack.pop()
59 | page = stack.join(":").split("/")
60 | page = page[page.length - 1]
61 | message = "line " + line + " of " + page + ": " + url
62 | this "log", message, "color:#D74B03;"
63 | return
64 |
65 | print.time = (message) ->
66 | console.time message unless ie
67 | return
68 |
69 | print.timeEnd = (message) ->
70 | console.timeEnd message unless ie
71 | return
72 |
73 | print.warning = (message, url) ->
74 | this "groupCollapsed", message, "color:#888;"
75 | @stack()
76 | @wiki url
77 | @groupEnd()
78 | return
79 |
80 | print.wiki = (url) ->
81 | if url
82 | if url of wiki
83 | url = d3plus.repo + "wiki/" + wiki[url]
84 | this "log", "documentation: " + url, "color:#aaa;"
85 | return
86 |
87 | module.exports = print
88 |
--------------------------------------------------------------------------------
/src/viz/helpers/shapes/arc.coffee:
--------------------------------------------------------------------------------
1 | shapeStyle = require "./style.coffee"
2 | largestRect = require "../../../geom/largestRect.coffee"
3 | path2poly = require "../../../geom/path2poly.coffee"
4 |
5 | module.exports = (vars, selection, enter, exit) ->
6 |
7 | arc = d3.svg.arc()
8 | .innerRadius 0
9 | .outerRadius (d) -> d.d3plus.r
10 | .startAngle (d) -> d.d3plus.startAngle
11 | .endAngle (d) -> d.d3plus.endAngle
12 |
13 | # Calculate label position and pass data from parent.
14 | data = (d) ->
15 | if vars.labels.value
16 | if d.d3plus.label
17 | d.d3plus_label = d.d3plus.label
18 | else
19 | poly = path2poly(arc(d))
20 | rect = largestRect poly,
21 | angle: 0
22 | if rect[0]
23 | d.d3plus_label =
24 | w: rect[0].width
25 | h: rect[0].height
26 | x: rect[0].cx
27 | y: rect[0].cy
28 | else
29 | delete d.d3plus_label
30 | [d]
31 |
32 | if vars.draw.timing
33 |
34 | newarc = d3.svg.arc()
35 | .innerRadius 0
36 | .outerRadius (d) -> d.d3plus.r
37 | .startAngle (d) ->
38 | d.d3plus.startAngleCurrent = 0 if d.d3plus.startAngleCurrent is undefined
39 | d.d3plus.startAngleCurrent = d.d3plus.startAngle if isNaN(d.d3plus.startAngleCurrent)
40 | d.d3plus.startAngleCurrent
41 | .endAngle (d) ->
42 | d.d3plus.endAngleCurrent = 0 if d.d3plus.endAngleCurrent is undefined
43 | d.d3plus.endAngleCurrent = d.d3plus.endAngle if isNaN(d.d3plus.endAngleCurrent)
44 | d.d3plus.endAngleCurrent
45 |
46 | arcTween = (arcs, newAngle) ->
47 | arcs.attrTween "d", (d) ->
48 |
49 | if newAngle is undefined
50 | s = d.d3plus.startAngle
51 | e = d.d3plus.endAngle
52 | else if newAngle is 0
53 | s = 0
54 | e = 0
55 |
56 | interpolateS = d3.interpolate(d.d3plus.startAngleCurrent, s)
57 | interpolateE = d3.interpolate(d.d3plus.endAngleCurrent, e)
58 | (t) ->
59 | d.d3plus.startAngleCurrent = interpolateS(t)
60 | d.d3plus.endAngleCurrent = interpolateE(t)
61 | newarc d
62 |
63 | enter.append("path")
64 | .attr "class", "d3plus_data"
65 | .call shapeStyle, vars
66 | .attr "d", newarc
67 |
68 | selection.selectAll("path.d3plus_data").data data
69 | .transition().duration vars.draw.timing
70 | .call shapeStyle, vars
71 | .call arcTween
72 |
73 | exit.selectAll("path.d3plus_data")
74 | .transition().duration vars.draw.timing
75 | .call arcTween, 0
76 |
77 | else
78 |
79 | enter.append("path").attr "class", "d3plus_data"
80 |
81 | selection.selectAll("path.d3plus_data").data data
82 | .call shapeStyle, vars
83 | .attr "d", arc
84 |
85 | return
86 |
--------------------------------------------------------------------------------
/src/viz/types/helpers/graph/includes/buffer.coffee:
--------------------------------------------------------------------------------
1 | closest = require "../../../../../util/closest.coffee"
2 |
3 | module.exports = (vars, axis, buffer) ->
4 |
5 | if vars[axis].scale.value isnt "share" and !vars[axis].range.value
6 |
7 | if axis is vars.axes.discrete
8 |
9 | domain = vars[axis].scale.viz.domain()
10 | domain = domain.slice().reverse() if axis is "y"
11 |
12 | if vars[axis].ticks.values.length is 1
13 | if vars[axis].value is vars.time.value and vars.data.time.ticks.length isnt 1
14 | closestTime = closest(vars.data.time.ticks, domain[0])
15 | timeIndex = vars.data.time.ticks.indexOf(closestTime)
16 | if timeIndex > 0
17 | domain[0] = vars.data.time.ticks[timeIndex - 1]
18 | else
19 | diff = vars.data.time.ticks[timeIndex + 1] - closestTime
20 | domain[0] = new Date(closestTime.getTime() - diff)
21 | if timeIndex < vars.data.time.ticks.length - 1
22 | domain[1] = vars.data.time.ticks[timeIndex + 1]
23 | else
24 | diff = closestTime - vars.data.time.ticks[timeIndex - 1]
25 | domain[1] = new Date(closestTime.getTime() + diff)
26 | else
27 | domain[0] -= 1
28 | domain[1] += 1
29 | else
30 | difference = Math.abs domain[1] - domain[0]
31 | additional = difference / (vars[axis].ticks.values.length - 1)
32 | additional = additional / 2
33 |
34 | domain[0] = domain[0] - additional
35 | domain[1] = domain[1] + additional
36 |
37 | domain = domain.reverse() if axis is "y"
38 | vars[axis].scale.viz.domain(domain)
39 |
40 | else if (buffer is "x" and axis is "x") or (buffer is "y" and axis is "y") or (buffer is true)
41 |
42 | domain = vars[axis].scale.viz.domain()
43 | domain = domain.slice().reverse() if axis is "y"
44 |
45 | allPositive = domain[0] >= 0 and domain[1] >= 0
46 | allNegative = domain[0] <= 0 and domain[1] <= 0
47 |
48 | additional = Math.abs(domain[1] - domain[0]) * 0.05
49 |
50 | domain[0] = domain[0] - additional
51 | domain[1] = domain[1] + additional
52 |
53 | domain[0] = 0 if (allPositive and domain[0] < 0) or (allNegative and domain[0] > 0)
54 | domain[1] = 0 if (allPositive and domain[1] < 0) or (allNegative and domain[1] > 0)
55 |
56 | domain = domain.reverse() if axis is "y"
57 |
58 | vars[axis].scale.viz.domain(domain)
59 |
60 | else if vars.axes.scale
61 |
62 | rangeMax = vars[axis].scale.viz.range()[1]
63 | maxSize = vars.axes.scale.range()[1]
64 |
65 | domainHigh = vars[axis].scale.viz.invert -maxSize * 2
66 | domainLow = vars[axis].scale.viz.invert rangeMax + maxSize * 2
67 |
68 | if domainHigh is domainLow
69 | domainHigh += 1
70 | domainLow -= 1
71 |
72 | vars[axis].scale.viz.domain([domainHigh,domainLow])
73 |
--------------------------------------------------------------------------------
/src/form/types/button/button.js:
--------------------------------------------------------------------------------
1 | var print = require("../../../core/console/print.coffee"),
2 | color = require("./functions/color.js"),
3 | icons = require("./functions/icons.js"),
4 | mouseevents = require("./functions/mouseevents.js"),
5 | style = require("./functions/style.js")
6 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7 | // Creates a Button
8 | //------------------------------------------------------------------------------
9 | module.exports = function( vars ) {
10 |
11 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12 | // Bind Data to Buttons
13 | //----------------------------------------------------------------------------
14 | var button = vars.container.ui.selectAll("div.d3plus_node")
15 | .data(vars.data.viz,function(d){
16 | return d[vars.id.value]
17 | })
18 |
19 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20 | // Enter Buttons
21 | //----------------------------------------------------------------------------
22 | if ( vars.dev.value ) print.time("enter")
23 |
24 | button.enter().append("div")
25 | .attr("class","d3plus_node")
26 | .call( color , vars )
27 | .call( style , vars )
28 | .call( icons , vars )
29 | .call( mouseevents , vars , color )
30 |
31 | if ( vars.dev.value ) print.timeEnd("enter")
32 |
33 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34 | // Update Buttons
35 | //----------------------------------------------------------------------------
36 | if (vars.draw.update || vars.draw.timing) {
37 |
38 | if ( vars.dev.value ) print.time("ordering")
39 | button.order()
40 | if ( vars.dev.value ) print.timeEnd("ordering")
41 |
42 | var updatedButtons = button
43 |
44 | }
45 | else {
46 |
47 | var checks = [ vars.focus.previous
48 | , vars.focus.value
49 | , vars.hover.previous
50 | , vars.hover.value ].filter(function(c){ return c })
51 |
52 | var updatedButtons = button.filter(function(b){
53 | return checks.indexOf(b[vars.id.value]) >= 0
54 | })
55 |
56 | }
57 |
58 | if ( vars.dev.value ) print.time("update")
59 | if (vars.draw.timing) {
60 | updatedButtons
61 | .transition().duration(vars.draw.timing)
62 | .call( color , vars )
63 | .call( style , vars )
64 | }
65 | else {
66 | updatedButtons
67 | .call( color , vars )
68 | .call( style , vars )
69 | }
70 |
71 | updatedButtons
72 | .call( icons , vars )
73 | .call( mouseevents , vars , color )
74 | if ( vars.dev.value ) print.timeEnd("update")
75 |
76 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
77 | // Exit Buttons
78 | //----------------------------------------------------------------------------
79 | button.exit().remove()
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/items.coffee:
--------------------------------------------------------------------------------
1 | active = require("./active.js")
2 | copy = require("../../../../util/copy.coffee")
3 | form = require("../../../form.js")
4 | print = require("../../../../core/console/print.coffee")
5 |
6 | # Populates item list based on filtered data.
7 | module.exports = (vars) ->
8 |
9 | if vars.open.value
10 |
11 | print.time "updating list items" if vars.dev.value
12 |
13 | unless "items" of vars.container
14 | vars.container.items = form()
15 | .container vars.container.list
16 | .type "button"
17 | .ui
18 | border: 0
19 | display: "block"
20 | margin: 0
21 | .width(false)
22 |
23 | large = if vars.draw.timing then vars.data.large else 1
24 | order = copy vars.order
25 | order.value = (if vars.text.solo.value.length and vars.text.solo.value[0] isnt "" then "d3plus_order" else vars.order.value)
26 | deepest = vars.depth.value is vars.id.nesting.length - 1
27 |
28 | if vars.focus.changed or not vars.container.items.focus().length
29 |
30 | vars.container.items
31 | .focus vars.focus.value, (value) ->
32 |
33 | change = value isnt vars.focus.value
34 | change = active(vars, value) if change and vars.active.value
35 |
36 | vars.self.focus value if change
37 |
38 | data = vars.data.filtered.filter((f) ->
39 | f[vars.id.value] is value
40 | )[0]
41 |
42 | if vars.depth.value < vars.id.nesting.length - 1 and vars.id.nesting[vars.depth.value + 1] of data
43 | depth = vars.depth.value
44 | solo = vars.id.solo.value
45 | vars.history.states.push -> vars.self.depth(depth).id(solo: solo).draw()
46 | vars.self.depth(vars.depth.value + 1).id(solo: [value]).draw()
47 | else unless vars.depth.changed
48 | vars.self.open(false).draw()
49 | else vars.self.draw() if change
50 |
51 | return
52 |
53 | if vars.data.changed
54 | vars.container.items
55 | .data
56 | large: large
57 | value: vars.data.filtered
58 |
59 | vars.container.items
60 | .active vars.active.value
61 | .draw
62 | update: vars.draw.update
63 | .font vars.font.secondary
64 | .id vars.id.value
65 | .icon
66 | button: (if deepest then false else vars.icon.next)
67 | select: (if deepest then vars.icon.select else false)
68 | .order order
69 | .text vars.text.secondary.value or vars.text.value
70 | .timing
71 | ui: vars.draw.timing
72 | .ui
73 | color:
74 | primary: (if vars.id.nesting.length is 1 then vars.ui.color.primary.value else vars.ui.color.secondary.value)
75 | secondary: vars.ui.color.secondary.value
76 | padding: vars.ui.padding
77 | .draw()
78 |
79 | print.timeEnd "updating list items" if vars.dev.value
80 |
81 | return
82 |
--------------------------------------------------------------------------------
/src/form/types/drop/functions/width.js:
--------------------------------------------------------------------------------
1 | var copy = require("../../../../util/copy.coffee"),
2 | fontTester = require("../../../../core/font/tester.coffee"),
3 | form = require("../../../form.js"),
4 | print = require("../../../../core/console/print.coffee"),
5 | validObject = require("../../../../object/validate.coffee")
6 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7 | // If no widths are defined, then this calculates the width needed to fit the
8 | // longest entry in the list.
9 | //------------------------------------------------------------------------------
10 | module.exports = function ( vars ) {
11 |
12 | var data = [], buffer = 0
13 | for ( var level in vars.data.nested.all ) {
14 | var newData = vars.data.nested.all[level]
15 | , key = validObject(vars.text.nesting) && level in vars.text.nesting
16 | ? vars.text.nesting[level][0] : level
17 |
18 | if ( [vars.id.value,vars.text.value].indexOf(key) < 0 ) {
19 | newData = copy(newData)
20 | newData.forEach(function(d){
21 | d[vars.text.value || vars.id.value] = d[key]
22 | })
23 | }
24 | data = data.concat( newData )
25 | }
26 |
27 | function getWidth( type ) {
28 |
29 | var key = type === "primary" ? "value" : type
30 | , icon = key === "value" ? vars.icon.drop.value
31 | : vars.icon.select.value || vars.icon.drop.value
32 | , text = key === "value" ? vars.text.value
33 | : vars.text.secondary.value || vars.text.value
34 | , font = key === "value" ? vars.font : vars.font.secondary
35 |
36 | if ( vars.dev.value ) print.time("calculating "+type+" width")
37 |
38 | var button = form()
39 | .container( fontTester() )
40 | .data({
41 | "large": 9999,
42 | "value": data
43 | })
44 | .draw({ "update": false })
45 | .font( font )
46 | .icon({ "button": icon, "value": vars.icon.value })
47 | .id(vars.id.value)
48 | .timing({
49 | "ui": 0
50 | })
51 | .text( text || vars.id.value )
52 | .type( "button" )
53 | .ui({
54 | "border": type === "primary" ? vars.ui.border : 0,
55 | "display": "inline-block",
56 | "margin": 0,
57 | "padding": vars.ui.padding
58 | })
59 | .width(false)
60 | .draw()
61 |
62 | var w = []
63 | button.selectAll("div.d3plus_node").each(function(o){
64 | w.push(this.offsetWidth)
65 | }).remove()
66 |
67 | var dropWidth = {}
68 | dropWidth[key] = d3.max(w)
69 |
70 | vars.self.width( dropWidth )
71 |
72 | if ( vars.dev.value ) print.timeEnd("calculating "+type+" width")
73 |
74 | }
75 |
76 | if ( typeof vars.width.value !== "number" ) {
77 |
78 | getWidth( "primary" )
79 |
80 | }
81 |
82 | if ( typeof vars.width.secondary !== "number" ) {
83 |
84 | if ( !vars.text.secondary.value || vars.text.value === vars.text.secondary.value ) {
85 | vars.self.width({"secondary": vars.width.value})
86 | }
87 | else {
88 | getWidth( "secondary" )
89 | }
90 |
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------