/*************************************************************************
    Spellify - spellify.js v1.0

    Copyright (c) 2006-2007 Nikola Kocic. (www.spellify.com, www.nikolakocic.com)
	
    Powered by Google(tm) spell checker.
   
    ***********************************************************************
	
    This file is part of Spellify.

    Spellify is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Spellify is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Spellify.  If not, see <http://www.gnu.org/licenses/>
	
/*******************************************************************************************************************************
*  Language Settings: 
*  
*  Set the corresponsding language value, i.e. eng for English, to the "lang" variable declared immediately below.
*		English 	- eng
*	 	Dansk		- da
*		Deutsch 	- de
*		Suomi		- fi
*		Fran�ais	- fr
*		Nederlands 	- nl
*		Espa�ol 	- es
*		Italiano 	- it
*		Polski 		- pl
*  		Portugu�s 	- pt
*		Svenska 	- sv
*/
var lang = 'fr';									//default language setting
/*******************************************************************************************************************************/
var maxTimeAfterLastStroke = 150;							//value in milliseconds before spell check occurs
var optionalLeftOffset = 35;								//optional left position offset for loader div
var optionalTopOffset = 0;								//optional top position offset for corrections div
/*************************************DO NOT CHANGE BELOW***********************************************************************/
var defUrl  = 'spellify/spellify.php';
var ignoreClassName = 'spellify_ignore'
var http_request;
var http_response;
var requestMethod = 'POST';
var timer = 0;
var timerID = 0;
var txtObject;
var correctionsBody;
var correctionsContainer;
var loaderDiv;
var spellifyDiv;
var isIE = (navigator.userAgent.indexOf('MSIE')>=0 && document.all) ? true : false;
/********************************************************************************************************************************/

function GoogCorrection(offset, length, suggestions)
{
	//Fields
	this._offset = offset;
	this._length = length;
	this._suggestions = suggestions;
	
	//Properties
	this.getOffset = function(){
		return this._offset;
	}
	this.getLength = function(){
		return this._length;
	}
	this.getSuggestions = function(){
		return this._suggestions;
	}
}

function XmlDocumentLoader(xml)
{
	//Fields
	this._xml = xml;
	this._xmlDoc = null;
	
	//Methods
	this.Create = function(){
		try
		{
			if(this._xml == '' || this._xml == null)
			{
				if ( typeof console != "undefined" && console !== null ) {
					console.error('XML string cannot be empty or null');
				}
			}
			else
			{
				//if internet explorer
				if (window.ActiveXObject)
			    {
				 	 this._xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
				  	 this._xmlDoc.async ="false";
				  
					  //try to load xml from file
					 this._xmlDoc.loadXML(this._xml);
			    }
				else
			    {
					var parser=new DOMParser();
					this._xmlDoc=parser.parseFromString(this._xml,"text/xml");
			    }
			}
			
			return this._xmlDoc;
		}
		catch(e)
		{
			if ( typeof console != "undefined" && console !== null ) {
				console.error(e.name + '\n' + e.message);
			}
		}
	}
}

function GoogSpellingCorrectionLoader(xmlSrc)
{
	//Fields
	this._xmlDoc = null;
	this._xml = xmlSrc;
	this._c_suggestions = new Array();
	this.isIE = (navigator.userAgent.indexOf('MSIE')>=0 && document.all) ? true : false;
	
	//Methods
	this.Load = function(){
		  xmlDocLoader = new XmlDocumentLoader(this._xml);
		  this._xmlDoc = xmlDocLoader.Create();
	}
	this.Parse = function(){
		try
		{
			var C = this._xmlDoc.getElementsByTagName("c");
			
			if(C.length == 0)
				return;
				
			for(i=0;i<C.length;i++)
			{
				var correctionOffset = C[i].getAttribute("o");
				var correctionLength = C[i].getAttribute("l");
				
				if(!this.IsNodeText(C[i]))
					return;
				else
				{
					var correctionCollection = C[i].childNodes[0].nodeValue.split("	");
					
					this._c_suggestions[i] = new GoogCorrection(correctionOffset, correctionLength, correctionCollection);
				}
			}
		}
		catch(e)
		{
			
			if ( typeof console != "undefined" && console !== null ) {
				console.error(e.name + '\n' + e.message);
			}
		}
	}
	
	this.IsNodeText = function (node){
			return (this.isIE) ? ((node.text == '') ? false : true) : ((node.textContent == '') ? false : true);
	}
	
	//Properties
	this.getCSuggestions = function(){
		return this._c_suggestions;
	}
}

function ClearTextBox(txtObjectId)
{
	document.getElementById(txtObjectId).value = '';
	ResetCorrectionsContainer();
}

function CreateRequest()
{
	if(window.XMLHttpRequest)
	{
		http_request = new XMLHttpRequest();
			
		if (http_request.overrideMimeType) 
		{
			http_request.overrideMimeType('text/xml');
		}
	}
	else if (window.ActiveXObject)  // IE
	{
		try 
		{
			http_request = new ActiveXObject("Msxml2.XMLHTTP");
		} 
		catch (e) 
		 {
			try 
			{
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
			} 
			catch (e) 
			{
				 
			}
		}
	}
	if (!http_request) {
		if ( typeof console != "undefined" && console !== null ) {
			console.error('Cannot create XMLHTTP instance');
		}
		
		return false;
	}
}

function InitializeSpellify()
{
	defUrl = SITE_URL + 'spellify/spellify.php';
	
	correctionsBody = document.getElementById('correctionsBody');
	correctionsContainer = document.getElementById('correctionsContainer');
	loaderDiv = document.getElementById('loaderDiv');
	spellifyDiv = document.getElementById('spellify');
		
	var inputFields = jQuery('.spellify_on input[spellify="on"]');
	var textareas = jQuery('.spellify_on textarea[spellify="on"]');
	
	if(spellifyDiv && correctionsBody && correctionsContainer && loaderDiv)
	{
		for(var i=0;i<inputFields.length;i++)
		{
			if(inputFields[i].className.match(ignoreClassName) == null && inputFields[i].type == "text")
			{
				inputFields[i].blur();
				inputFields[i].onkeydown  = Capture_Key;
				inputFields[i].onkeyup    = Capture_Key;
				inputFields[i].onkeypress = Capture_Key;
				inputFields[i].onfocus    = SetCorrectionContainerPosition;
				inputFields[i].onpaste	  = CheckTimer;
			}
		}
		
		for(var i=0;i<textareas.length;i++)
		{
			if(textareas[i].className.match(ignoreClassName) == null)
			{
				textareas[i].blur();
				textareas[i].onkeydown  = Capture_Key;
				textareas[i].onkeyup    = Capture_Key;
				textareas[i].onkeypress = Capture_Key;
				textareas[i].onfocus    = SetCorrectionContainerPosition;
				textareas[i].onpaste	= CheckTimer;
			}
		}
		
		CreateRequest();
	}
}

function SetCorrectionContainerPosition(e){
	ResetCorrectionsContainer();
	txtObject = getEventSrc(e);
	PositionCorrectionsContainer();
}

function getEventSrc(e) {
  if( !e || (!e.srcElement && !e.target) ) { e = window.event; }
  return src = (e && e.srcElement)? e.srcElement :
      (e && e.target)? e.target : false;
}

//Resets the corrections container
function ResetCorrectionsContainer(){
	correctionsBody.innerHTML = '';
	correctionsContainer.style.display = 'none';
}

function Capture_Key(e){	
		if(typeof window.event!="undefined"){
			e=window.event;
		}
		
		switch(e.type)
		{
			case "keydown" : 
				if ((e.keyCode >= 8 && e.keyCode < 32) || (e.keyCode > 32 && e.keyCode < 44))
				{
					loaderDiv.style.display = 'none';
				}
				else
				{
					ResetCorrectionsContainer();
				}

				ResetTimer();
				break;
								
			case "keyup" :
				if(e.keyCode == 8)
				{
					if(txtObject.value == '')
					{
						loaderDiv.style.display = 'none';
						jQuery('#correctionsContainer').fadeOut('fast');
					}
				}
				if(e.keyCode == 16)
				{
					if(!isTextSelected())
						CheckTimer();
				}
				break;
				
			case "keypress" :
				if( (e.keyCode >= 8 && e.keyCode < 32) || (e.keyCode > 32 && e.keyCode < 44))
				{
					ResetTimer();
				}
				else
				{
					if(!isTextSelected())
						CheckTimer();
				}
				break;
			default:
				break;
		}
}

function isTextSelected()
{
	if(isIE)
	{
		var range = document.selection.createRange();
		return (range.text.length > 0) ? true : false;
	}
	else
	{
		return (txtObject.selectionStart < txtObject.selectionEnd) ? true : false;
	}
}

function CheckTimer()
{
	if(timer == maxTimeAfterLastStroke)
	{		
		timer = 0;
		ResetTimer();
		loaderDiv.style.display = 'block';
		makeRequest('?lang=' + lang,  txtObject.value);
			
		return;
	}
		
	if(timer < maxTimeAfterLastStroke)
	{
		timer = timer + 10;
		timerID = setTimeout(CheckTimer, 50)
	}
}

function ResetTimer()
{
		timer = 0;
		clearTimeout(timerID);
}

function PositionCorrectionsContainer()
{	
		var leftPos = getLeftPos(txtObject);
		var topPos  = getTopPos(txtObject);
		correctionsContainer.style.left = leftPos  + 'px';
		correctionsContainer.style.top = topPos + txtObject.offsetHeight + optionalTopOffset + 'px';			
		
		loaderDiv.style.left = leftPos + txtObject.offsetWidth +  optionalLeftOffset + 'px';
		loaderDiv.style.top = topPos + 'px';
}

function getTopPos(obj)
{		
	  var newPos = obj.offsetTop;
	  while((obj = obj.offsetParent) != null)
	  {
	  	if(obj.tagName!='HTML')
		{
	  		newPos += obj.offsetTop;
	  		if(isIE)
			{
				newPos+=obj.clientTop;
			}
	  	}
	  } 
	  return newPos;
}

function getLeftPos(obj)
{	  
	  var newPos = obj.offsetLeft;
	  while((obj = obj.offsetParent) != null)
	  {
	  	if(obj.tagName!='HTML')
		{
	  		newPos += obj.offsetLeft;
	  		if(isIE)
			{
				newPos+=obj.clientLeft;
			}
	  	}
	  }
	  return newPos;
}

function makeRequest(parameters, svalue) {	
		http_request.onreadystatechange = GetResponse;
		http_request.open(requestMethod, defUrl + parameters, true);
			
		data = '<?xml version="1.0" encoding="utf-8" ?>';
		data +='<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="0" ignoreallcaps="0"><text>';
		data += svalue;
		data += '</text></spellrequest>';
		
		http_request.send(data);
}

function GetResponse(){
	if (http_request.readyState == 4) 
	{
		  if (http_request.status == 200) {
			http_response = http_request.responseText;
			
			loader = new GoogSpellingCorrectionLoader(http_response);
			loader.Load();
			loader.Parse();
			
			DisplaySuggestions(loader.getCSuggestions());
			
			loader = null;
			
			loaderDiv.style.display = 'none';
			correctionsContainer.style.display = 'none';
			jQuery('#correctionsContainer').fadeIn('fast');
			
			CreateRequest();

		  }
		  else 
		  {
			if ( typeof console != "undefined" && console !== null ) {
				console.error('There was a problem with the request');
			}
			loaderDiv.style.display = 'none';
		  }
	 }
}	

function DisplaySuggestions(contentArray)
{
		  correctionsBody.innerHTML = '';
		  if(contentArray.length == 0)
		  {
		  		correctionsBody.innerHTML = '<span class=\"noerrortext\">No spelling errors were found!</span>';
		  }
		  else
		  {
			  for(i=0; i<contentArray.length; i++)
			  {				  
			  	  var googCorrection = contentArray[i];
				  
				  var soffset = googCorrection.getOffset();
				  var slength = googCorrection.getLength();
				  
				  var spanSummaryLine = document.createElement('span');
				  spanSummaryLine.setAttribute('id', 'summaryline_' + String(i));
				  
				  var spanSuggestionCollection = document.createElement('span');
				  spanSuggestionCollection.setAttribute('id', 'spancollection_' + String(i));
				  spanSuggestionCollection.setAttribute('class', 'description');
				  
				  var suggestionArray = googCorrection.getSuggestions();
				  var incorrectWord = txtObject.value.substring(soffset, parseInt(slength) + parseInt(soffset));
				  
				  for(j=0; j<suggestionArray.length;j++)
				  {
						var suggestionSpan = document.createElement('span'); 
						var suggestion = suggestionArray[j];
						
						var re = /'/g;
						var suggestionRep = suggestion.replace(re, "\\'");
						var incorrectWordRep = incorrectWord.replace(re, "\\'");
						
						suggestionSpan.innerHTML = "<a class = \"correction\" href=\"javascript:void(0);\" onclick=\"ApplyCorrection(" + "'" + suggestionRep + "', '" + incorrectWordRep + "', 'summaryline_" + String(i) + "'" + ")\">" + suggestion + "</a>&nbsp;&nbsp;";						
						spanSuggestionCollection.appendChild(suggestionSpan);
				  }
	
				  spanSummaryLine.innerHTML =  '<span class=\"correctiontext\">' + incorrectWord + "&nbsp;&nbsp;:&nbsp;&nbsp;</span>" + spanSuggestionCollection.innerHTML + "<span style=\"font-weight: bold; font-size: 11pt;\">|</span>&nbsp;&nbsp;<a class = \"ignore\" href=\"javascript:void(0);\" onclick=\"IgnoreCorrection(" + "'summaryline_" + String(i) + "')\">ignore</a>" + "<br>";
				  correctionsBody.appendChild(spanSummaryLine);
			   }
		   } 
}

function ApplyCorrection(chosenSuggestion, incorrectWord, summaryLineRef)
{
		  var currentTextFieldVal = txtObject.value;
		  incorrectWord = incorrectWord.replace("\'", "'");
		  txtObject.value = currentTextFieldVal.replace(incorrectWord, chosenSuggestion);
		  IgnoreCorrection(summaryLineRef);
}

function IgnoreCorrection(summaryLineRef)
{
	  correctionsBody.removeChild(document.getElementById(summaryLineRef));
	  
	  var nodeCount = getCorrectionCount();
	  
	  if(nodeCount == 0)
	  {
	  	  correctionsContainer.style.display = 'none';
	  }
}

function getCorrectionCount()
{
	return document.getElementById('correctionsBody').childNodes.length;
}


if(window.addEventListener)
	window.addEventListener('load', InitializeSpellify, false);
else if(window.attachEvent)
	window.attachEvent('onload', InitializeSpellify);
