ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Category:

JavaScript: задача по созданию HTML-календаря

Решил задачу «Создайте календарь в виде таблицы» к подразделу 1.7 «Изменение документа» второй части учебника по JavaScript.

Стили для будущей таблицы уже заданы в заголовочной части (тег head) HTML-страницы. Кроме этого, на HTML-странице задан контейнер, куда нужно поместить созданную таблицу:
<div id="calendar"></div>

Требуется написать функцию на языке JavaScript, которая будет вызываться, к примеру, так:
createCalendar(calendar, 2012, 9); // сентябрь 2012 года

Эта функция должна создать календарь за указанный месяц указанного года в виде HTML-таблицы и поместить эту HTML-таблицу в указанный контейнер calendar. На HTML-странице в браузере такая таблица-календарь должна выглядеть примерно так:

пнвтсрчтптсбвс
12
3456789
10111213141516
17181920212223
24252627282930

HTML-таблица создается с помощью HTML-элементов table (таблица целиком), tr (строки таблицы, представляющие недели), th (ячейки заголовочной части таблицы, содержащие сокращенные названия дней недели) и td (ячейки таблицы, содержащие даты).

Итак, наша задача — написать функцию:
function createCalendar(elem, year, month) {
    // ... наш код ...
}

Очевидно, что должен быть некий цикл, в котором будем проходить даты заданного временного промежутка. Следовательно, должна быть некая переменная, назовём ее cur_date, которая будет содержать текущую дату и служить чем-то вроде счетчика (будем листать ее день за днем). Меняем код:
function createCalendar(elem, year, month) {
    let cur_date = new Date(year, month - 1, 1);      // текущая дата

    while (  ) {                                      // цикл
    
    }
}
Начальным значением переменной cur_date возьмём первое число заданного месяца заданного года. Тут нужно отметить, что пользователь нашей функции задаёт месяц целым числом от 1 до 12, а в языке JavaScript месяцы представляются целым числом от 0 до 11 (даты — числом от 1 до 31). Поэтому мы должны вычесть из переменной month единицу, чтобы получить нужное представление месяца для JavaScript.

Так как таблицу в любом случае необходимо начать строить с понедельника, то нужно отмотать наш счетчик cur_date в прошлое до ближайшего понедельника (он может быть в предыдущем месяце). Меняем код:
function createCalendar(elem, year, month) {
    let cur_date = new Date(year, month - 1, 1);      // текущая дата

    while ( cur_date.getDay() != 1 ) {                // находим ближайший понедельник
        cur_date.setDate(cur_date.getDate() - 1);     // слева
    }

    while (  ) {                                      // основной цикл
    
    }
}
Дни недели в языке JavaScript представляются целым числом от 0 до 6, причем отсчет начинается с воскресенья (обозначается нулем), понедельник обозначается единицей и так далее до субботы, которая обозначается числом 6. День недели определяем по текущей дате в переменной cur_date с помощью метода getDay. Условие продолжения работы цикла cur_date.getDay() != 1 читается как «пока не найден понедельник».

Основной цикл у нас будет листать недели, а внутри основного цикла создадим подцикл, который будет строить очередную неделю. Меняем код:
function createCalendar(elem, year, month) {
    let cur_date = new Date(year, month - 1, 1);      // текущая дата

    while ( cur_date.getDay() != 1 ) {                // находим ближайший понедельник
        cur_date.setDate(cur_date.getDate() - 1);     // слева
    }

    while (  ) {                                      // основной цикл (строим таблицу)

        for (let i = 0; i < 7; i++) {                 // строим очередную неделю

        }
    }
}

В полученный скелет добавляем создание HTML-элементов HTML-таблицы. Меняем код:
function createCalendar(elem, year, month) {
    let cur_date = new Date(year, month - 1, 1);      // текущая дата

    while ( cur_date.getDay() != 1 ) {                // находим ближайший понедельник
        cur_date.setDate(cur_date.getDate() - 1);     // (листаем дату назад)
    }

    let table = document.createElement("table");

    while ( /* условие */ ) {                         // строим таблицу
        let tr = document.createElement("tr");
        for (let i = 0; i < 7; i++) {                 // строим очередную неделю
            let td = document.createElement("td");
            td.textContent = cur_date.getDate();
            tr.append(td);
            cur_date.setDate(cur_date.getDate() + 1); // листаем дату вперёд
        }
        table.append(tr);
    }
    elem.append(table);                               // добавляем таблицу в заданный контейнер
}
Синим пометил места, в которых создаются конкретные HTML-элементы.

Цикл построения таблицы должен завершиться, когда текущая дата cur_date выйдет в следующий месяц. Чтобы засечь этот момент, я создал еще одну переменную fin_date, содержащую последнюю дату заданного месяца. Тогда условием продолжения цикла можно взять cur_date <= fin_date.

Кроме этого, нужно добавить заголовок таблицы с сокращенными названиями дней недели.

И последнее — поставим на строку вывода очередной даты td.textContent = cur_date.getDate(); условие, при котором будут выводиться только даты заданного месяца.

Меняем код:
function createCalendar(elem, year, month) {
    let cur_date = new Date(year, month - 1, 1);      // текущая дата
    let fin_date = new Date(year, month, 0);          // последняя дата заданного месяца

    while ( cur_date.getDay() != 1 ) {                // находим ближайший понедельник
        cur_date.setDate(cur_date.getDate() - 1);     // (листаем дату назад)
    }

    let table = document.createElement("table");      // заголовок таблицы
    table.innerHTML = "<tr><th>пн</th><th>вт</th><th>ср</th>" +
                      "<th>чт</th><th>пт</th><th>сб</th><th>вс</th></tr>";

    while ( cur_date <= fin_date ) {                  // строим таблицу
        let tr = document.createElement("tr");
        for (let i = 0; i < 7; i++) {                 // строим очередную неделю
            let td = document.createElement("td");
            if ( cur_date.getMonth() == month - 1 ) { // показывать только даты заданного
                td.textContent = cur_date.getDate();  // месяца
            }
            tr.append(td);
            cur_date.setDate(cur_date.getDate() + 1); // листаем дату вперёд
        }
        table.append(tr);
    }

    elem.append(table);                               // добавляем таблицу в заданный контейнер
}

Это окончательный вариант.
Tags: Образование, Программирование
Subscribe

Recent Posts from This Journal

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments