﻿if (typeof(Tangora) == 'undefined') var Tangora = {};
Tangora.Layout = new LayoutController();

function LayoutController()
{
	this.RegisteredLayouts = [];
	
	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.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);
			
			if (this.GetIEVersion() == '6.0')
		    {
		        Tangora.Events.AddHandler(window, 'onload', this.IE6Patch);
		        Tangora.Events.AddHandler(window, 'onload', this.IE6Hover);
		    }		
		}
		else // Manager - EditWebPage
		{
			Tangora.Core.AddHandler(window, 'load', this.Resize);			
			Tangora.Core.AddHandler(window, 'resize', this.Resize);
		}
	}
		
	this.Resize = function()
	{
	    // For debugging:
	    if (/tangoralayoutresize=false/i.test(location.href) || Tangora.ByPassResizeScript)
	    {
	        return;
	    }
	    
		var tl = Tangora.Layout;
		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.Initialize();
}

