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

Subscribers

People subscribed via source and target branches