﻿/*************************
* glocalnet.js (c) Glocalnet 2009
*
* @dependencies: Prototype 1.6.1, Scriptaculous 1.8.3, Prototypextensions 0.1.2, SWFObject 2.2
*/
var glocalnet = {
    /*****************************************************
    * Properties
    *
    */  
    options : {
        dir             : '/js/glocalnet',                              // path to glocalnet.js
        headline_url    : location.protocol + '//www.glocalnet.se/title', // title generator context root
        orderflow_id    : 'orderflow',                                  // orderflow element id
        content_id      : 'content',                                    // content element id
        content_inner_id: 'content-inner',                              // inner content element id
        tabs_id         : 'tabs',                                       // tabs element id
        banner_id       : 'banner',                                     // banner element id
        main_id         : 'main',                                       // main content container element id
        site_id         : 'site',                                       // site container
        ticker_id       : 'ticker',                                     // Ticker on start page
        print_id        : 'print',                                      // printable view element id  
        footer_id		: 'footer',								        // footer element id				
        // Do not change below this line
        dom_loaded      : false,
        window_loaded   : false,
        orderflow_inited: false,
        tabs_disabled   : false,
        debug           : false,
        styleSheets     : document.styleSheets,
        orderflow_top   : 0,
        footer_top      : 0,
        tabs_top        : 0,
        content_top     : 0,
        mouseX			: null,
        mouseY			: null
        
    },
    /*****************************************************
    * Public - Initialize application
    *
    * @param
    * @returns 
    */  
    initialize : function() {
        document.observe("dom:loaded", this.__domLoaded.bind(this));
        Element.observe(window, "load", this.__windowLoaded.bind(this));
        Event.observe(document, 'mousemove', this.__mousemove.bind(this));
        

    },
    /*****************************************************
    * Private - Run DOM parsing
    *
    * @params
    * @returns 
    */  
    __domLoaded : function() {
        this.options.dom_loaded = true;
        this.options.orderflow_top = parseInt(this.__getRuleProp(this.options.orderflow_id, 'marginTop'));
        this.options.tabs_top = parseInt(this.__getRuleProp(this.options.tabs_id, 'marginTop'));
        if($(this.options.content_id))
            this.options.content_top = $(this.options.content_id).positionedOffset().top;
        if($(this.options.footer_id))
            this.options.footer_top = $(this.options.footer_id).positionedOffset().top;

        if(!$(this.options.print_id)) {
        	
        } 
        glocalnet.headlines();

    },
    /*****************************************************
    * Private -
    *
    * @param	Object (Event)
    * @returns 
    */  
    __windowLoaded : function(e) {
        this.options.window_loaded = true;
        
        glocalnet.boxes();
        glocalnet.accordion();
        glocalnet.tabs();
    },    
    /*****************************************************
     * Private - 
     *
     * @params	Object (Event)
     * @returns 
     */  
    __mousemove : function(e) {
    	this.options.mouseX = Event.pointerX(e); 
    	this.options.mouseY = Event.pointerY(e)
    },
    /*****************************************************
    * Public - Get user client
    *
    * @param
    * @returns String
    */    
    browser : function() {
        var ua = navigator.userAgent.toLowerCase();
        var client = {
            isStrict:   document.compatMode == 'CSS1Compat',
            isOpera:    ua.indexOf('opera') > -1,
            isIE6:      ua.indexOf('msie 6') > -1,
            isIE7:      ua.indexOf('msie 7') > -1,
            isIE8:      ua.indexOf('msie 8') > -1,
            isSafari:   /webkit|khtml/.test(ua),
            isWindows:  ua.indexOf('windows') != -1 || ua.indexOf('win32') != -1,
            isMac:      ua.indexOf('macintosh') != -1 || ua.indexOf('mac os x') != -1,
            isLinux:    ua.indexOf('linux') != -1,
            isIphone:   ua.indexOf('iphone') != -1,
            isMobile:   ua.indexOf('iphone') != -1 || ua.indexOf('sony') != -1 || ua.indexOf('utc') != -1 || ua.indexOf('nokia') != -1
        };
        return client;
    },
    /*****************************************************
     * Public - Apply rounded cornered box to elements within parent
     *
     * @param  	{Object|String|Undefined} parent
     * @returns 
     */    
     headlines : function(parent) {
         if(this.options.dom_loaded) {
             this.__headlines(parent);
         } else {
             document.observe("dom:loaded", glocalnet.__headlines.bind(glocalnet, parent));
         }
     },
    /*****************************************************
    * Private - Replace element text with image text
    *
    * @param    {Object|String|Undefined} parent
    * @returns 
    */    
    __headlines : function(parent) {
        parent = $(parent) || $(document.body);
        parent.select('h1, h2, h3, h4, h5, h6, [rel="headline"]').each(function(element) {
            try {
                // don't parse twice
                if(element.readAttribute('rel') == "skip") return;
                element.writeAttribute('rel', 'skip');
                //if(glocalnet.browser().isIE6) return;
                if(element.hasClassName('plain')) return;

                // get title string and return if empty
                var title = element.innerHTML.toString().unescapeHTML().strip();
                if(title.length == 0) return;
                
                // parameters for font rendering
                var params = element.readAttribute('params') || '';
                params = params.toQueryParams();
                params.t = params.t || title; // title string
                params.s = params.s || '12'; // size in points
                params.w = params.w || 'm'; // font weight 
                params.c = params.c || '000'; // font color
                params.a = params.a || 'fff'; // font alpha color
             
                // look for selector ending with "-headline" or last class selector in loaded stylesheets
                var cls = element.className.length == 0 ? element.tagName.toLowerCase() +'-headline' : $w(element.className).last();
                var rule = glocalnet.__getRule(cls);
                // apply any styles found to this title image
                if(rule && rule.style) {
                    if(rule.style.backgroundColor) {
                        var bgcolor = rule.style.backgroundColor;
                        if(bgcolor.indexOf('#') == -1) bgcolor = glocalnet.__rgbToHex(bgcolor);
                        else bgcolor = bgcolor.substring(1);
                        params.a = bgcolor;
                        element.setStyle({backgroundColor: 'transparent'});
                    }
                    if(rule.style.color) {
                        var color = rule.style.color;
                        if(color.indexOf('#') == -1) color = glocalnet.__rgbToHex(color);
                        else color = color.substring(1);
                        params.c = color; 
                    }
                    if(rule.style.fontWeight) {
                        switch(rule.style.fontWeight ) {
                            case "bolder": params.w = "b";
                                break;
                            case "bold": params.w = "b";
                                break;
                            case "normal": params.w = "m";
                                break;
                            case "lighter": params.w = "l";
                                break;
                            case "500": params.w = "r_a";
                            	break;
                            case "600": params.w = "b_a";
                            	break;
                            default: params.w = "m";
                                break;
                        }
  
                    }
                    if(rule.style.fontSize){
                        params.s = parseInt(rule.style.fontSize);
                    }
                }
                // create a browser friendly filename
                var filename = title.toLowerCase().replace(/ö/g, "o").replace(/[åä]/g, "a").replace(/[^A-Za-z0-9_-]/g, "");
                var extension = ".gif";
                var src = glocalnet.options.headline_url + "/" + filename + extension + "?" + Object.toQueryString(params);
                // render the image element
                element.innerHTML = '<img src="'+src+'" border="0" alt="'+title+'" />';
                
            } catch(e) { 
                if(glocalnet.options.debug) alert(e.message);
            }
        });
    },
    /*****************************************************
    * Private - Get css rule from selector
    *
    * @param 	String (Selector)
    * @returns 	String
    */  
    __getRule : function(selector) {
        var styleSheets = this.options.styleSheets;
        try {
            for(var i=0; i<styleSheets.length; i++) {
                var css = styleSheets[i];
                var rules = css.cssRules ? css.cssRules : css.rules;
                for(var j=0; j<rules.length; j++) {    
                    if(rules[j].selectorText != null && rules[j].selectorText.toLowerCase().endsWith(selector))
                        return rules[j];
                }
            }
        } catch(e) {
            if(this.options.debug) alert(e.message);
        } 
        return null;
    },
    /*****************************************************
    * Private - Get css rule property from selector
    *
    * @param   	{String} selector
    * @param   	{String} prop
    * @returns 	String
    */  
    __getRuleProp : function(selector, prop) {
        var rule = this.__getRule(selector);
        if(!rule) return null;
        return rule.style[prop] || null;
    },    
    /*****************************************************
    * Private - Convert RGB rgb(xxx,xxx,xxx) to HEXA #xxxxxx
    *
    * @param   	{String} str
    * @returns  {String}
    */  
    __rgbToHex : function(str) {
       str = str.replace(/rgb\(|\)/g, "").split(",");
       if(str.length != 3) str = ["24","23","23"];
       str[0] = parseInt(str[0], 10).toString(16).toLowerCase();
       str[1] = parseInt(str[1], 10).toString(16).toLowerCase();
       str[2] = parseInt(str[2], 10).toString(16).toLowerCase();
       str[0] = (str[0].length == 1) ? '0' + str[0] : str[0];
       str[1] = (str[1].length == 1) ? '0' + str[1] : str[1];
       str[2] = (str[2].length == 1) ? '0' + str[2] : str[2];
       
       return (str.join(""));
    },
    /*****************************************************
    * Public - Apply rounded cornered box to elements within parent
    *
    * @param   	{Object|String|Undefined} parent_id
    * @returns 
    */    
    boxes : function(parent_id) {
        if(this.options.dom_loaded) {
            this.__boxes(parent_id);
        } else {
            document.observe("dom:loaded", glocalnet.__boxes.bind(glocalnet, parent_id));
        }
    },
    /*****************************************************
    * Private - Apply rounded cornered box to elements within parent
    *
    * @param   	{Object|String|Undefined} parent_id
    * @returns 
    */    
    __boxes : function(parent_id) {
        var parent = $(parent_id) || $(this.options.site_id);
        if (parent != null) {
            parent.select('.box').each(function(el) {
                glocalnet.__box(el, el.readAttribute('rel'));
            });
        }
    },    
    /*****************************************************
    * Public - Apply rounded cornered box to element
    *
    * @param  	{Object|String} id
    * @param  	{String|Undefined} cls
    * @returns 
    */    
    box : function(id, cls) {
        if(this.options.dom_loaded) {
            this.__box(id, cls);
        } else {
            document.observe("dom:loaded", glocalnet.__box.bind(glocalnet, id, cls));
        }
    },
    /*****************************************************
    * Private - Apply rounded cornered box to element
    *
    * @param   	{Object|String} id
    * @param  	{String|Undefined} cls
    * @returns       
    */    
    __box : function(id, cls) {
        var el = $(id);
        if(!el) return;	
        if(el.hasClassName('boxed')) return;
        try {
            cls = Object.isString(cls) ? cls : "";
			if(cls.indexOf('shadow') > -1) {
					cls = cls.length > 0 ? " " + cls : "";
					var box = new Element('div', {'class' : 'shadow-box' + cls});	
					var markup =
					'<div class="shadow-box">' +
					'	<div class="shadow-outer">' +
					'   	<div class="shadow-top"></div>' + 
					'   	<div class="shadow-inner"></div>' + 
					'	</div>';
					'   <div class="shadow-bot"><div><!-- IE --></div></div>' +
					'</div>';	
				    var outer = new Element('div', {'class' : 'shadow-outer'});
					var top = new Element('div', {'class' : 'shadow-top'});
					var inner = new Element('div', {'class' : 'shadow-inner'});
					var bot = new Element('div', {'class' : 'shadow-bot'}).update('<div><!-- IE --></div>');

					Element.wrap(el, inner);
					Element.wrap(inner, outer);
					Element.insert(outer, {'top' : top});
					Element.wrap(outer, box);
					Element.insert(box, {'bottom' : bot});	
					
					// we live in a world of hacks :-)
					if(cls.indexOf('dropdown') > -1) {
						if(glocalnet.browser().isIE6) {
							box.replace(el);
							box = el;
							el = new Element('div');
							box.addClassName('shadow-box' + cls);
						} 
						box.setStyle({'width':el.getStyle('width')});
						box.setStyle({'display':'none'});
						el.setStyle({'display':'block'});
						
						box.next().observe("mouseover", function(e) {
							box.show();
							var offset = box.viewportOffset();
							var dimensions = box.getDimensions()
							new PeriodicalExecuter(function(pe){
								if(glocalnet.options.mouseX < (offset.left-10) ||
								   glocalnet.options.mouseX > (offset.left+dimensions.width) ||
								   glocalnet.options.mouseY > (offset.top+dimensions.height)) {
									box.hide();
									pe.stop();
								}
							}, .3);
							
						});
					}
			}else {
				cls = Object.isString(cls) && cls.length > 0 ? " rounded-box-" + cls : ""; 
				var box = new Element('div', {'class' : 'rounded-box' + cls});	
				var markup =
					'<div class="rounded-box">' +
					'   <div class="top"><span><!-- IE --></span><div><!-- IE --></div></div>' + 
					'   <div class="mid"></div>' +
                    '   <div class="bot"><span><!-- IE --></span><span class="bl"><!-- IE --></span><span class="br"><!-- IE --></span><div><!-- IE --></div></div>' +
					'</div>';
				var top = new Element('div', {'class' : 'top'}).update('<span><!-- IE --></span><div><!-- IE --></div>');
				var mid = new Element('div', {'class' : 'mid'});
				var bot = new Element('div', {'class' : 'bot'}).update('<span><!-- IE --></span><span class="bl"><!-- IE --></span><span class="br"><!-- IE --></span><div><!-- IE --></div>');
				Element.wrap(el, mid);
				Element.wrap(mid, box);
				Element.insert(box, {'top' : top});
				Element.insert(box, {'bottom' : bot});
			}
            el.addClassName('boxed');
        } catch (e) {
            if(this.options.debug) alert(e.message);
        }
    },
    /*****************************************************
    * Public - CFE - Custom Form Elements
    *
    * @param   {Object|String} parent
    * @param   {Object} params
    * @returns 
    */  
    forms : function(parent, params) {
        params = typeof params == "object" ? params : {};
        params = Object.extend({
            bind_submit: true
        }, params);
        if(!$(parent)) throw ("No form found. Could not parse forms()");
        
        $(parent).select('form').each(function(el) {
            el.select('input[type=submit]').each(function(input) {
                var outer = new Element('div', {'class' : el.className});
                Element.wrap(input, outer);
            }, this);
            if(params.bind_submit) el.observe('submit', this.__onSubmit.bind(this));
            el.select('input[type=text]').each(function(input) {
                var w = Math.max(input.getWidth(), parseInt(input.getStyle('width')));
                var cls = input.hasClassName("error") ? "form-input input-error" : "form-input";
                cls = input.disabled ? "form-input input-disabled" : cls;
                var outer = new Element('div', {'class' : cls, 'style' : 'width:'+(w+4)+'px'});
                outer.appendChild(new Element('div', {'class' : 'l'} ));
                outer.appendChild(new Element('div', {'class' : 'r'} ));
                Element.wrap(input, outer);
                if(input.value == "") input.value = input.title;
                input.observe('focus', this.__onInput.bind(this, input, outer, "focus"));
                input.observe('blur', this.__onInput.bind(this, input, outer, "blur"));
                this.__onInput(input, outer, "blur");
            }, this);
            el.select('input[type=password]').each(function(input) {
                var w = Math.max(input.getWidth(), parseInt(input.getStyle('width')));
                var cls = input.hasClassName("error") ? "form-input input-error" : "form-input";
                cls = input.disabled ? "form-input input-disabled" : cls;
                var outer = new Element('div', {'class' : cls, 'style' : 'width:'+(w+4)+'px'});
                outer.appendChild(new Element('div', {'class' : 'l'} ));
                outer.appendChild(new Element('div', {'class' : 'r'} ));
                Element.wrap(input, outer);
                if(input.value == "") input.value = input.title;
                input.observe('focus', this.__onInput.bind(this, input, outer, "focus"));
                input.observe('blur', this.__onInput.bind(this, input, outer, "blur"));
                this.__onInput(input, outer, "blur");
            }, this);
            el.select('select').each(function(input) {
                input.setOpacity(0);
                var w = Math.max(input.getWidth(), parseInt(input.getStyle('width')));
                var outer = new Element('div', {'class' : 'form-select', 'style' : 'width:'+(w+4)+'px'});
                outer.appendChild(new Element('div', {'class' : 'l'} ));
                outer.appendChild(new Element('div', {'class' : 'r'} ));
                outer.appendChild(new Element('span'));
                Element.wrap(input, outer);
                input.observe('focus', this.__onInput.bind(this, input, outer, "focus"));
                input.observe('blur', this.__onInput.bind(this, input, outer, "blur"));
                input.observe('change', this.__onSelect.bind(this, outer));
                this.__onInput(input, outer, "blur");
                this.__onSelect(outer);
            }, this);
            el.select('input[type=checkbox]').each(function(input) {
                input.setOpacity(0);
                var label = input.up().down('label').remove();
                var outer = new Element('div', {'class' : 'form-checkbox'});
                Element.wrap(input, outer).appendChild(label);
                input.observe('click', this.__onCheckbox.bind(this, outer));
                input.observe('focus', this.__onCheckbox.bind(this, outer));
                input.observe('blur', this.__onCheckbox.bind(this, outer));
                this.__onCheckbox(outer);
            }, this);
            el.select('input[type=radio]').each(function(input) {
                input.setOpacity(0);
                var label = input.up().down('label').remove();
                var outer = new Element('div', {'class' : 'form-radio'});
                Element.wrap(input, outer).appendChild(label);
                input.observe('click', this.__onRadio.bind(this, outer));
                input.observe('focus', this.__onRadio.bind(this, outer));
                input.observe('blur', this.__onRadio.bind(this, outer));
                this.__onRadio(outer);
                label.observe("click", function(e) {
                    Event.stop(e);
                    input.click();
                });
            }, this);
        }, this);
    },
    /*****************************************************
    * Public - Toggles form groups visible and disabled states on input fields
    *
    * @param    {Object} input (Prototype Element)  
    * @param    {Object} outer (Prototype Element)   
    * @param    {String} state      
    * @param    {Object} e (Prototype Event)  
    * @returns 
    */  
    toggleGroup : function(source, target, state) {
        source = $(source);
        if(!source) throw "No source element found.";
        target = $(target) || new Element('div');
        // IE6 has problem to render CFE elements if they are hidden
        // Submit the form each time we call a toggle function
		if(glocalnet.browser().isIE6) {
			var form = source.up('form');
			var obj = form.down('button[type="submit"]');
			if(form.slideEvents) form.slideEvents.value = "";
			if(form.loadEvents) form.loadEvents.value = "";
			obj.click();
			return;
		}
        if(Object.isUndefined(state)) {
            source.toggle();
        } else if(state == true) {
            source.show();
        } else {
            source.hide();
        }
        if(source.getStyle('display') == 'block') {
            target.select('.form-input').each(function(el) {
                el.addClassName('input-disabled'); 
                el.down('input').disabled = true;
            });
            source.select('.form-input').each(function(el) {
                el.removeClassName('input-disabled'); 
                el.down('input').disabled = false;
            });
        }
        else {
            target.select('.form-input').each(function(el) {
                el.removeClassName('input-disabled'); 
                el.down('input').disabled = false;
            });
            source.select('.form-input').each(function(el) {
                el.addClassName('input-disabled'); 
                el.down('input').disabled = true;
            });
        } 
        
    },
    /*****************************************************
    * Private - Orderflow input event handler
    *
    * @param    {Object} input (Prototype Element)  
    * @param    {Object} outer (Prototype Element)   
    * @param    {String} state      
    * @param    {Object} e (Prototype Event)  
    * @returns 
    */  
    __onInput : function(input, outer, state, e) {
        if(state == "focus" && input.value == input.title) {
        	input.value = "";
        } else if(state == "blur" && input.value == "") {
        	input.value = input.title;
        }
    },
    /*****************************************************
    * Private - Orderflow select event handler
    *
    * @param    {Object} outer (Prototype Element)    
    * @param    {Object} e (Prototype Event)  
    * @returns 
    */  
    __onSelect : function(outer, e) {
        outer.down('select').select('option').each(function(option, index) {
            if(index == 0 || option.selected) {
                outer.down('span').innerHTML = option.value;
            }
        }, this);
    },
    /*****************************************************
    * Private - Orderflow checkbox event handler
    *
    * @param    {Object} outer (Prototype Element)    
    * @param    {Object} e (Prototype Event)    
    * @returns 
         */  
    __onCheckbox : function(outer, e) {
        if(outer.down('input').checked) {
            outer.down('label').addClassName('checked');
        } else {
            outer.down('label').removeClassName('checked');
        }
    },
    /*****************************************************
    * Private - Orderflow radiobutton event handler
    *
    * @param    {Object} e (Prototype Event)
    * @returns 
    */   
    __onRadio : function(outer, e) {
        $$('input[name='+outer.down('input').name+']').each(function(el) {
            var label = el.up().down('label');
            if(!el.checked) label.removeClassName('checked');
        });
        if(outer.down('input').checked) {
            outer.down('label').addClassName('checked');
        } 
    },   
    /*****************************************************
    * Private - submit orderflow event
    *
    * @param    {Object} e (Prototype Event)
    * @returns 
    */   
    __onSubmit : function(e) { 
        Event.stop(e);
        var form = Event.element(e);
        form.select('input[type=text]').each(function(input) {
            if(input.value == input.title) 
                input.value = "";
        });
        var do_slide = false;
        var do_load = false;
        var skip_forms_gui = false;
        var eventId = form._eventId ? form._eventId.value : '';
        
        if (form.slideEvents) {
        	var eventIdShouldSlide = form.slideEvents.value.indexOf(eventId)>-1;
        	do_slide = form && eventIdShouldSlide;
        }
        if (form.loadEvents) {
        	var eventIdShouldLoad = form.loadEvents.value.indexOf(eventId)>-1;
        	do_load = form && eventIdShouldLoad;
        	do_slide = do_slide || do_load;
        }
        if (form.skip_forms_gui) {
        	skip_forms_gui = form.skip_forms_gui.value != "false";
        }
        
        var target_el;
        var parent = form.up(1);
        if (parent && Object.isString(parent.id) && parent.id.length > 0) {
        	target_el = parent.id;
        }
        var params = {
            parameters : Form.serialize(form),
            method : form.method || 'get',
            form: form,
            slider : do_slide,
            loader : do_load,
            target_el : target_el || this.options.orderflow_id,
            skip_forms_gui : skip_forms_gui
        }
        form.disable();
        this.__loadOrderflow(form.action, params);   
    },
    /*****************************************************
    * Private - load content into orderflow
    *
    * @param 
    * @returns 
    */ 
    __initOrderflow : function() {
        if($(this.options.orderflow_id) && !this.options.orderflow_inited){
            if(!this.browser().isIE6 && !this.browser().isMobile) {
                Event.observe(window, "scroll", this.__onScrollWindow.bind(this));
                new PeriodicalExecuter(this.__onScrollWindow.bind(this), 2);
            }
            this.options.orderflow_inited = true;
            $(this.options.orderflow_id).show();
        }
    },
    /*****************************************************
    * Public - Load content into orderflow
    *
    * @param    {String} url 
    * @param    {Object} params
    * @returns 
    */  
    loadOrderflow : function(url, params) {   
        if(this.options.dom_loaded) {
            this.__loadOrderflow(url, params);
        } else {
            Element.observe(window, "load", glocalnet.__loadOrderflow.bind(glocalnet, url, params));
        }
    }, 
    /*****************************************************
    * Private - Take care of form submissions for Ajax requests in orderflow
    *
    * @param    {String} url 
    * @param    {Object} params
    * @param    {Object} e (Event)    
    * @returns 
    */  
    __loadOrderflow : function(url, params, e) {
        if(glocalnet.orderflow_sliding) return;
        params = typeof params == "object" ? params : {};
        params = Object.extend({
            method: 'get',
            evalScripts : true,
            parameters : '',
            slider:false,
            loader:false,
            target_el : this.options.orderflow_id
        }, params);
        this.__initOrderflow();
        var target_el = $(params.target_el);
        if(!target_el) throw "No orderflow found.";
        var form = params.form;
        var orderflow_body = target_el.down('.orderflow-body');
        var do_slide = params.slider;
        var do_load = true; //params.loader;
        
    
        var ajax_params = { 
            method: params.method, 
            parameters: params.parameters,
            evalScripts: params.evalScripts,
            onProgress : function() {
            },
            onCreate : function() {
               
            },
            onFailure: function() { 
                if(glocalnet.options.debug) alert("Could not load: " + url + "?" + params.parameters); 
                if(!orderflow_body) return;
                var effect_params = {
                    duration: duration,
                    transition: Effect.Transitions.Quad.easeInOut,
                    afterFinish : function() {
                        glocalnet.orderflow_sliding = false;
                        if(params.form) params.form.enable();
                        target_el.select('.form-error').each(function(el) {
                            el.setStyle({'visibility':'visible'});
                        });
                    }
                };
                var loader = target_el.down('.loader');
                if(loader) {
                    loader.update("Ett fel har uppstått. Försök igen.");
                     new Effect.Fade(loader, {
                        duration: .2,
                        delay: 1,
                        afterFinish: function() {
                            if(do_slide) new Effect.SlideDown(orderflow_body, effect_params);
                            else orderflow_body.show();
                        }
                   });
                } else {
                    if(do_slide) new Effect.SlideDown(orderflow_body, effect_params);
                    else orderflow_body.show();
                }
            },
            onSuccess : function(t) {
                var result_el = new Element('div', {'class': 'orderflow-inner'}).update(t.responseText);
                if($('kundservice')) {
                	Element.insert(result_el, {bottom: '<div class="kundservice">'+$('kundservice').innerHTML+'</div>'});
                }
                
                glocalnet.headlines(result_el);
                glocalnet.forms(result_el);
                glocalnet.__add_offers(result_el);
                glocalnet.boxes(result_el);
                //glocalnet.accordion(result_el);
                var result_body = result_el.down('.orderflow-body');
                var result_body_height = result_body ? result_body.getHeight() : 0;
                var effect_params = {
                    duration: Math.max(.4, Math.round((result_body_height / 800) * 100) / 100),
                    transition: Effect.Transitions.Quad.easeInOut,
                    afterFinish : function() {
                        glocalnet.orderflow_sliding = false;
                        
                        target_el.select('.form-error').each(function(el) {
                            el.setStyle({'visibility':'visible'});
                        });
                    },
                    afterUpdate  : function() {
                    	glocalnet.__onScrollWindow();
                    }
                };
                var loader = target_el.down('.loader');
                if(loader) {
                    new Effect.Fade(loader, {
                        duration: .2,
                        delay: .2,
                        afterFinish: function() {
                            target_el.update(result_el);
                            if(result_body && do_slide && do_slide && !glocalnet.browser().isMobile && !glocalnet.browser().isIE6) {
                                result_body.hide();
                                var height = result_body.getHeight();
                                effect_params.duration = Math.max(.4, Math.round((height / 800) * 100) / 100);
                                new Effect.SlideDown(result_body, effect_params);
                            } else {
                                glocalnet.orderflow_sliding = false;
                                target_el.select('.form-error').each(function(el) {
                                    el.setStyle({'visibility':'visible'});
                                });
                            }
                        }
                   });
                } else if(result_body && do_slide && !glocalnet.browser().isMobile && !glocalnet.browser().isIE6) {
                    result_body.hide();
                    var height = result_body.getHeight();
                    effect_params.duration = Math.max(.4, Math.round((height / 800) * 100) / 100);
                    new Effect.SlideDown(result_body, effect_params);
                } else {
                    target_el.update(result_el);
                    glocalnet.orderflow_sliding = false;
                    target_el.select('.form-error').each(function(el) {
                        el.setStyle({'visibility':'visible'});
                    });
                }
            }
        };
        
        if(do_slide && orderflow_body) {
            glocalnet.orderflow_sliding = true;
            var height = orderflow_body.getHeight();
            var duration = Math.max(.4, Math.round((height / 800) * 100) / 100);
            new Effect.SlideUp(orderflow_body, {
                afterFinish: function() {
                    new Ajax.Request(url, ajax_params);
                }, 
                beforeStart : function() {
                    if(do_load) glocalnet.__addLoader(target_el, "Läser in...");
                    target_el.select('.form-error').each(function(el) {
                        el.setStyle({'visibility':'hidden'});
                    });
                },
                duration: duration,
                transition: Effect.Transitions.Quad.easeInOut
            });
        } else {     
            glocalnet.orderflow_sliding = false;
            if(!orderflow_body && do_load) glocalnet.__addLoader(target_el, "");
            new Ajax.Request(url, ajax_params);
        }

    }, 
    /*****************************************************
    * Public - Content page Ajax wrapper with history
    *
    * @param    {String} url 
    * @param    {Object} params
    * @returns 
    */  
    loadPage : function(url, params) {   
        if(this.options.dom_loaded) {
            this.__loadPage(url, params);
        } else {
            document.observe("dom:loaded", glocalnet.__loadPage.bind(glocalnet, url, params));
        }
    },           
    /*****************************************************
    * Private - Content page Ajax wrapper with history
    *
    * @param    {String} url 
    * @param    {Object} params
    * @returns 
    */  
    __loadPage : function(url, params) {
        params = typeof params == "object" ? params : {};
        params = Object.extend({
            method: 'get',
            evalScripts : true,
            parameters : '',
            slider:true,
            target_el : this.options.content_id
        }, params);

        var target_el = $(params.target_el);
        if(!target_el) throw "No content found.";
        
        var pathInfo = this.__parseUrl(url);
        var do_slide = params.slider;
        
        var ajax_params = { 
            method: params.method, 
            parameters: params.parameters,
            evalScripts: params.evalScripts,
            history : {
	           id : 'page',
	           state : pathInfo.filename,
	           cache : true,
	           onStateChange : function (state){
	               History.setTitle(History.getTitle() + " - " + state.ucfirst());
	           }
            },
            onCreate : function() {
            },
            onSuccess : function(t) {
                var result_el = new Element('div', {'class': 'content-body'}).update(t.responseText);
                glocalnet.headlines(result_el);
                glocalnet.forms(result_el);
                glocalnet.boxes(result_el);
				glocalnet.accordion(result_el);
                var content_body = target_el.down('.content-body');
                
                if(do_slide && content_body)
                    new Effect.SlideUp(target_el, {
                        afterFinish : function() {
                            target_el.hide(); 
                            target_el.update(result_el);
                            new Effect.SlideDown(target_el, {
                                duration: .5
                            });
                        },
                        duration: .3
                    });
	            else {
                    target_el.hide(); 
                    target_el.update(result_el);
                    new Effect.SlideDown(target_el, {
                        duration: .5
                    });
	            }
	       },
	       onComplete : function() {
	       },
	       onFailure : function(t) {
	           if(glocalnet.options.debug) alert('Error ' + t.status + ' -- ' + t.statusText);
	       }
	   };
	   new Ajax.History.Request(url, ajax_params);
	},
    /*****************************************************
    * Public - Simple Ajax Request wrapper 
    *
    * @param    {String} url 
    * @param    {Object} params
    * @returns 
    */  
    loadSimple : function(url, params) {   
        if(this.options.dom_loaded) {
            this.__loadSimple(url, params);
        } else {
            document.observe("dom:loaded", glocalnet.__loadSimple.bind(glocalnet, url, params));
        }
    }, 
    /*****************************************************
    * Private - Simple Ajax Request wrapper 
    *
    * @param    {String} url 
    * @param    {Object} params
    * @returns 
    */  
    __loadSimple : function(url, params) {
        params = typeof params == "object" ? params : {};
        params = Object.extend({
            method: 'get',
            evalScripts : true,
            parameters : '',
            target_el : this.options.content_id, // Element id of target
            wrapper_cls: 'content-page',
            slider : false
        }, params);
        
        target_el = $(params.target_el);
        if(!target_el) throw "No target element found.";
        var do_slide = params.slider;
       
        var ajax_params = { 
            method: params.method, 
            parameters: params.parameters,
            evalScripts: params.evalScripts,
            onSuccess : function(t) {
                var result_el = new Element('div', {'class': params.wrapper_cls}).update(t.responseText);
                glocalnet.headlines(result_el);
                glocalnet.forms(result_el);
                glocalnet.boxes(result_el);
                glocalnet.accordion(result_el);
                target_el.update(result_el);
                if(do_slide) {
                    new Effect.SlideDown(target_el, {
                        duration: .5
                    });
	            } else {
					// Adjust content height to newly loaded content
                    glocalnet.__tabsAdjust();
	            }
            },
            onFailure : function(t) {
                if(glocalnet.options.debug) alert('Error ' + t.status + ' -- ' + t.statusText);
            }
        }
        new Ajax.Request(url, ajax_params);
    },
    /*****************************************************
    * Private - Add AJAX loader
    *
    * @param    {Object} el (Prototype extended element)
    * @returns  {Object}
    */  
    __addLoader : function(el, str) {
        str = Object.isString(str) ? str : "Sökning pågår..."
        el = $(el);
        if(!el) return;
        var loader = el.down('.loader') || new Element('div', {style : 'display:none;', 'class' : 'loader'});
        loader.update(str);
        Element.insert(el, {bottom: loader});
        loader.appear({duration:.2,delay:.1});
        return loader;
    },      
    /*****************************************************
    * Public - Initialize tabs
    *
    * @param
    * @returns 
    * @html 
        <div id="tabs">
            <ul>
                <li><a href="#erbjudanden">Erbjudanden</a></li>
                <li><a href="#priser_villkor">Priser &amp; villkor</a></li>
                etc...
            </ul>
        </div>
        <div id="content">
            <div id="content-inner">
                <div class="content-page"><%@include file="erbjudanden.jsp"%></div>
                <div class="content-page"><%@include file="priser_villkor.jsp"%></div>
                etc...
            </div>
        </div>
    */  
    tabs : function () {
       if(this.options.dom_loaded) {
            this.__tabs();
        } else {
            document.observe("dom:loaded", glocalnet.__tabs.bind());
        }
    },
    /*****************************************************
    * Private - Initialize tabs after DOM is loaded
    *
    * @param
    * @returns 
    */  
    __tabs : function() {
        if(!$(this.options.content_id) || !$(this.options.tabs_id)) {
            return;
        }
        if(this.__tabsItems().length == 0) {
            return;
        }
        if(this.__tabsItems()[0].readAttribute('index') != null) {
            return;
        }
        
        var width = $(this.options.content_id).getWidth() - parseInt($(this.options.tabs_id).getStyle('margin-left'));
        var max_width = Math.min(width, 700);
        var tab_width = Math.min(140,Math.floor(parseInt(max_width) / this.__tabsItems().length));
        this.__tabsItems().each(function(el, index) {
        	var content = $(this.options.content_id).select('.content-page')[index];
            el.setStyle({'width' : tab_width + 'px'});
            var text = el.innerHTML;
            el.innerHTML = "";
            el.appendChild(new Element('div', {'class' : 'tab-l'}));
            el.appendChild(new Element('div', {'class' : 'tab-m', 'style' : 'width:'+(tab_width-14)+'px'}));
            el.appendChild(new Element('div', {'class' : 'tab-r'}));
            el.appendChild(new Element('span').update(text));
            el.observe("click", this.__tabsClick.bind(this, el));
            el.writeAttribute('index', index);
            el.writeAttribute('h', content.getHeight());
            var href = el.readAttribute('href');
            el.writeAttribute('page', href.substring(href.indexOf('#')+1));
        }, this);    
        
        //var selected = glocalnet.__tabsSelected();
        //$(this.options.content_inner_id).setStyle({'left': '-'+(parseInt(selected.readAttribute('index')) * width)+'px'});
        $(this.options.tabs_id).hide();
        $(this.options.tabs_id).setStyle({'visibility':'visible'});
        $(this.options.tabs_id).appear({'duration':.1,'delay':.5});
        this.__tabsDefault();
    },
    /*****************************************************
    * Private - On click tab event
    *
    * @param    {Object} el (Prototype extended element)
    * @param    {Object} e (Event)          
    * @returns 
    */  
    __tabsClick : function(el, e) {
        Event.stop(e);
        this.__tabsSelect(el);
    },  
    /*****************************************************
    * Private - Get tab items
    *
    * @param
    * @returns {Array} (Prototype array)
    */      
    __tabsItems : function() {
        if(!this.tab_items) {
            this.tab_items = $$('#'+this.options.tabs_id+' ul li a');
        }
        return this.tab_items;
    },
    /*****************************************************
    * Private - Set default tab and select it
    *
    * @param
    * @returns 
    */  
    __tabsDefault : function() {
        History.Observer.start();
        History.Registry.set({
            id: 'page',
            onStateChange: function(page) {
                glocalnet.__tabsSelect();
            }
        });
        
        this.__tabsSelect();
    },
    /*****************************************************
    * Private - Select tab based on url hash value
    *
    * @param
    * @returns (Object) Selected tab element
    */  
    __tabsSelected : function() {
        var hash = document.location.hash;
        var page = hash.length > 0 ? hash.split("=")[1] : "";
        var selected = 0;
        this.__tabsItems().each(function(el, index) {
            if(el.readAttribute('page') == page) {
                selected = index;
            }
        },this);
        
        return this.__tabsItems()[selected];
    },
    /*****************************************************
    * Private
    *
    * @param    {Object} el (Prototype Element Object)
    * @returns 
    */  
    __tabsSelect : function(el) {
    	if(glocalnet.options.tabs_disabled) return;
        if(Object.isNumber(el)) {
            el = this.__tabsItems()[el];
        } else {
            el = $(el) || glocalnet.__tabsSelected();
        }
        
        var contents = $(this.options.content_id).select('.content-page')
        this.__tabsItems().each(function(element, index) {
            element.removeClassName('active');
            
            if(element == el) {
                var href = el.readAttribute('href');
                var page = href.substring(href.indexOf("#")+1);
                var title = el.down('span').innerHTML;
                History.set('page', page);
                History.setTitle(title.unescapeHTML().ucfirst() + " - " + History.getTitle());
                element.addClassName('active');
            }else {
            	contents[index].hide();
            }
        }, this);
        this.__tabsDisplay(el);
    },
    /*****************************************************
     * Private - Initialize tabs after DOM is loaded
     *
     * @param	(Object|String) parent
     * @returns 
     */  
    add_offers : function (parent) {
        if(this.options.dom_loaded) {
             this.__add_offers(parent);
         } else {
             document.observe("dom:loaded", this.__add_offers.bind(this, parent));
         }
     },
     /*****************************************************
     * Private - Initialize tabs after DOM is loaded
     *
     * @param	(Object) parent
     * @returns 
     */  
     __add_offers : function(parent) {
    	 var parent = $(parent) || $(document.body);
    	 
    	 var els = parent.select('.orderflow-add-offer');
    	 els.each(function(el) {
        	el.observe('click', this.__add_offersClick.bind(this, el, els));
    	 }, this);
    	 this.__add_offersSelect(null, els);
     },
     /*****************************************************
      * Private
      *
      * @param	(Object) target
      * @param	(Array) els
      * @param	(Object) e
      * @returns 
      */  
     __add_offersClick : function(target, els, e) {
    	 this.__add_offersSelect(target, els);
    	 
     },
     /*****************************************************
      * Private 
      *
      * @param    {Object} 		element
      * @returns
      */ 
      __add_offersSelect : function (target, els) {
      	var selectedTab = this.__tabsSelected();
      	
      	var selectedPage = selectedTab ? selectedTab.readAttribute('page') : "";
      	var page = target ? target.readAttribute("rel") : selectedPage;
      	if(!target) {
      		return;
      	}
      	
      	var pageAlreadyPresent = 'Välj {0} med hjälp av en <strong>Väljknapp</strong> nedan.'; 
	   	if(selectedPage == "") {
	   		var item = "erbjudande";
      		this.loadPopup(null,  {target_el: new Element('a'), title: 'Välj erbjudande', content: pageAlreadyPresent.replace("{0}", item), once: true, width: '400px'});
	   	} else if (page == selectedPage) {
	   		var item = target.innerHTML.split(/\W+/).slice(2).join(" ");
      		this.loadPopup(null,  {target_el: new Element('a'), title: target.innerHTML, content: pageAlreadyPresent.replace("{0}", item), once: true, width: '400px'});
      	} else {
      		this.__tabsItems().each(function(el, index) {
                if(el.readAttribute('page') == page) {
                    this.__tabsSelect(index);
                    return;
                }
            },this);
      	}
      },
    /*****************************************************
    * Private
    *
    * @param    {Object} el (Prototype Element Object)
    * @returns 
    */  
    __tabsDisplay : function(el) {
        if(Object.isNumber(el)) {
            el = this.__tabsItems()[el];
        } else {
            el = $(el) || this.__tabsItems()[0];
        }
        var index = parseInt(el.readAttribute('index'));
        var c = $(this.options.content_id)
        var content = c.select('.content-page')[index];
        
        this.closePopup();
        
        /* BEGIN DISABLE TRANSITIONS */
        var old_height = c.getHeight();
        if(this.old_content) {
        	this.old_content.hide();
        }
        this.old_content = content;
        this.options.tabs_disabled = true;
        
        content.show();
        glocalnet.options.tabs_disabled = false;

        if(History.get("anchor")) {
        	Effect.ScrollTo(History.get("anchor"),  {delay:.2,duration:.5});
        }
        return;
    },
    /*****************************************************
    * Private - Adjust content height (used if content changes at runtime)
    *
    * @param    {Object} content (Prototype Element Object)
    * @returns 
    */  
    __tabsAdjust : function(content) {
        conent = $(content) || $(this.options.content_id);
        var start_val = $(this.options.content_id).getHeight();
        var end_val = content.getHeight();

        new Effect.Tween(glocalnet.options.content_id, start_val, end_val, {
                duration: .2
            },
            function(p) {
                $(glocalnet.options.content_id).setStyle({'height':p+'px'});
            }
        );
    },
    /*****************************************************
    * Public - Create accordion behavior
    *
    * @param
    * @returns 
    */  
    accordion : function (parent) {
       if(this.options.dom_loaded) {
            this.__accordion(parent);
        } else {
            document.observe("dom:loaded", glocalnet.__accordion.bind(glocalnet, parent));
        }
    },
    /*****************************************************
    * Private  - Create accordion behavior
    *
    * @param    {Object} parent (Prototype Element Object)
    * @returns 
    */  
    __accordion : function(parent) {
        parent = $(parent) || $(document.body);
        parent.select('.accordion').each(function(accordion) {
            if(accordion.readAttribute('loaded')) return;
            var accordion_boxes = accordion.select('.shadow-box');
            try {
            
                accordion_boxes.each(function(el, index) {
                    var z = accordion_boxes.length-index;
                    el.setStyle({zIndex: z, position: 'relative', cursor: 'pointer'});
                    el.observe("click", glocalnet.__accordionClick.bind(glocalnet, accordion, index));
                    el.down('.box').appendChild(new Element('div', {'class': 'arrow-closed'}).update('Svar:'));
                    el.writeAttribute('open', 'false');
                    accordion.writeAttribute('active', 'false');
                });
            } catch(e) {
                
                if(this.options.debug) alert("Error in accordion(): " + e.emssage);
            }
            accordion.writeAttribute('loaded', 1);
        });
    },
    /*****************************************************
    * Private  - On click an accordion
    *
    * @param    {Object} accordion (Prototype Element Object)
    * @param    {Integer} index
    * @param    {Object} e (Prototype Event Object)         
    * @returns 
    */  
    __accordionClick : function(accordion, index, e) {
        var accordion_boxes = accordion.select('.shadow-box');
        var selected_box = accordion_boxes[index];
        var selected_height = selected_box.down('.box').getHeight();
        var is_open = selected_box.readAttribute('open');
        var is_active = accordion.readAttribute('active');
        var delay = is_active == 'true'  ? .2 : 0;
        // Close all accordions
        accordion_boxes.each(function(el, i) {
            var inner = el.down('.shadow-inner');
            var height = parseInt(inner.getStyle('height'));
            el.writeAttribute('open', 'false');
            el.down('.arrow-closed').removeClassName('arrow-open');
            new Effect.Tween(inner, height, 0, {
                    duration:delay,
                    afterFinish : function(ef) {
                        accordion.writeAttribute('active', 'false');
                    }
                }, function(p) {
                    inner.setStyle({'height': p+'px'});
                }
            );
        });
        if(is_open == 'true') return;    
        var selected_inner = selected_box.down('.shadow-inner');
        selected_box.writeAttribute('open', 'true');
        selected_box.down('.arrow-closed').addClassName('arrow-open');
        // Open selected accordion
        new Effect.Tween(selected_inner, 0, selected_height, {
                duration: .3,
                delay: delay,
                afterFinish: function(ef) {
                    accordion.writeAttribute('active', 'true');
                }
            }, function(p) {
                selected_inner.setStyle({'height': p+'px'});
            }
        );
    },
    /*****************************************************
    * Public - Load flash banner. Looks for backup image with same path if none provided.
    *
    * @param    {Array|Object} arr (Array of banners or Object of one banner)
    * @param    {Object|Undefined} params
    * @returns 
    */  
    loadBanner : function(arr, params) {
        if(this.options.dom_loaded) {
        	 this.__loadBanner(arr, params);
        } else {
            document.observe("dom:loaded", glocalnet.__loadBanner.bind(glocalnet, arr, params));
        }
    }, 
    /*****************************************************
    * Private - Perform banner initialization after DOM is loaded
    *
    * @param    {Array|Object} arr (Array of banners or Object of one banner)
    * @returns 
    */     
    __loadBanner : function(arr, params) {
        params = Object.isUndefined(params) ? {} : params;
        params = Object.extend({
            target_id: this.options.banner_id,
            width: 925,
            height: 254,
            preload: true,
            wmode: 'opaque',
            scale: 'noscale',
            shuffle: false,
            duration: 1,
            delay: 0,
            prop: 'x',
            id: null
        }, params);

        if(!$(params.target_id)) return;
        if(!Object.isArray(arr)) {
            arr = [arr];
        }
        if(params.shuffle && arr.length > 2) arr.shuffle();  
        var flashvars = {f: "", c: "", t: "", d: "", p: ""};
        var slideshow = new Element('div', {'style': 'height:'+params.height+'px;width:'+params.width+'px;overflow:hidden;'});
        var has_swf = false;
        arr.each(function(obj) {
           if(!obj) return;
           obj.src = obj.src || "";
           obj.href = obj.href || "";
           obj.target = obj.target || "";
           obj.delay = obj.delay || "";
           obj.img = obj.img || obj.src.replace(/\.swf/, '.jpg');
           obj.alt = obj.alt || "";
           has_swf = has_swf ? has_swf : obj.src.indexOf('.swf') > -1;
           
           flashvars.alt = obj.alt;
           flashvars.clickTag = flashvars.clickTAG = obj.href;
           flashvars.f += (flashvars.f.length > 0) ? "," + obj.src : obj.src;
           flashvars.c += (flashvars.c.length > 0) ? "," + obj.href : obj.href;
           flashvars.d += (flashvars.d.length > 0) ? "," + obj.delay : obj.delay;
           flashvars.t += (flashvars.t.length > 0) ? "," + obj.target : obj.target;
           flashvars.p += (flashvars.p.length > 0) ? "," + obj.alt : obj.alt;
           var img = new Element('img', {'src': obj.img, 'width': params.width, 'height': params.height, 'alt': obj.alt});
           if(obj.href.length > 0) {
                var a = new Element('a', {'href': obj.href, 'rel': Object.toQueryString(obj)});
                a.appendChild(img);
                slideshow.appendChild(a);
           } else {
                slideshow.appendChild(img);
           }
           
        });
        var flashparams = {'wmode' : params.wmode, 'scale' : params.scale};
        var attributes = {};
        if(params.id) {
        	attributes.id = params.id;
        	flashvars.sc_movie_id = params.id; // ActionSource specific id
        } else {
        	flashvars.sc_movie_id = arr[0].src;
        }
        $(params.target_id).update(slideshow);
        var src = params.preload ? '/swf/preloader.swf' : arr[0].src;
        if(has_swf){
            swfobject.embedSWF(src, slideshow.identify(), params.width, params.height, '10.0.0', '/swf/expressInstall.swf', flashvars, flashparams, attributes);
        }
        this.slideshow(slideshow, params);
        $(params.target_id).setStyle({'visibility':'visible'});
    },   
    /*****************************************************
    * Public - Load ticker on start page
    *
    * @param    {Array} arr (Array of text messages)
    * @param    {Object} params
    * @returns 
    */  
    loadTicker : function(arr, params) {
        if(this.options.dom_loaded) {
            this.__loadTicker(arr, params);
        } else {
            document.observe("dom:loaded", this.__loadTicker.bind(this, arr, params));
        } 
    },         
    /*****************************************************
    * Private - Perform ticker initialization after DOM is loaded
    *
    * @param    {Array} arr
    * @param    {Object} params
    * @returns 
    */  
    __loadTicker : function(arr, params) {
        params = Object.isUndefined(params) ? {} : params;
        params = Object.extend({
            element_id: this.options.ticker_id,
            shuffle: false,
            paused: false,
            duration: 5,
            delay: 5,
            height: 36
        }, params);
        if(!$(params.element_id)) return;
        var div = new Element('div');
        if(!Object.isArray(arr)) {
            arr = [];
            $(params.element_id).select('div').each(function(el) {
                arr.push(el.innerHTML);
                el.remove();
            });
        }
        if(params.shuffle) arr.shuffle();
        arr.each(function(str, i){
            div.appendChild(new Element('span', {'style':'top:'+(params.height*i)+'px'}).update(str));
        }); 
        $(params.element_id).update(div);

        if(params.paused) return;
        
        var pe = new PeriodicalExecuter(this.__moveTicker.bind(this, arr.length, params), params.delay);
        
        div.observe("mouseover", function() {
            pe.stop();
        });
        
        div.observe("mouseout", function() {
            pe = new PeriodicalExecuter(glocalnet.__moveTicker.bind(glocalnet, arr.length, params), params.duration);
        });
    },   
    /*****************************************************
    * Private - Move ticker text on a timed interval
    *
    * @param    {Integer} max
    * @param    {Object} params    
    * @param    {object} pe (PeriodicalExecuter)          
    * @returns 
    */  
    __moveTicker : function(max, params, pe) {
    	pe.stop();
    	pe = new PeriodicalExecuter(this.__moveTicker.bind(this, max, params), params.duration);
        var top = params.height * max;
        $$('#'+params.element_id+' span').each(function(el) {
            new Effect.Move(el, {
                y: -params.height, 
                mode: 'relative',
                transition: Effect.Transitions.Quad.easeInOut,
                duration: 1,
                afterFinish : function() {
                    var y = parseInt(el.getStyle('top'));
                    if(Object.isNumber(y) && y < 0) {
                        el.setStyle({'top' : ((max-1)*params.height) + 'px'});
                    }
                }
            });
        });
    },    
    /*****************************************************
     * Public
     *
     * @param    {Object|String} parent (Prototype Element Object | Element id)
     * @param    {Object} params
     * @returns 
     */  
     slideshows : function(parent, params) {
         if(this.options.dom_loaded) {
             this.__slideshows(parent, params);
         } else {
             document.observe("dom:loaded", this.__slideshows.bind(this, parent, params));
         } 
     }, 
     /*****************************************************
     * Private
     *
     * @param  
     * @returns 
     */  
     __slideshows : function(parent, params) {
         parent = $(parent) || $(this.options.site_id);
         parent.select('[rel="slideshow"]').each(function(el) {
             this.slideshow(el);
         },this);
     },   
     /*****************************************************
     * Public - Load one slideshow
     *
     * @param    {Object|String} el     
     * @param    {Object|Undefined} params         
     * @returns 
     */ 
     slideshow : function(el, params) {
         el = $(el);
         if(!el) return;
         if(el.readAttribute('loaded')) return;
         params = typeof params == "object" ? params : {};
         params = Object.extend({
             prop: 'x',
             delay: 0,
             duration: 1,
             index: 0
         }, params);
         params.rule = params.prop == 'y' ? 'top' : 'left';  
         var slides = el.immediateDescendants();
         if(slides.length < 2) return;
         params.value = params.prop == 'x' ? (params.value > 0 ? el.getWidth() : params.width) : (params.value > 0 ? el.getHeight() : params.height);
         if(params.value == 0) return; // hidden element has no width/height
         params.value += 5; // spacing between images
         slides.each(function(slide, i){
             el.appendChild(new Element('span', {'style':params.rule+':'+(params.value*i)+'px;position:absolute;', rel: slide.readAttribute('rel')}).update(slide.remove()));
         }, this); 
         el.writeAttribute('loaded', 'true');
         this.__slideshowRun(el, params, params.delay);
     },
     /*****************************************************
     * Private - Move slideshow images on a timed interval
     *
     * @param    {Object} slideshow
     * @param    {Object} params     
     * @param    {Number} delay          
     * @returns 
     */  
     __slideshowRun : function(slideshow, params, delay) {
         var slides = slideshow.immediateDescendants();
         var slide = slides[params.index];
         var slide_params = (slide.readAttribute('rel') || '').toQueryParams();
         var delay = Object.isUndefined(delay) ? slide_params.delay : slide_params.delay;
         params.index = params.index+1 >= slides.length ? 0 : params.index+1;
         var max = slides.length;
         var end = params.value * max;
         slides.each(function(el, counter) {
             new Effect.Move(el, {
                 x: params.prop == 'x' ? -params.value : 0, 
                 y: params.prop == 'y' ? -params.value : 0, 
                 mode: 'relative',
                 duration: Object.isNumber(params.duration) ? params.duration : 1,
                 delay: Object.isNumber(delay) ? delay : 10,
                 transition: Effect.Transitions.sinoidal,
                 afterFinish : function() {
                     var v = parseInt(el.getStyle(params.rule));
                     if(Object.isNumber(v) && v < 0) {
                         switch(params.prop) {
                             case "y":
                             	el.setStyle({'top' : ((max-1)*params.value) + 'px'});
                                 break;
                             case "x":
                             	el.setStyle({'left' : ((max-1)*params.value) + 'px'});
                                 break;
                                 
                          }
                     }
                     if(counter == slides.length-1)
                     	glocalnet.__slideshowRun(slideshow, params);
                 }
             });
         });
     },   
    /*****************************************************
     * Public
     *
     * @param    {Object|String} parent (Prototype Element Object | Element id)
     * @param    {Object} params
     * @returns 
     */  
     fadeshows : function(parent, params) {
         if(this.options.dom_loaded) {
             this.__fadeshows(parent, params);
         } else {
             document.observe("dom:loaded", this.__fadeshows.bind(this, parent, params));
         } 
     }, 
     /*****************************************************
     * Private
     *
     * @param  
     * @returns 
     */  
     __fadeshows : function(parent) {
         parent = $(parent) || $(this.options.site_id);
         parent.select('[rel="fadeshow"]').each(function(el) {
             this.fadeshow(el);
         },this);
     },   
     /*****************************************************
     * Public - Load one fadeshow
     *
     * @param    {Object|String} el           
     * @returns 
     */ 
     fadeshow : function(el) {
         el = $(el);
         if(!el) return;
         if(el.readAttribute('loaded')) return;
         var slides = el.immediateDescendants();
         if(slides.length < 2) return;
         slides.each(function(slide, i){
         	if(i > 0) slide.setStyle({'display':'none'});
         }, this); 
         el.writeAttribute('loaded', 'true');
         this.__fadeshowRun(slides, 0, slides.length-1, 1);
     },
     /*****************************************************
     * Private - Fade fadeshow images on a timed interval
     *
     * @param    {Array} slides
     * @param    {Number} index          
     * @returns 
     */  
     __fadeshowRun : function(slides, index, prev, delay) {
 		if(index >= slides.length) {
 			index = 0;
 			prev = slides.length - 1;
 		}
 		slides[prev].fade({
 			duration: 1,
 			delay: delay,
 			afterFinish : function() {
 				slides[index].appear({
 		        	afterFinish : function() {
 		        		glocalnet.__fadeshowRun(slides, index+1, index, 3)
 		        	},
 					duration: 1
 		        });
 			}
         });
         
     },
     
    /*****************************************************
    * Private - Window scroll event handler to position orderflow
    *
    * @param    {Object} e (Event)
    * @returns 
    */  
    __onScrollWindow : function(e) {
        var margin_top = 10;
        
        var viewport_height = document.viewport.getDimensions().height;
        var viewport_offset = document.viewport.getScrollOffsets().top+margin_top;
        
        var footer_top = this.options.footer_top;
        
        var orderflow_top = (this.options.content_top+this.options.tabs_top) + margin_top;
        var orderflow_height = $(glocalnet.options.orderflow_id).getDimensions().height;
        var orderflow_bot = orderflow_height + viewport_offset;
        
        var content_top = $(glocalnet.options.content_id).positionedOffset().top;
        var content_height = $(glocalnet.options.content_id).getDimensions().height;
        var content_bot = content_top+content_height;

        if(orderflow_height < viewport_height && viewport_offset >= orderflow_top && content_height > orderflow_height) {
            $(glocalnet.options.orderflow_id).addClassName('scrolling');
            if(orderflow_bot > content_bot-margin_top) {
                $(glocalnet.options.orderflow_id).setStyle({'top' : (margin_top-(orderflow_bot-content_bot+margin_top))+'px'});
            } else {
                $(glocalnet.options.orderflow_id).setStyle({'top' : margin_top+'px'});
            }
        } else{
            $(glocalnet.options.orderflow_id).removeClassName('scrolling');
            $(glocalnet.options.orderflow_id).setStyle({'top' : '0px'});
        }
    },
    /*****************************************************
    * Private - Get filename and path from url 
    *
    * @param    {String} data
    * @returns 
    */  
    __parseUrl : function (data) {
        data = data.replace(/^\s|\s$/g, "");

        if (/\.\w+$/.test(data)) {
            var m = data.match(/([^\/\\]+)\.(\w+)$/);
            if (m)
                return {filename: m[1], ext: m[2]};
            else
                return {filename: "no file name", ext:null};
        } else {
            var m = data.match(/([^\/\\]+)$/);
            if (m)
                return {filename: m[1], ext: null};
            else
                return {filename: "no file name", ext:null};
        }
    },
    /*****************************************************
    * Public - Open location in new window or specified target
    *
    * @param    {String} url
    * @param    {Object} params
    * @returns
    */ 
    openWindow : function (url, params) {
        params = params || {};
        params = Object.extend({
            name: 'glocalnet',
            resizable: 'no',
            menubar: 'no',
            location: 'no',
            scrollbars: 'yes',
            titlebar: 'no',
            directories: 'no',
            location: 'no',
            status: 'no'
        }, params);
        params.left = params.left || Math.round((screen.availWidth-params.width)/2);
        params.screenX = params.left;
        params.top = params.top || Math.round((screen.availHeight-params.height)/2);
        params.screenY= params.top;
        
   
        var features = "";
        Object.keys(params).each(function(prop) {
            if(features.length > 0) features += ","
            features += (prop + "=" + params[prop]);
        });
        if(params.name == "_blank")
            window.open(url);
        else 
            window.open(url, params.name, features);
    },
    /*****************************************************
     * Public - Close popup
     *
     * @param
     * @returns
     */ 
     closePopup : function () {
    	this.popup.__destroy();
     },
    /*****************************************************
    * Public - Open location in popup
    *
    * @param    {String} url
    * @param    {Object} params
    * @returns
    */ 
    loadPopup : function (url, params) {
        if(this.options.dom_loaded) {
            this.__loadPopup(url, params);
        } else {
            document.observe("dom:loaded", this.__loadPopup.bind(this, url, params));
        } 
    },
    /*****************************************************
    * Private - Open location in popup
    *
    * @param    {String} url
    * @param    {Object} params
    * @returns
    */ 
    __loadPopup : function (url, params) {
        params = params || {};
        params = Object.extend({
            title: null,
            skin: null,
            source_el: null,
            target_el: null,
            content: null,
            event: null,
            modal: params.skin ? false : true
        }, params);
        this.popup.__open(url, params);
    },
    /*****************************************************
    * Public - Send Page View stats wrapper (call from flash campaigns)
    *
    * @param    {String} pageName  (Subpage1[|Subpage2|Subpage3|etc])
    * @returns
    */ 
    sendStats : function (pageName) {
        this.stats.sendAdformOmnitureStatsWithPageName(pageName);
    }
}

/* String to unicode */
String.prototype.toUnicode = function () {
    return this.replace(/./g, function (char) {
        return "&#" + String.charCodeAt(char) + ";";
    });
};

/* Array shuffle */
Array.prototype.shuffle = function() {
     var i = this.length, j, temp;
     if(i == 0) return;
     while(i--)
     {
         j = Math.floor((i+1) * Math.random());
         temp = this[i];
         this[i] = this[j];
         this[j] = temp;
     }
}
     
/* Include Popup Div */
document.write('<script src="'+glocalnet.options.dir+'/popup/popup.js" type="text/javascript"></script>');
document.write('<link rel="stylesheet" type="text/css" href="'+glocalnet.options.dir+'/popup/popup.css">');

/* Include Site statistics */
document.write('<script src="'+glocalnet.options.dir+'/stats/stats.js" type="text/javascript"></script>');

/* Include Easing equations */
document.write('<script src="'+glocalnet.options.dir+'/effects/easing.js" type="text/javascript"></script>');

/* Initialize */
glocalnet.initialize();


