
// --- basic helpers -----------------------------------------------------------

function ttGI(id) 
{
    return document.getElementById(id);
}


function ttGetTarget(e)
{
    e = (e) ? e : ((window.event) ? window.event : "");
    return (e.target) ? e.target : e.srcElement;
}


function ttSetAttr(elemId, attrName, value)
{
    var o = ttGI(elemId);
    if (o)
        o[attrName] = value;
}


function ttSetStyle(elemId, attrName, value)
{
    var o = ttGI(elemId);
    if (o)
        o.style[attrName] = value;
}


function ttParseNumeric(s, minVal, maxVal)
{
    if (minVal == undefined)
        minVal = 0;
    if (maxVal == undefined)
        maxVal = 100000;
    var n = parseInt('0' + s.replace(/[^0-9]/,''), 10); // avoids NaN
    return n < minVal ? minVal : (n > maxVal ? maxVal : n);
}


function ttBacksearchDataId(node, classToken)      // classToken may be like 'js-MyId-'
{
    if (!node) {
        return '';
    }
    if (typeof(node.className) != 'undefined' && node.className)
    {
        var id = ttGetIdFromClassname(node, classToken);
        if (id !== null)
            return id;
    }
    return ttBacksearchDataId(node.parentNode, classToken)    
}


function ttGetIdFromClassname(node, classToken)    // classToken may be like 'js-MyId-'
{
    if (node.className.indexOf(classToken) >= 0)
    {
        var classes = node.className.split(' ');
        for (var i = 0 ; i < classes.length ; i++)
        {
            if (classes[i].indexOf(classToken) == 0)
            {
                return classes[i].substr(classToken.length);
            }
        }
        return '';
    }
    return null;
}


function ttGetElementsByClassName(basenode, tagname, classname)
{
    var elems  = (tagname == "*" && document.all) ? document.all : basenode.getElementsByTagName(tagname);
    var result = [];
    classname = classname.replace(/\-/g, "\\-");
    var reg = new RegExp("(^|\\s)" + classname + "(\\s|$)");
    for(var i=0 ; i < elems.length; i++) 
    {
        if (reg.test(elems[i].className))
            result.push(elems[i]);
    }
    return (result);
}   


function ttBacksearchByTagName(node, tagname)
{
    if (!node || node.nodeName == tagname)
        return node;
    return ttBacksearchByTagName(node.parentNode, tagname);
}


function ttBacksearchByClassname(node, classname)
{
    if (!node || ttHasClass(node, classname))
        return node;
    return ttBacksearchClassname(node.parentNode, classname);
}


function ttHasClass(o, classname)
{
    return (' ' + o.className + ' ').indexOf(' ' + classname + ' ') != -1; 
}


function ttRemoveClass(o, classname)
{
    var reg = new RegExp("\\s" + classname + "(\\s|$)", 'g');
    o.className = (' ' + o.className).replace(reg, ' ').substring(1);
}


function ttAddClass(o, classname)
{
    if ( (' ' + o.className + ' ').indexOf(' ' + classname + ' ') != -1 )
        return;
    o.className = (o.className == '') ? classname : (o.className + ' ' + classname);
}


function ttSwapClass(o, oldClassname, newClassname)
{
//var old = o.className;
    ttRemoveClass(o, oldClassname);
    ttAddClass(o, newClassname);    
//alert(o.id + ': [' + old + '] -> [' + o.className + ']');
}

// --- Positions ---------------------------------------------------------------

function ttViewportWidth() 
{
    if (document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth;
    if (document.body && document.body.clientWidth ) return document.body.clientWidth;
    return window.innerWidth - 18;
}


function ttViewportHeight() 
{
    if (document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight;
    if (document.body && document.body.clientHeight) return document.body.clientHeight;
    return window.innerHeight - 18;
}


function ttViewportScrollX() 
{
    if (document.documentElement && document.documentElement.scrollLeft) return document.documentElement.scrollLeft;
    if (document.body && document.body.scrollLeft) return document.body.scrollLeft;
    if (window.pageXOffset) return window.pageXOffset;
    if (window.scrollX) return window.scrollX;
    return 0;
}


function ttViewportScrollY() 
{
    if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop;
    if (document.body && document.body.scrollTop) return document.body.scrollTop;
    if (window.pageYOffset) return window.pageYOffset;
    if (window.scrollY) return window.scrollY;
    return 0;
}


function ttPageX(elem)
{
    return elem.offsetParent ? elem.offsetLeft + ttPageX(elem.offsetParent) : elem.offsetLeft;
}


function ttPageY(elem)
{
    return elem.offsetParent ? elem.offsetTop + ttPageY(elem.offsetParent) : elem.offsetTop;
}


function ttHorzCenterInWindow(width)
{
    var x = (ttViewportWidth() - width) / 2 + ttViewportScrollX();
    return isNaN(x) ? 0 : x;
}


function ttVertCenterInWindow(height)
{
    var y = (ttViewportHeight() - height) / 2 + ttViewportScrollY();
    return isNaN(y) ? 0 : y;    
}


function TT_PageXY(baseElemId)
{
    var baseX = null;
    var baseY = null;
    this.info  = null;    
    
    this.getX = function(elem)        
    {
        //if (this.info !== null) console.info('getX ['+this.info+']');                                
        if (elem.id == baseElemId) {
            if (baseX === null)
                baseX = ttPageX(document.getElementById(baseElemId));        
            return baseX                    
        }
        return elem.offsetParent ? elem.offsetLeft + this.getX(elem.offsetParent) : elem.offsetLeft;            
    }
        
    this.getY = function(elem)        
    {
        //if (this.info !== null) console.info('getY ['+this.info+']');                                
        if (elem.id == baseElemId) {
            if (baseY === null)
                baseY = ttPageY(document.getElementById(baseElemId));        
            return baseY
        }
        return elem.offsetParent ? elem.offsetTop + this.getY(elem.offsetParent) : elem.offsetTop;
    }
}


// --- Ajax Request ------------------------------------------------------------

var TT_HTTP = {};
TT_HTTP._factory = null;
TT_HTTP._factories = [
    function() { return new XMLHttpRequest(); },
    function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
    function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
];


TT_HTTP.newRequest = function()
{
    // if an appropriate factory was already found, use it
    if (TT_HTTP._factory != null)
        return TT_HTTP._factory();
    // else search a working factory, one that creates a request
    for(var i = 0; i < TT_HTTP._factories.length; i++)
    {
        try
        {
            var factory = TT_HTTP._factories[i];
            var request = factory();
            if (request != null) {
                TT_HTTP._factory = factory;
                return request;
            }
        }
        catch(e) { continue; }
    }
    // no factory method did work, each did throw an exception
    TT_HTTP._factory = function() {
        throw new Error("XMLHttpRequest not supported");
    }
    TT_HTTP._factory(); // throw exception
}

