skip to Main Content

Basically im trying to do some calendar knowledge , the calendar fetches the events from google , but thats not the issue. That part is done. I have this logic that im not being able to implement . The desired behavior is showing only future dates for example: we are in 2024 july , so in month dropdown when 2024 is chosen it should only display current month and further and when any other year after the current year is selected it should display all months. This part is working well .
The biig issue right now is when i’m viewing for example 2025 march which is an year after current year and a month before current month if i try to switch the view to 2024 the month dropdown should default to july(current month) and the variables associated to it for the calendar rendering should be updated aswell.That’s not happening though, it goes to an not existent option in the dropdown. i’ve been looking and trying for hours so i’m here in stackoverflow in hopes of a solution. Sorry for the text , im tired and i might’ve written some confusing things so ask me something and i’ll obviously glady reply! Thanks in advance.

function populateMonths() {
    const selectMonth = document.getElementById('selectMonth');
    const currentYear = new Date().getFullYear();
    const currentMonth = new Date().getMonth();
    const months = [
        'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 
        'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
    ];

    selectMonth.innerHTML = ''; // Clear existing options

    let startMonth = 0;
    if (selectedYear === currentYear) {
        startMonth = currentMonth; // Show from current month onwards
    }

    console.log(`currentYear: ${currentYear}`);
    console.log(`currentMonth: ${currentMonth}`);
    console.log(`selectedYear: ${selectedYear}`);
    console.log(`selectedMonth: ${selectedMonth}`);
    console.log(`startMonth: ${startMonth}`);

    months.slice(startMonth).forEach((month, index) => {
        const monthIndex = startMonth + index;
        const option = document.createElement('option');
        option.value = monthIndex; // Adjust value to reflect actual month index
        option.textContent = months[monthIndex];
        selectMonth.appendChild(option);
    });

    selectMonth.selectedIndex = selectedMonth - startMonth;

    console.log(`Final selectedIndex: ${selectMonth.selectedIndex}`);
}






function populateYears() {
    const selectYear = document.getElementById('selectYear');
    const currentYear = new Date().getFullYear();
    const yearsToShow = 3; // Number of years to show, starting from the current year

    selectYear.innerHTML = ''; // Clear existing options

    for (let i = 0; i < yearsToShow; i++) {
        const year = currentYear + i;
        const option = document.createElement('option');
        option.value = year;
        option.textContent = year;
        selectYear.appendChild(option);
    }

    selectYear.value = selectedYear;
}

function changeMonth() {
    selectedMonth = parseInt(document.getElementById('selectMonth').value);
    renderCalendar(selectedYear, selectedMonth);
}

function changeYear() {
    selectedYear = parseInt(document.getElementById('selectYear').value);
    populateMonths();
    renderCalendar(selectedYear, selectedMonth);
}

function renderCalendar(year, month) {
    const calendar = document.getElementById('calendar');
    calendar.innerHTML = '';

    const firstDayOfMonth = new Date(year, month, 1);
    const lastDayOfMonth = new Date(year, month + 1, 0);
    const daysInMonth = lastDayOfMonth.getDate();

    const startingDay = firstDayOfMonth.getDay(); // 0 (Sunday) to 6 (Saturday)
    const daysOfWeek = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'];

    // Create header row for days of the week
    for (let day = 0; day < 7; day++) {
        const cell = document.createElement('div');
        cell.classList.add('cell', 'header-cell');
        cell.textContent = daysOfWeek[day];
        calendar.appendChild(cell);
    }

    // Create blank cells for the days before the first day of the month
    for (let i = 0; i < startingDay; i++) {
        const cell = document.createElement('div');
        cell.classList.add('cell', 'empty-cell');
        calendar.appendChild(cell);
    }

    // Create cells for each day in the month
    for (let i = 1; i <= daysInMonth; i++) {
        const date = new Date(year, month, i);
        const dateString = formatDate(date); // Format date to 'YYYY-MM-DD'

        const cell = document.createElement('div');
        cell.classList.add('cell');
        cell.textContent = i;

        const dayEvents = events.filter(event => event.date === dateString);

        if (isFullyBooked(dateString)) {
            cell.classList.add('booked');
            cell.title = 'Totalmente reservado';
        } else if (isHalfBooked(dayEvents)) {
            cell.classList.add('half-booked');
            cell.title = 'Parcialmente reservado';
            cell.addEventListener('mouseover', () => showAvailableHoursTooltip(cell, dayEvents));
            cell.addEventListener('mouseout', hideTooltip);
        } else {
            cell.classList.add('available');
            cell.title = 'Disponível';
        }

        calendar.appendChild(cell);
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    let selectedYear = new Date().getFullYear();
    let selectedMonth = new Date().getMonth();
    
    function populateMonths() {
        const selectMonth = document.getElementById('selectMonth');
        const currentYear = new Date().getFullYear();
        const currentMonth = new Date().getMonth();
        const months = [
            'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 
            'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
        ];
    
        selectMonth.innerHTML = ''; // Clear existing options
    
        let startMonth = 0;
        if (selectedYear === currentYear) {
            startMonth = currentMonth; // Show from current month onwards
        }
    
        months.slice(startMonth).forEach((month, index) => {
            const monthIndex = startMonth + index;
            const option = document.createElement('option');
            option.value = monthIndex; // Adjust value to reflect actual month index
            option.textContent = months[monthIndex];
            selectMonth.appendChild(option);
        });
    
        // If the selected month is before the current month, reset it to the current month
        if (selectedYear === currentYear && selectedMonth < currentMonth) {
            selectedMonth = currentMonth;
        }
    
        selectMonth.selectedIndex = selectedMonth - startMonth;
    
        console.log(`Final selectedIndex: ${selectMonth.selectedIndex}`);
    }
    
    function populateYears() {
        const selectYear = document.getElementById('selectYear');
        const currentYear = new Date().getFullYear();
        const yearsToShow = 3; // Number of years to show, starting from the current year
    
        selectYear.innerHTML = ''; // Clear existing options
    
        for (let i = 0; i < yearsToShow; i++) {
            const year = currentYear + i;
            const option = document.createElement('option');
            option.value = year;
            option.textContent = year;
            selectYear.appendChild(option);
        }
    
        selectYear.value = selectedYear;
    }
    
    function changeMonth() {
        selectedMonth = parseInt(document.getElementById('selectMonth').value);
        renderCalendar(selectedYear, selectedMonth);
    }
    
    function changeYear() {
        selectedYear = parseInt(document.getElementById('selectYear').value);
        populateMonths();
        renderCalendar(selectedYear, selectedMonth);
    }

    literally

    if (selectedYear === currentYear && selectedMonth < currentMonth) {
            selectedMonth = currentMonth;
        }
    

    in populateMonths solved it!


  2. Hope this helps, the code is a lot less complicated than I thought. Play around with the select to see the functionality to help you understand what this code does. I’ve not implemented populate years so I assume that is already correct. You can convert the event listeners to the respective changeMonth and changeYears functions you had in your original code. The code below is to only help you get the select functionality to work as you intended it to.

    const months = [
      'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 
      'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
    ]
    
    
    
    const selectMonth = document.getElementById('selectMonth')
    const selectYear = document.getElementById('selectYear')
    
    
    
    function filteredMonths(year) {
        const currentYear = new Date().getFullYear();
        const currentMonth = new Date().getMonth();
        
        if (year > currentYear) return months // return all months if future year
        
        return months.slice(currentMonth, months.length)
    }
    
    
    let lastMonthSelected = null // helps with month memory
    
    
    function populateMonths(year) {
        const validMonths = filteredMonths(year)
        const currentMonth = new Date().getMonth();
        
        selectMonth.innerHTML = ''
    
        validMonths.forEach(monthName => {
            const option = document.createElement('option');
            option.value = months.indexOf(monthName); 
            option.textContent = monthName
            selectMonth.appendChild(option);
        });
        
        // if month = 'Outubro' and year change to 2025, stay selected on 'Outubro' still
        if (lastMonthSelected && validMonths.indexOf(lastMonthSelected) > -1) {
          selectMonth.selectedIndex = validMonths.indexOf(lastMonthSelected);
          return
        }
        
        const currentMonthIndex = validMonths.indexOf(months[currentMonth])
        const startIndex = currentMonthIndex > -1 ? currentMonthIndex : 0
    
        selectMonth.selectedIndex = startIndex;
        lastMonthSelected = months[currentMonth]
    }
    
    
    
    function updateMonthOptions() {
      const year = selectYear.value || 2024; // set defaults too
      populateMonths(year)
      // you dont need to store the selected year or month in a variable unless you need it for another part of your program, but if you did need it, add it here
    }
    
    
    
    selectYear.addEventListener('change', updateMonthOptions);
    selectMonth.addEventListener('change', () => {
       lastMonthSelected = selectMonth.options[selectMonth.selectedIndex].text
    });
    updateMonthOptions() // call once in beginning to set defaults
    <select id="selectYear">
      <option value="2024">2024</option>
      <option value="2025">2025</option>
      <option value="2026">2026</option>
    </select>
    <select id="selectMonth">
        <!-- Options will be dynamically populated -->
    </select>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search