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.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +13 -0
  4. data/Gemfile +8 -0
  5. data/Gemfile.lock +37 -0
  6. data/History.txt +6 -0
  7. data/LICENSE.txt +23 -0
  8. data/{README.txt → README.md} +15 -12
  9. data/Rakefile +4 -11
  10. data/lib/rubyvis.rb +1 -1
  11. data/lib/rubyvis/scale/quantitative.rb +14 -18
  12. data/lib/rubyvis/scene/svg_label.rb +1 -1
  13. data/rubyvis.gemspec +21 -0
  14. data/spec/anchor_spec.rb +2 -1
  15. data/spec/line_spec.rb +2 -2
  16. data/spec/scale_linear_datetime_spec.rb +23 -8
  17. data/spec/spec_helper.rb +2 -1
  18. metadata +31 -214
  19. data/.gemtest +0 -0
  20. data/vendor/protovis/protovis-r3.3.js +0 -287
  21. data/vendor/protovis/src/behavior/Behavior.js +0 -32
  22. data/vendor/protovis/src/behavior/Drag.js +0 -112
  23. data/vendor/protovis/src/behavior/Pan.js +0 -110
  24. data/vendor/protovis/src/behavior/Point.js +0 -157
  25. data/vendor/protovis/src/behavior/Resize.js +0 -104
  26. data/vendor/protovis/src/behavior/Select.js +0 -100
  27. data/vendor/protovis/src/behavior/Zoom.js +0 -85
  28. data/vendor/protovis/src/color/Color.js +0 -598
  29. data/vendor/protovis/src/color/Colors.js +0 -135
  30. data/vendor/protovis/src/color/Ramp.js +0 -17
  31. data/vendor/protovis/src/data/Arrays.js +0 -277
  32. data/vendor/protovis/src/data/Dom.js +0 -380
  33. data/vendor/protovis/src/data/Flatten.js +0 -146
  34. data/vendor/protovis/src/data/Histogram.js +0 -120
  35. data/vendor/protovis/src/data/LinearScale.js +0 -54
  36. data/vendor/protovis/src/data/LogScale.js +0 -142
  37. data/vendor/protovis/src/data/Nest.js +0 -257
  38. data/vendor/protovis/src/data/Numbers.js +0 -313
  39. data/vendor/protovis/src/data/Objects.js +0 -78
  40. data/vendor/protovis/src/data/OrdinalScale.js +0 -267
  41. data/vendor/protovis/src/data/QuantileScale.js +0 -180
  42. data/vendor/protovis/src/data/QuantitativeScale.js +0 -440
  43. data/vendor/protovis/src/data/RootScale.js +0 -55
  44. data/vendor/protovis/src/data/Scale.js +0 -86
  45. data/vendor/protovis/src/data/Transform.js +0 -109
  46. data/vendor/protovis/src/data/Tree.js +0 -124
  47. data/vendor/protovis/src/data/Vector.js +0 -118
  48. data/vendor/protovis/src/geo/Geo.js +0 -5
  49. data/vendor/protovis/src/geo/GeoScale.js +0 -307
  50. data/vendor/protovis/src/geo/LatLng.js +0 -23
  51. data/vendor/protovis/src/geo/Projection.js +0 -43
  52. data/vendor/protovis/src/geo/Projections.js +0 -117
  53. data/vendor/protovis/src/lang/Array.js +0 -112
  54. data/vendor/protovis/src/lang/init.js +0 -26
  55. data/vendor/protovis/src/layout/Arc.js +0 -178
  56. data/vendor/protovis/src/layout/Bullet.js +0 -164
  57. data/vendor/protovis/src/layout/Cluster.js +0 -205
  58. data/vendor/protovis/src/layout/Force.js +0 -309
  59. data/vendor/protovis/src/layout/Grid.js +0 -119
  60. data/vendor/protovis/src/layout/Hierarchy.js +0 -249
  61. data/vendor/protovis/src/layout/Horizon.js +0 -159
  62. data/vendor/protovis/src/layout/Indent.js +0 -83
  63. data/vendor/protovis/src/layout/Layout.js +0 -56
  64. data/vendor/protovis/src/layout/Matrix.js +0 -177
  65. data/vendor/protovis/src/layout/Network.js +0 -302
  66. data/vendor/protovis/src/layout/Pack.js +0 -323
  67. data/vendor/protovis/src/layout/Partition.js +0 -203
  68. data/vendor/protovis/src/layout/Rollup.js +0 -203
  69. data/vendor/protovis/src/layout/Stack.js +0 -391
  70. data/vendor/protovis/src/layout/Tree.js +0 -282
  71. data/vendor/protovis/src/layout/Treemap.js +0 -347
  72. data/vendor/protovis/src/mark/Anchor.js +0 -81
  73. data/vendor/protovis/src/mark/Area.js +0 -268
  74. data/vendor/protovis/src/mark/Bar.js +0 -93
  75. data/vendor/protovis/src/mark/Dot.js +0 -212
  76. data/vendor/protovis/src/mark/Ease.js +0 -150
  77. data/vendor/protovis/src/mark/Image.js +0 -154
  78. data/vendor/protovis/src/mark/Label.js +0 -155
  79. data/vendor/protovis/src/mark/Line.js +0 -195
  80. data/vendor/protovis/src/mark/Mark.js +0 -1237
  81. data/vendor/protovis/src/mark/Panel.js +0 -273
  82. data/vendor/protovis/src/mark/Rule.js +0 -143
  83. data/vendor/protovis/src/mark/Transient.js +0 -7
  84. data/vendor/protovis/src/mark/Transition.js +0 -195
  85. data/vendor/protovis/src/mark/Wedge.js +0 -244
  86. data/vendor/protovis/src/physics/BoundConstraint.js +0 -75
  87. data/vendor/protovis/src/physics/ChargeForce.js +0 -184
  88. data/vendor/protovis/src/physics/CollisionConstraint.js +0 -113
  89. data/vendor/protovis/src/physics/Constraint.js +0 -26
  90. data/vendor/protovis/src/physics/DragForce.js +0 -49
  91. data/vendor/protovis/src/physics/Force.js +0 -25
  92. data/vendor/protovis/src/physics/Particle.js +0 -81
  93. data/vendor/protovis/src/physics/PositionConstraint.js +0 -72
  94. data/vendor/protovis/src/physics/Quadtree.js +0 -195
  95. data/vendor/protovis/src/physics/Simulation.js +0 -159
  96. data/vendor/protovis/src/physics/SpringForce.js +0 -141
  97. data/vendor/protovis/src/pv-internals.js +0 -154
  98. data/vendor/protovis/src/pv.js +0 -95
  99. data/vendor/protovis/src/scene/SvgArea.js +0 -172
  100. data/vendor/protovis/src/scene/SvgBar.js +0 -28
  101. data/vendor/protovis/src/scene/SvgCurve.js +0 -354
  102. data/vendor/protovis/src/scene/SvgDot.js +0 -81
  103. data/vendor/protovis/src/scene/SvgImage.js +0 -45
  104. data/vendor/protovis/src/scene/SvgLabel.js +0 -46
  105. data/vendor/protovis/src/scene/SvgLine.js +0 -159
  106. data/vendor/protovis/src/scene/SvgPanel.js +0 -126
  107. data/vendor/protovis/src/scene/SvgRule.js +0 -26
  108. data/vendor/protovis/src/scene/SvgScene.js +0 -185
  109. data/vendor/protovis/src/scene/SvgWedge.js +0 -66
  110. data/vendor/protovis/src/text/DateFormat.js +0 -262
  111. data/vendor/protovis/src/text/Format.js +0 -78
  112. data/vendor/protovis/src/text/NumberFormat.js +0 -227
  113. 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
- };