Adds old docs. old-docs
authordsc <dsc@less.ly>
Fri, 21 Sep 2012 22:07:17 +0000 (15:07 -0700)
committerdsc <dsc@less.ly>
Fri, 21 Sep 2012 22:07:17 +0000 (15:07 -0700)
24 files changed:
old-docs/internals/backbone-base.html [new file with mode: 0644]
old-docs/internals/backbone-base.md [new file with mode: 0644]
old-docs/internals/dashboard.md [new file with mode: 0644]
old-docs/internals/data-ui.md [new file with mode: 0644]
old-docs/internals/framework.md [new file with mode: 0644]
old-docs/internals/middleware.md [new file with mode: 0644]
old-docs/internals/scaffold.md [new file with mode: 0644]
old-docs/internals/specs/chart-element.yaml [new file with mode: 0644]
old-docs/internals/specs/chart-options/source-group-options.yaml [new file with mode: 0644]
old-docs/internals/specs/chart-options/stroke-object.yaml [new file with mode: 0644]
old-docs/internals/specs/chart-options/timeseries-options.md [new file with mode: 0644]
old-docs/internals/specs/chart-options/timeseries-options.yaml [new file with mode: 0644]
old-docs/internals/specs/chart-options/viewport-options.yaml [new file with mode: 0644]
old-docs/internals/specs/dataset-spec.yaml [new file with mode: 0644]
old-docs/internals/specs/graph-spec.yaml [new file with mode: 0644]
old-docs/internals/specs/legacy-graph-spec.yaml [new file with mode: 0644]
old-docs/later.md [new file with mode: 0644]
old-docs/notes/d3-mvc.md [new file with mode: 0644]
old-docs/notes/graphs.md [new file with mode: 0644]
old-docs/notes/housekeeping.md [new file with mode: 0644]
old-docs/notes/notes.md [new file with mode: 0644]
old-docs/notes/option-tag-notes.md [new file with mode: 0644]
old-docs/notes/prototype-sync-up.mediawiki [new file with mode: 0644]
old-docs/todo.md [new file with mode: 0644]

diff --git a/old-docs/internals/backbone-base.html b/old-docs/internals/backbone-base.html
new file mode 100644 (file)
index 0000000..8c7235a
--- /dev/null
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf8">
+<title>Backbone Base Classes | Limn Docs</title>
+<link rel="stylesheet" href="/vendor/bootstrap/css/bootstrap.css" type="text/css">
+<link rel="stylesheet" href="/docs/assets/github-readme.css" type="text/css">
+<link rel='stylesheet' href='/docs/assets/solarized.css' type='text/css'>
+</head>
+<body><div class="site">
+<div id="readme" class="content md markdown announce">
+<div class="wikistyle">
+    
+<h1 id="backbone-base-classes">Backbone Base Classes</h1>
+<p>Nearly all models, model collections, and views in the project derive from three base classes, aptly named <code>BaseModel</code>, <code>BaseList</code>, and <code>BaseView</code>. Herein we'll discuss some of the more arcane aspects of these classes, especially the default behavior they implement, and the ways in which subclasses can augment it.</p>
+<h2 id="table-of-contents">Table of Contents</h2>
+<div class="toc">
+<ul>
+<li><a href="#backbone-base-classes">Backbone Base Classes</a><ul>
+<li><a href="#table-of-contents">Table of Contents</a></li>
+<li><a href="#basemixin">BaseMixin</a><ul>
+<li><a href="#declarative-binding">Declarative Binding</a></li>
+<li><a href="#synchronization">Synchronization</a></li>
+</ul>
+</li>
+<li><a href="#basemodel">BaseModel</a><ul>
+<li><a href="#nested-attribute-lookup">Nested Attribute Lookup</a></li>
+<li><a href="#kv-pairs-serialization">KV-Pairs Serialization</a></li>
+</ul>
+</li>
+<li><a href="#baselist">BaseList</a></li>
+<li><a href="#baseview">BaseView</a><ul>
+<li><a href="#model-integration">Model Integration</a></li>
+<li><a href="#render-lifecycle">Render Lifecycle</a></li>
+<li><a href="#subviews">Subviews</a></li>
+<li><a href="#future-enhancements">Future Enhancements</a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<h2 id="basemixin">BaseMixin</h2>
+<p>Though these three do not share a common base class (as each derives from its Backbone counterpart), they do share a set of methods and properties defined in a <code>BaseMixin</code> (the mixin is applied to each Base itself, so you do not need to apply it to any of your subclasses).</p>
+<h3 id="declarative-binding">Declarative Binding</h3>
+<p>Due to the fact that JavaScript functions are unbound, it is sometimes necessary to force a method to retain class context (<code>this</code>) for event handlers. The property <code>__bind__</code> allows you to specify this declaratively; it is a list of method names to be bound when <code>initialize()</code> is called on a new instance. The <code>__bind__</code> property recursively cascades up the inheritance chain, so all classes will have their binds applied.</p>
+<h3 id="synchronization">Synchronization</h3>
+<p>Due to the asynchronous nature of UI programming, it's often necessary to notify the world that this class is waiting for something. It might not even matter what they're waiting for -- in many cases, you just want to show a spinner or disable modifications while "stuff happens".</p>
+<p>To this end, all Base classes provide methods for this kind of synchronization: <code>wait()</code> and <code>unwait()</code> manipulate a simple counter, <code>waitingOn</code>. When it moves above zero through a call to <code>wait()</code>, the event <code>start-waiting</code> is fired. When it returns to zero through a call to <code>unwait()</code>, the event <code>stop-waiting</code> is fired. Finally, a decorator method <code>unwaitAnd(fn)</code> allows you to wrap another method, such that invoking the returned function will call  <code>unwait()</code>  and then delegate to the passed method.</p>
+<h2 id="basemodel">BaseModel</h2>
+<p><code>BaseModel</code> provides two simple but important features: nested lookups and KV-pairs serialization.</p>
+<h3 id="nested-attribute-lookup">Nested Attribute Lookup</h3>
+<p>Calls to <code>get(key)</code> can specify a nested attribute lookup by using dot-delimited keys.</p>
+<div class="highlight"><pre><span class="n">m</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BaseModel</span> <span class="p">{</span> <span class="n">foo:</span><span class="p">{</span><span class="n">bar:1</span><span class="p">}</span> <span class="p">}</span>
+<span class="n">m</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;foo.bar&#39;</span><span class="p">)</span> <span class="n">is</span> <span class="mi">1</span>
+</pre></div>
+
+
+<h3 id="kv-pairs-serialization">KV-Pairs Serialization</h3>
+<p>KV-Pairs, also known as <code>www-form-encoding</code>, is the default serialization format for data posted by HTML forms. The query string in a URL (the bit after the first <code>?</code>, but before any <code>#</code>) also usually takes this format. Unfortunately, JavaScript provides no built-in serialization for objects to this format. These methods fill that gap.</p>
+<div class="highlight"><pre><span class="n">m</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BaseModel</span> <span class="p">{</span> <span class="n">a:1</span><span class="p">,</span> <span class="n">b:2</span> <span class="p">}</span>
+<span class="n">m</span><span class="o">.</span><span class="n">toKV</span><span class="p">()</span> <span class="n">is</span> <span class="s">&#39;a=1&amp;b=2&#39;</span>
+</pre></div>
+
+
+<p>JavaScript 1.8 introduced a protocol for [JSON serialization][json], whereby objects can specify a <code>toJSON()</code> method that returns an object to be serialized, rather than forcing the programmer to reimplement serialization just to customize what data is serialized.</p>
+<p>The KV-Pairs protocol functions similarly. It consists in a family of instance methods and a class method, any of which can be replaced via inheritance:</p>
+<ul>
+<li><strong><code>toKV(item_delim='&amp;', kv_delim='=') -&gt; String</code></strong> performs the actual serialization of the object a <code>www-form-encoded</code> string by invoking <code>toKVPairs()</code> and passing the result to <code>_.toKV</code> (along with the delimiters).</li>
+<li><strong><code>toKVPairs() -&gt; Object</code></strong> is the counterpart of <code>toJSON()</code> -- it is expected to return an object to be serialized. Unlike <code>toJSON()</code>, it must return a proper object, and no recursive application of this function will be applied. This is due to the fact that query strings, unlike JSON, are fundamentally one-dimensional; without a type system, nesting requires a convention for delimiting sub-objects. The default implementation handles sub-objects using <code>_.collapseObject()</code> (rather than encoding them), and serializes each value using <code>serialize(v)</code>.</li>
+<li><strong><code>_.collapseObject(obj, parent={}, prefix='') -&gt; Object</code></strong> is an [Underscore][underscore] extension that copies and flattens a tree of sub-objects into namespaced keys on the parent object, such that <code>{ "foo":{ "bar":1 } }</code> becomes <code>{ "foo.bar":1 }</code>. Note that only plain objects are collapsed -- it is assumed that object subclasses will correctly <code>.toString()</code> or otherwise handle their serialization in the <code>serialize(v)</code> step.</li>
+<li><strong><code>serialize(v) -&gt; String</code></strong> is called by the default implementation of <code>toKVPairs()</code> to transform each non-function value to a string.</li>
+<li><strong><code>toURL(item_delim='&amp;', kv_delim='=') -&gt; String</code></strong> is used to create a URL that uniquely identifies the model state, typically for use with the HTML5 History API.</li>
+<li>The class method <strong><code>fromKV(s, item_delim='&amp;', kv_delim='=') -&gt; Model</code></strong> uses <code>_.fromKV</code> to deserialize the <code>www-form-encoded</code> string, uncollapses it with <code>_.uncollapseObject()</code>, and then creates a new model instance with the result.</li>
+</ul>
+<div class="highlight"><pre><span class="n">m</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BaseModel</span> <span class="p">{</span> <span class="n">a:1</span><span class="p">,</span> <span class="n">b:2</span><span class="p">,</span> <span class="n">foo:</span><span class="p">{</span> <span class="n">bar:3</span> <span class="p">}</span> <span class="p">}</span>
+<span class="n">m</span><span class="o">.</span><span class="n">toKV</span><span class="p">()</span> <span class="n">is</span> <span class="s">&#39;a=1&amp;b=2&amp;foo.bar=3&#39;</span>
+</pre></div>
+
+
+<p>The Underscore extensions can be found in <code>lib/util/underscore</code>, specifically <code>kv.co</code> and <code>object.co</code>.</p>
+<h2 id="baselist">BaseList</h2>
+<p><code>BaseList</code> mostly exists for completeness -- at present, it merely provides implementations of the KV-Pairs protocol fed by <code>toJSON()</code>. This typically has a poor result.</p>
+<h2 id="baseview">BaseView</h2>
+<p><code>BaseView</code> provides a large number of convenience methods, most of which are simple enough to read about in the source-docs. Instead, we'll focus here on the view lifecycle.</p>
+<h3 id="model-integration">Model Integration</h3>
+<p>The <code>setModel(model) -&gt; model</code> method sets a variety of metadata on both the view and the model -- use it to change the <code>BaseView</code>'s model object should that ever be necessary. It does the following:</p>
+<ul>
+<li>Sets <code>model.view</code> equal to the <code>BaseView</code>. This is mostly useful for debugging in the console, as models should otherwise need no knowledge of any views.</li>
+<li>Sets data attributes for <code>"model"</code> and <code>"view"</code> on the view's DOM element.</li>
+<li>Register listeners on <code>change</code> to render the view and <code>destroy</code> to remove itself from the DOM.</li>
+</ul>
+<h3 id="render-lifecycle">Render Lifecycle</h3>
+<p>Backbone has provides almost no help in managing a view's relationship with the DOM. Unfortunately for us, this is in no way a simple task, and it also happens to be the place most likely to have serious user-facing performance implications. <code>BaseView</code> takes some steps to smooth this over (though there is much more that could be done) by implementing a default rendering lifecycle that eliminates much boilerplate.</p>
+<ul>
+<li>Note that <code>Backbone.View</code>'s constructor creates a DOM element for the view (as <code>this.el</code>), and wraps it with jQuery (as <code>this.$el</code>). This is basically all Backbone does, ever.</li>
+<li>At the end of <code>initialize()</code>, <code>BaseView</code> invokes the <code>build()</code> method.</li>
+<li><strong><code>build() -&gt; this</code></strong> should populate the view with HTML, but does not attach it to the DOM. The default implementation of <code>build()</code> is a no-op unless the view has a <code>template()</code> method. If it does, <code>build()</code> invokes <code>this.$template()</code>, attaches its <code>innerHTML</code> content to the view's DOM element, and updates the element's CSS classes to match the template's. Finally, it calls <code>attachSubviews()</code>, which we'll come to later.</li>
+<li><strong><code>$template(locals) -&gt; jQuery</code></strong> invokes the view's <code>template()</code>, merging a set of default locals ($, op, the model, the view) with the result of the <code>toTemplateLocals()</code> method, and then with the supplied locals. It then wraps the templated result with jQuery.</li>
+<li><code>toTemplateLocals()</code> should return a plain object with (presumably) the model's attributes converted to presentation values used in the template. By default it merely calls <code>model.toJSON()</code>.</li>
+<li>The <code>render()</code> method invokes <code>build()</code> and then triggers a <code>render</code> event. As noted above, it is registered as a listener on Model <code>change</code> events.</li>
+</ul>
+<p>These methods (plus the <code>render</code> event) provide ample places to customize the rendering lifecycle. Many views do; here are some notes:</p>
+<ul>
+<li>Nearly all views override <code>toTemplateLocals()</code> to format the locals for presentation.</li>
+<li>Many override <code>render()</code> to avoid rebuilding the DOM. Once this pattern emerged, it became obvious I should modify <code>render()</code> to call an <code>update(locals)</code> method if it exists, rather than blowing away whatever DOM content is there.</li>
+<li>Data-binding frameworks exist to integrate with DOM content, but all of them I've seen are either excessively verbose, heavy-weight, and presumptuous, or do not play well with Backbone. A simple data-binding convention would go a long way to eliminating boilerplate.</li>
+</ul>
+<h3 id="subviews">Subviews</h3>
+<p><code>BaseView</code> provides simple subview management methods and hooks:</p>
+<ul>
+<li><strong><code>addSubview([selector], view) -&gt; view</code></strong> registers a new subview. You may optionally pass a selector as the first argument to specify its attachment point in the view. The subview is not attached to the DOM until <code>attachSubviews()</code> is called (which normally happens during <code>build()</code> and <code>render()</code>).</li>
+<li><strong><code>hasSubview(view)</code></strong> tests if a view is registered.</li>
+<li><strong><code>removeSubview(view) -&gt; [view, selector] | null</code></strong> unregisters a subview. Note that it does not remove the subview from the DOM.</li>
+<li><strong><code>attachSubviews() -&gt; this</code></strong> attaches each subview to the view's DOM element. If the given subview was registered with a selector, the element it picks out will become the subview's parent. Otherwise, it is appended to the view's element.</li>
+<li><code>**renderSubviews() -&gt; this**</code> is a convenience method for invoking <code>render</code> on each subview; it is not called by anything in the render lifecycle. Note <code>renderSubviews()</code> does not call <code>attachSubviews()</code>.</li>
+</ul>
+<h3 id="future-enhancements">Future Enhancements</h3>
+<p>View handling could use a lot of work to eliminate boilerplate and simplify common tasks. The biggest pain-points I've noted are:</p>
+<ul>
+<li>Views have no way of being notified when their DOM element is actually parented (or unparented) in the DOM. This is generally a very hard problem in rich client development on the web, and there are no bulletproof solutions. Still, we should be providing some methods which in turn fire an event for this.</li>
+<li>As mentioned in the discussion of the render lifecycle, it would help to integrate a default data-binding convention and related methods.</li>
+<li>Events don't bubble through the view hierarchy as they do with the DOM. This means views must manually inform their subviews to re-render. I left this unimplemented mostly because of the render-vs-update issue above.</li>
+</ul>
+
+<br style="clear:both;">
+</div>
+
+</div>
+</div></body>
+</html>
diff --git a/old-docs/internals/backbone-base.md b/old-docs/internals/backbone-base.md
new file mode 100644 (file)
index 0000000..ffcfb70
--- /dev/null
@@ -0,0 +1,130 @@
+# Backbone Base Classes
+
+Nearly all models, model collections, and views in the project derive from three base classes, aptly named `BaseModel`, `BaseList`, and `BaseView`, each extending their [Backbone][backbone] counterpart. Herein we'll discuss some of the more arcane aspects of these classes, especially the default behavior they implement, and the ways in which subclasses can augment it.
+
+
+## Table of Contents
+
+[TOC]
+
+
+## BaseMixin
+
+Though these three do not share a common base class (as each derives from its Backbone counterpart), they do share a set of methods and properties defined in a `BaseMixin` (the mixin is applied to each Base itself, so you do not need to apply it to any of your subclasses).
+
+### Declarative Binding
+
+Due to the fact that JavaScript functions are unbound, it is sometimes necessary to force a method to retain class context (`this`) for event handlers. The property `__bind__` allows you to specify this declaratively; it is a list of method names to be bound when `initialize()` is called on a new instance. The `__bind__` property recursively cascades up the inheritance chain, so all classes will have their binds applied.
+
+### Synchronization
+
+Due to the asynchronous nature of UI programming, it's often necessary to notify the world that this class is waiting for something. It might not even matter what they're waiting for -- in many cases, you just want to show a spinner or disable modifications while "stuff happens".
+
+To this end, all Base classes provide methods for this kind of synchronization: `wait()` and `unwait()` manipulate a simple counter, `waitingOn`. When it moves above zero through a call to `wait()`, the event `start-waiting` is fired. When it returns to zero through a call to `unwait()`, the event `stop-waiting` is fired. Finally, a decorator method `unwaitAnd(fn)` allows you to wrap another method, such that invoking the returned function will call  `unwait()`  and then delegate to the passed method.
+
+
+## BaseModel
+
+`BaseModel` extends [Backbone.Model](http://backbonejs.org/#Model) to provide two simple but important features: nested lookups and KV-pairs serialization.
+
+### Nested Attribute Lookup
+
+Calls to `get(key)` can specify a nested attribute lookup by using dot-delimited keys.
+
+```coffee
+m = new BaseModel { foo:{bar:1} }
+m.get('foo.bar') is 1
+```
+
+### KV-Pairs Serialization
+
+KV-Pairs, also known as `www-form-encoding`, is the default serialization format for data posted by HTML forms. The query string in a URL (the bit after the first `?`, but before any `#`) also usually takes this format. Unfortunately, JavaScript provides no built-in serialization for objects to this format. These methods fill that gap.
+
+```coffee
+m = new BaseModel { a:1, b:2 }
+m.toKV() is 'a=1&b=2'
+```
+
+JavaScript 1.8 introduced a protocol for [JSON serialization][json], whereby objects can specify a `toJSON()` method that returns an object to be serialized, rather than forcing the programmer to reimplement serialization just to customize what data is serialized.
+
+The KV-Pairs protocol functions similarly. It consists in a family of instance methods and a class method, any of which can be replaced via inheritance:
+
+- **`toKV(item_delim='&', kv_delim='=') -> String`** performs the actual serialization of the object a `www-form-encoded` string by invoking `toKVPairs()` and passing the result to `_.toKV` (along with the delimiters).
+- **`toKVPairs() -> Object`** is the counterpart of `toJSON()` -- it is expected to return an object to be serialized. Unlike `toJSON()`, it must return a proper object, and no recursive application of this function will be applied. This is due to the fact that query strings, unlike JSON, are fundamentally one-dimensional; without a type system, nesting requires a convention for delimiting sub-objects. The default implementation handles sub-objects using `_.collapseObject()` (rather than encoding them), and serializes each value using `serialize(v)`.
+- **`_.collapseObject(obj, parent={}, prefix='') -> Object`** is an [Underscore][underscore] extension that copies and flattens a tree of sub-objects into namespaced keys on the parent object, such that `{ "foo":{ "bar":1 } }` becomes `{ "foo.bar":1 }`. Note that only plain objects are collapsed -- it is assumed that object subclasses will correctly `.toString()` or otherwise handle their serialization in the `serialize(v)` step.
+- **`serialize(v) -> String`** is called by the default implementation of `toKVPairs()` to transform each non-function value to a string.
+- **`toURL(item_delim='&', kv_delim='=') -> String`** is used to create a URL that uniquely identifies the model state, typically for use with the HTML5 History API.
+- The class method **`fromKV(s, item_delim='&', kv_delim='=') -> Model`** uses `_.fromKV` to deserialize the `www-form-encoded` string, uncollapses it with `_.uncollapseObject()`, and then creates a new model instance with the result.
+
+```coffee
+m = new BaseModel { a:1, b:2, foo:{ bar:3 } }
+m.toKV() is 'a=1&b=2&foo.bar=3'
+```
+
+The [Underscore][underscore] extensions can be found in `lib/util/underscore`, specifically `kv.co` and `object.co`.
+
+
+## BaseList
+
+`BaseList` extends [Backbone.Collection](http://backbonejs.org/#Collection) -- at present, it merely provides implementations of the KV-Pairs protocol fed by `toJSON()`. This typically has a poor result, as you get things like:
+
+```coffee
+list = new BaseList [{ foo:1, bar:2 }]
+list.toKV() is '0.foo=1&0.bar=2'
+```
+
+...Which, while reasonable and correct, is not terribly semantic. We'd probably prefer the collection indices in there to be replaced with `model.id` or `model.cid`, but I was hesitant to be opinionated about something I've never seen a use for.
+
+
+## BaseView
+
+`BaseView` extends [Backbone.View](http://backbonejs.org/#View) to provide a large number of convenience methods. Many of these are simple enough to read about in the source-docs, so instead, we'll mostly focus here on the view lifecycle.
+
+### Model Integration
+
+The `setModel(model) -> model` method sets a variety of metadata on both the view and the model -- use it to change the `BaseView`'s model object should that ever be necessary. It does the following:
+
+- Sets `model.view` equal to the `BaseView`. This is mostly useful for debugging in the console, as models should otherwise need no knowledge of any views.
+- Sets data attributes for `"model"` and `"view"` on the view's DOM element.
+- Register listeners on `change` to render the view and `destroy` to remove itself from the DOM.
+
+### Render Lifecycle
+
+Backbone has provides almost no help in managing a view's relationship with the DOM. Unfortunately for us, this is in no way a simple task, and it also happens to be the place most likely to have serious user-facing performance implications. `BaseView` takes some steps to smooth this over (though there is much more that could be done) by implementing a default rendering lifecycle that eliminates much boilerplate.
+
+- Note that `Backbone.View`'s constructor creates a DOM element for the view (as `this.el`), and wraps it with jQuery (as `this.$el`). This is basically all Backbone does, ever.
+- At the end of `initialize()`, `BaseView` invokes the `build()` method.
+- **`build() -> this`** should populate the view with HTML, but does not attach it to the DOM. The default implementation of `build()` is a no-op unless the view has a `template()` method. If it does, `build()` invokes `this.$template()`, attaches its `innerHTML` content to the view's DOM element, and updates the element's CSS classes to match the template's. Finally, it calls `attachSubviews()`, which we'll come to later.
+- **`$template(locals) -> jQuery`** invokes the view's `template()`, merging a set of default locals ($, op, the model, the view) with the result of the `toTemplateLocals()` method, and then with the supplied locals. It then wraps the templated result with jQuery.
+- `toTemplateLocals()` should return a plain object with (presumably) the model's attributes converted to presentation values used in the template. By default it merely calls `model.toJSON()`.
+- The `render()` method invokes `build()` and then triggers a `render` event. As noted above, it is registered as a listener on Model `change` events.
+
+These methods (plus the `render` event) provide ample places to customize the rendering lifecycle. Many views do; here are some notes:
+
+- Nearly all views override `toTemplateLocals()` to format the locals for presentation.
+- Many override `render()` to avoid rebuilding the DOM. Once this pattern emerged, it became obvious I should modify `render()` to call an `update(locals)` method if it exists, rather than blowing away whatever DOM content is there.
+- Data-binding frameworks exist to integrate with DOM content, but all of them I've seen are either excessively verbose, heavy-weight, and presumptuous, or do not play well with Backbone. A simple data-binding convention would go a long way to eliminating boilerplate.
+
+### Subviews
+
+`BaseView` provides simple subview management methods and hooks:
+
+- **`addSubview([selector], view) -> view`** registers a new subview. You may optionally pass a selector as the first argument to specify its attachment point in the view. The subview is not attached to the DOM until `attachSubviews()` is called (which normally happens during `build()` and `render()`).
+- **`hasSubview(view)`** tests if a view is registered.
+- **`removeSubview(view) -> [view, selector] | null`** unregisters a subview. Note that it does not remove the subview from the DOM.
+- **`attachSubviews() -> this`** attaches each subview to the view's DOM element. If the given subview was registered with a selector, the element it picks out will become the subview's parent. Otherwise, it is appended to the view's element.
+- `**renderSubviews() -> this**` is a convenience method for invoking `render` on each subview; it is not called by anything in the render lifecycle. Note `renderSubviews()` does not call `attachSubviews()`.
+
+### Future Enhancements
+
+View handling could use a lot of work to eliminate boilerplate and simplify common tasks. The biggest pain-points I've noted are:
+
+- Views have no way of being notified when their DOM element is actually parented (or unparented) in the DOM. This is generally a very hard problem in rich client development on the web, and there are no bulletproof solutions. Still, we should be providing some methods which in turn fire an event for this.
+- As mentioned in the discussion of the render lifecycle, it would help to integrate a default data-binding convention and related methods.
+- Events don't bubble through the view hierarchy as they do with the DOM. This means views must manually inform their subviews to re-render. I left this unimplemented mostly because of the render-vs-update issue above.
+
+
+
+[backbone]: http://backbonejs.org/
+[underscore]: http://underscorejs.org/
+[json]: https://developer.mozilla.org/en/JSON#toJSON()_method
diff --git a/old-docs/internals/dashboard.md b/old-docs/internals/dashboard.md
new file mode 100644 (file)
index 0000000..29a5e15
--- /dev/null
@@ -0,0 +1,8 @@
+# Dashboard
+
+## Features
+
+- Home: Marquee/highlighted graphs showed, plus
+- Browse graphs by time, cat, tag
+- View a graphs -> Edit
+
diff --git a/old-docs/internals/data-ui.md b/old-docs/internals/data-ui.md
new file mode 100644 (file)
index 0000000..944ebfa
--- /dev/null
@@ -0,0 +1,2 @@
+# Data UI
+
diff --git a/old-docs/internals/framework.md b/old-docs/internals/framework.md
new file mode 100644 (file)
index 0000000..88ba7d5
--- /dev/null
@@ -0,0 +1,57 @@
+# UI Base Framework
+
+Notes from working with Backbone, Bootstrap, and other friends.
+
+
+## Bootstrap Enhancements
+
+### CSS Classes
+- Apple-style tokens/tags
+- Table styles for "active", "error", etc
+- Table highlights (like stickies in a book)
+- Container Shadow Lines (horizontal & vertical)
+- Lion-style scrollbars
+
+
+### Components
+- Better Isotope integration
+- Tear-away / Pop-out containers
+- Facebook-style Thing Selector, with filtering, a drag-n-drop hopper, etc
+- On-hover Components (like changing to a button, expanding, etc); also, +HoverIntent
+
+
+## Backbone Base
+
+- Nested Models are a huge painpoint
+- A more coherent "loading" event model is needed
+- How can we unify a view's root DOM element with the view?
+    - Free event bubbling between views
+    - Eliminate the "I heard an event, what view handles it?" dance
+    - Reduces need for some boilerplate views
+    - Data properties to create "anonymous inner views":
+        - `<div data-view="ViewClass" data-view-extends="SuperViewClass" data-model="ModelClass" />`
+        - ...then need some sort of IOC-style wiring to hand out objects
+    - Requires rich events with nested properties that can be used for filtering on subscribe
+- A View has many `ViewField`s, mapping to the model's attributes.
+    - Implicitly created for simple fields (text, form elements)
+    - Handles data-binding:
+        - Serialization for presentation formatting
+        - Deserialization back into typed value
+        - Fires element-specific `change` events
+    - Subclasses for:
+        - Rich widgets (datepicker, colorpicker, etc)
+        - Dependent and derived fields
+        - Or declarative config and event binding
+- `CollectionView`, when the view holds a `Backbone.Collection`, not a `Backbone.Model`
+    - Comes with CRUD for .add(model)/remove(model), creating the needed subview, attaching it, etc
+    - Subclasses with specialized support for `ListView`, `DictView`
+    - Mixins for further subclasses for:
+        - `TableView` (and all manner of stupid subclasses)
+        - `Form{List,Dict}View`
+        - `TabPane{List,Dict}View`
+- All Views should have a `StateMachine` (also supporting the `EventEmitter` API) to ease coordinating event flows
+    - Significantly simplifies "loading" and "waiting" states
+    - Trivial to "disable" elements
+    - Easy modal UIs
+
+
diff --git a/old-docs/internals/middleware.md b/old-docs/internals/middleware.md
new file mode 100644 (file)
index 0000000..181236d
--- /dev/null
@@ -0,0 +1,66 @@
+# Limn Middleware
+
+Limn is an [Express][express] application, allowing it to be effortlessly composed as middleware with both Express and [Connect][connect] applications. 
+
+
+You mount Limn in your application the same as you would other piece of middleware, by passing it to `app.use()`.
+
+Via [Express][express]:
+
+```js
+var limn    = require('limn')
+,   express = require('express')
+;
+
+var app = express()
+  .use( express.logger('dev') )
+  .use( express.static('public') )
+  
+  .get( '/', function(req, res){
+    res.send('hello world');
+  })
+  
+  // Mount Limn at /vis
+  .use( '/vis', limn({
+    dataDir : './data',
+    proxy   : true
+  }) );
+
+app.listen(3000);
+```
+
+
+Or via [Connect][connect]:
+
+```js
+var limn    = require('limn')
+,   connect = require('connect')
+;
+
+var app = connect()
+  .use( connect.logger('dev') )
+  .use( connect.static('public') )
+  
+  // Mount Limn at /
+  .use( limn({
+    dataDir : './data',
+    proxy   : true
+  }) );
+
+app.listen(3000);
+```
+
+
+## Options
+
+- `dataDir` -- [$CWD/data] Path to directory where data files should be written.
+- `datasetDir` -- Path to a directory to statically serve as `/data` if present.
+- `proxy`
+    - `enabled` -- [false] Enables remote dataset proxy. If omitted, the proxy will be enabled if either `proxy.whitelist` or `proxy.blacklist` are set.
+    - `whitelist` -- Array of domain patterns to whitelist for proxy. Strings are matched via glob-like syntax, but regular expressions may also be passed. If `proxy.enabled` is true but no whitelist is provided, it defaults to `['*']`.
+    - `blacklist` -- Array of domain patterns to blacklist from proxying. Strings are matched via glob-like syntax, but regular expressions may also be passed.
+
+
+
+[express]: http://expressjs.com "Express"
+[connect]: http://senchalabs.org/connect "Connect"
diff --git a/old-docs/internals/scaffold.md b/old-docs/internals/scaffold.md
new file mode 100644 (file)
index 0000000..40bf678
--- /dev/null
@@ -0,0 +1,2 @@
+# Scaffold Framework
+
diff --git a/old-docs/internals/specs/chart-element.yaml b/old-docs/internals/specs/chart-element.yaml
new file mode 100644 (file)
index 0000000..5055c01
--- /dev/null
@@ -0,0 +1,31 @@
+###  Chart Element Spec  ###
+# 
+# Describes the format of graph json/yaml files saved by the Limn framework.
+
+
+elementType         : Typename of the ChartElementView which renders this element.
+
+index               : Positional index of this element, for layering against its siblings.
+label               : (?) Human-readable label for this metric. If empty, defaults to the column
+                      label for the datasource.
+disabled            : Whether this metric is disabled. Disabled metrics behave exactly like
+                      deleted/non-existant metrics, except that they still appear in the dataset UI.
+
+# XXX: should this be an array of metrics?
+data : 
+    source_id       : Identifier for the datasource that backs this metric.
+    source_col      : Column (index or id) in the datasource that backs this metric.
+    type            : (?) DataType for this column -- usually "int".
+    timespan : 
+        # clamp the timespan to these bounds and transform to match the step
+        start       : Start of the data, eg: 2012/01/01T00:00:00 or 2012/01/01 or 1325404800
+                      All dates should be seconds-since-the-epoch, or ISO-8601 formatted: YYYY/MM/DDThh:mm:ss.s
+                      See also: http://www.w3.org/TR/NOTE-datetime
+                      And: http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html
+        end         : End of the data, eg: 2012/02/01T00:00:00 or 2012/02/01 or 1328083200
+        step        : Amount of time between elapsed between each row, measured in seconds, eg: 86400
+
+options             : Dict of chart option names to values.
+                      Lookups cascade to the parent element, terminating before the Graph object.
+elements            : Array of children, also Chart Elements.
+
diff --git a/old-docs/internals/specs/chart-options/source-group-options.yaml b/old-docs/internals/specs/chart-options/source-group-options.yaml
new file mode 100644 (file)
index 0000000..fbeaa0f
--- /dev/null
@@ -0,0 +1,13 @@
+# DataSource Group Options
+#   When importing all metrics from a DataSource, configuration (and UI/UX) can be simplified.
+
+palette:
+    - id:String
+    - [color, color]
+    - Object: 
+        start : color
+        end   : color
+        steps : 0 -- a positive number; otherwise, adjust number of steps to fit number of columns by interpolating colors
+labels:
+    format : '$source, $metric'
+
diff --git a/old-docs/internals/specs/chart-options/stroke-object.yaml b/old-docs/internals/specs/chart-options/stroke-object.yaml
new file mode 100644 (file)
index 0000000..e70bcdc
--- /dev/null
@@ -0,0 +1,15 @@
+# Stroke Options Object
+#   Many chart elements accept an array of Stroke objects, which are defined as follows:
+
+- width: 4.0
+- color: null := default from palette | a valid CSS color
+- opacity: 1.0
+- style:
+    - solid | dashed | dotted -- presets for advanced options which are otherwise hidden
+    - solid  := (all defaults)
+    - dashed := dashes:[2,2]
+    - dotted := dashes:[1,1], caps:round, joins:round
+# (advanced options)
+- dashes: null | dash pattern array (int array) -- null == solid
+- caps: butt | round | square
+- joins: miter | round | bevel
diff --git a/old-docs/internals/specs/chart-options/timeseries-options.md b/old-docs/internals/specs/chart-options/timeseries-options.md
new file mode 100644 (file)
index 0000000..cd138ef
--- /dev/null
@@ -0,0 +1,73 @@
+# Timeseries Chart Options
+
+Right now, all options are global (apply to all metrics of a chart) because that's how Dygraph worked. This doesn't make sense when you have per-metric options, which we see bleeding in now with color etc, or when you want to mix and match chart-types.
+
+That said, most "local" (per-metric) options also make sense as global defaults for new metrics. Cases where that doesn't hold are noted.
+
+
+## Local Per-Metric Options
+
+- id
+- enabled
+- visible
+- type
+
+- label
+- format
+- timespan: [start, stop] -- inferred
+- stroke[]
+    - width: 4.0
+    - color: default from palette
+    - opacity: 1.0
+    - style: solid | dashed | dotted -- presets for advanced options which are otherwise hidden
+        - solid  := (all defaults)
+        - dashed := dashes:[2,2]
+        - dotted := dashes:[1,1], caps:round, joins:round
+    - (advanced options)
+    - dashes: null | dash pattern array (int array) -- null == solid
+    - caps: butt | round | square
+    - joins: miter | round | bevel
+- fill: null | color | gradient?
+- opacity: 1.0
+- points
+    - enabled: false
+    - size: 0
+    - color: inherit from first stroke
+- horizon: false
+- smoothing: false
+- axis
+    - scale: linear | log | sqrt | pow | (discrete | quantize | quantile)?
+    - scaleQuanta: Number -- for linear, log(?), pow, discrete, quant*
+    - range: [min, max] -- auto-inferred from dataset extents
+    - ticks: Number
+    - format: inherit from format
+- data
+    - errorBars: false | choose error data column
+
+
+## Chart-Global Options
+
+- palette: id:String | [color, color] | Object:
+    - start: color
+    - end: color
+    - steps: 0 -- a positive number; otherwise, adjust number of steps to fit number of columns by interpolating colors
+- stacked: false
+- axis
+- grid[x,y]
+    - enabled: false
+    - stroke
+- timespan: [start, stop] -- inferred
+- legend
+    - enabled: true
+    - fixed: false -- when true, graph is smaller to accommodate legend; otherwise, legend moves itself
+    - draggable: false -- legend won't dodge the mouse so you can grab it
+- zoom
+    - enabled: true -- enables Y-zoom independent of pan
+    - starting: 1.0
+    - range: [min, max]
+- pan
+    - enabled: true
+    - starting: [0, 1.0] -- Floats as % of timespan, or Dates
+- minimap: false
+- transitions: ?
+
diff --git a/old-docs/internals/specs/chart-options/timeseries-options.yaml b/old-docs/internals/specs/chart-options/timeseries-options.yaml
new file mode 100644 (file)
index 0000000..65379a0
--- /dev/null
@@ -0,0 +1,50 @@
+# Timeseries Chart Options
+#   These options are expected by many downstream chart elements, and so can be
+#   set upstream for convenience. Some even have reasonable defaults!
+
+enabled: true -- disabling an element allows you to save an element without displaying it at all.
+
+label: Label for a single metric. (Default: inherit from DataSource Metric)
+type: "int" -- data type
+
+timespan :
+    axis : x | y -- governs which axis to use as the time axis
+    range: [start, stop] -- inferred by default from the data series
+scale :
+    # applies to the value dimension of the series
+    type: linear | log | sqrt | pow | (discrete | quantize | quantile)?
+    scaleQuanta: Number -- for linear, log(?), pow, discrete, quant*
+    range: [min, max] -- auto-inferred from dataset extents
+    clamp : false -- limit to values in the range
+    round : false -- round values to integers/discrete values
+
+stroke: Stroke[] -- Strokes applied to the elements of the visualization.
+opacity: 1.0 -- applies to all features of the element as a whole. You can still use rgba() to add alpha to fills, etc.
+fill: null | color | gradient?
+visible: true -- Start visible?
+format: Format string for a data value when displayed (such as in an inspector).
+        (Default: KMB with commas and ~3 sigFigs)
+
+points:
+    # Display for the individual data points -- creates hidden PointsChartElement as a child.
+    - enabled: false
+    - size: 0
+    - color: null := inherit from first stroke | color
+
+axis:
+    - scale: linear | log | sqrt | pow | (discrete | quantize | quantile)?
+    - scaleQuanta: Number -- for linear, log(?), pow, discrete, quant*
+    - range: [min, max] -- auto-inferred from dataset extents
+    - ticks: Number -- uses d3 heuristic by default
+    - format: inherit from data value format
+    - position: left | right || top | bottom
+
+
+
+
+### XXX: Maybe!
+
+errorBars: false | choose error data column
+horizon: false
+smoothing: false
+
diff --git a/old-docs/internals/specs/chart-options/viewport-options.yaml b/old-docs/internals/specs/chart-options/viewport-options.yaml
new file mode 100644 (file)
index 0000000..7644dd7
--- /dev/null
@@ -0,0 +1,20 @@
+## Chart Viewport Options
+
+width : auto
+height : 320
+# margin : {top:20, right:20, bottom:20, left:20}
+
+zoom:
+    # enables Y-zoom independent of pan by drawing a rect
+    enabled: true
+    starting: 1.0
+    range: [min, max]
+pan:
+    enabled: true
+    starting: [0, 1.0] -- Floats as % of timespan, or Dates
+    bleed :
+        # allows pan beyond the data range
+        - false | 0 -- Disabled.
+        - Int | '{Number}px' -- Allow this many pixels of overpan on data range. [Default: 20]
+        - Float | '{Number}%' -- Allow bleed equal to a percentage of the **Viewport width** on both sides of the data range.
+        - [begin, end] -- Specify the begin and end bleed separately.
diff --git a/old-docs/internals/specs/dataset-spec.yaml b/old-docs/internals/specs/dataset-spec.yaml
new file mode 100644 (file)
index 0000000..47fc0b7
--- /dev/null
@@ -0,0 +1,48 @@
+###  Limn Datasource Spec  ###
+# 
+# Describes the format of datasource json/yaml files for use in the Limn chart UI.
+# 
+# Reminder: the project transparently compiles any .yaml files requested as .json
+# at request time -- you're welcome to generate them in either form.
+# TODO: Thrift/Avro schema?
+
+
+id        : Unique identifier for this datasource. This file should be named `{id}.{ext}`
+            and live in the data directory alongside the data file.
+name      : Human-friendly name for the datasource.
+shortName : A shorter version of the datasource name for use in the UI.
+title     : Title for use on the graph of the data in some chart-types.
+subtitle  : A subtitle for use on the graph of the data in some chart-types.
+desc      : Description of the datasource.
+notes     : Notes about the datasource, particularly about definitions, data integrity,
+            data normalization, data generation, etc.
+
+format    : Data format. Valid: csv, json. (Maybe in the future: yaml, xml, etc.)
+url       : Canonical URL for the datasource's data file, eg: /data/datasources/{id}.csv
+
+
+### Timespan and quanta covered by this datasource
+timespan :
+    start : Start of the data, eg: 2012/01/01T00:00:00 or 2012/01/01 or 1325404800
+            All dates should be seconds-since-the-epoch, or ISO-8601 formatted: YYYY/MM/DDThh:mm:ss.s
+            See also: http://www.w3.org/TR/NOTE-datetime
+            And: http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html
+    end   : End of the data, eg: 2012/02/01T00:00:00 or 2012/02/01 or 1328083200
+    step  : Amount of time between elapsed between each row, measured in seconds, eg: 86400
+
+### Metadata about the Datatypes
+# Note: 'columns' can also be supplied as a list of { label, type, id } objects instead of two lists. (TODO)
+columns :
+    ids    : List of the column-ids in order. This is like column-label, except it must be unique
+             for the dataset. This allows charts to specify their metrics by (dataset, col_id)
+             rather than column-index, making the chart independent of column-order.
+    labels : List of the column-names in order. (Future optimization: the date column could
+             be omitted if the data is sorted and contains no gaps -- each datapoint is exactly
+             timespan.step apart, and none are missing.)
+    types  : List of the column datatype-names in order. Valid type names: date, float, int.
+
+### Defaults for charting
+chart :
+    chartType : Visualization library to use. Valid: dygraphs.
+    options   : Dict of option-names to values.
+
diff --git a/old-docs/internals/specs/graph-spec.yaml b/old-docs/internals/specs/graph-spec.yaml
new file mode 100644 (file)
index 0000000..7d5d4a2
--- /dev/null
@@ -0,0 +1,45 @@
+###  Graph Spec  ###
+# 
+# Describes the format of graph json/yaml files saved by the Limn framework.
+
+
+id                      : Unique identifier for this graph. This file will be named {id}.json
+                          and live in the data directory alongside the data file. Defaults to the slug.
+slug                    : Unique identifier used in URLs for the graph.
+
+name                    : Human-friendly name given to the graph.
+shortName               : A shorter version of the graph name for use in the UI.
+desc                    : Description of the graph.
+
+width                   : Width in pixels of the graph, or "auto" to fit to 100% of the container.
+height                  : Height in pixels of the graph, or "auto" to fit to 100% of the container.
+parents                 : Array of graph-ids from which to inherit values.
+
+
+# `elements` is an Array of Chart Element objects
+elements : 
+    elementType         : Typename of the ChartElementView which renders this element.
+    
+    index               : Positional index of this element, for layering against its siblings.
+    label               : (?) Human-readable label for this metric. If empty, defaults to the column
+                          label for the datasource.
+    disabled            : Whether this metric is disabled. Disabled metrics behave exactly like
+                          deleted/non-existant metrics, except that they still appear in the dataset UI.
+    
+    # XXX: should this be an array of metrics?
+    data : 
+        source_id       : Identifier for the datasource that backs this metric.
+        source_col      : Column (index or id) in the datasource that backs this metric.
+        type            : (?) DataType for this column -- usually "int".
+        timespan : 
+            start       : Start of the data, eg: 2012/01/01T00:00:00 or 2012/01/01 or 1325404800
+                          All dates should be seconds-since-the-epoch, or ISO-8601 formatted: YYYY/MM/DDThh:mm:ss.s
+                          See also: http://www.w3.org/TR/NOTE-datetime
+                          And: http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html
+            end         : End of the data, eg: 2012/02/01T00:00:00 or 2012/02/01 or 1328083200
+            step        : Amount of time between elapsed between each row, measured in seconds, eg: 86400
+    
+    options             : Dict of chart option names to values.
+                          Lookups cascade to the parent element, terminating before the Graph object.
+    elements            : Array of children, also Chart Elements.
+
diff --git a/old-docs/internals/specs/legacy-graph-spec.yaml b/old-docs/internals/specs/legacy-graph-spec.yaml
new file mode 100644 (file)
index 0000000..47e39b3
--- /dev/null
@@ -0,0 +1,51 @@
+###  Legacy Graph Spec  ###
+# 
+# Describes the format of graph json/yaml files saved by the Limn framework.
+
+
+id                      : Unique identifier for this graph. This file will be named {id}.json
+                          and live in the data directory alongside the data file. Defaults to the slug.
+slug                    : Unique identifier used in URLs for the graph.
+
+name                    : Human-friendly name given to the graph.
+shortName               : A shorter version of the graph name for use in the UI.
+desc                    : Description of the graph.
+
+width                   : Width in pixels of the graph, or "auto" to fit to 100% of the container.
+height                  : Height in pixels of the graph, or "auto" to fit to 100% of the container.
+parents                 : Array of graph-ids from which to inherit values.
+
+### Metadata about the Data Sources and Metrics
+data : 
+    palette             : Name of a color palette to use to generate new default colors for columns.
+    # `metrics` is an array of Metric objects, matching the description below
+    metrics : 
+        label           : Human-readable label for this metric. If empty, defaults to the column
+                          label for the datasource.
+        type            : DataType for this column -- usually "int".
+        disabled        : Whether this metric is disabled. Disabled metrics behave exactly like
+                          deleted/non-existant metrics, except that they still appear in the dataset UI.
+        timespan : 
+            start       : Start of the data, eg: 2012/01/01T00:00:00 or 2012/01/01 or 1325404800
+                          All dates should be seconds-since-the-epoch, or ISO-8601 formatted: YYYY/MM/DDThh:mm:ss.s
+                          See also: http://www.w3.org/TR/NOTE-datetime
+                          And: http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html
+            end         : End of the data, eg: 2012/02/01T00:00:00 or 2012/02/01 or 1328083200
+            step        : Amount of time between elapsed between each row, measured in seconds, eg: 86400
+        
+        # DataSource
+        source_id       : Identifier for the datasource that backs this metric.
+        source_col      : Column in the datasource that backs this metric.
+        
+        # Chart Options
+        color           : Color of the line in the chart.
+        visible         : Whether this metric begins hidden in the display.
+        format_value    : Format string or method to use to format displayed metric values.
+        format_axis     : Format string or method to use to format displayed metric values in the axis.
+        
+        transforms      : List of transforms to apply to the data before display.
+        scale           : Scaling factor for this metric (a shortcut for transforming the data).
+
+### Defaults for charting
+chartType               : Visualization library to use. Valid: "dygraphs".
+options                 : Dict of chart option names to values.
diff --git a/old-docs/later.md b/old-docs/later.md
new file mode 100644 (file)
index 0000000..db1d125
--- /dev/null
@@ -0,0 +1,20 @@
+# later
+
+- [Graph Edit UI]
+    - Filter/Sort attributes, datasets, etc
+    - Outline all changed options
+- Dashboard
+    - How should they be laid out?
+- Stacked bar charts seem to be something a lot of us are into, but dygraphs won't be doing that. (tho d3 does)
+- Sort by custom tag order
+
+- Graphs should have tags
+- 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
+
diff --git a/old-docs/notes/d3-mvc.md b/old-docs/notes/d3-mvc.md
new file mode 100644 (file)
index 0000000..f83f243
--- /dev/null
@@ -0,0 +1,29 @@
+# d3.mvc
+
+An MVC framework built on top of `d3`.
+
+
+## d3.model
+
+d3.model(attrs) -> d3.Model
+
+### Attribute Accessors
+
+- attr() -> Map
+- attr(k) -> *
+- attr(k, v) -> this
+- has(k) -> Boolean
+- get(k, [default]) -> *
+- set(k, v) -> this
+- del(k) -> this
+
+
+
+
+
+## d3.view
+
+
+
+
+
diff --git a/old-docs/notes/graphs.md b/old-docs/notes/graphs.md
new file mode 100644 (file)
index 0000000..b8c46c5
--- /dev/null
@@ -0,0 +1,54 @@
+# Graphs and Metrics for the March Dealine
+
+- Reprocess all datafiles and fix dates to use `/` instead of `-` -- see:
+    - (Safari) dygraph on safari has a bug parsing dates, bug http://code.google.com/p/dygraphs/issues/detail?id=287
+
+## 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.
+
+       For each language project:
+       
+       - 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
+       
+       ERIK's input - Better comparative trend reporting - states that he would like to be able to compare all these metrics between languages
+
+- 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/old-docs/notes/housekeeping.md b/old-docs/notes/housekeeping.md
new file mode 100644 (file)
index 0000000..c464fd2
--- /dev/null
@@ -0,0 +1,56 @@
+# Housekeeping
+
+## Base
+- BaseModel
+    - `.fromURL()` -- use `.chartType.parseValue k, v` for parsers
+- BaseView
+    - `.modelEvents` or maybe `.events.{ el, model, view... }`
+- AppView for common `main()` tasks
+- ScaffoldView: generic form for a model's fields
+    - Bootstrap horizontal-form
+    - Hooks for filtering visibility
+    - Controls: Save, Load, Cancel; Delete
+
+
+## Edit UI
+- Backbone.Router?
+- Loading Indicator:
+    - Render UI at start with `loading` mode, showing placeholders and indicator
+    - Activate Loading Spinner post-ready when waiting
+
+
+## Data UI
+- Timespan compat check
+- Metric: `column_idx` -> `column_id`
+- Tab-pane height fix? all `inline-block`: `<dataset-pane> <sep-line height="100%"> <metric-edit-panes>`
+- Should data files have timespan in name?
+
+
+## Graph Options UI
+- `tags.json` to describe colors, sorting, ignored-tags
+- Outline modified
+- Fix UI pill color when expanded
+- Filter:
+    - by major Categories: labels, grid, axes, display, interactivity
+    - by Tag (collapsable box)
+    - via typeahead box: names + tags
+- Sort
+    - by: Modified, Importance, Tag, Lexical
+    - Use `categoryRows`
+- Derived Options:
+    - visibility
+    - colors
+    - dateWindow
+    - file
+    - width, height
+- Buttons: Reset {all,visible} to defaults
+
+
+## Misc
+- Generate markdoc wiki from `/docs` on Build, Deploy
+- Refactor directories:
+    - dataset/
+        dataset/ +metric
+        datasource/ +column
+- Wrap `Backbone.extend()` to fire `subclass` event on parent class
+
diff --git a/old-docs/notes/notes.md b/old-docs/notes/notes.md
new file mode 100644 (file)
index 0000000..8445690
--- /dev/null
@@ -0,0 +1,52 @@
+# notes
+
+## Limn
+
+
+
+
+
+## Data UI
+
+
+## Value Formatter
+
+```
+[sign][#][minW][~maxW][,][.precision][type]
+
+sign        ::=  "+" | "-" | " "
+#           ::=  Output will be prefixed by '0b' for binary, '0o' for octal, or '0x' for hexadecimal
+minW        ::=  Minimum field width
+maxW        ::=  Maximum field width
+,           ::=  Use comma for thousands separator
+precision   ::=  How many digits displayed...
+                    fF - after the decimal point
+                    gG - before and after the decimal point
+type        ::=  Use type-specific formatting:
+                    String:     s
+                    Integer:    b (base2) | c (unicode chars) | d (base10) | o (base8) | xX (base16) | n (locale-aware)
+                    Float:      eE (scientific) | fF (fixed) | gG (general) | % | 
+                                k (use KMBT when rounding;  )
+```
+
+
+## Start Server in Screen & Tee Logs
+
+    screen -dr limn
+    ./lib/server/server.co | tee -a logs/limn.log
+
+
+## Deployer Config
+
+    set -xg LIMN_DEPLOY_HOST dsc@reportcard2.pmtpa.wmflabs
+    set -xg LIMN_DEPLOY_PATH /srv/reportcard/limn/
+    set -xg LIMN_DEV_HOST master.reportcard.wmflabs.org
+
+
+## Data UI
+
+- Data UI = DataView
+    - DataSet UI = DataSetView
+        - DataSetMetricView
+    - Metric UI = MetricEditView
+        - DataSource UI = DataSourceUIView
\ No newline at end of file
diff --git a/old-docs/notes/option-tag-notes.md b/old-docs/notes/option-tag-notes.md
new file mode 100644 (file)
index 0000000..afb83cf
--- /dev/null
@@ -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/old-docs/notes/prototype-sync-up.mediawiki b/old-docs/notes/prototype-sync-up.mediawiki
new file mode 100644 (file)
index 0000000..a78bea4
--- /dev/null
@@ -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/old-docs/todo.md b/old-docs/todo.md
new file mode 100644 (file)
index 0000000..0d68f7d
--- /dev/null
@@ -0,0 +1,179 @@
+# todo
+
+## GitHub Migration
+- Resolve workflow for /data
+    - Extract history for /data, re-commit metadata files
+- Update & scrub docs & readme
+- Webhook to push to Gerrit (on analytics.wmflabs.org?)
+
+
+
+## Features
+
+### Display UI
+- Toggle Per-Metric Visibility
+    - Should redraw axes & scaling
+- Keyboard Shortcuts:
+    - Zoom to last 3 months
+    - Zoom out
+    - Pan left/right by timestep
+- Callout: current key-metric; YoY%, MoM% for key-metric
+
+
+### Charting
+- Better Benchmark Line on the graph
+- Per-series styles
+- Meta-metrics:
+    - Year-over-year
+
+
+### Edit UX
+- Info & Alert message boxes, eg: save, load success/error, validation
+- Visual indicator graph is unsaved or has changes
+- Keyboard Shortcuts:
+    - Move between tabs
+    - Zoom/pan chart
+    - Focus on form?
+    - Manipulating datasources and other complex forms (up, down, select, back, etc)
+- Fields in `info` tab for graph identifiers:
+    - Short URL (slug only)
+    - Full URL (no slug -- all options)
+    - Embed code (iframe with .js pointer)
+- Standard-view preview
+- Bold/darken numeric portion of formatted legend? Decrease size, change color of KMB suffix?
+
+
+### GraphModel
+- Use dataset name for `Graph.name` if empty
+- Cascade dataset chart-type defaults before `root`
+- `.toURL()`:
+    - Slug only if not `.isNew()`
+    - Filter `id` out
+    - Diff with last saved state
+    - validation: check `slug` is unique if unsaved
+    - Do not include `undefined` & empty values
+    - Compact some components (w/ collapse and expand methods):
+        - `options` -> `o`
+        - `dataset` -> `d`
+- Graph Options (non-chart options):
+    - `palette`: String | { name:String, length:Number }
+    - Zoom range: `dateWindow`
+    - redraw graph on page resize?
+- history w/ undo/redo
+- "Save as PNG" link; post PNG to server
+
+
+### Data UI
+- Controls:
+    - Delete metric
+    - Reorder metrics
+    - "Import All..." Button: import all cols from a datasource
+        - Backwards compat with `dataset` URL-field
+- Global Settings Pane w/ Palette, etc
+    - `palette`: String | { name:String, length:Number }
+- Metric Presentation:
+    - label, color
+    - Date range selector & scrubber?
+    - visible, disable
+    - transform
+    - legend, label format
+    - axes
+- Timespan:
+    - Step compat check
+    - Use `step` to format date legend/labels (`1mo`? omit day, eg `2012/01`)
+    - Date picker
+- Apply `meta.chart.{type, options}`
+
+
+### Annotations
+- Props:
+    - label/title
+    - desc/text: markdown
+    - location:
+        - dataset, value
+        - series, x
+    - disabled
+    - visible?
+    - dygraphs:
+        - cssClass
+        - attachAtBottom
+        - tickHeight
+    - symbol:
+        - letter: auto from `title` by default
+        - icon: replace letter with `<i class="icon-foobar"/>`
+- Actions:
+    - CRUD
+    - Enable/Disable
+    - Clear All
+    - Ordering?
+- Events:
+    - show
+    - hide
+- UI for icon?
+- Click chart to add an Annotation
+
+
+### Chart Options UI
+- `tags.json` to describe colors, sorting, ignored-tags
+- Outline modified
+- Fix UI pill color when expanded
+- Filter:
+    - by major Categories: labels, grid, axes, display, interactivity
+    - by Tag (collapsable box)
+    - via typeahead box: names + tags
+- Sort
+    - by: Modified, Importance, Tag, Lexical
+    - Use `categoryRows`
+- Derived Options:
+    - `visibility`
+    - `colors`
+    - `dateWindow`
+    - `file`
+    - `width`, `height`
+- Buttons: Reset {all,visible} to Defaults
+
+
+### Server
+- Prompt to override slug
+- Generate UUID for `Graph.id`
+- Embedding endpoints: iframe URL, `.js`
+
+
+### Admin UIs
+- Manage saved Graphs
+- Create new DataSource
+- User/Group management
+
+
+### Dashboard
+- Combine Graphs UI
+- Featured Graphs (reportcard)
+- Browse Graphs
+    - New
+    - Recently Edited
+    - Popular
+- Graph tags as categories (searchable?)
+- Users & Auth
+- "Fork this Graph"
+- User-relative slugs? `/user/:user/graph/:graph.slug/`
+- Sparklines
+
+
+
+
+
+
+
+## Future
+
+### General Wishlist
+- Library for undo/redo
+- LocalStorage for unsaved changes, so accidental refresh (etc) doesn't lose changes
+
+
+### from Diederik
+
+- Relationships between datasets which can help inform rich UI responses (click on "Europe" and have it expand to the countries)
+- easily create new graphs side-by-side
+- clear current graph
+