/*************************************************************
Script:		utils.js
Desc:		Useful functions and generic classes
Version:	0.8
	
debug
Loaders (loader manager)
Loader
iFrame
Swiff.Uploader - Flash FileReference Control
Fx.ProgressBar
EzUpload
EzUploader - manages multiple EzUploads
Fx.Slide
Accordion
Drag
Drag.Move
Asset
Layers (layer manager)
Layer
HistoryManager
Dropdowns
DatePicker
Date Prototypes
Canvas functions
CanvasBox
MultiBox
	
*************************************************************/

var debug = true;

if (!debug) {
    var console = {
        log: function() { }
    }
}

/*************************************************************
Class:		iFrame
Version:	1.0
Author:		Samuel Birch
Status:		Ready
*************************************************************/
/*
Usage:
var frame = new iFrame();
frame.show();
frame.hide();
	
if needed:
frame.set(param); 
param can be either an element to set its size & position against or an object containing size and position properties.
frame.fillPage(); fills the iframe to the full page width & height, including scrolling area.
	
*/
var iFrame = new Class({

    Implements: [Options, Events],

    getOptions: function() {
        return {
            src: 'javascript:void(0);',
            id: 'iFrame_' + new Date().getTime(),
            container: document.body,
            zIndex: 1,
            browsers: (Browser.Engine.trident4)
        };
    },

    initialize: function(options) {
        this.setOptions(this.getOptions(), options);
        this.container = $(this.options.container);

        if ($(this.options.id)) {
            this.frame = $(this.options.id);
        } else {

            this.frame = new Element('iframe', {
                'id': this.options.id,
                'name': this.options.id,
                'src': this.options.src,
                'frameborder': 0,
                'scrolling': 'no',
                'styles': {
                    'position': 'absolute',
                    'zIndex': this.options.zIndex,
                    'border': '0',
                    'filter': 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)',
                    'top': 0,
                    'left': 0,
                    'width': '100%',
                    'height': '100%',
                    'display': 'none'
                }
            });

            this.frame.injectInside(this.container);
        }

    },

    set: function(element) {
        if ($type(element) == 'object') {
            var coords = element;
        } else {
            var el = $(element);
            var coords = el.getCoordinates();
        }

        this.frame.setStyles({
            'top': coords.top,
            'left': coords.left,
            'width': coords.width,
            'height': coords.height
        });
    },

    fillPage: function() {
        this.frame.setStyles({
            'top': 0,
            'left': 0,
            'width': window.getScrollSize().x,
            'height': window.getScrollSize().y
        });
    },

    show: function() {
        //if (this.options.browsers) {
        this.frame.setStyle('display', 'block');
        //}
    },

    hide: function() {
        this.frame.setStyle('display', 'none')
    }

});



/*************************************************************
Class:		Layers (layer manager)
Version:	1.0
Author:		Samuel Birch
Status:		Testing
*************************************************************/
var Layers = new Class({

    Implements: Options,

    getOptions: function() {
        return {

    };
},

initialize: function(options) {
    this.setOptions(this.getOptions(), options);
    this.layers = [];
    this.elements = [];
},

toggle: function(el, options) {
    if ($(el)) {
        el = this.GetElement(el);
    }
    if (this.elements.contains(el)) {
        var n = this.elements.indexOf(el);
        if (this.layers[n].options.control == options.control) {
            this.hide(el, options);
        } else {
            this.show(el, options);
        }
    } else {
        this.show(el, options);
    }
    return false;
},

show: function(el, options) {
    if ($(el)) {
        el = this.GetElement(el);
    }
    if (this.elements.contains(el)) {
        var n = this.elements.indexOf(el);
        if (this.layers[n].inProgress == false) {
            if (this.layers[n].visible) {
                el.store('show', true);
                el.store('options', options);
                this.hide(el, options);
            } else {
                this.layers[n].show();
            }
        }
    } else {
        this.elements.push(el);
        var l = new Layer(el, options);
        this.layers.push(l);
        l.show();
    }
    return false;
},

hide: function(el, options, delay) {
    if ($(el)) {
        el = this.GetElement(el);
    }
    if (this.elements.contains(el)) {
        var n = this.elements.indexOf(el);
        if (this.layers[n].inProgress == false) {
            this.layers[n].hide();
        }
        else {
            (function() { layers.hide(el); }).delay(250, el);
        }
    }
    return false;
},

UpdateDimensions: function(el) {
    if ($(el)) {
        el = this.GetElement(el);
    }
    if (this.elements.contains(el)) {
        var n = this.elements.indexOf(el);
        this.layers[n].updateFrameDimensions();
    }
    return false;
},

GetElement: function(el) {

    var correctElement = $(el);
    $(document.body).getElements('div[id=' + el + ']').each(function(element, index) {
        if (layers.elements.contains(element)) {
            correctElement = element;
        }
    });

    return correctElement;
}

});

var layers = new Layers();

/*************************************************************
Class:		Layer
Version:	1.0
Author:		Samuel Birch
Status:		Testing
*************************************************************/
var Layer = new Class({

    Implements: Options,

    getOptions: function() {
        return {
            fade: false,
            slide: false,
            vertical: null, //slide direction: up, down
            horizontal: null, //slide direction: left, right
            duration: 500, //milliseconds
            transition: 'sine:out',
            control: null, //element/string of the control that the layer is to be positioned against
            position: null, //type in relation to the control: top, left, bottom, right, center   XY object: (array) [x,y], 
            align: null, //the side to be aligned to the control: top, left, bottom, right
            center: 'both', //both, vertical, horizontal
            container: window, //used with center
            modal: false,
            modalTarget: null,
            bgColor: '#000',
            opacity: 0.7,
            dropshadow: false,
            shadow: null, //glow, drop, null
            shadowSize: 8,
            closeOnMouseout: false,
            mouseoutDelay: 2000,
            closeOnBlur: false,
            MoveToBody: false,
            OnHide: $empty,
            OnShow: $empty,
            multibox: false,
            initialWidth: 400,
            initialHeight: 300
        };
    },

    initialize: function(element, options) {
        this.setOptions(this.getOptions(), options);
        this.layer = $(element);
        this.unique = new Date().getTime();
        this.ref = element;

        this.visible = false;
        this.doBlur = false;
        this.inProgress = false;

        if (this.layer && this.options.MoveToBody) {
            if (this.layer.getParent() != document.body) {
                this.layer.inject($(document.body));
            }
        }

        if (this.layer) {
            this.ref = this.layer;
            this.layer.setStyles({
                'display': 'block',
                'visibility': 'hidden',
                'position': 'absolute'
            });

            this.coords = this.layer.getCoordinates();
            //this.coords.width++;
            this.layer.setStyles({
                'position': 'relative',
                //'visibility': 'visible',
                'z-index': 2
            });

            //if the layer element is the same as has been previously used then it would already be wrapped in a container.
            // so lets check and see.
            var useParentAsContainer = false;
            if (this.layer.getParent().id) {

                if (this.layer.getParent().id.contains('EzLayerWrapperElement')) {
                    useParentAsContainer = true;
                }
            }

            if (useParentAsContainer) {
                this.container = this.layer.getParent();
                this.container.setStyles({ 'overflow': 'hidden', 'width': 0, 'height': 0, 'display': 'none' });

            } else {
                this.container = new Element('div', {
                    'id': 'EzLayerWrapperElement' + this.unique,
                    'styles': {
                        'overflow': 'hidden',
                        'width': 0,
                        'height': 0,
                        'display': 'none'
                    }
                }).wraps(this.layer);
            }
            if (this.options.multibox) {
                this.container.setStyles({
                    'overflow': 'visible',
                    'position': 'absolute'
                });
            }

            this.layer.setStyle('visibility', 'visible');
        }

        if (this.options.modalTarget) {
            this.options.modal = false;
            var modalTarget = $(this.options.modalTarget);
            if (!this.layer) {
                this.layer = new Element('div').inject(document.body);
            }

            var tag = modalTarget.get('tag');
            if (tag == 'img' || tag == 'input' || tag == 'textarea' || tag == 'select') {
                //create a container
                modalTarget = new Element('span').wraps(modalTarget);
            }

            if (modalTarget.getStyle('position') == 'static') {
                modalTarget.setStyle('position', 'relative');
            };

            this.loaderContainer = new Element('div', {
                'class': 'ezLoader',
                'styles': {
                    'position': 'absolute',
                    'top': 0,
                    'left': 0,
                    'width': '100%',
                    'height': '100%',
                    'zIndex': 1
                }
            }).wraps(this.layer).inject(modalTarget);
            this.content = new Element('div', {
                'styles': {
                    'position': 'absolute',
                    'height': 'auto',
                    'width': '100%',
                    'zIndex': 2
                }
            }).wraps(this.layer);
            this.bg = new Element('div', {
                'styles': {
                    'position': 'absolute',
                    'width': '100%',
                    'height': '100%',
                    'top': 0,
                    'left': 0,
                    'zIndex': 1,
                    'background-color': this.options.bgColor,
                    'opacity': this.options.opacity
                }
            }).inject(this.loaderContainer);

            this.content = this.layer;
            this.layer = this.loaderContainer;

            this.container = new Element('div').wraps(this.layer);

            if (Browser.Engine.trident4) {
                var c = modalTarget.getCoordinates();

                this.container.setStyles({
                    'position': 'absolute',
                    'top': 0,
                    'left': 0,
                    'width': c.width,
                    'height': c.height
                });
            }

            this.coords = modalTarget.getCoordinates();
            this.coords.width++;
        }


        this.layerRef = this.layer;

        /*if (this.options.dropshadow) {
        this.coords.width += 8;
        this.coords.height += 8;
        this.layerRef = this.createDropshadow();
        }*/
        if (this.options.shadow) {
            var num = 0;
            if (this.options.shadow == 'glow') {
                num = this.options.shadowSize * 2;
            }
            if (this.options.shadow == 'drop') {
                num = this.options.shadowSize;
            }
            this.coords.width += num;
            this.coords.height += num;
            this.layerRef = this.createShadow();
        }

        this.fx = {};

        if (Browser.Engine.trident4) {
            var c = this.container;
            if (this.options.modal) {
                c = document.body;
            }
            this.frame = new iFrame({ container: c });
            this.frame.frame.setStyle('height', '100%');
            this.frameTimer = 0;
        }

        if (this.options.modal) {
            if ($('ezLayerOverlay' + this.unique)) {
                this.overlay = $('ezLayerOverlay' + this.unique).setStyles({
                    'backgroundColor': this.options.bgColor
                });
            } else {
                this.overlay = new Element('div', {
                    'id': 'ezLayerOverlay' + this.unique,
                    'styles': {
                        'position': 'absolute',
                        'display': 'none',
                        'opacity': 0,
                        'top': 0,
                        'left': 0,
                        'width': window.getScrollSize().x,
                        'height': window.getScrollSize().y,
                        'zIndex': 2,
                        'backgroundColor': this.options.bgColor
                    }
                }).inject(document.body);
            }
            this.fx.overlay = new Fx.Tween(this.overlay, {
                duration: this.options.duration,
                transition: Fx.Transitions.linear,
                onComplete: function() {
                    if (this.overlay.getStyle('opacity') == 0) {
                        this.overlay.setStyle('display', 'none');
                    }
                } .bind(this)
            });
            if (this.frame) {
                this.frame.fillPage();
            }
        }

        this.fx.container = new Fx.Morph(this.container, {
            duration: this.options.duration,
            transition: this.options.transition,
            link: 'cancel',
            onStart: function() {
                if (this.doHide && this.frame) {
                    $clear(this.frameTimer);
                }
                if (!this.options.fade) {
                    this.container.setStyle('opacity', 1);
                }

            } .bind(this),
            onComplete: function() {
                if (this.doHide) {
                    this.container.setStyle('display', 'none');
                    if (!this.options.multibox) {
                        this.layer.setStyle('display', 'none');
                        this.layer.inject(this.container, 'before');
                        if (this.frame) {
                            this.frame.frame.destroy();
                        }
                        this.container.destroy();
                        if (this.options.modalTarget) {
                            this.content.setStyle('display', 'none');
                            this.content.inject(this.layer, 'before');
                            this.layer.destroy();
                        }
                        if (this.overlay) {
                            this.overlay.destroy();
                        }
                        this.visible = false;
                        var n = layers.elements.indexOf(this.ref);
                        layers.elements.erase(this.ref);
                        layers.layers.splice(n, 1);

                        if ($type(this.ref) == 'element') {
                            if (this.ref.retrieve('show')) {
                                this.ref.store('show', false);
                                layers.show(this.ref, this.ref.retrieve('options'));
                            } else {
                                this.inProgress = false;
                            }
                            this.inProgress = false;
                        }
                    }
                }
                else {
                    if (!Browser.Engine.trident4) {
                        this.container.store('defaults', this.container.getCoordinates());
                        this.container.setStyles({
                            'overflow': 'visible'
                        });
                        if (!this.options.multibox) {
                            this.container.setStyle('height', 'auto')
                        }

                        this.updateFrameDimensions();
                    }

                    if (this.options.closeOnMouseout) {
                        this.layer.addEvents({
                            'mouseout': function() {
                                this.delay = layers.hide.delay(this.options.mouseoutDelay, layers, this.ref);
                            } .bind(this),
                            'mouseover': function() {
                                $clear(this.delay);
                            } .bind(this)
                        });
                        if (this.options.control) {
                            $(this.options.control).cloneEvents(this.layer, 'mouseout');
                            $(this.options.control).cloneEvents(this.layer, 'mouseover');
                        }
                    }

                    this.doBlur = true;
                    this.visible = true;
                    this.inProgress = false;
                }
            } .bind(this)
        });

        this.fx.layer = new Fx.Tween(this.layerRef, {
            duration: this.options.duration,
            onComplete: function() {
                if (this.doHide) {
                    (function() { this.layerRef.setStyle('opacity', 1); }).delay(50, this);
                }
            } .bind(this)
        });

        this.position();

        window.addEvent('resize', this.resize.bind(this));

        if (this.options.closeOnBlur) {
            document.addEvent('click', function(e) {
                if (this.doBlur) {
                    e = new Event(e);
                    var lCoords = this.layer.getCoordinates();
                    var doHide = true;

                    if (e.page.x > lCoords.left && e.page.x < lCoords.right && e.page.y > lCoords.top && e.page.y < lCoords.bottom) {
                        doHide = false;
                    }
                    if (doHide) {
                        if (this.options.OnHide) {
                            layers.hide(this.ref, { onHide: this.options.OnHide });
                        } else {
                            layers.hide(this.ref);
                        }
                    }

                }
            } .bind(this));
        }
    },

    updateFrameDimensions: function() {
        if (this.frame) {
            var coords = this.container.getCoordinates();
            if (this.options.modalTarget) {
                coords = $(this.options.modalTarget).getCoordinates();
                this.layer.setStyles({
                    'width': coords.width,
                    'height': coords.height
                });
                this.bg.setStyles({
                    'width': coords.width,
                    'height': coords.height
                });
            }
            this.frame.frame.setStyles({
                'width': coords.width,
                'height': coords.height
            });
        }
    },

    resize: function(w, h) {
        if (this.overlay) {
            this.overlay.setStyle('display', 'none');
            this.overlay.setStyles({
                'width': window.getScrollSize().x,
                'height': window.getScrollSize().y,
                'display': 'block'
            });
        }
        if (this.frame && this.options.modal) {
            this.frame.fillPage();
        }
        if (this.options.position == 'center') {
            this.center();

        } else if (this.options.multibox) {
            if (w) {
                var top = (window.getCoordinates().height / 2) - (h / 2);
                var left = (window.getCoordinates().width / 2) - (w / 2);
                var defaults = this.container.retrieve('defaults');
                var myFx = {};
                myFx['height'] = h;
                myFx['top'] = top > 0 ? top : 0;
                myFx['width'] = w;
                myFx['left'] = left > 0 ? left : 0;
                //console.info(defaults);
                /*if(defaults){
                myFx['height'] = [defaults.height,h];
                myFx['width'] = [defaults.width,w];
                }*/

                this.fx.container.start(myFx);
            } else {
                var cont = this.container.getCoordinates();
                var top = (window.getCoordinates().height / 2) - (cont.height / 2);
                var left = (window.getCoordinates().width / 2) - (cont.width / 2);
                var myFx = {};
                myFx['top'] = top > 0 ? top : 0;
                myFx['left'] = left > 0 ? left : 0;
                this.fx.container.start(myFx);
            }
        } else {
            this.position();
        }

        this.updateFrameDimensions();
    },

    position: function(obj) {
        var control = $(this.options.control);
        var pos = this.options.position;
        var align = this.options.align;
        var center = this.options.center;
        var container = this.container;

        if (control) {
            var cPos = control.getCoordinates();
            var styles = {};

            styles.position = 'absolute';
            styles.zIndex = 3;
            styles.top = cPos.top;
            styles.left = cPos.left;

            if (pos == 'top') {
                this.options.vertical = 'up';
                styles.top = cPos.top - this.coords.height;
                styles.left = cPos.left;
                styles.width = this.coords.width;
            }
            if (pos == 'left') {
                this.options.horizontal = 'left';
                styles.top = cPos.top;
                styles.left = cPos.left - this.coords.width;
                styles.height = this.coords.height;
            }
            if (pos == 'bottom') {
                this.options.vertical = 'down';
                styles.top = cPos.bottom;
                styles.left = cPos.left;
                styles.width = this.coords.width;
            }
            if (pos == 'right') {
                this.options.horizontal = 'right';
                styles.top = cPos.top;
                styles.left = cPos.right;
                styles.height = this.coords.height;
            }
            if (pos == 'center') {
                styles.top = cPos.bottom;
                styles.width = this.coords.width;
                styles.height = this.coords.height;
            }

            if (align == 'top') {
                styles.top = cPos.top;
            }
            if (align == 'bottom') {
                styles.top = cPos.top + cPos.height - this.coords.height
            }
            if (align == 'left') {
                styles.left = cPos.left;
            }
            if (align == 'right') {
                styles.left = cPos.left + cPos.width - this.coords.width
            }

            //IE hack for positioning layer
            if (Browser.Engine.trident) {
                styles.top += $(document.body).getStyle('margin-top').toInt();
                styles.left += $(document.body).getStyle('margin-left').toInt();
            }

            if ($type(pos) == 'array') {

                styles.top += pos[1];
                styles.left += pos[0];

                if (this.options.vertical) {
                    styles.width = this.coords.width;
                }
                if (this.options.horizontal) {
                    styles.height = this.coords.height;
                }
            }
            this.container.setStyles(styles);
            this.coords.top = styles.top;
            this.coords.left = styles.left;
            this.coords.bottom = styles.top + this.coords.height;
            this.coords.right = styles.left + this.coords.width;

            if (pos == 'center') {
                this.center(true);
            }

        } else {
            if ($type(pos) == 'array') {
                this.container.setStyles({
                    'top': pos[1],
                    'left': pos[0],
                    'position': 'absolute',
                    'zIndex': 3,
                    'width': this.coords.width,
                    'height': this.coords.height
                });
            } else if (pos == 'center') {
                if (this.options.modalTarget == null) {
                    this.container.setStyles({
                        'position': 'absolute',
                        'zIndex': 3,
                        'width': this.coords.width,
                        'height': this.coords.height
                    });
                }
                this.center();
            } else if (obj) {
                //multibox
                this.container.setStyles(obj);
            } else {
                if (this.options.modalTarget == null) {
                    this.container.setStyles({
                        'width': this.coords.width,
                        'height': this.coords.height
                    });
                }
            }
        }

    },

    center: function(control) {

        var container = $(this.options.container);
        var coords = container.getCoordinates();
        var top = coords.top + (coords.height / 2) - (this.coords.height / 2);
        var left = coords.left + (coords.width / 2) - (this.coords.width / 2);

        if (this.options.modalTarget && this.content) {
            var contentCoords = this.content.getCoordinates();
            coords = this.container.getCoordinates();
            top = (coords.height / 2) - (contentCoords.height / 2);
            left = (coords.width / 2) - (contentCoords.width / 2);
        }

        //IE hack for positioning layer
        if (Browser.Engine.trident) {
            top += $(document.body).getStyle('margin-top').toInt();
            left += $(document.body).getStyle('margin-left').toInt();
        }

        if (this.options.modalTarget) {
            if (this.content) {
                if (this.options.center == 'horizontal') {
                    this.content.setStyles({ 'left': left });
                }
                if (this.options.center == 'vertical') {
                    this.content.setStyles({ 'top': top });
                }
                if (this.options.center == 'both') {
                    this.content.setStyles({ 'top': top, 'left': left });
                }
            }
        } else {
            if (this.options.center == 'horizontal') {
                this.container.setStyles({ 'left': left });
            }
            if (this.options.center == 'vertical') {
                this.container.setStyles({ 'top': top });
            }
            if (this.options.center == 'both') {
                this.container.setStyles({ 'top': top, 'left': left });
            }
        }


    },

    show: function() {
        this.doHide = false;
        if (this.frame) {
            this.frame.show();
        }

        if (this.shadow) {
            this.shadow.resize();
        }

        this.inProgress = true;

        var myFx = {};
        var styles = {};

        if (this.options.vertical) {
            myFx['height'] = [0, this.coords.height];
            if (this.options.slide) { styles.height = 0; } else { styles.height = this.coords.height }
            if (this.options.vertical == 'up') {
                myFx['top'] = [this.coords.top + this.coords.height, this.coords.top];
            }
        } else if (this.options.multibox) {
            myFx['height'] = this.options.initialHeight;
            myFx['top'] = (window.getCoordinates().height / 2) - (this.options.initialHeight / 2);
        } else {
            styles.height = this.coords.height;
        }

        if (this.options.horizontal) {
            myFx['width'] = [0, this.coords.width];
            if (this.options.slide) { styles.width = 0; } else { styles.width = this.coords.width }
            if (this.options.horizontal == 'left') {
                myFx['left'] = [this.coords.right, this.coords.left];
            }
        } else if (this.options.multibox) {
            myFx['width'] = this.options.initialWidth;
            myFx['left'] = (window.getCoordinates().width / 2) - (this.options.initialWidth / 2);
        } else {
            styles.width = this.coords.width;
        }

        if (!this.options.slide && this.options.fade && !this.options.multibox) {
            var myFx = {};
        }

        if (this.options.fade) {
            styles.opacity = 0;
            myFx['opacity'] = [0, 1];
        }
        styles.display = 'block';

        this.options.OnShow();

        this.container.setStyles(styles);

        if (!this.options.slide && !this.options.fade && !this.options.multibox) {
            this.fx.container.fireEvent('complete');
        } else {
            this.fx.container.start(myFx);
        }


        /*if(this.options.slide){
        this.fx.container.start(myFx);
        }else{
        this.fx.container.fireEvent('complete');
        }

        if (this.options.fade) {
        this.fx.layer.start('opacity', 0, 1);
        }else{
        this.fx.layer.fireEvent('complete');
        }*/
        if (this.overlay) {
            this.overlay.setStyle('display', 'block');
            this.fx.overlay.start('opacity', 0, this.options.opacity);
        }

        if ((this.frame && !this.options.modal) || this.shadow) {
            this.contentHeight = this.container.getCoordinates().height;
            //this.frameTimer = (function(){this.checkDimensions(); }).periodical(150, this);
            this.frameTimer = (function() { this.checkDimensions(); }).delay(this.options.duration, this);
        }
    },

    hide: function(obj) {
        this.doHide = true;
        this.doBlur = false;
        this.inProgress = true;
        var myFx = {};
        var coords = this.layerRef.getCoordinates();

        window.removeEvent('resize', this.resize.bind(this));

        if (this.frameTimer) {
            $clear(this.frameTimer);
        }

        if (!this.options.multibox) {
            this.container.setStyles({
                'overflow': 'hidden',
                'width': coords.width,
                'height': coords.height
            });
        }

        if (this.options.vertical) {
            myFx['height'] = 0;
            if (this.options.vertical == 'up') {
                myFx['top'] = this.coords.bottom;
            }
        }
        if (this.options.horizontal) {
            myFx['width'] = 0;
            if (this.options.horizontal == 'left') {
                myFx['left'] = this.coords.right;
            }
        }
        if (this.options.multibox) {
            /*myFx['width'] = [this.container.getStyle('width'),0];
            myFx['height'] = [this.container.getStyle('height'),0];
            myFx['top'] = this.coords.top;
            myFx['left'] = this.coords.left;*/
            myFx['width'] = obj.width;
            myFx['height'] = obj.height;
            myFx['top'] = obj.top;
            myFx['left'] = obj.left;
        }

        if (this.options.slide || this.options.multibox) {
            this.fx.container.start(myFx);
        } else if (this.options.fade) {
            this.fx.container.fireEvent('complete', this, this.options.duration);
        } else {
            this.fx.container.fireEvent('complete');
        }

        this.options.OnHide();

        if (this.options.fade) {
            this.fx.layer.start('opacity', 0);
        } else {
            this.fx.layer.fireEvent('complete');
        }
        if (this.overlay) {
            this.fx.overlay.cancel();
            this.fx.overlay.start('opacity', 0);
        }

    },

    createDropshadow: function() {
        return new Element('div', {
            'class': 'ezLayer-upperRight'
        }).wraps(
		new Element('div', {
		    'class': 'ezLayer-lowerLeft'
		}).wraps(
		new Element('div', {
		    'class': 'ezLayer-shadow'
		}).wraps(
		new Element('div', {
		    'class': 'ezLayer-wrapper'
		}).wraps(this.layer)
		)))
    },

    createShadow: function() {
        var num = this.options.shadowSize;
        var padding = '';
        if (this.options.shadow == 'glow') {
            padding = num + 'px'
        }
        if (this.options.shadow == 'drop') {
            padding = '0px ' + num + 'px ' + num + 'px 0px';
        }
        var div = new Element('div', {
            'class': 'ezLayerShadow'
        }).wraps(
		new Element('div', {
		    'class': 'ezLayerWrapper',
		    'styles': {
		        'padding': padding
		    }
		}).wraps(this.layer)
		);
        this.shadow = new canvasBox({
            shadowType: this.options.shadow,
            shadowBlur: num,
            container: div,
            size: this.coords
        });
        return div;
    },

    checkDimensions: function() {
        if (this.contentHeight != this.container.getCoordinates().height) {
            this.contentHeight = this.container.getCoordinates().height;
            if (this.frame) {
                this.updateFrameDimensions();
            }
            if (this.shadow) {
                this.shadow.options.size = this.container.getCoordinates();
                this.shadow.resize();
            }
        }
        this.frameTimer = this.checkDimensions.delay(150, this);
    }

});


/*************************************************************
Class:		datePicker
Version:	1.0
Author:		Samuel Birch
Status:		dev
*************************************************************/
/*
Usage:
	
*/
var datePicker = new Class({

    Implements: [Options, Events],

    getOptions: function() {
        return {
            classname: 'calendar',
            format: 'yyyy/mm/dd', //  dd/mm/yyyy  yyyy/mm/dd  dd-mm-yyyy  yyyy-mm-dd  dd/mm/yy  dd-mm-yy  mm/dd/yyyy  mm-dd-yyyy
            range: null, // [min, max]
            blockedDates: null, // []
            blockedDays: null, // ['sat', 'sun']
            toggleClear: true,
            input: null,
            container: null,
            width: 170,
            height: 162,
            headerHeight: 22,
            OnSelect: $empty,
            position: 'right'
        };
    },

    initialize: function(options) {
        this.setOptions(this.getOptions(), options);
        this.ref = 'calIcon_' + $time();
        this.container = new Element('div', { 'class': this.options.classname + 'Container' });
        //this.container.inject(document.body);
        if (this.options.container) {
            this.container.inject($(this.options.container));
        }

        this.header = new Element('div', { 'class': this.options.classname + 'Header' }).inject(this.container);

        this.prevArrow = new Element('span', { 'class': 'left' }).inject(this.header);
        this.prevArrow.addEvent('click', this.previous.bind(this));

        this.titleHolder = new Element('span', { 'class': 'title' }).inject(this.header);
        this.titleHolder.addEvent('click', this.showPanel.bind(this));

        this.nextArrow = new Element('span', { 'class': 'right' }).inject(this.header);
        this.nextArrow.addEvent('click', this.next.bind(this));

        this.headerHeight = this.options.headerHeight;

        this.input = $(this.options.input);

        if (this.input) {
            //create icon...
            this.icon = new Element('span', {
                'class': this.options.classname + 'Icon',
                'id': this.ref,
                'html': '&nbsp;'
            }).inject(this.input, 'after');
            this.icon.addEvent('click', this.toggle.bind(this, false));
            this.input.set('readOnly', true);
            this.input.addEvent('focus', this.toggle.bind(this, false));
            this.container.setStyle('display', 'none').inject(document.body);
        }

        this.today = new Date();
        this.currentDate = this.today.getFirstDay();

        if (this.options.blockedDates) {
            this.options.blockedDates.each(function(el, i) {
                this.options.blockedDates[i] = this.today.parse(el).format('yyyy/mm/dd');
            }, this);
        }
        if (this.options.range) {
            this.options.range.each(function(el, i) {
                this.options.range[i] = this.today.parse(el);
            }, this);
        }
        if (this.options.container) {
            this.show();
        }
    },

    createCalendarDates: function(date) {

        date = date.clearTime();
        var firstDay = date.getFirstDay();
        var monthName = firstDay.getFullMonthName();
        var fullYear = firstDay.getFullYear();
        var startDate = firstDay.getPreviousDay('mon');

        this.title = monthName + ' ' + fullYear;
        this.shownDate = date;
        this.panel = 'month';

        var div = new Element('div', { 'class': this.options.classname });
        var table = new Element('table', { 'cellspacing': 1, 'class': 'date' }).inject(div);

        var body = new Element('tbody').inject(table);

        var head = new Element('tr').inject(body);
        new Element('th', { 'text': 'Mon', 'scope': 'col' }).inject(head);
        new Element('th', { 'text': 'Tue', 'scope': 'col' }).inject(head);
        new Element('th', { 'text': 'Wed', 'scope': 'col' }).inject(head);
        new Element('th', { 'text': 'Thu', 'scope': 'col' }).inject(head);
        new Element('th', { 'text': 'Fri', 'scope': 'col' }).inject(head);
        new Element('th', { 'text': 'Sat', 'scope': 'col' }).inject(head);
        new Element('th', { 'text': 'Sun', 'scope': 'col' }).inject(head);

        //var body = new Element('tbody').inject(table);
        var count = 0;
        var row = 1;
        for (var i = 0; i < 6; i++) {
            var tr = new Element('tr', { 'class': 'row' + row }).inject(body);
            for (var j = 0; j < 7; j++) {
                var classname = '';

                if (startDate.isBeforeMonth(date)) {
                    classname += ' past';
                }
                if (startDate.isAfterMonth(date)) {
                    classname += ' future';
                }
                if (startDate.isSame(startDate.today())) {
                    classname += ' today';
                }
                if (this.selected) {
                    if (startDate.isSame(this.selected)) {
                        classname += ' selected';
                    }
                }
                if (this.options.blockedDates) {
                    if (this.options.blockedDates.contains(startDate.format('yyyy/mm/dd'))) {
                        classname += ' blocked';
                    }
                }
                if (this.options.range) {
                    if (startDate.isBefore(this.options.range[0]) || startDate.isAfter(this.options.range[1])) {
                        classname += ' blocked';
                    }
                }
                if (this.options.blockedDays) {
                    if (this.options.blockedDays.contains(startDate.getShortDayName().toLowerCase())) {
                        classname += ' blocked';
                    }
                }

                var el = new Element('td', {
                    'text': startDate.getDate(),
                    'class': classname
                }).inject(tr);
                //el.addEvent('click', this.selectDate.bind(this, startDate));
                if (!el.hasClass('blocked')) {
                    el.addEvent('click', this.selectDate.bind(this, startDate));
                }

                startDate = startDate.addDay();
            }
            row++;
        }
        return div;
    },

    createCalendarMonths: function(date) {

        date = date.clearTime();
        var fullYear = date.getFullYear();

        this.title = fullYear;
        this.shownDate = date;
        this.panel = 'year';

        var div = new Element('div', { 'class': this.options.classname });
        var table = new Element('table', { 'cellspacing': 1, 'class': 'month' }).inject(div);
        var body = new Element('tbody').inject(table);

        //
        var count = 0;
        var row = 1;
        for (var i = 0; i < 3; i++) {
            var tr = new Element('tr', { 'class': 'row' + row }).inject(body);
            for (var j = 0; j < 4; j++) {
                var classname = '';

                if (this.selectedMonth) {
                    if (this.selectedYear == date.getFullYear()) {
                        if (this.selectedMonth == count) {
                            classname = 'selected';
                        }
                    }
                }
                var el = new Element('td', {
                    'text': date.shortMonthNames[count].capitalize(),
                    'class': classname
                }).inject(tr);
                el.addEvent('click', this.selectMonth.bind(this, count));
                count++;
            }
            row++;
        }
        return div;
    },

    createCalendarYears: function(date) {

        date = date.clearTime();

        var y = date.getFullYear() - new Date().getFullYear();
        var num = Math.floor(y / 12);

        startDate = new Date().addYears((num * 12)).addYears(-2);

        this.title = 'Years:';
        this.shownDate = date;
        this.panel = 'years';

        var div = new Element('div', { 'class': this.options.classname });
        var table = new Element('table', { 'cellspacing': 1, 'class': 'month' }).inject(div);

        var body = new Element('tbody').inject(table);
        var count = 0;
        var row = 1;
        for (var i = 0; i < 3; i++) {
            var tr = new Element('tr', { 'class': 'row' + row }).inject(body);
            for (var j = 0; j < 4; j++) {
                var classname = '';

                if (this.selectedYear) {
                    if (startDate.getFullYear() == this.selectedYear) {
                        classname = 'selected';
                    }
                }
                var el = new Element('td', {
                    'text': startDate.getFullYear(),
                    'class': classname
                }).inject(tr);
                el.addEvent('click', this.selectYear.bind(this, startDate.getFullYear()));
                startDate = startDate.addYear();
            }
            row++;
        }
        return div;
    },

    showMonth: function(date) {
        this.month = this.createCalendarDates(date).setStyles({
            'position': 'absolute',
            'top': this.headerHeight,
            'left': 0,
            'zIndex': 0
        }).inject(this.container);
        this.titleHolder.set('html', this.title);
    },

    showMonths: function(date, slide) {
        this.months = this.createCalendarMonths(date).setStyles({
            'position': 'absolute',
            'top': -(this.options.height),
            'left': 0,
            'zIndex': 2
        }).inject(this.container);
        this.titleHolder.set('html', this.title);

        if (slide) {
            new Fx.Tween(this.months, {
                onComplete: function() { this.month.setStyle('display', 'none'); } .bind(this)
            }).start('top', -(this.options.height), this.headerHeight);
        } else {
            this.months.setStyle('top', this.headerHeight);
        }
    },

    showYears: function(date) {
        this.years = this.createCalendarYears(date).setStyles({
            'position': 'absolute',
            'top': -(this.options.height),
            'left': 0,
            'zIndex': 3
        }).inject(this.container);
        this.titleHolder.set('html', this.title);

        new Fx.Tween(this.years, {
            onComplete: function() { this.months.setStyle('display', 'none'); } .bind(this)
        }).start('top', -(this.options.height), this.headerHeight);
    },

    hideMonths: function() {
        this.month.setStyle('display', 'block');
        new Fx.Tween(this.months, {
            onComplete: function() {
                this.months.destroy();
            } .bind(this)
        }).start('top', this.headerHeight, -(this.options.height));
    },

    hideYears: function() {
        this.months.setStyle('display', 'block');
        new Fx.Tween(this.years, {
            onComplete: function() {
                this.years.destroy();
            } .bind(this)
        }).start('top', this.headerHeight, -(this.options.height));
    },

    toggle: function(date) {
        if (this.showing) {
            this.hide();
        } else {
            this.show(date);
        }
    },

    show: function(date) {
        this.showing = true;
        if (this.months) {
            this.months.destroy();
        }
        if (this.years) {
            this.years.destroy();
        }

        if (!date && this.input) {
            date = this.input.get('value');
        }
        if (date) {
            if ($type(date) == 'string') {
                date = new Date().parse(date, this.options.format);
            }
            this.selected = date.clearTime();
            this.selectedMonth = this.selected.getMonth();
            this.selectedYear = this.selected.getFullYear();
        } else {
            date = new Date().today();
        }

        this.currentDate = date.getFirstDay();
        this.showMonth(date);

        if (this.input) {

            layers.show(this.container, {
                control: this.ref,
                fade: true,
                position: this.options.position,
                dropshadow: true,
                closeOnBlur: true,
                OnHide: function() { this.showing = false } .bind(this)
            });
        }

    },

    hide: function() {
        this.showing = false;
        if (this.input) {
            layers.hide(this.container);
        }
    },

    next: function() {
        if (this.panel == 'month') {
            this.nextMonth();
        }
        if (this.panel == 'year') {
            this.nextYear();
        }
        if (this.panel == 'years') {
            this.nextYears();
        }
    },

    previous: function() {
        if (this.panel == 'month') {
            this.previousMonth();
        }
        if (this.panel == 'year') {
            this.previousYear();
        }
        if (this.panel == 'years') {
            this.previousYears();
        }
    },

    showPanel: function() {
        if (this.panel == 'month') {
            this.showMonths(this.shownDate, true);
        } else if (this.panel == 'year') {
            this.showYears(this.shownDate);
        }
    },

    nextMonth: function() {
        this.currentDate = this.currentDate.addMonths(1);
        var newCal = this.createCalendarDates(this.currentDate).setStyles({
            'position': 'absolute',
            'top': this.headerHeight,
            'left': this.options.width,
            'zIndex': 0
        }).inject(this.container);
        this.titleHolder.set('html', this.title);

        new Fx.Tween(this.month, {
            onComplete: function() {
                this.month.destroy();
            } .bind(this)
        }).start('left', 0, -(this.options.width));
        new Fx.Tween(newCal, {
            onComplete: function() {
                this.month = newCal;
            } .delay(600, this)
        }).start('left', this.options.width, 0);
    },

    previousMonth: function() {
        this.currentDate = this.currentDate.addMonths(-1);
        var newCal = this.createCalendarDates(this.currentDate).setStyles({
            'position': 'absolute',
            'top': this.headerHeight,
            'left': -(this.options.width),
            'zIndex': 0
        }).inject(this.container);
        this.titleHolder.set('html', this.title);

        new Fx.Tween(this.month, {
            onComplete: function() {
                this.month.destroy();
            } .bind(this)
        }).start('left', 0, this.options.width);
        new Fx.Tween(newCal, {
            onComplete: function() {
                this.month = newCal;
            } .delay(600, this)
        }).start('left', -(this.options.width), 0);
    },

    nextYear: function() {
        this.currentDate = this.currentDate.addYears(1);
        var newCal = this.createCalendarMonths(this.currentDate).setStyles({
            'position': 'absolute',
            'top': this.headerHeight,
            'left': this.options.width,
            'zIndex': 2
        }).inject(this.container);
        this.titleHolder.set('html', this.title);

        new Fx.Tween(this.months, {
            onComplete: function() {
                this.months.destroy();
            } .bind(this)
        }).start('left', 0, -(this.options.width));
        new Fx.Tween(newCal, {
            onComplete: function() {
                this.months = newCal;
            } .delay(600, this)
        }).start('left', this.options.width, 0);
    },

    previousYear: function() {
        this.currentDate = this.currentDate.addYears(-1);
        var newCal = this.createCalendarMonths(this.currentDate).setStyles({
            'position': 'absolute',
            'top': this.headerHeight,
            'left': -(this.options.width),
            'zIndex': 2
        }).inject(this.container);
        this.titleHolder.set('html', this.title);

        new Fx.Tween(this.months, {
            onComplete: function() {
                this.months.destroy();
            } .bind(this)
        }).start('left', 0, this.options.width);
        new Fx.Tween(newCal, {
            onComplete: function() {
                this.months = newCal;
            } .delay(600, this)
        }).start('left', -(this.options.width), 0);
    },

    nextYears: function() {
        this.currentDate = this.currentDate.addYears(12);
        var newCal = this.createCalendarYears(this.currentDate).setStyles({
            'position': 'absolute',
            'top': this.headerHeight,
            'left': this.options.width,
            'zIndex': 3
        }).inject(this.container);

        new Fx.Tween(this.years, {
            onComplete: function() {
                this.years.destroy();
            } .bind(this)
        }).start('left', 0, -(this.options.width));
        new Fx.Tween(newCal, {
            onComplete: function() {
                this.years = newCal;
            } .delay(600, this)
        }).start('left', this.options.width, 0);
    },

    previousYears: function() {
        this.currentDate = this.currentDate.addYears(-12);
        var newCal = this.createCalendarYears(this.currentDate).setStyles({
            'position': 'absolute',
            'top': this.headerHeight,
            'left': -(this.options.width),
            'zIndex': 3
        }).inject(this.container);

        new Fx.Tween(this.years, {
            onComplete: function() {
                this.years.destroy();
            } .bind(this)
        }).start('left', 0, this.options.width);
        new Fx.Tween(newCal, {
            onComplete: function() {
                this.years = newCal;
            } .delay(600, this)
        }).start('left', -(this.options.width), 0);
    },

    selectDate: function(date) {
        //console.log(date);
        if (this.input) {
            if (this.options.toggleClear) {
                if (this.input.get('value') == date.format(this.options.format)) {
                    this.input.set('value', '');
                    this.selected = null;
                } else {
                    this.input.set('value', date.format(this.options.format));
                }
            } else {
                this.input.set('value', date.format(this.options.format));
            }
        }
        this.hide();
        if (this.options.OnSelect) {
            this.options.OnSelect();
        }
    },

    selectMonth: function(date) {
        //console.log(date);
        this.month.destroy();
        this.currentDate.setMonth(date);
        this.selectedMonth = date;
        this.showMonth(this.currentDate);
        this.hideMonths();
    },

    selectYear: function(date) {
        //console.log(date);
        this.months.destroy();
        this.currentDate.setFullYear(date);
        this.selectedMonth = null;
        this.selectedYear = date;
        this.showMonths(this.currentDate);
        this.hideYears();
    }

});


/*************************************************************
date prototypes
Version:	1.0
Author:		Samuel Birch
Status:		dev
*************************************************************/

Date.implement({
    'parse': function(str, format) {
    	
    	var s = '-';
    	
    	if(format.indexOf('/') > 0){
    		s = '/';
    	}
    	
    	var f = format.split(s);
    	var d = str.split(s);
    	
    	var dd;
    	var mm;
    	var yy;
    	
    	for(var i=0; i<f.length; i++){
    		var el = f[i].substr(0,1);
    		if(el == 'd'){
    			dd = d[i];
    		}
    		if(el == 'm'){
    			mm = d[i];
    		}
    		if(el == 'y'){
    			yy = d[i];
    		}
    	}
    	
    	var date = new Date(yy+'/'+mm+'/'+dd);
    	
       // var date = new Date(str);
        var valid = false;
        this.dateFormats.each(function(el) {
            if (str == date.format(el)) {
                //console.log('match: '+el);
                valid = true;
            }
        });
        if (!valid) {
            var sep = '';
            if (str.contains('/')) {
                sep = '/';
            }
            if (str.contains('-')) {
                sep = '-';
            }

            var a = str.split(sep);
            if (a[0].length == 4) {
                return new Date(a[0] + '/' + a[1] + '/' + a[2]);
            } else {
                if (a[2].length == 2) {
                    a[2] = '20' + a[2];
                }
                return new Date(a[2] + '/' + a[1] + '/' + a[0]);
            }
        } else {
            return date;
        }
    },
    'format': function(format) {
        var dd = this.getDate().toString();
        var mm = (this.getMonth() + 1).toString();
        var yyyy = this.getFullYear().toString();
        var yy = yyyy.substr(2);

        if (dd.length == 1) { dd = '0' + dd }
        if (mm.length == 1) { mm = '0' + mm }

        //console.log(yy);

        format = format.replace('dd', dd);
        format = format.replace('mm', mm);
        format = format.replace('yyyy', yyyy);
        format = format.replace('yy', yy);

        return format;
    },
    'today': function() {
        return new Date().clearTime();
    },
    'getFirstDay': function() {
        return new Date(this.getFullYear() + '/' + (this.getMonth() + 1) + '/1');
    },
    'clone': function() {
        return new Date(this);
    },
    'addDay': function() {
        return this.addDays(1);
    },
    'addDays': function(num) {
        if (!num) { num = 0 }
        return new Date(this.getFullYear() + '/' + (this.getMonth() + 1) + '/' + (this.getDate() + num));
    },
    'addMonth': function() {
        return this.addMonths(1);
    },
    'addMonths': function(num) {
        if (!num) { num = 0 }
        return new Date(this.getFullYear() + '/' + (this.getMonth() + 1 + num) + '/' + this.getDate());
    },
    'addYear': function() {
        return this.addYears(1);
    },
    'addYears': function(num) {
        if (!num) { num = 0 }
        return new Date((this.getFullYear() + num) + '/' + (this.getMonth() + 1) + '/' + this.getDate());
    },
    'isBeforeMonth': function(date) {
        if (this.getFirstDay() < date.getFirstDay()) {
            return true;
        } else {
            return false;
        }
    },
    'isAfterMonth': function(date) {
        if (this.getFirstDay() > date.getFirstDay()) {
            return true;
        } else {
            return false;
        }
    },
    'isBefore': function(date) {
        if (this.getTime() < date.getTime()) {
            return true;
        } else {
            return false;
        }
    },
    'isAfter': function(date) {
        if (this.getTime() > date.getTime()) {
            return true;
        } else {
            return false;
        }
    },
    'isSame': function(date) {
        if (this.getTime() == date.getTime()) {
            return true;
        } else {
            return false;
        }
    },
    'getPreviousDay': function(day) {
        if (day) {
            day = this.getDayFromName(day);
            var date = this;
            if (date.getDay() != day) {
                do {
                    date = date.addDays(-1);
                } while (date.getDay() != day);
            }
            return date;
        } else {
            return this.addDays(-1);
        }
    },
    'getDayFromName': function(name) {
        name = name.toLowerCase();
        if (this.fullDayNames.contains(name)) {
            return this.fullDayNames.indexOf(name);
        }
        if (this.shortDayNames.contains(name)) {
            return this.shortDayNames.indexOf(name);
        }
    },
    'getFullDayName': function() {
        return this.fullDayNames[this.getDay()].capitalize();
    },
    'getShortDayName': function() {
        return this.shortDayNames[this.getDay()].capitalize();
    },
    'getFullMonthName': function() {
        return this.fullMonthNames[this.getMonth()].capitalize();
    },
    'getShortMonthName': function() {
        return this.shortMonthNames[this.getMonth()].capitalize();
    },
    'clearTime': function() {
        return new Date(this.getFullYear() + '/' + (this.getMonth() + 1) + '/' + this.getDate());
    },
    'fullDayNames': ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'],
    'shortDayNames': ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
    'fullMonthNames': ['january', 'febuary', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'],
    'shortMonthNames': ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'],
    'dateFormats': ['dd/mm/yyyy', 'dd/mm/yy', 'yyyy/mm/dd', 'dd-mm-yyyy', 'dd-mm-yy', 'yyyy-mm-dd', 'mm/dd/yyyy', 'mm-dd-yyyy']
});
