rubyvis 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +13 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +37 -0
- data/History.txt +6 -0
- data/LICENSE.txt +23 -0
- data/{README.txt → README.md} +15 -12
- data/Rakefile +4 -11
- data/lib/rubyvis.rb +1 -1
- data/lib/rubyvis/scale/quantitative.rb +14 -18
- data/lib/rubyvis/scene/svg_label.rb +1 -1
- data/rubyvis.gemspec +21 -0
- data/spec/anchor_spec.rb +2 -1
- data/spec/line_spec.rb +2 -2
- data/spec/scale_linear_datetime_spec.rb +23 -8
- data/spec/spec_helper.rb +2 -1
- metadata +31 -214
- data/.gemtest +0 -0
- data/vendor/protovis/protovis-r3.3.js +0 -287
- data/vendor/protovis/src/behavior/Behavior.js +0 -32
- data/vendor/protovis/src/behavior/Drag.js +0 -112
- data/vendor/protovis/src/behavior/Pan.js +0 -110
- data/vendor/protovis/src/behavior/Point.js +0 -157
- data/vendor/protovis/src/behavior/Resize.js +0 -104
- data/vendor/protovis/src/behavior/Select.js +0 -100
- data/vendor/protovis/src/behavior/Zoom.js +0 -85
- data/vendor/protovis/src/color/Color.js +0 -598
- data/vendor/protovis/src/color/Colors.js +0 -135
- data/vendor/protovis/src/color/Ramp.js +0 -17
- data/vendor/protovis/src/data/Arrays.js +0 -277
- data/vendor/protovis/src/data/Dom.js +0 -380
- data/vendor/protovis/src/data/Flatten.js +0 -146
- data/vendor/protovis/src/data/Histogram.js +0 -120
- data/vendor/protovis/src/data/LinearScale.js +0 -54
- data/vendor/protovis/src/data/LogScale.js +0 -142
- data/vendor/protovis/src/data/Nest.js +0 -257
- data/vendor/protovis/src/data/Numbers.js +0 -313
- data/vendor/protovis/src/data/Objects.js +0 -78
- data/vendor/protovis/src/data/OrdinalScale.js +0 -267
- data/vendor/protovis/src/data/QuantileScale.js +0 -180
- data/vendor/protovis/src/data/QuantitativeScale.js +0 -440
- data/vendor/protovis/src/data/RootScale.js +0 -55
- data/vendor/protovis/src/data/Scale.js +0 -86
- data/vendor/protovis/src/data/Transform.js +0 -109
- data/vendor/protovis/src/data/Tree.js +0 -124
- data/vendor/protovis/src/data/Vector.js +0 -118
- data/vendor/protovis/src/geo/Geo.js +0 -5
- data/vendor/protovis/src/geo/GeoScale.js +0 -307
- data/vendor/protovis/src/geo/LatLng.js +0 -23
- data/vendor/protovis/src/geo/Projection.js +0 -43
- data/vendor/protovis/src/geo/Projections.js +0 -117
- data/vendor/protovis/src/lang/Array.js +0 -112
- data/vendor/protovis/src/lang/init.js +0 -26
- data/vendor/protovis/src/layout/Arc.js +0 -178
- data/vendor/protovis/src/layout/Bullet.js +0 -164
- data/vendor/protovis/src/layout/Cluster.js +0 -205
- data/vendor/protovis/src/layout/Force.js +0 -309
- data/vendor/protovis/src/layout/Grid.js +0 -119
- data/vendor/protovis/src/layout/Hierarchy.js +0 -249
- data/vendor/protovis/src/layout/Horizon.js +0 -159
- data/vendor/protovis/src/layout/Indent.js +0 -83
- data/vendor/protovis/src/layout/Layout.js +0 -56
- data/vendor/protovis/src/layout/Matrix.js +0 -177
- data/vendor/protovis/src/layout/Network.js +0 -302
- data/vendor/protovis/src/layout/Pack.js +0 -323
- data/vendor/protovis/src/layout/Partition.js +0 -203
- data/vendor/protovis/src/layout/Rollup.js +0 -203
- data/vendor/protovis/src/layout/Stack.js +0 -391
- data/vendor/protovis/src/layout/Tree.js +0 -282
- data/vendor/protovis/src/layout/Treemap.js +0 -347
- data/vendor/protovis/src/mark/Anchor.js +0 -81
- data/vendor/protovis/src/mark/Area.js +0 -268
- data/vendor/protovis/src/mark/Bar.js +0 -93
- data/vendor/protovis/src/mark/Dot.js +0 -212
- data/vendor/protovis/src/mark/Ease.js +0 -150
- data/vendor/protovis/src/mark/Image.js +0 -154
- data/vendor/protovis/src/mark/Label.js +0 -155
- data/vendor/protovis/src/mark/Line.js +0 -195
- data/vendor/protovis/src/mark/Mark.js +0 -1237
- data/vendor/protovis/src/mark/Panel.js +0 -273
- data/vendor/protovis/src/mark/Rule.js +0 -143
- data/vendor/protovis/src/mark/Transient.js +0 -7
- data/vendor/protovis/src/mark/Transition.js +0 -195
- data/vendor/protovis/src/mark/Wedge.js +0 -244
- data/vendor/protovis/src/physics/BoundConstraint.js +0 -75
- data/vendor/protovis/src/physics/ChargeForce.js +0 -184
- data/vendor/protovis/src/physics/CollisionConstraint.js +0 -113
- data/vendor/protovis/src/physics/Constraint.js +0 -26
- data/vendor/protovis/src/physics/DragForce.js +0 -49
- data/vendor/protovis/src/physics/Force.js +0 -25
- data/vendor/protovis/src/physics/Particle.js +0 -81
- data/vendor/protovis/src/physics/PositionConstraint.js +0 -72
- data/vendor/protovis/src/physics/Quadtree.js +0 -195
- data/vendor/protovis/src/physics/Simulation.js +0 -159
- data/vendor/protovis/src/physics/SpringForce.js +0 -141
- data/vendor/protovis/src/pv-internals.js +0 -154
- data/vendor/protovis/src/pv.js +0 -95
- data/vendor/protovis/src/scene/SvgArea.js +0 -172
- data/vendor/protovis/src/scene/SvgBar.js +0 -28
- data/vendor/protovis/src/scene/SvgCurve.js +0 -354
- data/vendor/protovis/src/scene/SvgDot.js +0 -81
- data/vendor/protovis/src/scene/SvgImage.js +0 -45
- data/vendor/protovis/src/scene/SvgLabel.js +0 -46
- data/vendor/protovis/src/scene/SvgLine.js +0 -159
- data/vendor/protovis/src/scene/SvgPanel.js +0 -126
- data/vendor/protovis/src/scene/SvgRule.js +0 -26
- data/vendor/protovis/src/scene/SvgScene.js +0 -185
- data/vendor/protovis/src/scene/SvgWedge.js +0 -66
- data/vendor/protovis/src/text/DateFormat.js +0 -262
- data/vendor/protovis/src/text/Format.js +0 -78
- data/vendor/protovis/src/text/NumberFormat.js +0 -227
- data/vendor/protovis/src/text/TimeFormat.js +0 -115
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Constructs a new line mark with default properties. Lines are not typically
|
|
3
|
-
* constructed directly, but by adding to a panel or an existing mark via
|
|
4
|
-
* {@link pv.Mark#add}.
|
|
5
|
-
*
|
|
6
|
-
* @class Represents a series of connected line segments, or <i>polyline</i>,
|
|
7
|
-
* that can be stroked with a configurable color and thickness. Each
|
|
8
|
-
* articulation point in the line corresponds to a datum; for <i>n</i> points,
|
|
9
|
-
* <i>n</i>-1 connected line segments are drawn. The point is positioned using
|
|
10
|
-
* the box model. Arbitrary paths are also possible, allowing radar plots and
|
|
11
|
-
* other custom visualizations.
|
|
12
|
-
*
|
|
13
|
-
* <p>Like areas, lines can be stroked and filled with arbitrary colors. In most
|
|
14
|
-
* cases, lines are only stroked, but the fill style can be used to construct
|
|
15
|
-
* arbitrary polygons.
|
|
16
|
-
*
|
|
17
|
-
* <p>See also the <a href="../../api/Line.html">Line guide</a>.
|
|
18
|
-
*
|
|
19
|
-
* @extends pv.Mark
|
|
20
|
-
*/
|
|
21
|
-
pv.Line = function() {
|
|
22
|
-
pv.Mark.call(this);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
pv.Line.prototype = pv.extend(pv.Mark)
|
|
26
|
-
.property("lineWidth", Number)
|
|
27
|
-
.property("lineJoin", String)
|
|
28
|
-
.property("strokeStyle", pv.color)
|
|
29
|
-
.property("fillStyle", pv.color)
|
|
30
|
-
.property("segmented", Boolean)
|
|
31
|
-
.property("interpolate", String)
|
|
32
|
-
.property("eccentricity", Number)
|
|
33
|
-
.property("tension", Number);
|
|
34
|
-
|
|
35
|
-
pv.Line.prototype.type = "line";
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The width of stroked lines, in pixels; used in conjunction with
|
|
39
|
-
* <tt>strokeStyle</tt> to stroke the line.
|
|
40
|
-
*
|
|
41
|
-
* @type number
|
|
42
|
-
* @name pv.Line.prototype.lineWidth
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
|
|
47
|
-
* stroke the line. The default value of this property is a categorical color.
|
|
48
|
-
*
|
|
49
|
-
* @type string
|
|
50
|
-
* @name pv.Line.prototype.strokeStyle
|
|
51
|
-
* @see pv.color
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* The type of corners where two lines meet. Accepted values are "bevel",
|
|
56
|
-
* "round" and "miter". The default value is "miter".
|
|
57
|
-
*
|
|
58
|
-
* <p>For segmented lines, only "miter" joins and "linear" interpolation are
|
|
59
|
-
* currently supported. Any other value, including null, will disable joins,
|
|
60
|
-
* producing disjoint line segments. Note that the miter joins must be computed
|
|
61
|
-
* manually (at least in the current SVG renderer); since this calculation may
|
|
62
|
-
* be expensive and unnecessary for small lines, specifying null can improve
|
|
63
|
-
* performance significantly.
|
|
64
|
-
*
|
|
65
|
-
* <p>This property is <i>fixed</i>. See {@link pv.Mark}.
|
|
66
|
-
*
|
|
67
|
-
* @type string
|
|
68
|
-
* @name pv.Line.prototype.lineJoin
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* The line fill style; if non-null, the interior of the line is closed and
|
|
73
|
-
* filled with the specified color. The default value of this property is a
|
|
74
|
-
* null, meaning that lines are not filled by default.
|
|
75
|
-
*
|
|
76
|
-
* <p>This property is <i>fixed</i>. See {@link pv.Mark}.
|
|
77
|
-
*
|
|
78
|
-
* @type string
|
|
79
|
-
* @name pv.Line.prototype.fillStyle
|
|
80
|
-
* @see pv.color
|
|
81
|
-
*/
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Whether the line is segmented; whether variations in stroke style, line width
|
|
85
|
-
* and the other properties are treated as fixed. Rendering segmented lines is
|
|
86
|
-
* noticeably slower than non-segmented lines.
|
|
87
|
-
*
|
|
88
|
-
* <p>This property is <i>fixed</i>. See {@link pv.Mark}.
|
|
89
|
-
*
|
|
90
|
-
* @type boolean
|
|
91
|
-
* @name pv.Line.prototype.segmented
|
|
92
|
-
*/
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* How to interpolate between values. Linear interpolation ("linear") is the
|
|
96
|
-
* default, producing a straight line between points. For piecewise constant
|
|
97
|
-
* functions (i.e., step functions), either "step-before" or "step-after" can be
|
|
98
|
-
* specified. To draw a clockwise circular arc between points, specify "polar";
|
|
99
|
-
* to draw a counterclockwise circular arc between points, specify
|
|
100
|
-
* "polar-reverse". To draw open uniform b-splines, specify "basis". To draw
|
|
101
|
-
* cardinal splines, specify "cardinal"; see also {@link #tension}.
|
|
102
|
-
*
|
|
103
|
-
* <p>This property is <i>fixed</i>. See {@link pv.Mark}.
|
|
104
|
-
*
|
|
105
|
-
* @type string
|
|
106
|
-
* @name pv.Line.prototype.interpolate
|
|
107
|
-
*/
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* The eccentricity of polar line segments; used in conjunction with
|
|
111
|
-
* interpolate("polar"). The default value of 0 means that line segments are
|
|
112
|
-
* drawn as circular arcs. A value of 1 draws a straight line. A value between 0
|
|
113
|
-
* and 1 draws an elliptical arc with the given eccentricity.
|
|
114
|
-
*
|
|
115
|
-
* @type number
|
|
116
|
-
* @name pv.Line.prototype.eccentricity
|
|
117
|
-
*/
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* The tension of cardinal splines; used in conjunction with
|
|
121
|
-
* interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
|
|
122
|
-
* the given tension. In some sense, the tension can be interpreted as the
|
|
123
|
-
* "length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
|
|
124
|
-
* linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
|
|
125
|
-
* default value is 0.7.
|
|
126
|
-
*
|
|
127
|
-
* <p>This property is <i>fixed</i>. See {@link pv.Mark}.
|
|
128
|
-
*
|
|
129
|
-
* @type number
|
|
130
|
-
* @name pv.Line.prototype.tension
|
|
131
|
-
*/
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Default properties for lines. By default, there is no fill and the stroke
|
|
135
|
-
* style is a categorical color. The default interpolation is linear.
|
|
136
|
-
*
|
|
137
|
-
* @type pv.Line
|
|
138
|
-
*/
|
|
139
|
-
pv.Line.prototype.defaults = new pv.Line()
|
|
140
|
-
.extend(pv.Mark.prototype.defaults)
|
|
141
|
-
.lineJoin("miter")
|
|
142
|
-
.lineWidth(1.5)
|
|
143
|
-
.strokeStyle(pv.Colors.category10().by(pv.parent))
|
|
144
|
-
.interpolate("linear")
|
|
145
|
-
.eccentricity(0)
|
|
146
|
-
.tension(.7);
|
|
147
|
-
|
|
148
|
-
/** @private Reuse Area's implementation for segmented bind & build. */
|
|
149
|
-
pv.Line.prototype.bind = pv.Area.prototype.bind;
|
|
150
|
-
pv.Line.prototype.buildInstance = pv.Area.prototype.buildInstance;
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Constructs a new line anchor with default properties. Lines support five
|
|
154
|
-
* different anchors:<ul>
|
|
155
|
-
*
|
|
156
|
-
* <li>top
|
|
157
|
-
* <li>left
|
|
158
|
-
* <li>center
|
|
159
|
-
* <li>bottom
|
|
160
|
-
* <li>right
|
|
161
|
-
*
|
|
162
|
-
* </ul>In addition to positioning properties (left, right, top bottom), the
|
|
163
|
-
* anchors support text rendering properties (text-align, text-baseline). Text is
|
|
164
|
-
* rendered to appear outside the line. Note that this behavior is different
|
|
165
|
-
* from other mark anchors, which default to rendering text <i>inside</i> the
|
|
166
|
-
* mark.
|
|
167
|
-
*
|
|
168
|
-
* <p>For consistency with the other mark types, the anchor positions are
|
|
169
|
-
* defined in terms of their opposite edge. For example, the top anchor defines
|
|
170
|
-
* the bottom property, such that a bar added to the top anchor grows upward.
|
|
171
|
-
*
|
|
172
|
-
* @param {string} name the anchor name; either a string or a property function.
|
|
173
|
-
* @returns {pv.Anchor}
|
|
174
|
-
*/
|
|
175
|
-
pv.Line.prototype.anchor = function(name) {
|
|
176
|
-
return pv.Area.prototype.anchor.call(this, name)
|
|
177
|
-
.textAlign(function(d) {
|
|
178
|
-
switch (this.name()) {
|
|
179
|
-
case "left": return "right";
|
|
180
|
-
case "bottom":
|
|
181
|
-
case "top":
|
|
182
|
-
case "center": return "center";
|
|
183
|
-
case "right": return "left";
|
|
184
|
-
}
|
|
185
|
-
})
|
|
186
|
-
.textBaseline(function(d) {
|
|
187
|
-
switch (this.name()) {
|
|
188
|
-
case "right":
|
|
189
|
-
case "left":
|
|
190
|
-
case "center": return "middle";
|
|
191
|
-
case "top": return "bottom";
|
|
192
|
-
case "bottom": return "top";
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
};
|
|
@@ -1,1237 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Constructs a new mark with default properties. Marks, with the exception of
|
|
3
|
-
* the root panel, are not typically constructed directly; instead, they are
|
|
4
|
-
* added to a panel or an existing mark via {@link pv.Mark#add}.
|
|
5
|
-
*
|
|
6
|
-
* @class Represents a data-driven graphical mark. The <tt>Mark</tt> class is
|
|
7
|
-
* the base class for all graphical marks in Protovis; it does not provide any
|
|
8
|
-
* specific rendering functionality, but together with {@link Panel} establishes
|
|
9
|
-
* the core framework.
|
|
10
|
-
*
|
|
11
|
-
* <p>Concrete mark types include familiar visual elements such as bars, lines
|
|
12
|
-
* and labels. Although a bar mark may be used to construct a bar chart, marks
|
|
13
|
-
* know nothing about charts; it is only through their specification and
|
|
14
|
-
* composition that charts are produced. These building blocks permit many
|
|
15
|
-
* combinatorial possibilities.
|
|
16
|
-
*
|
|
17
|
-
* <p>Marks are associated with <b>data</b>: a mark is generated once per
|
|
18
|
-
* associated datum, mapping the datum to visual <b>properties</b> such as
|
|
19
|
-
* position and color. Thus, a single mark specification represents a set of
|
|
20
|
-
* visual elements that share the same data and visual encoding. The type of
|
|
21
|
-
* mark defines the names of properties and their meaning. A property may be
|
|
22
|
-
* static, ignoring the associated datum and returning a constant; or, it may be
|
|
23
|
-
* dynamic, derived from the associated datum or index. Such dynamic encodings
|
|
24
|
-
* can be specified succinctly using anonymous functions. Special properties
|
|
25
|
-
* called event handlers can be registered to add interactivity.
|
|
26
|
-
*
|
|
27
|
-
* <p>Protovis uses <b>inheritance</b> to simplify the specification of related
|
|
28
|
-
* marks: a new mark can be derived from an existing mark, inheriting its
|
|
29
|
-
* properties. The new mark can then override properties to specify new
|
|
30
|
-
* behavior, potentially in terms of the old behavior. In this way, the old mark
|
|
31
|
-
* serves as the <b>prototype</b> for the new mark. Most mark types share the
|
|
32
|
-
* same basic properties for consistency and to facilitate inheritance.
|
|
33
|
-
*
|
|
34
|
-
* <p>The prioritization of redundant properties is as follows:<ol>
|
|
35
|
-
*
|
|
36
|
-
* <li>If the <tt>width</tt> property is not specified (i.e., null), its value
|
|
37
|
-
* is the width of the parent panel, minus this mark's left and right margins;
|
|
38
|
-
* the left and right margins are zero if not specified.
|
|
39
|
-
*
|
|
40
|
-
* <li>Otherwise, if the <tt>right</tt> margin is not specified, its value is
|
|
41
|
-
* the width of the parent panel, minus this mark's width and left margin; the
|
|
42
|
-
* left margin is zero if not specified.
|
|
43
|
-
*
|
|
44
|
-
* <li>Otherwise, if the <tt>left</tt> property is not specified, its value is
|
|
45
|
-
* the width of the parent panel, minus this mark's width and the right margin.
|
|
46
|
-
*
|
|
47
|
-
* </ol>This prioritization is then duplicated for the <tt>height</tt>,
|
|
48
|
-
* <tt>bottom</tt> and <tt>top</tt> properties, respectively.
|
|
49
|
-
*
|
|
50
|
-
* <p>While most properties are <i>variable</i>, some mark types, such as lines
|
|
51
|
-
* and areas, generate a single visual element rather than a distinct visual
|
|
52
|
-
* element per datum. With these marks, some properties may be <b>fixed</b>.
|
|
53
|
-
* Fixed properties can vary per mark, but not <i>per datum</i>! These
|
|
54
|
-
* properties are evaluated solely for the first (0-index) datum, and typically
|
|
55
|
-
* are specified as a constant. However, it is valid to use a function if the
|
|
56
|
-
* property varies between panels or is dynamically generated.
|
|
57
|
-
*
|
|
58
|
-
* <p>See also the <a href="../../api/">Protovis guide</a>.
|
|
59
|
-
*/
|
|
60
|
-
pv.Mark = function() {
|
|
61
|
-
/*
|
|
62
|
-
* TYPE 0 constant defs
|
|
63
|
-
* TYPE 1 function defs
|
|
64
|
-
* TYPE 2 constant properties
|
|
65
|
-
* TYPE 3 function properties
|
|
66
|
-
* in order of evaluation!
|
|
67
|
-
*/
|
|
68
|
-
this.$properties = [];
|
|
69
|
-
this.$handlers = {};
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
/** @private Records which properties are defined on this mark type. */
|
|
73
|
-
pv.Mark.prototype.properties = {};
|
|
74
|
-
|
|
75
|
-
/** @private Records the cast function for each property. */
|
|
76
|
-
pv.Mark.cast = {};
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @private Defines and registers a property method for the property with the
|
|
80
|
-
* given name. This method should be called on a mark class prototype to define
|
|
81
|
-
* each exposed property. (Note this refers to the JavaScript
|
|
82
|
-
* <tt>prototype</tt>, not the Protovis mark prototype, which is the {@link
|
|
83
|
-
* #proto} field.)
|
|
84
|
-
*
|
|
85
|
-
* <p>The created property method supports several modes of invocation: <ol>
|
|
86
|
-
*
|
|
87
|
-
* <li>If invoked with a <tt>Function</tt> argument, this function is evaluated
|
|
88
|
-
* for each associated datum. The return value of the function is used as the
|
|
89
|
-
* computed property value. The context of the function (<tt>this</tt>) is this
|
|
90
|
-
* mark. The arguments to the function are the associated data of this mark and
|
|
91
|
-
* any enclosing panels. For example, a linear encoding of numerical data to
|
|
92
|
-
* height is specified as
|
|
93
|
-
*
|
|
94
|
-
* <pre>m.height(function(d) d * 100);</pre>
|
|
95
|
-
*
|
|
96
|
-
* The expression <tt>d * 100</tt> will be evaluated for the height property of
|
|
97
|
-
* each mark instance. The return value of the property method (e.g.,
|
|
98
|
-
* <tt>m.height</tt>) is this mark (<tt>m</tt>)).<p>
|
|
99
|
-
*
|
|
100
|
-
* <li>If invoked with a non-function argument, the property is treated as a
|
|
101
|
-
* constant. The return value of the property method (e.g., <tt>m.height</tt>)
|
|
102
|
-
* is this mark.<p>
|
|
103
|
-
*
|
|
104
|
-
* <li>If invoked with no arguments, the computed property value for the current
|
|
105
|
-
* mark instance in the scene graph is returned. This facilitates <i>property
|
|
106
|
-
* chaining</i>, where one mark's properties are defined in terms of another's.
|
|
107
|
-
* For example, to offset a mark's location from its prototype, you might say
|
|
108
|
-
*
|
|
109
|
-
* <pre>m.top(function() this.proto.top() + 10);</pre>
|
|
110
|
-
*
|
|
111
|
-
* Note that the index of the mark being evaluated (in the above example,
|
|
112
|
-
* <tt>this.proto</tt>) is inherited from the <tt>Mark</tt> class and set by
|
|
113
|
-
* this mark. So, if the fifth element's top property is being evaluated, the
|
|
114
|
-
* fifth instance of <tt>this.proto</tt> will similarly be queried for the value
|
|
115
|
-
* of its top property. If the mark being evaluated has a different number of
|
|
116
|
-
* instances, or its data is unrelated, the behavior of this method is
|
|
117
|
-
* undefined. In these cases it may be better to index the <tt>scene</tt>
|
|
118
|
-
* explicitly to specify the exact instance.
|
|
119
|
-
*
|
|
120
|
-
* </ol><p>Property names should follow standard JavaScript method naming
|
|
121
|
-
* conventions, using lowerCamel-style capitalization.
|
|
122
|
-
*
|
|
123
|
-
* <p>In addition to creating the property method, every property is registered
|
|
124
|
-
* in the {@link #properties} map on the <tt>prototype</tt>. Although this is an
|
|
125
|
-
* instance field, it is considered immutable and shared by all instances of a
|
|
126
|
-
* given mark type. The <tt>properties</tt> map can be queried to see if a mark
|
|
127
|
-
* type defines a particular property, such as width or height.
|
|
128
|
-
*
|
|
129
|
-
* @param {string} name the property name.
|
|
130
|
-
* @param {function} [cast] the cast function for this property.
|
|
131
|
-
*/
|
|
132
|
-
pv.Mark.prototype.property = function(name, cast) {
|
|
133
|
-
if (!this.hasOwnProperty("properties")) {
|
|
134
|
-
this.properties = pv.extend(this.properties);
|
|
135
|
-
}
|
|
136
|
-
this.properties[name] = true;
|
|
137
|
-
|
|
138
|
-
/*
|
|
139
|
-
* Define the setter-getter globally, since the default behavior should be the
|
|
140
|
-
* same for all properties, and since the Protovis inheritance chain is
|
|
141
|
-
* independent of the JavaScript inheritance chain. For example, anchors
|
|
142
|
-
* define a "name" property that is evaluated on derived marks, even though
|
|
143
|
-
* those marks don't normally have a name.
|
|
144
|
-
*/
|
|
145
|
-
pv.Mark.prototype.propertyMethod(name, false, pv.Mark.cast[name] = cast);
|
|
146
|
-
return this;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* @private Defines a setter-getter for the specified property.
|
|
151
|
-
*
|
|
152
|
-
* <p>If a cast function has been assigned to the specified property name, the
|
|
153
|
-
* property function is wrapped by the cast function, or, if a constant is
|
|
154
|
-
* specified, the constant is immediately cast. Note, however, that if the
|
|
155
|
-
* property value is null, the cast function is not invoked.
|
|
156
|
-
*
|
|
157
|
-
* @param {string} name the property name.
|
|
158
|
-
* @param {boolean} [def] whether is a property or a def.
|
|
159
|
-
* @param {function} [cast] the cast function for this property.
|
|
160
|
-
*/
|
|
161
|
-
pv.Mark.prototype.propertyMethod = function(name, def, cast) {
|
|
162
|
-
if (!cast) cast = pv.Mark.cast[name];
|
|
163
|
-
this[name] = function(v) {
|
|
164
|
-
|
|
165
|
-
/* If this is a def, use it rather than property. */
|
|
166
|
-
if (def && this.scene) {
|
|
167
|
-
var defs = this.scene.defs;
|
|
168
|
-
if (arguments.length) {
|
|
169
|
-
defs[name] = {
|
|
170
|
-
id: (v == null) ? 0 : pv.id(),
|
|
171
|
-
value: ((v != null) && cast) ? cast(v) : v
|
|
172
|
-
};
|
|
173
|
-
return this;
|
|
174
|
-
}
|
|
175
|
-
return defs[name] ? defs[name].value : null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/* If arguments are specified, set the property value. */
|
|
179
|
-
if (arguments.length) {
|
|
180
|
-
var type = !def << 1 | (typeof v == "function");
|
|
181
|
-
this.propertyValue(name, (type & 1 && cast) ? function() {
|
|
182
|
-
var x = v.apply(this, arguments);
|
|
183
|
-
return (x != null) ? cast(x) : null;
|
|
184
|
-
} : (((v != null) && cast) ? cast(v) : v)).type = type;
|
|
185
|
-
return this;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return this.instance()[name];
|
|
189
|
-
};
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
/** @private Sets the value of the property <i>name</i> to <i>v</i>. */
|
|
193
|
-
pv.Mark.prototype.propertyValue = function(name, v) {
|
|
194
|
-
var properties = this.$properties, p = {name: name, id: pv.id(), value: v};
|
|
195
|
-
for (var i = 0; i < properties.length; i++) {
|
|
196
|
-
if (properties[i].name == name) {
|
|
197
|
-
properties.splice(i, 1);
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
properties.push(p);
|
|
202
|
-
return p;
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
/* Define all global properties. */
|
|
206
|
-
pv.Mark.prototype
|
|
207
|
-
.property("data")
|
|
208
|
-
.property("visible", Boolean)
|
|
209
|
-
.property("left", Number)
|
|
210
|
-
.property("right", Number)
|
|
211
|
-
.property("top", Number)
|
|
212
|
-
.property("bottom", Number)
|
|
213
|
-
.property("cursor", String)
|
|
214
|
-
.property("title", String)
|
|
215
|
-
.property("reverse", Boolean)
|
|
216
|
-
.property("antialias", Boolean)
|
|
217
|
-
.property("events", String)
|
|
218
|
-
.property("id", String);
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* The mark type; a lower camelCase name. The type name controls rendering
|
|
222
|
-
* behavior, and unless the rendering engine is extended, must be one of the
|
|
223
|
-
* built-in concrete mark types: area, bar, dot, image, label, line, panel,
|
|
224
|
-
* rule, or wedge.
|
|
225
|
-
*
|
|
226
|
-
* @type string
|
|
227
|
-
* @name pv.Mark.prototype.type
|
|
228
|
-
*/
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* The mark prototype, possibly undefined, from which to inherit property
|
|
232
|
-
* functions. The mark prototype is not necessarily of the same type as this
|
|
233
|
-
* mark. Any properties defined on this mark will override properties inherited
|
|
234
|
-
* either from the prototype or from the type-specific defaults.
|
|
235
|
-
*
|
|
236
|
-
* @type pv.Mark
|
|
237
|
-
* @name pv.Mark.prototype.proto
|
|
238
|
-
*/
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* The mark anchor target, possibly undefined.
|
|
242
|
-
*
|
|
243
|
-
* @type pv.Mark
|
|
244
|
-
* @name pv.Mark.prototype.target
|
|
245
|
-
*/
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* The enclosing parent panel. The parent panel is generally undefined only for
|
|
249
|
-
* the root panel; however, it is possible to create "offscreen" marks that are
|
|
250
|
-
* used only for inheritance purposes.
|
|
251
|
-
*
|
|
252
|
-
* @type pv.Panel
|
|
253
|
-
* @name pv.Mark.prototype.parent
|
|
254
|
-
*/
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* The child index. -1 if the enclosing parent panel is null; otherwise, the
|
|
258
|
-
* zero-based index of this mark into the parent panel's <tt>children</tt> array.
|
|
259
|
-
*
|
|
260
|
-
* @type number
|
|
261
|
-
*/
|
|
262
|
-
pv.Mark.prototype.childIndex = -1;
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* The mark index. The value of this field depends on which instance (i.e.,
|
|
266
|
-
* which element of the data array) is currently being evaluated. During the
|
|
267
|
-
* build phase, the index is incremented over each datum; when handling events,
|
|
268
|
-
* the index is set to the instance that triggered the event.
|
|
269
|
-
*
|
|
270
|
-
* @type number
|
|
271
|
-
*/
|
|
272
|
-
pv.Mark.prototype.index = -1;
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* The current scale factor, based on any enclosing transforms. The current
|
|
276
|
-
* scale can be used to create scale-independent graphics. For example, to
|
|
277
|
-
* define a dot that has a radius of 10 irrespective of any zooming, say:
|
|
278
|
-
*
|
|
279
|
-
* <pre>dot.shapeRadius(function() 10 / this.scale)</pre>
|
|
280
|
-
*
|
|
281
|
-
* Note that the stroke width and font size are defined irrespective of scale
|
|
282
|
-
* (i.e., in screen space) already. Also note that when a transform is applied
|
|
283
|
-
* to a panel, the scale affects only the child marks, not the panel itself.
|
|
284
|
-
*
|
|
285
|
-
* @type number
|
|
286
|
-
* @see pv.Panel#transform
|
|
287
|
-
*/
|
|
288
|
-
pv.Mark.prototype.scale = 1;
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* @private The scene graph. The scene graph is an array of objects; each object
|
|
292
|
-
* (or "node") corresponds to an instance of this mark and an element in the
|
|
293
|
-
* data array. The scene graph can be traversed to lookup previously-evaluated
|
|
294
|
-
* properties.
|
|
295
|
-
*
|
|
296
|
-
* @name pv.Mark.prototype.scene
|
|
297
|
-
*/
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* The root parent panel. This may be undefined for "offscreen" marks that are
|
|
301
|
-
* created for inheritance purposes only.
|
|
302
|
-
*
|
|
303
|
-
* @type pv.Panel
|
|
304
|
-
* @name pv.Mark.prototype.root
|
|
305
|
-
*/
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* The data property; an array of objects. The size of the array determines the
|
|
309
|
-
* number of marks that will be instantiated; each element in the array will be
|
|
310
|
-
* passed to property functions to compute the property values. Typically, the
|
|
311
|
-
* data property is specified as a constant array, such as
|
|
312
|
-
*
|
|
313
|
-
* <pre>m.data([1, 2, 3, 4, 5]);</pre>
|
|
314
|
-
*
|
|
315
|
-
* However, it is perfectly acceptable to define the data property as a
|
|
316
|
-
* function. This function might compute the data dynamically, allowing
|
|
317
|
-
* different data to be used per enclosing panel. For instance, in the stacked
|
|
318
|
-
* area graph example (see {@link #scene}), the data function on the area mark
|
|
319
|
-
* dereferences each series.
|
|
320
|
-
*
|
|
321
|
-
* @type array
|
|
322
|
-
* @name pv.Mark.prototype.data
|
|
323
|
-
*/
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* The visible property; a boolean determining whether or not the mark instance
|
|
327
|
-
* is visible. If a mark instance is not visible, its other properties will not
|
|
328
|
-
* be evaluated. Similarly, for panels no child marks will be rendered.
|
|
329
|
-
*
|
|
330
|
-
* @type boolean
|
|
331
|
-
* @name pv.Mark.prototype.visible
|
|
332
|
-
*/
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* The left margin; the distance, in pixels, between the left edge of the
|
|
336
|
-
* enclosing panel and the left edge of this mark. Note that in some cases this
|
|
337
|
-
* property may be redundant with the right property, or with the conjunction of
|
|
338
|
-
* right and width.
|
|
339
|
-
*
|
|
340
|
-
* @type number
|
|
341
|
-
* @name pv.Mark.prototype.left
|
|
342
|
-
*/
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* The right margin; the distance, in pixels, between the right edge of the
|
|
346
|
-
* enclosing panel and the right edge of this mark. Note that in some cases this
|
|
347
|
-
* property may be redundant with the left property, or with the conjunction of
|
|
348
|
-
* left and width.
|
|
349
|
-
*
|
|
350
|
-
* @type number
|
|
351
|
-
* @name pv.Mark.prototype.right
|
|
352
|
-
*/
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* The top margin; the distance, in pixels, between the top edge of the
|
|
356
|
-
* enclosing panel and the top edge of this mark. Note that in some cases this
|
|
357
|
-
* property may be redundant with the bottom property, or with the conjunction
|
|
358
|
-
* of bottom and height.
|
|
359
|
-
*
|
|
360
|
-
* @type number
|
|
361
|
-
* @name pv.Mark.prototype.top
|
|
362
|
-
*/
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* The bottom margin; the distance, in pixels, between the bottom edge of the
|
|
366
|
-
* enclosing panel and the bottom edge of this mark. Note that in some cases
|
|
367
|
-
* this property may be redundant with the top property, or with the conjunction
|
|
368
|
-
* of top and height.
|
|
369
|
-
*
|
|
370
|
-
* @type number
|
|
371
|
-
* @name pv.Mark.prototype.bottom
|
|
372
|
-
*/
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* The cursor property; corresponds to the CSS cursor property. This is
|
|
376
|
-
* typically used in conjunction with event handlers to indicate interactivity.
|
|
377
|
-
*
|
|
378
|
-
* @type string
|
|
379
|
-
* @name pv.Mark.prototype.cursor
|
|
380
|
-
* @see <a href="http://www.w3.org/TR/CSS2/ui.html#propdef-cursor">CSS2 cursor</a>
|
|
381
|
-
*/
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* The title property; corresponds to the HTML/SVG title property, allowing the
|
|
385
|
-
* general of simple plain text tooltips.
|
|
386
|
-
*
|
|
387
|
-
* @type string
|
|
388
|
-
* @name pv.Mark.prototype.title
|
|
389
|
-
*/
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* The events property; corresponds to the SVG pointer-events property,
|
|
393
|
-
* specifying how the mark should participate in mouse events. The default value
|
|
394
|
-
* is "painted". Supported values are:
|
|
395
|
-
*
|
|
396
|
-
* <p>"painted": The given mark may receive events when the mouse is over a
|
|
397
|
-
* "painted" area. The painted areas are the interior (i.e., fill) of the mark
|
|
398
|
-
* if a 'fillStyle' is specified, and the perimeter (i.e., stroke) of the mark
|
|
399
|
-
* if a 'strokeStyle' is specified.
|
|
400
|
-
*
|
|
401
|
-
* <p>"all": The given mark may receive events when the mouse is over either the
|
|
402
|
-
* interior (i.e., fill) or the perimeter (i.e., stroke) of the mark, regardless
|
|
403
|
-
* of the specified fillStyle and strokeStyle.
|
|
404
|
-
*
|
|
405
|
-
* <p>"none": The given mark may not receive events.
|
|
406
|
-
*
|
|
407
|
-
* @type string
|
|
408
|
-
* @name pv.Mark.prototype.events
|
|
409
|
-
*/
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* The reverse property; a boolean determining whether marks are ordered from
|
|
413
|
-
* front-to-back or back-to-front. SVG does not support explicit z-ordering;
|
|
414
|
-
* shapes are rendered in the order they appear. Thus, by default, marks are
|
|
415
|
-
* rendered in data order. Setting the reverse property to false reverses the
|
|
416
|
-
* order in which they are rendered; however, the properties are still evaluated
|
|
417
|
-
* (i.e., built) in forward order.
|
|
418
|
-
*
|
|
419
|
-
* @type boolean
|
|
420
|
-
* @name pv.Mark.prototype.reverse
|
|
421
|
-
*/
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* The instance identifier, for correspondence across animated transitions. If
|
|
425
|
-
* no identifier is specified, correspondence is determined using the mark
|
|
426
|
-
* index. Identifiers are not global, but local to a given mark.
|
|
427
|
-
*
|
|
428
|
-
* @type String
|
|
429
|
-
* @name pv.Mark.prototype.id
|
|
430
|
-
*/
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Default properties for all mark types. By default, the data array is the
|
|
434
|
-
* parent data as a single-element array; if the data property is not specified,
|
|
435
|
-
* this causes each mark to be instantiated as a singleton with the parents
|
|
436
|
-
* datum. The visible property is true by default, and the reverse property is
|
|
437
|
-
* false.
|
|
438
|
-
*
|
|
439
|
-
* @type pv.Mark
|
|
440
|
-
*/
|
|
441
|
-
pv.Mark.prototype.defaults = new pv.Mark()
|
|
442
|
-
.data(function(d) { return [d]; })
|
|
443
|
-
.visible(true)
|
|
444
|
-
.antialias(true)
|
|
445
|
-
.events("painted");
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Sets the prototype of this mark to the specified mark. Any properties not
|
|
449
|
-
* defined on this mark may be inherited from the specified prototype mark, or
|
|
450
|
-
* its prototype, and so on. The prototype mark need not be the same type of
|
|
451
|
-
* mark as this mark. (Note that for inheritance to be useful, properties with
|
|
452
|
-
* the same name on different mark types should have equivalent meaning.)
|
|
453
|
-
*
|
|
454
|
-
* @param {pv.Mark} proto the new prototype.
|
|
455
|
-
* @returns {pv.Mark} this mark.
|
|
456
|
-
* @see #add
|
|
457
|
-
*/
|
|
458
|
-
pv.Mark.prototype.extend = function(proto) {
|
|
459
|
-
this.proto = proto;
|
|
460
|
-
this.target = proto.target;
|
|
461
|
-
return this;
|
|
462
|
-
};
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Adds a new mark of the specified type to the enclosing parent panel, whilst
|
|
466
|
-
* simultaneously setting the prototype of the new mark to be this mark.
|
|
467
|
-
*
|
|
468
|
-
* @param {function} type the type of mark to add; a constructor, such as
|
|
469
|
-
* <tt>pv.Bar</tt>.
|
|
470
|
-
* @returns {pv.Mark} the new mark.
|
|
471
|
-
* @see #extend
|
|
472
|
-
*/
|
|
473
|
-
pv.Mark.prototype.add = function(type) {
|
|
474
|
-
return this.parent.add(type).extend(this);
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
/**
|
|
478
|
-
* Defines a custom property on this mark. Custom properties are currently
|
|
479
|
-
* fixed, in that they are initialized once per mark set (i.e., per parent panel
|
|
480
|
-
* instance). Custom properties can be used to store local state for the mark,
|
|
481
|
-
* such as data needed by other properties (e.g., a custom scale) or interaction
|
|
482
|
-
* state.
|
|
483
|
-
*
|
|
484
|
-
* <p>WARNING We plan on changing this feature in a future release to define
|
|
485
|
-
* standard properties, as opposed to <i>fixed</i> properties that behave
|
|
486
|
-
* idiosyncratically within event handlers. Furthermore, we recommend storing
|
|
487
|
-
* state in an external data structure, rather than tying it to the
|
|
488
|
-
* visualization specification as with defs.
|
|
489
|
-
*
|
|
490
|
-
* @param {string} name the name of the local variable.
|
|
491
|
-
* @param {function} [v] an optional initializer; may be a constant or a
|
|
492
|
-
* function.
|
|
493
|
-
*/
|
|
494
|
-
pv.Mark.prototype.def = function(name, v) {
|
|
495
|
-
this.propertyMethod(name, true);
|
|
496
|
-
return this[name](arguments.length > 1 ? v : null);
|
|
497
|
-
};
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Returns an anchor with the specified name. All marks support the five
|
|
501
|
-
* standard anchor names:<ul>
|
|
502
|
-
*
|
|
503
|
-
* <li>top
|
|
504
|
-
* <li>left
|
|
505
|
-
* <li>center
|
|
506
|
-
* <li>bottom
|
|
507
|
-
* <li>right
|
|
508
|
-
*
|
|
509
|
-
* </ul>In addition to positioning properties (left, right, top bottom), the
|
|
510
|
-
* anchors support text rendering properties (text-align, text-baseline). Text is
|
|
511
|
-
* rendered to appear inside the mark by default.
|
|
512
|
-
*
|
|
513
|
-
* <p>To facilitate stacking, anchors are defined in terms of their opposite
|
|
514
|
-
* edge. For example, the top anchor defines the bottom property, such that the
|
|
515
|
-
* mark extends upwards; the bottom anchor instead defines the top property,
|
|
516
|
-
* such that the mark extends downwards. See also {@link pv.Layout.Stack}.
|
|
517
|
-
*
|
|
518
|
-
* <p>While anchor names are typically constants, the anchor name is a true
|
|
519
|
-
* property, which means you can specify a function to compute the anchor name
|
|
520
|
-
* dynamically. See the {@link pv.Anchor#name} property for details.
|
|
521
|
-
*
|
|
522
|
-
* @param {string} name the anchor name; either a string or a property function.
|
|
523
|
-
* @returns {pv.Anchor} the new anchor.
|
|
524
|
-
*/
|
|
525
|
-
pv.Mark.prototype.anchor = function(name) {
|
|
526
|
-
if (!name) name = "center"; // default anchor name
|
|
527
|
-
return new pv.Anchor(this)
|
|
528
|
-
.name(name)
|
|
529
|
-
.data(function() {
|
|
530
|
-
return this.scene.target.map(function(s) { return s.data; });
|
|
531
|
-
})
|
|
532
|
-
.visible(function() {
|
|
533
|
-
return this.scene.target[this.index].visible;
|
|
534
|
-
})
|
|
535
|
-
.id(function() {
|
|
536
|
-
return this.scene.target[this.index].id;
|
|
537
|
-
})
|
|
538
|
-
.left(function() {
|
|
539
|
-
var s = this.scene.target[this.index], w = s.width || 0;
|
|
540
|
-
switch (this.name()) {
|
|
541
|
-
case "bottom":
|
|
542
|
-
case "top":
|
|
543
|
-
case "center": return s.left + w / 2;
|
|
544
|
-
case "left": return null;
|
|
545
|
-
}
|
|
546
|
-
return s.left + w;
|
|
547
|
-
})
|
|
548
|
-
.top(function() {
|
|
549
|
-
var s = this.scene.target[this.index], h = s.height || 0;
|
|
550
|
-
switch (this.name()) {
|
|
551
|
-
case "left":
|
|
552
|
-
case "right":
|
|
553
|
-
case "center": return s.top + h / 2;
|
|
554
|
-
case "top": return null;
|
|
555
|
-
}
|
|
556
|
-
return s.top + h;
|
|
557
|
-
})
|
|
558
|
-
.right(function() {
|
|
559
|
-
var s = this.scene.target[this.index];
|
|
560
|
-
return this.name() == "left" ? s.right + (s.width || 0) : null;
|
|
561
|
-
})
|
|
562
|
-
.bottom(function() {
|
|
563
|
-
var s = this.scene.target[this.index];
|
|
564
|
-
return this.name() == "top" ? s.bottom + (s.height || 0) : null;
|
|
565
|
-
})
|
|
566
|
-
.textAlign(function() {
|
|
567
|
-
switch (this.name()) {
|
|
568
|
-
case "bottom":
|
|
569
|
-
case "top":
|
|
570
|
-
case "center": return "center";
|
|
571
|
-
case "right": return "right";
|
|
572
|
-
}
|
|
573
|
-
return "left";
|
|
574
|
-
})
|
|
575
|
-
.textBaseline(function() {
|
|
576
|
-
switch (this.name()) {
|
|
577
|
-
case "right":
|
|
578
|
-
case "left":
|
|
579
|
-
case "center": return "middle";
|
|
580
|
-
case "top": return "top";
|
|
581
|
-
}
|
|
582
|
-
return "bottom";
|
|
583
|
-
});
|
|
584
|
-
};
|
|
585
|
-
|
|
586
|
-
/** @deprecated Replaced by {@link #target}. */
|
|
587
|
-
pv.Mark.prototype.anchorTarget = function() {
|
|
588
|
-
return this.target;
|
|
589
|
-
};
|
|
590
|
-
|
|
591
|
-
/**
|
|
592
|
-
* Alias for setting the left, right, top and bottom properties simultaneously.
|
|
593
|
-
*
|
|
594
|
-
* @see #left
|
|
595
|
-
* @see #right
|
|
596
|
-
* @see #top
|
|
597
|
-
* @see #bottom
|
|
598
|
-
* @returns {pv.Mark} this.
|
|
599
|
-
*/
|
|
600
|
-
pv.Mark.prototype.margin = function(n) {
|
|
601
|
-
return this.left(n).right(n).top(n).bottom(n);
|
|
602
|
-
};
|
|
603
|
-
|
|
604
|
-
/**
|
|
605
|
-
* @private Returns the current instance of this mark in the scene graph. This
|
|
606
|
-
* is typically equivalent to <tt>this.scene[this.index]</tt>, however if the
|
|
607
|
-
* scene or index is unset, the default instance of the mark is returned. If no
|
|
608
|
-
* default is set, the default is the last instance. Similarly, if the scene or
|
|
609
|
-
* index of the parent panel is unset, the default instance of this mark in the
|
|
610
|
-
* last instance of the enclosing panel is returned, and so on.
|
|
611
|
-
*
|
|
612
|
-
* @returns a node in the scene graph.
|
|
613
|
-
*/
|
|
614
|
-
pv.Mark.prototype.instance = function(defaultIndex) {
|
|
615
|
-
var scene = this.scene || this.parent.instance(-1).children[this.childIndex],
|
|
616
|
-
index = !arguments.length || this.hasOwnProperty("index") ? this.index : defaultIndex;
|
|
617
|
-
return scene[index < 0 ? scene.length - 1 : index];
|
|
618
|
-
};
|
|
619
|
-
|
|
620
|
-
/**
|
|
621
|
-
* @private Find the instances of this mark that match source.
|
|
622
|
-
*
|
|
623
|
-
* @see pv.Anchor
|
|
624
|
-
*/
|
|
625
|
-
pv.Mark.prototype.instances = function(source) {
|
|
626
|
-
var mark = this, index = [], scene;
|
|
627
|
-
|
|
628
|
-
/* Mirrored descent. */
|
|
629
|
-
while (!(scene = mark.scene)) {
|
|
630
|
-
source = source.parent;
|
|
631
|
-
index.push({index: source.index, childIndex: mark.childIndex});
|
|
632
|
-
mark = mark.parent;
|
|
633
|
-
}
|
|
634
|
-
while (index.length) {
|
|
635
|
-
var i = index.pop();
|
|
636
|
-
scene = scene[i.index].children[i.childIndex];
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
/*
|
|
640
|
-
* When the anchor target is also an ancestor, as in the case of adding
|
|
641
|
-
* to a panel anchor, only generate one instance per panel. Also, set
|
|
642
|
-
* the margins to zero, since they are offset by the enclosing panel.
|
|
643
|
-
*/
|
|
644
|
-
if (this.hasOwnProperty("index")) {
|
|
645
|
-
var s = pv.extend(scene[this.index]);
|
|
646
|
-
s.right = s.top = s.left = s.bottom = 0;
|
|
647
|
-
return [s];
|
|
648
|
-
}
|
|
649
|
-
return scene;
|
|
650
|
-
};
|
|
651
|
-
|
|
652
|
-
/**
|
|
653
|
-
* @private Returns the first instance of this mark in the scene graph. This
|
|
654
|
-
* method can only be called when the mark is bound to the scene graph (for
|
|
655
|
-
* example, from an event handler, or within a property function).
|
|
656
|
-
*
|
|
657
|
-
* @returns a node in the scene graph.
|
|
658
|
-
*/
|
|
659
|
-
pv.Mark.prototype.first = function() {
|
|
660
|
-
return this.scene[0];
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
/**
|
|
664
|
-
* @private Returns the last instance of this mark in the scene graph. This
|
|
665
|
-
* method can only be called when the mark is bound to the scene graph (for
|
|
666
|
-
* example, from an event handler, or within a property function). In addition,
|
|
667
|
-
* note that mark instances are built sequentially, so the last instance of this
|
|
668
|
-
* mark may not yet be constructed.
|
|
669
|
-
*
|
|
670
|
-
* @returns a node in the scene graph.
|
|
671
|
-
*/
|
|
672
|
-
pv.Mark.prototype.last = function() {
|
|
673
|
-
return this.scene[this.scene.length - 1];
|
|
674
|
-
};
|
|
675
|
-
|
|
676
|
-
/**
|
|
677
|
-
* @private Returns the previous instance of this mark in the scene graph, or
|
|
678
|
-
* null if this is the first instance.
|
|
679
|
-
*
|
|
680
|
-
* @returns a node in the scene graph, or null.
|
|
681
|
-
*/
|
|
682
|
-
pv.Mark.prototype.sibling = function() {
|
|
683
|
-
return (this.index == 0) ? null : this.scene[this.index - 1];
|
|
684
|
-
};
|
|
685
|
-
|
|
686
|
-
/**
|
|
687
|
-
* @private Returns the current instance in the scene graph of this mark, in the
|
|
688
|
-
* previous instance of the enclosing parent panel. May return null if this
|
|
689
|
-
* instance could not be found.
|
|
690
|
-
*
|
|
691
|
-
* @returns a node in the scene graph, or null.
|
|
692
|
-
*/
|
|
693
|
-
pv.Mark.prototype.cousin = function() {
|
|
694
|
-
var p = this.parent, s = p && p.sibling();
|
|
695
|
-
return (s && s.children) ? s.children[this.childIndex][this.index] : null;
|
|
696
|
-
};
|
|
697
|
-
|
|
698
|
-
/**
|
|
699
|
-
* Renders this mark, including recursively rendering all child marks if this is
|
|
700
|
-
* a panel. This method finds all instances of this mark and renders them. This
|
|
701
|
-
* method descends recursively to the level of the mark to be rendered, finding
|
|
702
|
-
* all visible instances of the mark. After the marks are rendered, the scene
|
|
703
|
-
* and index attributes are removed from the mark to restore them to a clean
|
|
704
|
-
* state.
|
|
705
|
-
*
|
|
706
|
-
* <p>If an enclosing panel has an index property set (as is the case inside in
|
|
707
|
-
* an event handler), then only instances of this mark inside the given instance
|
|
708
|
-
* of the panel will be rendered; otherwise, all visible instances of the mark
|
|
709
|
-
* will be rendered.
|
|
710
|
-
*/
|
|
711
|
-
pv.Mark.prototype.render = function() {
|
|
712
|
-
var parent = this.parent,
|
|
713
|
-
stack = pv.Mark.stack;
|
|
714
|
-
|
|
715
|
-
/* For the first render, take it from the top. */
|
|
716
|
-
if (parent && !this.root.scene) {
|
|
717
|
-
this.root.render();
|
|
718
|
-
return;
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
/* Record the path to this mark. */
|
|
722
|
-
var indexes = [];
|
|
723
|
-
for (var mark = this; mark.parent; mark = mark.parent) {
|
|
724
|
-
indexes.unshift(mark.childIndex);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
/** @private */
|
|
728
|
-
function render(mark, depth, scale) {
|
|
729
|
-
mark.scale = scale;
|
|
730
|
-
if (depth < indexes.length) {
|
|
731
|
-
stack.unshift(null);
|
|
732
|
-
if (mark.hasOwnProperty("index")) {
|
|
733
|
-
renderInstance(mark, depth, scale);
|
|
734
|
-
} else {
|
|
735
|
-
for (var i = 0, n = mark.scene.length; i < n; i++) {
|
|
736
|
-
mark.index = i;
|
|
737
|
-
renderInstance(mark, depth, scale);
|
|
738
|
-
}
|
|
739
|
-
delete mark.index;
|
|
740
|
-
}
|
|
741
|
-
stack.shift();
|
|
742
|
-
} else {
|
|
743
|
-
mark.build();
|
|
744
|
-
|
|
745
|
-
/*
|
|
746
|
-
* In the update phase, the scene is rendered by creating and updating
|
|
747
|
-
* elements and attributes in the SVG image. No properties are evaluated
|
|
748
|
-
* during the update phase; instead the values computed previously in the
|
|
749
|
-
* build phase are simply translated into SVG. The update phase is
|
|
750
|
-
* decoupled (see pv.Scene) to allow different rendering engines.
|
|
751
|
-
*/
|
|
752
|
-
pv.Scene.scale = scale;
|
|
753
|
-
pv.Scene.updateAll(mark.scene);
|
|
754
|
-
}
|
|
755
|
-
delete mark.scale;
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
/**
|
|
759
|
-
* @private Recursively renders the current instance of the specified mark.
|
|
760
|
-
* This is slightly tricky because `index` and `scene` properties may or may
|
|
761
|
-
* not already be set; if they are set, it means we are rendering only a
|
|
762
|
-
* specific instance; if they are unset, we are rendering all instances.
|
|
763
|
-
* Furthermore, we must preserve the original context of these properties when
|
|
764
|
-
* rendering completes.
|
|
765
|
-
*
|
|
766
|
-
* <p>Another tricky aspect is that the `scene` attribute should be set for
|
|
767
|
-
* any preceding children, so as to allow property chaining. This is
|
|
768
|
-
* consistent with first-pass rendering.
|
|
769
|
-
*/
|
|
770
|
-
function renderInstance(mark, depth, scale) {
|
|
771
|
-
var s = mark.scene[mark.index], i;
|
|
772
|
-
if (s.visible) {
|
|
773
|
-
var childIndex = indexes[depth],
|
|
774
|
-
child = mark.children[childIndex];
|
|
775
|
-
|
|
776
|
-
/* Set preceding child scenes. */
|
|
777
|
-
for (i = 0; i < childIndex; i++) {
|
|
778
|
-
mark.children[i].scene = s.children[i];
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/* Set current child scene, if necessary. */
|
|
782
|
-
stack[0] = s.data;
|
|
783
|
-
if (child.scene) {
|
|
784
|
-
render(child, depth + 1, scale * s.transform.k);
|
|
785
|
-
} else {
|
|
786
|
-
child.scene = s.children[childIndex];
|
|
787
|
-
render(child, depth + 1, scale * s.transform.k);
|
|
788
|
-
delete child.scene;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
/* Clear preceding child scenes. */
|
|
792
|
-
for (i = 0; i < childIndex; i++) {
|
|
793
|
-
delete mark.children[i].scene;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
/* Bind this mark's property definitions. */
|
|
799
|
-
this.bind();
|
|
800
|
-
|
|
801
|
-
/* The render context is the first ancestor with an explicit index. */
|
|
802
|
-
while (parent && !parent.hasOwnProperty("index")) parent = parent.parent;
|
|
803
|
-
|
|
804
|
-
/* Recursively render all instances of this mark. */
|
|
805
|
-
this.context(
|
|
806
|
-
parent ? parent.scene : undefined,
|
|
807
|
-
parent ? parent.index : -1,
|
|
808
|
-
function() { render(this.root, 0, 1); });
|
|
809
|
-
};
|
|
810
|
-
|
|
811
|
-
/** @private Stores the current data stack. */
|
|
812
|
-
pv.Mark.stack = [];
|
|
813
|
-
|
|
814
|
-
/**
|
|
815
|
-
* @private In the bind phase, inherited property definitions are cached so they
|
|
816
|
-
* do not need to be queried during build.
|
|
817
|
-
*/
|
|
818
|
-
pv.Mark.prototype.bind = function() {
|
|
819
|
-
var seen = {}, types = [[], [], [], []], data, required = [];
|
|
820
|
-
|
|
821
|
-
/** Scans the proto chain for the specified mark. */
|
|
822
|
-
function bind(mark) {
|
|
823
|
-
do {
|
|
824
|
-
var properties = mark.$properties;
|
|
825
|
-
for (var i = properties.length - 1; i >= 0 ; i--) {
|
|
826
|
-
var p = properties[i];
|
|
827
|
-
if (!(p.name in seen)) {
|
|
828
|
-
seen[p.name] = p;
|
|
829
|
-
switch (p.name) {
|
|
830
|
-
case "data": data = p; break;
|
|
831
|
-
case "visible": case "id": required.push(p); break;
|
|
832
|
-
default: types[p.type].push(p); break;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
} while (mark = mark.proto);
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
/* Scan the proto chain for all defined properties. */
|
|
840
|
-
bind(this);
|
|
841
|
-
bind(this.defaults);
|
|
842
|
-
types[1].reverse();
|
|
843
|
-
types[3].reverse();
|
|
844
|
-
|
|
845
|
-
/* Any undefined properties are null. */
|
|
846
|
-
var mark = this;
|
|
847
|
-
do for (var name in mark.properties) {
|
|
848
|
-
if (!(name in seen)) {
|
|
849
|
-
types[2].push(seen[name] = {name: name, type: 2, value: null});
|
|
850
|
-
}
|
|
851
|
-
} while (mark = mark.proto);
|
|
852
|
-
|
|
853
|
-
/* Define setter-getter for inherited defs. */
|
|
854
|
-
var defs = types[0].concat(types[1]);
|
|
855
|
-
for (var i = 0; i < defs.length; i++) {
|
|
856
|
-
this.propertyMethod(defs[i].name, true);
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
/* Setup binds to evaluate constants before functions. */
|
|
860
|
-
this.binds = {
|
|
861
|
-
properties: seen,
|
|
862
|
-
data: data,
|
|
863
|
-
defs: defs,
|
|
864
|
-
required: required,
|
|
865
|
-
optional: pv.blend(types)
|
|
866
|
-
};
|
|
867
|
-
};
|
|
868
|
-
|
|
869
|
-
/**
|
|
870
|
-
* @private Evaluates properties and computes implied properties. Properties are
|
|
871
|
-
* stored in the {@link #scene} array for each instance of this mark.
|
|
872
|
-
*
|
|
873
|
-
* <p>As marks are built recursively, the {@link #index} property is updated to
|
|
874
|
-
* match the current index into the data array for each mark. Note that the
|
|
875
|
-
* index property is only set for the mark currently being built and its
|
|
876
|
-
* enclosing parent panels. The index property for other marks is unset, but is
|
|
877
|
-
* inherited from the global <tt>Mark</tt> class prototype. This allows mark
|
|
878
|
-
* properties to refer to properties on other marks <i>in the same panel</i>
|
|
879
|
-
* conveniently; however, in general it is better to reference mark instances
|
|
880
|
-
* specifically through the scene graph rather than depending on the magical
|
|
881
|
-
* behavior of {@link #index}.
|
|
882
|
-
*
|
|
883
|
-
* <p>The root scene array has a special property, <tt>data</tt>, which stores
|
|
884
|
-
* the current data stack. The first element in this stack is the current datum,
|
|
885
|
-
* followed by the datum of the enclosing parent panel, and so on. The data
|
|
886
|
-
* stack should not be accessed directly; instead, property functions are passed
|
|
887
|
-
* the current data stack as arguments.
|
|
888
|
-
*
|
|
889
|
-
* <p>The evaluation of the <tt>data</tt> and <tt>visible</tt> properties is
|
|
890
|
-
* special. The <tt>data</tt> property is evaluated first; unlike the other
|
|
891
|
-
* properties, the data stack is from the parent panel, rather than the current
|
|
892
|
-
* mark, since the data is not defined until the data property is evaluated.
|
|
893
|
-
* The <tt>visible</tt> property is subsequently evaluated for each instance;
|
|
894
|
-
* only if true will the {@link #buildInstance} method be called, evaluating
|
|
895
|
-
* other properties and recursively building the scene graph.
|
|
896
|
-
*
|
|
897
|
-
* <p>If this mark is being re-built, any old instances of this mark that no
|
|
898
|
-
* longer exist (because the new data array contains fewer elements) will be
|
|
899
|
-
* cleared using {@link #clearInstance}.
|
|
900
|
-
*
|
|
901
|
-
* @param parent the instance of the parent panel from the scene graph.
|
|
902
|
-
*/
|
|
903
|
-
pv.Mark.prototype.build = function() {
|
|
904
|
-
var scene = this.scene, stack = pv.Mark.stack;
|
|
905
|
-
if (!scene) {
|
|
906
|
-
scene = this.scene = [];
|
|
907
|
-
scene.mark = this;
|
|
908
|
-
scene.type = this.type;
|
|
909
|
-
scene.childIndex = this.childIndex;
|
|
910
|
-
if (this.parent) {
|
|
911
|
-
scene.parent = this.parent.scene;
|
|
912
|
-
scene.parentIndex = this.parent.index;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
/* Resolve anchor target. */
|
|
917
|
-
if (this.target) scene.target = this.target.instances(scene);
|
|
918
|
-
|
|
919
|
-
/* Evaluate defs. */
|
|
920
|
-
if (this.binds.defs.length) {
|
|
921
|
-
var defs = scene.defs;
|
|
922
|
-
if (!defs) scene.defs = defs = {};
|
|
923
|
-
for (var i = 0; i < this.binds.defs.length; i++) {
|
|
924
|
-
var p = this.binds.defs[i], d = defs[p.name];
|
|
925
|
-
if (!d || (p.id > d.id)) {
|
|
926
|
-
defs[p.name] = {
|
|
927
|
-
id: 0, // this def will be re-evaluated on next build
|
|
928
|
-
value: (p.type & 1) ? p.value.apply(this, stack) : p.value
|
|
929
|
-
};
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
/* Evaluate special data property. */
|
|
935
|
-
var data = this.binds.data;
|
|
936
|
-
data = data.type & 1 ? data.value.apply(this, stack) : data.value;
|
|
937
|
-
|
|
938
|
-
/* Create, update and delete scene nodes. */
|
|
939
|
-
stack.unshift(null);
|
|
940
|
-
scene.length = data.length;
|
|
941
|
-
for (var i = 0; i < data.length; i++) {
|
|
942
|
-
pv.Mark.prototype.index = this.index = i;
|
|
943
|
-
var s = scene[i];
|
|
944
|
-
if (!s) scene[i] = s = {};
|
|
945
|
-
s.data = stack[0] = data[i];
|
|
946
|
-
this.buildInstance(s);
|
|
947
|
-
}
|
|
948
|
-
pv.Mark.prototype.index = -1;
|
|
949
|
-
delete this.index;
|
|
950
|
-
stack.shift();
|
|
951
|
-
|
|
952
|
-
return this;
|
|
953
|
-
};
|
|
954
|
-
|
|
955
|
-
/**
|
|
956
|
-
* @private Evaluates the specified array of properties for the specified
|
|
957
|
-
* instance <tt>s</tt> in the scene graph.
|
|
958
|
-
*
|
|
959
|
-
* @param s a node in the scene graph; the instance of the mark to build.
|
|
960
|
-
* @param properties an array of properties.
|
|
961
|
-
*/
|
|
962
|
-
pv.Mark.prototype.buildProperties = function(s, properties) {
|
|
963
|
-
for (var i = 0, n = properties.length; i < n; i++) {
|
|
964
|
-
var p = properties[i], v = p.value; // assume case 2 (constant)
|
|
965
|
-
switch (p.type) {
|
|
966
|
-
case 0:
|
|
967
|
-
case 1: v = this.scene.defs[p.name].value; break;
|
|
968
|
-
case 3: v = v.apply(this, pv.Mark.stack); break;
|
|
969
|
-
}
|
|
970
|
-
s[p.name] = v;
|
|
971
|
-
}
|
|
972
|
-
};
|
|
973
|
-
|
|
974
|
-
/**
|
|
975
|
-
* @private Evaluates all of the properties for this mark for the specified
|
|
976
|
-
* instance <tt>s</tt> in the scene graph. The set of properties to evaluate is
|
|
977
|
-
* retrieved from the {@link #properties} array for this mark type (see {@link
|
|
978
|
-
* #type}). After these properties are evaluated, any <b>implied</b> properties
|
|
979
|
-
* may be computed by the mark and set on the scene graph; see
|
|
980
|
-
* {@link #buildImplied}.
|
|
981
|
-
*
|
|
982
|
-
* <p>For panels, this method recursively builds the scene graph for all child
|
|
983
|
-
* marks as well. In general, this method should not need to be overridden by
|
|
984
|
-
* concrete mark types.
|
|
985
|
-
*
|
|
986
|
-
* @param s a node in the scene graph; the instance of the mark to build.
|
|
987
|
-
*/
|
|
988
|
-
pv.Mark.prototype.buildInstance = function(s) {
|
|
989
|
-
this.buildProperties(s, this.binds.required);
|
|
990
|
-
if (s.visible) {
|
|
991
|
-
this.buildProperties(s, this.binds.optional);
|
|
992
|
-
this.buildImplied(s);
|
|
993
|
-
}
|
|
994
|
-
};
|
|
995
|
-
|
|
996
|
-
/**
|
|
997
|
-
* @private Computes the implied properties for this mark for the specified
|
|
998
|
-
* instance <tt>s</tt> in the scene graph. Implied properties are those with
|
|
999
|
-
* dependencies on multiple other properties; for example, the width property
|
|
1000
|
-
* may be implied if the left and right properties are set. This method can be
|
|
1001
|
-
* overridden by concrete mark types to define new implied properties, if
|
|
1002
|
-
* necessary.
|
|
1003
|
-
*
|
|
1004
|
-
* @param s a node in the scene graph; the instance of the mark to build.
|
|
1005
|
-
*/
|
|
1006
|
-
pv.Mark.prototype.buildImplied = function(s) {
|
|
1007
|
-
var l = s.left;
|
|
1008
|
-
var r = s.right;
|
|
1009
|
-
var t = s.top;
|
|
1010
|
-
var b = s.bottom;
|
|
1011
|
-
|
|
1012
|
-
/* Assume width and height are zero if not supported by this mark type. */
|
|
1013
|
-
var p = this.properties;
|
|
1014
|
-
var w = p.width ? s.width : 0;
|
|
1015
|
-
var h = p.height ? s.height : 0;
|
|
1016
|
-
|
|
1017
|
-
/* Compute implied width, right and left. */
|
|
1018
|
-
var width = this.parent ? this.parent.width() : (w + l + r);
|
|
1019
|
-
if (w == null) {
|
|
1020
|
-
w = width - (r = r || 0) - (l = l || 0);
|
|
1021
|
-
} else if (r == null) {
|
|
1022
|
-
if (l == null) {
|
|
1023
|
-
l = r = (width - w) / 2;
|
|
1024
|
-
} else {
|
|
1025
|
-
r = width - w - l;
|
|
1026
|
-
}
|
|
1027
|
-
} else if (l == null) {
|
|
1028
|
-
l = width - w - r;
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
/* Compute implied height, bottom and top. */
|
|
1032
|
-
var height = this.parent ? this.parent.height() : (h + t + b);
|
|
1033
|
-
if (h == null) {
|
|
1034
|
-
h = height - (t = t || 0) - (b = b || 0);
|
|
1035
|
-
} else if (b == null) {
|
|
1036
|
-
if (t == null) {
|
|
1037
|
-
b = t = (height - h) / 2;
|
|
1038
|
-
} else {
|
|
1039
|
-
b = height - h - t;
|
|
1040
|
-
}
|
|
1041
|
-
} else if (t == null) {
|
|
1042
|
-
t = height - h - b;
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
s.left = l;
|
|
1046
|
-
s.right = r;
|
|
1047
|
-
s.top = t;
|
|
1048
|
-
s.bottom = b;
|
|
1049
|
-
|
|
1050
|
-
/* Only set width and height if they are supported by this mark type. */
|
|
1051
|
-
if (p.width) s.width = w;
|
|
1052
|
-
if (p.height) s.height = h;
|
|
1053
|
-
|
|
1054
|
-
/* Set any null colors to pv.Color.transparent. */
|
|
1055
|
-
if (p.textStyle && !s.textStyle) s.textStyle = pv.Color.transparent;
|
|
1056
|
-
if (p.fillStyle && !s.fillStyle) s.fillStyle = pv.Color.transparent;
|
|
1057
|
-
if (p.strokeStyle && !s.strokeStyle) s.strokeStyle = pv.Color.transparent;
|
|
1058
|
-
};
|
|
1059
|
-
|
|
1060
|
-
/**
|
|
1061
|
-
* Returns the current location of the mouse (cursor) relative to this mark's
|
|
1062
|
-
* parent. The <i>x</i> coordinate corresponds to the left margin, while the
|
|
1063
|
-
* <i>y</i> coordinate corresponds to the top margin.
|
|
1064
|
-
*
|
|
1065
|
-
* @returns {pv.Vector} the mouse location.
|
|
1066
|
-
*/
|
|
1067
|
-
pv.Mark.prototype.mouse = function() {
|
|
1068
|
-
|
|
1069
|
-
/* Compute xy-coordinates relative to the panel. */
|
|
1070
|
-
var x = pv.event.pageX || 0,
|
|
1071
|
-
y = pv.event.pageY || 0,
|
|
1072
|
-
n = this.root.canvas();
|
|
1073
|
-
do {
|
|
1074
|
-
x -= n.offsetLeft;
|
|
1075
|
-
y -= n.offsetTop;
|
|
1076
|
-
} while (n = n.offsetParent);
|
|
1077
|
-
|
|
1078
|
-
/* Compute the inverse transform of all enclosing panels. */
|
|
1079
|
-
var t = pv.Transform.identity,
|
|
1080
|
-
p = this.properties.transform ? this : this.parent,
|
|
1081
|
-
pz = [];
|
|
1082
|
-
do { pz.push(p); } while (p = p.parent);
|
|
1083
|
-
while (p = pz.pop()) t = t.translate(p.left(), p.top()).times(p.transform());
|
|
1084
|
-
t = t.invert();
|
|
1085
|
-
|
|
1086
|
-
return pv.vector(x * t.k + t.x, y * t.k + t.y);
|
|
1087
|
-
};
|
|
1088
|
-
|
|
1089
|
-
/**
|
|
1090
|
-
* Registers an event handler for the specified event type with this mark. When
|
|
1091
|
-
* an event of the specified type is triggered, the specified handler will be
|
|
1092
|
-
* invoked. The handler is invoked in a similar method to property functions:
|
|
1093
|
-
* the context is <tt>this</tt> mark instance, and the arguments are the full
|
|
1094
|
-
* data stack. Event handlers can use property methods to manipulate the display
|
|
1095
|
-
* properties of the mark:
|
|
1096
|
-
*
|
|
1097
|
-
* <pre>m.event("click", function() this.fillStyle("red"));</pre>
|
|
1098
|
-
*
|
|
1099
|
-
* Alternatively, the external data can be manipulated and the visualization
|
|
1100
|
-
* redrawn:
|
|
1101
|
-
*
|
|
1102
|
-
* <pre>m.event("click", function(d) {
|
|
1103
|
-
* data = all.filter(function(k) k.name == d);
|
|
1104
|
-
* vis.render();
|
|
1105
|
-
* });</pre>
|
|
1106
|
-
*
|
|
1107
|
-
* The return value of the event handler determines which mark gets re-rendered.
|
|
1108
|
-
* Use defs ({@link #def}) to set temporary state from event handlers.
|
|
1109
|
-
*
|
|
1110
|
-
* <p>The complete set of event types is defined by SVG; see the reference
|
|
1111
|
-
* below. The set of supported event types is:<ul>
|
|
1112
|
-
*
|
|
1113
|
-
* <li>click
|
|
1114
|
-
* <li>mousedown
|
|
1115
|
-
* <li>mouseup
|
|
1116
|
-
* <li>mouseover
|
|
1117
|
-
* <li>mousemove
|
|
1118
|
-
* <li>mouseout
|
|
1119
|
-
*
|
|
1120
|
-
* </ul>Since Protovis does not specify any concept of focus, it does not
|
|
1121
|
-
* support key events; these should be handled outside the visualization using
|
|
1122
|
-
* standard JavaScript. In the future, support for interaction may be extended
|
|
1123
|
-
* to support additional event types, particularly those most relevant to
|
|
1124
|
-
* interactive visualization, such as selection.
|
|
1125
|
-
*
|
|
1126
|
-
* <p>TODO In the current implementation, event handlers are not inherited from
|
|
1127
|
-
* prototype marks. They must be defined explicitly on each interactive mark. In
|
|
1128
|
-
* addition, only one event handler for a given event type can be defined; when
|
|
1129
|
-
* specifying multiple event handlers for the same type, only the last one will
|
|
1130
|
-
* be used.
|
|
1131
|
-
*
|
|
1132
|
-
* @see <a href="http://www.w3.org/TR/SVGTiny12/interact.html#SVGEvents">SVG events</a>
|
|
1133
|
-
* @param {string} type the event type.
|
|
1134
|
-
* @param {function} handler the event handler.
|
|
1135
|
-
* @returns {pv.Mark} this.
|
|
1136
|
-
*/
|
|
1137
|
-
pv.Mark.prototype.event = function(type, handler) {
|
|
1138
|
-
this.$handlers[type] = pv.functor(handler);
|
|
1139
|
-
return this;
|
|
1140
|
-
};
|
|
1141
|
-
|
|
1142
|
-
/** @private Evaluates the function <i>f</i> with the specified context. */
|
|
1143
|
-
pv.Mark.prototype.context = function(scene, index, f) {
|
|
1144
|
-
var proto = pv.Mark.prototype,
|
|
1145
|
-
stack = pv.Mark.stack,
|
|
1146
|
-
oscene = pv.Mark.scene,
|
|
1147
|
-
oindex = proto.index;
|
|
1148
|
-
|
|
1149
|
-
/** @private Sets the context. */
|
|
1150
|
-
function apply(scene, index) {
|
|
1151
|
-
pv.Mark.scene = scene;
|
|
1152
|
-
proto.index = index;
|
|
1153
|
-
if (!scene) return;
|
|
1154
|
-
|
|
1155
|
-
var that = scene.mark,
|
|
1156
|
-
mark = that,
|
|
1157
|
-
ancestors = [];
|
|
1158
|
-
|
|
1159
|
-
/* Set ancestors' scene and index; populate data stack. */
|
|
1160
|
-
do {
|
|
1161
|
-
ancestors.push(mark);
|
|
1162
|
-
stack.push(scene[index].data);
|
|
1163
|
-
mark.index = index;
|
|
1164
|
-
mark.scene = scene;
|
|
1165
|
-
index = scene.parentIndex;
|
|
1166
|
-
scene = scene.parent;
|
|
1167
|
-
} while (mark = mark.parent);
|
|
1168
|
-
|
|
1169
|
-
/* Set ancestors' scale; requires top-down. */
|
|
1170
|
-
for (var i = ancestors.length - 1, k = 1; i > 0; i--) {
|
|
1171
|
-
mark = ancestors[i];
|
|
1172
|
-
mark.scale = k;
|
|
1173
|
-
k *= mark.scene[mark.index].transform.k;
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
/* Set children's scene and scale. */
|
|
1177
|
-
if (that.children) for (var i = 0, n = that.children.length; i < n; i++) {
|
|
1178
|
-
mark = that.children[i];
|
|
1179
|
-
mark.scene = that.scene[that.index].children[i];
|
|
1180
|
-
mark.scale = k;
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
/** @private Clears the context. */
|
|
1185
|
-
function clear(scene, index) {
|
|
1186
|
-
if (!scene) return;
|
|
1187
|
-
var that = scene.mark,
|
|
1188
|
-
mark;
|
|
1189
|
-
|
|
1190
|
-
/* Reset children. */
|
|
1191
|
-
if (that.children) for (var i = 0, n = that.children.length; i < n; i++) {
|
|
1192
|
-
mark = that.children[i];
|
|
1193
|
-
delete mark.scene;
|
|
1194
|
-
delete mark.scale;
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
/* Reset ancestors. */
|
|
1198
|
-
mark = that;
|
|
1199
|
-
do {
|
|
1200
|
-
stack.pop();
|
|
1201
|
-
if (mark.parent) {
|
|
1202
|
-
delete mark.scene;
|
|
1203
|
-
delete mark.scale;
|
|
1204
|
-
}
|
|
1205
|
-
delete mark.index;
|
|
1206
|
-
} while (mark = mark.parent);
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
/* Context switch, invoke the function, then switch back. */
|
|
1210
|
-
clear(oscene, oindex);
|
|
1211
|
-
apply(scene, index);
|
|
1212
|
-
try {
|
|
1213
|
-
f.apply(this, stack);
|
|
1214
|
-
} finally {
|
|
1215
|
-
clear(scene, index);
|
|
1216
|
-
apply(oscene, oindex);
|
|
1217
|
-
}
|
|
1218
|
-
};
|
|
1219
|
-
|
|
1220
|
-
/** @private Execute the event listener, then re-render. */
|
|
1221
|
-
pv.Mark.dispatch = function(type, scene, index) {
|
|
1222
|
-
var m = scene.mark, p = scene.parent, l = m.$handlers[type];
|
|
1223
|
-
if (!l) return p && pv.Mark.dispatch(type, p, scene.parentIndex);
|
|
1224
|
-
m.context(scene, index, function() {
|
|
1225
|
-
m = l.apply(m, pv.Mark.stack);
|
|
1226
|
-
if (m && m.render) m.render();
|
|
1227
|
-
});
|
|
1228
|
-
return true;
|
|
1229
|
-
};
|
|
1230
|
-
|
|
1231
|
-
pv.Mark.prototype.transition = function() {
|
|
1232
|
-
return new pv.Transition(this);
|
|
1233
|
-
};
|
|
1234
|
-
|
|
1235
|
-
pv.Mark.prototype.on = function(state) {
|
|
1236
|
-
return this["$" + state] = new pv.Transient(this);
|
|
1237
|
-
};
|