source: Dev/branches/rest-dojo-ui/client/dojox/string/BidiComplex.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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 dojox.string.BidiComplex;
315});
Note: See TracBrowser for help on using the repository browser.