Merge lp:~bcsaller/juju-gui/framework-docs into lp:juju-gui/experimental
- framework-docs
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju GUI Hackers | Pending | ||
Review via email: mp+136578@code.launchpad.net |
Commit message
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.
Benjamin Saller (bcsaller) wrote : | # |
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 .
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.
- 261. By Benjamin Saller
-
merge Nicola's doc changes, thanks
Benjamin Saller (bcsaller) wrote : | # |
Please take a look.
Gary Poster (gary) wrote : | # |
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:/
File docs/d3-
https:/
docs/d3-
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:/
docs/d3-
will be made available in the modules runtime.
Modules' run times or module's run time.
https:/
docs/d3-
method automatically have a reference to
"Added by the" or "added via the"
https:/
docs/d3-
call options which will default to an empty
…the addModule call result in an attribute called 'options,' which…
https:/
docs/d3-
component and using the MyModule constructor
…and then, using the MyModule constructor, create…
https:/
docs/d3-
drawing the scene described by any data the
I found this sentence hard to parse. "…which draws…" maybe?
https:/
docs/d3-
called on on the modules each modules
…on the modules, each module's…
https:/
docs/d3-
In terms of the framework itself, I wonder if the first render should
not call the normal render behavior. In other words,...
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.
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.
Benjamin Saller (bcsaller) wrote : | # |
https:/
File docs/d3-
https:/
docs/d3-
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).
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:/
Preview Diff
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 |
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: component- framework. rst
A [revision details]
A docs/d3-