AutorÃa | Ultima modificación | Ver Log |
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,offset = parseFloat(styles.label.offset),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 * offset;}else if(rot === 90){leftOffset -= labelWidth * 0.5;topOffset = topOffset + labelWidth/2 - (labelWidth * offset);}else if(rot === -90){leftOffset -= labelWidth * 0.5;topOffset = topOffset - labelHeight + labelWidth/2 - (labelWidth * offset);}else{leftOffset -= labelWidth + (labelHeight * absRot/360);topOffset -= labelHeight * offset;}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,offset = parseFloat(styles.label.offset),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 * offset;}else if(rot === 90){leftOffset -= labelWidth * 0.5;topOffset = topOffset - labelHeight + labelWidth/2 - (labelWidth * offset);}else if(rot === -90){topOffset = topOffset + labelWidth/2 - (labelWidth * offset);leftOffset -= labelWidth * 0.5;}else{topOffset -= labelHeight * offset;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,offset = parseFloat(styles.label.offset),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 === 90){topOffset -= labelHeight/2 * rot/90;leftOffset = leftOffset + labelHeight/2 - (labelHeight * offset);}else if(rot === -90){topOffset -= labelHeight/2 * absRot/90;leftOffset = leftOffset - labelWidth + labelHeight/2 - (labelHeight * offset);}else if(rot > 0){leftOffset = leftOffset + labelHeight/2 - (labelHeight * offset);topOffset -= labelHeight/2 * rot/90;}else if(rot < 0){leftOffset = leftOffset - labelWidth + labelHeight/2 - (labelHeight * offset);topOffset -= labelHeight/2 * absRot/90;}else{leftOffset -= labelWidth * offset;}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,offset = parseFloat(styles.label.offset),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 * offset;topOffset -= labelHeight;}else{if(rot === 90){leftOffset = leftOffset - labelWidth + labelHeight/2 - (labelHeight * offset);topOffset -= (labelHeight * 0.5);}else if (rot === -90){leftOffset = leftOffset + labelHeight/2 - (labelHeight * offset);topOffset -= (labelHeight * 0.5);}else if(rot > 0){leftOffset = leftOffset - labelWidth + labelHeight/2 - (labelHeight * offset);topOffset -= labelHeight - (labelHeight * rot/180);}else{leftOffset = leftOffset + labelHeight/2 - (labelHeight * offset);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,offset: 0.5,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",len,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,firstPoint,lastPoint,firstLabel,lastLabel,staticCoord,dynamicCoord,edgeOffset,explicitLabels = this._labelValuesExplicitlySet ? this.get("labelValues") : null,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(direction === "vertical"){staticCoord = "x";dynamicCoord = "y";}else{staticCoord = "y";dynamicCoord = "x";}labelData = this._getLabelData(lineStart[staticCoord],staticCoord,dynamicCoord,this.get("minimum"),this.get("maximum"),edgeOffset,layoutLength - edgeOffset - edgeOffset,len,explicitLabels);points = labelData.points;labelValues = labelData.values;len = points.length;if(!this._labelValuesExplicitlySet){this.set("labelValues", labelValues, {src: "internal"});}//Don't create the last label or tick.if(this.get("hideFirstMajorUnit")){firstPoint = points.shift();firstLabel = labelValues.shift();len = len - 1;}//Don't create the last label or tick.if(this.get("hideLastMajorUnit")){lastPoint = points.pop();lastLabel = labelValues.pop();len = len - 1;}if(len < 1){this._clearLabelCache();}else{this.drawLine(path, lineStart, this.getLineEnd(lineStart));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._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(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], points[i], styles, i]);}if(firstPoint){points.unshift(firstPoint);}if(lastPoint){points.push(lastPoint);}if(firstLabel){labelValues.unshift(firstLabel);}if(lastLabel){labelValues.push(lastLabel);}this._tickPoints = points;}}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} styles styles applied to label* @return HTMLElement* @private*/getLabel: function(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;},/*** 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(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;if(majorUnit.determinant === "count"){units = majorUnit.count;}else if(majorUnit.determinant === "distance"){len = this.getLength();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>offset</td><dd>A number between 0 and 1 indicating the relationship of the label to a tick. For a horizontal axis* label, a value of 0 will position the label's left side even to the the tick. A position of 1 would position the* right side of the label with the tick. A position of 0.5 would center the label horizontally with the tick. For a* vertical axis, a value of 0 would position the top of the label with the tick, a value of 1 would position the bottom* of the label with the tick and a value 0 would center the label vertically with the tick. The default value is 0.5.</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.18.1', {"requires": ["dom", "widget", "widget-position", "widget-stack", "graphics", "axis-base"]});