2
YUI 3.13.0 (build 508226d)
3
Copyright 2013 Yahoo! Inc. All rights reserved.
4
Licensed under the BSD License.
5
http://yuilibrary.com/license/
8
YUI.add('axis', function (Y, NAME) {
11
* Provides base functionality for drawing chart axes.
16
var CONFIG = Y.config,
17
DOCUMENT = CONFIG.doc,
19
IS_STRING = Y_Lang.isString,
26
* Algorithmic strategy for rendering a left axis.
28
* @class LeftAxisLayout
32
LeftAxisLayout = function() {};
34
LeftAxisLayout.prototype = {
36
* Default margins for text fields.
39
* @method _getDefaultMargins
42
_getDefaultMargins: function()
53
* Sets the length of the tick on either side of the axis line.
55
* @method setTickOffset
58
setTickOffsets: function()
61
majorTicks = host.get("styles").majorTicks,
62
tickLength = majorTicks.length,
63
halfTick = tickLength * 0.5,
64
display = majorTicks.display;
65
host.set("topTickOffset", 0);
66
host.set("bottomTickOffset", 0);
71
host.set("rightTickOffset", tickLength);
72
host.set("leftTickOffset", 0);
75
host.set("rightTickOffset", 0);
76
host.set("leftTickOffset", tickLength);
79
host.set("rightTickOffset", halfTick);
80
host.set("leftTickOffset", halfTick);
83
host.set("rightTickOffset", 0);
84
host.set("leftTickOffset", 0);
93
* @param {Path} path reference to the path `Path` element in which to draw the tick.
94
* @param {Object} pt Point on the axis in which the tick will intersect.
95
* @param {Object} tickStyle Hash of properties to apply to the tick.
98
drawTick: function(path, pt, tickStyles)
101
style = host.get("styles"),
102
padding = style.padding,
103
tickLength = tickStyles.length,
104
start = {x:padding.left, y:pt.y},
105
end = {x:tickLength + padding.left, y:pt.y};
106
host.drawLine(path, start, end);
110
* Calculates the coordinates for the first point on an axis.
112
* @method getLineStart
116
getLineStart: function()
118
var style = this.get("styles"),
119
padding = style.padding,
120
majorTicks = style.majorTicks,
121
tickLength = majorTicks.length,
122
display = majorTicks.display,
123
pt = {x:padding.left, y:0};
124
if(display === "outside")
128
else if(display === "cross")
130
pt.x += tickLength/2;
136
* Calculates the point for a label.
138
* @method getLabelPoint
139
* @param {Object} point Point on the axis in which the tick will intersect.
143
getLabelPoint: function(point)
145
return {x:point.x - this.get("leftTickOffset"), y:point.y};
149
* Updates the value for the `maxLabelSize` for use in calculating total size.
151
* @method updateMaxLabelSize
152
* @param {HTMLElement} label to measure
155
updateMaxLabelSize: function(labelWidth, labelHeight)
158
props = this._labelRotationProps,
160
absRot = props.absRot,
161
sinRadians = props.sinRadians,
162
cosRadians = props.cosRadians,
168
else if(absRot === 90)
174
max = (cosRadians * labelWidth) + (sinRadians * labelHeight);
176
host._maxLabelSize = Math.max(host._maxLabelSize, max);
180
* Determines the available label width when the axis width has been explicitly set.
182
* @method getExplicitlySized
186
getExplicitlySized: function(styles)
188
if(this._explicitWidth)
191
w = host._explicitWidth,
192
totalTitleSize = host._totalTitleSize,
193
leftTickOffset = host.get("leftTickOffset"),
194
margin = styles.label.margin.right;
195
host._maxLabelSize = w - (leftTickOffset + margin + totalTitleSize);
202
* Rotate and position title.
204
* @method positionTitle
205
* @param {HTMLElement} label to rotate position
208
positionTitle: function(label)
211
bounds = host._titleBounds,
212
margin = host.get("styles").title.margin,
213
props = host._titleRotationProps,
214
w = bounds.right - bounds.left,
215
labelWidth = label.offsetWidth,
216
labelHeight = label.offsetHeight,
217
x = (labelWidth * -0.5) + (w * 0.5),
218
y = (host.get("height") * 0.5) - (labelHeight * 0.5);
219
props.labelWidth = labelWidth;
220
props.labelHeight = labelHeight;
221
if(margin && margin.left)
227
props.transformOrigin = [0.5, 0.5];
228
host._rotate(label, props);
232
* Rotate and position labels.
234
* @method positionLabel
235
* @param {HTMLElement} label to rotate position
236
* @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
240
positionLabel: function(label, pt, styles, i)
243
tickOffset = host.get("leftTickOffset"),
244
totalTitleSize = this._totalTitleSize,
245
leftOffset = pt.x + totalTitleSize - tickOffset,
247
props = this._labelRotationProps,
249
absRot = props.absRot,
250
maxLabelSize = host._maxLabelSize,
251
labelWidth = this._labelWidths[i],
252
labelHeight = this._labelHeights[i];
255
leftOffset -= labelWidth;
256
topOffset -= labelHeight * 0.5;
260
leftOffset -= labelWidth * 0.5;
264
leftOffset -= labelWidth * 0.5;
265
topOffset -= labelHeight;
269
leftOffset -= labelWidth + (labelHeight * absRot/360);
270
topOffset -= labelHeight * 0.5;
272
props.labelWidth = labelWidth;
273
props.labelHeight = labelHeight;
274
props.x = Math.round(maxLabelSize + leftOffset);
275
props.y = Math.round(topOffset);
276
this._rotate(label, props);
280
* Adjusts the coordinates of an axis label based on the rotation.
282
* @method _setRotationCoords
283
* @param {Object} props Coordinates, dimension and rotation properties of the label.
286
_setRotationCoords: function(props)
289
absRot = props.absRot,
292
labelWidth = props.labelWidth,
293
labelHeight = props.labelHeight;
296
leftOffset = labelWidth;
297
topOffset = labelHeight * 0.5;
302
leftOffset = labelWidth * 0.5;
306
leftOffset = labelWidth * 0.5;
307
topOffset = labelHeight;
311
leftOffset = labelWidth + (labelHeight * absRot/360);
312
topOffset = labelHeight * 0.5;
314
props.x -= leftOffset;
315
props.y -= topOffset;
319
* Returns the transformOrigin to use for an axis label based on the position of the axis
320
* and the rotation of the label.
322
* @method _getTransformOrigin
323
* @param {Number} rot The rotation (in degrees) of the label.
327
_getTransformOrigin: function(rot)
332
transformOrigin = [0, 0];
336
transformOrigin = [0.5, 0];
340
transformOrigin = [0.5, 1];
344
transformOrigin = [1, 0.5];
346
return transformOrigin;
350
* Adjust the position of the Axis widget's content box for internal axes.
352
* @method offsetNodeForTick
353
* @param {Node} cb contentBox of the axis
356
offsetNodeForTick: function()
361
* Sets the width of the axis based on its contents.
363
* @method setCalculatedSize
366
setCalculatedSize: function()
369
graphic = this.get("graphic"),
370
style = host.get("styles"),
372
tickOffset = host.get("leftTickOffset"),
373
max = host._maxLabelSize,
374
totalTitleSize = this._totalTitleSize,
375
ttl = Math.round(totalTitleSize + tickOffset + max + label.margin.right);
376
if(this._explicitWidth)
378
ttl = this._explicitWidth;
380
this.set("calculatedWidth", ttl);
381
graphic.set("x", ttl - tickOffset);
385
Y.LeftAxisLayout = LeftAxisLayout;
387
* RightAxisLayout contains algorithms for rendering a right axis.
389
* @class RightAxisLayout
393
RightAxisLayout = function(){};
395
RightAxisLayout.prototype = {
397
* Default margins for text fields.
400
* @method _getDefaultMargins
403
_getDefaultMargins: function()
414
* Sets the length of the tick on either side of the axis line.
416
* @method setTickOffset
419
setTickOffsets: function()
422
majorTicks = host.get("styles").majorTicks,
423
tickLength = majorTicks.length,
424
halfTick = tickLength * 0.5,
425
display = majorTicks.display;
426
host.set("topTickOffset", 0);
427
host.set("bottomTickOffset", 0);
432
host.set("leftTickOffset", tickLength);
433
host.set("rightTickOffset", 0);
436
host.set("leftTickOffset", 0);
437
host.set("rightTickOffset", tickLength);
440
host.set("rightTickOffset", halfTick);
441
host.set("leftTickOffset", halfTick);
444
host.set("leftTickOffset", 0);
445
host.set("rightTickOffset", 0);
454
* @param {Path} path reference to the path `Path` element in which to draw the tick.
455
* @param {Object} pt Point on the axis in which the tick will intersect.
456
* @param {Object) tickStyle Hash of properties to apply to the tick.
459
drawTick: function(path, pt, tickStyles)
462
style = host.get("styles"),
463
padding = style.padding,
464
tickLength = tickStyles.length,
465
start = {x:padding.left, y:pt.y},
466
end = {x:padding.left + tickLength, y:pt.y};
467
host.drawLine(path, start, end);
471
* Calculates the coordinates for the first point on an axis.
473
* @method getLineStart
477
getLineStart: function()
480
style = host.get("styles"),
481
padding = style.padding,
482
majorTicks = style.majorTicks,
483
tickLength = majorTicks.length,
484
display = majorTicks.display,
485
pt = {x:padding.left, y:padding.top};
486
if(display === "inside")
490
else if(display === "cross")
492
pt.x += tickLength/2;
498
* Calculates the point for a label.
500
* @method getLabelPoint
501
* @param {Object} point Point on the axis in which the tick will intersect.
505
getLabelPoint: function(point)
507
return {x:point.x + this.get("rightTickOffset"), y:point.y};
511
* Updates the value for the `maxLabelSize` for use in calculating total size.
513
* @method updateMaxLabelSize
514
* @param {HTMLElement} label to measure
517
updateMaxLabelSize: function(labelWidth, labelHeight)
520
props = this._labelRotationProps,
522
absRot = props.absRot,
523
sinRadians = props.sinRadians,
524
cosRadians = props.cosRadians,
530
else if(absRot === 90)
536
max = (cosRadians * labelWidth) + (sinRadians * labelHeight);
538
host._maxLabelSize = Math.max(host._maxLabelSize, max);
542
* Determines the available label width when the axis width has been explicitly set.
544
* @method getExplicitlySized
548
getExplicitlySized: function(styles)
550
if(this._explicitWidth)
553
w = host._explicitWidth,
554
totalTitleSize = this._totalTitleSize,
555
rightTickOffset = host.get("rightTickOffset"),
556
margin = styles.label.margin.right;
557
host._maxLabelSize = w - (rightTickOffset + margin + totalTitleSize);
564
* Rotate and position title.
566
* @method positionTitle
567
* @param {HTMLElement} label to rotate position
570
positionTitle: function(label)
573
bounds = host._titleBounds,
574
margin = host.get("styles").title.margin,
575
props = host._titleRotationProps,
576
labelWidth = label.offsetWidth,
577
labelHeight = label.offsetHeight,
578
w = bounds.right - bounds.left,
579
x = this.get("width") - (labelWidth * 0.5) - (w * 0.5),
580
y = (host.get("height") * 0.5) - (labelHeight * 0.5);
581
props.labelWidth = labelWidth;
582
props.labelHeight = labelHeight;
583
if(margin && margin.right)
589
props.transformOrigin = [0.5, 0.5];
590
host._rotate(label, props);
594
* Rotate and position labels.
596
* @method positionLabel
597
* @param {HTMLElement} label to rotate position
598
* @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
602
positionLabel: function(label, pt, styles, i)
605
tickOffset = host.get("rightTickOffset"),
606
labelStyles = styles.label,
610
props = this._labelRotationProps,
612
absRot = props.absRot,
613
labelWidth = this._labelWidths[i],
614
labelHeight = this._labelHeights[i];
615
if(labelStyles.margin && labelStyles.margin.left)
617
margin = labelStyles.margin.left;
621
topOffset -= labelHeight * 0.5;
625
leftOffset -= labelWidth * 0.5;
626
topOffset -= labelHeight;
630
leftOffset -= labelWidth * 0.5;
634
topOffset -= labelHeight * 0.5;
635
leftOffset += labelHeight/2 * absRot/90;
637
leftOffset += margin;
638
leftOffset += tickOffset;
639
props.labelWidth = labelWidth;
640
props.labelHeight = labelHeight;
641
props.x = Math.round(leftOffset);
642
props.y = Math.round(topOffset);
643
this._rotate(label, props);
647
* Adjusts the coordinates of an axis label based on the rotation.
649
* @method _setRotationCoords
650
* @param {Object} props Coordinates, dimension and rotation properties of the label.
653
_setRotationCoords: function(props)
656
absRot = props.absRot,
659
labelWidth = props.labelWidth,
660
labelHeight = props.labelHeight;
663
topOffset = labelHeight * 0.5;
667
leftOffset = labelWidth * 0.5;
668
topOffset = labelHeight;
672
leftOffset = labelWidth * 0.5;
676
topOffset = labelHeight * 0.5;
677
leftOffset = labelHeight/2 * absRot/90;
679
props.x -= leftOffset;
680
props.y -= topOffset;
684
* Returns the transformOrigin to use for an axis label based on the position of the axis
685
* and the rotation of the label.
687
* @method _getTransformOrigin
688
* @param {Number} rot The rotation (in degrees) of the label.
692
_getTransformOrigin: function(rot)
697
transformOrigin = [0, 0];
701
transformOrigin = [0.5, 1];
705
transformOrigin = [0.5, 0];
709
transformOrigin = [0, 0.5];
711
return transformOrigin;
715
* Adjusts position for inner ticks.
717
* @method offsetNodeForTick
718
* @param {Node} cb contentBox of the axis
721
offsetNodeForTick: function(cb)
724
tickOffset = host.get("leftTickOffset"),
725
offset = 0 - tickOffset;
726
cb.setStyle("left", offset);
730
* Assigns a height based on the size of the contents.
732
* @method setCalculatedSize
735
setCalculatedSize: function()
738
styles = host.get("styles"),
739
labelStyle = styles.label,
740
totalTitleSize = this._totalTitleSize,
741
ttl = Math.round(host.get("rightTickOffset") + host._maxLabelSize + totalTitleSize + labelStyle.margin.left);
742
if(this._explicitWidth)
744
ttl = this._explicitWidth;
746
host.set("calculatedWidth", ttl);
747
host.get("contentBox").setStyle("width", ttl);
751
Y.RightAxisLayout = RightAxisLayout;
753
* Contains algorithms for rendering a bottom axis.
755
* @class BottomAxisLayout
759
BottomAxisLayout = function(){};
761
BottomAxisLayout.prototype = {
763
* Default margins for text fields.
766
* @method _getDefaultMargins
769
_getDefaultMargins: function()
780
* Sets the length of the tick on either side of the axis line.
782
* @method setTickOffsets
785
setTickOffsets: function()
788
majorTicks = host.get("styles").majorTicks,
789
tickLength = majorTicks.length,
790
halfTick = tickLength * 0.5,
791
display = majorTicks.display;
792
host.set("leftTickOffset", 0);
793
host.set("rightTickOffset", 0);
798
host.set("topTickOffset", tickLength);
799
host.set("bottomTickOffset", 0);
802
host.set("topTickOffset", 0);
803
host.set("bottomTickOffset", tickLength);
806
host.set("topTickOffset", halfTick);
807
host.set("bottomTickOffset", halfTick);
810
host.set("topTickOffset", 0);
811
host.set("bottomTickOffset", 0);
817
* Calculates the coordinates for the first point on an axis.
819
* @method getLineStart
822
getLineStart: function()
824
var style = this.get("styles"),
825
padding = style.padding,
826
majorTicks = style.majorTicks,
827
tickLength = majorTicks.length,
828
display = majorTicks.display,
829
pt = {x:0, y:padding.top};
830
if(display === "inside")
834
else if(display === "cross")
836
pt.y += tickLength/2;
845
* @param {Path} path reference to the path `Path` element in which to draw the tick.
846
* @param {Object} pt hash containing x and y coordinates
847
* @param {Object} tickStyles hash of properties used to draw the tick
850
drawTick: function(path, pt, tickStyles)
853
style = host.get("styles"),
854
padding = style.padding,
855
tickLength = tickStyles.length,
856
start = {x:pt.x, y:padding.top},
857
end = {x:pt.x, y:tickLength + padding.top};
858
host.drawLine(path, start, end);
862
* Calculates the point for a label.
864
* @method getLabelPoint
865
* @param {Object} pt Object containing x and y coordinates
869
getLabelPoint: function(point)
871
return {x:point.x, y:point.y + this.get("bottomTickOffset")};
875
* Updates the value for the `maxLabelSize` for use in calculating total size.
877
* @method updateMaxLabelSize
878
* @param {HTMLElement} label to measure
881
updateMaxLabelSize: function(labelWidth, labelHeight)
884
props = this._labelRotationProps,
886
absRot = props.absRot,
887
sinRadians = props.sinRadians,
888
cosRadians = props.cosRadians,
894
else if(absRot === 90)
900
max = (sinRadians * labelWidth) + (cosRadians * labelHeight);
902
host._maxLabelSize = Math.max(host._maxLabelSize, max);
906
* Determines the available label height when the axis width has been explicitly set.
908
* @method getExplicitlySized
912
getExplicitlySized: function(styles)
914
if(this._explicitHeight)
917
h = host._explicitHeight,
918
totalTitleSize = host._totalTitleSize,
919
bottomTickOffset = host.get("bottomTickOffset"),
920
margin = styles.label.margin.right;
921
host._maxLabelSize = h - (bottomTickOffset + margin + totalTitleSize);
928
* Rotate and position title.
930
* @method positionTitle
931
* @param {HTMLElement} label to rotate position
934
positionTitle: function(label)
937
bounds = host._titleBounds,
938
margin = host.get("styles").title.margin,
939
props = host._titleRotationProps,
940
h = bounds.bottom - bounds.top,
941
labelWidth = label.offsetWidth,
942
labelHeight = label.offsetHeight,
943
x = (host.get("width") * 0.5) - (labelWidth * 0.5),
944
y = host.get("height") - labelHeight/2 - h/2;
945
props.labelWidth = labelWidth;
946
props.labelHeight = labelHeight;
947
if(margin && margin.bottom)
953
props.transformOrigin = [0.5, 0.5];
954
host._rotate(label, props);
958
* Rotate and position labels.
960
* @method positionLabel
961
* @param {HTMLElement} label to rotate position
962
* @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
966
positionLabel: function(label, pt, styles, i)
969
tickOffset = host.get("bottomTickOffset"),
970
labelStyles = styles.label,
972
props = host._labelRotationProps,
974
absRot = props.absRot,
975
leftOffset = Math.round(pt.x),
976
topOffset = Math.round(pt.y),
977
labelWidth = host._labelWidths[i],
978
labelHeight = host._labelHeights[i];
979
if(labelStyles.margin && labelStyles.margin.top)
981
margin = labelStyles.margin.top;
985
topOffset -= labelHeight/2 * rot/90;
989
leftOffset -= labelWidth;
990
topOffset -= labelHeight/2 * absRot/90;
994
leftOffset -= labelWidth * 0.5;
997
topOffset += tickOffset;
998
props.labelWidth = labelWidth;
999
props.labelHeight = labelHeight;
1000
props.x = leftOffset;
1001
props.y = topOffset;
1002
host._rotate(label, props);
1006
* Adjusts the coordinates of an axis label based on the rotation.
1008
* @method _setRotationCoords
1009
* @param {Object} props Coordinates, dimension and rotation properties of the label.
1012
_setRotationCoords: function(props)
1014
var rot = props.rot,
1015
absRot = props.absRot,
1016
labelWidth = props.labelWidth,
1017
labelHeight = props.labelHeight,
1024
topOffset = labelHeight/2 * rot/90;
1028
leftOffset = labelWidth;
1029
topOffset = labelHeight/2 * absRot/90;
1033
leftOffset = labelWidth * 0.5;
1036
props.x -= leftOffset;
1037
props.y -= topOffset;
1041
* Returns the transformOrigin to use for an axis label based on the position of the axis
1042
* and the rotation of the label.
1044
* @method _getTransformOrigin
1045
* @param {Number} rot The rotation (in degrees) of the label.
1049
_getTransformOrigin: function(rot)
1051
var transformOrigin;
1054
transformOrigin = [0, 0.5];
1058
transformOrigin = [1, 0.5];
1062
transformOrigin = [0, 0];
1064
return transformOrigin;
1068
* Adjusts position for inner ticks.
1070
* @method offsetNodeForTick
1071
* @param {Node} cb contentBox of the axis
1074
offsetNodeForTick: function(cb)
1077
cb.setStyle("top", 0 - host.get("topTickOffset"));
1081
* Assigns a height based on the size of the contents.
1083
* @method setCalculatedSize
1086
setCalculatedSize: function()
1089
styles = host.get("styles"),
1090
labelStyle = styles.label,
1091
totalTitleSize = host._totalTitleSize,
1092
ttl = Math.round(host.get("bottomTickOffset") + host._maxLabelSize + labelStyle.margin.top + totalTitleSize);
1093
if(host._explicitHeight)
1095
ttl = host._explicitHeight;
1097
host.set("calculatedHeight", ttl);
1100
Y.BottomAxisLayout = BottomAxisLayout;
1102
* Contains algorithms for rendering a top axis.
1104
* @class TopAxisLayout
1108
TopAxisLayout = function(){};
1110
TopAxisLayout.prototype = {
1112
* Default margins for text fields.
1115
* @method _getDefaultMargins
1118
_getDefaultMargins: function()
1129
* Sets the length of the tick on either side of the axis line.
1131
* @method setTickOffsets
1134
setTickOffsets: function()
1137
majorTicks = host.get("styles").majorTicks,
1138
tickLength = majorTicks.length,
1139
halfTick = tickLength * 0.5,
1140
display = majorTicks.display;
1141
host.set("leftTickOffset", 0);
1142
host.set("rightTickOffset", 0);
1146
host.set("bottomTickOffset", tickLength);
1147
host.set("topTickOffset", 0);
1150
host.set("bottomTickOffset", 0);
1151
host.set("topTickOffset", tickLength);
1154
host.set("topTickOffset", halfTick);
1155
host.set("bottomTickOffset", halfTick);
1158
host.set("topTickOffset", 0);
1159
host.set("bottomTickOffset", 0);
1165
* Calculates the coordinates for the first point on an axis.
1167
* @method getLineStart
1170
getLineStart: function()
1173
style = host.get("styles"),
1174
padding = style.padding,
1175
majorTicks = style.majorTicks,
1176
tickLength = majorTicks.length,
1177
display = majorTicks.display,
1178
pt = {x:0, y:padding.top};
1179
if(display === "outside")
1183
else if(display === "cross")
1185
pt.y += tickLength/2;
1194
* @param {Path} path reference to the path `Path` element in which to draw the tick.
1195
* @param {Object} pt hash containing x and y coordinates
1196
* @param {Object} tickStyles hash of properties used to draw the tick
1199
drawTick: function(path, pt, tickStyles)
1202
style = host.get("styles"),
1203
padding = style.padding,
1204
tickLength = tickStyles.length,
1205
start = {x:pt.x, y:padding.top},
1206
end = {x:pt.x, y:tickLength + padding.top};
1207
host.drawLine(path, start, end);
1211
* Calculates the point for a label.
1213
* @method getLabelPoint
1214
* @param {Object} pt hash containing x and y coordinates
1218
getLabelPoint: function(pt)
1220
return {x:pt.x, y:pt.y - this.get("topTickOffset")};
1224
* Updates the value for the `maxLabelSize` for use in calculating total size.
1226
* @method updateMaxLabelSize
1227
* @param {HTMLElement} label to measure
1230
updateMaxLabelSize: function(labelWidth, labelHeight)
1233
props = this._labelRotationProps,
1235
absRot = props.absRot,
1236
sinRadians = props.sinRadians,
1237
cosRadians = props.cosRadians,
1243
else if(absRot === 90)
1249
max = (sinRadians * labelWidth) + (cosRadians * labelHeight);
1251
host._maxLabelSize = Math.max(host._maxLabelSize, max);
1255
* Determines the available label height when the axis width has been explicitly set.
1257
* @method getExplicitlySized
1261
getExplicitlySized: function(styles)
1263
if(this._explicitHeight)
1266
h = host._explicitHeight,
1267
totalTitleSize = host._totalTitleSize,
1268
topTickOffset = host.get("topTickOffset"),
1269
margin = styles.label.margin.right;
1270
host._maxLabelSize = h - (topTickOffset + margin + totalTitleSize);
1277
* Rotate and position title.
1279
* @method positionTitle
1280
* @param {HTMLElement} label to rotate position
1283
positionTitle: function(label)
1286
bounds = host._titleBounds,
1287
margin = host.get("styles").title.margin,
1288
props = host._titleRotationProps,
1289
labelWidth = label.offsetWidth,
1290
labelHeight = label.offsetHeight,
1291
h = bounds.bottom - bounds.top,
1292
x = (host.get("width") * 0.5) - (labelWidth * 0.5),
1293
y = h/2 - labelHeight/2;
1294
props.labelWidth = labelWidth;
1295
props.labelHeight = labelHeight;
1296
if(margin && margin.top)
1302
props.transformOrigin = [0.5, 0.5];
1303
host._rotate(label, props);
1307
* Rotate and position labels.
1309
* @method positionLabel
1310
* @param {HTMLElement} label to rotate position
1311
* @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
1315
positionLabel: function(label, pt, styles, i)
1318
totalTitleSize = this._totalTitleSize,
1319
maxLabelSize = host._maxLabelSize,
1321
topOffset = pt.y + totalTitleSize + maxLabelSize,
1322
props = this._labelRotationProps,
1324
absRot = props.absRot,
1325
labelWidth = this._labelWidths[i],
1326
labelHeight = this._labelHeights[i];
1329
leftOffset -= labelWidth * 0.5;
1330
topOffset -= labelHeight;
1336
leftOffset -= labelWidth;
1337
topOffset -= (labelHeight * 0.5);
1339
else if (rot === -90)
1341
topOffset -= (labelHeight * 0.5);
1345
leftOffset -= labelWidth;
1346
topOffset -= labelHeight - (labelHeight * rot/180);
1350
topOffset -= labelHeight - (labelHeight * absRot/180);
1353
props.x = Math.round(leftOffset);
1354
props.y = Math.round(topOffset);
1355
props.labelWidth = labelWidth;
1356
props.labelHeight = labelHeight;
1357
this._rotate(label, props);
1361
* Adjusts the coordinates of an axis label based on the rotation.
1363
* @method _setRotationCoords
1364
* @param {Object} props Coordinates, dimension and rotation properties of the label.
1367
_setRotationCoords: function(props)
1369
var rot = props.rot,
1370
absRot = props.absRot,
1371
labelWidth = props.labelWidth,
1372
labelHeight = props.labelHeight,
1377
leftOffset = labelWidth * 0.5;
1378
topOffset = labelHeight;
1384
leftOffset = labelWidth;
1385
topOffset = (labelHeight * 0.5);
1387
else if (rot === -90)
1389
topOffset = (labelHeight * 0.5);
1393
leftOffset = labelWidth;
1394
topOffset = labelHeight - (labelHeight * rot/180);
1398
topOffset = labelHeight - (labelHeight * absRot/180);
1401
props.x -= leftOffset;
1402
props.y -= topOffset;
1406
* Returns the transformOrigin to use for an axis label based on the position of the axis
1407
* and the rotation of the label.
1409
* @method _getTransformOrigin
1410
* @param {Number} rot The rotation (in degrees) of the label.
1414
_getTransformOrigin: function(rot)
1416
var transformOrigin;
1419
transformOrigin = [0, 0];
1425
transformOrigin = [1, 0.5];
1427
else if (rot === -90)
1429
transformOrigin = [0, 0.5];
1433
transformOrigin = [1, 0.5];
1437
transformOrigin = [0, 0.5];
1440
return transformOrigin;
1444
* Adjusts position for inner ticks.
1446
* @method offsetNodeForTick
1447
* @param {Node} cb contentBox of the axis
1450
offsetNodeForTick: function()
1455
* Assigns a height based on the size of the contents.
1457
* @method setCalculatedSize
1460
setCalculatedSize: function()
1463
graphic = host.get("graphic"),
1464
styles = host.get("styles"),
1465
labelMargin = styles.label.margin,
1466
totalLabelSize = labelMargin.bottom + host._maxLabelSize,
1467
totalTitleSize = host._totalTitleSize,
1468
topTickOffset = this.get("topTickOffset"),
1469
ttl = Math.round(topTickOffset + totalLabelSize + totalTitleSize);
1470
if(this._explicitHeight)
1472
ttl = this._explicitHeight;
1474
host.set("calculatedHeight", ttl);
1475
graphic.set("y", ttl - topTickOffset);
1478
Y.TopAxisLayout = TopAxisLayout;
1481
* An abstract class that provides the core functionality for draw a chart axis. Axis is used by the following classes:
1483
* <li>{{#crossLink "CategoryAxis"}}{{/crossLink}}</li>
1484
* <li>{{#crossLink "NumericAxis"}}{{/crossLink}}</li>
1485
* <li>{{#crossLink "StackedAxis"}}{{/crossLink}}</li>
1486
* <li>{{#crossLink "TimeAxis"}}{{/crossLink}}</li>
1492
* @uses TopAxisLayout
1493
* @uses RightAxisLayout
1494
* @uses BottomAxisLayout
1495
* @uses LeftAxisLayout
1497
* @param {Object} config (optional) Configuration parameters.
1500
Y.Axis = Y.Base.create("axis", Y.Widget, [Y.AxisBase], {
1502
* Calculates and returns a value based on the number of labels and the index of
1503
* the current label.
1505
* @method getLabelByIndex
1506
* @param {Number} i Index of the label.
1507
* @param {Number} l Total number of labels.
1510
getLabelByIndex: function(i, l)
1512
var position = this.get("position"),
1513
direction = position === "left" || position === "right" ? "vertical" : "horizontal";
1514
return this._getLabelByIndex(i, l, direction);
1523
this.after("dataReady", Y.bind(this._dataChangeHandler, this));
1524
this.after("dataUpdate", Y.bind(this._dataChangeHandler, this));
1525
this.after("stylesChange", this._updateHandler);
1526
this.after("overlapGraphChange", this._updateHandler);
1527
this.after("positionChange", this._positionChangeHandler);
1528
this.after("widthChange", this._handleSizeChange);
1529
this.after("heightChange", this._handleSizeChange);
1530
this.after("calculatedWidthChange", this._handleSizeChange);
1531
this.after("calculatedHeightChange", this._handleSizeChange);
1534
* Storage for calculatedWidth value.
1536
* @property _calculatedWidth
1540
_calculatedWidth: 0,
1543
* Storage for calculatedHeight value.
1545
* @property _calculatedHeight
1549
_calculatedHeight: 0,
1552
* Handles change to the dataProvider
1554
* @method _dataChangeHandler
1555
* @param {Object} e Event object
1558
_dataChangeHandler: function()
1560
if(this.get("rendered"))
1567
* Handles change to the position attribute
1569
* @method _positionChangeHandler
1570
* @param {Object} e Event object
1573
_positionChangeHandler: function(e)
1575
this._updateGraphic(e.newVal);
1576
this._updateHandler();
1580
* Updates the the Graphic instance
1582
* @method _updateGraphic
1583
* @param {String} position Position of axis
1586
_updateGraphic: function(position)
1588
var graphic = this.get("graphic");
1589
if(position === "none")
1606
* Handles changes to axis.
1608
* @method _updateHandler
1609
* @param {Object} e Event object
1612
_updateHandler: function()
1614
if(this.get("rendered"))
1624
renderUI: function()
1626
this._updateGraphic(this.get("position"));
1635
var layout = this._layout,
1643
defaultMargins = layout._getDefaultMargins();
1644
styles = this.get("styles");
1645
label = styles.label.margin;
1646
title =styles.title.margin;
1647
//need to defaultMargins method to the layout classes.
1648
for(i in defaultMargins)
1650
if(defaultMargins.hasOwnProperty(i))
1652
label[i] = label[i] === undefined ? defaultMargins[i] : label[i];
1653
title[i] = title[i] === undefined ? defaultMargins[i] : title[i];
1661
* Creates a graphic instance to be used for the axis line and ticks.
1663
* @method _setCanvas
1666
_setCanvas: function()
1668
var cb = this.get("contentBox"),
1669
bb = this.get("boundingBox"),
1670
p = this.get("position"),
1671
pn = this._parentNode,
1672
w = this.get("width"),
1673
h = this.get("height");
1674
bb.setStyle("position", "absolute");
1675
bb.setStyle("zIndex", 2);
1676
w = w ? w + "px" : pn.getStyle("width");
1677
h = h ? h + "px" : pn.getStyle("height");
1678
if(p === "top" || p === "bottom")
1680
cb.setStyle("width", w);
1684
cb.setStyle("height", h);
1686
cb.setStyle("position", "relative");
1687
cb.setStyle("left", "0px");
1688
cb.setStyle("top", "0px");
1689
this.set("graphic", new Y.Graphic());
1690
this.get("graphic").render(cb);
1694
* Gets the default value for the `styles` attribute. Overrides
1695
* base implementation.
1697
* @method _getDefaultStyles
1701
_getDefaultStyles: function()
1723
determinant:"count",
1747
rotation: undefined,
1755
hideOverlappingLabelTicks: false
1758
return Y.merge(Y.Renderer.prototype._getDefaultStyles(), axisstyles);
1762
* Updates the axis when the size changes.
1764
* @method _handleSizeChange
1765
* @param {Object} e Event object.
1768
_handleSizeChange: function(e)
1770
var attrName = e.attrName,
1771
pos = this.get("position"),
1772
vert = pos === "left" || pos === "right",
1773
cb = this.get("contentBox"),
1774
hor = pos === "bottom" || pos === "top";
1775
cb.setStyle("width", this.get("width"));
1776
cb.setStyle("height", this.get("height"));
1777
if((hor && attrName === "width") || (vert && attrName === "height"))
1784
* Maps key values to classes containing layout algorithms
1786
* @property _layoutClasses
1792
top : TopAxisLayout,
1793
bottom: BottomAxisLayout,
1794
left: LeftAxisLayout,
1795
right : RightAxisLayout
1799
* Draws a line segment between 2 points
1802
* @param {Object} startPoint x and y coordinates for the start point of the line segment
1803
* @param {Object} endPoint x and y coordinates for the for the end point of the line segment
1804
* @param {Object} line styles (weight, color and alpha to be applied to the line segment)
1807
drawLine: function(path, startPoint, endPoint)
1809
path.moveTo(startPoint.x, startPoint.y);
1810
path.lineTo(endPoint.x, endPoint.y);
1814
* Generates the properties necessary for rotating and positioning a text field.
1816
* @method _getTextRotationProps
1817
* @param {Object} styles properties for the text field
1821
_getTextRotationProps: function(styles)
1823
if(styles.rotation === undefined)
1825
switch(this.get("position"))
1828
styles.rotation = -90;
1831
styles.rotation = 90;
1834
styles.rotation = 0;
1838
var rot = Math.min(90, Math.max(-90, styles.rotation)),
1839
absRot = Math.abs(rot),
1840
radCon = Math.PI/180,
1841
sinRadians = parseFloat(parseFloat(Math.sin(absRot * radCon)).toFixed(8)),
1842
cosRadians = parseFloat(parseFloat(Math.cos(absRot * radCon)).toFixed(8));
1847
sinRadians: sinRadians,
1848
cosRadians: cosRadians,
1849
textAlpha: styles.alpha
1859
_drawAxis: function ()
1863
this._callLater = true;
1866
this._drawing = true;
1867
this._callLater = false;
1870
var styles = this.get("styles"),
1872
labelStyles = styles.label,
1873
majorTickStyles = styles.majorTicks,
1874
drawTicks = majorTickStyles.display !== "none",
1877
layout = this._layout,
1883
labelFunction = this.get("labelFunction"),
1884
labelFunctionScope = this.get("labelFunctionScope"),
1885
labelFormat = this.get("labelFormat"),
1886
graphic = this.get("graphic"),
1887
path = this.get("path"),
1890
position = this.get("position"),
1898
explicitLabels = this._labelValuesExplicitlySet ? this.get("labelValues") : null,
1899
direction = (position === "left" || position === "right") ? "vertical" : "horizontal";
1900
this._labelWidths = [];
1901
this._labelHeights = [];
1902
graphic.set("autoDraw", false);
1904
path.set("stroke", {
1905
weight: line.weight,
1909
this._labelRotationProps = this._getTextRotationProps(labelStyles);
1910
this._labelRotationProps.transformOrigin = layout._getTransformOrigin(this._labelRotationProps.rot);
1911
layout.setTickOffsets.apply(this);
1912
layoutLength = this.getLength();
1914
len = this.getTotalMajorUnits();
1915
edgeOffset = this.getEdgeOffset(len, layoutLength);
1916
this.set("edgeOffset", edgeOffset);
1917
lineStart = layout.getLineStart.apply(this);
1919
if(direction === "vertical")
1930
labelData = this._getLabelData(
1931
lineStart[staticCoord],
1934
this.get("minimum"),
1935
this.get("maximum"),
1937
layoutLength - edgeOffset - edgeOffset,
1942
points = labelData.points;
1943
labelValues = labelData.values;
1944
len = points.length;
1945
if(!this._labelValuesExplicitlySet)
1947
this.set("labelValues", labelValues, {src: "internal"});
1950
//Don't create the last label or tick.
1951
if(this.get("hideFirstMajorUnit"))
1954
labelValues.shift();
1958
//Don't create the last label or tick.
1959
if(this.get("hideLastMajorUnit"))
1968
this._clearLabelCache();
1972
this.drawLine(path, lineStart, this.getLineEnd(lineStart));
1975
tickPath = this.get("tickPath");
1977
tickPath.set("stroke", {
1978
weight: majorTickStyles.weight,
1979
color: majorTickStyles.color,
1980
opacity: majorTickStyles.alpha
1982
for(i = 0; i < len; i = i + 1)
1987
layout.drawTick.apply(this, [tickPath, points[i], majorTickStyles]);
1991
this._createLabelCache();
1992
this._tickPoints = points;
1993
this._maxLabelSize = 0;
1994
this._totalTitleSize = 0;
1995
this._titleSize = 0;
1997
explicitlySized = layout.getExplicitlySized.apply(this, [styles]);
1998
for(i = 0; i < len; i = i + 1)
2003
label = this.getLabel(point, labelStyles);
2004
this._labels.push(label);
2005
this.get("appendLabelFunction")(label, labelFunction.apply(labelFunctionScope, [labelValues[i], labelFormat]));
2006
labelWidth = Math.round(label.offsetWidth);
2007
labelHeight = Math.round(label.offsetHeight);
2008
if(!explicitlySized)
2010
this._layout.updateMaxLabelSize.apply(this, [labelWidth, labelHeight]);
2012
this._labelWidths.push(labelWidth);
2013
this._labelHeights.push(labelHeight);
2016
this._clearLabelCache();
2017
if(this.get("overlapGraph"))
2019
layout.offsetNodeForTick.apply(this, [this.get("contentBox")]);
2021
layout.setCalculatedSize.apply(this);
2022
if(this._titleTextField)
2024
this._layout.positionTitle.apply(this, [this._titleTextField]);
2026
len = this._labels.length;
2027
for(i = 0; i < len; ++i)
2029
layout.positionLabel.apply(this, [this.get("labels")[i], this._tickPoints[i], styles, i]);
2033
this._drawing = false;
2040
this._updatePathElement();
2041
this.fire("axisRendered");
2046
* Calculates and sets the total size of a title.
2048
* @method _setTotalTitleSize
2049
* @param {Object} styles Properties for the title field.
2052
_setTotalTitleSize: function(styles)
2054
var title = this._titleTextField,
2055
w = title.offsetWidth,
2056
h = title.offsetHeight,
2057
rot = this._titleRotationProps.rot,
2060
margin = styles.margin,
2061
position = this.get("position"),
2062
matrix = new Y.Matrix();
2064
bounds = matrix.getContentRect(w, h);
2065
if(position === "left" || position === "right")
2067
size = bounds.right - bounds.left;
2070
size += margin.left + margin.right;
2075
size = bounds.bottom - bounds.top;
2078
size += margin.top + margin.bottom;
2081
this._titleBounds = bounds;
2082
this._totalTitleSize = size;
2088
* @method _updatePathElement
2091
_updatePathElement: function()
2093
var path = this._path,
2094
tickPath = this._tickPath,
2095
redrawGraphic = false,
2096
graphic = this.get("graphic");
2099
redrawGraphic = true;
2104
redrawGraphic = true;
2114
* Updates the content and style properties for a title field.
2116
* @method _updateTitle
2119
_setTitle: function()
2124
title = this.get("title"),
2125
titleTextField = this._titleTextField,
2127
if(title !== null && title !== undefined)
2130
rotation: "rotation",
2134
styles = this.get("styles").title;
2137
titleTextField = DOCUMENT.createElement('span');
2138
titleTextField.style.display = "block";
2139
titleTextField.style.whiteSpace = "nowrap";
2140
titleTextField.setAttribute("class", "axisTitle");
2141
this.get("contentBox").append(titleTextField);
2143
else if(!DOCUMENT.createElementNS)
2145
if(titleTextField.style.filter)
2147
titleTextField.style.filter = null;
2150
titleTextField.style.position = "absolute";
2153
if(styles.hasOwnProperty(i) && !customStyles.hasOwnProperty(i))
2155
titleTextField.style[i] = styles[i];
2158
this.get("appendTitleFunction")(titleTextField, title);
2159
this._titleTextField = titleTextField;
2160
this._titleRotationProps = this._getTextRotationProps(styles);
2161
this._setTotalTitleSize(styles);
2163
else if(titleTextField)
2165
parentNode = titleTextField.parentNode;
2168
parentNode.removeChild(titleTextField);
2170
this._titleTextField = null;
2171
this._totalTitleSize = 0;
2176
* Creates or updates an axis label.
2179
* @param {Object} pt x and y coordinates for the label
2180
* @param {Object} styles styles applied to label
2181
* @return HTMLElement
2184
getLabel: function(pt, styles)
2188
labelCache = this._labelCache,
2190
rotation: "rotation",
2194
if(labelCache && labelCache.length > 0)
2196
label = labelCache.shift();
2200
label = DOCUMENT.createElement("span");
2201
label.className = Y.Lang.trim([label.className, "axisLabel"].join(' '));
2202
this.get("contentBox").append(label);
2204
if(!DOCUMENT.createElementNS)
2206
if(label.style.filter)
2208
label.style.filter = null;
2211
label.style.display = "block";
2212
label.style.whiteSpace = "nowrap";
2213
label.style.position = "absolute";
2216
if(styles.hasOwnProperty(i) && !customStyles.hasOwnProperty(i))
2218
label.style[i] = styles[i];
2225
* Creates a cache of labels that can be re-used when the axis redraws.
2227
* @method _createLabelCache
2230
_createLabelCache: function()
2234
while(this._labels.length > 0)
2236
this._labelCache.push(this._labels.shift());
2241
this._clearLabelCache();
2247
* Removes axis labels from the dom and clears the label cache.
2249
* @method _clearLabelCache
2252
_clearLabelCache: function()
2254
if(this._labelCache)
2256
var len = this._labelCache.length,
2261
label = this._labelCache[i];
2262
this._removeChildren(label);
2263
Y.Event.purgeElement(label, true);
2264
label.parentNode.removeChild(label);
2267
this._labelCache = [];
2271
* Gets the end point of an axis.
2273
* @method getLineEnd
2277
getLineEnd: function(pt)
2279
var w = this.get("width"),
2280
h = this.get("height"),
2281
pos = this.get("position");
2282
if(pos === "top" || pos === "bottom")
2284
return {x:w, y:pt.y};
2288
return {x:pt.x, y:h};
2293
* Calcuates the width or height of an axis depending on its direction.
2299
getLength: function()
2302
style = this.get("styles"),
2303
padding = style.padding,
2304
w = this.get("width"),
2305
h = this.get("height"),
2306
pos = this.get("position");
2307
if(pos === "top" || pos === "bottom")
2309
l = w - (padding.left + padding.right);
2313
l = h - (padding.top + padding.bottom);
2319
* Gets the position of the first point on an axis.
2321
* @method getFirstPoint
2322
* @param {Object} pt Object containing x and y coordinates.
2326
getFirstPoint:function(pt)
2328
var style = this.get("styles"),
2329
pos = this.get("position"),
2330
padding = style.padding,
2331
np = {x:pt.x, y:pt.y};
2332
if(pos === "top" || pos === "bottom")
2334
np.x += padding.left + this.get("edgeOffset");
2338
np.y += this.get("height") - (padding.top + this.get("edgeOffset"));
2344
* Rotates and positions a text field.
2347
* @param {HTMLElement} label text field to rotate and position
2348
* @param {Object} props properties to be applied to the text field.
2351
_rotate: function(label, props)
2353
var rot = props.rot,
2358
matrix = new Y.Matrix(),
2359
transformOrigin = props.transformOrigin || [0, 0],
2361
if(DOCUMENT.createElementNS)
2363
matrix.translate(x, y);
2365
Y_DOM.setStyle(label, "transformOrigin", (transformOrigin[0] * 100) + "% " + (transformOrigin[1] * 100) + "%");
2366
Y_DOM.setStyle(label, "transform", matrix.toCSSText());
2370
textAlpha = props.textAlpha;
2371
if(Y_Lang.isNumber(textAlpha) && textAlpha < 1 && textAlpha > -1 && !isNaN(textAlpha))
2373
filterString = "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + Math.round(textAlpha * 100) + ")";
2377
//ms filters kind of, sort of uses a transformOrigin of 0, 0.
2378
//we'll translate the difference to create a true 0, 0 origin.
2380
offsetRect = matrix.getContentRect(props.labelWidth, props.labelHeight);
2382
matrix.translate(offsetRect.left, offsetRect.top);
2383
matrix.translate(x, y);
2384
this._simulateRotateWithTransformOrigin(matrix, rot, transformOrigin, props.labelWidth, props.labelHeight);
2387
filterString += " ";
2393
filterString += matrix.toFilterText();
2394
label.style.left = matrix.dx + "px";
2395
label.style.top = matrix.dy + "px";
2399
label.style.left = x + "px";
2400
label.style.top = y + "px";
2404
label.style.filter = filterString;
2410
* Simulates a rotation with a specified transformOrigin.
2412
* @method _simulateTransformOrigin
2413
* @param {Matrix} matrix Reference to a `Matrix` instance.
2414
* @param {Number} rot The rotation (in degrees) that will be performed on a matrix.
2415
* @param {Array} transformOrigin An array represeniting the origin in which to perform the transform. The first
2416
* index represents the x origin and the second index represents the y origin.
2417
* @param {Number} w The width of the object that will be transformed.
2418
* @param {Number} h The height of the object that will be transformed.
2421
_simulateRotateWithTransformOrigin: function(matrix, rot, transformOrigin, w, h)
2423
var transformX = transformOrigin[0] * w,
2424
transformY = transformOrigin[1] * h;
2425
transformX = !isNaN(transformX) ? transformX : 0;
2426
transformY = !isNaN(transformY) ? transformY : 0;
2427
matrix.translate(transformX, transformY);
2429
matrix.translate(-transformX, -transformY);
2433
* Returns the coordinates (top, right, bottom, left) for the bounding box of the last label.
2435
* @method getMaxLabelBounds
2438
getMaxLabelBounds: function()
2440
return this._getLabelBounds(this.getMaximumValue());
2444
* Returns the coordinates (top, right, bottom, left) for the bounding box of the first label.
2446
* @method getMinLabelBounds
2449
getMinLabelBounds: function()
2451
return this._getLabelBounds(this.getMinimumValue());
2455
* Returns the coordinates (top, right, bottom, left) for the bounding box of a label.
2457
* @method _getLabelBounds
2458
* @param {String} Value of the label
2462
_getLabelBounds: function(val)
2464
var layout = this._layout,
2465
labelStyles = this.get("styles").label,
2466
matrix = new Y.Matrix(),
2468
props = this._getTextRotationProps(labelStyles);
2469
props.transformOrigin = layout._getTransformOrigin(props.rot);
2470
label = this.getLabel({x: 0, y: 0}, labelStyles);
2471
this.get("appendLabelFunction")(label, this.get("labelFunction").apply(this, [val, this.get("labelFormat")]));
2472
props.labelWidth = label.offsetWidth;
2473
props.labelHeight = label.offsetHeight;
2474
this._removeChildren(label);
2475
Y.Event.purgeElement(label, true);
2476
label.parentNode.removeChild(label);
2479
layout._setRotationCoords(props);
2480
matrix.translate(props.x, props.y);
2481
this._simulateRotateWithTransformOrigin(matrix, props.rot, props.transformOrigin, props.labelWidth, props.labelHeight);
2482
return matrix.getContentRect(props.labelWidth, props.labelHeight);
2486
* Removes all DOM elements from an HTML element. Used to clear out labels during detruction
2489
* @method _removeChildren
2492
_removeChildren: function(node)
2494
if(node.hasChildNodes())
2497
while(node.firstChild)
2499
child = node.firstChild;
2500
this._removeChildren(child);
2501
node.removeChild(child);
2507
* Destructor implementation Axis class. Removes all labels and the Graphic instance from the widget.
2509
* @method destructor
2512
destructor: function()
2514
var cb = this.get("contentBox").getDOMNode(),
2515
labels = this.get("labels"),
2516
graphic = this.get("graphic"),
2518
len = labels ? labels.length : 0;
2521
while(labels.length > 0)
2523
label = labels.shift();
2524
this._removeChildren(label);
2525
cb.removeChild(label);
2536
* Length in pixels of largest text bounding box. Used to calculate the height of the axis.
2538
* @property maxLabelSize
2545
* Updates the content of text field. This method writes a value into a text field using
2546
* `appendChild`. If the value is a `String`, it is converted to a `TextNode` first.
2549
* @param label {HTMLElement} label to be updated
2550
* @param val {String} value with which to update the label
2553
_setText: function(textField, val)
2555
textField.innerHTML = "";
2556
if(Y_Lang.isNumber(val))
2566
val = DOCUMENT.createTextNode(val);
2568
textField.appendChild(val);
2572
* Returns the total number of majorUnits that will appear on an axis.
2574
* @method getTotalMajorUnits
2577
getTotalMajorUnits: function()
2580
majorUnit = this.get("styles").majorUnit,
2582
if(majorUnit.determinant === "count")
2584
units = majorUnit.count;
2586
else if(majorUnit.determinant === "distance")
2588
len = this.getLength();
2589
units = (len/majorUnit.distance) + 1;
2595
* Returns the distance between major units on an axis.
2597
* @method getMajorUnitDistance
2598
* @param {Number} len Number of ticks
2599
* @param {Number} uiLen Size of the axis.
2600
* @param {Object} majorUnit Hash of properties used to determine the majorUnit
2603
getMajorUnitDistance: function(len, uiLen, majorUnit)
2606
if(majorUnit.determinant === "count")
2608
if(!this.get("calculateEdgeOffset"))
2614
else if(majorUnit.determinant === "distance")
2616
dist = majorUnit.distance;
2622
* Checks to see if data extends beyond the range of the axis. If so,
2623
* that data will need to be hidden. This method is internal, temporary and subject
2624
* to removal in the future.
2626
* @method _hasDataOverflow
2630
_hasDataOverflow: function()
2632
if(this.get("setMin") || this.get("setMax"))
2640
* Returns a string corresponding to the first label on an
2643
* @method getMinimumValue
2646
getMinimumValue: function()
2648
return this.get("minimum");
2652
* Returns a string corresponding to the last label on an
2655
* @method getMaximumValue
2658
getMaximumValue: function()
2660
return this.get("maximum");
2666
* When set, defines the width of a vertical axis instance. By default, vertical axes automatically size based
2667
* on their contents. When the width attribute is set, the axis will not calculate its width. When the width
2668
* attribute is explicitly set, axis labels will postion themselves off of the the inner edge of the axis and the
2669
* title, if present, will position itself off of the outer edge. If a specified width is less than the sum of
2670
* the axis' contents, excess content will overflow.
2680
if(this._explicitWidth)
2682
return this._explicitWidth;
2684
return this._calculatedWidth;
2687
setter: function(val)
2689
this._explicitWidth = val;
2695
* When set, defines the height of a horizontal axis instance. By default, horizontal axes automatically size based
2696
* on their contents. When the height attribute is set, the axis will not calculate its height. When the height
2697
* attribute is explicitly set, axis labels will postion themselves off of the the inner edge of the axis and the
2698
* title, if present, will position itself off of the outer edge. If a specified height is less than the sum of
2699
* the axis' contents, excess content will overflow.
2709
if(this._explicitHeight)
2711
return this._explicitHeight;
2713
return this._calculatedHeight;
2716
setter: function(val)
2718
this._explicitHeight = val;
2724
* Calculated value of an axis' width. By default, the value is used internally for vertical axes. If the `width`
2725
* attribute is explicitly set, this value will be ignored.
2727
* @attribute calculatedWidth
2734
return this._calculatedWidth;
2737
setter: function(val)
2739
this._calculatedWidth = val;
2745
* Calculated value of an axis' height. By default, the value is used internally for horizontal axes. If the `height`
2746
* attribute is explicitly set, this value will be ignored.
2748
* @attribute calculatedHeight
2755
return this._calculatedHeight;
2758
setter: function(val)
2760
this._calculatedHeight = val;
2766
* Difference between the first/last tick and edge of axis.
2768
* @attribute edgeOffset
2778
* The graphic in which the axis line and ticks will be rendered.
2780
* @attribute graphic
2798
var graphic = this.get("graphic");
2801
this._path = graphic.addShape({type:"path"});
2809
* @attribute tickPath
2821
var graphic = this.get("graphic");
2824
this._tickPath = graphic.addShape({type:"path"});
2827
return this._tickPath;
2832
* Contains the contents of the axis.
2840
* Direction of the axis.
2842
* @attribute position
2848
setter: function(val)
2850
var LayoutClass = this._layoutClasses[val];
2851
if(val && val !== "none")
2853
this._layout = new LayoutClass();
2860
* Distance determined by the tick styles used to calculate the distance between the axis
2861
* line in relation to the top of the axis.
2863
* @attribute topTickOffset
2871
* Distance determined by the tick styles used to calculate the distance between the axis
2872
* line in relation to the bottom of the axis.
2874
* @attribute bottomTickOffset
2882
* Distance determined by the tick styles used to calculate the distance between the axis
2883
* line in relation to the left of the axis.
2885
* @attribute leftTickOffset
2893
* Distance determined by the tick styles used to calculate the distance between the axis
2894
* line in relation to the right side of the axis.
2896
* @attribute rightTickOffset
2904
* Collection of labels used to render the axis.
2913
return this._labels;
2918
* Collection of points used for placement of labels and ticks along the axis.
2920
* @attribute tickPoints
2928
if(this.get("position") === "none")
2930
return this.get("styles").majorUnit.count;
2932
return this._tickPoints;
2937
* Indicates whether the axis overlaps the graph. If an axis is the inner most axis on a given
2938
* position and the tick position is inside or cross, the axis will need to overlap the graph.
2940
* @attribute overlapGraph
2946
validator: function(val)
2948
return Y_Lang.isBoolean(val);
2953
* Length in pixels of largest text bounding box. Used to calculate the height of the axis.
2955
* @attribute maxLabelSize
2962
return this._maxLabelSize;
2965
setter: function(val)
2967
this._maxLabelSize = val;
2973
* Title for the axis. When specified, the title will display. The position of the title is determined by the axis position.
2975
* <dt>top</dt><dd>Appears above the axis and it labels. The default rotation is 0.</dd>
2976
* <dt>right</dt><dd>Appears to the right of the axis and its labels. The default rotation is 90.</dd>
2977
* <dt>bottom</dt><dd>Appears below the axis and its labels. The default rotation is 0.</dd>
2978
* <dt>left</dt><dd>Appears to the left of the axis and its labels. The default rotation is -90.</dd>
2989
* Function used to append an axis value to an axis label. This function has the following signature:
2991
* <dt>textField</dt><dd>The axis label to be appended. (`HTMLElement`)</dd>
2992
* <dt>val</dt><dd>The value to attach to the text field. This method will accept an `HTMLELement`
2993
* or a `String`. This method does not use (`HTMLElement` | `String`)</dd>
2995
* The default method appends a value to the `HTMLElement` using the `appendChild` method. If the given
2996
* value is a `String`, the method will convert the the value to a `textNode` before appending to the
2997
* `HTMLElement`. This method will not convert an `HTMLString` to an `HTMLElement`.
2999
* @attribute appendLabelFunction
3002
appendLabelFunction: {
3005
return this._setText;
3010
* Function used to append a title value to the title object. This function has the following signature:
3012
* <dt>textField</dt><dd>The title text field to be appended. (`HTMLElement`)</dd>
3013
* <dt>val</dt><dd>The value to attach to the text field. This method will accept an `HTMLELement`
3014
* or a `String`. This method does not use (`HTMLElement` | `String`)</dd>
3016
* The default method appends a value to the `HTMLElement` using the `appendChild` method. If the given
3017
* value is a `String`, the method will convert the the value to a `textNode` before appending to the
3018
* `HTMLElement` element. This method will not convert an `HTMLString` to an `HTMLElement`.
3020
* @attribute appendTitleFunction
3023
appendTitleFunction: {
3026
return this._setText;
3031
* An array containing the unformatted values of the axis labels. By default, TimeAxis, NumericAxis and
3032
* StackedAxis labelValues are determined by the majorUnit style. By default, CategoryAxis labels are
3033
* determined by the values of the dataProvider.
3034
* <p>When the labelValues attribute is explicitly set, the labelValues are dictated by the set value and
3035
* the position of ticks and labels are determined by where those values would fall on the axis. </p>
3037
* @attribute labelValues
3043
setter: function(val)
3045
var opts = arguments[2];
3046
if(!val || (opts && opts.src && opts.src === "internal"))
3048
this._labelValuesExplicitlySet = false;
3052
this._labelValuesExplicitlySet = true;
3059
* Suppresses the creation of the the first visible label and tick.
3061
* @attribute hideFirstMajorUnit
3064
hideFirstMajorUnit: {
3069
* Suppresses the creation of the the last visible label and tick.
3071
* @attribute hideLastMajorUnit
3074
hideLastMajorUnit: {
3079
* Style properties used for drawing an axis. This attribute is inherited from `Renderer`. Below are the default values:
3081
* <dt>majorTicks</dt><dd>Properties used for drawing ticks.
3083
* <dt>display</dt><dd>Position of the tick. Possible values are `inside`, `outside`, `cross` and `none`.
3084
* The default value is `inside`.</dd>
3085
* <dt>length</dt><dd>The length (in pixels) of the tick. The default value is 4.</dd>
3086
* <dt>color</dt><dd>The color of the tick. The default value is `#dad8c9`</dd>
3087
* <dt>weight</dt><dd>Number indicating the width of the tick. The default value is 1.</dd>
3088
* <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the tick. The default value is 1.</dd>
3091
* <dt>line</dt><dd>Properties used for drawing the axis line.
3093
* <dt>weight</dt><dd>Number indicating the width of the axis line. The default value is 1.</dd>
3094
* <dt>color</dt><dd>The color of the axis line. The default value is `#dad8c9`.</dd>
3095
* <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the tick. The default value is 1.</dd>
3098
* <dt>majorUnit</dt><dd>Properties used to calculate the `majorUnit` for the axis.
3100
* <dt>determinant</dt><dd>The algorithm used for calculating distance between ticks. The possible options are
3101
* `count` and `distance`. If the `determinant` is `count`, the axis ticks will spaced so that a specified number
3102
* of ticks appear on the axis. If the `determinant` is `distance`, the axis ticks will spaced out according to
3103
* the specified distance. The default value is `count`.</dd>
3104
* <dt>count</dt><dd>Number of ticks to appear on the axis when the `determinant` is `count`. The default value is 11.</dd>
3105
* <dt>distance</dt><dd>The distance (in pixels) between ticks when the `determinant` is `distance`. The default
3109
* <dt>label</dt><dd>Properties and styles applied to the axis labels.
3111
* <dt>color</dt><dd>The color of the labels. The default value is `#808080`.</dd>
3112
* <dt>alpha</dt><dd>Number between 0 and 1 indicating the opacity of the labels. The default value is 1.</dd>
3113
* <dt>fontSize</dt><dd>The font-size of the labels. The default value is 85%</dd>
3114
* <dt>rotation</dt><dd>The rotation, in degrees (between -90 and 90) of the labels. The default value is 0.</dd>
3115
* <dt>margin</dt><dd>The distance between the label and the axis/tick. Depending on the position of the `Axis`,
3116
* only one of the properties used.
3118
* <dt>top</dt><dd>Pixel value used for an axis with a `position` of `bottom`. The default value is 4.</dd>
3119
* <dt>right</dt><dd>Pixel value used for an axis with a `position` of `left`. The default value is 4.</dd>
3120
* <dt>bottom</dt><dd>Pixel value used for an axis with a `position` of `top`. The default value is 4.</dd>
3121
* <dt>left</dt><dd>Pixel value used for an axis with a `position` of `right`. The default value is 4.</dd>
3133
Y.AxisType = Y.Base.create("baseAxis", Y.Axis, [], {});
3136
}, '3.13.0', {"requires": ["dom", "widget", "widget-position", "widget-stack", "graphics", "axis-base"]});