Merge lp:~bcsaller/juju-gui/framework-docs into lp:juju-gui/experimental

Proposed by Benjamin Saller
Status: Merged
Merged at revision: 261
Proposed branch: lp:~bcsaller/juju-gui/framework-docs
Merge into: lp:juju-gui/experimental
Diff against target: 266 lines (+244/-0)
2 files modified
docs/d3-component-framework.rst (+242/-0)
docs/index.rst (+2/-0)
To merge this branch: bzr merge lp:~bcsaller/juju-gui/framework-docs
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+136578@code.launchpad.net

Description of the change

D3 Components Documentation

This make an effort to provide a high level modules writer guide. As a
concession it refers the reader to portions of the YUI event and D3 data
binding docs.

https://codereview.appspot.com/6858085/

To post a comment you must log in.
Revision history for this message
Benjamin Saller (bcsaller) wrote :

Reviewers: mp+136578_code.launchpad.net,

Message:
Please take a look.

Description:
D3 Components Documentation

This make an effort to provide a high level modules writer guide. As a
concession it refers the reader to portions of the YUI event and D3 data
binding docs.

https://code.launchpad.net/~bcsaller/juju-gui/framework-docs/+merge/136578

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/6858085/

Affected files:
   A [revision details]
   A docs/d3-component-framework.rst

Revision history for this message
Nicola Larosa (teknico) wrote :

Thanks for these docs, they're much useful.

I made quite a few small adjustments to the text flow and markup, so
instead of wasting your time and mine by making lots of small comments
inline, I just created a new branch and made all changes there. I did
not reflow paragraphs even when lines got too long, to avoid obscuring
the changes in the diff.

Note that some additions and deletions of blank lines are needed to make
the document compile to HTML correctly.

I also added the document to the index.rst file, so that it appears in
the generated output.

I'm sorry for the extensive rework: I do believe it significantly
improves overall readability, however.

Please find the changes at lp:~teknico/juju-gui/framework-docs .

https://codereview.appspot.com/6858085/

Revision history for this message
Benjamin Saller (bcsaller) wrote :

On 2012/11/28 12:33:03, teknico wrote:
> Thanks for these docs, they're much useful.

> I made quite a few small adjustments to the text flow and markup, so
instead of
> wasting your time and mine by making lots of small comments inline, I
just
> created a new branch and made all changes there. I did not reflow
paragraphs
> even when lines got too long, to avoid obscuring the changes in the
diff.

> Note that some additions and deletions of blank lines are needed to
make the
> document compile to HTML correctly.

> I also added the document to the index.rst file, so that it appears in
the
> generated output.

> I'm sorry for the extensive rework: I do believe it significantly
improves
> overall readability, however.

> Please find the changes at lp:~teknico/juju-gui/framework-docs .

Thank you! I merged your changes to this branch and will re-propose if
there is another reviewer.

https://codereview.appspot.com/6858085/

lp:~bcsaller/juju-gui/framework-docs updated
261. By Benjamin Saller

merge Nicola's doc changes, thanks

Revision history for this message
Benjamin Saller (bcsaller) wrote :
Revision history for this message
Gary Poster (gary) wrote :
Download full text (12.1 KiB)

Hi Ben. This is really a great improvement. Thank you.

I have a number of suggestions, and I noticed that Nicola has a branch
of changes. I hope it is not too hard to reconcile our two reviews.

I did have a few observations about the framework itself. I would be
happy to discuss them if you would like.

Thanks again.

Gary

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst
File docs/d3-component-framework.rst (right):

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode21
docs/d3-component-framework.rst:21: models one concern of the resultant
Scene.
This is a reasonable basic definition of a module. It could be expanded:
what do you mean by a "concern"? What's a guideline for dividing up
these concerns? Beyond that, some of your other terms could use
definitions. You start to define a "component" in line 35, but what is
the relationship between d3 and the "component"? Is the component
expected to correspond with a scene? What is the component a component
of? A definition of scene (which you capitalize here for a reason that
isn't clear to me) would be helpful as well. Perhaps the definition of
component should come before that of module because this is a
"component" system. Perhaps also these definitions deserve their own
section, but that's just one way of many to handle it.

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode37
docs/d3-component-framework.rst:37: added options can be passed that
will be made available in the modules runtime.
Modules' run times or module's run time.

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode38
docs/d3-component-framework.rst:38: Modules added by via the `addModule`
method automatically have a reference to
"Added by the" or "added via the"

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode40
docs/d3-component-framework.rst:40: the addModule call in an Attribute
call options which will default to an empty
…the addModule call result in an attribute called 'options,' which…

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode47
docs/d3-component-framework.rst:47: This example would create a new
component and using the MyModule constructor
…and then, using the MyModule constructor, create…

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode56
docs/d3-component-framework.rst:56: Components then support rendering,
drawing the scene described by any data the
I found this sentence hard to parse. "…which draws…" maybe?

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode64
docs/d3-component-framework.rst:64: information. Once update has been
called on on the modules each modules
…on the modules, each module's…

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode67
docs/d3-component-framework.rst:67: section on events below).
In terms of the framework itself, I wonder if the first render should
not call the normal render behavior. In other words,...

Revision history for this message
Gary Poster (gary) wrote :

To be clear, I am fine with you landing this with the document changes
that I have suggested (or similar ones, after reconciling my review and
the other). I do not need for the framework changes I mentioned to be
made in this branch. If you agree with those suggestions, though, please
make bugs and cards for them, or ask me to. I would be happy to.

https://codereview.appspot.com/6858085/

Revision history for this message
Benjamin Saller (bcsaller) wrote :

On 2012/11/28 14:12:29, gary.poster wrote:
> To be clear, I am fine with you landing this with the document changes
that I
> have suggested (or similar ones, after reconciling my review and the
other). I
> do not need for the framework changes I mentioned to be made in this
branch. If
> you agree with those suggestions, though, please make bugs and cards
for them,
> or ask me to. I would be happy to.

Thanks for the great review. I've gone and updated the doc in a way that
I hope is reflective of where we are headed while still being
immediately useful.

I'm going to go ahead and submit it next.

https://codereview.appspot.com/6858085/

Revision history for this message
Benjamin Saller (bcsaller) wrote :

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst
File docs/d3-component-framework.rst (right):

https://codereview.appspot.com/6858085/diff/1/docs/d3-component-framework.rst#newcode67
docs/d3-component-framework.rst:67: section on events below).
On 2012/11/28 14:10:29, gary.poster wrote:
> In terms of the framework itself, I wonder if the first render should
not call
> the normal render behavior. In other words, it should renderOnce and
then update
> and then stop.

> In fact, if update is supposed to be about incremental updates, and
renderOnce
> is about preparing for an update, then the render method seems
superfluous. The
> pattern that seems to be falling out to me is this: when you call
render on a
> component, it calls render on a module, and then it calls update on a
module.
> You never have to call render on the module again. Effectively,
renderOnce
> become render, and the current render disappears. This seems is
simpler and
> sufficient. If it is not sufficient, then my understanding is
insufficient, and
> we might need some more explanation here of some sort.

These are good ideas. There are some special cases where render might be
called more than once (detach/re-attach to DOM for example) which I've
added to the doc. Its also nice for modules to be assured that things
like the svg element will be present on the container (via its
renderOnce) so that when each modules render is called they can draw
reliably without lots of extra checks. I've expanded this section to
indicate this (I hope clearly).

https://codereview.appspot.com/6858085/

Revision history for this message
Benjamin Saller (bcsaller) wrote :

*** Submitted:

D3 Components Documentation

This make an effort to provide a high level modules writer guide. As a
concession it refers the reader to portions of the YUI event and D3 data
binding docs.

R=teknico, benjamin.saller, gary.poster
CC=
https://codereview.appspot.com/6858085

https://codereview.appspot.com/6858085/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'docs/d3-component-framework.rst'
2--- docs/d3-component-framework.rst 1970-01-01 00:00:00 +0000
3+++ docs/d3-component-framework.rst 2012-11-28 13:27:24 +0000
4@@ -0,0 +1,242 @@
5+======================
6+D3 Component Framework
7+======================
8+
9+The D3 Component codebase is a small framework with the following goals:
10+
11+- Support clear separation of concerns among various sections of application
12+ logic.
13+- Support incremental updates of the D3 scene.
14+- Allow simple configuration of features to aid in the reusability of D3
15+ application logic.
16+
17+It accomplishes this through a number of declarative tools and suggested
18+patterns around application development. The document below attempts to
19+explain this usage as it exists today.
20+
21+Module Writers Guide
22+====================
23+
24+Using the component framework means taking advantage of the tools offered
25+through its module system. Components manage one or more modules, each of which
26+models one concern of the resultant Scene.
27+
28+Modules declare events using structures dictated by the framework. Event
29+bindings allow the module to respond to both changes in its underlying data and
30+to changes in application state (through things like user interaction). It is
31+through these bound events that most rendering and interaction with the scene
32+are performed. Render becomes a rarely invoked complete redraw of the scene
33+while the modules themselves handle incremental updates via their event
34+handlers.
35+
36+Component API
37+=============
38+
39+Components support few actions (as most of the non-declarative work happens in
40+Modules). Components are containers for modules and have support functions for
41+adding and removing modules from their management. In addition, when modules are
42+added options can be passed that will be made available in the modules runtime.
43+Modules added by via the ``addModule`` method automatically have a reference to
44+the component via an YUI Attribute named ``component``, and any options passed to
45+the addModule call in an Attribute called ``options``, which will default to an empty
46+object.
47+
48+::
49+
50+ comp = new Component();
51+ comp.addModule(MyModule, {foo: bar})
52+
53+This example would create a new component and, using the MyModule constructor,
54+create an instance of this module (or use an instance if directly passed) and
55+set the ``component`` and ``options`` Attributes. In this example the Module would
56+have its ``foo`` option set to ``bar`` such that::
57+
58+ modInstance.get('options.foo') === 'bar'
59+
60+where modInstance is the instance created by the above example's addModule call.
61+
62+Components then support rendering, drawing the scene described by any data the
63+modules reference. This is done in a number of phases. The first time ``render``
64+is called, a special ``renderOnce`` is called. This allows the component to do any
65+necessary setup work. Typically this will be to create some svg element and
66+retain a reference to it. In the context of renderOnce, ``render`` will call
67+``update`` on each of its modules in the order they were added. The ``update``
68+method is used to recalculate any intermediate state associated with rendering
69+the various data objects. This typically includes things like position
70+information. Once ``update`` has been called on the modules, each module's
71+``render`` method is invoked. This performs the actual drawing work. It is at
72+this point that any d3js synthetic events are bound to the canvas (see the
73+section on events below).
74+
75+The most important aspect of addModule (and its inverse removeModule) is that
76+they properly support adding and removing event listeners. When a component's
77+addModule method is triggered it will bind all the declarative events of the
78+module, and when removeModule is called it will properly clean up event
79+subscriptions. Properly defining and using events is the core of the component
80+system and this is described in its own section.
81+
82+As a final step, if the module has a ``componentBound`` callback it will be
83+invoked after successfully binding the module. This gives the module a
84+chance to initialize any data that depends on component state (which can
85+be obtained through ``.get('component')``).
86+
87+Events
88+======
89+
90+The heart of the component system events can be defined in a number of ways and
91+understanding how to take advantage of the binding features will greatly aid in
92+producing a system which allows for clean, clear, well separated concerns and
93+which in turn supports incremental rendering and data updates.
94+
95+There are three categories of events supported by the component framework. They
96+each have their purpose and share some common syntax around expression in the
97+module declaration, but a module writer must understand them all to properly use
98+the framework.
99+
100+When modules are added three sets of declarative events are bound. This is done
101+by including in the module an events object with the following (each optional)
102+sections::
103+
104+ events = {scene: {},
105+ d3: {}
106+ yui: {}
107+ };
108+
109+Most commonly there are ``scene`` events. Scene events describe YUI style event
110+delegation. This has advantages in that it scales well and these events can be
111+bound once to the top level container object of a component, and will work for
112+a DOM element matching its selector. Scene events are defined in one of two
113+ways: the first is a shorthand, the later is the more complete definition
114+(you'll see this in the other events types as well).
115+
116+::
117+
118+ scene: { selector: 'callback name on module'}
119+
120+also supported is::
121+
122+ scene: {selector: function() {...}}
123+
124+Though the string name of a callback is preferred, as this makes the whole
125+set of events more easily readable. The final form is::
126+
127+ scene: {selector: {callback: 'callbackName'}}
128+
129+This expanded format is common to the other types of event declarations as
130+well as supporting options available to the other types of bindings.
131+
132+Regardless of form selector is a CSS selector, typically either a ``.class`` or
133+an ``#id`` though pseudo-selectors work as well. With scene events these
134+selectors are relative to whatever container was established on initialization
135+of the Component. A concrete example might be::
136+
137+ scene: {'.person': {click: 'personClick'}}
138+
139+Which says that whenever an object in the scene with a ``person`` class is
140+clicked, invoke the ``personClick`` handler. Handlers all have a common signature.
141+To understand the calling convention you must understand a bit about how D3
142+data bindings work. If you're not familiar with that, please read the D3
143+documents related to data binding. The short version is that each DOM element
144+can have data associated with it through D3's sophisticated data binding model.
145+In the YUI world it might be common that rendered DOM elements have D3 bound
146+data coming from a YUI App.Model. Knowing this we can understand the calling
147+convention::
148+
149+ callback(D3Data, component)
150+ Where 'this' is the DOM element that triggered the selection
151+ Any return is ignored.
152+
153+In the near future scene events will support an additional context attribute in
154+their handler definition which can either be ``component`` or ``module`` and will
155+default to module.
156+
157+.. note::
158+
159+ At the time of this writing this is currently component and doesn't support
160+ context selection. This is addressed in a branch and when landed this note
161+ can be removed. It's worth noting now as the default will change.
162+
163+The second type of event are D3 specific bindings. While declared in a style
164+similar to scene events, D3 events are bound after the modules render method is
165+triggered, as DOM elements must be present to be bound. There are very few cases
166+to prefer this style of event binding over normal scene events; however, there
167+are legitimate uses. If the event is a D3 synthetic event such as zoom or drag,
168+using D3 event bindings make sense as these cannot be delegated to using scene
169+events. The second case we are aware of at the time of this writing is that
170+certain mouse events are dealt with more easily using D3 events, as D3 uses a
171+well documented system of x, y position coordinates which the mouse events map
172+cleanly. This is a possible area for future expansion both in terms of cleaner
173+mouse handling and creating a possible mapping of D3 synthetics to YUI custom
174+events. An example of D3 events follows::
175+
176+ d3: {dragstart: 'beginDrag',
177+ drag: 'redrawConnectors',
178+ dragend: 'savePosition'}
179+
180+The calling convention is as above::
181+
182+ callback(D3Data, component)
183+ 'this' is the DOMElement triggering the event.
184+ Return value is ignored.
185+
186+The final type of event is called ``yui`` events. This classification doesn't
187+depend on DOM selection or delegation, and is designed to provide simple
188+handling; its use case is YUI custom events. A common pattern for
189+usage might be to emit events of interest (or possible interest) from one
190+module and listen for those events in another. By subscribing to custom events
191+across modules, it's reasonably easy to extend functionality with only a loose
192+coupling of the modules themselves (through event names only as an example).
193+
194+YUI events are defined similarly to the others but differ in some key ways.
195+First, they don't depend on a DOM selector, they depend on a YUI styled event
196+name (prefixed or otherwise). Secondly, they support a traditional YUI notion
197+of event phases: ``before``, ``on`` and ``after``. For additional details on how those
198+work, refer to the YUI event docs.
199+
200+::
201+
202+ yui: {'cancelAction': {callback: 'closeMenu',
203+ phase: 'before',
204+ context: 'module'
205+ }
206+ }
207+
208+In this example another module might fire a ``cancelAction`` event; our module
209+wants to respond to this by closing its menu before the triggering event is
210+handled, and the context (this) of the callback should be this module.
211+
212+Context can either be ``component`` or ``module``, with module being the default
213+``this`` for handlers. Phase can be ``before``, ``on``, or ``after``, with ``on`` being
214+the default.
215+
216+Complete Example
217+================
218+
219+While the frameworks tests show off these features, here is a complete example of
220+a module with some description.
221+
222+::
223+
224+ TestModule = Y.Base.create('TestModule', Module, [], {
225+ events: {
226+ scene: { '.thing': {click: 'decorateThing'}},
227+ d3: {drag: 'dragObject'},
228+ yui: { cancel: 'cancelHandler'}
229+ },
230+
231+ decorateThing: function(data, context) {
232+ // this is a DOM .thing element that was clicked
233+ // data is D3 bound data, context will be the module.
234+ },
235+
236+ dragObject: function(data, context) {
237+ // this is a DOM element that had the D3.behavior.drag applied
238+ // and was then dragged with a mouse event.
239+ // data is D3 bound data, context will be the module.
240+ },
241+
242+ cancelHandler: function(evt) {
243+ // this is the module
244+ // evt is the YUI event object
245+ }
246+ });
247
248=== modified file 'docs/index.rst'
249--- docs/index.rst 2012-11-01 10:56:56 +0000
250+++ docs/index.rst 2012-11-28 13:27:24 +0000
251@@ -3,6 +3,7 @@
252 You can adapt this file completely to your liking, but it should at least
253 contain the root `toctree` directive.
254
255+======================
256 Juju GUI documentation
257 ======================
258
259@@ -14,6 +15,7 @@
260 readme
261 style-guide
262 architecture
263+ d3-component-framework
264 process
265
266 Indices and tables

Subscribers

People subscribed via source and target branches