/** * 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;