source: Dev/trunk/src/client/dojox/string/BidiComplex.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 8.1 KB
Line 
1// summary:
2//              BiDiComplex module handles complex expression issues known when using BiDi characters
3//              in File Paths, URLs, E-mail Address, XPATH, etc.
4//              this module adds property listeners to the text fields to correct the text representation
5//              in both static text and dynamic text during user input.
6
7define(["dojo/_base/kernel", "dojo/_base/lang", "dojo/_base/array", "dojo/_base/connect", "dojo/_base/sniff",
8                "dojo/keys"],
9  function(dojo, lang, arr, hub, has, keys){
10        dojo.experimental("dojox.string.BidiComplex");
11        var bdc = lang.getObject("string.BidiComplex", true, dojox);
12
13        var _str0 = []; //FIXME: shared reference here among various functions means the functions can't be reused
14
15        bdc.attachInput = function(/*DOMNode*/field, /*String*/pattern){
16                // summary:
17                //              Attach key listeners to the INPUT field to accomodate dynamic complex BiDi expressions
18                // field: INPUT DOM node
19                // pattern: Complex Expression Pattern type. One of "FILE_PATH", "URL", "EMAIL", "XPATH"
20
21                field.alt = pattern;
22
23                hub.connect(field, "onkeydown",  this, "_ceKeyDown");
24                hub.connect(field, "onkeyup", this, "_ceKeyUp");
25
26                hub.connect(field, "oncut", this, "_ceCutText");
27                hub.connect(field, "oncopy", this, "_ceCopyText");
28
29                field.value = bdc.createDisplayString(field.value, field.alt);
30        };
31               
32        bdc.createDisplayString = function(/*String*/str, /*String*/pattern){
33                // summary:
34                //              Create the display string by adding the Unicode direction Markers
35                // pattern: Complex Expression Pattern type. One of "FILE_PATH", "URL", "EMAIL", "XPATH"
36
37                str = bdc.stripSpecialCharacters(str);
38                var segmentsPointers = bdc._parse(str, pattern);
39               
40                var buf = '\u202A'/*LRE*/ + str;
41                var shift = 1;
42                arr.forEach(segmentsPointers, function(n){
43                        if(n != null){
44                                var preStr = buf.substring(0, n + shift);
45                                var postStr = buf.substring(n + shift, buf.length);
46                                buf = preStr + '\u200E'/*LRM*/ + postStr;
47                                shift++;
48                        }
49                });
50                return buf;
51        };
52
53        bdc.stripSpecialCharacters = function(str){
54                // summary:
55                //              removes all Unicode directional markers from the string
56
57                return str.replace(/[\u200E\u200F\u202A-\u202E]/g, ""); // String
58        };
59
60        bdc._ceKeyDown = function(event){
61                var elem = has("ie") ? event.srcElement : event.target;
62                _str0 = elem.value;
63        };
64                               
65        bdc._ceKeyUp = function(event){
66                var LRM = '\u200E';
67                var elem = has("ie") ? event.srcElement : event.target;
68
69                var str1 = elem.value;
70                var ieKey = event.keyCode;
71               
72                if((ieKey == keys.HOME)
73                        || (ieKey == keys.END)
74                        || (ieKey == keys.SHIFT)){
75                        return;
76                }
77
78                var cursorStart, cursorEnd;
79                var selection = bdc._getCaretPos(event, elem);
80                if(selection){
81                        cursorStart = selection[0];
82                        cursorEnd = selection[1];
83                }
84
85        //Jump over a cursor processing
86                if(has("ie")){
87                        var cursorStart1 = cursorStart, cursorEnd1 = cursorEnd;
88
89                        if(ieKey == keys.LEFT_ARROW){
90                                if((str1.charAt(cursorEnd-1) == LRM)
91                                                && (cursorStart == cursorEnd)){
92                                        bdc._setSelectedRange(elem,cursorStart - 1, cursorEnd - 1);
93                                }
94                                return;
95                        }
96
97                        if(ieKey == keys.RIGHT_ARROW){
98                                if(str1.charAt(cursorEnd-1) == LRM){
99                                        cursorEnd1 = cursorEnd + 1;
100                                        if(cursorStart == cursorEnd){
101                                                cursorStart1 = cursorStart + 1;
102                                        }
103                                }
104
105                                bdc._setSelectedRange(elem, cursorStart1, cursorEnd1);
106                                return;
107                        }
108                }else{ //Firefox
109                        if(ieKey == keys.LEFT_ARROW){
110                                if(str1.charAt(cursorEnd-1) == LRM){
111                                        bdc._setSelectedRange(elem, cursorStart - 1, cursorEnd - 1);
112                                }
113                                return;
114                        }
115                        if(ieKey == keys.RIGHT_ARROW){
116                                if(str1.charAt(cursorEnd-1) == LRM){
117                                        bdc._setSelectedRange(elem, cursorStart + 1, cursorEnd + 1);
118                                }
119                                return;
120                        }
121                }
122               
123                var str2 = bdc.createDisplayString(str1, elem.alt);
124
125                if(str1 != str2)
126                {
127                        window.status = str1 + " c=" + cursorEnd;
128                        elem.value = str2;
129
130                        if((ieKey == keys.DELETE) && (str2.charAt(cursorEnd)==LRM)){
131                                elem.value = str2.substring(0, cursorEnd) + str2.substring(cursorEnd+2, str2.length);
132                        }
133
134                        if(ieKey == keys.DELETE){
135                                bdc._setSelectedRange(elem,cursorStart,cursorEnd);
136                        }else if(ieKey == keys.BACKSPACE){
137                                if((_str0.length >= cursorEnd) && (_str0.charAt(cursorEnd-1)==LRM)){
138                                        bdc._setSelectedRange(elem, cursorStart - 1, cursorEnd - 1);
139                                }else{
140                                        bdc._setSelectedRange(elem, cursorStart, cursorEnd);
141                                }
142                        }else if(elem.value.charAt(cursorEnd) != LRM){
143                                bdc._setSelectedRange(elem, cursorStart + 1, cursorEnd + 1);
144                        }
145                }
146        };
147
148        bdc._processCopy = function(elem, text, isReverse){
149                // summary:
150                //              This function strips the unicode directional controls when the text copied to the Clipboard
151
152                if(text == null){
153                        if(has("ie")){
154                                var range = document.selection.createRange();
155                                text = range.text;
156                        }else{
157                                text = elem.value.substring(elem.selectionStart, elem.selectionEnd);
158                        }
159                }
160
161                var textToClipboard = bdc.stripSpecialCharacters(text);
162       
163                if(has("ie")){
164                        window.clipboardData.setData("Text", textToClipboard);
165                }
166                return true;
167        };
168
169        bdc._ceCopyText = function(elem){
170                if(has("ie")){
171                        elem.returnValue = false;
172                }
173                return bdc._processCopy(elem, null, false);
174        };
175
176        bdc._ceCutText = function(elem){
177
178                var ret = bdc._processCopy(elem, null, false);
179                if(!ret){
180                        return false;
181                }
182
183                if(has("ie")){
184        //              curPos = elem.selectionStart;
185                        document.selection.clear();
186                }else{
187                        var curPos = elem.selectionStart;
188                        elem.value = elem.value.substring(0, curPos) + elem.value.substring(elem.selectionEnd);
189                        elem.setSelectionRange(curPos, curPos);
190                }
191
192                return true;
193        };
194
195        // is there dijit code to do this?
196        bdc._getCaretPos = function(event, elem){
197                if(has("ie")){
198                        var position = 0,
199                        range = document.selection.createRange().duplicate(),
200                        range2 = range.duplicate(),
201                        rangeLength = range.text.length;
202
203                        if(elem.type == "textarea"){
204                                range2.moveToElementText(elem);
205                        }else{
206                                range2.expand('textedit');
207                        }
208                        while(range.compareEndPoints('StartToStart', range2) > 0){
209                                range.moveStart('character', -1);
210                                ++position;
211                        }
212
213                        return [position, position + rangeLength];
214                }
215
216                return [event.target.selectionStart, event.target.selectionEnd];
217        };
218
219        // is there dijit code to do this?
220        bdc._setSelectedRange = function(elem,selectionStart,selectionEnd){
221                if(has("ie")){
222                        var range = elem.createTextRange();
223                        if(range){
224                                if(elem.type == "textarea"){
225                                        range.moveToElementText(elem);
226                                }else{
227                                        range.expand('textedit');
228                                }
229
230                                range.collapse();
231                                range.moveEnd('character', selectionEnd);
232                                range.moveStart('character', selectionStart);
233                                range.select();
234                        }
235                }else{
236                        elem.selectionStart = selectionStart;
237                        elem.selectionEnd = selectionEnd;
238                }
239        };
240
241        var _isBidiChar = function(c){
242                return (c >= '\u0030' && c <= '\u0039') || (c > '\u00ff');
243        };
244
245        var _isLatinChar = function(c){
246                return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A');
247        };
248
249        var _isCharBeforeBiDiChar = function(buffer, i, previous){
250                while(i > 0){
251                        if(i == previous){
252                                return false;
253                        }
254                        i--;
255                        if(_isBidiChar(buffer.charAt(i))){
256                                return true;
257                        }
258                        if(_isLatinChar(buffer.charAt(i))){
259                                return false;
260                        }
261                }
262                return false;
263        };
264
265
266        bdc._parse = function(/*String*/str, /*String*/pattern){
267                var previous = -1, segmentsPointers = [];
268                var delimiters = {
269                        FILE_PATH: "/\\:.",
270                        URL: "/:.?=&#",
271                        XPATH: "/\\:.<>=[]",
272                        EMAIL: "<>@.,;"
273                }[pattern];
274
275                switch(pattern){
276                        case "FILE_PATH":
277                        case "URL":
278                        case "XPATH":
279                                arr.forEach(str, function(ch, i){
280                                        if(delimiters.indexOf(ch) >= 0 && _isCharBeforeBiDiChar(str, i, previous)){
281                                                previous = i;
282                                                segmentsPointers.push(i);
283                                        }
284                                });
285                                break;
286                        case "EMAIL":
287                                var inQuotes = false; // FIXME: unused?
288       
289                                arr.forEach(str, function(ch, i){
290                                        if(ch== '\"'){
291                                                if(_isCharBeforeBiDiChar(str, i, previous)){
292                                                        previous = i;
293                                                        segmentsPointers.push(i);
294                                                }
295                                                i++;
296                                                var i1 = str.indexOf('\"', i);
297                                                if(i1 >= i){
298                                                        i = i1;
299                                                }
300                                                if(_isCharBeforeBiDiChar(str, i, previous)){
301                                                        previous = i;
302                                                        segmentsPointers.push(i);
303                                                }
304                                        }
305       
306                                        if(delimiters.indexOf(ch) >= 0 && _isCharBeforeBiDiChar(str, i, previous)){
307                                                                previous = i;
308                                                                segmentsPointers.push(i);
309                                        }
310                                });
311                }
312                return segmentsPointers;
313        };
314        return bdc;
315});
Note: See TracBrowser for help on using the repository browser.