Location: A review of cardiac cellular electrophysiology models @ f6a8f9030738 / dojo-presentation / js / dojo / dojox / string / BidiComplex.js

Author:
David Nickerson <nickerso@users.sourceforge.net>
Date:
2009-07-16 02:00:03+12:00
Desc:
the starting point for the HH tutorial example
Permanent Source URI:
https://models.fieldml.org/workspace/a1/rawfile/f6a8f90307388eb4b040ee3566b84d88b59247f7/dojo-presentation/js/dojo/dojox/string/BidiComplex.js

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<dojox.string.BidiComplex._segmentsPointers.length; i++){ // FIXME: just whack array?
			dojox.string.BidiComplex._segmentsPointers[i] = null;
		}
	}
	var sp_len = 0;

	if(pattern == "FILE_PATH"){
		delimiters = "/\\:."; // FIXME: use split?
		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;
			}
		}
	}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;        
};