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"]});