как исправить сценарий работы календаря?

Есть такой скрипт календаря, при попытке изменить html-код, удалить элементы (table class=table_month_horiz, table class=table_month_vert, span id=month_name, span id=num_year, button id=table_rotate),скрипт перестаёт работать, что либо показывать... Возможно ли как-то исправить код, чтобы на странице была только одна таблица, или table class=table_month_horiz или table class=table_month_vert и при нажатии кнопки менялся класс таблицы, с вертикальной на горизонтальную и обратно, чтобы при удалении кнопки отображалась только одна таблица указанная в html-коде, и при попытке удалить спаны (span id=month_name, span id=num_year), скрипт не перестал показывать таблицу, сделать типа сначала проверить есть ли на странице спаны с этими ид'ами и только после этого выводить текстом, название месяца и год. так возможно сделать на js?

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <style>
        #navigation_panel {
            white-space: nowrap;
            border: 1px solid hsl(0, 0%, 50%);
            border-radius: 6px;
            padding: 5px 15px;
            margin: 0 0 5px;
        }
        
        input {
            width: 56px;
            display: inline-block;
            text-align: center;
            border: 1px solid hsl(210, 100%, 50%);
            background-color: hsl(210, 100%, 90%);
            color: hsl(210, 100%, 50%);
            font: bold 14px serif;
        }
        
        #table_rotate {
            border: 1px solid hsl(210, 100%, 50%);
            border-radius: 12px 12px 0 12px;
            background-color: hsl(210, 100%, 90%);
            color: hsl(210, 100%, 50%);
        }
        
        select {
            border: 1px solid hsl(210, 100%, 50%);
            background-color: hsl(210, 100%, 90%);
            color: hsl(210, 100%, 50%);
            font: bold 14px serif;
        }
        
        .table_month_horiz,
        .table_month_vert {
            width: 250px;
            height: 250px;
            border: 1px solid hsl(0, 0%, 50%);
            border-radius: 6px;
        }
        
        td {
            border: 1px solid hsl(0, 0%, 50%);
            border-radius: 6px;
            text-align: center;
            font: 14px serif;
        }

        #num_year,
        #month_name {
            background-color: hsl(210, 100%, 95%);
            color: hsl(210, 100%, 50%);
            font: bold 14px serif;
            text-align: center;
        }

        #months_name {
            background-color: hsl(210, 100%, 95%);
            color: hsl(210, 100%, 50%);
            font: bold 14px serif;
            text-align: center;
            border: 1px solid hsl(0, 0%, 50%);
            border-radius: 6px;
            padding: 5px;
            margin: 0 0 5px;
        }

        #month {
            display: inline-block;
            border: 1px solid hsl(0, 0%, 50%);
            border-radius: 6px;
            padding: 5px;
            width: 250px;
        }

        #month_name {
            padding: 5px;
        }

        .table_month_vert,
        .table_month_horiz {
            table-layout: fixed;
            width: 100%;
            border-spacing: 3px;
        }

        .table_month_horiz tr td:nth-child(1) {
            width: 20%;
            background-color: hsl(210, 100%, 88%);
            color: hsl(210, 100%, 50%);
            font-weight: bold;
        } /* названия будних дней недели */
        
        .table_month_horiz tr:nth-child(n+6) td:nth-child(1) {
        width: 20%;
        background-color: hsl(348, 100%, 88%);
        color: hsl(348, 100%, 50%);
        font-weight: bold;
        } /* названия выходных дней недели */
        
        .table_month_horiz tr td:nth-child(n+2) {
        width: 20%;
        background-color: hsl(210, 100%, 95%);
        color: hsl(210, 100%, 50%);
        } /* будниe */
        
        .table_month_horiz tr:nth-child(n+6) td:nth-child(n+2) {
        width: 20%;
        background-color: hsl(348, 100%, 95%);
        color: hsl(348, 100%, 50%);
        } /* выходныe */
        
        .table_month_vert tr:nth-child(1) td.day {
            background-color: hsl(210, 100%, 88%);
            color: hsl(210, 100%, 50%);
            font-weight: bold;
        } /* названия будних дней недели */
        
        .table_month_vert tr:nth-child(1) td.day:nth-child(n+6) {
        background-color: hsl(348, 100%, 88%);
        color: hsl(348, 100%, 50%);
        font-weight: bold;
        } /* названия выходных дней недели */
        
        .table_month_vert tr:nth-child(n+2) td.day {
        background-color: hsl(210, 100%, 95%);
        color: hsl(210, 100%, 50%);
        } /* будниe */
        
        .table_month_vert tr:nth-child(n+2) td.day:nth-child(n+6) {
        background-color: hsl(348, 100%, 95%);
        color: hsl(348, 100%, 50%);
        } /* выходныe */

    </style>
</head>

<body>
    <div id="month">
        <div id="navigation_panel">
        <select id="select_month"></select>
        <input id="year_input" type="number" value="">
        <button id="table_rotate">➘</button>
        </div>
        <div id="months_name"><span id="month_name"></span><span id="num_year"></div> 
        <table class="table_month_horiz"></table>
        <table class="table_month_vert"></table>
    </div>
    <script>
        var calendar = {
            type: 'horiz',
            element: document.querySelector('.table_month_vert'),
            
            update: function(year, month) {
                this.year = year;
                this.month = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь', ][month];
                var startDay = new Date(year, month, 1);
                var offsetDay = (startDay.getDay() || 7) - 1;
                startDay.setDate(startDay.getDate() - offsetDay);
                var lastDay = new Date(startDay);
                var days = new Date(year, month + 1, 0).getDate();
                days = Math.ceil((days + offsetDay) / 7) * 7;
                lastDay.setDate(lastDay.getDate() + days);
                this.data = ['Пн.', 'Вт.', 'Ср.', 'Чт.', 'Пт.', 'Сб.', 'Вс.'];
                while (startDay < lastDay) {
                    this.data.push(startDay.getDate());
                    startDay.setHours(24);
                }
            },
            
            render2: function(horiz) {
                var html = '';
                if (horiz) {

                    this.element.classList.add("horiz");
                    for (var i = 0, j = 0; i < this.data.length; j = ++i % 7) {
                        if (j == 0) html += '<tr class="week">';
                        html += '<td class="day">' + this.data[i] + '</td>';
                        if (j == 6) html += '</td>';
                    }
                } else {
                    html = ['<tr class="week_day">', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>'];
                    for (var i = 0; i < this.data.length; i++) {
                        html[i % 7] += '<td class="day">' + this.data[i];
                    }
                    html = html.join('')
                }

                this.numYear.textContent = this.year;
                this.monthName.textContent = this.month;
                this.element.innerHTML = html;
            },
            render: function() {
                var html = '';
                if (this.type == 'vert') {
                    
                    this.element.innerHTML = '';
                    this.element = document.querySelector('.table_month_vert');
                    this.element.classList.add("horiz");
                    
                    for (var i = 0, j = 0; i < this.data.length; j = ++i % 7) {
                        if (j == 0) html += '<tr class="week">';
                        html += '<td class="day">' + this.data[i] + '</td>';
                        if (j == 6) html += '</td>';
                    }
                } else {
                    
                    this.element.innerHTML = '';
                    this.element = document.querySelector('.table_month_horiz');
                    html = ['<tr class="week_day">', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>'];
                    for (var i = 0; i < this.data.length; i++) {
                        html[i % 7] += '<td class="day">' + this.data[i];
                    }
                    html = html.join('');
                    
                }
                this.numYear.textContent = this.year;
                this.monthName.textContent = this.month;
                this.element.innerHTML = html;
            },
            toggle: function(){
                this.type = this.type == 'vert' ? 'horiz' : 'vert';
                this.render();
            },
        };
        var today = new Date(),
            thisYear = today.getFullYear(),
            thisMonth = today.getMonth();
        calendar.days = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
        calendar.numYear = document.querySelector('#num_year');
        calendar.monthName = document.querySelector('#month_name');
        calendar.update(thisYear, thisMonth);
        calendar.render();
        
        selector = document.querySelector('#select_month');
        month_list = ['Январь', 'Февраль', 'Март', 'Апрель', ' Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
        for (var i = 0; i < month_list.length; i++){
        selector.options[i] = new Option(month_list[i], i);
        }
        selector.selectedIndex = thisMonth;
        
        //Это для того, чтобы менять календарь при изменении месяца и года
        selector.addEventListener('change', load);
        document.querySelector('#year_input').addEventListener('input', load);
        
        document.getElementById('table_rotate').addEventListener('click', function() {

        calendar.toggle();
        });
        
        function load(){
        var year = document.getElementById('year_input').value;
        var month = selector.selectedIndex;
        calendar.update(year, month);
        calendar.render();
        }

        document.addEventListener("DOMContentLoaded", ()=>{
        document.querySelector('#year_input').value = thisYear;
        load();
        });
    </script>
</body>
</html>


Ответы (1 шт):

Автор решения: Andrey Semykin

var calendar = {
  type: 'horiz',
  element: document.querySelector('.table_month'),

  update: function(year, month) {
this.year = year;
this.month = ['Январь', 'Февраль', 'Март',
              'Апрель', 'Май', 'Июнь',
              'Июль', 'Август', 'Сентябрь',
              'Октябрь', 'Ноябрь', 'Декабрь', ][month];
var startDay = new Date(year, month, 1);
var offsetDay = (startDay.getDay() || 7) - 1;
startDay.setDate(startDay.getDate() - offsetDay);
var lastDay = new Date(startDay);
var days = new Date(year, month + 1, 0).getDate();
days = Math.ceil((days + offsetDay) / 7) * 7;
lastDay.setDate(lastDay.getDate() + days);
this.data = ['Пн.', 'Вт.', 'Ср.', 'Чт.', 'Пт.', 'Сб.', 'Вс.'];
while (startDay < lastDay) {
  this.data.push(startDay.getDate());
  startDay.setHours(24);
}
  },

  render2: function(horiz) {
var html = '';
if (horiz) {

  this.element.classList.add("horiz");
  for (var i = 0, j = 0; i < this.data.length; j = ++i % 7) {
    if (j == 0) html += '<tr class="week">';
    html += '<td class="day">' + this.data[i] + '</td>';
    if (j == 6) html += '</td>';
  }
} else {
  html = ['<tr class="week_day">', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>'];
  for (var i = 0; i < this.data.length; i++) {
    html[i % 7] += '<td class="day">' + this.data[i];
  }
  html = html.join('')
}

this.numYear.textContent = this.year;
this.monthName.textContent = this.month;
this.element.innerHTML = html;
  },
  render: function() {
var html = '';
if (this.type == 'vert') {

  this.element.innerHTML = '';
  this.element = document.querySelector('.table_month');
  this.element.classList.add("horiz");

  for (var i = 0, j = 0; i < this.data.length; j = ++i % 7) {
    if (j == 0) html += '<tr class="week">';
    html += '<td class="day">' + this.data[i] + '</td>';
    if (j == 6) html += '</td>';
  }
} else {

  this.element.innerHTML = '';
  this.element = document.querySelector('.table_month');
  html = ['<tr class="week_day">', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>', '<tr>'];
  for (var i = 0; i < this.data.length; i++) {
    html[i % 7] += '<td class="day">' + this.data[i];
  }
  html = html.join('');

}
this.numYear.textContent = this.year;
this.monthName.textContent = this.month;
this.element.innerHTML = html;
  },
  toggle: function() {
this.type = this.type == 'vert' ? 'horiz' : 'vert';
this.render();
  },
};
var today = new Date(),
  thisYear = today.getFullYear(),
  thisMonth = today.getMonth();
calendar.days = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
calendar.numYear = document.querySelector('#num_year');
calendar.monthName = document.querySelector('#month_name');
calendar.update(thisYear, thisMonth);
calendar.render();

selector = document.querySelector('#select_month');
month_list = ['Январь', 'Февраль', 'Март', 
          'Апрель', ' Май', 'Июнь', 
          'Июль', 'Август', 'Сентябрь', 
          'Октябрь', 'Ноябрь', 'Декабрь'];
for (var i = 0; i < month_list.length; i++) {
  selector.options[i] = new Option(month_list[i], i);
}
selector.selectedIndex = thisMonth;

//Это для того, чтобы менять календарь при изменении месяца и года
selector.addEventListener('change', load);
document.querySelector('#year_input').addEventListener('input', load);

document.getElementById('table_rotate').addEventListener('click', function() {

  calendar.toggle();
});

function load() {
  var year = document.getElementById('year_input').value;
  var month = selector.selectedIndex;
  calendar.update(year, month);
  calendar.render();
}

document.addEventListener("DOMContentLoaded", () => {
  document.querySelector('#year_input').value = thisYear;
  load();
});
#navigation_panel {
  white-space: nowrap;
  border: 1px solid hsl(0, 0%, 50%);
  border-radius: 6px;
  padding: 5px 15px;
  margin: 0 0 5px;
}

input {
  width: 56px;
  display: inline-block;
  text-align: center;
  border: 1px solid hsl(210, 100%, 50%);
  background-color: hsl(210, 100%, 90%);
  color: hsl(210, 100%, 50%);
  font: bold 14px serif;
}

#table_rotate {
  border: 1px solid hsl(210, 100%, 50%);
  border-radius: 12px 12px 0 12px;
  background-color: hsl(210, 100%, 90%);
  color: hsl(210, 100%, 50%);
}

select {
  border: 1px solid hsl(210, 100%, 50%);
  background-color: hsl(210, 100%, 90%);
  color: hsl(210, 100%, 50%);
  font: bold 14px serif;
}

.table_month_horiz,
.table_month_vert {
  width: 250px;
  height: 250px;
  border: 1px solid hsl(0, 0%, 50%);
  border-radius: 6px;
}

td {
  border: 1px solid hsl(0, 0%, 50%);
  border-radius: 6px;
  text-align: center;
  font: 14px serif;
}

#num_year,
#month_name {
  background-color: hsl(210, 100%, 95%);
  color: hsl(210, 100%, 50%);
  font: bold 14px serif;
  text-align: center;
}

#months_name {
  background-color: hsl(210, 100%, 95%);
  color: hsl(210, 100%, 50%);
  font: bold 14px serif;
  text-align: center;
  border: 1px solid hsl(0, 0%, 50%);
  border-radius: 6px;
  padding: 5px;
  margin: 0 0 5px;
}

#month {
  display: inline-block;
  border: 1px solid hsl(0, 0%, 50%);
  border-radius: 6px;
  padding: 5px;
  width: 250px;
}

#month_name {
  padding: 5px;
}

.table_month_vert,
.table_month_horiz {
  table-layout: fixed;
  width: 100%;
  border-spacing: 3px;
}

.table_month_horiz tr td:nth-child(1) {
  width: 20%;
  background-color: hsl(210, 100%, 88%);
  color: hsl(210, 100%, 50%);
  font-weight: bold;
}


/* названия будних дней недели */

.table_month_horiz tr:nth-child(n+6) td:nth-child(1) {
  width: 20%;
  background-color: hsl(348, 100%, 88%);
  color: hsl(348, 100%, 50%);
  font-weight: bold;
}


/* названия выходных дней недели */

.table_month_horiz tr td:nth-child(n+2) {
  width: 20%;
  background-color: hsl(210, 100%, 95%);
  color: hsl(210, 100%, 50%);
}


/* будниe */

.table_month_horiz tr:nth-child(n+6) td:nth-child(n+2) {
  width: 20%;
  background-color: hsl(348, 100%, 95%);
  color: hsl(348, 100%, 50%);
}


/* выходныe */

.table_month_vert tr:nth-child(1) td.day {
  background-color: hsl(210, 100%, 88%);
  color: hsl(210, 100%, 50%);
  font-weight: bold;
}


/* названия будних дней недели */

.table_month_vert tr:nth-child(1) td.day:nth-child(n+6) {
  background-color: hsl(348, 100%, 88%);
  color: hsl(348, 100%, 50%);
  font-weight: bold;
}


/* названия выходных дней недели */

.table_month_vert tr:nth-child(n+2) td.day {
  background-color: hsl(210, 100%, 95%);
  color: hsl(210, 100%, 50%);
}


/* будниe */

.table_month_vert tr:nth-child(n+2) td.day:nth-child(n+6) {
  background-color: hsl(348, 100%, 95%);
  color: hsl(348, 100%, 50%);
}


/* выходныe */
<div id="month">
  <div id="navigation_panel">
<select id="select_month"></select>
<input id="year_input" type="number" value="">
<button id="table_rotate">➘</button>
  </div>
  <div id="months_name"><span id="month_name"></span><span id="num_year"></span>
<table class="table_month"></table>

  </div>

→ Ссылка