﻿/**
* jQuery jquery Plugin 1.0.0
*
* http://www.devcoach.com/
* http://docs.jquery.com/Plugins/jquery
*
* Copyright (c) 2011 devcoach 
* 
* Author: lennybacon
*
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*/
/// <reference path="jquery-1.6.1-vsdoc.js" />


// build namespace hirarchy...
var devcoach = devcoach || {};
devcoach.JQuery = devcoach.JQuery || {};

// define static object ...
devcoach.JQuery.datePickerCalendar = {
    defaults: 
        {
            january: 'January',
            february: 'February',
            march: 'March',
            april: 'April',
            may: 'May',
            june: 'June',
            july: 'July',
            august: 'August',
            september: 'September',
            october: 'October',
            november: 'November',
            december: 'December',

            monday: 'Monday',
            tuesday: 'Tuesday',
            wednesday: 'Wednesday',
            thursday: 'Thursday',
            friday: 'Friday',
            saturday: 'Saturday',
            sunday: 'Sunday',

            today: 'Today',

            format: 'mm/dd/yyyy',

            startWithSunday: true,
            
            charsOfDay: 3
        }
};

// define the plugin
(function ($) {
    
    /// <summary>
    /// A plugin to ...
    /// </summary>
    /// <remarks>
    /// Methods can be called as <br/>
    ///    $(selector).datePickerCalendar('methodName', arg1, arg2, ...);
    /// or, from within the plugin itself, as
    ///     methods.methodName(arg1, arg2, ...);
    /// </remarks>
    $.fn.datePickerCalendar = function (method) {

        /// <summary>
        /// Gets the default properties.
        /// </summary>
        var defaults = {};

        /// <summary>
        /// Gets the default and user-provided properties.
        /// </summary>
        var settings = {};

        /// <summary>
        /// Gets the public methods of the plugin.
        /// </summary>
        var methods = {

            /// <summary>
            /// Initializes th plugin..
            /// </summary>
            init: function (options) {

                // load defaults from static object...
                defaults = 
                    $.extend(
                        defaults, 
                        devcoach.JQuery.datePickerCalendar.defaults);
                
                // merged default and user-provided properties (if any)...
                settings = $.extend({}, defaults, options);
                
                // iterate through all the DOM elements...
                return this.each(function () {
                    var jqueryElement = $(this); 
                    var domElement = this;
                    
                     // disable autocomplete 
                    domElement.setAttribute('autocomplete', 'off');

                    jqueryElement.after(
                        '<div id="' +
                        domElement.id +
                        'DatePicker" class="datepicker"' + 
                        ' style="display: none;"></div>');

                    jqueryElement.focus(helpers.showDatePicker);
                    jqueryElement.click(helpers.showDatePicker);
                    
                    var jqueryDatePickerElement = 
                        $('#' + domElement.id + 'DatePicker');
                    
                    jqueryDatePickerElement.keypress(helpers.handleKeyPress);
                    if ($.browser.mozilla == false) {
                        jqueryDatePickerElement.keydown(helpers.handleKeyDown);
                    }

                    jqueryDatePickerElement.mouseover(
                        function () {
                            jqueryElement.data('isInSelectionMode', true);
                        });
                    
                    jqueryDatePickerElement.mouseout(
                        function (eventObject) {
                            jqueryElement.data('isInSelectionMode', false);
                            setTimeout(
                                function () {
                                    if (jqueryElement.data('isInSelectionMode') == false) {
                                        jqueryDatePickerElement.fadeOut('fast');
                                    }
                                }, 500);
                        });

                });

            },

            /// <summary>
            /// Sets the date formated to the dom element value property.
            /// </summary>
            setDate: function (selectedYear, selectedMonth, selectedDay) {
                // load defaults from static object...
                defaults = 
                    $.extend(
                        defaults, 
                        devcoach.JQuery.datePickerCalendar.defaults);
                return this.each(
                    function () {
                        var domElement = this; 
                        var jqueryElement = $(this); 
                        jqueryElement.data('isInSelectionMode', false);
                        
                       
                        
                        domElement.value =
                            helpers.formatDate(
                                selectedYear,
                                helpers.fixLen(selectedMonth),
                                helpers.fixLen(selectedDay),
                                defaults.format);

                        $('#' + domElement.id + 'DatePicker').fadeOut('fast');
                    });
            },
            
            
            /// <summary>
            /// Builds the calendar.
            /// </summary>
            buildCalendar: function (year, month, selectedYear, selectedMonth, selectedDay) {
                // load defaults from static object...
                defaults = 
                    $.extend(
                        defaults, 
                        devcoach.JQuery.datePickerCalendar.defaults);
                
                return this.each(
                    function () {
                        var domElement = this; // reference to the actual DOM element
                        
                        var dayNames =
                            ((defaults.startWithSunday)
                                ? new Array(
                                    defaults.sunday.substring(0, defaults.charsOfDay),
                                    defaults.monday.substring(0, defaults.charsOfDay),
                                    defaults.tuesday.substring(0, defaults.charsOfDay),
                                    defaults.wednesday.substring(0, defaults.charsOfDay),
                                    defaults.thursday.substring(0, defaults.charsOfDay),
                                    defaults.friday.substring(0, defaults.charsOfDay),
                                    defaults.saturday.substring(0, defaults.charsOfDay))
                                : new Array(
                                    defaults.monday.substring(0, defaults.charsOfDay),
                                    defaults.tuesday.substring(0, defaults.charsOfDay),
                                    defaults.wednesday.substring(0, defaults.charsOfDay),
                                    defaults.thursday.substring(0, defaults.charsOfDay),
                                    defaults.friday.substring(0, defaults.charsOfDay),
                                    defaults.saturday.substring(0, defaults.charsOfDay),
                                    defaults.sunday.substring(0, defaults.charsOfDay)));

                        var months =
                            new Array(
                                defaults.january,
                                defaults.february,
                                defaults.march,
                                defaults.april,
                                defaults.may,
                                defaults.june,
                                defaults.july,
                                defaults.august,
                                defaults.september,
                                defaults.october,
                                defaults.november,
                                defaults.december);

                        // Schaltjahr berechnung
                        var daysInMonth =
                        new Array(
                            31,
                            ((0 == (year % 4)) && 
                                (0 != (year % 100))) || (0 == year % 400)
                                    ? 29
                                    : 28,
                            31,
                            30,
                            31,
                            30,
                            31,
                            31,
                            30,
                            31,
                            30,
                            31);

                        

                        var previousMonthCall =
                            '$(\'#' + domElement.id + '\').datePickerCalendar(\'buildCalendar\', ' + ((month <= 1) ? (year - 1) : year) + ', ' + ((month <= 1) ? 12 : (month - 1)) + ', ' + selectedYear + ', ' + selectedMonth + ', ' + selectedDay + ')';

                        var previousYearCall =
                            '$(\'#' + domElement.id + '\').datePickerCalendar(\'buildCalendar\', ' + ((year <= 1) ? 0 : (year - 1)) + ', ' + month + ', ' + selectedYear + ', ' + selectedMonth + ', ' + selectedDay + ')';

                        var nextMonthCall =
                            '$(\'#' + domElement.id + '\').datePickerCalendar(\'buildCalendar\', ' + (((month) >= 12) ? (year + 1) : year) + ', ' + (((month) >= 12) ? 1 : (month + 1)) + ', ' + selectedYear + ', ' + selectedMonth + ', ' + selectedDay + ')';

                        var nextYearCall =
                            '$(\'#' + domElement.id + '\').datePickerCalendar(\'buildCalendar\', ' + (year + 1) + ', ' + month + ', ' + selectedYear + ', ' + selectedMonth + ', ' + selectedDay + ')';

                        var howManyDays = 7;

                        var columns = 7;

                        var grid = '<div class="datePickerHeader">';
                        grid +='<table style="width: 100%;">';
                        grid += '<tr><td style="text-align: left;" class="datePickerNav">';
                        grid += '<a href="javascript://" onclick="' + previousYearCall + '">&nbsp;&#9664;</a>';
                        grid += '</td><td style="text-align: left;" class="datePickerNav">';
                        grid += '<a href="javascript://" onclick="' + previousMonthCall + '">&#9668;</a>';
                        grid += '</td><td class="datePickerMonthName" style="text-align: center; width: 100%;" >';
                        grid += months[month - 1];
                        grid += ' ';
                        grid += year;
                        grid += '</td><td style="text-align: right;" class="datePickerNav">';
                        grid += '<a href="javascript://" onclick="' + nextMonthCall + '">&#9658;</a>';
                        grid += '</td><td style="text-align: right;" class="datePickerNav">';
                        grid += '<a href="javascript://" onclick="' + nextYearCall + '">&#9654;&nbsp;</a>';
                        grid += '</td>';
                        grid += '</tr>';
                        grid +='</table>';
                        grid +='<table  style="border: 0px; width: 100%;">';
                        grid += '<tr>';
                        for (var iPreDayNames = 0; iPreDayNames < columns - 7; iPreDayNames++) {
                            grid += '<td>&nbsp;</td>';
                        }

                        for (var iDayNames = columns - 7; iDayNames < 7; iDayNames++) {
                            grid += '<td class="datePickerDayName" style="text-align: center;">' + dayNames[iDayNames] + '</td>';
                        }
                        grid += '</tr>';
                        
                        grid += '</table></div>';
                        grid += '<table class="datePickerTable" style="width: 100%;">';

                        

                        var firstDayOfMonth = 
                            new Date(year, month - 1, 1).getDay();
                        
                        // find column of first day
                        var dayInMonthOffset = 
                            (7 - firstDayOfMonth + ((defaults.startWithSunday) 
                                ? 1 
                                : firstDayOfMonth == 0 ? -5 : 2));
                        
                        for (var intWeek = 0; intWeek < 6; intWeek++) {
                            grid += '<tr>';
                            for (var intDay = 0; intDay < howManyDays; intDay++) {
                                
                                var dayOfMonth = (intWeek * 7) + intDay + dayInMonthOffset - 7;
                                
                                if (dayOfMonth <= 0) {
                                    grid += '<td style="text-align: center;"><div class="datePickerNone">&nbsp;</div></td>';
                                }
                                else if (year == selectedYear && month == selectedMonth && dayOfMonth == selectedDay) {
                                    var setSelectedDateCall =
                                        '$(\'#' + domElement.id + '\').datePickerCalendar(\'setDate\', ' + year + ', ' + month + ', ' + dayOfMonth + ')';
                                    grid += '<td style="text-align: center;"><div class="datePickerDay datePickerSelected"><a id="' + domElement.id + '_' + year + '_' + month + '_' + dayOfMonth + '" href="javascript://" onclick="' + setSelectedDateCall + '">' + dayOfMonth + '</a></div></td>';
                                }
                                else if (dayOfMonth <= daysInMonth[month - 1]) {
                                    var setDateCall =
                                        '$(\'#' + domElement.id + '\').datePickerCalendar(\'setDate\', ' + year + ', ' + month + ', ' + dayOfMonth + ')';
                                    grid += '<td style="text-align: center;" class="datePickerDay"><div class="datePickerDay"><a href="javascript://" onclick="' + setDateCall + '">' + dayOfMonth + '</a></div></td>';
                                }
                                else {
                                    grid += '<td style="text-align: center;" class="datePickerNone"><div class="datePickerNone">&nbsp;</div></td>';
                                }
                            }
                            grid += '</tr>';
                        }

                        var now = new Date();
                        var todayCall =
                            '$(\'#' + domElement.id + '\').datePickerCalendar(\'setDate\', ' + now.getFullYear() + ', ' + (now.getMonth() + 1) + ', ' + now.getDate() + ')';

                        
                        grid += '</table>';

                        grid += '<div class="datePickerFooter" style="text-align: center;">';
                        grid += '<a href="javascript://" onclick="' + todayCall + '">' + defaults.today + '</a>';
                        grid += '</div>';
                        var domCalendarElementId = domElement.id + 'DatePicker';
                        var domCalendarElement = 
                            document.getElementById(domCalendarElementId);
                        domCalendarElement.innerHTML = grid;

                        var selectedId = 
                            domElement.id + 
                            '_' + 
                            selectedYear + 
                            '_' + 
                            selectedMonth + 
                            '_' + 
                            selectedDay;
                        
                        var selectedDate = document.getElementById(selectedId);
                        if (selectedDate) {
                            selectedDate.focus();
                        }
                    });
            }
        };

        /// <summary>
        /// Gets the private methods of the plugin.
        /// </summary>
        var helpers = {
            
            /// <summary>
            /// Shows the date picker.
            /// </summary>
            showDatePicker: function (eventObject) {

                var selectedElement = eventObject.currentTarget;
                var datePickerId = selectedElement.id + 'DatePicker';
                var datePickerElement = document.getElementById(datePickerId);

                // set position to absolute
                datePickerElement.style.position = 'absolute';

                // get offset of textbox...
                //var elmTop = parseInt(selectedElement.offsetTop);

                var absPosTop = helpers.getAbsTop(selectedElement);
                
                var elmHeight = parseInt(selectedElement.offsetHeight);
                var topE = (absPosTop + elmHeight - 1) + 'px';
         
                datePickerElement.style.top = topE;

                datePickerElement.style.left =
                    parseInt(helpers.getAbsLeft(selectedElement)) + 'px';

                //datePickerElement.style.height = '200px';
                datePickerElement.style.zIndex = 99;

                datePickerElement.style.backgroundColor = '#fff';

                datePickerElement.style.width = '225px';
                datePickerElement.style.border = '1px solid #999';

                var theDate;
                if (selectedElement.value.length > 0) {
                    theDate =
                        helpers.getDateFromString(
                            selectedElement.value,
                            defaults.format);
                } else {
                    theDate = new Date();
                }
                var year = theDate.getFullYear();
                var month = theDate.getMonth() + 1;

                var selectedYear = theDate.getFullYear();
                var selectedMonth = theDate.getMonth() + 1;
                var selectedDay = theDate.getDate();

                $('#' + selectedElement.id).datePickerCalendar(
                    'buildCalendar', 
                    year, 
                    month, 
                    selectedYear, 
                    selectedMonth, 
                    selectedDay);

                $(datePickerElement).fadeIn('fast');
            },

            /// <summary>
            /// Hides the date picker.
            /// </summary>
            hideDatePicker: function (eventObject) {
                var domElement = eventObject.currentTarget;
                var jqueryElement =  $(domElement);
                var isInSelectionMode = jqueryElement.data('isInSelectionMode');
                if (isInSelectionMode == true) return;
                $('#' + domElement.id + 'DatePicker').fadeOut('fast');
                jqueryElement.data('isInSelectionMode', false);
            },

            /// <summary>
            /// Handles the key down event.
            /// </summary>
            handleKeyDown: function (eventObject) {
                var domElement = eventObject.currentTarget;
                var jqueryElement =  $(domElement);
                var key = eventObject.keyCode;
                if (key == 27) { // esc
                    jqueryElement.fadeOut('fast');
                    jqueryElement.data('isInSelectionMode', false);
                    return true;
                }
                return true;
            },

            /// <summary>
            /// Handles the key press event.
            /// </summary>
            handleKeyPress: function (eventObject) {
                var domElement = eventObject.currentTarget;
                var jqueryElement =  $(domElement);
                var key = eventObject.keyCode;
                if (key == 27) { // esc
                    jqueryElement.fadeOut('fast');
                    jqueryElement.data('isInSelectionMode', false);
                    return true;
                }
                return true;
            },

            getStyle: function (domElement,styleProp)
            {
	            if (domElement.currentStyle) {
	                    return domElement.currentStyle[styleProp];
	            }
                if (window.getComputedStyle) {
                 return document.defaultView.getComputedStyle(domElement, null).
                     getPropertyValue(styleProp);
                }
                return null;
            },
            getAbsTop: function(domElement) {
	            var elementTop = 0;
                if (domElement.offsetParent) {
                    do {
                        var position = helpers.getStyle(domElement, 'position');
                        if(position!='static') {
                            break;
                        }
                        elementTop += domElement.offsetTop;
                    } while (domElement = domElement.offsetParent);
                }
                return elementTop;
            },
            getAbsLeft: function(domElement) {
	            var elementLeft = 0;
                if (domElement.offsetParent) {
                    do {
                        var position = helpers.getStyle(domElement, 'position');
                        if(position!='static') {
                            break;
                        }
                        elementLeft += domElement.offsetLeft;
                    } while (domElement = domElement.offsetParent);
                }
                return elementLeft;
            },
            
            
            
            /// <summary>
            /// gets the date from a string.
            /// </summary>
            getAbsPos: function (element) {
	            var res = new Object();
	            res.x = 0; res.y = 0;
	            if (element !== null) { 
		            if (element.getBoundingClientRect) {
			            var viewportElement = document.documentElement;  
 	                    var box = element.getBoundingClientRect();
		                var scrollLeft = viewportElement.scrollLeft;
 		                var scrollTop = viewportElement.scrollTop;

		                res.x = box.left + scrollLeft;
		                res.y = box.top + scrollTop;

		            }
		            else { //for old browsers
			            res.x = element.offsetLeft;
			            res.y = element.offsetTop;

			            var parentNode = element.parentNode;
			            var borderWidth = null;

			            while (offsetParent != null) {
				            res.x += offsetParent.offsetLeft;
				            res.y += offsetParent.offsetTop;
				
				            var parentTagName = 
					            offsetParent.tagName.toLowerCase();	

				            if ((__isIEOld && parentTagName != "table") || 
					            ((__isFireFoxNew || __isChrome) && 
						            parentTagName == "td")) {		    
					            borderWidth = kGetBorderWidth
							            (offsetParent);
					            res.x += borderWidth.left;
					            res.y += borderWidth.top;
				            }
				
				            if (offsetParent != document.body && 
				            offsetParent != document.documentElement) {
					            res.x -= offsetParent.scrollLeft;
					            res.y -= offsetParent.scrollTop;
				            }


				            //next lines are necessary to fix the problem 
				            //with offsetParent
				            if (!__isIE && !__isOperaOld || __isIENew) {
					            while (offsetParent != parentNode && 
						            parentNode !== null) {
						            res.x -= parentNode.scrollLeft;
						            res.y -= parentNode.scrollTop;
						            if (__isFireFoxOld || __isWebKit) 
						            {
						                borderWidth = 
						                 kGetBorderWidth(parentNode);
						                res.x += borderWidth.left;
						                res.y += borderWidth.top;
						            }
						            parentNode = parentNode.parentNode;
					            }    
				            }

				            parentNode = offsetParent.parentNode;
				            offsetParent = offsetParent.offsetParent;
			            }
		            }
	            }
                return res;
            },
            
            /// <summary>
            /// gets the date from a string.
            /// </summary>
            getDateFromString: function (dateString, format) {
                var separator;
                if (format.indexOf('/') > -1) {
                    separator = '/';
                }
                else if (format.indexOf('.') > -1) {
                    separator = '.';
                }
                else {
                    separator = '-';
                }
                var formatparts = format.split(separator);
                var dateparts = dateString.split(separator);

                if (formatparts.length != dateparts.length) {
                    return new Date();
                }

                var yearIndex = -1;
                var monthIndex = -1;
                var dayIndex = -1;

                for (var i = 0; i < formatparts.length; i++) {
                    var currentFormatPart = formatparts[i].toLowerCase();
                    if (currentFormatPart.indexOf('y') > -1) {
                        yearIndex = i;
                        continue;
                    }
                    if (currentFormatPart.indexOf('m') > -1) {
                        monthIndex = i;
                        continue;
                    }
                    if (currentFormatPart.indexOf('d') > -1) {
                        dayIndex = i;
                        continue;
                    }
                }

                if (yearIndex > -1 && monthIndex > -1 && dayIndex > -1) {

                    var yearString = dateparts[yearIndex];
                    var monthString = dateparts[monthIndex];
                    var dayString = dateparts[dayIndex];

                    var yearInt = parseInt(yearString, 10);
                    var monthInt = parseInt(monthString, 10) - 1;
                    var dayInt = parseInt(dayString, 10);

                    var returnDate = new Date(yearInt, monthInt, dayInt);
                    return returnDate;
                }

                return new Date();
            },

            /// <summary>
            /// Formats the date as string.
            /// </summary>
            formatDate: function (year, month, day, format) {
                var separator;
                if (format.indexOf('/') > -1) {
                    separator = '/';
                }
                else if (format.indexOf('.') > -1) {
                    separator = '.';
                }
                else {
                    separator = '-';
                }
                var formatparts = format.split(separator);

                var yearIndex = -1;
                var monthIndex = -1;
                var dayIndex = -1;

                for (var i = 0; i < formatparts.length; i++) {
                    var currentFormatPart = formatparts[i].toLowerCase();
                    if (currentFormatPart.indexOf('y') > -1) {
                        yearIndex = i;
                        continue;
                    }
                    if (currentFormatPart.indexOf('m') > -1) {
                        monthIndex = i;
                        continue;
                    }
                    if (currentFormatPart.indexOf('d') > -1) {
                        dayIndex = i;
                        continue;
                    }
                }

                var dateArr = new Array('', '', '');

                for (var iDate = 0; iDate < dateArr.length; iDate++) {
                    if (iDate == yearIndex) {
                        dateArr[iDate] = year;
                    }
                    if (iDate == monthIndex) {
                        dateArr[iDate] = month;
                    }
                    if (iDate == dayIndex) {
                        dateArr[iDate] = day;
                    }
                }

                var retStr =
                    dateArr[0] + separator + dateArr[1] + separator + dateArr[2];

                return retStr;

            },

            /// <summary>
            /// Fixes the length of a number by prefixing a zero.
            /// </summary>
            fixLen: function (i) {
                return (((i + '').length != 2) ? '0' + i : i);
            }
        };       
        
        if (methods[method]) {
            return methods[method].apply(
                this, 
                Array.prototype.slice.call(arguments, 1));
        }  
        
        if (typeof method === 'object' || !method) {

            // call the initialization method
            return methods.init.apply(this, arguments);
        }

        $.error(
            'Method "' + 
                method + 
                '" does not exist in the plugin "datePickerCalendar" !');
        return null;
    };

})(jQuery);
