﻿
/*********************************************************
** Browser - to contain all required browser information
*********************************************************/

function BrowserBase()
{
	try
	{
	    this.AgentName=navigator.userAgent.toLowerCase();
	}
	catch(e)
	{
	    this.AgentName = '';
	}
	this.MajorVersionNumber =parseInt(navigator.appVersion);
	this.IsIE = ( this.AgentName.indexOf('msie') != -1 );
	this.IsChrome = ( this.AgentName.indexOf('chrome') != -1 );
	if ( this.IsIE )
	{
	    this.Version = parseFloat(this.AgentName.substring(this.AgentName.indexOf('msie') + 5, this.AgentName.length));
	}
}
var Browser = new BrowserBase();

/*********************************************************
** PanelController - for all hidden panels
 - PanelController.add(
    Name - Friendly name for the panel
    Align (top/bottom/left/right) - Alignment of Panel
    Position (top/bottom/left/right) - Position of Panel to button
    Button ID - Optional ID of the button linked to the panel (if 1 to 1)
    Panel ID - The ID of the panel to open
    Flip (true/false) - Enable panel to flip (default: false)
    Offset - {x: 0, y: 0} - Optional X, Y Offset for the Panel position (neg or pos)
    Close behaviour (onmouseout/onclick) - Optional choice of panel closing (default:onclick)
 );
- PanelController.attachEvents('SaleInformationPanel', {'SalesCalendar' : 'id', 'Sale' : 'div.class'});
- PanelController.show( Name );
- PanelController.close( Name );
*********************************************************/

PanelControllerBase = function()
{
    this.Panel = new Array();
    this.OpenPanel = { 'open':false, 'button':null, 'panel':null, 'name':'' };
}
PanelControllerBase.prototype = {
    add: function(name, align, position, button_id, panel_id, flip, offset, close_behaviour)
    {
        if (!this.Panel[name])
        {
            this.Panel[name] = {
                'align': align.toLowerCase(),
                'position': position.toLowerCase(),
                'button_id': button_id,
                'panel_id': panel_id,
                'mask_id': name + 'IFrameMask',
                'flip': (flip) ? flip : false,
                'offset': (offset) ? offset : { x: 0, y: 0 },
                'close_behaviour': (close_behaviour) ? close_behaviour.toLowerCase() : 'onclick'
            };
        }
    },

    attachEventToElement: function(panel_name, elementID, resource_path) {
        var element = document.getElementById(elementID);

        if (element.className.indexOf('openPanel:') == -1) {
            element.className += ' openPanel:' + panel_name;
            element.onmouseover = function() {
                if (this.className.indexOf('openPanel:') != -1) {
                    PanelController.show('', this, resource_path);
                }
            }
        }
    }
    ,
    
    attachEvents: function(panel_name, button_path, resource_path)
    {
        if (typeof button_path == 'object')
        {
            // Get the divs from the button path
            var buttons = this.getButtons(button_path);

            // Attach the events
            for (var j = 0; j < buttons.length; j++)
            {
                // If not already attached!
                if (buttons[j].className.indexOf('openPanel:') == -1)
                {
                    buttons[j].className += ' openPanel:' + panel_name;
                    buttons[j].onmouseover = function() {
                        if (this.className.indexOf('openPanel:') != -1)
                        {
                            PanelController.show('', this, resource_path);
                        }
                    }
                }
            }
        }
    },
    attachClickEvents: function(button_path, event, handler)
    {
        if (typeof button_path == 'object')
        {
            // Get the divs from the button path
            var buttons = this.getButtons(button_path);

            // Attach the events
            for (var j = 0; j < buttons.length; j++)
            {
                switch (event.toLowerCase())
                {
                    case 'onclick':
                        buttons[j].onclick = handler;
                        break;
                }
            }
        }
    },
    getButtons: function(button_path)
    {
        var object = document;
        var buttons = new Array();

        // Iterate through the object
        for (var item in button_path)
        {
            // Go through types
            switch (button_path[item])
            {
                case 'id':
                    object = object.getElementById(item);
                    break;
                case 'div.class':
                    var divs = object.getElementsByTagName('div');
                    for (var i = 0; i < divs.length; i++)
                    {
                        if (divs[i].className.indexOf('Sale ') != -1)
                        {
                            buttons.push(divs[i]);
                        }
                    }
                    break;
               case 'tagName':
                    buttons = object.getElementsByTagName(item);
                    break;

            }
        }
        return buttons;
    },
    show: function(name, button, resource_path)
    {
        // If no panel name and we have a button object      
        if (!name && button)
        {
            // If a panel name exists in the class
            if (button.className.indexOf('openPanel:') != -1)
            {
                name = button.className.split('openPanel:')[1];
                if (name.indexOf(' ') != -1)
                {
                    name = name.split(' ')[0];
                }
            }
        }

        if (button)
        {
            // Store which button has opened the panel
            this.Panel[name].button_id = button.id;
        }
        else
        {
            // Get the button if not dynamic
            button = document.getElementById(this.Panel[name].button_id);
        }

        // Get the element in the document
        var panel = document.getElementById(this.Panel[name].panel_id);
        var mask = document.getElementById(this.Panel[name].mask_id);

        // Remove the focus from the button and do hover style
        button.blur();
        button.style.cursor = 'pointer';

        if (Browser.IsIE && (Browser.Version < 7) && !mask)
        {
            // Get the panel size
            var panel_size = this.getElementSize(panel);

            // Create the iframe mask to enable the div to sit over form inputs in IE6
            this.createMask(name, panel_size.h, panel_size.w);

            // Set the zindex on the panel to always be above the iframe
            panel.style.zIndex = 12;
        }

        // If we have a resource_path then call the JSON load
        if (resource_path)
        {
            JSONUpdate.load(button, panel, resource_path);
        }

        // If mouseout required
        if (this.Panel[name].close_behaviour == 'onmouseout')
        {
            // Set as THE open panel
            this.OpenPanel = { 'open': true, 'button': button, 'panel': panel, 'name': name };
        }

        // Position the panel
        this.reposition(name, button, panel, mask);
    },
    move: function()
    {
        // Find and reposition open panels
        for (var name in this.Panel)
        {
            var p = this.Panel[name];
            var panel = document.getElementById(p.panel_id);
            if (panel.style.visibility == 'visible')
            {
                var button = document.getElementById(p.button_id);
                var mask = document.getElementById(p.mask_id);

                this.reposition(name, button, panel, mask);
            }
        }
    },
    reposition: function(name, button, panel, mask)
    {
        var button_pos = this.getAbsolutePosition(button);
        var button_size = this.getElementSize(button);
        var panel_size = this.getElementSize(panel);

        // Default position ( top, left )
        var y = button_pos.y;
        var x = button_pos.x;

        // Calculate the alignment
        switch (this.Panel[name].align)
        {
            case 'right':
                x = (button_pos.x + button_size.w) - panel_size.w;
                break;
            case 'left':
                x = button_pos.x;
                break;
            case 'top':
                y = button_pos.y;
                break;
            case 'bottom':
                y = (button_pos.y + button_size.h) - panel_size.h;
                break;
        }

        // Calculate the position
        switch (this.Panel[name].position)
        {
            case 'right':
                x = (button_pos.x + button_size.w + 1);
                break;
            case 'left':
                x = (button_pos.x - panel_size.w - 1);
                break;
            case 'top':
                y = (button_pos.y - panel_size.h - 1);
                break;
            case 'bottom':
                y = (button_pos.y + button_size.h + 1);
                break;
        }

        // Get the scrolling divs offset
        var div_scroll = this.getScrollOffset(button);

        // Flip panel?
        if (this.Panel[name].flip)
        {
            // Get sizes
            var body_scroll = this.getBodyScroll();
            var browser = this.getBrowserSize();

            // Vertical flip
            if ((body_scroll.y + browser.h) < (y + panel_size.h - div_scroll.y))
            {
                // Reset the y pos
                y = button_pos.y - panel_size.h;

                // If aligned to the top, switch it to the bottom
                if (this.Panel[name].align == 'top' && ( this.Panel[name].position == 'left' || this.Panel[name].position == 'right' ) )
                {
                    y += button_size.h;
                }

                // Do the negative y offset
                y += this.Panel[name].offset.y * -1;
            }
            else
            {
                // Do the y offset
                y += this.Panel[name].offset.y;
            }
        }
        else
        {
            // Do the y offset
            y += this.Panel[name].offset.y;
        }

        // Do the provided offsets
        x += this.Panel[name].offset.x;

        // Do the scrolling divs offset
        x -= div_scroll.x;
        y -= div_scroll.y;

        // Chrome workaround
        if (Browser.IsChrome)
        {
            y += document.body.scrollTop;
            x += document.body.scrollLeft;
        }

        // Move the mask for IE6
        if (mask)
        {
            mask.style.top = y + 'px';
            mask.style.left = x + 'px';
            mask.style.display = 'block';
        }

        panel.style.top = y + 'px';
        panel.style.left = x + 'px';
        panel.style.visibility = 'visible';
    },
    close: function(name)
    {
        // Get the element in the document
        var panel = document.getElementById(this.Panel[name].panel_id);
        var mask = document.getElementById(this.Panel[name].mask_id);
        panel.style.visibility = 'hidden';
        if (mask)
        {
            mask.style.display = 'none';
        }
        this.OpenPanel.open = false;
    },
    getAbsolutePosition: function(element)
    {
        var r = { x: element.offsetLeft, y: element.offsetTop };
        if (element.offsetParent)
        {
            var tmp = this.getAbsolutePosition(element.offsetParent);
            r.x += tmp.x;
            r.y += tmp.y;
        }
        return r;
    },
    getScrollOffset: function(element)
    {
        var s = { x: element.scrollLeft, y: element.scrollTop };
        if (element.parentNode.tagName.toLowerCase() != 'html')
        {
            var tmp = this.getScrollOffset(element.parentNode);
            s.x += tmp.x;
            s.y += tmp.y;
        }
        return s;
    },
    getBodyScroll: function()
    {
        var x = window.pageXOffset ||
            document.body.scrollLeft ||
            document.documentElement.scrollLeft;

        var y = window.pageYOffset ||
            document.body.scrollTop ||
            document.documentElement.scrollTop;

        return { x: (x ? x : 0), y: (y ? y : 0) };
    },
    getBrowserSize: function()
    {
        var w = document.documentElement.clientWidth;
        var h = document.documentElement.clientHeight;
        return { w: (w ? w : 0), h: (h ? h : 0) };
    },
    getElementSize: function(element)
    {
        return { w: element.offsetWidth, h: element.offsetHeight }
    },
    createMask: function(name, h, w)
    {
        var mask = document.createElement('iframe');
        mask.scrolling = 'no';
        mask.src = 'javascript:false;';
        mask.id = this.Panel[name].mask_id;
        mask.frameBorder = 0;
        mask.style.position = 'absolute';
        mask.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
        mask.style.zIndex = 10;
        mask.style.width = w + 'px';
        mask.style.height = h + 'px';
        document.getElementsByTagName('body')[0].appendChild(mask);
    },
    checkMouseOut: function()
    {
        if (this.OpenPanel.open)
        {
            // Get the mouse positions
            var mouse = { x: Mouse.x, y: Mouse.y };

            if (Browser.IsIE)
            {
                mouse.x += document.documentElement.scrollLeft;
                mouse.y += document.documentElement.scrollTop;
            }

            // Are we inside the button?
            var inside = this.isMouseInside(mouse, this.OpenPanel.button);

            if (!inside)
            {
                // Not inside the button, so are we inside the panel?
                inside = this.isMouseInside(mouse, this.OpenPanel.panel);

                if (!inside)
                {
                    // Not inside either so close
                    this.close(this.OpenPanel.name);
                }
            }
        }
    },
    isMouseInside: function(mouse, element)
    {
        // Get the absolute position of the element
        var absPos = this.getAbsolutePosition(element);

        // Get the scrolling divs offset
        var div_scroll = this.getScrollOffset(element);

        // Get the element positions - two pixels inside
        var pos =
        {
            l: absPos.x - div_scroll.x - 1,
            r: absPos.x + element.offsetWidth - div_scroll.x + 1,
            t: absPos.y - div_scroll.y - 1,
            b: absPos.y + element.offsetHeight - div_scroll.y + 1
        };

        // Chrome workaround
        if (Browser.IsChrome)
        {
            var body_scroll = this.getBodyScroll();
            pos.l += body_scroll.x;
            pos.r += body_scroll.x;
            pos.t += body_scroll.y;
            pos.b += body_scroll.y;
        }

        // Mouse inside?
        var inside = ((mouse.x > pos.l && mouse.x < pos.r) && (mouse.y > pos.t && mouse.y < pos.b));

        return inside;
    },
    getPanelNameById: function(id)
    {
        // Get the panel name from either the button or panel id
        for (var i in this.Panel)
        {
            if ((this.Panel[i].button_id == id) || (this.Panel[i].panel_id == id))
            {
                return i;
                break;
            }
        }
    },
    click: function()
    {
        // Loop through the panel to find an open one
        for (var name in this.Panel)
        {
            var p = this.Panel[name];
            var panel = document.getElementById(p.panel_id);
            if (panel.style.visibility == 'visible')
            {
                // If close on click and clicked outside of panel
                if ((p.close_behaviour == 'onclick') && !this.hitTest(panel))
                {
                    this.close(name);
                }
            }
        }
    },
    hitTest: function(panel)
    {
        var hit = false;
        var target = Mouse.target;
        do {
            if (target == panel)
            {
                hit = true;
            }
            target = target.parentNode;
        } while (!hit && target.parentNode)
        return hit;
    }
}

var PanelController = new PanelControllerBase();

window.onresize = function()
{
    PanelController.move();
}

/*********************************************************
** JSON Update
*********************************************************/

function JSONUpdateBase(){}
JSONUpdateBase.prototype = {
    load : function( button, panel, resource_path )
    {
        this.xmlHttpCall( 'GET', eval(resource_path) );
    },
    xmlHttpCall : function ( type, urlStr )
    {
	    var xmlHttpReq = false;
	    var self = this;
	    // Figure out the required request type
	    if ( window.XMLHttpRequest ) // Mozilla/Safari
	    {
		    self.xmlHttpReq = new XMLHttpRequest();
	    }
	    else if ( window.ActiveXObject ) // IE
	    {
		    self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
	    }
	    // Build the request.
	    self.xmlHttpReq.open( type, urlStr, true);
	    self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    	
	    // Define callback function, with nested function passed to this routine.
	    self.xmlHttpReq.onreadystatechange = function()
	    {
          if ( self.xmlHttpReq.readyState == 4 )
          {
              var response = self.xmlHttpReq.responseText;
              JSONUpdate.updateDocument(response);
          }
	    }
	    // Send the post request.
	    self.xmlHttpReq.send(''); // No args required but can add
    },
    updateDocument : function ( response )
    {
        var data = eval( '(' + response + ')' );
        //var data = response;
        for ( var a in data )
        {
            if ( document.getElementById(a) )
            {
                var e = document.getElementById(a); // html 'e'lement
                var o = eval("data." + a ); // JSON sub 'o'bject
                if ( o.display ){ e.style.display = o.display; }
                if ( o.href ){ e.href = o.href; }
                if ( o.innerHTML ){ e.innerHTML = o.innerHTML; }
                if ( o.src ){e.src = o.src; }
                
            }
        }
        // Call the move to update the position if the showing panel has resized with the new content
        PanelController.move();
    }
}

var JSONUpdate = new JSONUpdateBase();

/*********************************************************
** Mouse - to contain all required mouse information
*********************************************************/

function MouseBase()
{
    this.x = 0;
    this.y = 0;
    this.target;
}
MouseBase.prototype = {
    click : function(e)
    {
        // Get the window event for IE
        e = (!e) ? window.event : e;
        
        // Get the target
        this.target = ( e.target )? e.target : e.srcElement;
        
        // Hard code the click event - do as an addClickEvent for more
        PanelController.click();
    },
    move : function(e)
    {
        // Get the window event for IE
        e = (!e) ? window.event : e;
        this.x = ( e.pageX ) ? e.pageX : e.clientX;
        this.y = ( e.pageX ) ? e.pageY : e.clientY;
        
        PanelController.checkMouseOut();
    }
}
var Mouse = new MouseBase();

document.onmousedown = function(e)
{
    Mouse.click(e);
}
document.onmousemove = function(e)
{
    Mouse.move(e);
}