window.addEvent('domready', function() {

    // if there are datepicker on the page
    if (window.htmlform_initialize_datepicker) {

        // make them visible
        htmlform_initialize_datepicker();

    }

    // find all forms in page
    $$('.HTMLForm').each(function(form) {

        // find all dummy options (created when creating nested option groups for select boxes)
        form.getElements('option.dummy').each(function(option) {

            // remove them from the DOM
            // (we need them to create valid HTML/XHTML output as empty option groups are not allowed but IE does not
            // support neither the "disabled" attribute on options nor styling them)
            option.dispose();

        });

        form.getElements('div.fileinput').each(function(container) {

            var file_control = container.getElement('input.file');

            var text_control = container.getElement('input.text');

            file_control.addEvent('change', function() {

                text_control.value = this.value;

            });

        });

        // if custom styling is not disabled
        if (!form.hasClass('HTMLForm-noStyling')) {

            // find all checkbox and radio controls and iterate through them
            form.getElements('input.checkbox, input.radio').each(function(selectable) {

                // create a copy of the original checbox/radio button control
                // from now on, we will work only with this element as in the end we will delete the original element
                // from the DOM and we will replace it with our styled one
                var copy = selectable.clone(true, true);

                // create a new div element and assign an id to it (we will need this id later on)
                // the ID of the newly created div will be whatever the checkbox/radio button's name plus the
                // '_replacement' suffix
                var newElem = new Element('div', {id: copy.get('id') + '_replacement'});

                // if the control is a checbox
                if (copy.get('type') == 'checkbox') {

                    // set the appropriate class for our newly created div (checkes/not checked)
                    newElem.set('class', (copy.checked ? 'checkbox-checked' : 'checkbox-not-checked'));

                    // add an event to our newly created div
                    newElem.addEvent('click', function() {

                        // update the original's control state
                        copy.checked = (copy.checked ? false : true);

                        // update the class of our replacement div
                        newElem.set('class', (copy.checked ? 'checkbox-checked' : 'checkbox-not-checked'));

                    });

                    // if there's a label attached to the checkbox
                    form.getElements('label[for=' + copy.get('id') + ']').each(function(label) {

                        // add an event to the label control
                        label.addEvent('click', function() {

                            // simply fire the same event as when clicking on our styled div
                            newElem.fireEvent('click');

                        });

                    });

                // if the control is a radio control
                } else {

                    // set the appropriate class for our newly created div (selected/not selected)
                    newElem.set('class', (copy.checked ? 'radio-selected' : 'radio-not-selected'));

                    // add an event to our newly created div
                    newElem.addEvent('click', function() {

                        // update the original control's state
                        copy.checked = true;

                        // iterate through all the radio buttons with the same name
                        form.getElements('input[name=' + copy.get('name') + ']').each(function(radio) {

                            // and update their respective replacements according to the original control's state
                            $(radio.get('id') + '_replacement').set('class', (radio.checked ? 'radio-selected' : 'radio-not-selected'));

                        });

                    });

                    // if there's a label attached to the radio button
                    form.getElements('label[for=' + copy.get('id') + ']').each(function(label) {

                        // add an event to the label control
                        label.addEvent('click', function() {

                            // simply fire the same event as when clicking on our styled div
                            newElem.fireEvent('click');

                        });

                    });

                }

                // final preparation - we set some styles for the newly created div
                newElem.setStyles({

                    display:    'block',
                    float:      'left'

                });

                // replace the original controls
                newElem.replaces(selectable);

                // we now need to inject back the saved original control so that the form still works
                // first, set some styles
                copy.setStyles({

                    position:   'absolute',
                    visibility: 'hidden'

                });

                // inject the control into the DOM
                copy.inject(newElem, 'after');

            });

        }

        // iterate through all the submit buttons
        form.getElements('input.submit').each(function(button) {

            // get the file upload control(s), the "upload" button is attached to (if any)
            var file_controls = button.getProperty('alt');

            // if such controls exist
            if (null != file_controls) {

                // if all the file upload controls are to be replaced when the submit button is clicked
                if (file_controls == '*') {

                    // get all the file upload controls
                    file_controls = form.getElements('input.file');

                // if only specific file upload controls are to be replaced when the submit button is clicked
                } else {

                    // if more than one file upload control was specified,
                    // split by comma and make an array
                    file_controls = file_controls.split(',');

                    var tmp = [];

                    // iterate through the names of the file upload controls
                    file_controls.each(function(item) {

                        // trim
                        item = item.replace(/\s+$/, '').replace(/^\s+/, '');

                        // if control exists in DOM
                        if ($(item)) {

                            // put it in our temporary array
                            tmp.push($(item));

                        }

                    });

                    // array of file upload controls that are to be replaced when the submit button is clicked
                    file_controls = tmp;

                }

                // iterate through the file upload controls that are to be replaced when the submit button is clicked
                file_controls.each(function(file_control) {

                    // get the dimensions of the file upload control
                    var coordinates = file_control.getCoordinates();

                    // create a div that will replace the file upload control while the file is uploading
                    var progress = new Element('div');

                    // set some style for the newly created div
                    // the div will appear in the place of the file upload control - which we will hide later
                    progress.setStyles({

                        left:       coordinates.left,
                        top:        coordinates.top,
                        width:      coordinates.width,
                        height:     coordinates.height,
                        display:    'none'

                    });

                    // set an id for the newly created control
                    progress.setProperty('id', file_control.getProperty('id') + 'progressindicator');

                    // set the class for the newly created div
                    progress.addClass('htmlform-progress-indicator');

                    // inject the newly created div after the file upload control
                    progress.inject(document.body, 'bottom');

                });

                // attach the "onclick" event to the submit button
                button.addEvent('click', function(e) {

                    // iterate through the file upload controls that are to be replaced when the submit button is clicked
                    file_controls.each(function(file_control) {

                        // hide the file upload control
                        file_control.style.visibility = 'hidden';

                        // show the progress bar
                        $(file_control.getProperty('id') + 'progressindicator').style.display = 'block';

                    });

                });

            }

        });

        var default_value = [];

        var password_controls = [];

        // iterate through all the controls in the form that have the "control" class attached to them
        form.getElements('.control').each(function(control) {

            // get the parent row for the control
            var parents = control.getParent('div.row');

            // if the control has the "default-value" class set
            if (

                (control.get('tag') != 'textarea' && control.getProperty('alt') != null && control.getProperty('alt') != '') ||

                (control.get('tag') == 'textarea' && control.getProperty('title') != null && control.getProperty('title') != '')

            ) {

                // save the control's default value (stored in the "alt" attribute of the control)
                default_value[control.getProperty('id')] = control.get('tag') != 'textarea' ? control.getProperty('alt') : control.getProperty('title');

                // by default, assume this is not a password control and therefore there's no dummy control
                var dummy_control = undefined;

                // if
                if (

                    // control's type is password
                    control.getProperty('type') == 'password'

                ) {

                    // create a dummy password control
                    // this control will be visible until it gets focus
                    // when it gets focus, it will hide itself and show the original password control
                    dummy_control = new Element('input', {type: 'text'});

                    // set some properties for the dummy control so that it will look exactly like the password control
                    dummy_control.setProperty('class', control.getProperty('class'));
                    dummy_control.set('style', control.get('style'));
                    dummy_control.setProperty('value', default_value[control.getProperty('id')]);

                    // if the dummy control doesn't have the "default-value" class
                    // (as password controls loose this after submit)
                    if (!dummy_control.hasClass('default-value')) {

                        // make sure it does
                        dummy_control.addClass('default-value');

                    }

                    // if the password control has any custom styles set
                    if (null != control.getProperty('style')) {

                        // set them to the dummy control too
                        // (as we want it to look exactly like the password control)
                        dummy_control.setProperty('style', control.getProperty('style'));

                    }

                    // hide the password control
                    control.style.display = 'none';

                    // show the dummy password control
                    dummy_control.inject(control, 'after');

                    // make a note that this control is actually a password control
                    password_controls[control.getProperty('id')] = true;

                }

            }

            // if a dummy control exists
            if (dummy_control != undefined) {

                // attach the focus event to the control
                dummy_control.addEvent('focus', function() {

                    // hide the dummy control
                    this.style.display = 'none';

                    // show the real password control
                    control.style.display = 'block';

                    // give focus to the real password control
                    control.focus();

                });

            }

            // attach some events to the control
            control.addEvents({

                // on focus
                'focus': function() {

                    // if control has a parent row
                    if (parents != undefined) {

                        // highlight the parent row
                        parents.addClass('hover');

                    }

                    // if
                    if (

                        // control has the "default-value" class set AND
                        control.hasClass('default-value') &&

                        // the control has a default value
                        undefined !== default_value[this.getProperty('id')]

                    ) {

                        // remove the "default-value" class
                        // making the control use only its own class
                        control.removeClass('default-value');

                        // empty the value of the control
                        control.value = '';

                    }

                },

                // when the control loses focus
                'blur': function() {

                    // if control has a parent row
                    if (parents != undefined) {

                        // remove highlight from the parent row
                        parents.removeClass('hover');

                    }

                    // if
                    if (

                        // there is a default value for the control AND
                        undefined !== default_value[this.getProperty('id')] &&

                        (

                            // the value of the control is an empty string OR
                            this.value == '' ||

                            // the value of the control is the control's default value
                            this.value == default_value[this.getProperty('id')]

                        )

                    ) {

                        // add the "default-value" class
                        control.addClass('default-value');

                        // set the default value as the control's value
                        control.value = default_value[this.getProperty('id')];

                        // if the control is a password control
                        if (undefined !== password_controls[this.getProperty('id')]) {

                            // hide the control
                            this.style.display = 'none';

                            // and show the dummy control
                            dummy_control.style.display = 'block';

                        }

                    }

                }

            });

        });

        // search for "select" controls having the "other" class and attach an event to each
        form.getElements('select.other').addEvent('change', function() {

            // if the text box for entering the "other" option exists
            if ($(this.getProperty('id') + '_other')) {

                // if the selected value is the "other" value
                if (this.value == 'other') {

                    // show the text box
                    $(this.getProperty('id') + '_other').style.display = 'block';

                // otherwise
                } else {

                    // hide the text box
                    $(this.getProperty('id') + '_other').style.display = 'none';

                }

            }

        });

        // iterate through all the controls in the form that suppose to have only numbers entered in them
        form.getElements('.numbersonly').each(function(control) {

            // attach the "keypress" event to the control
            control.addEvent('keypress', function(e) {

                // get the character code of the pressed key
                var charCode = e.code;

                // if pressed key is not
                if (

                    (

                    // backspace, tab
                    (charCode != 8 && charCode != 9) &&

                    // end, home, left, right
                    (charCode < 35 || charCode > 38) &&

                    // dot
                    (charCode != 46) &&

                    // minus
                    (charCode != 45) &&

                    // anything but 0 through 9
                    (charCode < 48 || charCode > 57)

                    ) || (

                        // dot but dot already exists
                        charCode == 46 && control.value.match(/\./) != null

                    ) || (

                        // minus sign but minus sign already exists
                        charCode == 45 && control.value.match(/\-/) != null

                    )

                ) {

                    // don't allow the key
                    return false;

                }

                // allow the pressed key
                return true;

            });

        });

        // iterate through all the controls in the form that suppose to have only digits entered in them
        form.getElements('.digitsonly').each(function(control) {

            // attach the "keypress" event to the control
            control.addEvent('keypress', function(e) {

                // get the character code of the pressed key
                var charCode = e.code;

                // if pressed key is not
                if (

                    // backspace, tab
                    (charCode != 8 && charCode != 9) &&

                    // end, home, left, right
                    (charCode < 35 || charCode > 38) &&

                    // anything else but 0 through 9
                    (charCode < 48 || charCode > 57)

                ) {

                    // don't allow the key
                    return false;

                }

                // allow the pressed key
                return true;

            });

        });

    });

});

var Calendar=new Class({Implements:[Options],options:{blocked:[],classes:[],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],direction:0,draggable:true,months:["January","February","March","April","May","June","July","August","September","October","November","December"],navigation:1,offset:0,onHideStart:Class.empty,onHideComplete:Class.empty,onShowStart:Class.empty,onShowComplete:Class.empty,pad:1,tweak:{x:0,y:0}},initialize:function(g,b){if(!g){return false}this.setOptions(b);var e=["calendar","prev","next","month","year","today","invalid","valid","inactive","active","hover","hilite"];var a=e.map(function(l,k){if(this.options.classes[k]){if(this.options.classes[k].length){l=this.options.classes[k]}}return l},this);this.classes=a.associate(e);this.calendar=new Element("div",{styles:{left:"-1000px",opacity:0,position:"absolute",top:"-1000px",zIndex:1000}}).addClass(this.classes.calendar).injectInside(document.body);if(window.ie6){this.iframe=new Element("iframe",{styles:{left:"-1000px",position:"absolute",top:"-1000px",zIndex:999}}).injectInside(document.body);this.iframe.style.filter="progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"}this.fx=new Fx.Tween(this.calendar,{onStart:function(){if(this.calendar.getStyle("opacity")==0){if(window.ie6){this.iframe.setStyle("display","block")}this.calendar.setStyle("display","block");this.fireEvent("onShowStart",this.element)}else{this.fireEvent("onHideStart",this.element)}}.bind(this),onComplete:function(){if(this.calendar.getStyle("opacity")==0){this.calendar.setStyle("display","none");if(window.ie6){this.iframe.setStyle("display","none")}this.fireEvent("onHideComplete",this.element)}else{this.fireEvent("onShowComplete",this.element)}}.bind(this)});if(window.Drag&&this.options.draggable){this.drag=new Drag.Move(this.calendar,{onDrag:function(){if(window.ie6){this.iframe.setStyles({left:this.calendar.style.left,top:this.calendar.style.top})}}.bind(this)})}this.calendars=[];var j=0;var h=new Date();h.setDate(h.getDate()+this.options.direction.toInt());for(var c in g){var f={button:new Element("button",{type:"button"}),el:$(c),els:[],id:j++,month:h.getMonth(),visible:false,year:h.getFullYear()};if(!this.element(c,g[c],f)){continue}f.el.addClass(this.classes.calendar);f.button.addClass(this.classes.calendar).addEvent("click",function(i){this.toggle(i)}.pass(f,this)).injectAfter(f.el);f.val=this.read(f);$extend(f,this.bounds(f));$extend(f,this.values(f));this.rebuild(f);this.calendars.push(f)}},blocked:function(c){var a=[];var e=new Date(c.year,c.month,1).getDay();var b=new Date(c.year,c.month+1,0).getDate();this.options.blocked.each(function(m){var h=m.split(" ");for(var n=0;n<=3;n++){if(!h[n]){h[n]=(n==3)?"":"*"}h[n]=h[n].contains(",")?h[n].split(","):new Array(h[n]);var o=h[n].length-1;for(var l=o;l>=0;l--){if(h[n][l].contains("-")){var p=h[n][l].split("-");for(var g=p[0];g<=p[1];g++){if(!h[n].contains(g)){h[n].push(g+"")}}h[n].splice(l,1)}}}if(h[2].contains(c.year+"")||h[2].contains("*")){if(h[1].contains(c.month+1+"")||h[1].contains("*")){h[0].each(function(i){if(i>0){a.push(i.toInt())}});if(h[3]){for(var n=0;n<b;n++){var f=(n+e)%7;if(h[3].contains(f+"")){a.push(n+1)}}}}}},this);return a},bounds:function(c){var e=new Date(1000,0,1);var a=new Date(2999,11,31);var b=new Date().getDate()+this.options.direction.toInt();if(this.options.direction>0){e=new Date();e.setDate(b+this.options.pad*c.id)}if(this.options.direction<0){a=new Date();a.setDate(b-this.options.pad*(this.calendars.length-c.id-1))}c.els.each(function(g){if(g.get("tag")=="select"){if(g.format.test("(y|Y)")){var f=[];g.getChildren().each(function(k){var j=this.unformat(k.value,g.format);if(!f.contains(j[0])){f.push(j[0])}},this);f.sort(this.sort);if(f[0]>e.getFullYear()){d=new Date(f[0],e.getMonth()+1,0);if(e.getDate()>d.getDate()){e.setDate(d.getDate())}e.setYear(f[0])}if(f.getLast()<a.getFullYear()){d=new Date(f.getLast(),a.getMonth()+1,0);if(a.getDate()>d.getDate()){a.setDate(d.getDate())}a.setYear(f.getLast())}}if(g.format.test("(F|m|M|n)")){var h=[];var i=[];g.getChildren().each(function(k){var j=this.unformat(k.value,g.format);if($type(j[0])!="number"||j[0]==f[0]){if(!h.contains(j[1])){h.push(j[1])}}if($type(j[0])!="number"||j[0]==f.getLast()){if(!i.contains(j[1])){i.push(j[1])}}},this);h.sort(this.sort);i.sort(this.sort);if(h[0]>e.getMonth()){d=new Date(e.getFullYear(),h[0]+1,0);if(e.getDate()>d.getDate()){e.setDate(d.getDate())}e.setMonth(h[0])}if(i.getLast()<a.getMonth()){d=new Date(e.getFullYear(),i.getLast()+1,0);if(a.getDate()>d.getDate()){a.setDate(d.getDate())}a.setMonth(i.getLast())}}}},this);return{start:e,end:a}},caption:function(h){var a={prev:{month:true,year:true},next:{month:true,year:true}};if(h.year==h.start.getFullYear()){a.prev.year=false;if(h.month==h.start.getMonth()&&this.options.navigation==1){a.prev.month=false}}if(h.year==h.end.getFullYear()){a.next.year=false;if(h.month==h.end.getMonth()&&this.options.navigation==1){a.next.month=false}}if($type(h.months)=="array"){if(h.months.length==1&&this.options.navigation==2){a.prev.month=a.next.month=false}}var b=new Element("caption");var f=new Element("a").addClass(this.classes.prev).appendText("\x3c");var e=new Element("a").addClass(this.classes.next).appendText("\x3e");if(this.options.navigation==2){var g=new Element("span").addClass(this.classes.month).injectInside(b);if(a.prev.month){f.clone().addEvent("click",function(i){this.navigate(i,"m",-1)}.pass(h,this)).injectInside(g)}g.adopt(new Element("span").appendText(this.options.months[h.month]));if(a.next.month){e.clone().addEvent("click",function(i){this.navigate(i,"m",1)}.pass(h,this)).injectInside(g)}var c=new Element("span").addClass(this.classes.year).injectInside(b);if(a.prev.year){f.clone().addEvent("click",function(i){this.navigate(i,"y",-1)}.pass(h,this)).injectInside(c)}c.adopt(new Element("span").appendText(h.year));if(a.next.year){e.clone().addEvent("click",function(i){this.navigate(i,"y",1)}.pass(h,this)).injectInside(c)}}else{if(a.prev.month&&this.options.navigation){f.clone().addEvent("click",function(i){this.navigate(i,"m",-1)}.pass(h,this)).injectInside(b)}b.adopt(new Element("span").addClass(this.classes.month).appendText(this.options.months[h.month]));b.adopt(new Element("span").addClass(this.classes.year).appendText(h.year));if(a.next.month&&this.options.navigation){e.clone().addEvent("click",function(i){this.navigate(i,"m",1)}.pass(h,this)).injectInside(b)}}return b},changed:function(a){a.val=this.read(a);$extend(a,this.values(a));this.rebuild(a);if(!a.val){return}if(a.val.getDate()<a.days[0]){a.val.setDate(a.days[0])}if(a.val.getDate()>a.days.getLast()){a.val.setDate(a.days.getLast())}a.els.each(function(b){b.value=this.format(a.val,b.format)},this);this.check(a);this.calendars.each(function(b){if(b.visible){this.display(b)}},this)},check:function(a){this.calendars.each(function(e,b){if(e.val){var f=false;if(b<a.id){var c=new Date(Date.parse(a.val));c.setDate(c.getDate()-(this.options.pad*(a.id-b)));if(c<e.val){f=true}}if(b>a.id){var c=new Date(Date.parse(a.val));c.setDate(c.getDate()+(this.options.pad*(b-a.id)));if(c>e.val){f=true}}if(f){if(e.start>c){c=e.start}if(e.end<c){c=e.end}e.month=c.getMonth();e.year=c.getFullYear();$extend(e,this.values(e));e.val=e.days.contains(c.getDate())?c:null;this.write(e);if(e.visible){this.display(e)}}}else{e.month=a.month;e.year=a.year}},this)},clicked:function(c,a,b){b.val=(this.value(b)==a)?null:new Date(b.year,b.month,a);this.write(b);if(!b.val){b.val=this.read(b)}if(b.val){this.check(b);this.toggle(b)}else{c.addClass(this.classes.valid);c.removeClass(this.classes.active)}},display:function(l){this.calendar.empty();this.calendar.className=this.classes.calendar+" "+this.options.months[l.month].toLowerCase();var m=new Element("div").injectInside(this.calendar);var t=new Element("table").injectInside(m).adopt(this.caption(l));var s=new Element("thead").injectInside(t);var b=new Element("tr").injectInside(s);for(var r=0;r<=6;r++){var f=this.options.days[(r+this.options.offset)%7];b.adopt(new Element("th",{title:f}).appendText(f.substr(0,1)))}var a=new Element("tbody").injectInside(t);var b=new Element("tr").injectInside(a);var v=new Date(l.year,l.month,1);var e=((v.getDay()-this.options.offset)+7)%7;var k=new Date(l.year,l.month+1,0).getDate();var n=new Date(l.year,l.month,0).getDate();var g=this.value(l);var p=l.days;var o=[];var h=[];this.calendars.each(function(z,y){if(z!=l&&z.val){if(l.year==z.val.getFullYear()&&l.month==z.val.getMonth()){o.push(z.val.getDate())}if(l.val){for(var x=1;x<=k;x++){v.setDate(x);if((y<l.id&&v>z.val&&v<l.val)||(y>l.id&&v>l.val&&v<z.val)){if(!h.contains(x)){h.push(x)}}}}}},this);var v=new Date();var u=new Date(v.getFullYear(),v.getMonth(),v.getDate()).getTime();for(var r=1;r<43;r++){if((r-1)%7==0){b=new Element("tr").injectInside(a)}var j=new Element("td").injectInside(b);var q=r-e;var w=new Date(l.year,l.month,q);var c="";if(q===g){c=this.classes.active}else{if(o.contains(q)){c=this.classes.inactive}else{if(p.contains(q)){c=this.classes.valid}else{if(q>=1&&q<=k){c=this.classes.invalid}}}}if(w.getTime()==u){c=c+" "+this.classes.today}if(h.contains(q)){c=c+" "+this.classes.hilite}j.addClass(c);if(p.contains(q)){j.setProperty("title",this.format(w,"D M jS Y"));j.addEvents({click:function(y,i,x){this.clicked(y,i,x)}.pass([j,q,l],this),mouseover:function(x,i){x.addClass(i)}.pass([j,this.classes.hover]),mouseout:function(x,i){x.removeClass(i)}.pass([j,this.classes.hover])})}if(q<1){q=n+q}else{if(q>k){q=q-k}}j.appendText(q)}},element:function(b,c,e){if($type(c)=="object"){for(var a in c){if(!this.element(a,c[a],e)){return false}}return true}b=$(b);if(!b){return false}b.format=c;if(b.get("tag")=="select"){b.addEvent("change",function(f){this.changed(f)}.pass(e,this))}else{b.readOnly=true;b.addEvent("focus",function(f){this.toggle(f)}.pass(e,this))}e.els.push(b);return true},format:function(c,q){var o="";if(c){var g=c.getDate();var r=c.getDay();var e=this.options.days[r];var b=c.getMonth()+1;var m=this.options.months[b-1];var p=c.getFullYear()+"";for(var h=0,k=q.length;h<k;h++){var a=q.charAt(h);switch(a){case"y":p=p.substr(2);case"Y":o+=p;break;case"m":if(b<10){b="0"+b}case"n":o+=b;break;case"M":m=m.substr(0,3);case"F":o+=m;break;case"d":if(g<10){g="0"+g}case"j":o+=g;break;case"D":e=e.substr(0,3);case"l":o+=e;break;case"N":r+=1;case"w":o+=r;break;case"S":if(g%10==1&&g!="11"){o+="st"}else{if(g%10==2&&g!="12"){o+="nd"}else{if(g%10==3&&g!="13"){o+="rd"}else{o+="th"}}}break;default:o+=a}}}return o},navigate:function(c,b,e){switch(b){case"m":if($type(c.months)=="array"){var a=c.months.indexOf(c.month)+e;if(a<0||a==c.months.length){if(this.options.navigation==1){this.navigate(c,"y",e)}a=(a<0)?c.months.length-1:0}c.month=c.months[a]}else{var a=c.month+e;if(a<0||a==12){if(this.options.navigation==1){this.navigate(c,"y",e)}a=(a<0)?11:0}c.month=a}break;case"y":if($type(c.years)=="array"){var a=c.years.indexOf(c.year)+e;c.year=c.years[a]}else{c.year+=e}break}$extend(c,this.values(c));if($type(c.months)=="array"){var a=c.months.indexOf(c.month);if(a<0){c.month=c.months[0]}}this.display(c)},read:function(c){var a=[null,null,null];c.els.each(function(g){var f=this.unformat(g.value,g.format);f.each(function(j,h){if($type(j)=="number"){a[h]=j}})},this);if($type(a[0])=="number"){c.year=a[0]}if($type(a[1])=="number"){c.month=a[1]}var e=null;if(a.every(function(f){return $type(f)=="number"})){var b=new Date(a[0],a[1]+1,0).getDate();if(a[2]>b){a[2]=b}e=new Date(a[0],a[1],a[2])}return(c.val==e)?null:e},rebuild:function(a){a.els.each(function(b){if(b.get("tag")=="select"&&b.format.test("^(d|j)$")){var c=this.value(a);if(!c){c=b.value.toInt()}b.empty();a.days.each(function(e){var f=new Element("option",{selected:(c==e),value:((b.format=="d"&&e<10)?"0"+e:e)}).appendText(e).injectInside(b)},this)}},this)},sort:function(e,c){return e-c},toggle:function(c){document.removeEvent("mousedown",this.fn);if(c.visible){c.visible=false;c.button.removeClass(this.classes.active);this.fx.start("opacity",1,0)}else{this.fn=function(j,i){var j=new Event(j);var h=j.target;var g=false;while(h!=document.body&&h.nodeType==1){if(h==this.calendar){g=true}this.calendars.each(function(k){if(k.button==h||k.els.contains(h)){g=true}});if(g){j.stop();return false}else{h=h.parentNode}}this.toggle(i)}.create({"arguments":c,bind:this,event:true});document.addEvent("mousedown",this.fn);this.calendars.each(function(g){if(g==c){g.visible=true;g.button.addClass(this.classes.active)}else{g.visible=false;g.button.removeClass(this.classes.active)}},this);var b=window.getScrollSize();var f=c.button.getCoordinates();var a=f.right+this.options.tweak.x;var e=f.top+this.options.tweak.y;if(!this.calendar.coord){this.calendar.coord=this.calendar.getCoordinates()}if(a+this.calendar.coord.width>b.x){a-=(a+this.calendar.coord.width-b.x)}if(e+this.calendar.coord.height>b.y){e-=(e+this.calendar.coord.height-b.y)}this.calendar.setStyles({left:a+"px",top:e+"px"});if(window.ie6){this.iframe.setStyles({height:this.calendar.coord.height+"px",left:a+"px",top:e+"px",width:this.calendar.coord.width+"px"})}this.display(c);this.fx.start("opacity",0,1)}},unformat:function(b,l){l=l.escapeRegExp();var n={d:"([0-9]{2})",j:"([0-9]{1,2})",D:"("+this.options.days.map(function(c){return c.substr(0,3)}).join("|")+")",l:"("+this.options.days.join("|")+")",S:"(st|nd|rd|th)",F:"("+this.options.months.join("|")+")",m:"([0-9]{2})",M:"("+this.options.months.map(function(c){return c.substr(0,3)}).join("|")+")",n:"([0-9]{1,2})",Y:"([0-9]{4})",y:"([0-9]{2})"};var j=[];var k="";for(var e=0;e<l.length;e++){var m=l.charAt(e);if(n[m]){j.push(m);k+=n[m]}else{k+=m}}var h=b.match("^"+k+"$");var a=new Array(3);if(h){h=h.slice(1);j.each(function(g,f){f=h[f];switch(g){case"y":f="19"+f;case"Y":a[0]=f.toInt();break;case"F":f=f.substr(0,3);case"M":f=this.options.months.map(function(c){return c.substr(0,3)}).indexOf(f)+1;case"m":case"n":a[1]=f.toInt()-1;break;case"d":case"j":a[2]=f.toInt();break}},this)}return a},value:function(b){var a=null;if(b.val){if(b.year==b.val.getFullYear()&&b.month==b.val.getMonth()){a=b.val.getDate()}}return a},values:function(g){var e,a,j;g.els.each(function(i){if(i.get("tag")=="select"){if(i.format.test("(y|Y)")){e=[];i.getChildren().each(function(l){var k=this.unformat(l.value,i.format);if(!e.contains(k[0])){e.push(k[0])}},this);e.sort(this.sort)}if(i.format.test("(F|m|M|n)")){a=[];i.getChildren().each(function(l){var k=this.unformat(l.value,i.format);if($type(k[0])!="number"||k[0]==g.year){if(!a.contains(k[1])){a.push(k[1])}}},this);a.sort(this.sort)}if(i.format.test("(d|j)")&&!i.format.test("^(d|j)$")){j=[];i.getChildren().each(function(l){var k=this.unformat(l.value,i.format);if(k[0]==g.year&&k[1]==g.month){if(!j.contains(k[2])){j.push(k[2])}}},this)}}},this);var h=1;var f=new Date(g.year,g.month+1,0).getDate();if(g.year==g.start.getFullYear()){if(a==null&&this.options.navigation==2){a=[];for(var c=0;c<12;c++){if(c>=g.start.getMonth()){a.push(c)}}}if(g.month==g.start.getMonth()){h=g.start.getDate()}}if(g.year==g.end.getFullYear()){if(a==null&&this.options.navigation==2){a=[];for(var c=0;c<12;c++){if(c<=g.end.getMonth()){a.push(c)}}}if(g.month==g.end.getMonth()){f=g.end.getDate()}}var b=this.blocked(g);if($type(j)=="array"){j=j.filter(function(i){if(i>=h&&i<=f&&!b.contains(i)){return i}})}else{j=[];for(var c=h;c<=f;c++){if(!b.contains(c)){j.push(c)}}}j.sort(this.sort);return{days:j,months:a,years:e}},write:function(a){this.rebuild(a);a.els.each(function(b){b.value=this.format(a.val,b.format)},this)}});Calendar.implement(new Events,new Options);
