//>>built define("dojox/charting/axis2d/Default", ["dojo/_base/lang", "dojo/_base/array","dojo/_base/sniff", "dojo/_base/declare", "dojo/_base/connect", "dojo/_base/html", "dojo/dom-geometry", "./Invisible", "../scaler/common", "../scaler/linear", "./common", "dojox/gfx", "dojox/lang/utils"], function(lang, arr, has, declare, connect, html, domGeom, Invisible, scommon, lin, acommon, g, du){ /*===== dojox.charting.axis2d.__AxisCtorArgs = function( vertical, fixUpper, fixLower, natural, leftBottom, includeZero, fixed, majorLabels, minorTicks, minorLabels, microTicks, htmlLabels, min, max, from, to, majorTickStep, minorTickStep, microTickStep, labels, labelFunc, maxLabelSize, stroke, majorTick, minorTick, microTick, tick, font, fontColor ){ // summary: // Optional arguments used in the definition of an axis. // // vertical: Boolean? // A flag that says whether an axis is vertical (i.e. y axis) or horizontal. Default is false (horizontal). // fixUpper: String? // Align the greatest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none". Defaults to "none". // fixLower: String? // Align the smallest value on the axis with the specified tick level. Options are "major", "minor", "micro", or "none". Defaults to "none". // natural: Boolean? // Ensure tick marks are made on "natural" numbers. Defaults to false. // leftBottom: Boolean? // The position of a vertical axis; if true, will be placed against the left-bottom corner of the chart. Defaults to true. // includeZero: Boolean? // Include 0 on the axis rendering. Default is false. // fixed: Boolean? // Force all axis labels to be fixed numbers. Default is true. // majorLabels: Boolean? // Flag to draw all labels at major ticks. Default is true. // minorTicks: Boolean? // Flag to draw minor ticks on an axis. Default is true. // minorLabels: Boolean? // Flag to draw labels on minor ticks. Default is true. // microTicks: Boolean? // Flag to draw micro ticks on an axis. Default is false. // htmlLabels: Boolean? // Flag to use HTML (as opposed to the native vector graphics engine) to draw labels. Default is true. // min: Number? // The smallest value on an axis. Default is 0. // max: Number? // The largest value on an axis. Default is 1. // from: Number? // Force the chart to render data visible from this value. Default is 0. // to: Number? // Force the chart to render data visible to this value. Default is 1. // majorTickStep: Number? // The amount to skip before a major tick is drawn. Default is 4. // minorTickStep: Number? // The amount to skip before a minor tick is drawn. Default is 2. // microTickStep: Number? // The amount to skip before a micro tick is drawn. Default is 1. // labels: Object[]? // An array of labels for major ticks, with corresponding numeric values, ordered by value. // labelFunc: Function? // An optional function used to compute label values. // maxLabelSize: Number? // The maximum size, in pixels, for a label. To be used with the optional label function. // stroke: dojox.gfx.Stroke? // An optional stroke to be used for drawing an axis. // majorTick: Object? // An object containing a dojox.gfx.Stroke, and a length (number) for a major tick. // minorTick: Object? // An object containing a dojox.gfx.Stroke, and a length (number) for a minor tick. // microTick: Object? // An object containing a dojox.gfx.Stroke, and a length (number) for a micro tick. // tick: Object? // An object containing a dojox.gfx.Stroke, and a length (number) for a tick. // font: String? // An optional font definition (as used in the CSS font property) for labels. // fontColor: String|dojo.Color? // An optional color to be used in drawing labels. // enableCache: Boolean? // Whether the ticks and labels are cached from one rendering to another. This improves the rendering performance of // successive rendering but penalize the first rendering. For labels it is only working with gfx labels // not html ones. Default false. this.vertical = vertical; this.fixUpper = fixUpper; this.fixLower = fixLower; this.natural = natural; this.leftBottom = leftBottom; this.includeZero = includeZero; this.fixed = fixed; this.majorLabels = majorLabels; this.minorTicks = minorTicks; this.minorLabels = minorLabels; this.microTicks = microTicks; this.htmlLabels = htmlLabels; this.min = min; this.max = max; this.from = from; this.to = to; this.majorTickStep = majorTickStep; this.minorTickStep = minorTickStep; this.microTickStep = microTickStep; this.labels = labels; this.labelFunc = labelFunc; this.maxLabelSize = maxLabelSize; this.stroke = stroke; this.majorTick = majorTick; this.minorTick = minorTick; this.microTick = microTick; this.tick = tick; this.font = font; this.fontColor = fontColor; this.enableCache = enableCache; } var Invisible = dojox.charting.axis2d.Invisible =====*/ var labelGap = 4, // in pixels centerAnchorLimit = 45; // in degrees return declare("dojox.charting.axis2d.Default", Invisible, { // summary: // The default axis object used in dojox.charting. See dojox.charting.Chart.addAxis for details. // // defaultParams: Object // The default parameters used to define any axis. // optionalParams: Object // Any optional parameters needed to define an axis. /* // TODO: the documentation tools need these to be pre-defined in order to pick them up // correctly, but the code here is partially predicated on whether or not the properties // actually exist. For now, we will leave these undocumented but in the code for later. -- TRT // opt: Object // The actual options used to define this axis, created at initialization. // scalar: Object // The calculated helper object to tell charts how to draw an axis and any data. // ticks: Object // The calculated tick object that helps a chart draw the scaling on an axis. // dirty: Boolean // The state of the axis (whether it needs to be redrawn or not) // scale: Number // The current scale of the axis. // offset: Number // The current offset of the axis. opt: null, scalar: null, ticks: null, dirty: true, scale: 1, offset: 0, */ defaultParams: { vertical: false, // true for vertical axis fixUpper: "none", // align the upper on ticks: "major", "minor", "micro", "none" fixLower: "none", // align the lower on ticks: "major", "minor", "micro", "none" natural: false, // all tick marks should be made on natural numbers leftBottom: true, // position of the axis, used with "vertical" includeZero: false, // 0 should be included fixed: true, // all labels are fixed numbers majorLabels: true, // draw major labels minorTicks: true, // draw minor ticks minorLabels: true, // draw minor labels microTicks: false, // draw micro ticks rotation: 0, // label rotation angle in degrees htmlLabels: true, // use HTML to draw labels enableCache: false // whether we cache or not }, optionalParams: { min: 0, // minimal value on this axis max: 1, // maximal value on this axis from: 0, // visible from this value to: 1, // visible to this value majorTickStep: 4, // major tick step minorTickStep: 2, // minor tick step microTickStep: 1, // micro tick step labels: [], // array of labels for major ticks // with corresponding numeric values // ordered by values labelFunc: null, // function to compute label values maxLabelSize: 0, // size in px. For use with labelFunc maxLabelCharCount: 0, // size in word count. trailingSymbol: null, // TODO: add support for minRange! // minRange: 1, // smallest distance from min allowed on the axis // theme components stroke: {}, // stroke for an axis majorTick: {}, // stroke + length for a tick minorTick: {}, // stroke + length for a tick microTick: {}, // stroke + length for a tick tick: {}, // stroke + length for a tick font: "", // font for labels fontColor: "", // color for labels as a string title: "", // axis title titleGap: 0, // gap between axis title and axis label titleFont: "", // axis title font titleFontColor: "", // axis title font color titleOrientation: "" // "axis" means the title facing the axis, "away" means facing away }, constructor: function(chart, kwArgs){ // summary: // The constructor for an axis. // chart: dojox.charting.Chart // The chart the axis belongs to. // kwArgs: dojox.charting.axis2d.__AxisCtorArgs? // Any optional keyword arguments to be used to define this axis. this.opt = lang.clone(this.defaultParams); du.updateWithObject(this.opt, kwArgs); du.updateWithPattern(this.opt, kwArgs, this.optionalParams); if(this.opt.enableCache){ this._textFreePool = []; this._lineFreePool = []; this._textUsePool = []; this._lineUsePool = []; } }, getOffsets: function(){ // summary: // Get the physical offset values for this axis (used in drawing data series). // returns: Object // The calculated offsets in the form of { l, r, t, b } (left, right, top, bottom). var s = this.scaler, offsets = { l: 0, r: 0, t: 0, b: 0 }; if(!s){ return offsets; } var o = this.opt, labelWidth = 0, a, b, c, d, gl = scommon.getNumericLabel, offset = 0, ma = s.major, mi = s.minor, ta = this.chart.theme.axis, // TODO: we use one font --- of major tick, we need to use major and minor fonts taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font), taTitleFont = o.titleFont || (ta.tick && ta.tick.titleFont), taTitleGap = (o.titleGap==0) ? 0 : o.titleGap || (ta.tick && ta.tick.titleGap) || 15, taMajorTick = this.chart.theme.getTick("major", o), taMinorTick = this.chart.theme.getTick("minor", o), size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0, tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0, rotation = o.rotation % 360, leftBottom = o.leftBottom, cosr = Math.abs(Math.cos(rotation * Math.PI / 180)), sinr = Math.abs(Math.sin(rotation * Math.PI / 180)); this.trailingSymbol = (o.trailingSymbol === undefined || o.trailingSymbol === null) ? this.trailingSymbol : o.trailingSymbol; if(rotation < 0){ rotation += 360; } if(size){ // we need width of all labels if(this.labels){ labelWidth = this._groupLabelWidth(this.labels, taFont, o.maxLabelCharCount); }else{ labelWidth = this._groupLabelWidth([ gl(ma.start, ma.prec, o), gl(ma.start + ma.count * ma.tick, ma.prec, o), gl(mi.start, mi.prec, o), gl(mi.start + mi.count * mi.tick, mi.prec, o) ], taFont, o.maxLabelCharCount); } labelWidth = o.maxLabelSize ? Math.min(o.maxLabelSize, labelWidth) : labelWidth; if(this.vertical){ var side = leftBottom ? "l" : "r"; switch(rotation){ case 0: case 180: offsets[side] = labelWidth; offsets.t = offsets.b = size / 2; break; case 90: case 270: offsets[side] = size; offsets.t = offsets.b = labelWidth / 2; break; default: if(rotation <= centerAnchorLimit || (180 < rotation && rotation <= (180 + centerAnchorLimit))){ offsets[side] = size * sinr / 2 + labelWidth * cosr; offsets[leftBottom ? "t" : "b"] = size * cosr / 2 + labelWidth * sinr; offsets[leftBottom ? "b" : "t"] = size * cosr / 2; }else if(rotation > (360 - centerAnchorLimit) || (180 > rotation && rotation > (180 - centerAnchorLimit))){ offsets[side] = size * sinr / 2 + labelWidth * cosr; offsets[leftBottom ? "b" : "t"] = size * cosr / 2 + labelWidth * sinr; offsets[leftBottom ? "t" : "b"] = size * cosr / 2; }else if(rotation < 90 || (180 < rotation && rotation < 270)){ offsets[side] = size * sinr + labelWidth * cosr; offsets[leftBottom ? "t" : "b"] = size * cosr + labelWidth * sinr; }else{ offsets[side] = size * sinr + labelWidth * cosr; offsets[leftBottom ? "b" : "t"] = size * cosr + labelWidth * sinr; } break; } offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length) + (o.title ? (tsize + taTitleGap) : 0); }else{ var side = leftBottom ? "b" : "t"; switch(rotation){ case 0: case 180: offsets[side] = size; offsets.l = offsets.r = labelWidth / 2; break; case 90: case 270: offsets[side] = labelWidth; offsets.l = offsets.r = size / 2; break; default: if((90 - centerAnchorLimit) <= rotation && rotation <= 90 || (270 - centerAnchorLimit) <= rotation && rotation <= 270){ offsets[side] = size * sinr / 2 + labelWidth * cosr; offsets[leftBottom ? "r" : "l"] = size * cosr / 2 + labelWidth * sinr; offsets[leftBottom ? "l" : "r"] = size * cosr / 2; }else if(90 <= rotation && rotation <= (90 + centerAnchorLimit) || 270 <= rotation && rotation <= (270 + centerAnchorLimit)){ offsets[side] = size * sinr / 2 + labelWidth * cosr; offsets[leftBottom ? "l" : "r"] = size * cosr / 2 + labelWidth * sinr; offsets[leftBottom ? "r" : "l"] = size * cosr / 2; }else if(rotation < centerAnchorLimit || (180 < rotation && rotation < (180 - centerAnchorLimit))){ offsets[side] = size * sinr + labelWidth * cosr; offsets[leftBottom ? "r" : "l"] = size * cosr + labelWidth * sinr; }else{ offsets[side] = size * sinr + labelWidth * cosr; offsets[leftBottom ? "l" : "r"] = size * cosr + labelWidth * sinr; } break; } offsets[side] += labelGap + Math.max(taMajorTick.length, taMinorTick.length) + (o.title ? (tsize + taTitleGap) : 0); } } if(labelWidth){ this._cachedLabelWidth = labelWidth; } return offsets; // Object }, cleanGroup: function(creator){ if(this.opt.enableCache && this.group){ this._lineFreePool = this._lineFreePool.concat(this._lineUsePool); this._lineUsePool = []; this._textFreePool = this._textFreePool.concat(this._textUsePool); this._textUsePool = []; } this.inherited(arguments); }, createText: function(labelType, creator, x, y, align, textContent, font, fontColor, labelWidth){ if(!this.opt.enableCache || labelType=="html"){ return acommon.createText[labelType]( this.chart, creator, x, y, align, textContent, font, fontColor, labelWidth ); } var text; if (this._textFreePool.length > 0){ text = this._textFreePool.pop(); text.setShape({x: x, y: y, text: textContent, align: align}); // For now all items share the same font, no need to re-set it //.setFont(font).setFill(fontColor); // was cleared, add it back creator.add(text); }else{ text = acommon.createText[labelType]( this.chart, creator, x, y, align, textContent, font, fontColor, labelWidth ); } this._textUsePool.push(text); return text; }, createLine: function(creator, params){ var line; if(this.opt.enableCache && this._lineFreePool.length > 0){ line = this._lineFreePool.pop(); line.setShape(params); // was cleared, add it back creator.add(line); }else{ line = creator.createLine(params); } if(this.opt.enableCache){ this._lineUsePool.push(line); } return line; }, render: function(dim, offsets){ // summary: // Render/draw the axis. // dim: Object // An object of the form { width, height}. // offsets: Object // An object of the form { l, r, t, b }. // returns: dojox.charting.axis2d.Default // The reference to the axis for functional chaining. if(!this.dirty){ return this; // dojox.charting.axis2d.Default } // prepare variable var o = this.opt, ta = this.chart.theme.axis, leftBottom = o.leftBottom, rotation = o.rotation % 360, start, stop, titlePos, titleRotation=0, titleOffset, axisVector, tickVector, anchorOffset, labelOffset, labelAlign, // TODO: we use one font --- of major tick, we need to use major and minor fonts taFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font), taTitleFont = o.titleFont || (ta.tick && ta.tick.titleFont), // TODO: we use one font color --- we need to use different colors taFontColor = o.fontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "black", taTitleFontColor = o.titleFontColor || (ta.tick && ta.tick.titleFontColor) || "black", taTitleGap = (o.titleGap==0) ? 0 : o.titleGap || (ta.tick && ta.tick.titleGap) || 15, taTitleOrientation = o.titleOrientation || (ta.tick && ta.tick.titleOrientation) || "axis", taMajorTick = this.chart.theme.getTick("major", o), taMinorTick = this.chart.theme.getTick("minor", o), taMicroTick = this.chart.theme.getTick("micro", o), tickSize = Math.max(taMajorTick.length, taMinorTick.length, taMicroTick.length), taStroke = "stroke" in o ? o.stroke : ta.stroke, size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0, cosr = Math.abs(Math.cos(rotation * Math.PI / 180)), sinr = Math.abs(Math.sin(rotation * Math.PI / 180)), tsize = taTitleFont ? g.normalizedLength(g.splitFontString(taTitleFont).size) : 0; if(rotation < 0){ rotation += 360; } if(this.vertical){ start = {y: dim.height - offsets.b}; stop = {y: offsets.t}; titlePos = {y: (dim.height - offsets.b + offsets.t)/2}; titleOffset = size * sinr + (this._cachedLabelWidth || 0) * cosr + labelGap + Math.max(taMajorTick.length, taMinorTick.length) + tsize + taTitleGap; axisVector = {x: 0, y: -1}; labelOffset = {x: 0, y: 0}; tickVector = {x: 1, y: 0}; anchorOffset = {x: labelGap, y: 0}; switch(rotation){ case 0: labelAlign = "end"; labelOffset.y = size * 0.4; break; case 90: labelAlign = "middle"; labelOffset.x = -size; break; case 180: labelAlign = "start"; labelOffset.y = -size * 0.4; break; case 270: labelAlign = "middle"; break; default: if(rotation < centerAnchorLimit){ labelAlign = "end"; labelOffset.y = size * 0.4; }else if(rotation < 90){ labelAlign = "end"; labelOffset.y = size * 0.4; }else if(rotation < (180 - centerAnchorLimit)){ labelAlign = "start"; }else if(rotation < (180 + centerAnchorLimit)){ labelAlign = "start"; labelOffset.y = -size * 0.4; }else if(rotation < 270){ labelAlign = "start"; labelOffset.x = leftBottom ? 0 : size * 0.4; }else if(rotation < (360 - centerAnchorLimit)){ labelAlign = "end"; labelOffset.x = leftBottom ? 0 : size * 0.4; }else{ labelAlign = "end"; labelOffset.y = size * 0.4; } } if(leftBottom){ start.x = stop.x = offsets.l; titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 90 : 270; titlePos.x = offsets.l - titleOffset + (titleRotation == 270 ? tsize : 0); tickVector.x = -1; anchorOffset.x = -anchorOffset.x; }else{ start.x = stop.x = dim.width - offsets.r; titleRotation = (taTitleOrientation && taTitleOrientation == "axis") ? 90 : 270; titlePos.x = dim.width - offsets.r + titleOffset - (titleRotation == 270 ? 0 : tsize); switch(labelAlign){ case "start": labelAlign = "end"; break; case "end": labelAlign = "start"; break; case "middle": labelOffset.x += size; break; } } }else{ start = {x: offsets.l}; stop = {x: dim.width - offsets.r}; titlePos = {x: (dim.width - offsets.r + offsets.l)/2}; titleOffset = size * cosr + (this._cachedLabelWidth || 0) * sinr + labelGap + Math.max(taMajorTick.length, taMinorTick.length) + tsize + taTitleGap; axisVector = {x: 1, y: 0}; labelOffset = {x: 0, y: 0}; tickVector = {x: 0, y: 1}; anchorOffset = {x: 0, y: labelGap}; switch(rotation){ case 0: labelAlign = "middle"; labelOffset.y = size; break; case 90: labelAlign = "start"; labelOffset.x = -size * 0.4; break; case 180: labelAlign = "middle"; break; case 270: labelAlign = "end"; labelOffset.x = size * 0.4; break; default: if(rotation < (90 - centerAnchorLimit)){ labelAlign = "start"; labelOffset.y = leftBottom ? size : 0; }else if(rotation < (90 + centerAnchorLimit)){ labelAlign = "start"; labelOffset.x = -size * 0.4; }else if(rotation < 180){ labelAlign = "start"; labelOffset.y = leftBottom ? 0 : -size; }else if(rotation < (270 - centerAnchorLimit)){ labelAlign = "end"; labelOffset.y = leftBottom ? 0 : -size; }else if(rotation < (270 + centerAnchorLimit)){ labelAlign = "end"; labelOffset.y = leftBottom ? size * 0.4 : 0; }else{ labelAlign = "end"; labelOffset.y = leftBottom ? size : 0; } } if(leftBottom){ start.y = stop.y = dim.height - offsets.b; titleRotation = (taTitleOrientation && taTitleOrientation == "axis") ? 180 : 0; titlePos.y = dim.height - offsets.b + titleOffset - (titleRotation ? tsize : 0); }else{ start.y = stop.y = offsets.t; titleRotation = (taTitleOrientation && taTitleOrientation == "away") ? 180 : 0; titlePos.y = offsets.t - titleOffset + (titleRotation ? 0 : tsize); tickVector.y = -1; anchorOffset.y = -anchorOffset.y; switch(labelAlign){ case "start": labelAlign = "end"; break; case "end": labelAlign = "start"; break; case "middle": labelOffset.y -= size; break; } } } // render shapes this.cleanGroup(); try{ var s = this.group, c = this.scaler, t = this.ticks, canLabel, f = lin.getTransformerFromModel(this.scaler), // GFX Canvas now supports labels, so let's _not_ fallback to HTML anymore on canvas, just use // HTML labels if explicitly asked + no rotation + no IE + no Opera labelType = (!o.title || !titleRotation) && !rotation && this.opt.htmlLabels && !has("ie") && !has("opera") ? "html" : "gfx", dx = tickVector.x * taMajorTick.length, dy = tickVector.y * taMajorTick.length; s.createLine({ x1: start.x, y1: start.y, x2: stop.x, y2: stop.y }).setStroke(taStroke); //create axis title if(o.title){ var axisTitle = acommon.createText[labelType]( this.chart, s, titlePos.x, titlePos.y, "middle", o.title, taTitleFont, taTitleFontColor ); if(labelType == "html"){ this.htmlElements.push(axisTitle); }else{ //as soon as rotation is provided, labelType won't be "html" //rotate gfx labels axisTitle.setTransform(g.matrix.rotategAt(titleRotation, titlePos.x, titlePos.y)); } } // go out nicely instead of try/catch if(t==null){ this.dirty = false; return this; } arr.forEach(t.major, function(tick){ var offset = f(tick.value), elem, x = start.x + axisVector.x * offset, y = start.y + axisVector.y * offset; this.createLine(s, { x1: x, y1: y, x2: x + dx, y2: y + dy }).setStroke(taMajorTick); if(tick.label){ var label = o.maxLabelCharCount ? this.getTextWithLimitCharCount(tick.label, taFont, o.maxLabelCharCount) : { text: tick.label, truncated: false }; label = o.maxLabelSize ? this.getTextWithLimitLength(label.text, taFont, o.maxLabelSize, label.truncated) : label; elem = this.createText(labelType, s, x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x), y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y), labelAlign, label.text, taFont, taFontColor //this._cachedLabelWidth ); // if bidi support was required, the textDir is "auto" and truncation // took place, we need to update the dir of the element for cases as: // Fool label: 111111W (W for bidi character) // truncated label: 11... // in this case for auto textDir the dir will be "ltr" which is wrong. if(this.chart.truncateBidi && label.truncated){ this.chart.truncateBidi(elem, tick.label, labelType); } label.truncated && this.labelTooltip(elem, this.chart, tick.label, label.text, taFont, labelType); if(labelType == "html"){ this.htmlElements.push(elem); }else if(rotation){ elem.setTransform([ {dx: labelOffset.x, dy: labelOffset.y}, g.matrix.rotategAt( rotation, x + dx + anchorOffset.x, y + dy + anchorOffset.y ) ]); } } }, this); dx = tickVector.x * taMinorTick.length; dy = tickVector.y * taMinorTick.length; canLabel = c.minMinorStep <= c.minor.tick * c.bounds.scale; arr.forEach(t.minor, function(tick){ var offset = f(tick.value), elem, x = start.x + axisVector.x * offset, y = start.y + axisVector.y * offset; this.createLine(s, { x1: x, y1: y, x2: x + dx, y2: y + dy }).setStroke(taMinorTick); if(canLabel && tick.label){ var label = o.maxLabelCharCount ? this.getTextWithLimitCharCount(tick.label, taFont, o.maxLabelCharCount) : { text: tick.label, truncated: false }; label = o.maxLabelSize ? this.getTextWithLimitLength(label.text, taFont, o.maxLabelSize, label.truncated) : label; elem = this.createText(labelType, s, x + dx + anchorOffset.x + (rotation ? 0 : labelOffset.x), y + dy + anchorOffset.y + (rotation ? 0 : labelOffset.y), labelAlign, label.text, taFont, taFontColor //this._cachedLabelWidth ); // if bidi support was required, the textDir is "auto" and truncation // took place, we need to update the dir of the element for cases as: // Fool label: 111111W (W for bidi character) // truncated label: 11... // in this case for auto textDir the dir will be "ltr" which is wrong. if(this.chart.getTextDir && label.truncated){ this.chart.truncateBidi(elem, tick.label, labelType); } label.truncated && this.labelTooltip(elem, this.chart, tick.label, label.text, taFont, labelType); if(labelType == "html"){ this.htmlElements.push(elem); }else if(rotation){ elem.setTransform([ {dx: labelOffset.x, dy: labelOffset.y}, g.matrix.rotategAt( rotation, x + dx + anchorOffset.x, y + dy + anchorOffset.y ) ]); } } }, this); dx = tickVector.x * taMicroTick.length; dy = tickVector.y * taMicroTick.length; arr.forEach(t.micro, function(tick){ var offset = f(tick.value), elem, x = start.x + axisVector.x * offset, y = start.y + axisVector.y * offset; this.createLine(s, { x1: x, y1: y, x2: x + dx, y2: y + dy }).setStroke(taMicroTick); }, this); }catch(e){ // squelch } this.dirty = false; return this; // dojox.charting.axis2d.Default }, labelTooltip: function(elem, chart, label, truncatedLabel, font, elemType){ var modules = ["dijit/Tooltip"]; var aroundRect = {type: "rect"}, position = ["above", "below"], fontWidth = g._base._getTextBox(truncatedLabel, {font: font}).w || 0, fontHeight = font ? g.normalizedLength(g.splitFontString(font).size) : 0; if(elemType == "html"){ lang.mixin(aroundRect, html.coords(elem.firstChild, true)); aroundRect.width = Math.ceil(fontWidth); aroundRect.height = Math.ceil(fontHeight); this._events.push({ shape: dojo, handle: connect.connect(elem.firstChild, "onmouseover", this, function(e){ require(modules, function(Tooltip){ Tooltip.show(label, aroundRect, position); }); }) }); this._events.push({ shape: dojo, handle: connect.connect(elem.firstChild, "onmouseout", this, function(e){ require(modules, function(Tooltip){ Tooltip.hide(aroundRect); }); }) }); }else{ var shp = elem.getShape(), lt = html.coords(chart.node, true); aroundRect = lang.mixin(aroundRect, { x: shp.x - fontWidth / 2, y: shp.y }); aroundRect.x += lt.x; aroundRect.y += lt.y; aroundRect.x = Math.round(aroundRect.x); aroundRect.y = Math.round(aroundRect.y); aroundRect.width = Math.ceil(fontWidth); aroundRect.height = Math.ceil(fontHeight); this._events.push({ shape: elem, handle: elem.connect("onmouseenter", this, function(e){ require(modules, function(Tooltip){ Tooltip.show(label, aroundRect, position); }); }) }); this._events.push({ shape: elem, handle: elem.connect("onmouseleave", this, function(e){ require(modules, function(Tooltip){ Tooltip.hide(aroundRect); }); }) }); } } }); });