dojo.provide("dojox.string.BidiComplex"); dojo.experimental("dojox.string.BidiComplex"); // summary: // BiDiComplex module handels complex expression issues known when using BiDi characters // in File Paths, URLs, E-mail Address, XPATH, etc. // this module adds property listeners to the text fields to correct the text representation // in both static text and dynamic text during user input. dojox.string.BidiComplex.attachInput = function(/*DOMNode*/field, /*String*/pattern){ // summary: // Attach key listeners to the INPUT field to accomodate dynamic complex BiDi expressions // field: INPUT DOM node // pattern: Complex Expression Pattern type. One of "FILE_PATH", "URL", "EMAIL", "XPATH" dojox.string.BidiComplex._ce_type = pattern; //FIXME: shared ref field.alt = dojox.string.BidiComplex._ce_type; if((document.dir == "rtl")||(document.body.dir == "rtl")){ //FIXME: use !dojo._isBodyLtr()? field.style.textAlign = "right"; } //FIXME: use dojo.connect if(dojo.isIE){ field.onkeydown = new Function("dojox.string.BidiComplex._ceKeyDown(event);"); field.onkeyup = new Function("dojox.string.BidiComplex._ceKeyUp(event);"); }else{ field.onkeyup = dojox.string.BidiComplex._ceKeyUp; field.onkeydown = dojox.string.BidiComplex._ceKeyDown; } //FIXME: use dojo.connect field.oncut = dojox.string.BidiComplex._fOnCut; field.oncopy = dojox.string.BidiComplex._fOnCopy; field.value = dojox.string.BidiComplex._insertMarkers(field.value, field.alt); }; dojox.string.BidiComplex.createDisplayString = function(/*String*/str, /*String*/pattern){ // summary: // Create the display string by adding the Unicode direction Markers // pattern: Complex Expression Pattern type. One of "FILE_PATH", "URL", "EMAIL", "XPATH" //FIXME: inline _insertMarkers return dojox.string.BidiComplex._insertMarkers(str, pattern); }; dojox.string.BidiComplex.stripSpecialCharacters = function(str){ // summary: // removes all Unicode directional markers from the string return str.replace(/[\u200E\u200F\u202A-\u202E]/g, ""); // String }; //FIXME: these statics are worrysome dojox.string.BidiComplex._segmentsPointers = []; dojox.string.BidiComplex._ce_type = null; dojox.string.BidiComplex._PATH = null; dojox.string.BidiComplex._insertAlways = false; dojox.string.BidiComplex._fOnCut = new Function("dojox.string.BidiComplex._ceCutText(this)"); dojox.string.BidiComplex._fOnCopy = new Function("dojox.string.BidiComplex._ceCopyText(this);"); dojox.string.BidiComplex._ceKeyDown = function(event){ //FIXME: global references: obj and str0 obj = dojo.isIE ? event.srcElement : event.target; str0 = obj.value; }; dojox.string.BidiComplex._ceKeyUp = function(event){ var LRM = '\u200E'; //FIXME: str0 global reference obj = dojo.isIE ? event.srcElement : event.target; str1 = obj.value; if(obj.alt != ""){ dojox.string.BidiComplex._ce_type = obj.alt; } ieKey = event.keyCode; if((ieKey == dojo.keys.HOME) || (ieKey == dojo.keys.END) || (ieKey == dojo.keys.SHIFT)){ return; } var cursorStart, cursorEnd; var selection = dojox.string.BidiComplex._getCaretPos(event, obj); if(selection){ cursorStart = selection[0]; cursorEnd = selection[1]; } //Jump over a cursor processing if(dojo.isIE){ var cursorStart1 = cursorStart, cursorEnd1 = cursorEnd; if(ieKey == dojo.keys.LEFT_ARROW){ if((str1.charAt(cursorEnd-1) == LRM) && (cursorStart == cursorEnd)){ dojox.string.BidiComplex._setSelectedRange(obj,cursorStart - 1, cursorEnd - 1); } return; } if(ieKey == dojo.keys.RIGHT_ARROW){ if(str1.charAt(cursorEnd-1) == LRM){ cursorEnd1 = cursorEnd + 1; if(cursorStart == cursorEnd){ cursorStart1 = cursorStart + 1; } } dojox.string.BidiComplex._setSelectedRange(obj, cursorStart1, cursorEnd1); return; } }else{ //Firefox if(ieKey == dojo.keys.LEFT_ARROW){ if(str1.charAt(cursorEnd-1) == LRM){ dojox.string.BidiComplex._setSelectedRange(obj, cursorStart - 1, cursorEnd - 1); } return; } if(ieKey == dojo.keys.RIGHT_ARROW){ if(str1.charAt(cursorEnd-1) == LRM){ dojox.string.BidiComplex._setSelectedRange(obj, cursorStart + 1, cursorEnd + 1); } return; } } str2 = dojox.string.BidiComplex._insertMarkers(str1, obj.alt); if(str1 != str2) { window.status = str1 + " c=" + cursorEnd; obj.value = str2; if((ieKey == dojo.keys.DELETE) && (str2.charAt(cursorEnd)==LRM)){ obj.value = str2.substring(0, cursorEnd) + str2.substring(cursorEnd+2, str2.length); } if(ieKey == dojo.keys.DELETE){ setSelectedRange(obj,cursorStart,cursorEnd); }else if(ieKey == dojo.keys.BACKSPACE){ //FIXME: str0 global reference if(str0.charAt(cursorEnd-1)==LRM){ dojox.string.BidiComplex._setSelectedRange(obj, cursorStart - 1, cursorEnd - 1); }else{ dojox.string.BidiComplex._setSelectedRange(obj, cursorStart, cursorEnd); } }else if(obj.value.charAt(cursorEnd) != LRM){ dojox.string.BidiComplex._setSelectedRange(obj, cursorStart + 1, cursorEnd + 1); } } }; dojox.string.BidiComplex._processCopy = function(obj, text, isReverse){ // summary: // This function strips the unicode directional controls when the text copied to the Clipboard if(text == null){ if(dojo.isIE){ range = document.selection.createRange(); text = range.text; }else{ text = obj.value.substring(obj.selectionStart, obj.selectionEnd); } } var textToClipboard = dojox.string.BidiComplex.stripSpecialCharacters(text); if(dojo.isIE){ window.clipboardData.setData("Text", textToClipboard); return true; }else{ try { return window.SignedJs.processCopy(textToClipboard); //FIXME: what's this? }catch(e){ return false; } } }; dojox.string.BidiComplex._ceCopyText = function(obj){ if(dojo.isIE){ event.returnValue = false; } return dojox.string.BidiComplex._processCopy(obj, null, false); }; dojox.string.BidiComplex._ceCutText = function(obj){ var ret = dojox.string.BidiComplex._processCopy(obj, null, false); if(!ret){ return false; } if(dojo.isIE){ // curPos = obj.selectionStart; range = document.selection.clear(); }else{ var curPos = obj.selectionStart; obj.value = obj.value.substring(0, curPos) + obj.value.substring(obj.selectionEnd); obj.setSelectionRange(curPos, curPos); } return true; }; // is there dijit code to do this? dojox.string.BidiComplex._getCaretPos = function(event, obj){ if(dojo.isIE){ var position = 0, range = document.selection.createRange().duplicate(), range2 = range.duplicate(), rangeLength = range.text.length; if(obj.type == "textarea"){ range2.moveToElementText(obj); }else{ range2.expand('textedit'); } while(range.compareEndPoints('StartToStart', range2) > 0){ range.moveStart('character', -1); ++position; } return [position, position + rangeLength]; } return [event.target.selectionStart, event.target.selectionEnd]; }; // is there dijit code to do this? dojox.string.BidiComplex._setSelectedRange = function(obj,selectionStart,selectionEnd){ if(dojo.isIE){ var range = obj.createTextRange(); if(range){ if(obj.type == "textarea"){ range.moveToElementText(obj); }else{ range.expand('textedit'); } range.collapse(); range.moveEnd('character', selectionEnd); range.moveStart('character', selectionStart); range.select(); } }else{ obj.selectionStart = selectionStart; obj.selectionEnd = selectionEnd; } }; dojox.string.BidiComplex._isBidiChar = function(c){ if(c >= '\u0030' && c <= '\u0039'){ return true; } return c > '\u00ff'; }; dojox.string.BidiComplex._isLatinChar = function(c){ return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A'); }; dojox.string.BidiComplex._isCharBeforeBiDiChar = function(buffer, i, previous){ if(dojox.string.BidiComplex._insertAlways){ return true; } while(i > 0){ if(i == previous){ return false; } i--; if(dojox.string.BidiComplex._isBidiChar(buffer.charAt(i))){ return true; } if(dojox.string.BidiComplex._isLatinChar(buffer.charAt(i))){ return false; } } return false; }; dojox.string.BidiComplex._parse = function(/*String*/str, /*String*/pattern){ var i,i1; var delimiters; var previous = -1; //erase segmentsPointers if(dojox.string.BidiComplex._segmentsPointers != null){ for(i=0; i= 0) && dojox.string.BidiComplex._isCharBeforeBiDiChar(str, i, previous)){ previous = i; dojox.string.BidiComplex._segmentsPointers[sp_len++] = i; } } }else if(pattern == "URL"){ var buffer_length = str.length; // parse protocol, host, path delimiters = "/:.?=&#"; // FIXME: use split? for(i = 0; i < buffer_length; i++){ //FIXME: dojo.forEach if((delimiters.indexOf(str.charAt(i)) >= 0) && dojox.string.BidiComplex._isCharBeforeBiDiChar(str, i, previous)){ previous = i; dojox.string.BidiComplex._segmentsPointers[sp_len] = i; sp_len++; } } }else if(pattern == "EMAIL"){ delimiters = "<>@.,;"; // FIXME: use split? var inQuotes = false; for(i = 0; i < str.length; i++){ //FIXME: dojo.forEach if(str.charAt(i) == '\"'){ if(dojox.string.BidiComplex._isCharBeforeBiDiChar(str, i, previous)){ previous = i; dojox.string.BidiComplex._segmentsPointers[sp_len] = i; sp_len++; } i++; i1 = str.indexOf('\"', i); if(i1 >= i){ i = i1; } if(dojox.string.BidiComplex._isCharBeforeBiDiChar(str, i, previous)){ previous = i; dojox.string.BidiComplex._segmentsPointers[sp_len] = i; sp_len++; } } if((delimiters.indexOf(str.charAt(i)) >= 0) && dojox.string.BidiComplex._isCharBeforeBiDiChar(str, i, previous)){ previous = i; dojox.string.BidiComplex._segmentsPointers[sp_len] = i; sp_len++; } } }else if(pattern == "XPATH"){ delimiters = "/\\:.<>=[]"; for (i = 0; i < str.length; i++){ //FIXME: dojo.forEach if((delimiters.indexOf(str.charAt(i)) >= 0) && dojox.string.BidiComplex._isCharBeforeBiDiChar(str, i, previous)){ previous = i; dojox.string.BidiComplex._segmentsPointers[sp_len] = i; sp_len++; } } } return dojox.string.BidiComplex._segmentsPointers; }; dojox.string.BidiComplex._insertMarkers = function(/*String*/str,/*String*/pattern){ str = dojox.string.BidiComplex.stripSpecialCharacters(str); dojox.string.BidiComplex._segmentsPointers = dojox.string.BidiComplex._parse(str, pattern); // FIXME: shared ref var buf = '\u202A'/*LRE*/ + str; var shift = 1; var n; for(i = 0; i< dojox.string.BidiComplex._segmentsPointers.length; i++){ //FIXME: dojo.forEach n = dojox.string.BidiComplex._segmentsPointers[i]; if(n != null){ preStr = buf.substring(0, n + shift); postStr = buf.substring(n + shift, buf.length); buf = preStr + '\u200E'/*LRM*/ + postStr; shift++; } } return buf; };