From 6ac65e6aceda3e360de8f6bedd3cb27dbdd4fd29 Mon Sep 17 00:00:00 2001 From: dsc Date: Wed, 29 Feb 2012 09:03:40 -0800 Subject: [PATCH] Updates todo and adds notes from various planning meetings. --- docs/graphs.md | 47 -- docs/notes.md | 10 - docs/notes/graphs.md | 47 ++ docs/notes/notes.md | 10 + docs/notes/prototype-sync-up.mediawiki | 44 + docs/notes/tag-notes.md | 24 + docs/todo.md | 63 ++- lib/base.co | 17 +- lib/graph/graph-model.co | 8 + lib/graph/graph-view.co | 4 +- lib/main.co | 68 ++- lib/scaffold/scaffold-model.co | 24 +- lib/scaffold/scaffold-view.co | 5 +- lib/server/server.co | 19 +- lib/template/graph.jade | 20 +- lib/util/op.co | 2 +- lib/vis/vis-model.co | 30 +- lib/vis/vis-view.co | 64 +- msc/dygraph-options/data.yaml | 1369 +++++++++++++++++--------------- www/css/colors.styl | 4 +- www/css/graph.styl | 31 +- www/graph/test.jade | 1 - www/layout.jade | 17 +- www/modules.yaml | 1 + 24 files changed, 1097 insertions(+), 832 deletions(-) delete mode 100644 docs/graphs.md delete mode 100644 docs/notes.md create mode 100644 docs/notes/graphs.md create mode 100644 docs/notes/notes.md create mode 100644 docs/notes/prototype-sync-up.mediawiki create mode 100644 docs/notes/tag-notes.md diff --git a/docs/graphs.md b/docs/graphs.md deleted file mode 100644 index 19b82b8..0000000 --- a/docs/graphs.md +++ /dev/null @@ -1,47 +0,0 @@ -# Graphs and Metrics for the March Dealine - -## Done - -## Wanted - -- traffic metrics - - page views by language - - page views by project - - mobile stats - - ? - -- editor metrics - - NOTE: all the data files likely contain more raw information than can be displayed with simple line charts. For the Feb deadline it will probably be necessary to sum/average the data into a few descriptive 'totals'. The reason why I don't supply the already aggregated data is because we will be able to build more finegrained ways to explore the data without much effort. - - - number of editors - - all editors (>1 edit) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_1_edit/editors_RelativeAgeAllNamespaces.csv - - active editors (>5 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_5_edits/editors_RelativeAgeAllNamespaces.csv - - very active editors (>100 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_100_edits/editors_RelativeAgeAllNamespaces.csv - - new editors (e.g. <3 months) - sum of the first 3 data columns of 'all editors' csv - - number of edits - - all editors (>1 edit) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_1_edit/edits_RelativeAgeAllNamespaces.csv - - active editors (>5 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_5_edits/edits_RelativeAgeAllNamespaces.csv - - very active editors (>100 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_100_edits/edits_RelativeAgeAllNamespaces.csv - - new editors (e.g. <3 months) - sum of the first 3 data columns of 'all editors' csv - - editor activity histogram - - by number of editors - [dropbox]/enwp/csv/Cohort_trends/Histogram_cohorts/editors_EditorActivity.csv - - by number of edits - [dropbox]/enwp/csv/Cohort_trends/Histogram_cohorts/edits_EditorActivity.csv - - namespace activty - - by number of edits - [dropbox]/enwp/csv/Cohort_trends/Namespaces/edits_NameSpaces.csv - -- article metrics - - articles created over time - - by autoconfirmed editors - - by non-autoconfirmed editors - - by autopatrolled editors - - articles created in different languages - - articles deleted over time - - - - -## Nice to Have - - - diff --git a/docs/notes.md b/docs/notes.md deleted file mode 100644 index c4746e5..0000000 --- a/docs/notes.md +++ /dev/null @@ -1,10 +0,0 @@ -# notes - -## Scaffold Forms - -- Type to form mappings: - - String, Integer, Float -> text - - Boolean -> checkbox - - Object, Array, Function -> textarea - - diff --git a/docs/notes/graphs.md b/docs/notes/graphs.md new file mode 100644 index 0000000..19b82b8 --- /dev/null +++ b/docs/notes/graphs.md @@ -0,0 +1,47 @@ +# Graphs and Metrics for the March Dealine + +## Done + +## Wanted + +- traffic metrics + - page views by language + - page views by project + - mobile stats + - ? + +- editor metrics + + NOTE: all the data files likely contain more raw information than can be displayed with simple line charts. For the Feb deadline it will probably be necessary to sum/average the data into a few descriptive 'totals'. The reason why I don't supply the already aggregated data is because we will be able to build more finegrained ways to explore the data without much effort. + + - number of editors + - all editors (>1 edit) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_1_edit/editors_RelativeAgeAllNamespaces.csv + - active editors (>5 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_5_edits/editors_RelativeAgeAllNamespaces.csv + - very active editors (>100 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_100_edits/editors_RelativeAgeAllNamespaces.csv + - new editors (e.g. <3 months) - sum of the first 3 data columns of 'all editors' csv + - number of edits + - all editors (>1 edit) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_1_edit/edits_RelativeAgeAllNamespaces.csv + - active editors (>5 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_5_edits/edits_RelativeAgeAllNamespaces.csv + - very active editors (>100 edits) - [dropbox]/enwp/csv/Cohort_trends/Relative_age/More_than_100_edits/edits_RelativeAgeAllNamespaces.csv + - new editors (e.g. <3 months) - sum of the first 3 data columns of 'all editors' csv + - editor activity histogram + - by number of editors - [dropbox]/enwp/csv/Cohort_trends/Histogram_cohorts/editors_EditorActivity.csv + - by number of edits - [dropbox]/enwp/csv/Cohort_trends/Histogram_cohorts/edits_EditorActivity.csv + - namespace activty + - by number of edits - [dropbox]/enwp/csv/Cohort_trends/Namespaces/edits_NameSpaces.csv + +- article metrics + - articles created over time + - by autoconfirmed editors + - by non-autoconfirmed editors + - by autopatrolled editors + - articles created in different languages + - articles deleted over time + + + + +## Nice to Have + + + diff --git a/docs/notes/notes.md b/docs/notes/notes.md new file mode 100644 index 0000000..c4746e5 --- /dev/null +++ b/docs/notes/notes.md @@ -0,0 +1,10 @@ +# notes + +## Scaffold Forms + +- Type to form mappings: + - String, Integer, Float -> text + - Boolean -> checkbox + - Object, Array, Function -> textarea + + diff --git a/docs/notes/prototype-sync-up.mediawiki b/docs/notes/prototype-sync-up.mediawiki new file mode 100644 index 0000000..a78bea4 --- /dev/null +++ b/docs/notes/prototype-sync-up.mediawiki @@ -0,0 +1,44 @@ +What data? Agreement to focus on extant reportcard metrics: +* Visitors + ** Mostly comScore data: Unique Visitors, Reach % -- otto is on it; says "super easy" to convert to dygraph format + ** Referrer data? otto says it's in the CSVs & totes easy +* Mobile + *** where is ezachte's processed data used to make the pie chart? (otto will email) + *** dietz will parse HTML to extract mobile data from http://stats.wikimedia.org/EN/TablesPageViewsMonthlyMobile.htm + *** otto will aggregate from ezachte's CSVs after dealing with visitors +* Editors + ** fabz has x6 datasets -- see docs/graph.md for more details +* Wiki Content + ** otto will aggregate last if there is time +* Pageviews + * Mostly done and in data dir already (otto) + +UI -- dsc +* Add fields for graph metadata +* Cascading graph option presets +* Add option for a "Benchmark Value" on the graph +* Datasource UI + ** Sources Selector: list datasets via YAML metadata descriptor files + ** Metric Selector: select metrics out of a dataset + ** Date range selector? + ** Configure Metric for Graph: choose color, label, formatting, and transform (low-pri -- can hardcode for now) +* Graph Edit UI + ** Tabbed main container + ** Hide callback options + ** Redraw button + ** Add new tags + tag for "common"/"important" options + ** List tags to toggle all matching options + ** (work beyond here is low-pri) + *** Typeahead filter box for names/tags + *** Sort by Importance, Tag, Lexical + *** Collapse/uncollapse all + *** Reset all options to defaults + *** Outline modified options + +Other Business +* Need to write documentation about how to use this and gather feedback +* dsc to email Moeller and figure out schedule +* otto to email ezachte to figure out source for mobile graphs on stats.wikimedia.org + + + diff --git a/docs/notes/tag-notes.md b/docs/notes/tag-notes.md new file mode 100644 index 0000000..afb83cf --- /dev/null +++ b/docs/notes/tag-notes.md @@ -0,0 +1,24 @@ + +chart: title, titleHeight, + +axis-appearance + +x-axis: xlabel, xLabelHeight, drawXAxis, xAxisHeight, xAxisLabelWidth, xValueParser, drawXGrid, + +y-axis: ylabel, y2label, yLabelHeight, avoidMinZero, drawYAxis, includeZero, logscale, yAxisLabelWidth, valueRange, drawYGrid, labelsKMB, digitsAfterDecimal, labelsKMG2, maxNumberWidth, sigFigs, + +axes: axis, axisLabelColor, axisLabelFontSize, axisLabelFormatter, axisLabelWidith, axisLineColor, axisLineWidth, axisTickSize, pixelPerLabel, ticker, dateWindow + +line: connectSeparatedPoints, drawPoints, pointSize, strokePattern, strokeWidth, colorSaturation, colorValue, colors, + +graph: fillGraph, stackedGraph, stepPlot, panEdgeFraction, gridLineColor, gridLineWidth, highlightCircleSize, rangeSelectorHeight, rangeSelectorPlotFillColor, rangeSelectorPlotStrokeColor, showRangeSelector, rightGap, timingName, visibility + +legend: labelsDiv, labelsDivStyles, labelsDivWidth, labelsSeparateLines, labelsShowZeroValues, legend, showLabelsOnHighlight, + +callback: pointClickCallback, annotationClickHandler, annotationMouseOutHandler, annotationMouseOverHandler, valueFormatter, clickCallback, drawCallback, highlightCallback, underlayCallback, unhighlightCallback, zoomCallback, + +statistics: sigma, wilsonInterval, fillAlpha, customBars, errorBars, fractions, rollPeriod, showRoller, + +data: delimiter, displayAnnotations, + +interactivity: animatedZooms, hideOverlayOnMouseOut, isZoomedIgnoreProgrammaticZoom diff --git a/docs/todo.md b/docs/todo.md index 723a801..2683b03 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,28 +1,47 @@ # todo -- [graph options] - - special 'auto' value for width & height to fit to page-size - - non-lib option: redraw on page resize - - hide callbacks & handlers +- cascading presets +- base preset +- pass label element +- tags -> hidden detection: callbacks, deprecated, type=function +- title element to replace title option -## features -- Bookmarkable Graphs - - Load graph from URL - - Update URL when graph changes -- Ability to merge & filter datasets -- Discoverable & Self-Describing Data Sources - - ToC endpoint - - Metadata endpoint for each datasource/dataset - - (Both could be static files -- "endpoint" just means a convention to the URLs) -- Persist graph settings as a preset on the server -- Dashboard Configuration - - list of graphs w/ configuration identifiers +##### ohai ##### + +[Other Business] +- Need to write documentation about how to use this and gather feedback +- **dsc** to email Moeller and figure out schedule +- **otto** to email ezachte to figure out source for mobile graphs on stats.wikimedia.org ## ux +- Add fields for graph metadata (name, desc, slug, w/h, dataset) +- Cascading graph option presets +- Add option for a "Benchmark Value" on the graph +- [Datasource UI] + - Sources Selector: list datasets via YAML metadata descriptor files + - Metric Selector: select metrics out of a dataset + - Date range selector? + - Configure Metric for Graph: choose color, label, formatting, and transform (low-pri -- can hardcode for now) +- [Graph Edit UI] + - Tabbed main container + - Hide callback options + - Redraw button + - Add new tags + tag for "common"/"important" options + - List tags to toggle all matching options + - (work beyond here is low-pri) + - non-lib option: redraw graph on page resize + - Typeahead filter box for names/tags + - Sort by Importance, Tag, Lexical + - Collapse/uncollapse all + - Reset all options to defaults + - Outline modified options + +### later + - Filter/Sort attributes, datasets, etc - Improve graph color defaults - Stacked bar charts seem to be something a lot of us are into, but dygraphs won't be doing that. (tho d3 does) @@ -32,6 +51,18 @@ - Outline all changed options +## features + +- Ability to merge & filter datasets +- Discoverable & Self-Describing Data Sources + - ToC endpoint + - Metadata endpoint for each datasource/dataset + - (Both could be static files -- "endpoint" just means a convention to the URLs) +- Persist graph settings as a preset on the server +- Dashboard Configuration + - list of graphs w/ configuration identifiers + + ## notes diff --git a/lib/base.co b/lib/base.co index f3766f4..3f96421 100644 --- a/lib/base.co +++ b/lib/base.co @@ -12,8 +12,17 @@ BaseModel = exports.BaseModel = Backbone.Model.extend do # {{{ ctorName : 'BaseModel' initialize: -> - _.bindAll this, ...@__bind__ if @__bind__.length @__super__ = @constructor.__super__ + _.bindAll this, ...@__bind__ if @__bind__.length + + serialize: (v) -> + if v!? + v = '' + else if _.isBoolean v + v = Number v + else if _.isObject v + v = JSON.stringify v + String v /** * Like `.toJSON()` in that it should return a plain object with no functions, @@ -22,7 +31,10 @@ BaseModel = exports.BaseModel = Backbone.Model.extend do # {{{ * @returns {Object} */ toKVObject: -> - _.collapseObject @toJSON() + kvo = _.collapseObject @toJSON() + for k, v in kvo + kvo[k] = @serialize v + kvo /** * Serialize the model into a `www-form-encoded` string suitable for use as @@ -85,6 +97,7 @@ BaseView = exports.BaseView = Backbone.View.extend do # {{{ _.bindAll this, ...@__bind__ if @__bind__.length @__super__ = @constructor.__super__ + @build() @model.view = this @$el.data { @model, view:this } @model.on 'change', @render, this diff --git a/lib/graph/graph-model.co b/lib/graph/graph-model.co index 2728efa..372fb66 100644 --- a/lib/graph/graph-model.co +++ b/lib/graph/graph-model.co @@ -4,6 +4,8 @@ _ = require 'kraken/underscore' { Field, FieldList, FieldView, Scaffold, } = require 'kraken/scaffold' +IGNORED_TAGS = exports.IGNORED_TAGS = <[ callback deprecated debugging ]> + class exports.TagSet extends Array @@ -48,6 +50,12 @@ GraphOption = exports.GraphOption = Field.extend do # {{{ # Notify Tag indexer of category when created, to ensure all category-tags # get indices with colors :P KNOWN_TAGS.update @getCategory() + + # Ignore functions/callbacks and, ahem, hidden tags. + type = @get 'type', '' .toLowerCase() + tags = @get 'tags', [] + if _.str.include(type, 'function') or _.intersection tags, IGNORED_TAGS .length + @set 'ignore', true # Wrapper to ensure @set('tags') is called, as tags.push() diff --git a/lib/graph/graph-view.co b/lib/graph/graph-view.co index 4087cf5..3d87cb0 100644 --- a/lib/graph/graph-view.co +++ b/lib/graph/graph-view.co @@ -58,8 +58,10 @@ GraphOptionsScaffold = exports.GraphOptionsScaffold = Scaffold.extend do # {{{ ctorName : 'GraphOptionsScaffold' tagName : 'form' className : 'options scaffold' + template : require 'kraken/template/graph-scaffold' collectionType : GraphOptionList subviewType : GraphOptionView + $fields : '.fields' # GraphView will set this ready : false @@ -74,7 +76,7 @@ GraphOptionsScaffold = exports.GraphOptionsScaffold = Scaffold.extend do # {{{ # console.log "#this.render() -> .isotope()" @__super__.render ... return this unless @ready - @$el.isotope do + @$el.find '.options.control-group' .isotope do itemSelector : '.field.option' layoutMode : 'masonry' masonry : columnWidth : 10 diff --git a/lib/main.co b/lib/main.co index 43962e4..a90bd2a 100644 --- a/lib/main.co +++ b/lib/main.co @@ -1,3 +1,4 @@ +Seq = require 'seq' { _, op, } = require 'kraken/util' { BaseView, BaseModel, BaseList, @@ -10,37 +11,62 @@ { VisView, VisModel, } = require 'kraken/vis' -root = do -> this +root = this +CHART_OPTIONS_SPEC = [] +ROOT_VIS_DATA = {} +ROOT_VIS_OPTIONS = {} + # Create the Graph Scaffold main = -> + # TODO: create a preset manager + # Remove chart options from data so we don't have to deepcopy + ROOT_VIS_OPTIONS := delete root.ROOT_VIS_DATA.options + + # Bind to URL changes History.Adapter.bind window, 'statechange', -> - console.log 'StateChange!', String root.location + console.log 'StateChange!', String(root.location) - graph = root.graph = new VisView do - graph_spec : CHART_OPTIONS_SPEC # If we got querystring args, apply them to the graph - if root.location?.search.slice 1 - g = _.uncollapseObject _.fromKVPairs that - # yarr, have to do options separately or everything goes to shit - options = delete g.options - graph.model.set g, {+silent} - graph.chartOptions options, {+silent} + data = {} + if String(root.location).split '?' .1 + data = _.uncollapseObject _.fromKVPairs that.replace('#', '%23') - # Flush all changes once the DOM settles - _.defer do - -> graph.scaffold.invoke 'change' - 50 + # # yarr, have to do options separately or everything goes to shit + # options = delete data.options + # graph.model.set data, {+silent} + # graph.chartOptions options, {+silent} + # # Flush all changes once the DOM settles + # _.delay do + # -> + # graph.change() + # # graph.scaffold.invoke 'change' + # 50 + + + vis = root.vis = new VisModel data + graph = root.graph = new VisView do + graph_spec : root.CHART_OPTIONS_SPEC + model : vis $ '#content .inner' .append graph.el -jQuery.ajax do - url : '/graph/dygraph-options.json', - dataType : 'json' - success : (data) -> - root.CHART_OPTIONS_SPEC = data - jQuery main - error : (err) -> console.error err + +# Load data files +Seq([ <[ CHART_OPTIONS_SPEC /graph/dygraph-options.json ]>, + <[ ROOT_VIS_DATA /graph/root ]> +]) +.parEach_ (next, [key, url]) -> + jQuery.ajax do + url : url, + dataType : 'json' + success : (data) -> + root[key] = data + next.ok() + error : (err) -> console.error err +.seq -> + console.log 'All data loaded!' + jQuery main diff --git a/lib/scaffold/scaffold-model.co b/lib/scaffold/scaffold-model.co index 8142295..65814ff 100644 --- a/lib/scaffold/scaffold-model.co +++ b/lib/scaffold/scaffold-model.co @@ -14,6 +14,7 @@ Field = exports.Field = BaseModel.extend do # {{{ initialize: -> + _.bindAll this, ...(_.functions this .filter -> _.startsWith(it, 'parse')) @set 'value', @get('default'), {+silent} if not @has 'value' # console.log "#this.initialize!" # @on 'all', (evt) ~> console.log "#this.trigger(#evt)" @@ -38,7 +39,6 @@ Field = exports.Field = BaseModel.extend do # {{{ type = _ (type or @get 'type').toLowerCase() for t of <[ Integer Float Boolean Object Array Function ]> if type.startsWith t.toLowerCase() - # console.log "parse#t ->", @["parse#t"] unless @["parse#t"] return @["parse#t"] @parseString @@ -64,7 +64,7 @@ Field = exports.Field = BaseModel.extend do # {{{ parseFunction: (fn) -> if fn and _.startswith String(fn), 'function' - try eval "(#fn)" catch err + try eval "(#fn)" catch err then null else null @@ -90,21 +90,14 @@ Field = exports.Field = BaseModel.extend do # {{{ /* * * Serializers * * */ serializeValue: -> - v = @getValue() - if v!? - v = '' - else if _.isBoolean v - v = Number v - else if _.isArray(v) or _.isObject(v) - v = JSON.stringify v - String v + @serialize @getValue() toJSON: -> {id:@id} import do _.clone(@attributes) import { value:@getValue(), def:@get('default') } toKVObject: -> - { "#{@id}": @serializeValue() } + { "#{@id}":@serializeValue() } toString: -> "(#{@id}: #{@serializeValue()})" # }}} @@ -118,16 +111,17 @@ FieldList = exports.FieldList = BaseList.extend do # {{{ * Collects a map of fields to their values, excluding those set to `null` or their default. * @returns {Object} */ - values: (keepDefaults=false) -> + values: (opts={}) -> + opts = {-keepDefaults, -serialize} import opts _.synthesize do - if keepDefaults then @models else @models.filter -> not it.isDefault() - -> [ it.get('name'), it.getValue() ] + if opts.keepDefaults then @models else @models.filter -> not it.isDefault() + -> [ it.get('name'), if opts.serialize then it.serializeValue() else it.getValue() ] toJSON: -> @values() toKVObject: -> - _.collapseObject @toJSON() + _.collapseObject @values false, true toKVPairs: (item_delim='&', kv_delim='=') -> _.toKVPairs @toKVObject(), item_delim, kv_delim diff --git a/lib/scaffold/scaffold-view.co b/lib/scaffold/scaffold-view.co index 8f2c770..5e4cbfb 100644 --- a/lib/scaffold/scaffold-view.co +++ b/lib/scaffold/scaffold-view.co @@ -28,7 +28,7 @@ FieldView = exports.FieldView = BaseView.extend do # {{{ @trigger 'update', this render: -> - return @remove() if @model.get 'hidden', false + return @remove() if @model.get 'ignore', false return BaseView::render ... if @template name = @model.get 'name' @@ -74,6 +74,7 @@ Scaffold = exports.Scaffold = BaseView.extend do # {{{ addOne: (field) -> # console.log "[S] #this.addOne!", @__super__ + fields = if @$fields then @$el.find that else @$el _.remove @subviews, field.view if field.view # avoid duplicating event propagation @@ -85,7 +86,7 @@ Scaffold = exports.Scaffold = BaseView.extend do # {{{ SubviewType = @subviewType view = new SubviewType model:field @subviews.push view - @$el.append view.render().el unless field.get 'hidden' + fields.append view.render().el unless field.get 'ignore' view.on 'update', @change.bind(this, field) @render() diff --git a/lib/server/server.co b/lib/server/server.co index db5df45..3281595 100755 --- a/lib/server/server.co +++ b/lib/server/server.co @@ -2,6 +2,7 @@ fs = require 'fs' path = require 'path' +{existsSync:exists} = path {exec, spawn} = require 'child_process' _ = require 'underscore' @@ -65,6 +66,9 @@ app.configure -> # Allow "spoofing" HTTP methods that IE doesn't support app.use express.methodOverride() + # Route to the web services + app.use app.router + # Transparently recompile modules that have changed app.use compiler do enabled : <[ coco jade-browser stylus yaml ]> @@ -95,9 +99,6 @@ app.configure -> app.use express.static VAR app.use express.static STATIC - # Route to the web services - app.use app.router - # Serve directory listings app.use express.directory WWW app.use express.directory VAR @@ -113,6 +114,13 @@ app.configure -> app.get '/', (req, res) -> res.render 'dashboard' +app.get '/graph/:id', (req, res, next) -> + {id} = req.params + console.log req.url + if exists("#WWW/graph/#id.yaml") or exists("#WWW/graph/#id.json") + req.url += '.json' + next() + YAML_EXT_PAT = /\.ya?ml$/i @@ -167,6 +175,7 @@ app.get '/data/all', (req, res, next) -> console.error that if err.stack res.send { error:String(err), partial_data:data } + app.get '/:type/:action', (req, res, next) -> {type, action} = req.params if path.existsSync "#WWW/#type/#action.jade" @@ -174,6 +183,10 @@ app.get '/:type/:action', (req, res, next) -> else next() + + + + /** * Handle webhook notification to pull from origin. */ diff --git a/lib/template/graph.jade b/lib/template/graph.jade index 962f9e7..0216850 100644 --- a/lib/template/graph.jade +++ b/lib/template/graph.jade @@ -1,37 +1,35 @@ - var id = model.id || model.cid, graph_id = _.domize('graph', id) section.graph(id=graph_id) - .graph-label - .viewport - form.details.form-horizontal .name-row.row-fluid.control-group //- label.name.control-label(for="#{id}_name"): h3 Graph Name - .controls: input.span6.name(type='text', id="#{id}_name", placeholder='Graph Name', value=name) + input.span6.name(type='text', id="#{id}_name", name="name", placeholder='Graph Name', value=name) + + .viewport + .graph-label .row-fluid .half.control-group label.slug.control-label(for='slug') Slug .controls - input.span3.slug(type='text', id='slug', placeholder='graph_slug', value=slug) + input.span3.slug(type='text', id='slug', name='slug', placeholder='graph_slug', value=slug) p.help-block The slug uniquely identifies this graph and will be displayed in the URL. .half.control-group label.dataset.control-label(for='dataset') Data Set .controls - input.span3.dataset(type='text', id='dataset', placeholder='URL to dataset file', value=dataset) + input.span3.dataset(type='text', id='dataset', name='dataset', placeholder='URL to dataset file', value=dataset) p.help-block This dataset filename will soon be replaced by a friendly UI. .row-fluid .half.control-group label.width.control-label(for='width') Width .controls - input.span1.width(type='text', id='width', value=width) + input.span1.width(type='text', id='width', name='width', value=width) p.help-block Choosing 'auto' will size the graph to the viewport bounds. .half.control-group label.height.control-label(for='height') Height - .controls: input.span1.height(type='text', id='height', value=height) + .controls: input.span1.height(type='text', id='height', name='height', value=height) - fieldset.options - legend Graph Options - + diff --git a/lib/util/op.co b/lib/util/op.co index a47465b..ad42271 100644 --- a/lib/util/op.co +++ b/lib/util/op.co @@ -57,7 +57,7 @@ module.exports = op = toInt : (v) -> parseInt v toFloat : (v) -> parseFloat v toStr : (v) -> String v - toObject : (v) -> if typeof v is 'string' then JSON.parse v else v + toObject : (v) -> if typeof v is 'string' then JSON.parse(v) else v # comparison cmp : (x,y) -> if x < y then -1 else (if x > y then 1 else 0) diff --git a/lib/vis/vis-model.co b/lib/vis/vis-model.co index 5bd89c6..99cd073 100644 --- a/lib/vis/vis-model.co +++ b/lib/vis/vis-model.co @@ -2,6 +2,7 @@ _ = require 'kraken/underscore' { BaseModel, BaseView, } = require 'kraken/base' +root = do -> this /** @@ -10,26 +11,44 @@ _ = require 'kraken/underscore' */ VisModel = exports.VisModel = BaseModel.extend do # {{{ ctorName : 'VisModel' - urlRoot : '/graphs' + urlRoot : '/graph' idAttribute : 'slug' initialize : -> + BaseModel::initialize ... name = @get 'name' - if name and not (@id or @get('slug')) + if name and not @get 'slug', @id @set 'slug', _.underscored name + defaults: -> { slug : '' name : '' - dataset : '/data/pageviews_by.timestamp.language.csv' desc : '' + dataset : '/data/pageviews_by.timestamp.language.csv' + # presets : [] width : 'auto' height : 320 - options : {} - } + options : {} import root.ROOT_VIS_OPTIONS + } import root.ROOT_VIS_DATA + + parse: (data) -> + data = JSON.parse data if typeof data is 'string' + for k, v in data + data[k] = Number v if _.contains(<[ width height ]>, k) and v is not 'auto' + data + + set: (values, opts) -> + if arguments.length > 1 and typeof values is 'string' + [k, v, opts] = arguments + values = { "#k": v } + BaseModel::set.call this, @parse(values), opts + + + ### Chart Option Accessors ### hasOption: (key) -> options = @get 'options', {} @@ -51,6 +70,7 @@ VisModel = exports.VisModel = BaseModel.extend do # {{{ @trigger "change:options:#key", this, value, key, opts unless opts.silent + toString: -> "#{@ctorName}(id=#{@id}, name=#{@get 'name'}, dataset=#{@get 'dataset'})" # }}} diff --git a/lib/vis/vis-view.co b/lib/vis/vis-view.co index b707d58..71ff152 100644 --- a/lib/vis/vis-view.co +++ b/lib/vis/vis-view.co @@ -26,8 +26,10 @@ VisView = exports.VisView = BaseView.extend do # {{{ template : require 'kraken/template/graph' events: - 'keypress form.options .value' : 'onKeypress' - 'submit form.options' : 'onSubmit' + 'keypress form.details input[type="text"]' : 'onKeypress' + 'keypress form.options .value' : 'onKeypress' + 'submit form.details' : 'onDetailsSubmit' + 'submit form.options' : 'onOptionsSubmit' ready: false @@ -51,11 +53,10 @@ VisView = exports.VisView = BaseView.extend do # {{{ # console.log 'Model.changed(options) ->', changes @chartOptions changes, {+silent} - @build() @viewport = @$el.find '.viewport' @scaffold = new GraphOptionsScaffold - @$el.find 'fieldset' .append @scaffold.el + @$el.append @scaffold.el @scaffold.collection.reset that if o.graph_spec @scaffold.on 'change', (scaffold, value, key, field) ~> @@ -65,13 +66,21 @@ VisView = exports.VisView = BaseView.extend do # {{{ options = @model.get 'options', {} @chartOptions options, {+silent} + @resizeViewport() _.delay @onReady, DEBOUNCE_RENDER onReady: -> + console.log 'VisView.ready!' @ready = @scaffold.ready = true + @change() @renderAll() + change: -> + @model.change() + @scaffold.invoke 'change' + this + chartOptions: (values, opts) -> # Handle @chartOptions(k, v, opts) @@ -85,7 +94,7 @@ VisView = exports.VisView = BaseView.extend do # {{{ options.get(k)?.setValue v, opts this else - options.values() + options.values() # TODO: pull this from model (must clone), sort out events /** @@ -93,7 +102,7 @@ VisView = exports.VisView = BaseView.extend do # {{{ * @return { width, height } */ resizeViewport: -> - return this unless @ready and @chart + return this unless @ready # Remove old style, as it confuses dygraph after options update @viewport.attr 'style', '' @@ -104,23 +113,19 @@ VisView = exports.VisView = BaseView.extend do # {{{ height = @viewport.height() size = { width, height } @viewport.css size - console.log 'resizeViewport!', JSON.stringify(size), @viewport + # console.log 'resizeViewport!', JSON.stringify(size), @viewport # @chart.resize size if forceRedraw size + render: -> return this unless @ready - - # console.log "#this" - # console.log do - # " .viewport.{ width=%s, height=%s, style=%s }" - # @viewport.css('width') - # @viewport.css('height') - # @viewport.attr 'style' - # console.log ' .options:', JSON.stringify options + console.log 'VisView.render!' size = @resizeViewport() - options = @chartOptions() + options = @chartOptions() import size + options.labelsDiv = @$el.find '.graph-label' .0 + # @chart?.destroy() unless @chart @chart = new Dygraph do @@ -131,15 +136,18 @@ VisView = exports.VisView = BaseView.extend do # {{{ @chart.updateOptions options @chart.resize size - path = root.location?.path or '/' - url = "#path?#{@toKVPairs()}" - # console.log 'History.pushState', url - History.pushState url, @model.get('name', root.document?.title or ''), url + # path = String(root.location?.path or '/') + data = @toJSON() + title = @model.get('name', root.document?.title or '') + url = "?"+@toKVPairs() + # console.log 'History.pushState', JSON.stringify(data), title, url + History.pushState data, title, url this renderAll: -> return this unless @ready + console.log 'VisView.renderAll!' _.invoke @scaffold.subviews, 'render' @scaffold.render() @render() @@ -148,11 +156,23 @@ VisView = exports.VisView = BaseView.extend do # {{{ onKeypress: (evt) -> $(evt.target).submit() if evt.keyCode is 13 - onSubmit: -> - # console.log "#this.onSubmit!" + onDetailsSubmit: -> + console.log "#this.onDetailsSubmit!" + data = _.synthesize do + @$el.find('form.details').serializeArray() + -> [it.name, it.value] + console.log @$el, JSON.stringify data + @model.set data + false + + onOptionsSubmit: -> + console.log "#this.onOptionsSubmit!" @render() false + toJSON: -> + @model.toJSON() + toKVPairs: -> @model.toKVPairs.apply @model, arguments diff --git a/msc/dygraph-options/data.yaml b/msc/dygraph-options/data.yaml index 28edfbd..398d381 100644 --- a/msc/dygraph-options/data.yaml +++ b/msc/dygraph-options/data.yaml @@ -1,108 +1,123 @@ -- name: title +- name: dateWindow tags: - - labels - - display + - interactivity + - axes default: null examples: - - border - - demo - - noise - - styled-chart-labels - - multi-scale - - range-selector - - temperature-sf-ny - type: String - desc: Text to display above the chart. You can supply any HTML for this value, - not just text. If you wish to style it using CSS, use the 'dygraph-label' - or 'dygraph-title' classes. + - dateWindow + - drawing + - is-zoomed-ignore-programmatic-zoom + - link-interaction + - synchronize + - zoom + type: Array of two Dates or numbers + desc: Initially zoom in on a section of the graph. Is of the form [earliest, latest], + where earliest/latest are milliseconds since epoch. If the data for the x-axis + is numeric, the values in dateWindow must also be numbers. By default, the + full range of the input is shown. -- name: xlabel +- name: panEdgeFraction tags: - - labels - - display + - interactivity + - axes + - pan default: null examples: - - border - - demo - - styled-chart-labels - - multi-scale - type: String - desc: Text to display below the chart's x-axis. You can supply any HTML for this - value, not just text. If you wish to style it using CSS, use the 'dygraph-label' - or 'dygraph-xlabel' classes. + - zoom + type: Float + desc: A value representing the farthest a graph may be panned, in percent of the + display. For example, a value of 0.1 means that the graph can only be panned + 10% pased the edges of the displayed values. null means no bounds. -- name: ylabel + + +- name: visibility tags: - - labels + - lines + - data - display - default: null + default: true examples: - - border - - demo - - two-axes - - noise - - styled-chart-labels - - multi-scale - - range-selector - - temperature-sf-ny - - two-axes-vr - type: String - desc: Text to display to the left of the chart's y-axis. You can supply any HTML - for this value, not just text. If you wish to style it using CSS, use the - 'dygraph-label' or 'dygraph-ylabel' classes. The text will be rotated 90 degrees - by default, so CSS rules may behave in unintuitive ways. No additional space - is set aside for a y-axis label. If you need more space, increase the width - of the y-axis tick labels using the yAxisLabelWidth option. If you need a - wider div for the y-axis label, either style it that way with CSS (but remember - that it's rotated, so width is controlled by the 'height' property) or set - the yLabelWidth option. + - color-visibility + - no-visibility + - visibility + type: Array of booleans + desc: Which series should initially be visible? Once the Dygraph has been constructed, + you can access and modify the visibility of each series using the visibility + and setVisibility methods. -- name: y2label +- name: stackedGraph tags: - - labels + - lines + - data - display - default: null + default: false examples: + - stacked + type: Boolean + desc: If set, stack series on top of one another rather than drawing them independently. + +- name: fillGraph + tags: + - lines + - data + - display + default: false + examples: + - fillGraph - two-axes - - two-axes-vr - type: String - desc: Text to display to the right of the chart's secondary y-axis. This label - is only displayed if a secondary y-axis is present. See this test for an example - of how to do this. The comments for the 'ylabel' option generally apply here - as well. This label gets a 'dygraph-y2label' instead of a 'dygraph-ylabel' - class. + - steps + type: Boolean + desc: Should the area underneath the graph be filled? This option is not compatible + with error bars. -- name: titleHeight +- name: strokeWidth tags: - - labels + - lines + - data - display - default: 18 + default: 1 examples: + - linear-regression-addseries + - drawing + - grid_dot + - layout-options + - linear-regression-fractions + - linear-regression + - per-series + - unboxed-spark - styled-chart-labels type: Integer - desc: Height of the chart title, in pixels. This also controls the default font - size of the title. If you style the title on your own, this controls how much - space is set aside above the chart for the title's div. + desc: The width of the lines connecting data points. This can be used to increase + the contrast or some graphs. -- name: xLabelHeight - default: 18 +- name: strokePattern tags: - - labels + - lines + - data - display - type: Integer - desc: Height of the x-axis label, in pixels. This also controls the default font - size of the x-axis label. If you style the label on your own, this controls - how much space is set aside below the chart for the x-axis label's div. + default: null + examples: + - per-series + type: Array + desc: A custom pattern array where the even index is a draw and odd is a space + in pixels. If null then it draws a solid line. The array should have a even + length as any odd lengthed array could be expressed as a smaller even length + array. -- name: yLabelWidth - default: 18 +- name: stepPlot tags: - - labels + - lines + - data - display - type: Integer - desc: Width of the div which contains the y-axis label. Since the y-axis label - appears rotated 90 degrees, this actually affects the height of its div. + default: false + examples: + - avoidMinZero + - steps + - y-axis-formatter + type: Boolean + desc: When set, display the graph as a step plot instead of a line plot. - name: connectSeparatedPoints tags: @@ -124,6 +139,7 @@ tags: - lines - data + - points - display default: false examples: @@ -140,24 +156,11 @@ point. This makes the individual data points easier to see, but can increase visual clutter in the chart. -- name: fillGraph - tags: - - lines - - data - - display - default: false - examples: - - fillGraph - - two-axes - - steps - type: Boolean - desc: Should the area underneath the graph be filled? This option is not compatible - with error bars. - - name: pointSize tags: - lines - data + - points - display default: 1 examples: @@ -167,63 +170,36 @@ dot is always drawn when a point is "isolated", i.e. there is a missing point on either side of it. This also controls the size of those dots. -- name: stackedGraph +- name: rightGap + default: 5 tags: - lines - data + - points - display - default: false - examples: - - stacked - type: Boolean - desc: If set, stack series on top of one another rather than drawing them independently. + type: Integer + desc: Number of pixels to leave blank at the right edge of the Dygraph. This makes + it easier to highlight the right-most data point. -- name: stepPlot - tags: - - lines - - data - - display - default: false - examples: - - avoidMinZero - - steps - - y-axis-formatter - type: Boolean - desc: When set, display the graph as a step plot instead of a line plot. -- name: strokePattern + + +- name: colors tags: - - lines + - color - data - display default: null examples: - - per-series + - century-scale + - color-visibility + - demo + - reverse-y-axis + - color-cycle type: Array - desc: A custom pattern array where the even index is a draw and odd is a space - in pixels. If null then it draws a solid line. The array should have a even - length as any odd lengthed array could be expressed as a smaller even length - array. - -- name: strokeWidth - tags: - - lines - - data - - display - default: 1 - examples: - - linear-regression-addseries - - drawing - - grid_dot - - layout-options - - linear-regression-fractions - - linear-regression - - per-series - - unboxed-spark - - styled-chart-labels - type: Integer - desc: The width of the lines connecting data points. This can be used to increase - the contrast or some graphs. + desc: List of colors for the data series. These can be of the form "#AABBCC" or + "rgb(255,100,200)" or "yellow", etc. If not specified, equally-spaced points + around a color wheel are used. - name: colorSaturation default: 1.0 @@ -236,7 +212,7 @@ series colors. - name: colorValue - default: 1.0 + default: 0.5 tags: - color - data @@ -245,117 +221,324 @@ desc: If colors is not specified, value of the data series colors, as in hue/saturation/value. (0.0-1.0, default 0.5) -- name: colors + + +- name: animatedZooms tags: - - color - - data - - display + - interactivity + - zoom + default: false + examples: + - highlighted-region + - link-interaction + type: Boolean + desc: Set this option to animate the transition between zoom windows. Applies + to programmatic and interactive zooms. Note that if you also set a drawCallback, + it will be called several times on each zoom. If you set a zoomCallback, it + will only be called after the animation is complete. + +- name: highlightCircleSize + tags: + - interactivity + default: 3 + examples: + - dygraph-many-points-benchmark + - grid_dot + - per-series + - unboxed-spark + type: Integer + desc: The size in pixels of the dot drawn over highlighted points. + +- name: interactionModel + ignore: true + tags: + - interactivity default: null examples: - - century-scale - - color-visibility - - demo - - reverse-y-axis - - color-cycle - type: Array - desc: List of colors for the data series. These can be of the form "#AABBCC" or - "rgb(255,100,200)" or "yellow", etc. If not specified, equally-spaced points - around a color wheel are used. + - drawing + - interaction + type: Object + desc: 'TODO(konigsberg): document this' -- name: avoidMinZero +- name: isZoomedIgnoreProgrammaticZoom tags: - - axes + - interactivity + - zoom default: false examples: - - avoidMinZero + - is-zoomed-ignore-programmatic-zoom type: Boolean - desc: "When set, the heuristic that fixes the Y axis at zero for a data set with\ - \ the minimum Y value of zero is disabled. \nThis is particularly useful for\ - \ data sets that contain many zero values, especially for step plots which\ - \ may otherwise have lines not visible running along the bottom axis." + desc: When this option is passed to updateOptions() along with either the dateWindow + or valueRange options, the zoom flags are not changed to reflect a zoomed + state. This is primarily useful for when the display area of a chart is changed + programmatically and also where manual zooming is allowed and use is made + of the isZoomed method to determine this. -- name: axis + + +- name: labels tags: - - axes + - labels + - legend + - display default: null examples: + - linear-regression-addseries + - connect-separated + - drawing + - dygraph + - dygraph-many-points-benchmark + - dynamic-update + - highlighted-region + - independent-series + - isolated-points + - label-div + - link-interaction + - linear-regression + - negative + - missing-data + - native-format - two-axes + - perf + - small-range-zero - steps + - y-axis-formatter + - annotation-native + - multi-scale - two-axes-vr - value-axis-formatters - type: String or Object - desc: Set to either an object ({}) filled with options for this axis or to the - name of an existing data series with its own axis to re-use that axis. See - tests for usage. + type: Array + desc: A name for each data series, including the independent (X) series. For CSV + files and DataTable objections, this is determined by context. For raw data, + this must be specified. If it is not, default values are supplied and a warning + is logged. By default, labels roughly follow ["X", "Y1", "Y2", ...]* -- name: axisLabelColor - default: black +- name: xlabel tags: - - axes - - color - labels + - axes + - display + default: null + examples: + - border + - demo + - styled-chart-labels + - multi-scale type: String - desc: Color for x- and y-axis labels. This is a CSS color string. + desc: Text to display below the chart's x-axis. You can supply any HTML for this + value, not just text. If you wish to style it using CSS, use the 'dygraph-label' + or 'dygraph-xlabel' classes. -- name: axisLabelFontSize - default: 14 +- name: ylabel tags: + - labels - axes + - display + default: null + examples: + - border + - demo + - two-axes + - noise + - styled-chart-labels + - multi-scale + - range-selector + - temperature-sf-ny + - two-axes-vr + type: String + desc: Text to display to the left of the chart's y-axis. You can supply any HTML + for this value, not just text. If you wish to style it using CSS, use the + 'dygraph-label' or 'dygraph-ylabel' classes. The text will be rotated 90 degrees + by default, so CSS rules may behave in unintuitive ways. No additional space + is set aside for a y-axis label. If you need more space, increase the width + of the y-axis tick labels using the yAxisLabelWidth option. If you need a + wider div for the y-axis label, either style it that way with CSS (but remember + that it's rotated, so width is controlled by the 'height' property) or set + the yLabelWidth option. + +- name: y2label + tags: - labels - type: Integer - desc: Size of the font (in pixels) to use in the axis labels, both x- and y-axis. + - display + default: null + examples: + - two-axes + - two-axes-vr + type: String + desc: Text to display to the right of the chart's secondary y-axis. This label + is only displayed if a secondary y-axis is present. See this test for an example + of how to do this. The comments for the 'ylabel' option generally apply here + as well. This label gets a 'dygraph-y2label' instead of a 'dygraph-ylabel' + class. -- name: axisLabelFormatter +- name: legend tags: - - axes - labels + - legend + - display + default: onmouseover + examples: + - demo + - noise + - per-series + - styled-chart-labels + - multi-scale + - range-selector + - temperature-sf-ny + type: String + desc: When to display the legend. By default, it only appears when a user mouses + over the chart. Set it to "always" to always display a legend of some sort. + +- name: labelsSeparateLines + tags: + - labels + - legend + - display + default: false + examples: + - century-scale + - customLabel + - demo + - reverse-y-axis + type: Boolean + desc: Put
between lines in the label string. Often used in conjunction with + labelsDiv. + +- name: labelsShowZeroValues + tags: + - labels + - legend + - display + default: true + examples: + - label-div + type: Boolean + desc: Show zero value labels in the labelsDiv. + +- name: hideOverlayOnMouseOut + tags: + - labels + - interactivity + - legend + - display + default: true + examples: + - gviz-selection + type: Boolean + desc: Whether to hide the legend when the mouse leaves the chart area. + +- name: showLabelsOnHighlight + tags: + - labels + - legend + - interactivity + - display + default: true + examples: + - callback + type: Boolean + desc: Whether to show the legend upon mouseover. + + + + +- name: labelsDiv + ignore: true + tags: + - labels + - legend + - display default: null + type: DOM element or string + desc: Show data labels in an external div, rather than on the graph. This value + can either be a div element or a div id. examples: - - x-axis-formatter - - y-axis-formatter - - value-axis-formatters - type: function(number or Date, granularity, opts, dygraph) - desc: Function to call to format the tick values that appear along an axis. This - is usually set on a per-axis basis. The first parameter is either a number - (for a numeric axis) or a Date object (for a date axis). The second argument - specifies how fine-grained the axis is. For date axes, this is a reference - to the time granularity enumeration, defined in dygraph-tickers.js, e.g. Dygraph.WEEKLY. - opts is a function which provides access to various options on the dygraph, - e.g. opts('labelsKMB'). + - century-scale + - demo + - label-div + - reverse-y-axis + - unboxed-spark -- name: axisLabelWidth - default: 50 +- name: labelsDivStyles + ignore: true tags: - - axes - labels + - legend + - display + default: null + examples: + - border + - customLabel + - noise + - styled-chart-labels + - range-selector + - temperature-sf-ny + type: Object + desc: 'Additional styles to apply to the currently-highlighted points div. For + example, { ''font-weight'': ''bold'' } will make the labels bold.' + +- name: labelsDivWidth + ignore: true + tags: + - labels + - legend + - display + default: 250 + examples: + - customLabel + - noise type: Integer - desc: Width (in pixels) of the containing divs for x- and y-axis labels. For the - y-axis, this also controls + desc: Width (in pixels) of the div which shows information on the currently-highlighted + points. -- name: axisLineColor + + +- name: logscale tags: - axes - - color - default: black + - display + default: false examples: - - demo - type: String - desc: Color of the x- and y-axis lines. Accepts any value which the HTML canvas - strokeStyle attribute understands, e.g. 'black' or 'rgb(0, 100, 255)'. + - logscale + - stock + type: Boolean + desc: When set for a y-axis, the graph shows that axis in log scale. Any values + less than or equal to zero are not displayed. Not compatible with showZero, + and ignores connectSeparatedPoints. Also, showing log scale with valueRanges + that are less than zero will result in an unviewable graph. -- name: axisLineWidth - default: 0.3 +- name: axis tags: - axes - type: Float - desc: Thickness (in pixels) of the x- and y-axis lines. + default: null + examples: + - two-axes + - steps + - two-axes-vr + - value-axis-formatters + type: String or Object + desc: Set to either an object ({}) filled with options for this axis or to the + name of an existing data series with its own axis to re-use that axis. See + tests for usage. -- name: axisTickSize - default: '3.0' +- name: valueRange tags: - axes - type: Number - desc: The size of the line to display next to each tick mark on x- or y-axes. + - range + default: null + examples: + - drawing + - dynamic-update + - is-zoomed-ignore-programmatic-zoom + - no-visibility + - reverse-y-axis + - synchronize + - zoom + - two-axes-vr + type: Array of two numbers + desc: Explicitly set the vertical range of the graph to [low, high]. This may + be set on a per-axis basis to define each y-axis separately. By default, the + full range of the input is shown. - name: drawXAxis tags: @@ -380,6 +563,18 @@ desc: Whether to draw the y-axis. Setting this to false also prevents y-axis ticks from being drawn and reclaims the space for the chart grid/lines. +- name: avoidMinZero + tags: + - axes + default: false + examples: + - avoidMinZero + type: Boolean + desc: "When set, the heuristic that fixes the Y axis at zero for a data set with\ + \ the minimum Y value of zero is disabled. \nThis is particularly useful for\ + \ data sets that contain many zero values, especially for step plots which\ + \ may otherwise have lines not visible running along the bottom axis." + - name: includeZero tags: - axes @@ -395,19 +590,104 @@ zero, typically as the lowest value. This can be used to avoid exaggerating the variance in the data -- name: logscale +- name: axisLineWidth + default: 0.3 + tags: + - axes + type: Float + desc: Thickness (in pixels) of the x- and y-axis lines. + +- name: axisLineColor + tags: + - axes + - color + default: black + examples: + - demo + type: String + desc: Color of the x- and y-axis lines. Accepts any value which the HTML canvas + strokeStyle attribute understands, e.g. 'black' or 'rgb(0, 100, 255)'. + +- name: axisTickSize + default: 3.0 + tags: + - axes + type: Number + desc: The size of the line to display next to each tick mark on x- or y-axes. + +- name: xAxisHeight + default: null tags: - axes - display - default: false + type: Integer + desc: Height, in pixels, of the x-axis. If not set explicitly, this is computed + based on axisLabelFontSize and axisTickSize. + +- name: axisLabelColor + default: black + tags: + - axes + - color + - labels + type: String + desc: Color for x- and y-axis labels. This is a CSS color string. + +- name: axisLabelFontSize + default: 14 + tags: + - axes + - labels + type: Integer + desc: Size of the font (in pixels) to use in the axis labels, both x- and y-axis. + +- name: axisLabelFormatter + tags: + - axes + - labels + default: null examples: - - logscale - - stock - type: Boolean - desc: When set for a y-axis, the graph shows that axis in log scale. Any values - less than or equal to zero are not displayed. Not compatible with showZero, - and ignores connectSeparatedPoints. Also, showing log scale with valueRanges - that are less than zero will result in an unviewable graph. + - x-axis-formatter + - y-axis-formatter + - value-axis-formatters + type: function(number or Date, granularity, opts, dygraph) + desc: Function to call to format the tick values that appear along an axis. This + is usually set on a per-axis basis. The first parameter is either a number + (for a numeric axis) or a Date object (for a date axis). The second argument + specifies how fine-grained the axis is. For date axes, this is a reference + to the time granularity enumeration, defined in dygraph-tickers.js, e.g. Dygraph.WEEKLY. + opts is a function which provides access to various options on the dygraph, + e.g. opts('labelsKMB'). + +- name: axisLabelWidth + default: 50 + tags: + - axes + - labels + type: Integer + desc: Width (in pixels) of the containing divs for x- and y-axis labels. For the + y-axis, this also controls + +- name: xLabelHeight + default: 18 + tags: + - axes + - labels + - display + type: Integer + desc: Height of the x-axis label, in pixels. This also controls the default font + size of the x-axis label. If you style the label on your own, this controls + how much space is set aside below the chart for the x-axis label's div. + +- name: yLabelWidth + default: 18 + tags: + - axes + - labels + - display + type: Integer + desc: Width of the div which contains the y-axis label. Since the y-axis label + appears rotated 90 degrees, this actually affects the height of its div. - name: pixelsPerLabel tags: @@ -422,15 +702,6 @@ yield a sparser axis with fewer ticks. This is set on a per-axis basis. By default, values are 60 (x-axis) or 30 (y-axes). -- name: xAxisHeight - default: null - tags: - - axes - - display - type: Integer - desc: Height, in pixels, of the x-axis. If not set explicitly, this is computed - based on axisLabelFontSize and axisTickSize. - - name: xAxisLabelWidth tags: - axes @@ -472,60 +743,198 @@ uses Dygraph.dateTicker or Dygraph.numericTicks, but see dygraph-tickers.js for an extensive discussion. This is set on a per-axis basis. -- name: dateWindow +- name: labelsKMB tags: - - interactivity - - axes + - formatting + - labels + - display + default: false + examples: + - annotation-gviz + - century-scale + - demo + - labelsKMB + - no-range + - two-axes + - reverse-y-axis + - two-axes-vr + type: Boolean + desc: Show K/M/B for thousands/millions/billions on y-axis. + +- name: labelsKMG2 + tags: + - formatting + - labels + - display + default: false + examples: + - labels + - formatting + type: Boolean + desc: Show k/M/G for kilo/Mega/Giga on y-axis. This is different than labelsKMB + in that it uses base 2, not 10. + +- name: digitsAfterDecimal + tags: + - formatting + - display + default: 2 + examples: + - number-display + type: Integer + desc: Unless it's run in scientific mode (see the sigFigs option), dygraphs displays + numbers with digitsAfterDecimal digits after the decimal point. Trailing zeros + are not displayed, so with a value of 2 you'll get '0', '0.1', '0.12', '123.45' + but not '123.456' (it will be rounded to '123.46'). Numbers with absolute + value less than 0.1^digitsAfterDecimal (i.e. those which would show up as + '0.00') will be displayed in scientific notation. + +- name: maxNumberWidth + tags: + - formatting + - display + default: 6 + examples: + - number-display + type: Integer + desc: When displaying numbers in normal (not scientific) mode, large numbers will + be displayed with many trailing zeros (e.g. 100000000 instead of 1e9). This + can lead to unwieldy y-axis labels. If there are more than maxNumberWidth + digits to the left of the decimal in a number, dygraphs will switch to scientific + notation, even when not operating in scientific mode. If you'd like to see + all those digits, set this to something large, like 20 or 30. + +- name: sigFigs + tags: + - formatting + - display default: null examples: - - dateWindow - - drawing - - is-zoomed-ignore-programmatic-zoom - - link-interaction - - synchronize - - zoom - type: Array of two Dates or numbers - desc: Initially zoom in on a section of the graph. Is of the form [earliest, latest], - where earliest/latest are milliseconds since epoch. If the data for the x-axis - is numeric, the values in dateWindow must also be numbers. By default, the - full range of the input is shown. + - number-display + type: Integer + desc: By default, dygraphs displays numbers with a fixed number of digits after + the decimal point. If you'd prefer to have a fixed number of significant figures, + set this option to that number of sig figs. A value of 2, for instance, would + cause 1 to be display as 1.0 and 1234 to be displayed as 1.23e+3. -- name: panEdgeFraction +- name: valueFormatter tags: - - interactivity - - axes - - pan + - formatting + - labels + - display + - legend default: null examples: - - zoom - type: Float - desc: A value representing the farthest a graph may be panned, in percent of the - display. For example, a value of 0.1 means that the graph can only be panned - 10% pased the edges of the displayed values. null means no bounds. + - y-axis-formatter + - value-axis-formatters + type: function(num or millis, opts, dygraph) + desc: Function to provide a custom display format for the values displayed on + mouseover. This does not affect the values that appear on tick marks next + to the axes. To format those, see axisLabelFormatter. This is usually set + on a per-axis basis. For date axes, you can call new Date(millis) to get a + Date object. opts is a function you can call to access various options (e.g. + opts('labelsKMB')). Default formatter will depend on the type of your data. -- name: valueRange + + + +- name: title + ignore: true tags: - - interactivity - - range - - axes + - title + - labels + - display default: null examples: - - drawing + - border + - demo + - noise + - styled-chart-labels + - multi-scale + - range-selector + - temperature-sf-ny + type: String + desc: Text to display above the chart. You can supply any HTML for this value, + not just text. If you wish to style it using CSS, use the 'dygraph-label' + or 'dygraph-title' classes. + +- name: titleHeight + ignore: true + tags: + - title + - labels + - display + default: 18 + examples: + - styled-chart-labels + type: Integer + desc: Height of the chart title, in pixels. This also controls the default font + size of the title. If you style the title on your own, this controls how much + space is set aside above the chart for the title's div. + + + + +- name: showRoller + tags: + - summary data + - rolling averages + - interactivity + default: false + examples: + - annotation + - callback + - crosshair - dynamic-update - - is-zoomed-ignore-programmatic-zoom + - fractions + - isolated-points + - missing-data + - numeric-gviz + - steps + - underlay-callback + - range-selector + - temperature-sf-ny + type: Boolean + desc: If the rolling average period text box should be shown. + +- name: rollPeriod + tags: + - summary data + - rolling averages + - error bars + default: 1 + examples: + - annotation + - callback + - century-scale + - crosshair + - customLabel + - draw-points + - dygraph-many-points-benchmark + - grid_dot + - link-interaction + - missing-data + - resize - no-visibility + - noise + - perf - reverse-y-axis + - unboxed-spark + - spacing + - styled-chart-labels - synchronize - - zoom - - two-axes-vr - type: Array of two numbers - desc: Explicitly set the vertical range of the graph to [low, high]. This may - be set on a per-axis basis to define each y-axis separately. By default, the - full range of the input is shown. + - two-series + - underlay-callback + - visibility + - range-selector + - temperature-sf-ny + type: Integer >= 1 + desc: Number of days over which to average data. Discussed extensively above. - name: sigma default: 2.0 tags: + - summary data - error bars type: Float desc: When errorBars is set, shade this many standard deviations above/below each @@ -534,6 +943,7 @@ - name: wilsonInterval default: true tags: + - summary data - error bars type: Boolean desc: Use in conjunction with the "fractions" option. Instead of plotting +/- @@ -544,6 +954,7 @@ - name: fillAlpha default: 0.15 tags: + - summary data - error bars - color - data @@ -556,8 +967,10 @@ itself. This can be used to produce chart lines whose thickness varies at each point. + - name: customBars tags: + - summary data - source - error bars - csv @@ -576,6 +989,7 @@ - name: errorBars tags: + - summary data - source - error bars - csv @@ -611,6 +1025,7 @@ - name: fractions tags: + - summary data - source - error bars - csv @@ -624,6 +1039,8 @@ b are integers. The ratio will be plotted. This allows computation of Wilson confidence intervals (see below). + + - name: delimiter default: ',' tags: @@ -646,6 +1063,8 @@ * Dygraphs is slightly more accepting in the dates which it will parse. See code for details.' + + - name: drawXGrid tags: - grid @@ -687,63 +1106,23 @@ gridlines can be turned off entirely by using the drawXGrid and drawYGrid options. -- name: animatedZooms - tags: - - interactivity - - zoom - default: false - examples: - - highlighted-region - - link-interaction - type: Boolean - desc: Set this option to animate the transition between zoom windows. Applies - to programmatic and interactive zooms. Note that if you also set a drawCallback, - it will be called several times on each zoom. If you set a zoomCallback, it - will only be called after the animation is complete. - -- name: highlightCircleSize - tags: - - interactivity - default: 3 - examples: - - dygraph-many-points-benchmark - - grid_dot - - per-series - - unboxed-spark - type: Integer - desc: The size in pixels of the dot drawn over highlighted points. -- name: interactionModel - tags: - - interactivity - default: null - examples: - - drawing - - interaction - hidden: true - type: Object - desc: 'TODO(konigsberg): document this' -- name: pointClickCallback +- name: showRangeSelector tags: + - range - interactivity - - callback - default: null + default: false examples: - - annotation - - callback - type: function(e, point) - desc: "A function to call when a data point is clicked. The function should take\ - \ two arguments, the event object for the click, and the point that was clicked.\ - \ The 'point' argument has these properties:\n * xval/yval: The data coordinates\ - \ of the point (with dates/times as millis since epoch) \n * canvasx/canvasy:\ - \ The canvas coordinates at which the point is drawn. \n name: The name of\ - \ the data series to which the point belongs" + - range-selector + type: Boolean + desc: Show the range selector widget. This option can only be specified at Dygraph + creation time. - name: rangeSelectorHeight tags: - - interactivity - range + - interactivity default: 40 examples: - range-selector @@ -753,9 +1132,9 @@ - name: rangeSelectorPlotFillColor tags: + - range - interactivity - color - - range default: '#A7B1C4' examples: - range-selector @@ -766,9 +1145,9 @@ - name: rangeSelectorPlotStrokeColor tags: + - range - interactivity - color - - range default: '#808FAB' examples: - range-selector @@ -777,229 +1156,7 @@ or "rgb(255,100,200)" or "yellow". You can also specify null or "" to turn off stroke. -- name: showRangeSelector - tags: - - interactivity - - range - default: false - examples: - - range-selector - type: Boolean - desc: Show the range selector widget. This option can only be specified at Dygraph - creation time. - -- name: hideOverlayOnMouseOut - tags: - - interactivity - - labels - - legend - - display - default: true - examples: - - gviz-selection - type: Boolean - desc: Whether to hide the legend when the mouse leaves the chart area. - -- name: labels - tags: - - labels - - legend - - display - default: null - examples: - - linear-regression-addseries - - connect-separated - - drawing - - dygraph - - dygraph-many-points-benchmark - - dynamic-update - - highlighted-region - - independent-series - - isolated-points - - label-div - - link-interaction - - linear-regression - - negative - - missing-data - - native-format - - two-axes - - perf - - small-range-zero - - steps - - y-axis-formatter - - annotation-native - - multi-scale - - two-axes-vr - - value-axis-formatters - type: Array - desc: A name for each data series, including the independent (X) series. For CSV - files and DataTable objections, this is determined by context. For raw data, - this must be specified. If it is not, default values are supplied and a warning - is logged. By default, labels roughly follow ["X", "Y1", "Y2", ...]* - -- name: labelsDiv - tags: - - labels - - legend - - display - default: null - examples: - - century-scale - - demo - - label-div - - reverse-y-axis - - unboxed-spark - type: DOM element or string - desc: Show data labels in an external div, rather than on the graph. This value - can either be a div element or a div id. - -- name: labelsDivStyles - tags: - - labels - - legend - - display - default: null - examples: - - border - - customLabel - - noise - - styled-chart-labels - - range-selector - - temperature-sf-ny - type: Object - desc: 'Additional styles to apply to the currently-highlighted points div. For - example, { ''font-weight'': ''bold'' } will make the labels bold.' -- name: labelsDivWidth - tags: - - labels - - legend - - display - default: 250 - examples: - - customLabel - - noise - type: Integer - desc: Width (in pixels) of the div which shows information on the currently-highlighted - points. - -- name: labelsSeparateLines - tags: - - labels - - legend - - display - default: false - examples: - - century-scale - - customLabel - - demo - - reverse-y-axis - type: Boolean - desc: Put
between lines in the label string. Often used in conjunction with - labelsDiv. - -- name: labelsShowZeroValues - tags: - - labels - - legend - - display - default: true - examples: - - label-div - type: Boolean - desc: Show zero value labels in the labelsDiv. - -- name: legend - tags: - - labels - - legend - - display - default: onmouseover - examples: - - demo - - noise - - per-series - - styled-chart-labels - - multi-scale - - range-selector - - temperature-sf-ny - type: String - desc: When to display the legend. By default, it only appears when a user mouses - over the chart. Set it to "always" to always display a legend of some sort. - -- name: showLabelsOnHighlight - tags: - - interactivity - - labels - - legend - - display - default: true - examples: - - callback - type: Boolean - desc: Whether to show the legend upon mouseover. - -- name: rightGap - default: 5 - tags: - - display - type: Integer - desc: Number of pixels to leave blank at the right edge of the Dygraph. This makes - it easier to highlight the right-most data point. - -- name: rollPeriod - tags: - - rolling averages - - error bars - default: 1 - examples: - - annotation - - callback - - century-scale - - crosshair - - customLabel - - draw-points - - dygraph-many-points-benchmark - - grid_dot - - link-interaction - - missing-data - - resize - - no-visibility - - noise - - perf - - reverse-y-axis - - unboxed-spark - - spacing - - styled-chart-labels - - synchronize - - two-series - - underlay-callback - - visibility - - range-selector - - temperature-sf-ny - type: Integer >= 1 - desc: Number of days over which to average data. Discussed extensively above. - -- name: showRoller - tags: - - interactivity - - rolling averages - default: false - examples: - - annotation - - callback - - crosshair - - dynamic-update - - fractions - - isolated-points - - missing-data - - numeric-gviz - - steps - - underlay-callback - - range-selector - - temperature-sf-ny - type: Boolean - desc: If the rolling average period text box should be shown. - name: displayAnnotations tags: @@ -1055,111 +1212,22 @@ type: function(annotation, point, dygraph, event) desc: If provided, this function is called whenever the user mouses over an annotation. -- name: digitsAfterDecimal - tags: - - formatting - - display - default: 2 - examples: - - number-display - type: Integer - desc: Unless it's run in scientific mode (see the sigFigs option), dygraphs displays - numbers with digitsAfterDecimal digits after the decimal point. Trailing zeros - are not displayed, so with a value of 2 you'll get '0', '0.1', '0.12', '123.45' - but not '123.456' (it will be rounded to '123.46'). Numbers with absolute - value less than 0.1^digitsAfterDecimal (i.e. those which would show up as - '0.00') will be displayed in scientific notation. -- name: labelsKMB - tags: - - formatting - - labels - - display - default: false - examples: - - annotation-gviz - - century-scale - - demo - - labelsKMB - - no-range - - two-axes - - reverse-y-axis - - two-axes-vr - type: Boolean - desc: Show K/M/B for thousands/millions/billions on y-axis. -- name: labelsKMG2 - tags: - - formatting - - labels - - display - default: false - examples: - - labels - - formatting - type: Boolean - desc: Show k/M/G for kilo/Mega/Giga on y-axis. This is different than labelsKMB - in that it uses base 2, not 10. -- name: maxNumberWidth - tags: - - formatting - - display - default: 6 - examples: - - number-display - type: Integer - desc: When displaying numbers in normal (not scientific) mode, large numbers will - be displayed with many trailing zeros (e.g. 100000000 instead of 1e9). This - can lead to unwieldy y-axis labels. If there are more than maxNumberWidth - digits to the left of the decimal in a number, dygraphs will switch to scientific - notation, even when not operating in scientific mode. If you'd like to see - all those digits, set this to something large, like 20 or 30. -- name: sigFigs +- name: timingName tags: - - formatting - - display + - debugging default: null examples: - - number-display - type: Integer - desc: By default, dygraphs displays numbers with a fixed number of digits after - the decimal point. If you'd prefer to have a fixed number of significant figures, - set this option to that number of sig figs. A value of 2, for instance, would - cause 1 to be display as 1.0 and 1234 to be displayed as 1.23e+3. + - dygraph-many-points-benchmark + type: String + desc: Set this option to log timing information. The value of the option will + be logged along with the timing, so that you can distinguish multiple dygraphs + on the same page. -- name: valueFormatter - tags: - - labels - - formatting - - display - - legend - default: null - examples: - - y-axis-formatter - - value-axis-formatters - type: function(num or millis, opts, dygraph) - desc: Function to provide a custom display format for the values displayed on - mouseover. This does not affect the values that appear on tick marks next - to the axes. To format those, see axisLabelFormatter. This is usually set - on a per-axis basis. For date axes, you can call new Date(millis) to get a - Date object. opts is a function you can call to access various options (e.g. - opts('labelsKMB')). Default formatter will depend on the type of your data. -- name: isZoomedIgnoreProgrammaticZoom - tags: - - interactivity - - zoom - default: false - examples: - - is-zoomed-ignore-programmatic-zoom - type: Boolean - desc: When this option is passed to updateOptions() along with either the dateWindow - or valueRange options, the zoom flags are not changed to reflect a zoomed - state. This is primarily useful for when the display area of a chart is changed - programmatically and also where manual zooming is allowed and use is made - of the isZoomed method to determine this. - name: clickCallback tags: @@ -1247,24 +1315,29 @@ or out). minDate and maxDate are milliseconds since epoch. yRanges is an array of [bottom, top] pairs, one for each y-axis. - -- name: timingName +- name: pointClickCallback tags: - - debugging + - interactivity + - callback default: null examples: - - dygraph-many-points-benchmark - type: String - desc: Set this option to log timing information. The value of the option will - be logged along with the timimg, so that you can distinguish multiple dygraphs - on the same page. + - annotation + - callback + type: function(e, point) + desc: "A function to call when a data point is clicked. The function should take\ + \ two arguments, the event object for the click, and the point that was clicked.\ + \ The 'point' argument has these properties:\n * xval/yval: The data coordinates\ + \ of the point (with dates/times as millis since epoch) \n * canvasx/canvasy:\ + \ The canvas coordinates at which the point is drawn. \n name: The name of\ + \ the data series to which the point belongs" + + - name: pixelsPerXLabel tags: - deprecated - labels default: null - hidden: true type: Integer desc: 'Prefer axes { x: { pixelsPerLabel } }' @@ -1275,7 +1348,6 @@ default: null examples: - spacing - hidden: true type: Integer desc: 'Prefer axes: { y: { pixelsPerLabel } }' @@ -1284,7 +1356,6 @@ - deprecated - labels default: null - hidden: true type: function desc: 'Prefer axes { x: { axisLabelFormatter } }' @@ -1292,7 +1363,6 @@ tags: - deprecated default: null - hidden: true type: function desc: 'Prefer axes: { x: { valueFormatter } }' @@ -1301,7 +1371,6 @@ - deprecated - labels default: null - hidden: true type: function desc: 'Prefer axes: { y: { axisLabelFormatter } }' @@ -1312,51 +1381,37 @@ examples: - labelsKMB - multi-scale - hidden: true type: function desc: 'Prefer axes: { y: { valueFormatter } }' + + - name: width + ignore: true tags: - display default: 480 - hidden: true type: Integer desc: Width, in pixels, of the chart. If the container div has been explicitly sized, this will be ignored. - name: height + ignore: true tags: - display default: 320 - hidden: true type: Integer desc: Height, in pixels, of the chart. If the container div has been explicitly sized, this will be ignored. - name: file + ignore: true tags: - source default: null - hidden: true type: String desc: Sets the data being displayed in the chart. This can only be set when calling updateOptions; it cannot be set from the constructor. For a full description of valid data formats, see the Data Formats page. String can be a URL of CSV or CSV, GViz DataTable or 2D Array. -- name: visibility - tags: - - lines - - data - - display - default: true - examples: - - color-visibility - - no-visibility - - visibility - type: Array of booleans - desc: Which series should initially be visible? Once the Dygraph has been constructed, - you can access and modify the visibility of each series using the visibility - and setVisibility methods. - diff --git a/www/css/colors.styl b/www/css/colors.styl index 4c836b6..a486891 100644 --- a/www/css/colors.styl +++ b/www/css/colors.styl @@ -41,8 +41,8 @@ $hilite_favs = ($hilite_dkblue $hilite_ltblue $hilite_cyan $hilite_lime $hilite_ /* background colors */ -$main_bgcolor = white -$page_bgcolor = $light +$main_bgcolor = $light +$page_bgcolor = white $foot_bgcolor = #3b3b3b /* text & link colors */ diff --git a/www/css/graph.styl b/www/css/graph.styl index 4f9b09f..78ce592 100644 --- a/www/css/graph.styl +++ b/www/css/graph.styl @@ -8,7 +8,19 @@ section.graph position relative .graph-label - position relative + position absolute + z-index 100 + top 1em + right 1em + max-width 300px + + padding 1em + border-radius 5px + background-color rgba(255,255,255, 0.75) + font 12px/1.3 "helvetica neue", helvetica, arial, sans-serif + + .viewport:hover + .graph-label + border 1px solid $light .viewport position relative @@ -17,13 +29,19 @@ section.graph margin-bottom 1.5em overflow hidden + form.details position relative .name-row + font-size 120% line-height 2em - // input.name - // width 50% + input.name + font-size 120% + line-height 1.2 + height 1.2em + border-color $light + // width 50% .row-fluid .half.control-group width 50% @@ -38,11 +56,8 @@ section.graph font-size 11px line-height 1.3 - fieldset.options - border-radius 5px - legend - width auto - display inline-block + .options fieldset + border 0px .field.option float left diff --git a/www/graph/test.jade b/www/graph/test.jade index 906ecf6..5033daa 100644 --- a/www/graph/test.jade +++ b/www/graph/test.jade @@ -8,4 +8,3 @@ append styles mixin css('graph.css') mixin css('isotope.css') - diff --git a/www/layout.jade b/www/layout.jade index a76e3ee..ba83c88 100644 --- a/www/layout.jade +++ b/www/layout.jade @@ -21,16 +21,17 @@ html body block body - header.navbar.navbar-fixed-top: .navbar-inner: .container - block header - h1: a(href="/") Kraken - block nav - nav#menu: ul - block menu-items - li.home Home + //- + header + block header + h1: a(href="/") Kraken + block nav + nav#menu: ul + block menu-items + li.home Home section#content - .spacer + //- .spacer .inner block content diff --git a/www/modules.yaml b/www/modules.yaml index 6afc2de..e089e90 100644 --- a/www/modules.yaml +++ b/www/modules.yaml @@ -39,6 +39,7 @@ all: - template: - graph.jade - graph-option.jade + - graph-scaffold.jade - scaffold: - scaffold-model - scaffold-view -- 1.7.0.4