1 | define(["dojox/main", "dojo/_base/declare", "dojo/_base/lang", "dojo/dom-style", "dojo/_base/array", "dojo/sniff", |
---|
2 | "dojo/dom","dojo/dom-construct", |
---|
3 | "dojox/gfx", "dojox/gfx/_gfxBidiSupport", "../axis2d/common", "dojox/string/BidiEngine", |
---|
4 | "dojox/lang/functional","dojo/dom-attr","./_bidiutils"], |
---|
5 | function(dojox, declare, lang, domStyle, arr, has, dom, domConstruct, g, gBidi, da, BidiEngine, df, domAttr,utils){ |
---|
6 | // module: |
---|
7 | // dojox/charting/bidi/Chart |
---|
8 | var bidiEngine = new BidiEngine(); |
---|
9 | var dc = lang.getObject("charting", true, dojox); |
---|
10 | function validateTextDir(textDir){ |
---|
11 | return /^(ltr|rtl|auto)$/.test(textDir) ? textDir : null; |
---|
12 | }; |
---|
13 | |
---|
14 | return declare(null, { |
---|
15 | // textDir: String |
---|
16 | // Bi-directional support, the main variable which is responsible for the direction of the text. |
---|
17 | // The text direction can be different than the GUI direction by using this parameter. |
---|
18 | // Allowed values: |
---|
19 | // |
---|
20 | // 1. "ltr" |
---|
21 | // 2. "rtl" |
---|
22 | // 3. "auto" - contextual the direction of a text defined by first strong letter. |
---|
23 | // |
---|
24 | // By default is as the page direction. |
---|
25 | textDir:"", |
---|
26 | |
---|
27 | // dir: String |
---|
28 | // Mirroring support, the main variable which is responsible for the direction of the chart. |
---|
29 | // |
---|
30 | // Allowed values: |
---|
31 | // 1. "ltr" |
---|
32 | // 2. "rtl" |
---|
33 | // |
---|
34 | // By default is ltr. |
---|
35 | dir: "", |
---|
36 | isMirrored: false, |
---|
37 | |
---|
38 | getTextDir: function(text){ |
---|
39 | // summary: |
---|
40 | // Return direction of the text. |
---|
41 | // description: |
---|
42 | // If textDir is ltr or rtl returns the value. |
---|
43 | // If it's auto, calls to another function that responsible |
---|
44 | // for checking the value, and defining the direction. |
---|
45 | // text: |
---|
46 | // Used in case textDir is "auto", this case the direction is according to the first |
---|
47 | // strong (directionally - which direction is strong defined) letter. |
---|
48 | // tags: |
---|
49 | // protected. |
---|
50 | var textDir = this.textDir == "auto" ? bidiEngine.checkContextual(text) : this.textDir; |
---|
51 | // providing default value |
---|
52 | if(!textDir){ |
---|
53 | textDir = domStyle.get(this.node, "direction"); |
---|
54 | } |
---|
55 | return textDir; |
---|
56 | }, |
---|
57 | |
---|
58 | postscript: function(node,args){ |
---|
59 | // summary: |
---|
60 | // Kicks off chart instantiation. |
---|
61 | // description: |
---|
62 | // Used for setting the textDir of the chart. |
---|
63 | // tags: |
---|
64 | // private |
---|
65 | |
---|
66 | // validate textDir |
---|
67 | var textDir = args ? (args["textDir"] ? validateTextDir(args["textDir"]) : "") : ""; |
---|
68 | // if textDir wasn't defined or was defined wrong, apply default value |
---|
69 | textDir = textDir ? textDir : domStyle.get(this.node, "direction"); |
---|
70 | this.textDir = textDir; |
---|
71 | |
---|
72 | this.surface.textDir = textDir; |
---|
73 | |
---|
74 | // two data structures, used for storing data for further enablement to change |
---|
75 | // textDir dynamically |
---|
76 | this.htmlElementsRegistry = []; |
---|
77 | this.truncatedLabelsRegistry = []; |
---|
78 | // chart mirroring starts |
---|
79 | var chartDir = "ltr"; |
---|
80 | if(domAttr.has(node, "direction")){ |
---|
81 | chartDir = domAttr.get(node, "direction"); |
---|
82 | } |
---|
83 | this.setDir(args ? (args.dir ? args.dir: chartDir) : chartDir); |
---|
84 | // chart mirroring ends |
---|
85 | }, |
---|
86 | |
---|
87 | setTextDir: function(newTextDir, obj){ |
---|
88 | // summary: |
---|
89 | // Setter for the textDir attribute. |
---|
90 | // description: |
---|
91 | // Allows dynamically set the textDir, goes over all the text-children and |
---|
92 | // updates their base text direction. |
---|
93 | // tags: |
---|
94 | // public |
---|
95 | |
---|
96 | if(newTextDir == this.textDir){ |
---|
97 | return this; |
---|
98 | } |
---|
99 | if(validateTextDir(newTextDir) != null){ |
---|
100 | this.textDir = newTextDir; |
---|
101 | |
---|
102 | // set automatically all the gfx objects that were created by this surface |
---|
103 | // (groups, text objects) |
---|
104 | this.surface.setTextDir(newTextDir); |
---|
105 | |
---|
106 | // truncated labels that were created with gfx creator need to recalculate dir |
---|
107 | // for case like: "111111A" (A stands for bidi character) and the truncation |
---|
108 | // is "111..." If the textDir is auto, the display should be: "...111" but in gfx |
---|
109 | // case we will get "111...". Because this.surface.setTextDir will calculate the dir of truncated |
---|
110 | // label, which value is "111..." but th real is "111111A". |
---|
111 | // each time we created a gfx truncated label we stored it in the truncatedLabelsRegistry, so update now |
---|
112 | // the registry. |
---|
113 | if(this.truncatedLabelsRegistry && newTextDir == "auto"){ |
---|
114 | arr.forEach(this.truncatedLabelsRegistry, function(elem){ |
---|
115 | var tDir = this.getTextDir(elem["label"]); |
---|
116 | if(elem["element"].textDir != tDir){ |
---|
117 | elem["element"].setShape({textDir: tDir}); |
---|
118 | } |
---|
119 | }, this); |
---|
120 | } |
---|
121 | |
---|
122 | // re-render axes with html labels. for recalculation of the labels |
---|
123 | // positions etc. |
---|
124 | // create array of keys for all the axis in chart |
---|
125 | var axesKeyArr = df.keys(this.axes); |
---|
126 | if(axesKeyArr.length > 0){ |
---|
127 | // iterate over the axes, and for each that have html labels render it. |
---|
128 | arr.forEach(axesKeyArr, function(key, index, arr){ |
---|
129 | // get the axis |
---|
130 | var axis = this.axes[key]; |
---|
131 | // if the axis has html labels |
---|
132 | if(axis.htmlElements[0]){ |
---|
133 | axis.dirty = true; |
---|
134 | axis.render(this.dim, this.offsets); |
---|
135 | } |
---|
136 | },this); |
---|
137 | |
---|
138 | // recreate title |
---|
139 | if(this.title){ |
---|
140 | var forceHtmlLabels = (g.renderer == "canvas"), |
---|
141 | labelType = forceHtmlLabels || !has("ie") && !has("opera") ? "html" : "gfx", |
---|
142 | tsize = g.normalizedLength(g.splitFontString(this.titleFont).size); |
---|
143 | // remove the title |
---|
144 | domConstruct.destroy(this.chartTitle); |
---|
145 | this.chartTitle =null; |
---|
146 | // create the new title |
---|
147 | this.chartTitle = da.createText[labelType]( |
---|
148 | this, |
---|
149 | this.surface, |
---|
150 | this.dim.width/2, |
---|
151 | this.titlePos=="top" ? tsize + this.margins.t : this.dim.height - this.margins.b, |
---|
152 | "middle", |
---|
153 | this.title, |
---|
154 | this.titleFont, |
---|
155 | this.titleFontColor |
---|
156 | ); |
---|
157 | } |
---|
158 | }else{ |
---|
159 | // case of pies, spiders etc. |
---|
160 | arr.forEach(this.htmlElementsRegistry, function(elem, index, arr){ |
---|
161 | var tDir = newTextDir == "auto" ? this.getTextDir(elem[4]) : newTextDir; |
---|
162 | if(elem[0].children[0] && elem[0].children[0].dir != tDir){ |
---|
163 | domConstruct.destroy(elem[0].children[0]); |
---|
164 | elem[0].children[0] = da.createText["html"] |
---|
165 | (this, this.surface, elem[1], elem[2], elem[3], elem[4], elem[5], elem[6]).children[0]; |
---|
166 | } |
---|
167 | },this); |
---|
168 | } |
---|
169 | } |
---|
170 | return this; |
---|
171 | }, |
---|
172 | |
---|
173 | setDir : function(dir){ |
---|
174 | // summary: |
---|
175 | // Setter for the dir attribute. |
---|
176 | // description: |
---|
177 | // Allows dynamically set the dri attribute, which will used to |
---|
178 | // updates the chart rendering direction. |
---|
179 | // dir : the desired chart direction [rtl: for right to left ,ltr: for left to right] |
---|
180 | |
---|
181 | if(dir == "rtl" || dir == "ltr"){ |
---|
182 | if(this.dir != dir){ |
---|
183 | this.isMirrored = true; |
---|
184 | this.dirty = true; |
---|
185 | } |
---|
186 | this.dir = dir; |
---|
187 | } |
---|
188 | return this; |
---|
189 | }, |
---|
190 | |
---|
191 | isRightToLeft: function(){ |
---|
192 | // summary: |
---|
193 | // check the direction of the chart. |
---|
194 | // description: |
---|
195 | // check the dir attribute to determine the rendering direction |
---|
196 | // of the chart. |
---|
197 | return this.dir == "rtl"; |
---|
198 | }, |
---|
199 | |
---|
200 | applyMirroring: function(plot, dim, offsets){ |
---|
201 | // summary: |
---|
202 | // apply the mirroring operation to the current chart plots. |
---|
203 | // |
---|
204 | utils.reverseMatrix(plot, dim, offsets, this.dir == "rtl"); |
---|
205 | //force the direction of the node to be ltr to properly render the axes and the plots labels. |
---|
206 | domStyle.set(this.node, "direction", "ltr"); |
---|
207 | return this; |
---|
208 | }, |
---|
209 | |
---|
210 | formatTruncatedLabel: function(element, label, labelType){ |
---|
211 | this.truncateBidi(element, label, labelType); |
---|
212 | }, |
---|
213 | |
---|
214 | truncateBidi: function(elem, label, labelType){ |
---|
215 | // summary: |
---|
216 | // Enables bidi support for truncated labels. |
---|
217 | // description: |
---|
218 | // Can be two types of labels: html or gfx. |
---|
219 | // |
---|
220 | // ####gfx labels: |
---|
221 | // |
---|
222 | // Need to be stored in registry to be used when the textDir will be set dynamically. |
---|
223 | // Additional work on truncated labels is needed for case as 111111A (A stands for "bidi" character rtl directioned). |
---|
224 | // let's say in this case the truncation is "111..." If the textDir is auto, the display should be: "...111" but in gfx |
---|
225 | // case we will get "111...". Because this.surface.setTextDir will calculate the dir of truncated |
---|
226 | // label, which value is "111..." but th real is "111111A". |
---|
227 | // each time we created a gfx truncated label we store it in the truncatedLabelsRegistry. |
---|
228 | // |
---|
229 | // ####html labels: |
---|
230 | // |
---|
231 | // no need for repository (stored in another place). Here we only need to update the current dir according to textDir. |
---|
232 | // tags: |
---|
233 | // private |
---|
234 | |
---|
235 | if(labelType == "gfx"){ |
---|
236 | // store truncated gfx labels in the data structure. |
---|
237 | this.truncatedLabelsRegistry.push({element: elem, label: label}); |
---|
238 | if(this.textDir == "auto"){ |
---|
239 | elem.setShape({textDir: this.getTextDir(label)}); |
---|
240 | } |
---|
241 | } |
---|
242 | if(labelType == "html" && this.textDir == "auto"){ |
---|
243 | elem.children[0].dir = this.getTextDir(label); |
---|
244 | } |
---|
245 | }, |
---|
246 | |
---|
247 | render: function(){ |
---|
248 | this.inherited(arguments); |
---|
249 | this.isMirrored = false; |
---|
250 | return this; |
---|
251 | }, |
---|
252 | |
---|
253 | _resetLeftBottom: function(axis){ |
---|
254 | if(axis.vertical && this.isMirrored){ |
---|
255 | axis.opt.leftBottom = !axis.opt.leftBottom; |
---|
256 | } |
---|
257 | } |
---|
258 | }); |
---|
259 | }); |
---|
260 | |
---|