﻿
(function(){

WebPart = function(config)
{
    this.config = config;
};

WebPart.prototype = {
    load : function()
    {
        var c = this.config;
        if( c.loadFrom )
        {
            WebPartManager.loadHtml(c.loadFrom, c.params, c);
        }
    },
    submit : function(form)
    {
        WebPartManager.submitForm(form, null);
    },
    navigate : function(href)
    {
        WebPartManager.loadHtml(href, null, this.config);
    }
}

WebPartManager =
{    
    _WebParts : {},
    
    empty : function() {},
    
    init : function(config)
    {
        var o = new WebPart(config);
        WebPartManager._WebParts[config.id] = o;
        o.load();
    },
    getHtml : function(url, queryString, callback)
    {
        try 
        {                                            
            $.ajax({
                url:        url,
                type:       "GET",
                data:       queryString,
                dataType:   "html",
                success:    callback,
                error:      function(xml, status, e) 
                { 
                    //alert("Error occured while loading: " + url +'\n' + xml.status + ":" + xml.statusText + '\n' + xml.responseText); 
                    if( xml && xml.responseText )
                        callback(xml.responseText);
                    else
                        alert("Error occured while loading: " + url +'\n' + e.message);
                },
                cache:      true
            });
        } catch(e) { 
            alert(e);
        }
    },
    
    getWebPart : function(id)
    {
        return WebPartManager._WebParts[id];
    },
    
    
    loadHtml : function(url, params, config)
    {
        var container = $('#' + config.id);
        var queryString = $.param(params || {});
        
        if((config.beforeLoad || WebPartManager.empty)(url, params) !== false)
        {
            if(config.progressTemplate) container.html(config.progressTemplate);
            config.loadFrom = url;
            WebPartManager.getHtml(url, queryString, function(content)
            {
                (config.afterLoad || WebPartManager.empty)(url, content);
                WebPartManager.processHtml(content, container, config);
            });
        }
    },
    
    processHtml : function(content, container, config)
    {
        
        var result = WebPartManager.parseHtml(content, config);
            
        var head = document.getElementsByTagName('head')[0];
        
        $(result.styles).each(function(index,text)
        {                
            var styleNode = document.createElement("style");
	        styleNode.setAttribute("type", "text/css");
	        if(styleNode.styleSheet) // IE
	        {
		        styleNode.styleSheet.cssText = text;
	        } 
	        else // w3c
	        {
		        var cssText = document.createTextNode(text);
		        styleNode.appendChild(cssText);
	        }
			
	        head.appendChild(styleNode);
        });
        
        $(result.links).each(function(index,attrs)
        {
            window.setTimeout(function()
            {                
                var link = document.createElement('link');
                var href = "";
                for( var i = 0; i < attrs.length; i ++ )
                {
                    var attr = attrs[i];
                    if( attr.name == "href" ) href = attr.value;
                    link.setAttribute("" + attr.name, "" + attr.value);
                }
                
                if( href.length > 0 )
                { 
                    link.href = WebPartManager.resolveUrl( config.loadFrom, href );
                    if( !WebPartManager.isTagLoaded('link', 'href', link.href) )
                        head.appendChild(link);
                }
            }, 0);
        });
        
        var scriptsToLoad = result.externalScripts.length;
        
        $(result.externalScripts).each(function(index, scriptSrc)
        {
            scriptSrc = WebPartManager.resolveUrl( config.loadFrom, scriptSrc );
            
            if( WebPartManager.isTagLoaded('script', 'src', scriptSrc) )
            {
                scriptsToLoad --;
            }
            else
            {
                $.ajax({ 
                    url:        scriptSrc,
                    type:       "GET",
                    data:       null,
                    dataType:   "script",
                    success:    function(){ scriptsToLoad--; },
                    error:      function(){ scriptsToLoad--; },
                    cache:      true
                });
            }
        });
        
        // wait until all the external scripts are downloaded
        WebPartManager.until({ 
            test:       function() { return scriptsToLoad === 0; }, 
            delay:      100,
            callback:   function()
                        {
                            // render the body
                            var html = (config.beforeBodyTemplate||"") + result.body + (config.afterBodyTemplate||"");
                            container.html(html);
                            
                            window.setTimeout( function()
                            {
                                // execute all inline scripts 
                                $(result.inlineScripts).each(function(index, script)
                                { 
                                    $.globalEval(script);
                                });                            
                                
                                if( typeof callback == "function" ) callback();
                            }, 0 );
                        }
        });
    },
    
    isTagLoaded : function(tagName, attName, value)
    {
        // Create a temporary tag to see what value browser eventually 
        // gives to the attribute after doing necessary encoding
        var tag = document.createElement(tagName);
        tag[attName] = value;
        var tagFound = false;
        $(tagName,document).each(function(index,t) 
        { 
            if( tag[attName] === t[attName] ) { tagFound = true; return false } 
        });
        return tagFound;
    },
    
    
    
    until : function(o /* o = { test: function(){...}, delay:100, callback: function(){...} } */)
    {
        if( o.test() === true ) o.callback();
        else window.setTimeout( function() { WebPartManager.until(o); }, o.delay || 100);
    },
    
    delay : function( func, delay )
    {
        window.setTimeout( func, delay || 100 );
    },
    
    resolveUrl : function( baseUrl, relativeUrl )
    {
        // Hack for firefox, as Firefox make any relative URL absolute by just adding the current document's absolute path
        // to the URL
        var currentPageUrl = document.location.protocol + "//" + document.location.host + document.location.pathname;
            
        if( relativeUrl.indexOf(currentPageUrl) == 0) relativeUrl = relativeUrl.substring(currentPageUrl.length);
        
        // if it's an absolute URL, return as it is
        if( relativeUrl.indexOf("http://") >= 0 ) return relativeUrl;
        
        // If URL starts with root, then return it as it is
        if( relativeUrl.indexOf("/") == 0 ) return relativeUrl;
        
        var lastSeparator = baseUrl.lastIndexOf("/");
        if( lastSeparator < 0 ) return relativeUrl;
        else return baseUrl.substring(0, lastSeparator) + "/" + relativeUrl;
    },
    
    parseHtml : function(content,config)
    {
        var result = { body : "", externalScripts : [], inlineScripts : [], links : [], styles : [] };
        
        var bodyContent = [];
        var bodyStarted = false;
        
        var inlineScriptStarted = false;            
        var inlineScriptContent = [];
        
        var inlineStyleStarted = false;            
        var inlineStyleContent = [];            
        
        switch(config.type)
        {
            case "JS" :
                result.inlineScripts.push(content);
            break;
            case "HTML" :
            
                    HTMLParser(content, {
                                      start: function( tag, attrs, unary ) 
                                      {
                                            if( tag == "body" )
                                            {
                                                bodyStarted = true;
                                            }
                                            else if(tag == "script")
                                            {
                                                var srcFound = false;
                                                $(attrs).each(function(index,attr)
                                                {
                                                    if(attr.name == "src")
                                                    {
                                                        result.externalScripts.push(attr.value);
                                                        srcFound = true;
                                                    }
                                                });
                                                if( !srcFound )
                                                {
                                                    // inline script
                                                    inlineScriptStarted = true;
                                                    inlineScriptContent = [];
                                                }
                                            }
                                            else if(tag == "link")
                                            {
                                                result.links.push(attrs);
                                            }
                                            else if(tag == "style")
                                            {
                                                // inline style node
                                                inlineStyleStarted = true;
                                                inlineStyleContent = [];
                                            }
                                            else
                                            {
                                                if( bodyStarted )
                                                {
                                                    var attributes = [];
                                                    for ( var i = 0; i < attrs.length; i++ ) 
                                                        attributes.push(attrs[i].name + '="' + attrs[i].value + '"');
                                                        
                                                    bodyContent.push("<" + tag + " " + attributes.join(" ") + (unary ? "/" : "") + ">");
                                                }
                                            }
                                      },
                                      end: function( tag ) 
                                      {
                                        if( tag == "script" )
                                        { 
                                            if( inlineScriptStarted )
                                            {
                                                inlineScriptStarted = false;
                                                result.inlineScripts.push( inlineScriptContent.join("\n") );
                                            }
                                        }
                                        else if( tag == "style" )
                                        {
                                            inlineStyleStarted = false;
                                            result.styles.push( inlineStyleContent.join("\n") );
                                        }
                                        else
                                        {
                                            if( bodyStarted )
                                                bodyContent.push("</" + tag + ">");
                                        }
                                      },
                                      chars: function( text ) 
                                      {
                                        if( inlineScriptStarted ) 
                                            inlineScriptContent.push(text);
                                        else if( inlineStyleStarted ) 
                                            inlineStyleContent.push(text);
                                        else if( bodyStarted ) 
                                            bodyContent.push(text);
                                      },
                                      comment: function( text ) 
                                      {
                                      }
                                    });

            
             break;
            
        }
        
        
        
        
        result.body = bodyContent.join("\n");
        return result;
    },
    initContainers : function()
    {   
        
        $('div[@src]',document).each(function()
        {
            var container = $(this);
            var id = container.attr("id");
            if( null == WebPartManager._WebParts[id] )
            {
                WebPartManager.init({
                    id: id,
    		
	                loadFrom: container.attr("src"),
	                initialLoad : "GET",
    	            type : container.attr("type") , 
	                progressTemplate : container.attr("progressTemplate") || null,
    	            
                    showProgress : container.attr("showProgress") || false,
    		
	                beforeLoad: function(url,data) { return eval(container.attr("beforeLoad") || "true") },
	                afterLoad: function(data, response) { return eval(container.attr("afterLoad") || "true") },
	                beforePost: function(url,data) { return eval(container.attr("beforePost") || "true") },
	                afterPost: function(data, response) { return eval(container.attr("afterPost") || "true") },
            		
	                params : null,
            		
	                beforeBodyTemplate : container.attr("beforeBodyTemplate") || null,		
	                afterBodyTemplate : container.attr("afterBodyTemplate") || null
                });
            }
        });
    },
    initWebPart : function(webPartId)
    {   
        $(document.getElementById(webPartId),document).each(function()
        {
            
            var container = $(this);
            var id = container.attr("id");
//            if( null == WebPartManager._WebParts[id] )
//            {
                WebPartManager.init({
                    id: id,
    		
	                loadFrom: container.attr("src"),
	                initialLoad : "GET",
    	            type : container.attr("type") , 
	                progressTemplate : container.attr("progressTemplate") || null,
    	            
                    showProgress : container.attr("showProgress") || false,
    		
	                beforeLoad: function(url,data) { return eval(container.attr("beforeLoad") || "true") },
	                afterLoad: function(data, response) { return eval(container.attr("afterLoad") || "true") },
	                beforePost: function(url,data) { return eval(container.attr("beforePost") || "true") },
	                afterPost: function(data, response) { return eval(container.attr("afterPost") || "true") },
            		
	                params : null,
            		
	                beforeBodyTemplate : container.attr("beforeBodyTemplate") || null,		
	                afterBodyTemplate : container.attr("afterBodyTemplate") || null
                });
            //}
        });
    }
    
};

$(function()
{
   WebPartManager.initContainers();
});

})();




