﻿// ============================================================================================
// TABLE OF ALLOWED KEYS IN keyDown FUNCTIONS
// ============================================================================================
// 'a' and 'A' both return ascii 65, etc. so that it is left room for num part; shift, ctrl,
// alt are allowed
// --------------------------------------------------------------------------------------------
// key          ascii	hex     Decimal Money   Integer Date
// --------------------------------------------------------------------------------------------
// PgUp	        33	    21      yes     yes     yes     yes
// PgDn	        34	    22      yes     yes     yes     yes
// end	        35	    23      yes     yes     yes     yes
// home	        36	    24      yes     yes     yes     yes
// left	        37	    25      yes     yes     yes     yes
// up	        38	    26      yes     yes     yes     yes
// right	    39	    27      yes     yes     yes     yes
// down	        40	    28      yes     yes     yes     yes
// backspace    08      08      yes     yes     yes     yes
// tab	        9	    09      yes     yes     yes     yes
// enter	    13	    0D      yes     yes     yes     yes
// insert	    45	    2D      yes     yes     yes     yes
// delete	    46	    2E      yes     yes     yes     yes
// .	        190	    BE      no      no      no      yes     twice max for date
// ,	        188	    BC      yes     yes     no      no      twice max for decimal & money
// minus	    109	    6D      yes     yes     yes     no      ie
//              187     BB                                      gecko
// plus	        107	    6B      yes     yes     yes     no      ie
//              189     BD                                      gecko
// --------------------------------------------------------------------------------------------
// numeric part
// --------------------------------------------------------------------------------------------
// key          ascii	hex
// --------------------------------------------------------------------------------------------
// 0	        96	    60      yes     yes     yes     yes
// 1	        97	    61      yes     yes     yes     yes
// 2	        98	    62      yes     yes     yes     yes
// 3	        99	    63      yes     yes     yes     yes
// 4	        100	    64      yes     yes     yes     yes
// 5	        101	    65      yes     yes     yes     yes
// 6	        102	    66      yes     yes     yes     yes
// 7	        103	    67      yes     yes     yes     yes
// 8	        104	    68      yes     yes     yes     yes
// 9	        105	    69      yes     yes     yes     yes
// ,	        110	    6E      yes     yes     no      no      twice max for decimal & money
// enter	    13	    0D      yes     yes     yes     yes
// minus	    109	    6D      yes     yes     no      no      ie & gecko
// plus	        107	    6B      yes     yes     no      no      ie & gecko
// --------------------------------------------------------------------------------------------
// special for date
// --------------------------------------------------------------------------------------------
// key          ascii	hex
// --------------------------------------------------------------------------------------------
// C            67      43      no      no      no      yes
// D            68      44      no      no      no      yes
// T            84      54      no      no      no      yes
// Y            69      59      no      no      no      yes
// --------------------------------------------------------------------------------------------
// Allowed true characters for numbers (int, decimal, money, precent): 0-9,+-
// Allowed true characters for dates: 0-9.
// --------------------------------------------------------------------------------------------
// CONSTANTS
// --------------------------------------------------------------------------------------------
var rInt = new RegExp(/\x21|\x22|\x23|\x24|\x25|\x26|\x27|\x28|\x08|\x09|\x2D|\x0D|\x2E|\x0D|[+-]|[0-9]/);
var rDec = new RegExp(/\x21|\x22|\x23|\x24|\x25|\x26|\x27|\x28|\x08|\x09|\x2D|\x0D|\x2E|\x0D|[+-,]|[0-9]/);
var rDate = new RegExp(/\x21|\x22|\x23|\x24|\x25|\x26|\x27|\x28|\x08|\x09|\x2D|\x0D|\x2E|\x0D|[.CDTY]|[0-9]/);
var iInt = new RegExp(/([,\d]+[+-]+)|([+-]{2,}[,\d]*)|([.])/);    // +/- zero or one at beginning
var iDec = new RegExp(/(\d*(\d*[,]\d*){2,}\d*)|([,\d]+[+-]+)|([+-]{2,}[,\d]*)|([.])/);    // one comma only and +/- zero or one at beginning
var iDate = new RegExp(/(\d*(\d*[.]\d*){3,}\d*)/);   // no other condition

var is_gecko = /gecko/i.test(navigator.userAgent);
var is_ie    = /MSIE/.test(navigator.userAgent);

//forcing onchange event for programaticall changes
function fireOnChange(txt) {
    //IE
    if(txt.fireEvent)
    {
    txt.fireEvent('onchange');
    }
    //On Gecko based browsers
    if(document.createEvent)
    {
    var evt = document.createEvent('HTMLEvents');
    if(evt.initEvent)
        {
        evt.initEvent('change', true, true);
        }
    }
    if(txt.dispatchEvent)
    {
    txt.dispatchEvent(evt);
    }
}
// --------------------------------------------------------------------------------------------
// KEYBOARD FUNCTIONS
// --------------------------------------------------------------------------------------------
function ekeynum(e)
// Alpha charcters are all upper case, case is determined by e.ctrlKey
// Numeric characters are 48..57
// Numeric keypad characters are `,a-i
// +-,. are xBC,\x6E/,\xBE,x6B,\x6D
// see true numeric
{
    if(window.event) // IE
    {
        return e.keyCode;
    }
    else if(e.which) // Netscape/Firefox/Opera
    {
        return e.which;
    }
}
function isRegularChar(keychar,e,r)
// Based on rInt,rDec,rDate
{
    switch (e.shiftKey)
    {
        case false:
            switch (e.ctrlKey)
            {
                case false:
                    switch (e.altKey)
                    {
                        case false:
                            return r.test(keychar);
                        case true:
                            return /[0-9]/.test(keychar);
                    }
                    return r.test(keychar);
                case true:
                    return /[XCV0-9]/.test(keychar);
            }
        case true:
            return /\x09|\x23|\x24|\x25|\x26|\x27|\x28/.test(keychar);
    }
}
function iRegularFormat(i,s)
// Based od iInt,iDec,iDate
{
    return i.test(s);
}
function trueNumeric(keynum)
// True characters for numbers and dates, otherwise char(0)
{
    var keychar = String.fromCharCode(keynum);
    if (/[0-9]/.test(keychar)) return keychar;
    if (/\x60|\x61|\x62|\x63|\x64|\x65|\x66|\x67|\x68|\x69/.test(keychar)) return String.fromCharCode(keynum - 48);
    if (/\xBC|\x6E/.test(keychar)) return ',';
    if (/\xBE/.test(keychar)) return '.';
    if (/\x6B|\xBB/.test(keychar)) return '+';
    if (/\x6D|\xBD/.test(keychar)) return '-';
    return keychar;
}
function newString(x,keychar)
// if [0-9,.+-] is pressed, calculate new string
{
    var s = document.getElementById(x).value;
    if (!(/[0-9,.+-]/.test(keychar))) return s;
    var start = getSelectionStart(document.getElementById(x));
    var end = getSelectionEnd(document.getElementById(x));
    return s.substring(0,start) + keychar + s.substring(end,s.length);
}
function keyDown(x,e,r,i,appendix)
{
    var keynum = ekeynum(e);    // numeric value
    var keychar = trueNumeric(keynum);  // true character
    if (!isRegularChar(keychar,e,r)) return false;  // only regular chars for numbers and dates
    if (iRegularFormat(i,newString(x,keychar))) return keynum == 46 || false;   // check format with iInt,iDec,iDate; ignore delete button
    if (appendix != '')
    {
        var a = appendix.split('|');
        for (var i = 0; i < a.length; i++)
        {
            if (!eval(a[i])) return false;
        }
    }
    return true;
}
function change(x,e)
{
    document.getElementById(x).setAttribute('oldValue',document.getElementById(x).value);
}
// --------------------------------------------------------------------------------------------
// SELECTION FUNCTIONS
// --------------------------------------------------------------------------------------------
function setSelectionRange(input, start, end)
// Programatically makes selection
{
	if (is_gecko) {
		input.setSelectionRange(start, end);
	} else
	{
		// assumed IE
		var range = input.createTextRange();
		range.collapse(true);
		range.moveStart("character", start);
		range.moveEnd("character", end - start);
		range.select();
	}
}
function getSelectionStart(input)
{
	if (is_gecko) return input.selectionStart;  // firefox ..
    var range = document.selection.createRange().duplicate();   // ie
    var i = 0;
    while (range.moveStart("character",-1) != 0) i++;
    return i;
} 
function getSelectionEnd(input)
{
	if (is_gecko) return input.selectionEnd;    // firefox
    var range = document.selection.createRange().duplicate();   // ie
    var i = 0;
    while ( range.moveEnd("character", -1) != 0 ) i++;
    return i;
} 
function inputKey(input, ev)
{
    setTimeout(function()
    {
        document.getElementById("selStart").value = getSelectionStart(input);
        document.getElementById("selEnd").value = getSelectionEnd(input);
    }, 20);
  }
function doSelect(x)
// Select whole word
{
    var input = document.getElementById(x);
    var start = 0;
    var end = input.value.length;
    input.focus();
    setSelectionRange(input, start, end);
}
// --------------------------------------------------------------------------------------------
// DATE FUNCTIONS
// --------------------------------------------------------------------------------------------
function daysInMonth(month, year)
{
    var m = [31,28,31,30,31,30,31,31,30,31,30,31];
    if (month != 2) return m[month - 1];
    if (year%4 != 0) return m[1];
    if (year%100 == 0 && year%400 != 0) return m[1];
    return m[1] + 1;
}
function IncreaseYear(day, month, year, i)
{
    return day.toString() + '.' + month.toString() + '.' + (year + i).toString();
}
function DecreaseYear(day, month, year, i)
{
    return day.toString() + '.' + month.toString() + '.' + (year - i).toString();
}
function IncreaseMonth(day, month, year, i)
{
    month = month + i;
    if (month > 12)
    {
        month = 1;
        year = year + 1;
    }
    return day.toString() + '.' + month.toString() + '.' + year.toString();
}
function DecreaseMonth(day, month, year, i)
{
    month = month - i;
    if (month < 1)
    {
        month = 12;
        year = year - 1;
    }
    return day.toString() + '.' + month.toString() + '.' + year.toString();
}
function IncreaseDay(day, month, year, i)
{
    day = day + i;
    if (day > daysInMonth(month, year))
    {
        day = day - daysInMonth(month, year);
    }
    return day.toString() + '.' + month.toString() + '.' + year.toString();
}
function DecreaseDay(day, month, year, i)
{
    day = day - i;
    if (day < 1)
    {
        day = day - daysInMonth(month - 1, year);
    }
    return day.toString() + '.' + month.toString() + '.' + year.toString();
}
function IncreaseDate(part, s, c)
{
    var t = s.split('.');
    switch (part)
    {
        case 'day':
            return IncreaseDay(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
        case 'month':
            return IncreaseMonth(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
        case 'year':
            return IncreaseYear(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
        default:
            return IncreaseDay(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
    }
}
function DecreaseDate(part, s, c)
{
    var t = s.split('.');
    switch (part)
    {
        case 'day':
            return DecreaseDay(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
        case 'month':
            return DecreaseMonth(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
        case 'year':
            return DecreaseYear(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
        default:
            return DecreaseDay(parseInt(t[0]), parseInt(t[1]), parseInt(t[2]), parseInt(c));
    }
}
function CreateDate(s)
{
    var s1 = s.split('.');
    var d = new Date();
    d.setFullYear(s1[2],(parseInt(s1[1])-1).toString(),s1[0]);
    return d;
}
function IncDate(s, t, x, start, end, inc)
{
    var y = document.getElementById(x);
    if (s.substring(start,end) == t[0] && start == 0)
    {
        t[0] = (parseInt(t[0]) + inc).toString();
        var d = CreateDate(t[0] + '.' + t[1] + '.' + t[2]);
        y.value = d.getDate().toString() + '.' + (d.getMonth() + 1).toString() + '.' + d.getFullYear().toString();
        setSelectionRange(y, 0, d.getDate().toString().length);
    } else if (s.substring(start,end) == t[1] && start == t[0].length + 1)
    {
        t[1] = (parseInt(t[1]) + inc).toString();
        var d = CreateDate(t[0] + '.' + t[1] + '.' + t[2]);
        y.value = d.getDate().toString() + '.' + (d.getMonth() + 1).toString() + '.' + d.getFullYear().toString();
        setSelectionRange(y, d.getDate().toString().length + 1, d.getDate().toString().length + (d.getMonth() + 1).toString().length + 1);
    } else if (s.substring(start,end) == t[2] && start == t[0].length + t[1].length + 2)
    {
        t[2] = (parseInt(t[2]) + inc).toString();
        var d = CreateDate(t[0] + '.' + t[1] + '.' + t[2]);
        y.value = d.getDate().toString() + '.' + (d.getMonth() + 1).toString() + '.' + d.getFullYear().toString();
        setSelectionRange(y, d.getDate().toString().length + (d.getMonth() + 1).toString().length + 2, d.getDate().toString().length + (d.getMonth() + 1).toString().length + d.getFullYear().toString().length + 2);
    }
}
// --------------------------------------------------------------------------------------------
// FORMATTING FUNCTIONS
// --------------------------------------------------------------------------------------------
function numberFormat(x,decimals,suffix)
// Assumes only [+-.0-9] characters
// decimals is -1 for int
// suffix can be everything but +-,0-9 !
{
    var sign = x.substring(0,1);
    if (!/[+-]/.test(sign)) sign = '';
    var xStr = parseFloat(x).toFixed(decimals == -1 ? 0 : decimals).toString();
	var y = xStr.split('.');
	var y1 = y[0];
	var y2 = y.length > 1 ? y[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(y1))
	{
		y1 = y1.replace(rgx, '$1' + '.' + '$2');
	}
	if (decimals == -1) return sign + y1 + suffix;
	return sign + y1 + ',' + y2 + suffix;
}
function numberFocus(x,suffix)
{
    var y = document.getElementById(x);
    if (y.getAttribute('oldValue') == null)
    {
        var s = y.value.replace(/\./g,'');
        while (/[^+-.0-9]$/.test(s)) s = s.substring(0,y.value.length-1);
        document.getElementById(x).setAttribute('oldValue',s);
    }
    y.value = y.getAttribute('oldValue');
    setSelectionRange(y,0,y.value.length);
}
function numberBlur(x,decimals,suffix)
{
    var y = document.getElementById(x);
    if (y.value == '') return;
    y.value = numberFormat(y.value.replace(/\,/,'.'),decimals,suffix)
}
function dateFocus(x, e)
{
    var y=document.getElementById(x);
    if (y.value!='')
    {
        var i=y.value.search(/\./);
        if (i>0)
        {
            setSelectionRange(y, 0, i);
        }
        else
        {
            setSelectionRange(y, 0, y.value.length);
        }
    }
}
// --------------------------------------------------------------------------------------------
// APPENDIXES
// --------------------------------------------------------------------------------------------
function nextCell(direction, x, tblId)
// Za element z idjem x, ki pripada tabeli z idjem tblId naredi:
// 1. poišče pripadajoč indeks vrstice (i), stolpca (j) in childa v celici (k)
// 2. v odvisnosti od smeri (direction) poišče naslednji element, ki ni readonly
// 3. vrne id elementa
{
    var tbl = document.getElementById(tblId);
    var i = 0;
    var j = 0;
    var k = 0;
    while (i < tbl.rows.length)
    {
        j = 0;
        while (j < tbl.rows[i].cells.length)
        {
            k = 0;
            while (k < tbl.rows[i].cells[j].childNodes.length)
            {
                if (tbl.rows[i].cells[j].childNodes[k].id == x)
                {
                    switch (direction)
                    {
                        case 38:
                            i--;
                            if (i == 0) i = tbl.rows.length - 1;
                            var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            while (y.readOnly)
                            {
                                i--;
                                if (i == 0) i = tbl.rows.length - 1;
                                if (tbl.rows[i].cells[j].childNodes[k].id == x) return null; // če naredi cel krog, preprečim neskončno zanko (če bi bili vsi elementi readonly)
                                var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            }
                            break;
                        case 40:
                            i++;
                            if (i == tbl.rows.length) i = 1;
                            var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            while (y.readOnly)
                            {
                                i++;
                                if (i == tbl.rows.length) i = 1;
                                if (tbl.rows[i].cells[j].childNodes[k].id == x) return null;
                                var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            }
                            break;
                        case 37:
                            var z = document.getElementById(x);
                            var start = getSelectionStart(z);
                            var end = getSelectionEnd(z);
                            if (!((start == 0 && end == z.value.length) || (start == end && end == 0))) return null;
                            j--;
                            if (j == 0) j = tbl.rows[i].cells.length - 1;
                            var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            while (y.readOnly)
                            {
                                j--;
                                if (j == 0) j = tbl.rows[i].cells.length - 1;
                                if (tbl.rows[i].cells[j].childNodes[k].id == x) return null;
                                var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            }
                            break;
                        case 39:
                            var z = document.getElementById(x);
                            var start = getSelectionStart(z);
                            var end = getSelectionEnd(z);
                            if (!((start == 0 && end == z.value.length) || (start == end && end == z.value.length))) return null;
                            j++;
                            if (j == tbl.rows[i].cells.length) j = 1;
                            var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            while (y.readOnly)
                            {
                                j++;
                                if (j == tbl.rows[i].cells.length) j = 1;
                                if (tbl.rows[i].cells[j].childNodes[k].id == x) return null;
                                var y = document.getElementById(tbl.rows[i].cells[j].childNodes[k].id);
                            }
                            break;
                    }
                    return tbl.rows[i].cells[j].childNodes[k].id;
                }
                k++;
            }
            j++;
        }
        i++;
    }
}
function intAppendix(x,e,keynum,change)
// integer
{
    var y = document.getElementById(x);
    switch (keynum)
    {
        case 38:
            switch (e.shiftKey)
            {
                case true:
                    var i=0;
                    if (y.value != '') i = parseInt(y.value);
                    y.value = (i + change).toString();
                    setSelectionRange(y, 0, y.value.length);
                    fireOnChange(y);
                    return false;
                case false:
                    var z = document.getElementById(nextCell(38,x,y.parentNode.parentNode.parentNode.parentNode.id));
                    z.focus();
                    return false;
            }
        case 40:
            switch (e.shiftKey)
            {
                case true:
                    var i=0;
                    if (y.value != '') i = parseInt(y.value);
                    if (i - change>=0)
                    {
                        y.value = (i - change).toString();
                    }
                    setSelectionRange(y, 0, y.value.length);
                    fireOnChange(y);
                    return false;
                case false:
                    var z = document.getElementById(nextCell(40,x,y.parentNode.parentNode.parentNode.parentNode.id));
                    z.focus();
                    return false;
            }
        case 37:
            switch (e.shiftKey)
            {
                case true:
                    return true;
                case false:
                    var z = document.getElementById(nextCell(37,x,y.parentNode.parentNode.parentNode.parentNode.id));
                    z.focus();
                    return false;
            }
        case 39:
            switch (e.shiftKey)
            {
                case true:
                    return true;
                case false:
                    var s = nextCell(39,x,y.parentNode.parentNode.parentNode.parentNode.id);
                    if (s != null)
                    {
                        var z = document.getElementById(s);
                        z.focus();
                        return false;
                    } else return true;
            }
        default:
            return true;
    }
}
function decAppendix(x,e,keynum,change)
// decimal
{
    var y = document.getElementById(x);
    switch (keynum)
    {
        case 38:
            switch (e.shiftKey)
            {
                case true:
                    var i=0;
                    if (y.value != '') i = parseFloat(y.value.replace(",", "."));
                    y.value = (i + change).toString().replace(".", ",");
                    setSelectionRange(y, 0, y.value.length);
                    fireOnChange(y);
                    return false;
                case false:
                    var z = document.getElementById(nextCell(38,x,y.parentNode.parentNode.parentNode.parentNode.id));
                    z.focus();
                    return false;
            }
        case 40:
            switch (e.shiftKey)
            {
                case true:
                    var i=0;
                    if (y.value != '') i = parseFloat(y.value.replace(",", "."));
                    setSelectionRange(y, 0, y.value.length);
                    fireOnChange(y);
                    return false;
                case false:
                    var z = document.getElementById(nextCell(40,x,y.parentNode.parentNode.parentNode.parentNode.id));
                    z.focus();
                    return false;
            }
        case 37:
            switch (e.shiftKey)
            {
                case true:
                    return true;
                case false:
                    var z = document.getElementById(nextCell(37,x,y.parentNode.parentNode.parentNode.parentNode.id));
                    z.focus();
                    return false;
            }
        case 39:
            switch (e.shiftKey)
            {
                case true:
                    return true;
                case false:
                    var s = nextCell(39,x,y.parentNode.parentNode.parentNode.parentNode.id);
                    if (s != null)
                    {
                        var z = document.getElementById(s);
                        z.focus();
                        return false;
                    } else return true;
            }
        default:
            return true;
    }
}
function percAppendix(x,keychar)
// percent
{
    var s = newString(x,keychar);
    if (s == '') return true;
    if (!(parseFloat(s) >= 0)) return false;
    if (!(parseFloat(s) <= 100)) return false;
    return true;
}
function dateAppendix(e,x,keynum,keychar,change)
// date
{
    var m = [31,29,31,30,31,30,31,31,30,31,30,31];
    var y = document.getElementById(x);
    var s = y.value;
    var newValue = newString(x,keychar);
    var start = getSelectionStart(y);
    var end = getSelectionEnd(y);
    var t0 = s.split('.');
    var t = newValue.split('.');
    switch (keynum)
    {
        case 67:    // clear
            y.value = '';
            return false;
        case 68:    // today
            var now = new Date();
            y.value = now.getDate().toString() + '.' + (now.getMonth() + 1).toString() + '.' + now.getFullYear().toString();
            setSelectionRange(y, 0, (y.value.split('.'))[0].length);
            return false;
        case 84:    // tomoorow
            var now = new Date();
            y.value = (now.getDate() + 1).toString() + '.' + (now.getMonth() + 1).toString() + '.' + now.getFullYear().toString();
            setSelectionRange(y, 0, (y.value.split('.'))[0].length);
            return false;
        case 89:    // yesterday
            var now = new Date();
            y.value = (now.getDate() - 1).toString() + '.' + (now.getMonth() + 1).toString() + '.' + now.getFullYear().toString();
            setSelectionRange(y, 0, (y.value.split('.'))[0].length);
            return false;
        case 38:    // up arrow
            if (t0.length < 2) return false;
            IncDate(s, t0, y.id, start, end, 1);
            return false;
        case 40:    // down arrow
            if (t0.length < 2) return false;
            IncDate(s, t0, y.id, start, end, -1);
            return false;
        case 39:    // left arrow
            var y = document.getElementById(x);
            if (s.substring(start,end) == t0[0] && start == 0)
            {
                setSelectionRange(y, t0[0].length + 1, t0[0].length + t0[1].length + 1);
                return false;
            } else if (s.substring(start,end) == t0[1] && start == t0[0].length + 1)
            {
                setSelectionRange(y, t0[0].length + t0[1].length + 2, t0[0].length + t0[1].length + t0[2].length + 2);
                return false;
            } else if (s.substring(start,end) == t0[2] && start == t0[0].length + t0[1].length + 2)
            {
                setSelectionRange(y, 0, t0[0].length);
                return false;
            } else return true;
        case 37:    // right arrow
            var y = document.getElementById(x);
            if (s.substring(start,end) == t0[0] && start == 0)
            {
                setSelectionRange(y, t0[0].length + t0[1].length + 2, t0[0].length + t0[1].length + t0[2].length + 2);
                return false;
            } else if (s.substring(start,end) == t0[1] && start == t0[0].length + 1)
            {
                setSelectionRange(y, 0, t0[0].length);
                return false;
            } else if (s.substring(start,end) == t0[2] && start == t0[0].length + t0[1].length + 2)
            {
                setSelectionRange(y, t0[0].length + 1, t0[0].length + t0[1].length + 1);
                return false;
            } else return true;
    }
    if (/[0-9]/.test(keychar))
    {
        if (e.ctrlKey)
        {
            if (t.length < 2) return false;
            IncDate(s, t0, y.id, start, end, parseInt(keychar));
            return false;
        } else if (e.altKey)
        {
            if (t.length < 2) return false;
            IncDate(s, t0, y.id, start, end, - parseInt(keychar));
            return false;
        } else
        {
            switch (t0.length)
            {
                case 1:
                    if (t0[0].length == 2 && end == s.length)
                    {
                        y.value = t0[0] + '.' + keychar;
                        return false;
                    }
                    return parseInt(t[0]) <= 31;
                case 2:
                    if (t0[1].length == 2 && end == s.length)
                    {
                        y.value = t0[0] + '.' + t0[1] + '.' + keychar;
                        return false;
                    }
                    return parseInt(t[1]) <= 12 && parseInt(t[0]) <= m[parseInt(t[1] - 1)];
                case 3:
                    if (t[2].length > 4) return false;
                    if (t[2].length == 4) return parseInt(t[0]) <= daysInMonth(parseInt(t[1]),parseInt(t[2]));
            }
        }
    }
    return true;
}
