﻿if (typeof(Tangora) == 'undefined') var Tangora = {};
Tangora.Layout = new LayoutController();

function LayoutController()
{
    this.RegisteredLayouts = [];
    this.RegisteredLiquidLayouts = [];
	
	this.RegisterLayout = function(id, balanceMode, balancedColumns, blocklistMode)
	{
	    if (!balanceMode) balanceMode = 'Automatic';
	    if (!balancedColumns) balancedColumns = null;
	    if (!blocklistMode) blocklistMode = false;
		this.RegisteredLayouts.push({id:id,balanceMode:balanceMode,balancedColumns:balancedColumns,blocklistMode:blocklistMode});
    }

    this.RegisterLiquidLayout = function (id, blocklistMode)
    {
        var version = parseInt(this.GetIEVersion(), 10);
        if (version > 0 && version < 8)
        {
            this.RegisteredLiquidLayouts.push({id:id,blocklistMode:blocklistMode});
        }
    }
	
	this.StartupScripts = function()
	{
	    // Ensure highlights in visual designer layouts
	    highlightSearchwords();
	}
	
	
	this.IE6Patch = function()
	{
	    // Sets heights according to min-height
	    var divs = document.getElementsByTagName('div');
	    for (var i=0; i<divs.length; i++)
	    {
	        var minHeight = Tangora.Layout.GetStyle(divs[i], 'min-height');
	        var hasHeight = typeof(divs[i].style.height) != 'undefined' && divs[i].style.height != null && divs[i].style.height.length > 0 && divs[i].style.height != 'auto';
	        if (minHeight != 'auto' && !hasHeight)
	        {
	            divs[i].style.height = Tangora.Layout.GetStyle(divs[i], 'min-height');
	            divs[i].style.overflowY = 'visible';
	        }
	    }
	}
	
	this.IE6Hover = function() 
    {
        // Adds hover class to li-elements for css-hover navigations to work in IE6.
        var lis = document.getElementsByTagName("li");
        for (var i=0; i<lis.length; i++) 
        {
            if (lis[i].className.indexOf('navigationlistitem') != -1)
            {
	            lis[i].onmouseover=function() 
	            {
		            this.className += ' ie6hover';
	            }
	            lis[i].onmouseout=function() 
	            {
		            this.className = this.className.replace(new RegExp(' ie6hover\\b'), '');
	            }
	        }
        }
        
        // Sets correct navigation-styles, depending on horizontal or vertical navigation.
        // We need to do this post-processing because IE6 doesn't support multiple classnames,
        // so later-loaded navigation stylesheets may target level1 with undesired styles.
        
        // First find the navigation type of level 1 in the css-hover hierarchy:
        var navtype = '';
        var divs = document.getElementsByTagName('div');
        var wrapper = null;
        for (var i=0; i < divs.length; i++)
        {
            if(divs[i].className.indexOf('sfnavlevel1') != -1)
            {
                navtype = divs[i].className.replace('sfnavlevel1', '').replace(/\s/g, '');
                wrapper = divs[i].firstChild;
                break;   
            }   
        }
        
        // Then find out if it id a vertical style navigation adn what the navigation item width is:
        var vertical = false;
        var width = '150px'
        if (navtype != '')
        {
            for (var i=0; i<document.styleSheets.length; i++)
            {
                if (document.styleSheets[i].href.indexOf(navtype + '/navigation.css') != -1)
                {
                    for (var j=0; j<document.styleSheets[i].rules.length; j++)
                    {
                        if (document.styleSheets[i].rules[j].selectorText.toLowerCase() == 'div.sfnavlevel1 .navigationwrapper')
                        {
                            if (/float\s*:\s*left/i.test(document.styleSheets[i].rules[j].style.cssText))
                            {
                                vertical = true;
                            }
                        }
                        if (document.styleSheets[i].rules[j].selectorText.toLowerCase() == 'div.sfnavlevel1 li .navigationwrapper')
                        {
                            if  (/width\s*:\s*(\d*)(%|em|px|pt)/i.test(document.styleSheets[i].rules[j].style.cssText))
                            {
                                width = RegExp.$1 + RegExp.$2;
                            }
                        }
                    }
                    break;
                }    
            }
        }
        
        // Finally set the correct styles of level 1:
        var css = '';
        if (vertical)
        {
            css += 'div.sfnavlevel1 .navigationwrapper { clear:none; float:left; width:100%; }\n';
            css += 'div.sfnavlevel1 div.navigationwrapper ul.navigationlist li.navigationlistitem a,\n'; 
            css += 'div.sfnavlevel1 ul.navigationlist li.navigationlistitem { float:left; width:100%; }\n';
            css += 'div.sfnavlevel1 div.sfnavlevel2 { clear:none; }\n';
        }
        else
        {
            css += 'div.sfnavlevel1 .navigationwrapper { clear:both; float:none; width:auto; }\n';
            css += 'div.sfnavlevel1 div.navigationwrapper ul.navigationlist li.navigationlistitem a,'; 
            css += 'div.sfnavlevel1 ul.navigationlist li.navigationlistitem { float:left; }\n';
            css += 'div.sfnavlevel1 div.sfnavlevel2 ul.navigationlist li.navigationlistitem { width:'+ width +'; }\n';
            css += 'div.sfnavlevel1 div.sfnavlevel2 { clear:left; }\n'; 
        }
        if (wrapper)
        {
            var styleElement = document.createElement('style');
            styleElement.setAttribute('type', 'text/css');
            styleElement.styleSheet.cssText = css;
            var head = document.getElementsByTagName('head')[0];
            head.appendChild(styleElement);
        }
    }
    
    this.GetIEVersion = function()
    {
        // Some IE useragent contains both MSIE 6.0 & MSIE 7.0, so we get the highest version...
        var version = '0.0';
        var maxversion = '0.0';
        try
        {
            var ua = navigator.userAgent;
            var start = new Date().getTime();
            while (/msie\s\d*\.\d*/gi.test(ua))
            {
                ua = ua.substr(RegExp.lastIndex);
                version = RegExp.lastMatch.replace(/[^\d\.]/gi, '');
                if (parseInt(version, 10) > parseInt(maxversion, 10)) maxversion = version;
                if (new Date().getTime() - start > 100) break;
            }
        }
        catch (err) {}
        return maxversion;
    }

    this.Initialize = function ()
    {
        if (typeof (Tangora.Events) != 'undefined')
        {
            Tangora.Events.AddHandler(window, 'onload', this.Resize);
            Tangora.Events.AddHandler(window, 'onload', this.StartupScripts);

            var version = parseInt(this.GetIEVersion(), 10);
            if (version > 0)
            {
                if (version == 6)
                {
                    Tangora.Events.AddHandler(window, 'onload', this.IE6Patch);
                    Tangora.Events.AddHandler(window, 'onload', this.IE6Hover);
                }
                if (version < 8)
                {
                    Tangora.Events.AddHandler(window, 'onresize', this.ResizeDelay);
                }
            }
        }
        else // Manager - EditWebPage
        {
            Tangora.Core.AddHandler(window, 'load', this.Resize);
            Tangora.Core.AddHandler(window, 'resize', this.Resize);
        }
    }

    // resize delay is needed because IE fires resize events continuously so we will wait until no events has been dispatched for half a second 
    var resizeTimeout = null;
    this.ResizeDelay = function ()
    {
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(Tangora.Layout.Resize, 500);
    }

    this.Resize = function ()
    {
        // For debugging:
        if (/tangoralayoutresize=false/i.test(location.href) || Tangora.ByPassResizeScript)
        {
            return;
        }

        var tl = Tangora.Layout;

        // -------------------------------------------------------


        if (tl.RegisteredLiquidLayouts.length > 0)
        {
            // Resetting general styles from display:table-style to float-style

            var divs = document.getElementsByTagName('div');
            for (var i = 0; i < divs.length; i++)
            {
                var div = divs[i];

                if (/\s*layoutcolumnset\s*/i.test(div.className))
                {
                    div.style.display = 'block';
                    div.style.clear = 'both';
                }
                else if (/\s*layoutcolumn\s*/i.test(div.className))
                {
                    div.style.display = 'block';
                    div.style.overflow = 'hidden';
                    div.style.styleFloat = 'left';
                }
                else if (/\s*layoutfloatbreaker\s*/i.test(div.className))
                {
                    div.style.display = '';
                    div.style.clear = 'both';
                }
            }

            // Setting specific layout styles

            for (var i = 0; i < tl.RegisteredLiquidLayouts.length; i++)
            {
                var tlr = tl.RegisteredLiquidLayouts[i];
                if (tlr.blocklistMode)
                {
                    for (var j = 0; j < divs.length; j++)
                    {
                        if (divs[j].className == tlr.id)
                        {
                            tl.ConvertLiquidLayout(divs[j]);
                            tl.AdjustColumns(divs[j], 'Automatic', null, tlr.blocklistMode);
                        }
                    }
                }
                else
                {
                    tl.ConvertLiquidLayout(document.getElementById(tlr.id));
                    tl.AdjustColumns(document.getElementById(tlr.id), 'Automatic', null, tlr.blocklistMode);
                }
            }
        }

        // -------------------------------------------------------


        for (var i = 0; i < tl.RegisteredLayouts.length; i++)
        {
            var tlr = tl.RegisteredLayouts[i];
            if (tlr.balanceMode == 'Manual' && tlr.balancedColumns == null) continue; // No columns to balance
            if (tlr.blocklistMode)
            {
                // In blocklistmode the layout id is set as classname to avoid id-clashes so we have to find the wrapper(s) by the class name
                var divs = document.getElementsByTagName('div');
                for (var j = 0; j < divs.length; j++)
                {
                    if (divs[j].className == tlr.id)
                    {
                        tl.AdjustColumns(divs[j], tlr.balanceMode, tlr.balancedColumns, tlr.blocklistMode);
                    }
                }
            }
            else
            {
                tl.AdjustColumns(document.getElementById(tlr.id), tlr.balanceMode, tlr.balancedColumns, tlr.blocklistMode);
            }
        }

        // In IE6, IE7 there is a bug that incorrectly repositions all absolute/relative positioned elements if their container height is changed.
        // Container-heights do change in AdjustColumns, so below hack is needed to force absolute positioned elements back in place.
        // The flag Tangora.FixIEPositionAbsoluteBug should be set to true in the headsection of the layout. 
        if (Tangora.FixIEPositionAbsoluteBug && navigator.userAgent.indexOf('MSIE') != -1)
        {
            var elms = document.body.getElementsByTagName('*');
            for (var i = 0; i < elms.length; i++)
            {
                var pos = tl.GetStyle(elms[i], 'position');
                if (pos != null)
                {
                    elms[i].style.position = 'static';
                    if (pos.toLowerCase() == 'absolute')
                    {
                        elms[i].style.position = 'absolute';
                    }
                    else if (pos.toLowerCase() == 'relative')
                    {
                        elms[i].style.position = 'relative';
                    }
                }
            }
        }
    }
	
	this.AdjustColumns = function(wrapper, balanceMode, balancedColumns, blocklistMode)
	{
		if (wrapper)
		{
			var coll = this.GetColumnSets(wrapper);
			for (var i=0; i<coll.length; i++)
			{
				this.EnsureColumnHeights(coll[i], balanceMode, balancedColumns, blocklistMode);
			}
		}
	}
	
	this.GetStyle = function(elm, attribute)
	{
	    if (elm.currentStyle)
		{
			r = elm.currentStyle[this.CssCamelCase(attribute)];
		}
		else if (document.defaultView && document.defaultView.getComputedStyle)
		{
			var styles = document.defaultView.getComputedStyle(elm, null);
			if (styles) r = styles.getPropertyValue(attribute);
		}
		return r;
	}
	
	this.EnsureColumnHeights = function(colset, balanceMode, balancedColumns, blocklistMode)
	{
		var cols = this.GetColumns(colset);
		// reset columnset wrapper height
		colset.style.height = '';
		// first, iterate all columns in this columnset and find the max height
		var maxH = 0;
		for (var k=0; k<cols.length; k++)
		{
			// adjust any inner columns before measuring this column
			this.AdjustColumns(cols[k], balanceMode, balancedColumns, blocklistMode);
			// Height is reset according to the font-size.
			var fontSize = this.GetStyle(cols[k], 'font-size');
			if (navigator.userAgent.indexOf('MSIE 6.0') == -1 || this.GetStyle(cols[k], 'height') == 'auto')
			{
			    cols[k].style.height = (fontSize == '0pt') ? '0px' : '';
			}
			// Get column offsetheight and check if it's larger than the current max height 
			var h = cols[k].offsetHeight;
			if (h > maxH) maxH = h;
		}
 		// now, iterate all columns again and set their height to max height
		for (var l=0; l<cols.length; l++)
		{
			// the page uses the standards mode box model, so we have to subtract all affecting styles,
			// ie. border-top/-bottom, margin-top/-bottom and padding-top/-bottom, from max height before setting it
			var subt = this.GetHeightSubtracts(cols[l]);
			var newH = maxH - subt;
			if (newH < 0) newH = 0;
			if (balanceMode != 'Manual' || isBalancedColumn(cols[l]))
			{
			    cols[l].style.height = newH + 'px';
			}
		}
		colset.style.height = maxH + 'px';
		
		function isBalancedColumn(col)
		{
		    if (!balancedColumns) return false;
		    for (var h=0; h<balancedColumns.length; h++)
		    {
		        if (!blocklistMode && col.id == balancedColumns[h]) return true;
		        else if (blocklistMode && col.className.indexOf(balancedColumns[h]) != -1) return true;
		    }
		    return false;
		}
	}
	
	this.GetColumnSets = function(wrapper)
	{
		return this.GetChildNodes(wrapper, 'div', 'layoutcolumnset');
	}

	this.GetColumns = function(colset)
	{
		return this.GetChildNodes(colset, 'div', 'layoutcolumn');
	}
	
	this.GetChildNodes = function(parentElement, childTagName, childClassName)
	{
		var coll = [];
		for (var i=0; i<parentElement.childNodes.length; i++)
		{						
			var chld = parentElement.childNodes[i];
			if (chld.nodeType != 3 && chld.tagName && chld.tagName.toLowerCase() == childTagName.toLowerCase() && chld.className.indexOf(childClassName) > -1 && chld.parentNode == parentElement) coll.push(chld);
		}
		return coll;
	}

	this.GetHeightSubtracts = function(elm)
	{
		var affectingStyles = ['border-top-width', 'border-bottom-width', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom'];
		return Tangora.Layout.GetSubtracts(elm, affectingStyles);
	}
	
	this.GetWidthSubtracts = function(elm, marginsOnly)
	{
		var affectingStyles = ['border-left-width', 'border-right-width', 'padding-left', 'padding-right', 'margin-left', 'margin-right'];
		if (marginsOnly) affectingStyles = ['margin-left', 'margin-right'];
		return Tangora.Layout.GetSubtracts(elm, affectingStyles);
	}

	this.GetSubtracts = function(elm, affectingStyles)
	{
		var r = 0;
		for (var i=0; i<affectingStyles.length; i++)
		{
			var style = affectingStyles[i];
			var borderStyleWatch = (style.indexOf('border') > -1) ? this.CssCamelCase(style.substr(0, style.lastIndexOf('-')) + 'Style') : null;
			if (elm.currentStyle)
			{
				var n;
				if (borderStyleWatch && elm.currentStyle[borderStyleWatch] == 'none') n = 0;
				else n = parseInt(elm.currentStyle[this.CssCamelCase(style)]);
				if (!isNaN(n)) r += n;
			}
			else if (document.defaultView && document.defaultView.getComputedStyle)
			{
				var currStyle = document.defaultView.getComputedStyle(elm, null);
				if (currStyle)
				{
				    var n = parseInt(currStyle.getPropertyValue(style));
				    if (!isNaN(n)) r += n;
				}
			}
		}
		return r;
	}
	
	this.CssCamelCase = function(s)
	{
		var r = '';
		var lastWasHyphen = false;
		for (var i=0; i<s.length; i++)
		{
			var c = s.substr(i,1);
			if (c == '-')
			{
				lastWasHyphen = true;
			}
			else if (lastWasHyphen)
			{
				r += c.toUpperCase();
				lastWasHyphen = false;
			}
			else
			{
				r += c;
			}
		}
		return r;
	}
	
	this.SetBrowserSpecificStylesheet = function(file, conditions, andOr)
	{      
	    function compareVersion(v1, v2, operator)
	    {
	        var a = parseFloat(v1);
	        var b = parseFloat(v2)
	        switch (operator)
	        {
	            case 'equal': return a == b; break; 
                case 'not_equal': return a != b; break;
                case 'less_than': return a < b; break;
                case 'greater_than': return a > b; break;
                case 'less_than_or_equal': return a <= b; break;
                case 'greater_than_or_equal': return a >= b; break;
	        }
	    }
	
	    var show = false;
	    for (var i=0; i<conditions.length; i++)
	    {
	        var cnd = conditions[i];
	        var browser = navigator.userAgent;
	        var version = '';
	        if (cnd.Browser)
	        {
	            switch (cnd.Browser)
	            {
	                case 'Internet Explorer':
	                    if (/msie\s(\d+\.\d)/i.test(browser))
	                    {
	                        if (cnd.Version == 'all') show = true;
	                        else show = compareVersion(RegExp.$1, cnd.Version, cnd.Operator);    
	                    }       
	                    break;
	                case 'FireFox':
	                    if (/firefox\/(\d+\.\d)/i.test(browser))
	                    {
	                        if (cnd.Version == 'all') show = true;
	                        else show = compareVersion(RegExp.$1, cnd.Version, cnd.Operator);
	                    }
	                    break;
	                case 'Safari':
	                    if (/safari/i.test(browser) && !/chrome/i.test(browser))
	                    {
	                        if (cnd.Version == 'all') show = true;
	                        else if (/version\/(\d+\.\d)/i.test(browser)) show = compareVersion(RegExp.$1, cnd.Version, cnd.Operator);
	                        else show = compareVersion('2.0', cnd.Version, cnd.Operator); // safari version 2.0 and below does not have version number in useragent string
	                    }
	                    break;
	                case 'Chrome':
	                    if (/chrome\/(\d+\.\d)/i.test(browser))
	                    {
	                        if (cnd.Version == 'all') show = true;
	                        else show = compareVersion(RegExp.$1, cnd.Version, cnd.Operator);
	                    }
	                    break;
	                case 'Opera':
	                    if (/opera/i.test(browser))
	                    {
	                        if (cnd.Version == 'all') show = true;
	                        else if (/version\/(\d+\.\d)/i.test(browser)) show = compareVersion(RegExp.$1, cnd.Version, cnd.Operator);
	                        else if (/opera\/(\d+\.\d)/i.test(browser)) show = compareVersion(RegExp.$1, cnd.Version, cnd.Operator);
	                    }
	                    break;
	            }
	        }
	        else if (cnd.Regex)
	        {
	            var regex = new RegExp(cnd.Regex, "gi");
	            show = regex.test(browser);
	        }
	        if (!show && andOr == 'and') break;
	        if (show && andOr == 'or') break;
	    }
	    if (show)
	    {
	        document.write('<link rel="stylesheet" type="text/css" href="'+ file +'">');    
	    }
	}

	this.ConvertLiquidLayout = function (layout)
	{
	    var tl = Tangora.Layout;
	    var width = tl.GetStyle(layout, 'width');
	    if (width.indexOf('%') != -1)
	    {
	        // first run (page load) stores original percent
	        layout.orgpct = parseInt(width, 10);
	    }
	    if (typeof (layout.orgpct) != 'undefined')
	    {
	        // first and additional runs (page load and refreshes) width is calculated as the original percentage of the available space
	        if (layout.parentNode.clientWidth > 0)
	        {
	            layout.style.width = layout.parentNode.clientWidth * (layout.orgpct / 100);
	        }
	    }
	    tl.ConvertLiquidColumns(layout);
	}

	this.ConvertLiquidColumns = function (wrapper)
	{
	    var tl = Tangora.Layout;
	    var colsets = tl.GetColumnSets(wrapper);
	    for (var i = 0; i < colsets.length; i++)
	    {
	        var colset = colsets[i];
	        var cols = tl.GetColumns(colset);

	        // colset should use all available width
	        colset.style.width = colset.parentNode.clientWidth + 'px';

	        // in first run (page load) the columns still have their original percentage width - we store it in an expando for later retreval
	        for (var j = 0; j < cols.length; j++)
	        {
	            var col = cols[j];
	            var colwidth = tl.GetStyle(col, 'width');
	            if (colwidth.indexOf('%') != -1)
	            {
	                col.orgpct = parseInt(colwidth, 10);
	            }
	        }

	        var usedpx = 0;
	        var usedpct = 0;
	        var pctcols = []
	        for (var j = 0; j < cols.length; j++)
	        {
	            var col = cols[j];
	            if (typeof (col.orgpct) != 'undefined')
	            {
	                // percentage based column
	                usedpct += col.orgpct;
	                pctcols.push(col);
	            }
	            else
	            {
	                // pixel based column
	                usedpx += parseInt(tl.GetStyle(col, 'width'), 10);
	            }
	        }


	        var leftover = parseInt(colset.style.width, 10) - usedpx;
	        var pct2px = leftover / usedpct;
	        var pxconverted = 0;
	        for (var j = 0; j < pctcols.length; j++)
	        {
                var col = pctcols[j];
	            var pxlwidth = Math.round(col.orgpct * pct2px);
	            if (j < pctcols.length - 1)
	            {
	                col.style.width = pxlwidth + 'px';
	                pxconverted += pxlwidth;
	            }
	            else
	            {
	                // last column takes up all available pixels
	                col.style.width = Math.max(0, (leftover - pxconverted)) + 'px';
	            }
	        }
	        
            // recursive stuff
	        for (var j = 0; j < cols.length; j++)
	        {
	            tl.ConvertLiquidColumns(cols[j]);
	        }
	    }
	}
	
	this.Initialize();
}

