/********************************************************
For more info & download: http://www.ibegin.com/blog/p_ispell.html
Created for iBegin.com - local search done right
MIT Licensed Style
*********************************************************/

var iP; // global JSON string container
var spellCheck_url = "/ispell/ispell-checker.php";
var allow_addwords = false; // option to allow adding words, ispell-checker.php has to be modified also (this does not work on all servers)
var allow_multiple_popups = false; // this allows multiple popups on iSpell


var ispell_checking = false; // flag to set if we are on spell check mode


var ignored_words = new Array();

getISpellParent = function() {return document.getElementsByTagName("body")[0];}

checkSpelling = function(evt) {
	
	var evt = (evt) ? evt : ((window.event) ? event : null);
   
    var obj = (evt.target) ? evt.target : 
	  ((evt.srcElement) ? evt.srcElement : null);
   
	var trgtTextArea = obj.rel;
	var trgtElem = document.getElementById(obj.rel);
	var wrdsToCheck = trgtElem.value;

	var err_words = new Array(); // words that have errors

	var spellCheck_data = "i="+escape(wrdsToCheck);	
	
	var http = createRequestObject();
	
	toggle('ispell_indicator');
	
	http.onreadystatechange = function() {
	
		if(http.readyState == 4){
			
			var response = http.responseText;
			iP = eval('(' + response + ')'); // assign our JSON var to global

			if(iP.length == 0) {
				alert("No Suggestions");
				toggle('ispell_indicator');
				return;
			}

			for(var i=0;iP.length;i++) {
				if(iP[i]) {
					try{
						var phrase = iP[i];
						err_words[i] = phrase.word;
					} catch(e) {}
				} else {break;}
			}
			
			var objChecker = highlightTextArea(trgtElem,err_words);
			
			if(objChecker) {
				
				ispell_checking = true;
				
				var re = document.createElement('a');
				var objParent = obj.parentNode;
				re.setAttribute("id",obj.id);
				re.rel = obj.rel;
				re.href = "javascript:void(null);";
				re.innerHTML = "Resume Editing";
				
				re.onclick = function() {ispell_checking = false;resumeEditing(this,objChecker);return false;}
				
				objParent.insertBefore(re,obj);	
				objParent.removeChild(obj);
				
				toggle('ispell_indicator');
				
			}
			
		}
	}
	

	http.open('post',spellCheck_url,true);
	http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
	http.send(spellCheck_data);
	
	return true;
}

resumeISpell = function(objId) {
		
		if(ispell_checking) {
			var ispell_link = document.getElementById(objId);

			if(ispell_link.rel != "") {
				var ispell_checker = document.getElementById(ispell_link.rel+'_check');
				if(ispell_checker) {
					resumeEditing(ispell_link,ispell_checker);
				}
			}
		} else {
			return false;	
		}
}

resumeEditing = function(obj,objChecker) {
	
	destroyISpellPopups();
	
	var re = document.createElement('a');
	var objParent = obj.parentNode;
	re.setAttribute("id",obj.id);
	re.rel = obj.rel;
	re.href = "javascript:void(null);";
	re.innerHTML = "Check Spelling";
	
	addEvent(re, 'click', checkSpelling);
	
	createTextArea(obj,objChecker);
	objParent.insertBefore(re,obj);	
	objParent.removeChild(obj);
	return false;
}

addToDictionary = function(wrd) {
	var http = createRequestObject();
	
	toggle('ispell_indicator');
	
	http.onreadystatechange = function() {
		if(http.readyState == 4){
			var response = http.responseText;
			toggle('ispell_indicator');
		}
	}
	
	var lSpellCheckUrl = spellCheck_url+"?add="+escape(wrd);
	http.open('get',lSpellCheckUrl,true);
	http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
	http.send(null);
	
}

createTextArea = function(obj,objChecker) {
	var x = objChecker.innerHTML;
	
	var wrds = objChecker.getElementsByTagName("a");

	var rxp = new RegExp("<a *[word_error|word_checked]* [^<>]*>|</a>","gi");
	x = x.replace(rxp,"");

	var rxp = new RegExp("<br>|<br/>","gi");
	x = x.replace(rxp,"\n");
	
	var y = document.createElement('TEXTAREA');
	var z = objChecker.parentNode;
	y.setAttribute("id",obj.rel);
	y.setAttribute("name",objChecker.name);
	y.setAttribute("rel",objChecker.rel);
	
	y.className = 'ispell';
	z.insertBefore(y,objChecker);
	z.removeChild(objChecker);
	y.value = x;
	y.focus();
}

createCheckArea = function(objTextArea,strValue) {
	var y = document.createElement('DIV');
	var z = objTextArea.parentNode;
	y.setAttribute("id",objTextArea.id+'_check');
	y.setAttribute("rel",objTextArea.rel);
	y.className = 'ispell_checking';
	
	y.name = objTextArea.name;
	
	if(!strValue) {y.innerHTML = objTextArea.value;} 
	else {y.innerHTML = strValue;}	
	
	z.insertBefore(y,objTextArea);	
	z.removeChild(objTextArea);
	
	addEvent(y, 'click', function(objTrgt) {

		if (window.event) event.cancelBubble=true;
		else if (objTrgt.stopPropagation) objTrgt.stopPropagation();													  
		//destroyISpellPopups();
	});
	
	return y;
}

highlightTextArea = function(objTextArea,errwords) {

	if(!objTextArea) {return false;	}
	
	var strResult = "";
	
	if(objTextArea.value != "") {
		
		strResult = objTextArea.value;
		
		var rxp = new RegExp("\\n","gi");
		strResult = strResult.replace(rxp,"<br/>");

		for(var i=0;i<=errwords.length - 1;i++) {
			if(errwords[i]) {
				var wrd = errwords[i];
				
				var str = wrd;
				
				if(ignored_words.inArray(wrd)) {
					str = wrd.ignored_word(); 
				} else {
					str = wrd.spell_error(); 
				}
	
				var rxp = new RegExp("\\b"+wrd+"\\b","g");
				strResult = strResult.replace(rxp,str);
			}
		}
		
		
	}
	
	return createCheckArea(objTextArea,strResult);
}

suggestSpelling = function(objTrgt) {
	if (window.event) event.cancelBubble=true;
	else if (objTrgt.stopPropagation) objTrgt.stopPropagation();
	
	var wrd = objTrgt.rel;

	if(!allow_multiple_popups) {
		destroyISpellPopups();
	}

	for(var i=0;iP.length;i++) {
		if(iP[i]) {
			try{
				var phrase = iP[i];
				
				
				if(phrase.word.indexOf(wrd) != -1) {
	
					var sugList = phrase.suggestions;
					var wrd_b = createSuggestions(wrd,objTrgt);
					
					
					if(sugList.length > 0) {
						for(var j=0;j<=sugList.length-1;j++) {						
							var wrd_s = document.createElement('span');
							var wrd_a = document.createElement('a');
							wrd_s.className = "ispell_popup_item";
							wrd_a.href = "javascript:void(null)";
							wrd_a.innerHTML = sugList[j];
							wrd_a.onclick = function() {
								
								objTrgt.innerHTML = this.innerHTML;
								objTrgt.className = "word_checked";
								getISpellParent().removeChild(document.getElementById(wrd_b.parentNode.id));
								return false;
							}
							wrd_s.appendChild(wrd_a);
							wrd_b.appendChild(wrd_s);
						}
					} else {
						var wrd_s = document.createElement('span');
						wrd_s.className = "ispell_popup_item";
						wrd_s.innerHTML = "(No Suggestions)";
						wrd_b.appendChild(wrd_s);
					
					}
					
					
				}
				
				
				
			} catch(e) {}
		} else {break;}
	}

	return false;
}

createSuggestions = function(wrd,trgtElem) {
	var ipop = document.createElement("div");
	ipop.setAttribute("id","ispell_popup_"+wrd);
	ipop.className = "ispell_popup";

	var objX = findPosX(trgtElem); //var objX = findPosX(obj)+10;
	var objY = findPosY(trgtElem); //var objY = findPosY(obj)+30;
	ipop.style.display = 'block';
	ipop.style.left = objX+'px';
	ipop.style.top = objY+20+'px';
	
	var wrd_s = document.createElement('span');
	var wrd_t = document.createTextNode("Spelling Suggestions");
	wrd_s.appendChild(wrd_t);
	wrd_s.className = "ispell_popup_title";
	ipop.appendChild(wrd_s);
	
	var wrd_b = document.createElement('div');
	wrd_b.className = "ispell_suggestions";
	ipop.appendChild(wrd_b);
	
	// check if we have allow_addwords option
	if(allow_addwords) {
		var wrd_a = document.createElement('a');
		var wrd_t = document.createTextNode("Add To Dictionary");
		wrd_a.appendChild(wrd_t);
		wrd_a.href = "javascript:void(null)";
		wrd_a.className = "ispell_popup_menu";
		wrd_a.onclick = function() {
			if(allow_addwords) {
				addToDictionary(wrd);
			}
			trgtElem.className = "word_ignored";
			getISpellParent().removeChild(document.getElementById(wrd_b.parentNode.id));
			ignored_words[ignored_words.length+1] = wrd;
			return false;
		}
		ipop.appendChild(wrd_a);	
	}
	
	
	var wrd_a = document.createElement('a');
	var wrd_t = document.createTextNode("Ignore");
	wrd_a.appendChild(wrd_t);
	wrd_a.href = "javascript:void(null)";
	wrd_a.className = "ispell_popup_ignore";
	wrd_a.onclick = function() {						
		trgtElem.className = "word_ignored";
		getISpellParent().removeChild(document.getElementById(wrd_b.parentNode.id));
		ignored_words[ignored_words.length+1] = wrd;
		return false;
	}
	ipop.appendChild(wrd_a);
	
	var wrd_a = document.createElement('a');
	var wrd_t = document.createTextNode("Close [X]");
	wrd_a.appendChild(wrd_t);
	wrd_a.href = "javascript:void(null)";
	wrd_a.className = "ispell_popup_close";
	wrd_a.onclick = function() {
		getISpellParent().removeChild(document.getElementById(ipop.id));
		return false;
	}
	
	ipop.appendChild(wrd_a);
	getISpellParent().appendChild(ipop);
	
	return wrd_b;
}

destroyISpellPopups = function() {
	var ispell_popups = getElementsByClass('ispell_popup',document,'div');
	
	for(var i=0;i <= ispell_popups.length - 1;i++) {
		getISpellParent().removeChild(ispell_popups[i]);
	}
	
}

String.prototype.spell_error = function(s){
	return "<a  href=\"javascript:void(null);\" onclick=\"suggestSpelling(this);\" class=\"word_error\" rel=\""+this.toString()+"\">"+this.toString()+"</a>";
}

String.prototype.ignored_word = function(s){
	return "<a  href=\"javascript:void(null);\" onclick=\"suggestSpelling(this);\" class=\"word_ignored\" rel=\""+this.toString()+"\">"+this.toString()+"</a>";
}

Array.prototype.inArray = function (value) {
	var i;
	for (i=0; i < this.length; i++) {

		if (this[i] == value) {
			return true;
		}
	}
	return false;
};

function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

function toggle(obj) {
	var el = document.getElementById(obj);
	if ( el.style.display != 'none' ) {
		el.style.display = 'none';
	}
	else {
		el.style.display = '';
	}
}

function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}


addEvent = function(obj, evType, fn){ 
 if (obj.addEventListener){ 
   obj.addEventListener(evType, fn, false); 
   return true; 
 } else if (obj.attachEvent){ 
   var r = obj.attachEvent("on"+evType, fn); 
   return r; 
 } else { 
   return false; 
 } 
}


/* Start of JSON Parser*/
json = (function () {
    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            array: function (x) {
                var a = ['['], b, f, i, l = x.length, v;
                for (i = 0; i < l; i += 1) {
                    v = x[i];
                    f = s[typeof v];
                    if (f) {
                        v = f(v);
                        if (typeof v == 'string') {
                            if (b) {
                                a[a.length] = ',';
                            }
                            a[a.length] = v;
                            b = true;
                        }
                    }
                }
                a[a.length] = ']';
                return a.join('');
            },
            'boolean': function (x) {
                return String(x);
            },
            'null': function (x) {
                return "null";
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            object: function (x) {
                if (x) {
                    if (x instanceof Array) {
                        return s.array(x);
                    }
                    var a = ['{'], b, f, i, v;
                    for (i in x) {
                        v = x[i];
                        f = s[typeof v];
                        if (f) {
                            v = f(v);
                            if (typeof v == 'string') {
                                if (b) {
                                    a[a.length] = ',';
                                }
                                a.push(s.string(i), ':', v);
                                b = true;
                            }
                        }
                    }
                    a[a.length] = '}';
                    return a.join('');
                }
                return 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) {
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
                            return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            }
        };

    Object.prototype.toJSONString = function () {
        return s.object(this);
    };

    Array.prototype.toJSONString = function () {
        return s.array(this);
    };
})();

String.prototype.parseJSON = function () {
    try {
        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
                this.replace(/"(\\.|[^"\\])*"/g, ''))) &&
            eval('(' + this + ')');
    } catch (e) {
        return false;
    }
};


createRequestObject = function() {
	var xmlhttp;
		/*@cc_on
	@if (@_jscript_version>= 5)
			try {xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
					try {xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");}
					catch (E) {xmlhttp = false;}
			}
	@else
		xmlhttp = false;
	@end @*/
	if (!xmlhttp && typeof XMLHttpRequest != "undefined") {
			try {xmlhttp = new XMLHttpRequest();} catch (e) {xmlhttp = false;}
	}
	return xmlhttp;
}



addEvent(window, 'load', function() {
		var ispell_link = document.getElementById('ispell_link');
		addEvent(ispell_link, 'click', checkSpelling);
		
});

