--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.10.3/build/axis/axis-debug.js Tue Jul 16 14:29:46 2013 +0200
@@ -0,0 +1,3177 @@
+/*
+YUI 3.10.3 (build 2fb5187)
+Copyright 2013 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+
+YUI.add('axis', function (Y, NAME) {
+
+/**
+ * Provides base functionality for drawing chart axes.
+ *
+ * @module charts
+ * @submodule axis
+ */
+var CONFIG = Y.config,
+ DOCUMENT = CONFIG.doc,
+ Y_Lang = Y.Lang,
+ IS_STRING = Y_Lang.isString,
+ Y_DOM = Y.DOM,
+ LeftAxisLayout,
+ RightAxisLayout,
+ BottomAxisLayout,
+ TopAxisLayout;
+/**
+ * Algorithmic strategy for rendering a left axis.
+ *
+ * @class LeftAxisLayout
+ * @constructor
+ * @submodule axis
+ */
+LeftAxisLayout = function() {};
+
+LeftAxisLayout.prototype = {
+ /**
+ * Default margins for text fields.
+ *
+ * @private
+ * @method _getDefaultMargins
+ * @return Object
+ */
+ _getDefaultMargins: function()
+ {
+ return {
+ top: 0,
+ left: 0,
+ right: 4,
+ bottom: 0
+ };
+ },
+
+ /**
+ * Sets the length of the tick on either side of the axis line.
+ *
+ * @method setTickOffset
+ * @protected
+ */
+ setTickOffsets: function()
+ {
+ var host = this,
+ majorTicks = host.get("styles").majorTicks,
+ tickLength = majorTicks.length,
+ halfTick = tickLength * 0.5,
+ display = majorTicks.display;
+ host.set("topTickOffset", 0);
+ host.set("bottomTickOffset", 0);
+
+ switch(display)
+ {
+ case "inside" :
+ host.set("rightTickOffset", tickLength);
+ host.set("leftTickOffset", 0);
+ break;
+ case "outside" :
+ host.set("rightTickOffset", 0);
+ host.set("leftTickOffset", tickLength);
+ break;
+ case "cross":
+ host.set("rightTickOffset", halfTick);
+ host.set("leftTickOffset", halfTick);
+ break;
+ default:
+ host.set("rightTickOffset", 0);
+ host.set("leftTickOffset", 0);
+ break;
+ }
+ },
+
+ /**
+ * Draws a tick
+ *
+ * @method drawTick
+ * @param {Path} path reference to the path `Path` element in which to draw the tick.
+ * @param {Object} pt Point on the axis in which the tick will intersect.
+ * @param {Object} tickStyle Hash of properties to apply to the tick.
+ * @protected
+ */
+ drawTick: function(path, pt, tickStyles)
+ {
+ var host = this,
+ style = host.get("styles"),
+ padding = style.padding,
+ tickLength = tickStyles.length,
+ start = {x:padding.left, y:pt.y},
+ end = {x:tickLength + padding.left, y:pt.y};
+ host.drawLine(path, start, end);
+ },
+
+ /**
+ * Calculates the coordinates for the first point on an axis.
+ *
+ * @method getLineStart
+ * @return {Object}
+ * @protected
+ */
+ getLineStart: function()
+ {
+ var style = this.get("styles"),
+ padding = style.padding,
+ majorTicks = style.majorTicks,
+ tickLength = majorTicks.length,
+ display = majorTicks.display,
+ pt = {x:padding.left, y:0};
+ if(display === "outside")
+ {
+ pt.x += tickLength;
+ }
+ else if(display === "cross")
+ {
+ pt.x += tickLength/2;
+ }
+ return pt;
+ },
+
+ /**
+ * Calculates the point for a label.
+ *
+ * @method getLabelPoint
+ * @param {Object} point Point on the axis in which the tick will intersect.
+ * @return {Object}
+ * @protected
+ */
+ getLabelPoint: function(point)
+ {
+ return {x:point.x - this.get("leftTickOffset"), y:point.y};
+ },
+
+ /**
+ * Updates the value for the `maxLabelSize` for use in calculating total size.
+ *
+ * @method updateMaxLabelSize
+ * @param {HTMLElement} label to measure
+ * @protected
+ */
+ updateMaxLabelSize: function(labelWidth, labelHeight)
+ {
+ var host = this,
+ props = this._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ sinRadians = props.sinRadians,
+ cosRadians = props.cosRadians,
+ max;
+ if(rot === 0)
+ {
+ max = labelWidth;
+ }
+ else if(absRot === 90)
+ {
+ max = labelHeight;
+ }
+ else
+ {
+ max = (cosRadians * labelWidth) + (sinRadians * labelHeight);
+ }
+ host._maxLabelSize = Math.max(host._maxLabelSize, max);
+ },
+
+ /**
+ * Determines the available label width when the axis width has been explicitly set.
+ *
+ * @method getExplicitlySized
+ * @return Boolean
+ * @protected
+ */
+ getExplicitlySized: function(styles)
+ {
+ if(this._explicitWidth)
+ {
+ var host = this,
+ w = host._explicitWidth,
+ totalTitleSize = host._totalTitleSize,
+ leftTickOffset = host.get("leftTickOffset"),
+ margin = styles.label.margin.right;
+ host._maxLabelSize = w - (leftTickOffset + margin + totalTitleSize);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Rotate and position title.
+ *
+ * @method positionTitle
+ * @param {HTMLElement} label to rotate position
+ * @protected
+ */
+ positionTitle: function(label)
+ {
+ var host = this,
+ bounds = host._titleBounds,
+ margin = host.get("styles").title.margin,
+ props = host._titleRotationProps,
+ w = bounds.right - bounds.left,
+ labelWidth = label.offsetWidth,
+ labelHeight = label.offsetHeight,
+ x = (labelWidth * -0.5) + (w * 0.5),
+ y = (host.get("height") * 0.5) - (labelHeight * 0.5);
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ if(margin && margin.left)
+ {
+ x += margin.left;
+ }
+ props.x = x;
+ props.y = y;
+ props.transformOrigin = [0.5, 0.5];
+ host._rotate(label, props);
+ },
+
+ /**
+ * Rotate and position labels.
+ *
+ * @method positionLabel
+ * @param {HTMLElement} label to rotate position
+ * @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
+ * against.
+ * @protected
+ */
+ positionLabel: function(label, pt, styles, i)
+ {
+ var host = this,
+ tickOffset = host.get("leftTickOffset"),
+ totalTitleSize = this._totalTitleSize,
+ leftOffset = pt.x + totalTitleSize - tickOffset,
+ topOffset = pt.y,
+ props = this._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ maxLabelSize = host._maxLabelSize,
+ labelWidth = this._labelWidths[i],
+ labelHeight = this._labelHeights[i];
+ if(rot === 0)
+ {
+ leftOffset -= labelWidth;
+ topOffset -= labelHeight * 0.5;
+ }
+ else if(rot === 90)
+ {
+ leftOffset -= labelWidth * 0.5;
+ }
+ else if(rot === -90)
+ {
+ leftOffset -= labelWidth * 0.5;
+ topOffset -= labelHeight;
+ }
+ else
+ {
+ leftOffset -= labelWidth + (labelHeight * absRot/360);
+ topOffset -= labelHeight * 0.5;
+ }
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ props.x = Math.round(maxLabelSize + leftOffset);
+ props.y = Math.round(topOffset);
+ this._rotate(label, props);
+ },
+
+ /**
+ * Adjusts the coordinates of an axis label based on the rotation.
+ *
+ * @method _setRotationCoords
+ * @param {Object} props Coordinates, dimension and rotation properties of the label.
+ * @protected
+ */
+ _setRotationCoords: function(props)
+ {
+ var rot = props.rot,
+ absRot = props.absRot,
+ leftOffset,
+ topOffset,
+ labelWidth = props.labelWidth,
+ labelHeight = props.labelHeight;
+ if(rot === 0)
+ {
+ leftOffset = labelWidth;
+ topOffset = labelHeight * 0.5;
+ }
+ else if(rot === 90)
+ {
+ topOffset = 0;
+ leftOffset = labelWidth * 0.5;
+ }
+ else if(rot === -90)
+ {
+ leftOffset = labelWidth * 0.5;
+ topOffset = labelHeight;
+ }
+ else
+ {
+ leftOffset = labelWidth + (labelHeight * absRot/360);
+ topOffset = labelHeight * 0.5;
+ }
+ props.x -= leftOffset;
+ props.y -= topOffset;
+ },
+
+ /**
+ * Returns the transformOrigin to use for an axis label based on the position of the axis
+ * and the rotation of the label.
+ *
+ * @method _getTransformOrigin
+ * @param {Number} rot The rotation (in degrees) of the label.
+ * @return Array
+ * @protected
+ */
+ _getTransformOrigin: function(rot)
+ {
+ var transformOrigin;
+ if(rot === 0)
+ {
+ transformOrigin = [0, 0];
+ }
+ else if(rot === 90)
+ {
+ transformOrigin = [0.5, 0];
+ }
+ else if(rot === -90)
+ {
+ transformOrigin = [0.5, 1];
+ }
+ else
+ {
+ transformOrigin = [1, 0.5];
+ }
+ return transformOrigin;
+ },
+
+ /**
+ * Adjust the position of the Axis widget's content box for internal axes.
+ *
+ * @method offsetNodeForTick
+ * @param {Node} cb contentBox of the axis
+ * @protected
+ */
+ offsetNodeForTick: function()
+ {
+ },
+
+ /**
+ * Sets the width of the axis based on its contents.
+ *
+ * @method setCalculatedSize
+ * @protected
+ */
+ setCalculatedSize: function()
+ {
+ var host = this,
+ graphic = this.get("graphic"),
+ style = host.get("styles"),
+ label = style.label,
+ tickOffset = host.get("leftTickOffset"),
+ max = host._maxLabelSize,
+ totalTitleSize = this._totalTitleSize,
+ ttl = Math.round(totalTitleSize + tickOffset + max + label.margin.right);
+ if(this._explicitWidth)
+ {
+ ttl = this._explicitWidth;
+ }
+ this.set("calculatedWidth", ttl);
+ graphic.set("x", ttl - tickOffset);
+ }
+};
+
+Y.LeftAxisLayout = LeftAxisLayout;
+/**
+ * RightAxisLayout contains algorithms for rendering a right axis.
+ *
+ * @class RightAxisLayout
+ * @constructor
+ * @submodule axis
+ */
+RightAxisLayout = function(){};
+
+RightAxisLayout.prototype = {
+ /**
+ * Default margins for text fields.
+ *
+ * @private
+ * @method _getDefaultMargins
+ * @return Object
+ */
+ _getDefaultMargins: function()
+ {
+ return {
+ top: 0,
+ left: 4,
+ right: 0,
+ bottom: 0
+ };
+ },
+
+ /**
+ * Sets the length of the tick on either side of the axis line.
+ *
+ * @method setTickOffset
+ * @protected
+ */
+ setTickOffsets: function()
+ {
+ var host = this,
+ majorTicks = host.get("styles").majorTicks,
+ tickLength = majorTicks.length,
+ halfTick = tickLength * 0.5,
+ display = majorTicks.display;
+ host.set("topTickOffset", 0);
+ host.set("bottomTickOffset", 0);
+
+ switch(display)
+ {
+ case "inside" :
+ host.set("leftTickOffset", tickLength);
+ host.set("rightTickOffset", 0);
+ break;
+ case "outside" :
+ host.set("leftTickOffset", 0);
+ host.set("rightTickOffset", tickLength);
+ break;
+ case "cross" :
+ host.set("rightTickOffset", halfTick);
+ host.set("leftTickOffset", halfTick);
+ break;
+ default:
+ host.set("leftTickOffset", 0);
+ host.set("rightTickOffset", 0);
+ break;
+ }
+ },
+
+ /**
+ * Draws a tick
+ *
+ * @method drawTick
+ * @param {Path} path reference to the path `Path` element in which to draw the tick.
+ * @param {Object} pt Point on the axis in which the tick will intersect.
+ * @param {Object) tickStyle Hash of properties to apply to the tick.
+ * @protected
+ */
+ drawTick: function(path, pt, tickStyles)
+ {
+ var host = this,
+ style = host.get("styles"),
+ padding = style.padding,
+ tickLength = tickStyles.length,
+ start = {x:padding.left, y:pt.y},
+ end = {x:padding.left + tickLength, y:pt.y};
+ host.drawLine(path, start, end);
+ },
+
+ /**
+ * Calculates the coordinates for the first point on an axis.
+ *
+ * @method getLineStart
+ * @return {Object}
+ * @protected
+ */
+ getLineStart: function()
+ {
+ var host = this,
+ style = host.get("styles"),
+ padding = style.padding,
+ majorTicks = style.majorTicks,
+ tickLength = majorTicks.length,
+ display = majorTicks.display,
+ pt = {x:padding.left, y:padding.top};
+ if(display === "inside")
+ {
+ pt.x += tickLength;
+ }
+ else if(display === "cross")
+ {
+ pt.x += tickLength/2;
+ }
+ return pt;
+ },
+
+ /**
+ * Calculates the point for a label.
+ *
+ * @method getLabelPoint
+ * @param {Object} point Point on the axis in which the tick will intersect.
+ * @return {Object}
+ * @protected
+ */
+ getLabelPoint: function(point)
+ {
+ return {x:point.x + this.get("rightTickOffset"), y:point.y};
+ },
+
+ /**
+ * Updates the value for the `maxLabelSize` for use in calculating total size.
+ *
+ * @method updateMaxLabelSize
+ * @param {HTMLElement} label to measure
+ * @protected
+ */
+ updateMaxLabelSize: function(labelWidth, labelHeight)
+ {
+ var host = this,
+ props = this._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ sinRadians = props.sinRadians,
+ cosRadians = props.cosRadians,
+ max;
+ if(rot === 0)
+ {
+ max = labelWidth;
+ }
+ else if(absRot === 90)
+ {
+ max = labelHeight;
+ }
+ else
+ {
+ max = (cosRadians * labelWidth) + (sinRadians * labelHeight);
+ }
+ host._maxLabelSize = Math.max(host._maxLabelSize, max);
+ },
+
+ /**
+ * Determines the available label width when the axis width has been explicitly set.
+ *
+ * @method getExplicitlySized
+ * @return Boolean
+ * @protected
+ */
+ getExplicitlySized: function(styles)
+ {
+ if(this._explicitWidth)
+ {
+ var host = this,
+ w = host._explicitWidth,
+ totalTitleSize = this._totalTitleSize,
+ rightTickOffset = host.get("rightTickOffset"),
+ margin = styles.label.margin.right;
+ host._maxLabelSize = w - (rightTickOffset + margin + totalTitleSize);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Rotate and position title.
+ *
+ * @method positionTitle
+ * @param {HTMLElement} label to rotate position
+ * @protected
+ */
+ positionTitle: function(label)
+ {
+ var host = this,
+ bounds = host._titleBounds,
+ margin = host.get("styles").title.margin,
+ props = host._titleRotationProps,
+ labelWidth = label.offsetWidth,
+ labelHeight = label.offsetHeight,
+ w = bounds.right - bounds.left,
+ x = this.get("width") - (labelWidth * 0.5) - (w * 0.5),
+ y = (host.get("height") * 0.5) - (labelHeight * 0.5);
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ if(margin && margin.right)
+ {
+ x -= margin.left;
+ }
+ props.x = x;
+ props.y = y;
+ props.transformOrigin = [0.5, 0.5];
+ host._rotate(label, props);
+ },
+
+ /**
+ * Rotate and position labels.
+ *
+ * @method positionLabel
+ * @param {HTMLElement} label to rotate position
+ * @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
+ * against.
+ * @protected
+ */
+ positionLabel: function(label, pt, styles, i)
+ {
+ var host = this,
+ tickOffset = host.get("rightTickOffset"),
+ labelStyles = styles.label,
+ margin = 0,
+ leftOffset = pt.x,
+ topOffset = pt.y,
+ props = this._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ labelWidth = this._labelWidths[i],
+ labelHeight = this._labelHeights[i];
+ if(labelStyles.margin && labelStyles.margin.left)
+ {
+ margin = labelStyles.margin.left;
+ }
+ if(rot === 0)
+ {
+ topOffset -= labelHeight * 0.5;
+ }
+ else if(rot === 90)
+ {
+ leftOffset -= labelWidth * 0.5;
+ topOffset -= labelHeight;
+ }
+ else if(rot === -90)
+ {
+ leftOffset -= labelWidth * 0.5;
+ }
+ else
+ {
+ topOffset -= labelHeight * 0.5;
+ leftOffset += labelHeight/2 * absRot/90;
+ }
+ leftOffset += margin;
+ leftOffset += tickOffset;
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ props.x = Math.round(leftOffset);
+ props.y = Math.round(topOffset);
+ this._rotate(label, props);
+ },
+
+ /**
+ * Adjusts the coordinates of an axis label based on the rotation.
+ *
+ * @method _setRotationCoords
+ * @param {Object} props Coordinates, dimension and rotation properties of the label.
+ * @protected
+ */
+ _setRotationCoords: function(props)
+ {
+ var rot = props.rot,
+ absRot = props.absRot,
+ leftOffset = 0,
+ topOffset = 0,
+ labelWidth = props.labelWidth,
+ labelHeight = props.labelHeight;
+ if(rot === 0)
+ {
+ topOffset = labelHeight * 0.5;
+ }
+ else if(rot === 90)
+ {
+ leftOffset = labelWidth * 0.5;
+ topOffset = labelHeight;
+ }
+ else if(rot === -90)
+ {
+ leftOffset = labelWidth * 0.5;
+ }
+ else
+ {
+ topOffset = labelHeight * 0.5;
+ leftOffset = labelHeight/2 * absRot/90;
+ }
+ props.x -= leftOffset;
+ props.y -= topOffset;
+ },
+
+ /**
+ * Returns the transformOrigin to use for an axis label based on the position of the axis
+ * and the rotation of the label.
+ *
+ * @method _getTransformOrigin
+ * @param {Number} rot The rotation (in degrees) of the label.
+ * @return Array
+ * @protected
+ */
+ _getTransformOrigin: function(rot)
+ {
+ var transformOrigin;
+ if(rot === 0)
+ {
+ transformOrigin = [0, 0];
+ }
+ else if(rot === 90)
+ {
+ transformOrigin = [0.5, 1];
+ }
+ else if(rot === -90)
+ {
+ transformOrigin = [0.5, 0];
+ }
+ else
+ {
+ transformOrigin = [0, 0.5];
+ }
+ return transformOrigin;
+ },
+
+ /**
+ * Adjusts position for inner ticks.
+ *
+ * @method offsetNodeForTick
+ * @param {Node} cb contentBox of the axis
+ * @protected
+ */
+ offsetNodeForTick: function(cb)
+ {
+ var host = this,
+ tickOffset = host.get("leftTickOffset"),
+ offset = 0 - tickOffset;
+ cb.setStyle("left", offset);
+ },
+
+ /**
+ * Assigns a height based on the size of the contents.
+ *
+ * @method setCalculatedSize
+ * @protected
+ */
+ setCalculatedSize: function()
+ {
+ var host = this,
+ styles = host.get("styles"),
+ labelStyle = styles.label,
+ totalTitleSize = this._totalTitleSize,
+ ttl = Math.round(host.get("rightTickOffset") + host._maxLabelSize + totalTitleSize + labelStyle.margin.left);
+ if(this._explicitWidth)
+ {
+ ttl = this._explicitWidth;
+ }
+ host.set("calculatedWidth", ttl);
+ host.get("contentBox").setStyle("width", ttl);
+ }
+};
+
+Y.RightAxisLayout = RightAxisLayout;
+/**
+ * Contains algorithms for rendering a bottom axis.
+ *
+ * @class BottomAxisLayout
+ * @Constructor
+ * @submodule axis
+ */
+BottomAxisLayout = function(){};
+
+BottomAxisLayout.prototype = {
+ /**
+ * Default margins for text fields.
+ *
+ * @private
+ * @method _getDefaultMargins
+ * @return Object
+ */
+ _getDefaultMargins: function()
+ {
+ return {
+ top: 4,
+ left: 0,
+ right: 0,
+ bottom: 0
+ };
+ },
+
+ /**
+ * Sets the length of the tick on either side of the axis line.
+ *
+ * @method setTickOffsets
+ * @protected
+ */
+ setTickOffsets: function()
+ {
+ var host = this,
+ majorTicks = host.get("styles").majorTicks,
+ tickLength = majorTicks.length,
+ halfTick = tickLength * 0.5,
+ display = majorTicks.display;
+ host.set("leftTickOffset", 0);
+ host.set("rightTickOffset", 0);
+
+ switch(display)
+ {
+ case "inside" :
+ host.set("topTickOffset", tickLength);
+ host.set("bottomTickOffset", 0);
+ break;
+ case "outside" :
+ host.set("topTickOffset", 0);
+ host.set("bottomTickOffset", tickLength);
+ break;
+ case "cross":
+ host.set("topTickOffset", halfTick);
+ host.set("bottomTickOffset", halfTick);
+ break;
+ default:
+ host.set("topTickOffset", 0);
+ host.set("bottomTickOffset", 0);
+ break;
+ }
+ },
+
+ /**
+ * Calculates the coordinates for the first point on an axis.
+ *
+ * @method getLineStart
+ * @protected
+ */
+ getLineStart: function()
+ {
+ var style = this.get("styles"),
+ padding = style.padding,
+ majorTicks = style.majorTicks,
+ tickLength = majorTicks.length,
+ display = majorTicks.display,
+ pt = {x:0, y:padding.top};
+ if(display === "inside")
+ {
+ pt.y += tickLength;
+ }
+ else if(display === "cross")
+ {
+ pt.y += tickLength/2;
+ }
+ return pt;
+ },
+
+ /**
+ * Draws a tick
+ *
+ * @method drawTick
+ * @param {Path} path reference to the path `Path` element in which to draw the tick.
+ * @param {Object} pt hash containing x and y coordinates
+ * @param {Object} tickStyles hash of properties used to draw the tick
+ * @protected
+ */
+ drawTick: function(path, pt, tickStyles)
+ {
+ var host = this,
+ style = host.get("styles"),
+ padding = style.padding,
+ tickLength = tickStyles.length,
+ start = {x:pt.x, y:padding.top},
+ end = {x:pt.x, y:tickLength + padding.top};
+ host.drawLine(path, start, end);
+ },
+
+ /**
+ * Calculates the point for a label.
+ *
+ * @method getLabelPoint
+ * @param {Object} pt Object containing x and y coordinates
+ * @return Object
+ * @protected
+ */
+ getLabelPoint: function(point)
+ {
+ return {x:point.x, y:point.y + this.get("bottomTickOffset")};
+ },
+
+ /**
+ * Updates the value for the `maxLabelSize` for use in calculating total size.
+ *
+ * @method updateMaxLabelSize
+ * @param {HTMLElement} label to measure
+ * @protected
+ */
+ updateMaxLabelSize: function(labelWidth, labelHeight)
+ {
+ var host = this,
+ props = this._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ sinRadians = props.sinRadians,
+ cosRadians = props.cosRadians,
+ max;
+ if(rot === 0)
+ {
+ max = labelHeight;
+ }
+ else if(absRot === 90)
+ {
+ max = labelWidth;
+ }
+ else
+ {
+ max = (sinRadians * labelWidth) + (cosRadians * labelHeight);
+ }
+ host._maxLabelSize = Math.max(host._maxLabelSize, max);
+ },
+
+ /**
+ * Determines the available label height when the axis width has been explicitly set.
+ *
+ * @method getExplicitlySized
+ * @return Boolean
+ * @protected
+ */
+ getExplicitlySized: function(styles)
+ {
+ if(this._explicitHeight)
+ {
+ var host = this,
+ h = host._explicitHeight,
+ totalTitleSize = host._totalTitleSize,
+ bottomTickOffset = host.get("bottomTickOffset"),
+ margin = styles.label.margin.right;
+ host._maxLabelSize = h - (bottomTickOffset + margin + totalTitleSize);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Rotate and position title.
+ *
+ * @method positionTitle
+ * @param {HTMLElement} label to rotate position
+ * @protected
+ */
+ positionTitle: function(label)
+ {
+ var host = this,
+ bounds = host._titleBounds,
+ margin = host.get("styles").title.margin,
+ props = host._titleRotationProps,
+ h = bounds.bottom - bounds.top,
+ labelWidth = label.offsetWidth,
+ labelHeight = label.offsetHeight,
+ x = (host.get("width") * 0.5) - (labelWidth * 0.5),
+ y = host.get("height") - labelHeight/2 - h/2;
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ if(margin && margin.bottom)
+ {
+ y -= margin.bottom;
+ }
+ props.x = x;
+ props.y = y;
+ props.transformOrigin = [0.5, 0.5];
+ host._rotate(label, props);
+ },
+
+ /**
+ * Rotate and position labels.
+ *
+ * @method positionLabel
+ * @param {HTMLElement} label to rotate position
+ * @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
+ * against.
+ * @protected
+ */
+ positionLabel: function(label, pt, styles, i)
+ {
+ var host = this,
+ tickOffset = host.get("bottomTickOffset"),
+ labelStyles = styles.label,
+ margin = 0,
+ props = host._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ leftOffset = Math.round(pt.x),
+ topOffset = Math.round(pt.y),
+ labelWidth = host._labelWidths[i],
+ labelHeight = host._labelHeights[i];
+ if(labelStyles.margin && labelStyles.margin.top)
+ {
+ margin = labelStyles.margin.top;
+ }
+ if(rot > 0)
+ {
+ topOffset -= labelHeight/2 * rot/90;
+ }
+ else if(rot < 0)
+ {
+ leftOffset -= labelWidth;
+ topOffset -= labelHeight/2 * absRot/90;
+ }
+ else
+ {
+ leftOffset -= labelWidth * 0.5;
+ }
+ topOffset += margin;
+ topOffset += tickOffset;
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ props.x = leftOffset;
+ props.y = topOffset;
+ host._rotate(label, props);
+ },
+
+ /**
+ * Adjusts the coordinates of an axis label based on the rotation.
+ *
+ * @method _setRotationCoords
+ * @param {Object} props Coordinates, dimension and rotation properties of the label.
+ * @protected
+ */
+ _setRotationCoords: function(props)
+ {
+ var rot = props.rot,
+ absRot = props.absRot,
+ labelWidth = props.labelWidth,
+ labelHeight = props.labelHeight,
+ leftOffset,
+ topOffset;
+
+ if(rot > 0)
+ {
+ leftOffset = 0;
+ topOffset = labelHeight/2 * rot/90;
+ }
+ else if(rot < 0)
+ {
+ leftOffset = labelWidth;
+ topOffset = labelHeight/2 * absRot/90;
+ }
+ else
+ {
+ leftOffset = labelWidth * 0.5;
+ topOffset = 0;
+ }
+ props.x -= leftOffset;
+ props.y -= topOffset;
+ },
+
+ /**
+ * Returns the transformOrigin to use for an axis label based on the position of the axis
+ * and the rotation of the label.
+ *
+ * @method _getTransformOrigin
+ * @param {Number} rot The rotation (in degrees) of the label.
+ * @return Array
+ * @protected
+ */
+ _getTransformOrigin: function(rot)
+ {
+ var transformOrigin;
+ if(rot > 0)
+ {
+ transformOrigin = [0, 0.5];
+ }
+ else if(rot < 0)
+ {
+ transformOrigin = [1, 0.5];
+ }
+ else
+ {
+ transformOrigin = [0, 0];
+ }
+ return transformOrigin;
+ },
+
+ /**
+ * Adjusts position for inner ticks.
+ *
+ * @method offsetNodeForTick
+ * @param {Node} cb contentBox of the axis
+ * @protected
+ */
+ offsetNodeForTick: function(cb)
+ {
+ var host = this;
+ cb.setStyle("top", 0 - host.get("topTickOffset"));
+ },
+
+ /**
+ * Assigns a height based on the size of the contents.
+ *
+ * @method setCalculatedSize
+ * @protected
+ */
+ setCalculatedSize: function()
+ {
+ var host = this,
+ styles = host.get("styles"),
+ labelStyle = styles.label,
+ totalTitleSize = host._totalTitleSize,
+ ttl = Math.round(host.get("bottomTickOffset") + host._maxLabelSize + labelStyle.margin.top + totalTitleSize);
+ if(host._explicitHeight)
+ {
+ ttl = host._explicitHeight;
+ }
+ host.set("calculatedHeight", ttl);
+ }
+};
+Y.BottomAxisLayout = BottomAxisLayout;
+/**
+ * Contains algorithms for rendering a top axis.
+ *
+ * @class TopAxisLayout
+ * @constructor
+ * @submodule axis
+ */
+TopAxisLayout = function(){};
+
+TopAxisLayout.prototype = {
+ /**
+ * Default margins for text fields.
+ *
+ * @private
+ * @method _getDefaultMargins
+ * @return Object
+ */
+ _getDefaultMargins: function()
+ {
+ return {
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 4
+ };
+ },
+
+ /**
+ * Sets the length of the tick on either side of the axis line.
+ *
+ * @method setTickOffsets
+ * @protected
+ */
+ setTickOffsets: function()
+ {
+ var host = this,
+ majorTicks = host.get("styles").majorTicks,
+ tickLength = majorTicks.length,
+ halfTick = tickLength * 0.5,
+ display = majorTicks.display;
+ host.set("leftTickOffset", 0);
+ host.set("rightTickOffset", 0);
+ switch(display)
+ {
+ case "inside" :
+ host.set("bottomTickOffset", tickLength);
+ host.set("topTickOffset", 0);
+ break;
+ case "outside" :
+ host.set("bottomTickOffset", 0);
+ host.set("topTickOffset", tickLength);
+ break;
+ case "cross" :
+ host.set("topTickOffset", halfTick);
+ host.set("bottomTickOffset", halfTick);
+ break;
+ default:
+ host.set("topTickOffset", 0);
+ host.set("bottomTickOffset", 0);
+ break;
+ }
+ },
+
+ /**
+ * Calculates the coordinates for the first point on an axis.
+ *
+ * @method getLineStart
+ * @protected
+ */
+ getLineStart: function()
+ {
+ var host = this,
+ style = host.get("styles"),
+ padding = style.padding,
+ majorTicks = style.majorTicks,
+ tickLength = majorTicks.length,
+ display = majorTicks.display,
+ pt = {x:0, y:padding.top};
+ if(display === "outside")
+ {
+ pt.y += tickLength;
+ }
+ else if(display === "cross")
+ {
+ pt.y += tickLength/2;
+ }
+ return pt;
+ },
+
+ /**
+ * Draws a tick
+ *
+ * @method drawTick
+ * @param {Path} path reference to the path `Path` element in which to draw the tick.
+ * @param {Object} pt hash containing x and y coordinates
+ * @param {Object} tickStyles hash of properties used to draw the tick
+ * @protected
+ */
+ drawTick: function(path, pt, tickStyles)
+ {
+ var host = this,
+ style = host.get("styles"),
+ padding = style.padding,
+ tickLength = tickStyles.length,
+ start = {x:pt.x, y:padding.top},
+ end = {x:pt.x, y:tickLength + padding.top};
+ host.drawLine(path, start, end);
+ },
+
+ /**
+ * Calculates the point for a label.
+ *
+ * @method getLabelPoint
+ * @param {Object} pt hash containing x and y coordinates
+ * @return Object
+ * @protected
+ */
+ getLabelPoint: function(pt)
+ {
+ return {x:pt.x, y:pt.y - this.get("topTickOffset")};
+ },
+
+ /**
+ * Updates the value for the `maxLabelSize` for use in calculating total size.
+ *
+ * @method updateMaxLabelSize
+ * @param {HTMLElement} label to measure
+ * @protected
+ */
+ updateMaxLabelSize: function(labelWidth, labelHeight)
+ {
+ var host = this,
+ props = this._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ sinRadians = props.sinRadians,
+ cosRadians = props.cosRadians,
+ max;
+ if(rot === 0)
+ {
+ max = labelHeight;
+ }
+ else if(absRot === 90)
+ {
+ max = labelWidth;
+ }
+ else
+ {
+ max = (sinRadians * labelWidth) + (cosRadians * labelHeight);
+ }
+ host._maxLabelSize = Math.max(host._maxLabelSize, max);
+ },
+
+ /**
+ * Determines the available label height when the axis width has been explicitly set.
+ *
+ * @method getExplicitlySized
+ * @return Boolean
+ * @protected
+ */
+ getExplicitlySized: function(styles)
+ {
+ if(this._explicitHeight)
+ {
+ var host = this,
+ h = host._explicitHeight,
+ totalTitleSize = host._totalTitleSize,
+ topTickOffset = host.get("topTickOffset"),
+ margin = styles.label.margin.right;
+ host._maxLabelSize = h - (topTickOffset + margin + totalTitleSize);
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Rotate and position title.
+ *
+ * @method positionTitle
+ * @param {HTMLElement} label to rotate position
+ * @protected
+ */
+ positionTitle: function(label)
+ {
+ var host = this,
+ bounds = host._titleBounds,
+ margin = host.get("styles").title.margin,
+ props = host._titleRotationProps,
+ labelWidth = label.offsetWidth,
+ labelHeight = label.offsetHeight,
+ h = bounds.bottom - bounds.top,
+ x = (host.get("width") * 0.5) - (labelWidth * 0.5),
+ y = h/2 - labelHeight/2;
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ if(margin && margin.top)
+ {
+ y += margin.top;
+ }
+ props.x = x;
+ props.y = y;
+ props.transformOrigin = [0.5, 0.5];
+ host._rotate(label, props);
+ },
+
+ /**
+ * Rotate and position labels.
+ *
+ * @method positionLabel
+ * @param {HTMLElement} label to rotate position
+ * @param {Object} pt hash containing the x and y coordinates in which the label will be positioned
+ * against.
+ * @protected
+ */
+ positionLabel: function(label, pt, styles, i)
+ {
+ var host = this,
+ totalTitleSize = this._totalTitleSize,
+ maxLabelSize = host._maxLabelSize,
+ leftOffset = pt.x,
+ topOffset = pt.y + totalTitleSize + maxLabelSize,
+ props = this._labelRotationProps,
+ rot = props.rot,
+ absRot = props.absRot,
+ labelWidth = this._labelWidths[i],
+ labelHeight = this._labelHeights[i];
+ if(rot === 0)
+ {
+ leftOffset -= labelWidth * 0.5;
+ topOffset -= labelHeight;
+ }
+ else
+ {
+ if(rot === 90)
+ {
+ leftOffset -= labelWidth;
+ topOffset -= (labelHeight * 0.5);
+ }
+ else if (rot === -90)
+ {
+ topOffset -= (labelHeight * 0.5);
+ }
+ else if(rot > 0)
+ {
+ leftOffset -= labelWidth;
+ topOffset -= labelHeight - (labelHeight * rot/180);
+ }
+ else
+ {
+ topOffset -= labelHeight - (labelHeight * absRot/180);
+ }
+ }
+ props.x = Math.round(leftOffset);
+ props.y = Math.round(topOffset);
+ props.labelWidth = labelWidth;
+ props.labelHeight = labelHeight;
+ this._rotate(label, props);
+ },
+
+ /**
+ * Adjusts the coordinates of an axis label based on the rotation.
+ *
+ * @method _setRotationCoords
+ * @param {Object} props Coordinates, dimension and rotation properties of the label.
+ * @protected
+ */
+ _setRotationCoords: function(props)
+ {
+ var rot = props.rot,
+ absRot = props.absRot,
+ labelWidth = props.labelWidth,
+ labelHeight = props.labelHeight,
+ leftOffset,
+ topOffset;
+ if(rot === 0)
+ {
+ leftOffset = labelWidth * 0.5;
+ topOffset = labelHeight;
+ }
+ else
+ {
+ if(rot === 90)
+ {
+ leftOffset = labelWidth;
+ topOffset = (labelHeight * 0.5);
+ }
+ else if (rot === -90)
+ {
+ topOffset = (labelHeight * 0.5);
+ }
+ else if(rot > 0)
+ {
+ leftOffset = labelWidth;
+ topOffset = labelHeight - (labelHeight * rot/180);
+ }
+ else
+ {
+ topOffset = labelHeight - (labelHeight * absRot/180);
+ }
+ }
+ props.x -= leftOffset;
+ props.y -= topOffset;
+ },
+
+ /**
+ * Returns the transformOrigin to use for an axis label based on the position of the axis
+ * and the rotation of the label.
+ *
+ * @method _getTransformOrigin
+ * @param {Number} rot The rotation (in degrees) of the label.
+ * @return Array
+ * @protected
+ */
+ _getTransformOrigin: function(rot)
+ {
+ var transformOrigin;
+ if(rot === 0)
+ {
+ transformOrigin = [0, 0];
+ }
+ else
+ {
+ if(rot === 90)
+ {
+ transformOrigin = [1, 0.5];
+ }
+ else if (rot === -90)
+ {
+ transformOrigin = [0, 0.5];
+ }
+ else if(rot > 0)
+ {
+ transformOrigin = [1, 0.5];
+ }
+ else
+ {
+ transformOrigin = [0, 0.5];
+ }
+ }
+ return transformOrigin;
+ },
+
+ /**
+ * Adjusts position for inner ticks.
+ *
+ * @method offsetNodeForTick
+ * @param {Node} cb contentBox of the axis
+ * @protected
+ */
+ offsetNodeForTick: function()
+ {
+ },
+
+ /**
+ * Assigns a height based on the size of the contents.
+ *
+ * @method setCalculatedSize
+ * @protected
+ */
+ setCalculatedSize: function()
+ {
+ var host = this,
+ graphic = host.get("graphic"),
+ styles = host.get("styles"),
+ labelMargin = styles.label.margin,
+ totalLabelSize = labelMargin.bottom + host._maxLabelSize,
+ totalTitleSize = host._totalTitleSize,
+ topTickOffset = this.get("topTickOffset"),
+ ttl = Math.round(topTickOffset + totalLabelSize + totalTitleSize);
+ if(this._explicitHeight)
+ {
+ ttl = this._explicitHeight;
+ }
+ host.set("calculatedHeight", ttl);
+ graphic.set("y", ttl - topTickOffset);
+ }
+};
+Y.TopAxisLayout = TopAxisLayout;
+
+/**
+ * An abstract class that provides the core functionality for draw a chart axis. Axis is used by the following classes:
+ * <ul>
+ * <li>{{#crossLink "CategoryAxis"}}{{/crossLink}}</li>
+ * <li>{{#crossLink "NumericAxis"}}{{/crossLink}}</li>
+ * <li>{{#crossLink "StackedAxis"}}{{/crossLink}}</li>
+ * <li>{{#crossLink "TimeAxis"}}{{/crossLink}}</li>
+ * </ul>
+ *
+ * @class Axis
+ * @extends Widget
+ * @uses AxisBase
+ * @uses TopAxisLayout
+ * @uses RightAxisLayout
+ * @uses BottomAxisLayout
+ * @uses LeftAxisLayout
+ * @constructor
+ * @param {Object} config (optional) Configuration parameters.
+ * @submodule axis
+ */
+Y.Axis = Y.Base.create("axis", Y.Widget, [Y.AxisBase], {
+ /**
+ * Calculates and returns a value based on the number of labels and the index of
+ * the current label.
+ *
+ * @method getLabelByIndex
+ * @param {Number} i Index of the label.
+ * @param {Number} l Total number of labels.
+ * @return String
+ */
+ getLabelByIndex: function(i, l)
+ {
+ var position = this.get("position"),
+ direction = position === "left" || position === "right" ? "vertical" : "horizontal";
+ return this._getLabelByIndex(i, l, direction);
+ },
+
+ /**
+ * @method bindUI
+ * @private
+ */
+ bindUI: function()
+ {
+ this.after("dataReady", Y.bind(this._dataChangeHandler, this));
+ this.after("dataUpdate", Y.bind(this._dataChangeHandler, this));
+ this.after("stylesChange", this._updateHandler);
+ this.after("overlapGraphChange", this._updateHandler);
+ this.after("positionChange", this._positionChangeHandler);
+ this.after("widthChange", this._handleSizeChange);
+ this.after("heightChange", this._handleSizeChange);
+ this.after("calculatedWidthChange", this._handleSizeChange);
+ this.after("calculatedHeightChange", this._handleSizeChange);
+ },
+ /**
+ * Storage for calculatedWidth value.
+ *
+ * @property _calculatedWidth
+ * @type Number
+ * @private
+ */
+ _calculatedWidth: 0,
+
+ /**
+ * Storage for calculatedHeight value.
+ *
+ * @property _calculatedHeight
+ * @type Number
+ * @private
+ */
+ _calculatedHeight: 0,
+
+ /**
+ * Handles change to the dataProvider
+ *
+ * @method _dataChangeHandler
+ * @param {Object} e Event object
+ * @private
+ */
+ _dataChangeHandler: function()
+ {
+ if(this.get("rendered"))
+ {
+ this._drawAxis();
+ }
+ },
+
+ /**
+ * Handles change to the position attribute
+ *
+ * @method _positionChangeHandler
+ * @param {Object} e Event object
+ * @private
+ */
+ _positionChangeHandler: function(e)
+ {
+ this._updateGraphic(e.newVal);
+ this._updateHandler();
+ },
+
+ /**
+ * Updates the the Graphic instance
+ *
+ * @method _updateGraphic
+ * @param {String} position Position of axis
+ * @private
+ */
+ _updateGraphic: function(position)
+ {
+ var graphic = this.get("graphic");
+ if(position === "none")
+ {
+ if(graphic)
+ {
+ graphic.destroy();
+ }
+ }
+ else
+ {
+ if(!graphic)
+ {
+ this._setCanvas();
+ }
+ }
+ },
+
+ /**
+ * Handles changes to axis.
+ *
+ * @method _updateHandler
+ * @param {Object} e Event object
+ * @private
+ */
+ _updateHandler: function()
+ {
+ if(this.get("rendered"))
+ {
+ this._drawAxis();
+ }
+ },
+
+ /**
+ * @method renderUI
+ * @private
+ */
+ renderUI: function()
+ {
+ this._updateGraphic(this.get("position"));
+ },
+
+ /**
+ * @method syncUI
+ * @private
+ */
+ syncUI: function()
+ {
+ var layout = this._layout,
+ defaultMargins,
+ styles,
+ label,
+ title,
+ i;
+ if(layout)
+ {
+ defaultMargins = layout._getDefaultMargins();
+ styles = this.get("styles");
+ label = styles.label.margin;
+ title =styles.title.margin;
+ //need to defaultMargins method to the layout classes.
+ for(i in defaultMargins)
+ {
+ if(defaultMargins.hasOwnProperty(i))
+ {
+ label[i] = label[i] === undefined ? defaultMargins[i] : label[i];
+ title[i] = title[i] === undefined ? defaultMargins[i] : title[i];
+ }
+ }
+ }
+ this._drawAxis();
+ },
+
+ /**
+ * Creates a graphic instance to be used for the axis line and ticks.
+ *
+ * @method _setCanvas
+ * @private
+ */
+ _setCanvas: function()
+ {
+ var cb = this.get("contentBox"),
+ bb = this.get("boundingBox"),
+ p = this.get("position"),
+ pn = this._parentNode,
+ w = this.get("width"),
+ h = this.get("height");
+ bb.setStyle("position", "absolute");
+ bb.setStyle("zIndex", 2);
+ w = w ? w + "px" : pn.getStyle("width");
+ h = h ? h + "px" : pn.getStyle("height");
+ if(p === "top" || p === "bottom")
+ {
+ cb.setStyle("width", w);
+ }
+ else
+ {
+ cb.setStyle("height", h);
+ }
+ cb.setStyle("position", "relative");
+ cb.setStyle("left", "0px");
+ cb.setStyle("top", "0px");
+ this.set("graphic", new Y.Graphic());
+ this.get("graphic").render(cb);
+ },
+
+ /**
+ * Gets the default value for the `styles` attribute. Overrides
+ * base implementation.
+ *
+ * @method _getDefaultStyles
+ * @return Object
+ * @protected
+ */
+ _getDefaultStyles: function()
+ {
+ var axisstyles = {
+ majorTicks: {
+ display:"inside",
+ length:4,
+ color:"#dad8c9",
+ weight:1,
+ alpha:1
+ },
+ minorTicks: {
+ display:"none",
+ length:2,
+ color:"#dad8c9",
+ weight:1
+ },
+ line: {
+ weight:1,
+ color:"#dad8c9",
+ alpha:1
+ },
+ majorUnit: {
+ determinant:"count",
+ count:11,
+ distance:75
+ },
+ top: "0px",
+ left: "0px",
+ width: "100px",
+ height: "100px",
+ label: {
+ color:"#808080",
+ alpha: 1,
+ fontSize:"85%",
+ rotation: 0,
+ margin: {
+ top: undefined,
+ right: undefined,
+ bottom: undefined,
+ left: undefined
+ }
+ },
+ title: {
+ color:"#808080",
+ alpha: 1,
+ fontSize:"85%",
+ rotation: undefined,
+ margin: {
+ top: undefined,
+ right: undefined,
+ bottom: undefined,
+ left: undefined
+ }
+ },
+ hideOverlappingLabelTicks: false
+ };
+
+ return Y.merge(Y.Renderer.prototype._getDefaultStyles(), axisstyles);
+ },
+
+ /**
+ * Updates the axis when the size changes.
+ *
+ * @method _handleSizeChange
+ * @param {Object} e Event object.
+ * @private
+ */
+ _handleSizeChange: function(e)
+ {
+ var attrName = e.attrName,
+ pos = this.get("position"),
+ vert = pos === "left" || pos === "right",
+ cb = this.get("contentBox"),
+ hor = pos === "bottom" || pos === "top";
+ cb.setStyle("width", this.get("width"));
+ cb.setStyle("height", this.get("height"));
+ if((hor && attrName === "width") || (vert && attrName === "height"))
+ {
+ this._drawAxis();
+ }
+ },
+
+ /**
+ * Maps key values to classes containing layout algorithms
+ *
+ * @property _layoutClasses
+ * @type Object
+ * @private
+ */
+ _layoutClasses:
+ {
+ top : TopAxisLayout,
+ bottom: BottomAxisLayout,
+ left: LeftAxisLayout,
+ right : RightAxisLayout
+ },
+
+ /**
+ * Draws a line segment between 2 points
+ *
+ * @method drawLine
+ * @param {Object} startPoint x and y coordinates for the start point of the line segment
+ * @param {Object} endPoint x and y coordinates for the for the end point of the line segment
+ * @param {Object} line styles (weight, color and alpha to be applied to the line segment)
+ * @private
+ */
+ drawLine: function(path, startPoint, endPoint)
+ {
+ path.moveTo(startPoint.x, startPoint.y);
+ path.lineTo(endPoint.x, endPoint.y);
+ },
+
+ /**
+ * Generates the properties necessary for rotating and positioning a text field.
+ *
+ * @method _getTextRotationProps
+ * @param {Object} styles properties for the text field
+ * @return Object
+ * @private
+ */
+ _getTextRotationProps: function(styles)
+ {
+ if(styles.rotation === undefined)
+ {
+ switch(this.get("position"))
+ {
+ case "left" :
+ styles.rotation = -90;
+ break;
+ case "right" :
+ styles.rotation = 90;
+ break;
+ default :
+ styles.rotation = 0;
+ break;
+ }
+ }
+ var rot = Math.min(90, Math.max(-90, styles.rotation)),
+ absRot = Math.abs(rot),
+ radCon = Math.PI/180,
+ sinRadians = parseFloat(parseFloat(Math.sin(absRot * radCon)).toFixed(8)),
+ cosRadians = parseFloat(parseFloat(Math.cos(absRot * radCon)).toFixed(8));
+ return {
+ rot: rot,
+ absRot: absRot,
+ radCon: radCon,
+ sinRadians: sinRadians,
+ cosRadians: cosRadians,
+ textAlpha: styles.alpha
+ };
+ },
+
+ /**
+ * Draws an axis.
+ *
+ * @method _drawAxis
+ * @private
+ */
+ _drawAxis: function ()
+ {
+ if(this._drawing)
+ {
+ this._callLater = true;
+ return;
+ }
+ this._drawing = true;
+ this._callLater = false;
+ if(this._layout)
+ {
+ var styles = this.get("styles"),
+ line = styles.line,
+ labelStyles = styles.label,
+ majorTickStyles = styles.majorTicks,
+ drawTicks = majorTickStyles.display !== "none",
+ tickPoint,
+ majorUnit = styles.majorUnit,
+ len,
+ majorUnitDistance,
+ i = 0,
+ layout = this._layout,
+ layoutLength,
+ lineStart,
+ label,
+ labelWidth,
+ labelHeight,
+ labelFunction = this.get("labelFunction"),
+ labelFunctionScope = this.get("labelFunctionScope"),
+ labelFormat = this.get("labelFormat"),
+ graphic = this.get("graphic"),
+ path = this.get("path"),
+ tickPath,
+ explicitlySized,
+ position = this.get("position"),
+ labelData,
+ labelValues,
+ point,
+ points,
+ edgeOffset,
+ direction = (position === "left" || position === "right") ? "vertical" : "horizontal";
+ this._labelWidths = [];
+ this._labelHeights = [];
+ graphic.set("autoDraw", false);
+ path.clear();
+ path.set("stroke", {
+ weight: line.weight,
+ color: line.color,
+ opacity: line.alpha
+ });
+ this._labelRotationProps = this._getTextRotationProps(labelStyles);
+ this._labelRotationProps.transformOrigin = layout._getTransformOrigin(this._labelRotationProps.rot);
+ layout.setTickOffsets.apply(this);
+ layoutLength = this.getLength();
+
+ len = this.getTotalMajorUnits();
+ edgeOffset = this.getEdgeOffset(len, layoutLength);
+ this.set("edgeOffset", edgeOffset);
+ lineStart = layout.getLineStart.apply(this);
+
+ //if labelValues are explicitly set, get the points based on the calculated positions of the labelValues
+ //if not, get the points based on the axis length, number of ticks and majorUnit values
+ if(this._labelValuesExplicitlySet)
+ {
+ labelData = this._getDataFromLabelValues(lineStart, this.get("labelValues"), edgeOffset, layoutLength, direction);
+ points = labelData.points;
+ labelValues = labelData.values;
+ len = points.length;
+ }
+ else
+ {
+ majorUnitDistance = this.getMajorUnitDistance(len, layoutLength, majorUnit);
+ points = this._getPoints(lineStart, len, edgeOffset, majorUnitDistance, direction);
+ labelValues = [];
+ for(i = 0; i < len; i = i + 1)
+ {
+ labelValues.push(this._getLabelByIndex(i, len, direction));
+ }
+
+ //Don't set labelValues fix for #2533172 is available
+ //this.set("labelValues", labelValues, {src: internal});
+ }
+
+ //Don't create the last label or tick.
+ if(this.get("hideFirstMajorUnit"))
+ {
+ points.shift();
+ labelValues.shift();
+ len = len - 1;
+ }
+
+ //Don't create the last label or tick.
+ if(this.get("hideLastMajorUnit"))
+ {
+ points.pop();
+ labelValues.pop();
+ len = len - 1;
+ }
+
+ if(len < 1)
+ {
+ this._clearLabelCache();
+ }
+ else
+ {
+ tickPoint = this.getFirstPoint(lineStart);
+ this.drawLine(path, lineStart, this.getLineEnd(tickPoint));
+ if(drawTicks)
+ {
+ tickPath = this.get("tickPath");
+ tickPath.clear();
+ tickPath.set("stroke", {
+ weight: majorTickStyles.weight,
+ color: majorTickStyles.color,
+ opacity: majorTickStyles.alpha
+ });
+ for(i = 0; i < len; i = i + 1)
+ {
+ point = points[i];
+ if(point)
+ {
+ layout.drawTick.apply(this, [tickPath, points[i], majorTickStyles]);
+ }
+ }
+ }
+ this._createLabelCache();
+ this._tickPoints = points;
+ this._maxLabelSize = 0;
+ this._totalTitleSize = 0;
+ this._titleSize = 0;
+ this._setTitle();
+ explicitlySized = layout.getExplicitlySized.apply(this, [styles]);
+ for(i = 0; i < len; i = i + 1)
+ {
+ point = points[i];
+ if(point)
+ {
+ label = this.getLabel(point, labelStyles);
+ this._labels.push(label);
+ this.get("appendLabelFunction")(label, labelFunction.apply(labelFunctionScope, [labelValues[i], labelFormat]));
+ labelWidth = Math.round(label.offsetWidth);
+ labelHeight = Math.round(label.offsetHeight);
+ if(!explicitlySized)
+ {
+ this._layout.updateMaxLabelSize.apply(this, [labelWidth, labelHeight]);
+ }
+ this._labelWidths.push(labelWidth);
+ this._labelHeights.push(labelHeight);
+ }
+ }
+ this._clearLabelCache();
+ if(this.get("overlapGraph"))
+ {
+ layout.offsetNodeForTick.apply(this, [this.get("contentBox")]);
+ }
+ layout.setCalculatedSize.apply(this);
+ if(this._titleTextField)
+ {
+ this._layout.positionTitle.apply(this, [this._titleTextField]);
+ }
+ len = this._labels.length;
+ for(i = 0; i < len; ++i)
+ {
+ layout.positionLabel.apply(this, [this.get("labels")[i], this._tickPoints[i], styles, i]);
+ }
+ }
+ }
+ this._drawing = false;
+ if(this._callLater)
+ {
+ this._drawAxis();
+ }
+ else
+ {
+ this._updatePathElement();
+ this.fire("axisRendered");
+ }
+ },
+
+ /**
+ * Calculates and sets the total size of a title.
+ *
+ * @method _setTotalTitleSize
+ * @param {Object} styles Properties for the title field.
+ * @private
+ */
+ _setTotalTitleSize: function(styles)
+ {
+ var title = this._titleTextField,
+ w = title.offsetWidth,
+ h = title.offsetHeight,
+ rot = this._titleRotationProps.rot,
+ bounds,
+ size,
+ margin = styles.margin,
+ position = this.get("position"),
+ matrix = new Y.Matrix();
+ matrix.rotate(rot);
+ bounds = matrix.getContentRect(w, h);
+ if(position === "left" || position === "right")
+ {
+ size = bounds.right - bounds.left;
+ if(margin)
+ {
+ size += margin.left + margin.right;
+ }
+ }
+ else
+ {
+ size = bounds.bottom - bounds.top;
+ if(margin)
+ {
+ size += margin.top + margin.bottom;
+ }
+ }
+ this._titleBounds = bounds;
+ this._totalTitleSize = size;
+ },
+
+ /**
+ * Updates path.
+ *
+ * @method _updatePathElement
+ * @private
+ */
+ _updatePathElement: function()
+ {
+ var path = this._path,
+ tickPath = this._tickPath,
+ redrawGraphic = false,
+ graphic = this.get("graphic");
+ if(path)
+ {
+ redrawGraphic = true;
+ path.end();
+ }
+ if(tickPath)
+ {
+ redrawGraphic = true;
+ tickPath.end();
+ }
+ if(redrawGraphic)
+ {
+ graphic._redraw();
+ }
+ },
+
+ /**
+ * Updates the content and style properties for a title field.
+ *
+ * @method _updateTitle
+ * @private
+ */
+ _setTitle: function()
+ {
+ var i,
+ styles,
+ customStyles,
+ title = this.get("title"),
+ titleTextField = this._titleTextField,
+ parentNode;
+ if(title !== null && title !== undefined)
+ {
+ customStyles = {
+ rotation: "rotation",
+ margin: "margin",
+ alpha: "alpha"
+ };
+ styles = this.get("styles").title;
+ if(!titleTextField)
+ {
+ titleTextField = DOCUMENT.createElement('span');
+ titleTextField.style.display = "block";
+ titleTextField.style.whiteSpace = "nowrap";
+ titleTextField.setAttribute("class", "axisTitle");
+ this.get("contentBox").append(titleTextField);
+ }
+ else if(!DOCUMENT.createElementNS)
+ {
+ if(titleTextField.style.filter)
+ {
+ titleTextField.style.filter = null;
+ }
+ }
+ titleTextField.style.position = "absolute";
+ for(i in styles)
+ {
+ if(styles.hasOwnProperty(i) && !customStyles.hasOwnProperty(i))
+ {
+ titleTextField.style[i] = styles[i];
+ }
+ }
+ this.get("appendTitleFunction")(titleTextField, title);
+ this._titleTextField = titleTextField;
+ this._titleRotationProps = this._getTextRotationProps(styles);
+ this._setTotalTitleSize(styles);
+ }
+ else if(titleTextField)
+ {
+ parentNode = titleTextField.parentNode;
+ if(parentNode)
+ {
+ parentNode.removeChild(titleTextField);
+ }
+ this._titleTextField = null;
+ this._totalTitleSize = 0;
+ }
+ },
+
+ /**
+ * Creates or updates an axis label.
+ *
+ * @method getLabel
+ * @param {Object} pt x and y coordinates for the label
+ * @param {Object} styles styles applied to label
+ * @return HTMLElement
+ * @private
+ */
+ getLabel: function(pt, styles)
+ {
+ var i,
+ label,
+ labelCache = this._labelCache,
+ customStyles = {
+ rotation: "rotation",
+ margin: "margin",
+ alpha: "alpha"
+ };
+ if(labelCache && labelCache.length > 0)
+ {
+ label = labelCache.shift();
+ }
+ else
+ {
+ label = DOCUMENT.createElement("span");
+ label.className = Y.Lang.trim([label.className, "axisLabel"].join(' '));
+ this.get("contentBox").append(label);
+ }
+ if(!DOCUMENT.createElementNS)
+ {
+ if(label.style.filter)
+ {
+ label.style.filter = null;
+ }
+ }
+ label.style.display = "block";
+ label.style.whiteSpace = "nowrap";
+ label.style.position = "absolute";
+ for(i in styles)
+ {
+ if(styles.hasOwnProperty(i) && !customStyles.hasOwnProperty(i))
+ {
+ label.style[i] = styles[i];
+ }
+ }
+ return label;
+ },
+
+ /**
+ * Creates a cache of labels that can be re-used when the axis redraws.
+ *
+ * @method _createLabelCache
+ * @private
+ */
+ _createLabelCache: function()
+ {
+ if(this._labels)
+ {
+ while(this._labels.length > 0)
+ {
+ this._labelCache.push(this._labels.shift());
+ }
+ }
+ else
+ {
+ this._clearLabelCache();
+ }
+ this._labels = [];
+ },
+
+ /**
+ * Removes axis labels from the dom and clears the label cache.
+ *
+ * @method _clearLabelCache
+ * @private
+ */
+ _clearLabelCache: function()
+ {
+ if(this._labelCache)
+ {
+ var len = this._labelCache.length,
+ i = 0,
+ label;
+ for(; i < len; ++i)
+ {
+ label = this._labelCache[i];
+ this._removeChildren(label);
+ Y.Event.purgeElement(label, true);
+ label.parentNode.removeChild(label);
+ }
+ }
+ this._labelCache = [];
+ },
+
+ /**
+ * Gets the end point of an axis.
+ *
+ * @method getLineEnd
+ * @return Object
+ * @private
+ */
+ getLineEnd: function(pt)
+ {
+ var w = this.get("width"),
+ h = this.get("height"),
+ pos = this.get("position");
+ if(pos === "top" || pos === "bottom")
+ {
+ return {x:w, y:pt.y};
+ }
+ else
+ {
+ return {x:pt.x, y:h};
+ }
+ },
+
+ /**
+ * Calcuates the width or height of an axis depending on its direction.
+ *
+ * @method getLength
+ * @return Number
+ * @private
+ */
+ getLength: function()
+ {
+ var l,
+ style = this.get("styles"),
+ padding = style.padding,
+ w = this.get("width"),
+ h = this.get("height"),
+ pos = this.get("position");
+ if(pos === "top" || pos === "bottom")
+ {
+ l = w - (padding.left + padding.right);
+ }
+ else
+ {
+ l = h - (padding.top + padding.bottom);
+ }
+ return l;
+ },
+
+ /**
+ * Gets the position of the first point on an axis.
+ *
+ * @method getFirstPoint
+ * @param {Object} pt Object containing x and y coordinates.
+ * @return Object
+ * @private
+ */
+ getFirstPoint:function(pt)
+ {
+ var style = this.get("styles"),
+ pos = this.get("position"),
+ padding = style.padding,
+ np = {x:pt.x, y:pt.y};
+ if(pos === "top" || pos === "bottom")
+ {
+ np.x += padding.left + this.get("edgeOffset");
+ }
+ else
+ {
+ np.y += this.get("height") - (padding.top + this.get("edgeOffset"));
+ }
+ return np;
+ },
+
+ /**
+ * Calculates points based off the majorUnit count or distance of the Axis.
+ *
+ * @method _getPoints
+ * @param {Object} startPoint An object literal containing the x and y coordinates of the first
+ * point on the axis.
+ * @param {Number} len The number of points on an axis.
+ * @param {Number} edgeOffset The distance from the start of the axis and the point.
+ * @param {Number} majorUnitDistance The distance between points on an axis.
+ * @param {String} direction Indicates whether the axis is horizontal or vertical.
+ * @return Array
+ * @private
+ */
+ _getPoints: function(startPoint, len, edgeOffset, majorUnitDistance, direction)
+ {
+ var points = [],
+ i,
+ style = this.get("styles"),
+ staticCoord,
+ dynamicCoord,
+ constantVal,
+ newPoint,
+ padding,
+ coord;
+ if(direction === "vertical")
+ {
+ staticCoord = "x";
+ dynamicCoord = "y";
+ padding = style.padding.top;
+ }
+ else
+ {
+ staticCoord = "y";
+ dynamicCoord = "x";
+ padding = style.padding.left;
+ }
+ constantVal = startPoint[staticCoord];
+ coord = edgeOffset + padding;
+ for(i = 0; i < len; i = i + 1)
+ {
+ newPoint = {};
+ newPoint[staticCoord] = constantVal;
+ newPoint[dynamicCoord] = coord;
+ points.push(newPoint);
+ coord = coord + majorUnitDistance;
+ }
+ return points;
+ },
+
+ /**
+ * Rotates and positions a text field.
+ *
+ * @method _rotate
+ * @param {HTMLElement} label text field to rotate and position
+ * @param {Object} props properties to be applied to the text field.
+ * @private
+ */
+ _rotate: function(label, props)
+ {
+ var rot = props.rot,
+ x = props.x,
+ y = props.y,
+ filterString,
+ textAlpha,
+ matrix = new Y.Matrix(),
+ transformOrigin = props.transformOrigin || [0, 0],
+ offsetRect;
+ if(DOCUMENT.createElementNS)
+ {
+ matrix.translate(x, y);
+ matrix.rotate(rot);
+ Y_DOM.setStyle(label, "transformOrigin", (transformOrigin[0] * 100) + "% " + (transformOrigin[1] * 100) + "%");
+ Y_DOM.setStyle(label, "transform", matrix.toCSSText());
+ }
+ else
+ {
+ textAlpha = props.textAlpha;
+ if(Y_Lang.isNumber(textAlpha) && textAlpha < 1 && textAlpha > -1 && !isNaN(textAlpha))
+ {
+ filterString = "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + Math.round(textAlpha * 100) + ")";
+ }
+ if(rot !== 0)
+ {
+ //ms filters kind of, sort of uses a transformOrigin of 0, 0.
+ //we'll translate the difference to create a true 0, 0 origin.
+ matrix.rotate(rot);
+ offsetRect = matrix.getContentRect(props.labelWidth, props.labelHeight);
+ matrix.init();
+ matrix.translate(offsetRect.left, offsetRect.top);
+ matrix.translate(x, y);
+ this._simulateRotateWithTransformOrigin(matrix, rot, transformOrigin, props.labelWidth, props.labelHeight);
+ if(filterString)
+ {
+ filterString += " ";
+ }
+ else
+ {
+ filterString = "";
+ }
+ filterString += matrix.toFilterText();
+ label.style.left = matrix.dx + "px";
+ label.style.top = matrix.dy + "px";
+ }
+ else
+ {
+ label.style.left = x + "px";
+ label.style.top = y + "px";
+ }
+ if(filterString)
+ {
+ label.style.filter = filterString;
+ }
+ }
+ },
+
+ /**
+ * Simulates a rotation with a specified transformOrigin.
+ *
+ * @method _simulateTransformOrigin
+ * @param {Matrix} matrix Reference to a `Matrix` instance.
+ * @param {Number} rot The rotation (in degrees) that will be performed on a matrix.
+ * @param {Array} transformOrigin An array represeniting the origin in which to perform the transform. The first
+ * index represents the x origin and the second index represents the y origin.
+ * @param {Number} w The width of the object that will be transformed.
+ * @param {Number} h The height of the object that will be transformed.
+ * @private
+ */
+ _simulateRotateWithTransformOrigin: function(matrix, rot, transformOrigin, w, h)
+ {
+ var transformX = transformOrigin[0] * w,
+ transformY = transformOrigin[1] * h;
+ transformX = !isNaN(transformX) ? transformX : 0;
+ transformY = !isNaN(transformY) ? transformY : 0;
+ matrix.translate(transformX, transformY);
+ matrix.rotate(rot);
+ matrix.translate(-transformX, -transformY);
+ },
+
+ /**
+ * Returns the coordinates (top, right, bottom, left) for the bounding box of the last label.
+ *
+ * @method getMaxLabelBounds
+ * @return Object
+ */
+ getMaxLabelBounds: function()
+ {
+ return this._getLabelBounds(this.getMaximumValue());
+ },
+
+ /**
+ * Returns the coordinates (top, right, bottom, left) for the bounding box of the first label.
+ *
+ * @method getMinLabelBounds
+ * @return Object
+ */
+ getMinLabelBounds: function()
+ {
+ return this._getLabelBounds(this.getMinimumValue());
+ },
+
+ /**
+ * Returns the coordinates (top, right, bottom, left) for the bounding box of a label.
+ *
+ * @method _getLabelBounds
+ * @param {String} Value of the label
+ * @return Object
+ * @private
+ */
+ _getLabelBounds: function(val)
+ {
+ var layout = this._layout,
+ labelStyles = this.get("styles").label,
+ matrix = new Y.Matrix(),
+ label,
+ props = this._getTextRotationProps(labelStyles);
+ props.transformOrigin = layout._getTransformOrigin(props.rot);
+ label = this.getLabel({x: 0, y: 0}, labelStyles);
+ this.get("appendLabelFunction")(label, this.get("labelFunction").apply(this, [val, this.get("labelFormat")]));
+ props.labelWidth = label.offsetWidth;
+ props.labelHeight = label.offsetHeight;
+ this._removeChildren(label);
+ Y.Event.purgeElement(label, true);
+ label.parentNode.removeChild(label);
+ props.x = 0;
+ props.y = 0;
+ layout._setRotationCoords(props);
+ matrix.translate(props.x, props.y);
+ this._simulateRotateWithTransformOrigin(matrix, props.rot, props.transformOrigin, props.labelWidth, props.labelHeight);
+ return matrix.getContentRect(props.labelWidth, props.labelHeight);
+ },
+
+ /**
+ * Removes all DOM elements from an HTML element. Used to clear out labels during detruction
+ * phase.
+ *
+ * @method _removeChildren
+ * @private
+ */
+ _removeChildren: function(node)
+ {
+ if(node.hasChildNodes())
+ {
+ var child;
+ while(node.firstChild)
+ {
+ child = node.firstChild;
+ this._removeChildren(child);
+ node.removeChild(child);
+ }
+ }
+ },
+
+ /**
+ * Destructor implementation Axis class. Removes all labels and the Graphic instance from the widget.
+ *
+ * @method destructor
+ * @protected
+ */
+ destructor: function()
+ {
+ var cb = this.get("contentBox").getDOMNode(),
+ labels = this.get("labels"),
+ graphic = this.get("graphic"),
+ label,
+ len = labels ? labels.length : 0;
+ if(len > 0)
+ {
+ while(labels.length > 0)
+ {
+ label = labels.shift();
+ this._removeChildren(label);
+ cb.removeChild(label);
+ label = null;
+ }
+ }
+ if(graphic)
+ {
+ graphic.destroy();
+ }
+ },
+
+ /**
+ * Length in pixels of largest text bounding box. Used to calculate the height of the axis.
+ *
+ * @property maxLabelSize
+ * @type Number
+ * @protected
+ */
+ _maxLabelSize: 0,
+
+ /**
+ * Updates the content of text field. This method writes a value into a text field using
+ * `appendChild`. If the value is a `String`, it is converted to a `TextNode` first.
+ *
+ * @method _setText
+ * @param label {HTMLElement} label to be updated
+ * @param val {String} value with which to update the label
+ * @private
+ */
+ _setText: function(textField, val)
+ {
+ textField.innerHTML = "";
+ if(Y_Lang.isNumber(val))
+ {
+ val = val + "";
+ }
+ else if(!val)
+ {
+ val = "";
+ }
+ if(IS_STRING(val))
+ {
+ val = DOCUMENT.createTextNode(val);
+ }
+ textField.appendChild(val);
+ },
+
+ /**
+ * Returns the total number of majorUnits that will appear on an axis.
+ *
+ * @method getTotalMajorUnits
+ * @return Number
+ */
+ getTotalMajorUnits: function()
+ {
+ var units,
+ majorUnit = this.get("styles").majorUnit,
+ len = this.getLength();
+ if(majorUnit.determinant === "count")
+ {
+ units = majorUnit.count;
+ }
+ else if(majorUnit.determinant === "distance")
+ {
+ units = (len/majorUnit.distance) + 1;
+ }
+ return units;
+ },
+
+ /**
+ * Returns the distance between major units on an axis.
+ *
+ * @method getMajorUnitDistance
+ * @param {Number} len Number of ticks
+ * @param {Number} uiLen Size of the axis.
+ * @param {Object} majorUnit Hash of properties used to determine the majorUnit
+ * @return Number
+ */
+ getMajorUnitDistance: function(len, uiLen, majorUnit)
+ {
+ var dist;
+ if(majorUnit.determinant === "count")
+ {
+ if(!this.get("calculateEdgeOffset"))
+ {
+ len = len - 1;
+ }
+ dist = uiLen/len;
+ }
+ else if(majorUnit.determinant === "distance")
+ {
+ dist = majorUnit.distance;
+ }
+ return dist;
+ },
+
+ /**
+ * Checks to see if data extends beyond the range of the axis. If so,
+ * that data will need to be hidden. This method is internal, temporary and subject
+ * to removal in the future.
+ *
+ * @method _hasDataOverflow
+ * @protected
+ * @return Boolean
+ */
+ _hasDataOverflow: function()
+ {
+ if(this.get("setMin") || this.get("setMax"))
+ {
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Returns a string corresponding to the first label on an
+ * axis.
+ *
+ * @method getMinimumValue
+ * @return String
+ */
+ getMinimumValue: function()
+ {
+ return this.get("minimum");
+ },
+
+ /**
+ * Returns a string corresponding to the last label on an
+ * axis.
+ *
+ * @method getMaximumValue
+ * @return String
+ */
+ getMaximumValue: function()
+ {
+ return this.get("maximum");
+ }
+}, {
+ ATTRS:
+ {
+ /**
+ * When set, defines the width of a vertical axis instance. By default, vertical axes automatically size based
+ * on their contents. When the width attribute is set, the axis will not calculate its width. When the width
+ * attribute is explicitly set, axis labels will postion themselves off of the the inner edge of the axis and the
+ * title, if present, will position itself off of the outer edge. If a specified width is less than the sum of
+ * the axis' contents, excess content will overflow.
+ *
+ * @attribute width
+ * @type Number
+ */
+ width: {
+ lazyAdd: false,
+
+ getter: function()
+ {
+ if(this._explicitWidth)
+ {
+ return this._explicitWidth;
+ }
+ return this._calculatedWidth;
+ },
+
+ setter: function(val)
+ {
+ this._explicitWidth = val;
+ return val;
+ }
+ },
+
+ /**
+ * When set, defines the height of a horizontal axis instance. By default, horizontal axes automatically size based
+ * on their contents. When the height attribute is set, the axis will not calculate its height. When the height
+ * attribute is explicitly set, axis labels will postion themselves off of the the inner edge of the axis and the
+ * title, if present, will position itself off of the outer edge. If a specified height is less than the sum of
+ * the axis' contents, excess content will overflow.
+ *
+ * @attribute height
+ * @type Number
+ */
+ height: {
+ lazyAdd: false,
+
+ getter: function()
+ {
+ if(this._explicitHeight)
+ {
+ return this._explicitHeight;
+ }
+ return this._calculatedHeight;
+ },
+
+ setter: function(val)
+ {
+ this._explicitHeight = val;
+ return val;
+ }
+ },
+
+ /**
+ * Calculated value of an axis' width. By default, the value is used internally for vertical axes. If the `width`
+ * attribute is explicitly set, this value will be ignored.
+ *
+ * @attribute calculatedWidth
+ * @type Number
+ * @private
+ */
+ calculatedWidth: {
+ getter: function()
+ {
+ return this._calculatedWidth;
+ },
+
+ setter: function(val)
+ {
+ this._calculatedWidth = val;
+ return val;
+ }
+ },
+
+ /**
+ * Calculated value of an axis' height. By default, the value is used internally for horizontal axes. If the `height`
+ * attribute is explicitly set, this value will be ignored.
+ *
+ * @attribute calculatedHeight
+ * @type Number
+ * @private
+ */
+ calculatedHeight: {
+ getter: function()
+ {
+ return this._calculatedHeight;
+ },
+
+ setter: function(val)
+ {
+ this._calculatedHeight = val;
+ return val;
+ }
+ },
+
+ /**
+ * Difference between the first/last tick and edge of axis.
+ *
+ * @attribute edgeOffset
+ * @type Number
+ * @protected
+ */
+ edgeOffset:
+ {
+ value: 0
+ },
+
+ /**
+ * The graphic in which the axis line and ticks will be rendered.
+ *
+ * @attribute graphic
+ * @type Graphic
+ */
+ graphic: {},
+
+ /**
+ * @attribute path
+ * @type Shape
+ * @readOnly
+ * @private
+ */
+ path: {
+ readOnly: true,
+
+ getter: function()
+ {
+ if(!this._path)
+ {
+ var graphic = this.get("graphic");
+ if(graphic)
+ {
+ this._path = graphic.addShape({type:"path"});
+ }
+ }
+ return this._path;
+ }
+ },
+
+ /**
+ * @attribute tickPath
+ * @type Shape
+ * @readOnly
+ * @private
+ */
+ tickPath: {
+ readOnly: true,
+
+ getter: function()
+ {
+ if(!this._tickPath)
+ {
+ var graphic = this.get("graphic");
+ if(graphic)
+ {
+ this._tickPath = graphic.addShape({type:"path"});
+ }
+ }
+ return this._tickPath;
+ }
+ },
+
+ /**
+ * Contains the contents of the axis.
+ *
+ * @attribute node
+ * @type HTMLElement
+ */
+ node: {},
+
+ /**
+ * Direction of the axis.
+ *
+ * @attribute position
+ * @type String
+ */
+ position: {
+ lazyAdd: false,
+
+ setter: function(val)
+ {
+ var LayoutClass = this._layoutClasses[val];
+ if(val && val !== "none")
+ {
+ this._layout = new LayoutClass();
+ }
+ return val;
+ }
+ },
+
+ /**
+ * Distance determined by the tick styles used to calculate the distance between the axis
+ * line in relation to the top of the axis.
+ *
+ * @attribute topTickOffset
+ * @type Number
+ */
+ topTickOffset: {
+ value: 0
+ },
+
+ /**
+ * Distance determined by the tick styles used to calculate the distance between the axis
+ * line in relation to the bottom of the axis.
+ *
+ * @attribute bottomTickOffset
+ * @type Number
+ */
+ bottomTickOffset: {
+ value: 0
+ },
+
+ /**
+ * Distance determined by the tick styles used to calculate the distance between the axis
+ * line in relation to the left of the axis.
+ *
+ * @attribute leftTickOffset
+ * @type Number
+ */
+ leftTickOffset: {
+ value: 0
+ },
+
+ /**
+ * Distance determined by the tick styles used to calculate the distance between the axis
+ * line in relation to the right side of the axis.
+ *
+ * @attribute rightTickOffset
+ * @type Number
+ */
+ rightTickOffset: {
+ value: 0
+ },
+
+ /**
+ * Collection of labels used to render the axis.
+ *
+ * @attribute labels
+ * @type Array
+ */
+ labels: {
+ readOnly: true,
+ getter: function()
+ {
+ return this._labels;
+ }
+ },
+
+ /**
+ * Collection of points used for placement of labels and ticks along the axis.
+ *
+ * @attribute tickPoints
+ * @type Array
+ */
+ tickPoints: {
+ readOnly: true,
+
+ getter: function()
+ {
+ if(this.get("position") === "none")
+ {
+ return this.get("styles").majorUnit.count;
+ }
+ return this._tickPoints;
+ }
+ },
+
+ /**
+ * Indicates whether the axis overlaps the graph. If an axis is the inner most axis on a given
+ * position and the tick position is inside or cross, the axis will need to overlap the graph.
+ *
+ * @attribute overlapGraph
+ * @type Boolean
+ */
+ overlapGraph: {
+ value:true,
+
+ validator: function(val)
+ {
+ return Y_Lang.isBoolean(val);
+ }
+ },
+
+ /**
+ * Length in pixels of largest text bounding box. Used to calculate the height of the axis.
+ *
+ * @attribute maxLabelSize
+ * @type Number
+ * @protected
+ */
+ maxLabelSize: {
+ getter: function()
+ {
+ return this._maxLabelSize;
+ },
+
+ setter: function(val)
+ {
+ this._maxLabelSize = val;
+ return val;
+ }
+ },
+
+ /**
+ * Title for the axis. When specified, the title will display. The position of the title is determined by the axis position.
+ * <dl>
+ * <dt>top</dt><dd>Appears above the axis and it labels. The default rotation is 0.</dd>
+ * <dt>right</dt><dd>Appears to the right of the axis and its labels. The default rotation is 90.</dd>
+ * <dt>bottom</dt><dd>Appears below the axis and its labels. The default rotation is 0.</dd>
+ * <dt>left</dt><dd>Appears to the left of the axis and its labels. The default rotation is -90.</dd>
+ * </dl>
+ *
+ * @attribute title
+ * @type String
+ */
+ title: {
+ value: null
+ },
+
+ /**
+ * Function used to append an axis value to an axis label. This function has the following signature:
+ * <dl>
+ * <dt>textField</dt><dd>The axis label to be appended. (`HTMLElement`)</dd>
+ * <dt>val</dt><dd>The value to attach to the text field. This method will accept an `HTMLELement`
+ * or a `String`. This method does not use (`HTMLElement` | `String`)</dd>
+ * </dl>
+ * The default method appends a value to the `HTMLElement` using the `appendChild` method. If the given
+ * value is a `String`, the method will convert the the value to a `textNode` before appending to the
+ * `HTMLElement`. This method will not convert an `HTMLString` to an `HTMLElement`.
+ *
+ * @attribute appendLabelFunction
+ * @type Function
+ */
+ appendLabelFunction: {
+ valueFn: function()
+ {
+ return this._setText;
+ }
+ },
+
+ /**
+ * Function used to append a title value to the title object. This function has the following signature:
+ * <dl>
+ * <dt>textField</dt><dd>The title text field to be appended. (`HTMLElement`)</dd>
+ * <dt>val</dt><dd>The value to attach to the text field. This method will accept an `HTMLELement`
+ * or a `String`. This method does not use (`HTMLElement` | `String`)</dd>
+ * </dl>
+ * The default method appends a value to the `HTMLElement` using the `appendChild` method. If the given
+ * value is a `String`, the method will convert the the value to a `textNode` before appending to the
+ * `HTMLElement` element. This method will not convert an `HTMLString` to an `HTMLElement`.
+ *
+ * @attribute appendTitleFunction
+ * @type Function
+ */
+ appendTitleFunction: {
+ valueFn: function()
+ {
+ return this._setText;
+ }
+ },
+
+ /**
+ * An array containing the unformatted values of the axis labels. By default, TimeAxis, NumericAxis and
+ * StackedAxis labelValues are determined by the majorUnit style. By default, CategoryAxis labels are
+ * determined by the values of the dataProvider.
+ * <p>When the labelValues attribute is explicitly set, the labelValues are dictated by the set value and
+ * the position of ticks and labels are determined by where those values would fall on the axis. </p>
+ *
+ * @attribute labelValues
+ * @type Array
+ */
+ labelValues: {
+ lazyAdd: false,
+
+ setter: function(val)
+ {
+ var opts = arguments[2];
+ if(!val || (opts && opts.src && opts.src === "internal"))
+ {
+ this._labelValuesExplicitlySet = false;
+ }
+ else
+ {
+ this._labelValuesExplicitlySet = true;
+ }
+ return val;
+ }
+ },
+
+ /**
+ * Suppresses the creation of the the first visible label and tick.
+ *
+ * @attribute hideFirstMajorUnit
+ * @type Boolean
+ */
+ hideFirstMajorUnit: {
+ value: false
+ },
+
+ /**
+ * Suppresses the creation of the the last visible label and tick.
+ *
+ * @attribute hideLastMajorUnit
+ * @type Boolean
+ */
+ hideLastMajorUnit: {
+ value: false
+ }
+
+ /**
+ * Style properties used for drawing an axis. This attribute is inherited from `Renderer`. Below are the default values:
+ * <dl>
+ * <dt>majorTicks</dt><dd>Properties used for drawing ticks.
+ * <dl>
+ * <dt>display</dt><dd>Position of the tick. Possible values are `inside`, `outside`, `cross` and `none`.
+ * The default value is `inside`.</dd>
+ * <dt>length</dt><dd>The length (in pixels) of the tick. The default value is 4.</dd>
+ * <dt>color</dt><dd>The color of the tick. The default value is `#dad8c9`</dd>
+ * <dt>weight</dt><dd>Number indicating the width of the tick. The default value is 1.</dd>
+ * <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the tick. The default value is 1.</dd>
+ * </dl>
+ * </dd>
+ * <dt>line</dt><dd>Properties used for drawing the axis line.
+ * <dl>
+ * <dt>weight</dt><dd>Number indicating the width of the axis line. The default value is 1.</dd>
+ * <dt>color</dt><dd>The color of the axis line. The default value is `#dad8c9`.</dd>
+ * <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the tick. The default value is 1.</dd>
+ * </dl>
+ * </dd>
+ * <dt>majorUnit</dt><dd>Properties used to calculate the `majorUnit` for the axis.
+ * <dl>
+ * <dt>determinant</dt><dd>The algorithm used for calculating distance between ticks. The possible options are
+ * `count` and `distance`. If the `determinant` is `count`, the axis ticks will spaced so that a specified number
+ * of ticks appear on the axis. If the `determinant` is `distance`, the axis ticks will spaced out according to
+ * the specified distance. The default value is `count`.</dd>
+ * <dt>count</dt><dd>Number of ticks to appear on the axis when the `determinant` is `count`. The default value is 11.</dd>
+ * <dt>distance</dt><dd>The distance (in pixels) between ticks when the `determinant` is `distance`. The default
+ * value is 75.</dd>
+ * </dl>
+ * </dd>
+ * <dt>label</dt><dd>Properties and styles applied to the axis labels.
+ * <dl>
+ * <dt>color</dt><dd>The color of the labels. The default value is `#808080`.</dd>
+ * <dt>alpha</dt><dd>Number between 0 and 1 indicating the opacity of the labels. The default value is 1.</dd>
+ * <dt>fontSize</dt><dd>The font-size of the labels. The default value is 85%</dd>
+ * <dt>rotation</dt><dd>The rotation, in degrees (between -90 and 90) of the labels. The default value is 0.</dd>
+ * <dt>margin</dt><dd>The distance between the label and the axis/tick. Depending on the position of the `Axis`,
+ * only one of the properties used.
+ * <dl>
+ * <dt>top</dt><dd>Pixel value used for an axis with a `position` of `bottom`. The default value is 4.</dd>
+ * <dt>right</dt><dd>Pixel value used for an axis with a `position` of `left`. The default value is 4.</dd>
+ * <dt>bottom</dt><dd>Pixel value used for an axis with a `position` of `top`. The default value is 4.</dd>
+ * <dt>left</dt><dd>Pixel value used for an axis with a `position` of `right`. The default value is 4.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ *
+ * @attribute styles
+ * @type Object
+ */
+ }
+});
+Y.AxisType = Y.Base.create("baseAxis", Y.Axis, [], {});
+
+
+}, '3.10.3', {"requires": ["dom", "widget", "widget-position", "widget-stack", "graphics", "axis-base"]});