1

I'm trying to draw table having 3 rows. First row should have month name, second - number of day in month and third day of week. Something like this: enter image description here

I managed to do something that looks like this, but only for 2013. What I would like to get custom table for specific time period. So if I specify that I want table from 2013-01-15 to 2013-02-10 then it will have 27 columns in second and third row and 2 in first (with correct rowspan).

This is what I have right now: http://jsfiddle.net/Misiu/amEug/

This is my code for table generation for current year:

var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var dayNames = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Sn"];
var months = '';
for (var i = 0; i < monthNames.length; i++) {
    months += '<td colspan="' + monthDays[i] + '">' + monthNames[i] + '</td>';
}
$('tr#months').html(months);

var numbers = '';
var counter = 1;
var month = 0;
for (i = 0; i < 365; i++) {
    numbers += '<td>' + counter + '</td>';
    counter++;
    if (counter > monthDays[month]) {
        month++;
        counter = 1;
    }
}
$('tr#numbers').html(numbers);

var days = '';
var day = 0;
for (i = 0; i < 365; i++) {
    days += '<td' + (dayNames[day] == 'Sa' || dayNames[day] == 'Sn' ? ' class="weekend"' : '') + '>' + dayNames[day] + '</td>';
    day++;
    if (day > 6) day = 0;
}
$('tr#days').html(days);

Also I would like it to be as fast as possible, because if for some reason I would need large time period (4 years) I would like it to render fast (even on IE8).

Any advice on how to get this working will help. I've looked at jQuery UI datepicker code, but it is complex and has all features I don't need.

Shikiryu
  • 10,180
  • 8
  • 49
  • 75
Misiu
  • 4,738
  • 21
  • 94
  • 198
  • Have a look at my post here. It might help you do this a bit easier by using the Date object and extending it's functionality. http://stackoverflow.com/a/16406643/2356007 – jmiraglia May 15 '13 at 20:12
  • @jasonmmiraglia - this is same thing I had in mind :) I event started adding similar things inside jsfiddle – Misiu May 15 '13 at 20:16

3 Answers3

1

I would definitely use javascript built in date functions for this. You could do (not perfect but quickly wrote something that works):

var weekday=["Su", "Mo","Tu","We","Th","Fr","Sa"];
var months=["Jan", "Feb","Mar","Apr","May","Jun","Jul", "Aug","Sep","Oct","Nov","Dec"];
var start = new Date(2013,0,15); //months start at 0...
var end = new Date(2013,01,10);
var month = {};
var row1 = "<tr>";
var row2 = "<tr>";
var row3 = "<tr>";
for (start; start<end; start.setDate(start.getDate()+1)) {
    row2 += '<td>' + start.getDate() + '</td>';
    row3 += '<td>' + weekday[start.getDay()] + '</td>';
    month[months[start.getMonth()]] = typeof(month[months[start.getMonth()]])=="undefined"?1:month[months[start.getMonth()]]+1;
}
for (i=0; i<months.length; i++) {
    if (typeof(month[months[i]]) !== "undefined") {
       row1 += "<td colspan="+month[months[i]]+">"+months[i]+"</td>";
    }
}
row1 += "</tr>";
row2 += "</tr>";
row3 += "</tr>";
table = "<table>" + row1+row2+row3 + "</table>";
dave
  • 62,300
  • 5
  • 72
  • 93
  • One more question - why defining dates like so `var end = new Date("2013-12-31");`,`end = new Date(2013,11,31);` generates different table? When I use second option I get only 30 days in December. Please clear this out :) – Misiu May 15 '13 at 20:25
  • You may need to change `start – dave May 15 '13 at 21:55
1

This is my final solution:

var weekday = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

function renderHead(div, start, end) {
    var c_year = start.getFullYear();
    var r_year = "<tr>";
    var daysInYear = 0;

    var c_month = start.getMonth();
    var r_month = "<tr>";
    var daysInMonth = 0;

    var r_days = "<tr>";
    var r_days2 = "<tr>";
    for (start; start <= end; start.setDate(start.getDate() + 1)) {

        if (start.getFullYear() !== c_year) {
            r_year += '<td colspan="' + daysInYear + '">' + c_year + '</td>';
            c_year = start.getFullYear();
            daysInYear = 0;
        }
        daysInYear++;

        if (start.getMonth() !== c_month) {
            r_month += '<td colspan="' + daysInMonth + '">' + months[c_month] + '</td>';
            c_month = start.getMonth();
            daysInMonth = 0;
        }
        daysInMonth++;

        r_days += '<td>' + start.getDate() + '</td>';
        r_days2 += '<td>' + weekday[start.getDay()] + '</td>';
    }
    r_days += "</tr>";
    r_days2 += "</tr>";
    r_year += '<td colspan="' + (daysInYear) + '">' + c_year + '</td>';
    r_year += "</tr>";
    r_month += '<td colspan="' + (daysInMonth) + '">' + months[c_month] + '</td>';
    r_month += "</tr>";
    table = "<table>" + r_year + r_month + r_days + r_days2 + "</table>";

    div.html(table);
}

And here is working demo: http://jsfiddle.net/Misiu/sBCbC/10/

Misiu
  • 4,738
  • 21
  • 94
  • 198
0

Taking Misiu's code (answered in 2013, here his link to his working sample: http://jsfiddle.net/Misiu/sBCbC/10/ ) here is my solution, adding table (css) classes from Bootstrap5 and JSTL internazionalizated String for Months and Days.

I passed a Date (with tarea.getFechaInicio f.E., stored in MySQL) instead of giving manually the 3 parameters of "new Date" on the renderHead() method.

 <script type="application/javascript">
    var weekday = [
        "<fmt:message key="dia.domingo" />",
        "<fmt:message key="dia.lunes" />",
        "<fmt:message key="dia.martes" />",
        "<fmt:message key="dia.miercoles" />",
        "<fmt:message key="dia.jueves" />",
        "<fmt:message key="dia.viernes" />",
        "<fmt:message key="dia.sabado" />",
        ];
    var months = [
        "<fmt:message key="mes.enero" />",
        "<fmt:message key="mes.febrero" />",
        "<fmt:message key="mes.marzo" />",
        "<fmt:message key="mes.abril" />",
        "<fmt:message key="mes.mayo" />",
        "<fmt:message key="mes.junio" />",
        "<fmt:message key="mes.julio" />",
        "<fmt:message key="mes.agosto" />",
        "<fmt:message key="mes.septiembre" />",
        "<fmt:message key="mes.octubre" />",
        "<fmt:message key="mes.noviembre" />",
        "<fmt:message key="mes.Diciembre" />"
    ];


    function renderHead(div, start, end) {
        var c_year = start.getFullYear();
        var r_year = "<tr>";
        var daysInYear = 0;

        var c_month = start.getMonth();
        var r_month = "<tr>";
        var daysInMonth = 0;

        var r_days = "<tr>";
        var r_days2 = "<tr>";
        for (start; start <= end; start.setDate(start.getDate() + 1)) {

            if (start.getFullYear() !== c_year) {
                r_year += '<td colspan="' + daysInYear + '">' + c_year + '</td>';
                c_year = start.getFullYear();
                daysInYear = 0;
            }
            daysInYear++;

            if (start.getMonth() !== c_month) {
                r_month += '<td colspan="' + daysInMonth + '">' + months[c_month] + '</td>';
                c_month = start.getMonth();
                daysInMonth = 0;
            }
            daysInMonth++;

            r_days += '<td>' + start.getDate() + '</td>';
            r_days2 += '<td>' + weekday[start.getDay()] + '</td>';
        }
        r_days += "</tr>";
        r_days2 += "</tr>";
        r_year += '<td colspan="' + (daysInYear) + '">' + c_year + '</td>';
        r_year += "</tr>";
        r_month += '<td colspan="' + (daysInMonth) + '">' + months[c_month] + '</td>';
        r_month += "</tr>";
        table = "<table  class='table table-bordered table-responsive table-striped text-center>'" + r_year + r_month + r_days + r_days2 + "</table>";

        div.html(table);
    }
  //  renderHead($('div#table1'), new Date(2013, 0, 20), new Date(2015, 1, 5));
    renderHead($('div#table1'), new Date('<%=tarea.getFechaInicio()%>'),new Date('<%=tarea.getFechaFin()%>') );
ieselisra
  • 387
  • 4
  • 16