266 lines
9.6 KiB
JavaScript
266 lines
9.6 KiB
JavaScript
//>>built
|
|
define("dojox/charting/BidiSupport", ["dojo/_base/lang", "dojo/_base/html", "dojo/_base/array", "dojo/_base/sniff",
|
|
"dojo/dom","dojo/dom-construct",
|
|
"dojox/gfx", "dojox/gfx/_gfxBidiSupport", "./Chart", "./axis2d/common", "dojox/string/BidiEngine", "dojox/lang/functional"],
|
|
function(lang, html, arr, has, dom, domConstruct, g, gBidi, Chart, da, BidiEngine, df){
|
|
|
|
var bidiEngine = new BidiEngine();
|
|
|
|
lang.extend(Chart, {
|
|
// summary:
|
|
// Add support for bidi scripts.
|
|
// description:
|
|
// Bidi stands for support for languages with a bidirectional script.
|
|
// There's a special need for displaying BIDI text in rtl direction
|
|
// in ltr GUI, sometimes needed auto support.
|
|
// dojox.charting does not support control over base text direction provided in Dojo.
|
|
|
|
// textDir: String
|
|
// Bi-directional support, the main variable which is responsible for the direction of the text.
|
|
// The text direction can be different than the GUI direction by using this parameter.
|
|
// Allowed values:
|
|
// 1. "ltr"
|
|
// 2. "rtl"
|
|
// 3. "auto" - contextual the direction of a text defined by first strong letter.
|
|
// By default is as the page direction.
|
|
textDir:"",
|
|
|
|
getTextDir: function(/*String*/text){
|
|
// summary:
|
|
// Return direction of the text.
|
|
// description:
|
|
// If textDir is ltr or rtl returns the value.
|
|
// If it's auto, calls to another function that responsible
|
|
// for checking the value, and defining the direction.
|
|
// text:
|
|
// Used in case textDir is "auto", this case the direction is according to the first
|
|
// strong (directionally - which direction is strong defined) letter.
|
|
// tags:
|
|
// protected.
|
|
var textDir = this.textDir == "auto" ? bidiEngine.checkContextual(text) : this.textDir;
|
|
// providing default value
|
|
if(!textDir){
|
|
textDir = html.style(this.node,"direction");
|
|
}
|
|
return textDir;
|
|
},
|
|
|
|
postscript: function(node,args){
|
|
// summary:
|
|
// Kicks off chart instantiation.
|
|
// description:
|
|
// Used for setting the textDir of the chart.
|
|
// tags:
|
|
// private
|
|
|
|
// validate textDir
|
|
var textDir = args ? (args["textDir"] ? validateTextDir(args["textDir"]) : "") : "";
|
|
// if textDir wasn't defined or was defined wrong, apply default value
|
|
textDir = textDir ? textDir : html.style(this.node,"direction");
|
|
this.textDir = textDir;
|
|
|
|
this.surface.textDir = textDir;
|
|
|
|
// two data structures, used for storing data for further enablement to change
|
|
// textDir dynamically
|
|
this.htmlElementsRegistry = [];
|
|
this.truncatedLabelsRegistry = [];
|
|
},
|
|
|
|
setTextDir: function(/*String*/ newTextDir, obj){
|
|
// summary:
|
|
// Setter for the textDir attribute.
|
|
// description:
|
|
// Allows dynamically set the textDir, goes over all the text-children and
|
|
// updates their base text direction.
|
|
// tags:
|
|
// public
|
|
|
|
if(newTextDir == this.textDir){
|
|
return this;
|
|
}
|
|
if(validateTextDir(newTextDir) != null){
|
|
this.textDir = newTextDir;
|
|
|
|
// set automatically all the gfx objects that were created by this surface
|
|
// (groups, text objects)
|
|
this.surface.setTextDir(newTextDir);
|
|
|
|
// truncated labels that were created with gfx creator need to recalculate dir
|
|
// for case like: "111111A" (A stands for bidi character) and the truncation
|
|
// is "111..." If the textDir is auto, the display should be: "...111" but in gfx
|
|
// case we will get "111...". Because this.surface.setTextDir will calculate the dir of truncated
|
|
// label, which value is "111..." but th real is "111111A".
|
|
// each time we created a gfx truncated label we stored it in the truncatedLabelsRegistry, so update now
|
|
// the registry.
|
|
if(this.truncatedLabelsRegistry && newTextDir == "auto"){
|
|
arr.forEach(this.truncatedLabelsRegistry, function(elem){
|
|
var tDir = this.getTextDir(elem["label"]);
|
|
if(elem["element"].textDir != tDir){
|
|
elem["element"].setShape({textDir: tDir});
|
|
}
|
|
}, this);
|
|
}
|
|
|
|
// re-render axes with html labels. for recalculation of the labels
|
|
// positions etc.
|
|
// create array of keys for all the axis in chart
|
|
var axesKeyArr = df.keys(this.axes);
|
|
if(axesKeyArr.length > 0){
|
|
// iterate over the axes, and for each that have html labels render it.
|
|
arr.forEach(axesKeyArr, function(key, index, arr){
|
|
// get the axis
|
|
var axis = this.axes[key];
|
|
// if the axis has html labels
|
|
if(axis.htmlElements[0]){
|
|
axis.dirty = true;
|
|
axis.render(this.dim, this.offsets);
|
|
}
|
|
},this);
|
|
|
|
// recreate title
|
|
if(this.title){
|
|
var forceHtmlLabels = (g.renderer == "canvas"),
|
|
labelType = forceHtmlLabels || !has("ie") && !has("opera") ? "html" : "gfx",
|
|
tsize = g.normalizedLength(g.splitFontString(this.titleFont).size);
|
|
// remove the title
|
|
domConstruct.destroy(this.chartTitle);
|
|
this.chartTitle =null;
|
|
// create the new title
|
|
this.chartTitle = da.createText[labelType](
|
|
this,
|
|
this.surface,
|
|
this.dim.width/2,
|
|
this.titlePos=="top" ? tsize + this.margins.t : this.dim.height - this.margins.b,
|
|
"middle",
|
|
this.title,
|
|
this.titleFont,
|
|
this.titleFontColor
|
|
);
|
|
}
|
|
}else{
|
|
// case of pies, spiders etc.
|
|
arr.forEach(this.htmlElementsRegistry, function(elem, index, arr){
|
|
var tDir = newTextDir == "auto" ? this.getTextDir(elem[4]) : newTextDir;
|
|
if(elem[0].children[0] && elem[0].children[0].dir != tDir){
|
|
dom.destroy(elem[0].children[0]);
|
|
elem[0].children[0] = da.createText["html"]
|
|
(this, this.surface, elem[1], elem[2], elem[3], elem[4], elem[5], elem[6]).children[0];
|
|
}
|
|
},this);
|
|
}
|
|
}
|
|
},
|
|
|
|
truncateBidi: function(elem, label, labelType){
|
|
// summary:
|
|
// Enables bidi support for truncated labels.
|
|
// description:
|
|
// Can be two types of labels: html or gfx.
|
|
// gfx labels:
|
|
// Need to be stored in registry to be used when the textDir will be set dynamically.
|
|
// Additional work on truncated labels is needed for case as 111111A (A stands for "bidi" character rtl directioned).
|
|
// let say in this case the truncation is "111..." If the textDir is auto, the display should be: "...111" but in gfx
|
|
// case we will get "111...". Because this.surface.setTextDir will calculate the dir of truncated
|
|
// label, which value is "111..." but th real is "111111A".
|
|
// each time we created a gfx truncated label we store it in the truncatedLabelsRegistry.
|
|
// html labels:
|
|
// no need for repository (stored in another place). Here we only need to update the current dir according to textDir.
|
|
// tags:
|
|
// private
|
|
|
|
if(labelType == "gfx"){
|
|
// store truncated gfx labels in the data structure.
|
|
this.truncatedLabelsRegistry.push({element: elem, label: label});
|
|
if(this.textDir == "auto"){
|
|
elem.setShape({textDir: this.getTextDir(label)});
|
|
}
|
|
}
|
|
if(labelType == "html" && this.textDir == "auto"){
|
|
elem.children[0].dir = this.getTextDir(label);
|
|
}
|
|
}
|
|
});
|
|
|
|
var extendMethod = function(obj, method, bundleByPrototype, before, after){
|
|
// Some helper function. Used for extending method of obj.
|
|
// obj: Object
|
|
// The obj we overriding it's method.
|
|
// method: String
|
|
// The method that is extended, the original method is called before or after
|
|
// functions that passed to extendMethod.
|
|
// bundleByPrototype: boolean
|
|
// There's two methods to extend, using prototype or not.
|
|
// before: function
|
|
// If defined this function will be executed before the original method.
|
|
// after: function
|
|
// If defined this function will be executed after the original method.
|
|
if(bundleByPrototype){
|
|
var old = obj.prototype[method];
|
|
obj.prototype[method] =
|
|
function(){
|
|
var rBefore;
|
|
if (before){
|
|
rBefore = before.apply(this, arguments);
|
|
}
|
|
var r = old.apply(this, rBefore);
|
|
if (after){
|
|
r = after.call(this, r, arguments);
|
|
}
|
|
return r;
|
|
};
|
|
}else{
|
|
var old = lang.clone(obj[method]);
|
|
obj[method] =
|
|
function(){
|
|
var rBefore;
|
|
if (before){
|
|
rBefore = before.apply(this, arguments);
|
|
}
|
|
var r = old.apply(this, arguments);
|
|
if (after){
|
|
after(r, arguments);
|
|
}
|
|
return r;
|
|
};
|
|
}
|
|
};
|
|
|
|
var labelPreprocess = function(elem, chart, label, truncatedLabel, font, elemType){
|
|
// aditional preprocessing of the labels, needed for rtl base text direction in LTR
|
|
// GUI, or for ltr base text direction for RTL GUI.
|
|
|
|
var isChartDirectionRtl = (html.style(chart.node,"direction") == "rtl");
|
|
var isBaseTextDirRtl = (chart.getTextDir(label) == "rtl");
|
|
|
|
if(isBaseTextDirRtl && !isChartDirectionRtl){
|
|
label = "<span dir='rtl'>" + label +"</span>";
|
|
}
|
|
if(!isBaseTextDirRtl && isChartDirectionRtl){
|
|
label = "<span dir='ltr'>" + label +"</span>";
|
|
}
|
|
|
|
return arguments;
|
|
};
|
|
|
|
// connect labelPreprocess to run before labelTooltip.
|
|
// patch it only is available
|
|
if(dojox.charting.axis2d && dojox.charting.axis2d.Default){
|
|
extendMethod(dojox.charting.axis2d.Default,"labelTooltip",true, labelPreprocess, null);
|
|
//extendMethod(dijit,"showTooltip",false, labelPreprocess, null);
|
|
}
|
|
|
|
function htmlCreateText(r, agumentsArr){
|
|
// function to register HTML elements that created by html.createText, this array
|
|
// needed for allowing to change textDir dynamically.
|
|
agumentsArr[0].htmlElementsRegistry.push([r, agumentsArr[2], agumentsArr[3], agumentsArr[4], agumentsArr[5], agumentsArr[6], agumentsArr[7]]);
|
|
}
|
|
|
|
extendMethod(da.createText,"html", false, null, htmlCreateText);
|
|
|
|
function validateTextDir(textDir){
|
|
return /^(ltr|rtl|auto)$/.test(textDir) ? textDir : null;
|
|
}
|
|
|
|
});
|