0

I'm currently working on a little project for my office as a learning exercise. We have a tradition to bring food with us every monday so I tried to make a program that shows when eachs turn is. Currently my Webpage is able to create a calendar with a spare column for the color of a user.

(The current progress without the CSS file is linked below)

Now I want to assign a color to the coresponding user. I am able to write the PHP method but I am unsure how to put the returned value into the field. When I tried to use an AJAX method the resulting text was 'undefined'. So I read into it and realized that the AJAX functions are being executed parallel to the other processes.

Now the main question: Can I somehow make JavaScript wait until the Variables have returned befor further bulding the calendar? Or should I insert the colors afterwards. If so: How could I do it?

I don't necesseraly need writen code. Some explanation or ideas would be enough.

Thank you!

today = new Date();
currentMonth = today.getMonth();
currentYear = today.getFullYear();
currentWeek = getWeekNumber(today);
selectYear = document.getElementById("year");
selectMonth = document.getElementById("month");

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

monthAndYear = document.getElementById("monthAndYear");
showCalendar(currentMonth, currentYear);




function next() {
    currentYear = (currentMonth === 11) ? currentYear + 1 : currentYear;
    currentMonth = (currentMonth + 1) % 12;
    showCalendar(currentMonth, currentYear);
}

function previous() {
    currentYear = (currentMonth === 0) ? currentYear - 1 : currentYear;
    currentMonth = (currentMonth === 0) ? 11 : currentMonth - 1;
    showCalendar(currentMonth, currentYear);
}

function jump() {
    currentYear = parseInt(selectYear.value);
    currentMonth = parseInt(selectMonth.value);
    showCalendar(currentMonth, currentYear);
}


function showCalendar(month, year) {

    let firstDay = (new Date(year, month)).getDay();

    tbl = document.getElementById("calendar-body"); // body of the calendar

    // clearing all previous cells
    tbl.innerHTML = "";

    // filing data about month and in the page via DOM.
    monthAndYear.innerHTML = months[month] + " " + year;
    selectYear.value = year;
    selectMonth.value = month;

    // creating all cells



    let helper = 0;
    let dt = new Date(year,month,1);
    let date = (1+germanDate(dt.getDay()));

    // document.getElementById('dies').innerHTML = ((dt.getDay())+"<br />"+daysInMonth(month, year)+"<br />"+date);


    for (let i = 0; i < 6; i++) {
        // creates a table row
        let row = document.createElement("tr");

        //creating individual cells, filing them up with data.
            if (date > daysInMonth(month, year)) {
                if (helper<5){
                    while (helper<5){
                        let row = document.createElement("tr");
                        cell = document.createElement("td");
                        cell.classList.add("text-white");
                        cell.classList.add("bg-white");
                        cell.setAttribute('disabled', true);
                        cellText = document.createTextNode('|');
                        cell.appendChild(cellText);
                        row.appendChild(cell);
                        tbl.appendChild(row);
                        helper++;
                    }
                }
                break;
            }

            else {
                let dt = new Date(year,month,date)
                cell = document.createElement("td");

                    cellText = document.createTextNode(''+getWeekNumber(dt)+'. Week'); //insert weeknumber

                if (getWeekNumber(dt) === currentWeek && year === today.getFullYear() && month === today.getMonth()) {
                    cell.classList.add("table-info");   //if the week is the current one, make the cell blue
                } // color today's date
                cell.classList.add("cursorPointer");    //CSS -> change Cursor on hover
                cell.classList.add("col-11");

                cell.appendChild(cellText);
                row.appendChild(cell);

                cell = document.createElement("td");    //New cell for the color
                cellText = document.createTextNode('');
                cell.classList.add("col-1");
                cell.classList.add("table-white");
                cell.appendChild(cellText);
                row.appendChild(cell);


                date+=7;
                helper++;

            }

        tbl.appendChild(row); // appending each row into calendar body.
    }

}



var result = getWeekNumber(new Date());
document.write('It\'s currently week ' +result +'');


// check how many days in a month code from https://dzone.com/articles/determining-number-days-month
function daysInMonth(iMonth, iYear) {
    return 32 - new Date(iYear, iMonth, 32).getDate();
}

//By RobG https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php
function getWeekNumber(d) {
    // Copy date so don't modify original
    d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
    // Set to nearest Thursday: current date + 4 - current day number
    // Make Sunday's day number 7
    d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
    // Get first day of year
    var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
    // Calculate full weeks to nearest Thursday
    var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
    // Return array of year and week number
    return weekNo;
}



function goToDetails(monat, jahr){
    window.open('?kalenderDetails&jahr='+jahr+'&woche='+monat);
}

function germanDate($datum){
    switch($datum){
        case 1: return 0;
        case 0: return 1;
        default: return (8-$datum);
    }
}
.table {
    border-collapse: collapse !important; }
    .table td,
    .table th {
      background-color: #fff !important; }

  .table-bordered th,
  .table-bordered td {
    border: 1px solid #dee2e6 !important; }

  .table-dark {
    color: inherit; }
    .table-dark th,
    .table-dark td,
    .table-dark thead th,
    .table-dark tbody + tbody {
      border-color: #dee2e6; }

  .table .thead-dark th {
    color: inherit;
    border-color: #dee2e6; } }

/*# sourceMappingURL=main.css.map */
<!DOCTYPE html>
<html lang="de">

<head>
    <meta charset="utf-8">


    <link rel="icon" href="as" id=icon>


    <script src="JavaScript/Icon.js"> </script>
</head>

<body style="min-height: 100%">


<div class='container-fluid' style='height: 100%'>
    <div class="row" style="margin-top: 2em">
                    <div class="container col-12 col-lg-6">
                            <div class="card">
                                <h3 class="card-header" id="monthAndYear"></h3>
                                <div class="table-responsive">
                                    <table class="table table-bordered table-hover" id="calendar">
                            
                                        <tbody id="calendar-body">
                            
                                        </tbody>
                                    </table>
                                </div>
                        
                                <div class="form-inline">
                        
                                    <button class="btn btn-outline-primary col-sm-6 rounded-0" id="previous" onclick="previous()">Previous</button>
                        
                                    <button class="btn btn-outline-primary col-sm-6 rounded-0" id="next" onclick="next()">Next</button>
                                </div>
                                <br/>
                                <form class="form-inline">
                                    <label class="col-sm-4 text-left" for="month">Jump To: </label>
                                    <select class="form-control col-sm-4 rounded-0" name="month" id="month" onchange="jump()">
                                        <option value=0>Jan</option>
                                        <option value=1>Feb</option>
                                        <option value=2>Mar</option>
                                        <option value=3>Apr</option>
                                        <option value=4>May</option>
                                        <option value=5>Jun</option>
                                        <option value=6>Jul</option>
                                        <option value=7>Aug</option>
                                        <option value=8>Sep</option>
                                        <option value=9>Oct</option>
                                        <option value=10>Nov</option>
                                        <option value=11>Dec</option>
                                    </select>
                        
                        
                                    <label for="year"></label><select class="form-control col-sm-4 rounded-0" name="year" id="year" onchange="jump()">
                                    <option value=2018>2018</option>
                                    <option value=2019>2019</option>
                                    <option value=2020>2020</option>
                                    <option value=2021>2021</option>
                                    <option value=2022>2022</option>
                                    <option value=2023>2023</option>
                                    <option value=2024>2024</option>
                                    <option value=2025>2025</option>
                                    <option value=2026>2026</option>
                                    <option value=2027>2027</option>
                                    <option value=2028>2028</option>
                                    <option value=2029>2029</option>
                                    <option value=2030>2030</option>
                                </select></form>
                            </div>

                            
        </div>
    </div>
</div>

        </body>
</html>
HardReset
  • 95
  • 1
  • 9
  • currently this code fails for me because of `document.write('It\'s currently week....` was that simply for debugging? – Professor Abronsius Apr 12 '19 at 06:45
  • can you clarify `"I want to assign a color to the coresponding user"` please - how does this work? what user? where are you or did you trigger ajax requests? – Professor Abronsius Apr 12 '19 at 06:51
  • @RamRaider yes it was. I used that to see if the current week get's marked in my calendar. – HardReset Apr 12 '19 at 07:01
  • And as for the second question. After the table is created, you can see a second box next to the weeknumber. It is there so that the background is filled with a color. The color is being calculated by a PHP method. The PHP method then returns a String. But I simply don't know how to implement it into the calendar. If I do it while it is created by wraping the whole function 'showCalendar(month, year)' into the 'success: function(data){}' part it somehow messes it up.. – HardReset Apr 12 '19 at 07:05
  • ok - so clicking on either the previous or next buttons or selecting a different month will (??) send the ajax request to the PHP script which then does some calculations based upon user ( how does it know user? session? ) and you then want the returned data to be processed and then assign colours. Is that more or less correct? – Professor Abronsius Apr 12 '19 at 07:15
  • You can build the calendar beforehand, and give IDs or classes to the specific elements you are going to colour in later. Make them have something in the ID which identifies the user. Then when your Ajax call returns and tells you whose turn it is, you can get that element from the DOM and change its style property so it changes colour. I get the sense that this question is as much about DOM manipulation as Ajax. – ADyson Apr 12 '19 at 07:16
  • Of course, if you are going to redraw the calendar each time someone chooses a new date, which it looks like you might be doing from a brief glance at the code, you might need to store the data about whose turn it is separately in a global variable or something, so that you can restore that correctly whenever the calendar is redrawn, regardless of Ajax etc – ADyson Apr 12 '19 at 07:21
  • I'm not 100% certain that the calendar is actually functioning as it should. For some months it appears to return fewer weeks than there ought to be. For instance: May 2019 returns 4 weeks ( namely 19,20,21,22 ) but there are 5 weeks for May beginning with the 18th – Professor Abronsius Apr 12 '19 at 08:12
  • First of all: Thank you ADyson! That is exactcly what I ended up doing. After each row is drawn I make an AJAX request to change the background color of the table with the id 'x'. So that somewhere in the process the BG is changed! – HardReset Apr 12 '19 at 09:08
  • @RamRaider I will look into it. It should list all weeks, that begin with monday – HardReset Apr 12 '19 at 09:08

1 Answers1

0

When you use an AJAX call, it starts executing, but the rest of your code doesn't wait for it to finish before continuing, so it becomes a bit more difficult to coordinate the execution of your code.

What you need to do is to wait for the response of the AJAX call. The xmlHttpRequest object will fire an event when the response is finished, so you can attach an event listener to this event and fire the code that needs to wait for the AJAX call to complete inside the callback of the event listener.

This could be tricky at the beginning, but it's quite easy once you understand how it works, keep in mind that in javascript some code can execute simultaneously and you need to coordinate your different "threads" through callbacks.

I strongly recommend to read "Javascript, the good parts" from Douglas Crockford, which is one of the most insightful books on understanding several important things on this language that we love and hate so much.

Bardo
  • 2,470
  • 2
  • 24
  • 42