﻿//
// SharpSpell v3.0 - Copyright (c) 2006 Tachyon Labs (tachyon-labs.com)
//
// Real-time spell-as-you-type for the web spell checker.
// For more information, visit http://www.tachyon-labs.com/sharpspell/
//

var SharpSpell = { };

SharpSpell.UserAgent = navigator.userAgent.toLowerCase();
SharpSpell.IsIE = ((SharpSpell.UserAgent.indexOf("msie") != -1) && (SharpSpell.UserAgent.indexOf("opera") == -1));
SharpSpell.IsGecko = (navigator.product == "Gecko");
SharpSpell.IsOpera = (SharpSpell.UserAgent.indexOf("opera") != -1);

SharpSpell.SupportPath = "";

SharpSpell.getElementsByClassName = function(oElm, strTagName, strClassName)
{
    var arrElements = (strTagName == "*" && document.all)? document.all : 
    oElm.getElementsByTagName(strTagName);
    var arrReturnElements = [ ];
    strClassName = strClassName.replace(/\-/g, "\\-");
    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
    var oElement;
    for(var i=0; i<arrElements.length; i++){
        oElement = arrElements[i];      
        if(oRegExp.test(oElement.className)){
            arrReturnElements.push(oElement);
        }   
    }
    return arrReturnElements;
};

SharpSpell.addEvent = function (el, eventName, func) {
	if (el.attachEvent){ 
		el.attachEvent("on" + eventName, func);
	} else {
		el.addEventListener(eventName, func, true);
	}
};

SharpSpell.createCookie = function (name,value,days)
{
    var expires = "";
    if (days)
    {
        var date = new Date();
        date.setTime(date.getTime() + (days*24*60*60*1000));
        expires = "; expires=" + date.toGMTString();
    }
    document.cookie = name + "=" + value + expires + "; path=/";
};

SharpSpell.readCookie = function (name)
{
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++)
    {
        var c = ca[i];
        while (c.charAt(0) == ' ') { c = c.substring(1,c.length); }
        if (c.indexOf(nameEQ) == 0) { return c.substring(nameEQ.length,c.length); }
    }
    return;
};
        

SharpSpell.htmlEncode = function (s) {
	var str = s;
	str = str.replace(/&/g, "&amp;");
	str = str.replace(/</g, "&lt;");
	str = str.replace(/>/g, "&gt;");
	str = str.replace(/"/g, "&quot;");
	str = str.replace(/ /g, "&nbsp;");
	str = str.replace(/\r\n/g, "<br>");
	str = str.replace(/\n/g, "<br>");
	str = str.replace(/\r/g, "<br>");
	
	return str;
};

SharpSpell.getTextInternal = function (root, encode) {
	var html = "";
	switch (root.nodeType) {
	    case 1: // Node.ELEMENT_NODE
	    case 11: // Node.DOCUMENT_FRAGMENT_NODE
			var i;
			if (root.tagName.toLowerCase() == "br")
			{
				html+="\n";
		    }
			for (i = root.firstChild; i; i = i.nextSibling) {
				html += SharpSpell.getTextInternal(i, encode);
			}
			break;
	    case 3: // Node.TEXT_NODE
			if (root.data != '\n') 
			{
				html = root.data;
				if (encode) {
					html = html.replace(/&/g, "&amp;");
					html = html.replace(/</g, "&lt;");
					html = html.replace(/>/g, "&gt;");
					html = html.replace(/"/g, "&quot;");
					html = html.replace(/ /g, "&nbsp;");
				}
			}
			break;
	}
	return html;
};

SharpSpell.Debug = function (msg) {
    var p = document.createElement("p");
    p.appendChild(document.createTextNode(msg));
    document.body.appendChild(p);
};

SharpSpell.getScrollXY = function () {
  var scrOfX = 0, scrOfY = 0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
    scrOfX = window.pageXOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
    scrOfX = document.body.scrollLeft;
  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
    scrOfX = document.documentElement.scrollLeft;
  }

  return { x: scrOfX, y: scrOfY };
};

SharpSpell.getWindowSize = function () {
  var myWidth = 0, myHeight = 0;
  if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  } else if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight; 
  }
  return { width: myWidth, height: myHeight };
};

SharpSpell.getMousePos = function ()
{
	return { x: SharpSpell.MouseX, y: SharpSpell.MouseY };
};

SharpSpell.createXMLHTTP = function ()
{
	//XMLHttp init
	var xmlhttp = null;
	if (window.XMLHttpRequest)
	{
		xmlhttp = new XMLHttpRequest();
    }
    else if (window.ActiveXObject) 
    {
	    try {
		    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
	    } catch (e) {
		    try {
			    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
		    } catch (e) {
		        xmlhttp = false;
		    }
	    }    
    }
    return xmlhttp;
}

SharpSpell.addWordToDictionary = function (word) 
{
    var userdic = "";
    userdic = SharpSpell.readCookie("SharpSpellUserDic");
    if (!userdic || userdic.length == 0) 
    {
        SharpSpell.createCookie("SharpSpellUserDic", word, 360);
    }
    else
    {
        SharpSpell.createCookie("SharpSpellUserDic", "", -1);
        SharpSpell.createCookie("SharpSpellUserDic", userdic + "|" + word, 360);
    }
}

SharpSpell.addWordToIgnore = function (word)
{
    var ignore = "";
    ignore = SharpSpell.readCookie("SharpSpellIgnore");
    if (!ignore || ignore.length == 0) 
    {
        SharpSpell.createCookie("SharpSpellIgnore", word);
    }
    else
    {
        SharpSpell.createCookie("SharpSpellIgnore", "", -1);
        SharpSpell.createCookie("SharpSpellIgnore", ignore + "|" + word);
    }
}

SharpSpell.getUserDictionary = function ()
{
    var userdic;
    userdic = SharpSpell.readCookie("SharpSpellUserDic");
    if (userdic) {
        userdic = "|" + userdic + "|";
    } else {
        userdic = "";
    }
    return userdic;
}

SharpSpell.getUserIgnoreList = function ()
{
    var ignore;
    ignore = SharpSpell.readCookie("SharpSpellIgnore");
    if (ignore) {
        ignore = "|" + ignore + "|";
    } else {
        ignore = "";
    }
    return ignore;
}

SharpSpell.clearUserSettings = function ()
{
    SharpSpell.createCookie("SharpSpellIgnore", "", -1);
    SharpSpell.createCookie("SharpSpellUserDic", "", -1);
}


SharpSpell.getRealCoords = function (uEleObj,uEleAxis)
{
    //get real coords function
    var uTempObj,uEleAxis;
    (uEleAxis=="x") ? uElePos = uEleObj.offsetLeft - uEleObj.scrollLeft : uElePos = uEleObj.offsetTop - uEleObj.scrollTop;
    uTempObj = uEleObj.offsetParent;
    while(uTempObj != null){
        uElePos += (uEleAxis=="x") ? uTempObj.offsetLeft - uTempObj.scrollLeft : uTempObj.offsetTop - uTempObj.scrollTop;
        uTempObj = uTempObj.offsetParent;
    }
    return uElePos;
}


SharpSpell.getStyle = function (oElm, strCssRule){
// thanks to Robert Nyman
	var strValue = "";
	if(document.defaultView && document.defaultView.getComputedStyle){
		strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
	}
	else if(oElm.currentStyle){
        while(-1 != (dashIndex = strCssRule.indexOf('-'))) {
        strCssRule= strCssRule.substring(0,dashIndex) + strCssRule.substring(dashIndex + 1, dashIndex + 2).toUpperCase() + strCssRule.substring(dashIndex + 2);
        }
		strValue = oElm.currentStyle[strCssRule];
	}
	return strValue;
}

/* Cross-Browser Split v0.1; MIT-style license
By Steven Levithan <http://stevenlevithan.com>
An ECMA-compliant, uniform cross-browser split method */

String.prototype.split = function(separator, limit) {
	var flags = "";
	
	/* Behavior for separator: If it's...
	- Undefined: Return an array containing one element consisting of the entire string
	- A regexp or string: Use it
	- Anything else: Convert it to a string, then use it */
	if (separator === undefined) {
		return [this.toString()]; // toString is used because the typeof this is object
	} else if (separator === null || separator.constructor !== RegExp) {
		// Convert to a regex with escaped metacharacters
		separator = new RegExp(String(separator).replace(/[.*+?^${}()|[\]\/\\]/g, "\\$&"), "g");
	} else {
		flags = separator.toString().replace(/^[\S\s]+\//, "");
		if (!separator.global) {
			separator = new RegExp(separator.source, "g" + flags);
		}
	}
	
	// Used for the IE non-participating capturing group fix
	var separator2 = new RegExp("^" + separator.source + "$", flags);
	
	/* Behavior for limit: If it's...
	- Undefined: No limit
	- Zero: Return an empty array
	- A positive number: Use limit after dropping any decimal value (if it's then zero, return an empty array)
	- A negative number: No limit, same as if limit is undefined
	- A type/value which can be converted to a number: Convert, then use the above rules
	- A type/value which cannot be converted to a number: Return an empty array */
	if (limit === undefined || +limit < 0) {
		limit = false;
	} else {
		limit = Math.floor(+limit);
		if (!limit) return []; // NaN and 0 (the values which will trigger the condition here) are both falsy
	}
	
	var match,
		output = [],
		lastLastIndex = 0,
		i = 0;
	
	while ((limit ? i++ <= limit : true) && (match = separator.exec(this))) {
		// Fix IE's infinite-loop-resistant but incorrect RegExp.lastIndex
		if ((match[0].length === 0) && (separator.lastIndex > match.index)) {
			separator.lastIndex--;
		}
		
		if (separator.lastIndex > lastLastIndex) {
			/* Fix IE to return undefined for non-participating capturing groups (NPCGs). Although IE
			incorrectly uses empty strings for NPCGs with the exec method, it uses undefined for NPCGs
			with the replace method. Conversely, Firefox incorrectly uses empty strings for NPCGs with
			the replace and split methods, but uses undefined with the exec method. Crazy! */
			if (match.length > 1) {
				match[0].replace(separator2, function(){
					for (var j = 1; j < arguments.length - 2; j++){
						if (arguments[j] === undefined) match[j] = undefined;
					}
				});
			}
			
			output = output.concat(this.substring(lastLastIndex, match.index), (match.index === this.length ? [] : match.slice(1)));
			lastLastIndex = separator.lastIndex;
		}
		
		if (match[0].length === 0) {
			separator.lastIndex++;
		}
	}
	
	return (lastLastIndex === this.length)
		? (separator.test("") ? output : output.concat(""))
		: (limit ? output : output.concat(this.substring(lastLastIndex)));
};