diff options
Diffstat (limited to 'js/dojo/dojox/charting/Element.js')
| -rw-r--r-- | js/dojo/dojox/charting/Element.js | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/js/dojo/dojox/charting/Element.js b/js/dojo/dojox/charting/Element.js new file mode 100644 index 0000000..2f67b0e --- /dev/null +++ b/js/dojo/dojox/charting/Element.js @@ -0,0 +1,365 @@ +//>>built +define("dojox/charting/Element", ["dojo/_base/lang", "dojo/_base/array", "dojo/dom-construct","dojo/_base/declare", "dojox/gfx", "dojox/gfx/utils", "dojox/gfx/shape"], + function(lang, arr, domConstruct, declare, gfx, utils, shape){ + + return declare("dojox.charting.Element", null, { + // summary: + // A base class that is used to build other elements of a chart, such as + // a series. + // chart: dojox.charting.Chart + // The parent chart for this element. + // group: dojox.gfx.Group + // The visual GFX group representing this element. + // htmlElement: Array + // Any DOMNodes used as a part of this element (such as HTML-based labels). + // dirty: Boolean + // A flag indicating whether or not this element needs to be rendered. + + chart: null, + group: null, + htmlElements: null, + dirty: true, + + constructor: function(chart){ + // summary: + // Creates a new charting element. + // chart: dojox.charting.Chart + // The chart that this element belongs to. + this.chart = chart; + this.group = null; + this.htmlElements = []; + this.dirty = true; + this.trailingSymbol = "..."; + this._events = []; + }, + createGroup: function(creator){ + // summary: + // Convenience function to create a new dojox.gfx.Group. + // creator: dojox.gfx.Surface? + // An optional surface in which to create this group. + // returns: dojox.charting.Element + // A reference to this object for functional chaining. + if(!creator){ creator = this.chart.surface; } + if(!this.group){ + this.group = creator.createGroup(); + } + return this; // dojox.charting.Element + }, + purgeGroup: function(){ + // summary: + // Clear any elements out of our group, and destroy the group. + // returns: dojox.charting.Element + // A reference to this object for functional chaining. + this.destroyHtmlElements(); + if(this.group){ + // since 1.7.x we need dispose shape otherwise there is a memoryleak + utils.forEach(this.group, function(child){ + shape.dispose(child); + }); + this.group.clear(); + this.group.removeShape(); + this.group = null; + } + this.dirty = true; + if(this._events.length){ + arr.forEach(this._events, function(item){ + item.shape.disconnect(item.handle); + }); + this._events = []; + } + return this; // dojox.charting.Element + }, + cleanGroup: function(creator){ + // summary: + // Clean any elements (HTML or GFX-based) out of our group, and create a new one. + // creator: dojox.gfx.Surface? + // An optional surface to work with. + // returns: dojox.charting.Element + // A reference to this object for functional chaining. + this.destroyHtmlElements(); + if(!creator){ creator = this.chart.surface; } + if(this.group){ + this.group.clear(); + }else{ + this.group = creator.createGroup(); + } + this.dirty = true; + return this; // dojox.charting.Element + }, + destroyHtmlElements: function(){ + // summary: + // Destroy any DOMNodes that may have been created as a part of this element. + if(this.htmlElements.length){ + arr.forEach(this.htmlElements, domConstruct.destroy); + this.htmlElements = []; + } + }, + destroy: function(){ + // summary: + // API addition to conform to the rest of the Dojo Toolkit's standard. + this.purgeGroup(); + }, + //text utilities + getTextWidth: function(s, font){ + return gfx._base._getTextBox(s, {font: font}).w || 0; + }, + getTextWithLimitLength: function(s, font, limitWidth, truncated){ + // summary: + // Get the truncated string based on the limited width in px(dichotomy algorithm) + // s: String? + // candidate text. + // font: String? + // text's font style. + // limitWidth: Number? + // text limited width in px. + // truncated: Boolean? + // whether the input text(s) has already been truncated. + // returns: Object + // { + // text: processed text, maybe truncated or not + // truncated: whether text has been truncated + // } + if (!s || s.length <= 0) { + return { + text: "", + truncated: truncated || false + }; + } + if(!limitWidth || limitWidth <= 0){ + return { + text: s, + truncated: truncated || false + }; + } + var delta = 2, + //golden section for dichotomy algorithm + trucPercentage = 0.618, + minStr = s.substring(0,1) + this.trailingSymbol, + minWidth = this.getTextWidth(minStr, font); + if (limitWidth <= minWidth) { + return { + text: minStr, + truncated: true + }; + } + var width = this.getTextWidth(s, font); + if(width <= limitWidth){ + return { + text: s, + truncated: truncated || false + }; + }else{ + var begin = 0, + end = s.length; + while(begin < end){ + if(end - begin <= delta ){ + while (this.getTextWidth(s.substring(0, begin) + this.trailingSymbol, font) > limitWidth) { + begin -= 1; + } + return { + text: (s.substring(0,begin) + this.trailingSymbol), + truncated: true + }; + } + var index = begin + Math.round((end - begin) * trucPercentage), + widthIntercepted = this.getTextWidth(s.substring(0, index), font); + if(widthIntercepted < limitWidth){ + begin = index; + end = end; + }else{ + begin = begin; + end = index; + } + } + } + }, + getTextWithLimitCharCount: function(s, font, wcLimit, truncated){ + // summary: + // Get the truncated string based on the limited character count(dichotomy algorithm) + // s: String? + // candidate text. + // font: String? + // text's font style. + // wcLimit: Number? + // text limited character count. + // truncated: Boolean? + // whether the input text(s) has already been truncated. + // returns: Object + // { + // text: processed text, maybe truncated or not + // truncated: whether text has been truncated + // } + if (!s || s.length <= 0) { + return { + text: "", + truncated: truncated || false + }; + } + if(!wcLimit || wcLimit <= 0 || s.length <= wcLimit){ + return { + text: s, + truncated: truncated || false + }; + } + return { + text: s.substring(0, wcLimit) + this.trailingSymbol, + truncated: true + }; + }, + // fill utilities + _plotFill: function(fill, dim, offsets){ + // process a plot-wide fill + if(!fill || !fill.type || !fill.space){ + return fill; + } + var space = fill.space; + switch(fill.type){ + case "linear": + if(space === "plot" || space === "shapeX" || space === "shapeY"){ + // clone a fill so we can modify properly directly + fill = gfx.makeParameters(gfx.defaultLinearGradient, fill); + fill.space = space; + // process dimensions + if(space === "plot" || space === "shapeX"){ + // process Y + var span = dim.height - offsets.t - offsets.b; + fill.y1 = offsets.t + span * fill.y1 / 100; + fill.y2 = offsets.t + span * fill.y2 / 100; + } + if(space === "plot" || space === "shapeY"){ + // process X + var span = dim.width - offsets.l - offsets.r; + fill.x1 = offsets.l + span * fill.x1 / 100; + fill.x2 = offsets.l + span * fill.x2 / 100; + } + } + break; + case "radial": + if(space === "plot"){ + // this one is used exclusively for scatter charts + // clone a fill so we can modify properly directly + fill = gfx.makeParameters(gfx.defaultRadialGradient, fill); + fill.space = space; + // process both dimensions + var spanX = dim.width - offsets.l - offsets.r, + spanY = dim.height - offsets.t - offsets.b; + fill.cx = offsets.l + spanX * fill.cx / 100; + fill.cy = offsets.t + spanY * fill.cy / 100; + fill.r = fill.r * Math.sqrt(spanX * spanX + spanY * spanY) / 200; + } + break; + case "pattern": + if(space === "plot" || space === "shapeX" || space === "shapeY"){ + // clone a fill so we can modify properly directly + fill = gfx.makeParameters(gfx.defaultPattern, fill); + fill.space = space; + // process dimensions + if(space === "plot" || space === "shapeX"){ + // process Y + var span = dim.height - offsets.t - offsets.b; + fill.y = offsets.t + span * fill.y / 100; + fill.height = span * fill.height / 100; + } + if(space === "plot" || space === "shapeY"){ + // process X + var span = dim.width - offsets.l - offsets.r; + fill.x = offsets.l + span * fill.x / 100; + fill.width = span * fill.width / 100; + } + } + break; + } + return fill; + }, + _shapeFill: function(fill, bbox){ + // process shape-specific fill + if(!fill || !fill.space){ + return fill; + } + var space = fill.space; + switch(fill.type){ + case "linear": + if(space === "shape" || space === "shapeX" || space === "shapeY"){ + // clone a fill so we can modify properly directly + fill = gfx.makeParameters(gfx.defaultLinearGradient, fill); + fill.space = space; + // process dimensions + if(space === "shape" || space === "shapeX"){ + // process X + var span = bbox.width; + fill.x1 = bbox.x + span * fill.x1 / 100; + fill.x2 = bbox.x + span * fill.x2 / 100; + } + if(space === "shape" || space === "shapeY"){ + // process Y + var span = bbox.height; + fill.y1 = bbox.y + span * fill.y1 / 100; + fill.y2 = bbox.y + span * fill.y2 / 100; + } + } + break; + case "radial": + if(space === "shape"){ + // this one is used exclusively for bubble charts and pie charts + // clone a fill so we can modify properly directly + fill = gfx.makeParameters(gfx.defaultRadialGradient, fill); + fill.space = space; + // process both dimensions + fill.cx = bbox.x + bbox.width / 2; + fill.cy = bbox.y + bbox.height / 2; + fill.r = fill.r * bbox.width / 200; + } + break; + case "pattern": + if(space === "shape" || space === "shapeX" || space === "shapeY"){ + // clone a fill so we can modify properly directly + fill = gfx.makeParameters(gfx.defaultPattern, fill); + fill.space = space; + // process dimensions + if(space === "shape" || space === "shapeX"){ + // process X + var span = bbox.width; + fill.x = bbox.x + span * fill.x / 100; + fill.width = span * fill.width / 100; + } + if(space === "shape" || space === "shapeY"){ + // process Y + var span = bbox.height; + fill.y = bbox.y + span * fill.y / 100; + fill.height = span * fill.height / 100; + } + } + break; + } + return fill; + }, + _pseudoRadialFill: function(fill, center, radius, start, end){ + // process pseudo-radial fills + if(!fill || fill.type !== "radial" || fill.space !== "shape"){ + return fill; + } + // clone and normalize fill + var space = fill.space; + fill = gfx.makeParameters(gfx.defaultRadialGradient, fill); + fill.space = space; + if(arguments.length < 4){ + // process both dimensions + fill.cx = center.x; + fill.cy = center.y; + fill.r = fill.r * radius / 100; + return fill; + } + // convert to a linear gradient + var angle = arguments.length < 5 ? start : (end + start) / 2; + return { + type: "linear", + x1: center.x, + y1: center.y, + x2: center.x + fill.r * radius * Math.cos(angle) / 100, + y2: center.y + fill.r * radius * Math.sin(angle) / 100, + colors: fill.colors + }; + return fill; + } + }); +}); |
