
/*

31.03.2009 (c) Klaus

Diese Klasse öffnet einen Kalender, der es erleichtert Datums einzugeben.

*/

var g_opencal = null;

var mooCalendar = new Class({
    Implements: Options,
    options: {
        targetelem: null,           // wo soll das ausgewählte datum reingeschrieben werden
        direction: 0,               // dürfen nur vergangene (-1) , alle (0) oder nur zükünftige (1) monate angezeigt werden
        dockelem: null,             // an diesem element wird das popup ausgerichtet, wenn gesetzt
        dockelempos: 'ru',          // an welcher ecke des zielelementes soll kalender ausgerichtet werden        
        mouseevent: null,           // an den klickkoordianten des events wird das popup ausgerichtet, wenn gesetzt
        xpos: 0,                    // die x-position des popups
        ypos: 0,                    // die y-position des popups
        xdelta: 0,                  // verschiebung in der x-achse (zu dockelem oder mouseevent)
        ydelta: 0,                  // verschiebung in der y-achse (zu dockelem oder mouseevent)
        popupcss: 'mooCal',         // das css des übergreifenden popup-containers für dieses popup (customizing)
        startyear: 0,               // mit welchem jahr soll das jahresdropdown beginnen
        endyear: 0,                 // mit welchem jahr soll das jahresdropdown enden
        selectedMonth: 0,           // der selektierte monat
        selectedYear: 0,            // das selektierte jahr
        navigationtype: 0,          // 0: navigation über dropdowns, 1: navigation über pfeile (todo!)
        dateformat: "dd.MM.yyyy",   // in welchem datumsformat soll das zielobjekt befüllt werden
        months: ["Januar", "Februar", "Maerz", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]  // die monate

    },
    /* constructor */
    initialize: function(options) {

        this.setOptions(options);

        if (g_opencal != null)
            g_opencal.clear();

        g_opencal = this;


        // speichere objekt im zielelement
        if (this.options.targetelem != null) {
            this.options.targetelem = $(this.options.targetelem);

            if (this.options.targetelem.retrieve('mooCal') != null) {
                this.options.targetelem.retrieve('mooCal').clear();
            }
            this.options.targetelem.store('mooCal', this);

        }

        if (this.options.dockelem != null) {
            this.options.dockelem.store('mooCal', this);
        }

        // erzeuge html des popups
        this.popupcon = this.createHtml();

        // füge popup in dombaum ein
        if (this.options.contentelem == null)
            $(document.body).adopt(this.popupcon);
        else
            $(document.body).getFirst().adopt(this.popupcon);   // asp.net elemente müssen im aspnet_form drin sein

        // setze event für schliessen-button
        this.getCloseElem().addEvent("click", function(ev) {
            var e = new Event(ev);
            var popupElem = e.target.getParent().getParent();
            popupElem.destroy();
        });

        // hole dropdowns
        this.ddyear = this.popupcon.getElement('.dropdownyear');
        this.ddmonth = this.popupcon.getElement('.dropdownmonth');
        this.ddyear.store('mooCal', this);
        this.ddmonth.store('mooCal', this);

        // ermittle die zielposition des popups
        this.setTargetPosition();

        // setze die position des popups gemäß zielposition
        this.setPosition();

        // initialisiere navigation
        this.prepareNavigation(0);

        // zeige ausgewählten monat
        this.showMonth();

        //        try {
        //            var myDragInstance = new Drag(this.popupcon, { handle: this.popupcon.getElement('.headline') });
        //        } catch (ex) { alert(ex.message); }

    },

    /* füllt dropdowns mit monaten und jahren */
    prepareNavigation: function(typenr) {

        if (this.options.navigationtype == 0) {

           

            // hole eventuell vorhandenes datum aus dem zielelement
            var d = this.evalDate(this.options.targetelem.value);

            // wenn keines gesetzt
            if (d == null) {
                // nimm aktuelles datum
                this.options.selectedYear = new Date().getFullYear();
                this.options.selectedMonth = new Date().getMonth();

            } else {
                
                this.options.selectedYear = d.getFullYear();
                this.options.selectedMonth = d.getMonth();
            }

            // setze das start und endjahr anhand der optionen
            if (this.options.startyear == 0)
                this.options.startyear = new Date().getFullYear() - 1;

            if (this.options.endyear == 0)
                this.options.endyear = this.options.startyear + 4;
                
            // fülle das dropdown mit den jahren
            var count = 0;
            for (var i = this.options.startyear; i <= this.options.endyear; i++) {
                var opt = document.createElement("option");
                opt.value = i;
                opt.text = i;
                this.ddyear.options[count] = opt;
                count++;

                if (i == this.options.selectedYear)
                    opt.selected = true;
            }

            // fülle das dropdown mit den monaten
            for (var i = 0; i < 12; i++) {
                var opt = document.createElement("option");
                opt.value = i;
                opt.text = this.options.months[i];
                this.ddmonth.options[i] = opt;

                if (i == this.options.selectedMonth)
                    opt.selected = true;
            }
            
            // was soll passieren wenn jahr-dropdown gewechselt wird
            this.ddyear.addEvent("change", function(ev) {

                var e = new Event(ev);
                var calobj = $(e.target).retrieve('mooCal');

                if (calobj != null) {
                    calobj.options.selectedYear = calobj.ddyear.options[calobj.ddyear.selectedIndex].value;
                    calobj.showMonth();
                }

            });

            // was soll passieren wenn jahr-dropdown gewechselt wird
            this.ddmonth.addEvent("change", function(ev) {

                var e = new Event(ev);
                var calobj = $(e.target).retrieve('mooCal');

                if (calobj != null) {
                    calobj.options.selectedMonth = calobj.ddmonth.options[calobj.ddmonth.selectedIndex].value;
                    calobj.showMonth();
                }

            });
        }

    },

    /* liest ein als string angegebenes datum aus und gibt ein date-objekt zurück */
    evalDate: function(datestr) {

    try {

            if (datestr.indexOf("/") >= 0) {            // MM/dd/yyyy
                var d = new Date();
                d.setDate(datestr);
            } else if (datestr.indexOf(".") >= 0) {     // dd.MM.yyyy

                var arrDate = datestr.split('.')
                var y = arrDate[2];
                var m = arrDate[1];
                var d = arrDate[0];
                return new Date(y, m - 1, d);
            }
        } catch (ex) {  return null; }
    },

    /* stellt die tage eines monats in kalenderform dar */
    showMonth: function() {


        var caldisplay = this.popupcon.getElement('.display');
        caldisplay.empty();

        var dm = new Date(this.options.selectedYear, this.options.selectedMonth, 1);

        var totaldays = this.getTotalDaysOfMonth(dm.getMonth(), dm.getFullYear());
        var firstday = this.getWeekNumber(dm.getDay());
        var currday = firstday;
        var wcount = 0;

        var row = new Element("div", { id: "day_row", 'class': 'rowdays' }); ;
        caldisplay.appendChild(row);

        for (var j = 0; j < firstday; j++) {
            var div = document.createElement("div");
            div.className = "day_other";
            div.innerHTML = "&nbsp;";
            row.appendChild(div);
        }

        for (var i = 1; i <= totaldays; i++) {

            var cssclass = "day_default";

            if (currday > 4)
                cssclass = "day_holiday";

            var daydiv = document.createElement("div");
            daydiv.className = cssclass;

            daydiv = $(daydiv);

            var d = new Date(this.getYear(), this.getMonth(), i);

            daydiv.innerHTML = i;
            row.appendChild(daydiv);
            daydiv.store("mooCal", this);
            daydiv.store("date", d);

            daydiv.addEvent('click', function(ev) {
                var e = new Event(ev);
                var calobj = $(e.target).retrieve('mooCal');
                calobj.exportDate($(e.target).retrieve('date'));
                calobj.clear();
            });

            if (currday == 6) {
                row = document.createElement("div");
                row.className = "rowdays";
                caldisplay.appendChild(row);
                currday = 0;
            }
            else {
                currday++;
            }

        }

    },

    /* gibt zurück wieviele tage ein monat hat. Schaltjahre werden berücksichtigt */
    getTotalDaysOfMonth: function(month, year) {
        if (month == 0 || month == 2 || month == 4 || month == 6 || month == 7 || month == 9 || month == 11)
            return 31;

        // februar
        if (month == 1) {
            // schaltjahr?
            if (year % 4 == 0)
                if (year % 100 > 0 || year % 400 == 0)
                return 29;

            return 28;
        }

        return 30;
    },

    /* gibt die zahl eines wochentages zurück gemäss date-objekt */
    getWeekNumber: function(numberOfDay) {
        if (numberOfDay == 0)
            return 6;
        else
            return --numberOfDay;

    },

    /* fügt eine 0 vor einstelligen zahlen */
    formatNumber: function(nr) {
        if (nr < 10)
            return "0" + nr;
        else
            return nr;
    },

    /* schreibt das ausgewählte datum in das zielobjekt */
    exportDate: function(d) {
        if (this.options.targetelem != null) {
            var format = this.options.dateformat;

            format = format.replace(/dd/, this.formatNumber(d.getDate()));
            format = format.replace(/MM/, this.formatNumber(d.getMonth() + 1));
            format = format.replace(/yyyy/, d.getFullYear());
            format = format.replace(/yy/, (d.getFullYear().toString()).substring(2));

            format = format.replace(/Month/, this.options.months[d.getMonth()]);
            format = format.replace(/Mon/, this.options.months[d.getMonth().toString().substring(3)]);

            this.options.targetelem.value = format;
        }
    },

    /* gibt den aktuell ausgewählten monat an */
    getMonth: function(d) {
        if (this.options.navigationtype == 0)
            return this.ddmonth.options[this.ddmonth.selectedIndex].value;
        else
            return this.options.selectedMonth;
    },

    /* gibt das aktuell ausgewählte jahr zurück */
    getYear: function(d) {
        if (this.options.navigationtype == 0)
            return this.ddyear.options[this.ddyear.selectedIndex].value;
        else
            return this.options.selectedYear;
    },

    /* setzt die position des popups anhand des zielobjektes oder des mouseevents. wo soll die spitze hinzeigen? */
    setTargetPosition: function() {

        if (this.options.mouseevent == null && this.options.dockelem == null)
            this.options.dockelem = this.options.targetelem;

        if (this.options.mouseevent != null) {
            this.options.xpos = this.options.mouseevent.page.x;
            this.options.ypos = this.options.mouseevent.page.y;
        }
        else if (this.options.dockelem != null) {
            this.options.dockelem = $(this.options.dockelem);

            this.options.xpos = this.options.dockelem.getPosition().x;
            this.options.ypos = this.options.dockelem.getPosition().y;

            if (this.options.dockelempos == "ro") {
                this.options.xpos += this.options.dockelem.getSize().x;
            } else if (this.options.dockelempos == "lu") {
                this.options.ypos += this.options.dockelem.getSize().y;
            } else if (this.options.dockelempos == "ru") {
                this.options.xpos += this.options.dockelem.getSize().x;
                this.options.ypos += this.options.dockelem.getSize().y;
            } else if (this.options.dockelempos == "center") {
                this.options.xpos += this.options.dockelem.getSize().x / 2;
                this.options.ypos += this.options.dockelem.getSize().y / 2;
            }
        }

        this.options.xpos += this.options.xdelta;
        this.options.ypos += this.options.ydelta;

    },


    /* setzt die position des popups relativ zur sichtbaren spitze */
    setPosition: function() {

        if (this.options.peakmode == "lo") {

        }
        else if (this.options.peakmode == "ro") {
            this.options.xpos = this.options.xpos - this.popupcon.getSize().x;
        }
        else if (this.options.peakmode == "lu") {

            this.options.ypos = this.options.ypos - this.popupcon.getSize().y;
        }
        else if (this.options.peakmode == "ru") {
            this.options.xpos = this.options.xpos - this.popupcon.getSize().x - (this.getPeak("ru").getSize().x - this.getPeak("ru").getStyle("left").toInt());
            this.options.ypos = this.options.ypos - this.popupcon.getSize().y;
        }

        // setze position endgültig
        this.popupcon.style.top = this.options.ypos + "px";
        this.popupcon.style.left = this.options.xpos + "px";
    },


    /* erzeugt den HTML-Code für das Popup */
    createHtml: function() {

        var popupcon = new Element("div", { id: "maindiv", 'class': this.options.popupcss });

        var html = "";

        html += "<div class=\"maindiv\">";
        html += "   <div class=\"headlinediv\">Kalender</div>";
        html += "   <div class=\"closediv\">X</div>";
        html += "   <div class=\"navigation\">";
        html += "        <select class=\"dropdownmonth\"></select>";
        html += "        <select class=\"dropdownyear\"></select>";
        html += "   </div>";
        html += "   <div class=\"weekdiv\">";
        html += "       <div class=\"weekday\">Mo</div>";
        html += "       <div class=\"weekday\">Di</div>";
        html += "       <div class=\"weekday\">Mi</div>";
        html += "       <div class=\"weekday\">Do</div>";
        html += "       <div class=\"weekday\">Fr</div>";
        html += "       <div class=\"weekday\">Sa</div>";
        html += "       <div class=\"weekday\">So</div>";
        html += "   </div>";
        html += "   <div id=\"caldisplay\" class=\"display\"></div>";
        html += "</div>";

        popupcon.set('html', html);

        return popupcon;
    },

    /* gibt das Element im Popup zurück, das die Headline enthält */
    getHeadlineElem: function() {
        return this.popupcon.getElement('.headlinediv');
    },

    /* gibt das Element im Popup zurück, mit das Popup geschlossen wird */
    getCloseElem: function() {
        return this.popupcon.getElement('.closediv');
    },

    /* löscht das popup und entfernt es aus dem DOM */
    clear: function() {

        if (this.options.contentelem == null)
            this.popupcon.destroy();
        else
            this.popupcon.style.display = 'none';

    }
});

