function nextNodeOf(oNode) {
    do oNode = oNode.nextSibling;
    while (oNode && oNode.nodeType != 1);
    return oNode;
}

function previousNodeOf(oNode) {
    do oNode = oNode.previousSibling;
    while (oNode && oNode.nodeType != 1);
    return oNode;
}

function firstChildOf(oNode) {
    oNode = oNode.firstChild;
    while (oNode && oNode.nodeType != 1)
        oNode = oNode.nextSibling;
    return oNode;
}

function lastChildOf(oNode) {
    oNode = oNode.lastChild;
    while (oNode && oNode.nodeType != 1)
        oNode = oNode.previousSibling;
    return oNode;
}

function cancelEventBubbling(e) {
    if (!e) var e = window.event;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
}

function checkDates(startDateInputId, invalidStartDateAlert, endDateInputId, invalidEndDateAlert, endDateBeforeStartAlert) {
    var alerts = [];

    var startDateInput = startDateInputId ? document.getElementById(startDateInputId) : null;
    var startStringDate = startDateInput ? startDateInput.value : null;
    var startDateParts = startStringDate ? startStringDate.split(".") : null;
    var startDate = startDateParts ? new Date(startDateParts[2], (startDateParts[1] - 1), startDateParts[0]) : null;

    if (startStringDate && !startDate.getTime()) {
        startDateInput.className = "dateEditError";
        alerts[alerts.length] = invalidStartDateAlert;
    } else if (startDateInput)
        startDateInput.className = "dateEdit";

    var endDateInput = endDateInputId ? document.getElementById(endDateInputId) : null;
    var endStringDate = endDateInput ? endDateInput.value : null;
    var endDateParts = endStringDate ? endStringDate.split(".") : null;
    var endDate = endDateParts ? new Date(endDateParts[2], (endDateParts[1] - 1), endDateParts[0]) : null;

    if (endStringDate && !endDate.getTime()) {
        endDateInput.className = "dateEditError";
        alerts[alerts.length] = invalidEndDateAlert;
    } else if (endDateInput)
        endDateInput.className = "dateEdit";

    if (startDate && endDate && startDate.getTime() > endDate.getTime()) {
        startDateInput.className = "dateEditError";
        endDateInput.className = "dateEditError";
        alerts[alerts.length] = endDateBeforeStartAlert;
    }

    if (alerts.length > 0) {
        alert(alerts.join('\n'));
        return false;
    } else
        return true;
}

function toggleBlock(toggleButton) {
    var header = toggleButton.parentNode;
    var block = nextNodeOf(header);
    if (header.className == "collapsedBlockHeader") {
        block.style.display = "";
        header.className = "expandedBlockHeader";
    } else {
        block.style.display = "none";
        header.className = "collapsedBlockHeader";
    }
}

function toggleItemSet(toggleButton, headerInTable) {
    var header = toggleButton.parentNode;
    var block = nextNodeOf(headerInTable ? header.parentNode.parentNode.parentNode.parentNode : header);
    if (header.className == "collapsedItemHeader") {
        block.style.display = "";
        header.className = "expandedItemHeader";
    } else {
        block.style.display = "none";
        header.className = "collapsedItemHeader";
    }
}

function CutString(string,limit){
    // temparary node to parse the html tags in the string
    this.tempDiv = document.createElement('div');
    this.tempDiv.id = "TempNodeForTest";
    this.tempDiv.innerHTML = string;
    // while parsing text no of characters parsed
    this.charCount = 0;
    this.limit = limit;

}

CutString.prototype.cut = function(){
    var newDiv = document.createElement('div');
    this.searchEnd(this.tempDiv, newDiv);
    return newDiv.innerHTML;
};

CutString.prototype.searchEnd = function(parseDiv, newParent){
    var ele;
    var newEle;
    for(var j=0; j< parseDiv.childNodes.length; j++){
	ele = parseDiv.childNodes[j];
	// not text node
	if(ele.nodeType != 3){
	    newEle = ele.cloneNode(true);
	    newParent.appendChild(newEle);
	    if(ele.childNodes.length === 0)
		continue;
	    newEle.innerHTML = '';
	    var res = this.searchEnd(ele,newEle);
	    if(res)
		return res;
	    else{
		continue;
	    }
	}

	// the limit of the char count reached
	if(ele.nodeValue.length + this.charCount >= this.limit){
	    newEle = ele.cloneNode(true);
	    newEle.nodeValue = ele.nodeValue.substr(0, this.limit - this.charCount);
	    newParent.appendChild(newEle);
	    return true;
	}
	newEle = ele.cloneNode(true);
	newParent.appendChild(newEle);
	this.charCount += ele.nodeValue.length;
    }
    return false;
};

function cutHtmlString($string, $limit){
    var output = new CutString($string,$limit);
    return output.cut();
}

function loadXML(url, callback) {
    try {
        var xmlHttp = null;
        if (window.XMLHttpRequest) {
            xmlHttp = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            try {
                xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
            } catch (e) {
                xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
            }
        }

        if (!xmlHttp)
            return -1;

        xmlHttp.open("GET", url, true);
        xmlHttp.onreadystatechange = function () {
            if (xmlHttp.readyState == 4)
                callback(xmlHttp.status == 200 ? xmlHttp.responseXML: null);
        };
        xmlHttp.send(null);
        return 0;
    }
    catch (ex) {
        return -1;
    }
}


// XmlHttp factory
function XmlHttp() {}

XmlHttp.create = function () {
	try {
		if (window.XMLHttpRequest) {
			var req = new XMLHttpRequest();

			// some versions of Moz do not support the readyState property
			// and the onreadystate event so we patch it!
			if (req.readyState == null) {
				req.readyState = 1;
				req.addEventListener("load", function () {
					req.readyState = 4;
					if (typeof req.onreadystatechange == "function")
						req.onreadystatechange();
				}, false);
			}

			return req;
		}
		if (window.ActiveXObject) {
			return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
		}
	}
	catch (ex) {}
	// fell through
	throw new Error("Your browser does not support XmlHttp objects");
};

function getXmlHttpPrefix() {
	if (getXmlHttpPrefix.prefix)
		return getXmlHttpPrefix.prefix;

	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
	var o;
	for (var i = 0; i < prefixes.length; i++) {
		try {
			// try to create the objects
			o = new ActiveXObject(prefixes[i] + ".XmlHttp");
			return getXmlHttpPrefix.prefix = prefixes[i];
		}
		catch (ex) {}
	}

	throw new Error("Could not find an installed XML parser");
}

function loadText(url, callback, protocol) {
    try {
        var xmlHttp = null;
        if (window.XMLHttpRequest) {
            xmlHttp = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            try {
                xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
            } catch (e) {
                xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
            }
        }

        if (!xmlHttp)
            return -1;

        xmlHttp.open(protocol ? protocol : "GET", url, true);
        xmlHttp.onreadystatechange = function () {
            if (xmlHttp.readyState == 4)
                callback(xmlHttp.status == 200 ? xmlHttp.responseText : null, url);
        };
        xmlHttp.send(null);
        return 0;
    }
    catch (ex) {
        return -1;
    }
}


function addGridRow(gridId) {
    var tbody = firstChildOf(document.getElementById(gridId));
    var newRow = nextNodeOf(firstChildOf(tbody)).cloneNode(true);
    tbody.appendChild(newRow);
    newRow.style.display = "";
}

function deleteGridRow(deleteButton) {
    var tr = deleteButton.parentNode.parentNode;
    tr.parentNode.removeChild(tr);
}
