Pergunta

I am trying to create a room availability script for a conference room at my university. I decided to achieve it using jQuery by parsing a JSON feed of a public Google calendar and then displaying on the screen whether room is available or not.

I feel stupid, I have been fighting this problems for 3 days and no matter whether there is an appointment in Google calendar or not the script says that room is available. Could anyone offer a suggestion why this may be happening. I am not a programmer and I bet this is something really simple but I just can't seem to see it. Any help would be greatly appreciated!

A minimal working example on jsFiddle and below:

<html>
<head>
<title>Graduate Center Conference Room</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script>
// Declare global variables

var events = [];
var currentReservation = null;
var nextReservation = null;
var gclaData = 'http://www.google.com/calendar/feeds/4occ2bc4m626a3pgmirlm06q5s%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&singleevents=true&max-results=2&alt=json';

// Parse Google Calendar Public JSON Feed and store in the events global array

$(document).ready(function () {
$.getJSON(gclaData, function (data) {
    $.each(data.feed.entry, function (i, entry) {
        var dtStart = new Date(entry["gd$when"][0].startTime);
        var dtEnd = new Date(entry["gd$when"][0].endTime);
        var dtSummary = entry.content.$t;
        var dtTitle = entry.title.$t;

        events[i] = {
            'start': dtStart,
                'end': dtEnd,
                'title': dtTitle,
                'summary': dtSummary
        };
    });
});

reservationInfo = '';

// sort events just in case (JSON should be sorted anyways)    

events.sort(function (a, b) {
    return a.start - b.start;
});

// current date

var dtNow = new Date();

// let's assume there are no current room reservations unless script detects otherwise.
// No reservations indicated by -1
currentReservation = -1;

// loop through the events array and if current time falls between start and end of a element in the array the mark it as a reservation currently in progress 

for (var i in events) {
    if (dtNow >= events[i].start && dtNow <= events[i].end) currentReservation = i;
}

// Print the result to a output div

if (-1 == currentReservation) {

    reservationInfo = '<h1>ROOM AVAILABLE</h1>';
    $('#output').html(reservationInfo);

} else {

    reservationInfo = '<h1>ROOM OCCUPIED</h1>';
    $('#output').html(reservationInfo);
}
});
</script>
</head>
<body>
            <div id="output"></div>
</body>
</html>
Foi útil?

Solução

Some observations...

1) Do some refactor to your code and always do some debugging!

2) Your events variable is not the expected object since ajax calls are asynchronous and other code gets executed before getting into the callback that will fill your object. In other words, you need to wait for ajax call otherwise your object won't be the expected one (maybe will be undefined at first and after a moment, when ajax call finishes, an object with data).

Just to know, you can force an ajax call to be synchronous but that's NOT a good approach.

Try this:

I like to work this way, code it's way better organized:

Live Demo: http://jsfiddle.net/oscarj24/8HVj7/


HTML:

<div id="output"></div>

jQuery:

/*
 * http://stackoverflow.com/questions/23205399/conference-room-availability-in-javascript
 * @author: Oscar Jara
 */

/* Google calendar URL */
var url = 'http://www.google.com/calendar/feeds/4occ2bc4m626a3pgmirlm06q5s%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&singleevents=true&max-results=2&alt=json';

/* Status list used to show final message to UI */
var statusList = {
    'ROOM_A': 'Available',
    'ROOM_O': 'Occupied',
    'ERROR_DATA': 'No data found at Google calendar.',
    'ERROR_PROCESS': 'There was an error checking room availability.'
};

/* Document onReady handler */
$(document).ready(function () {
    getCalData(url);
});

/* 
 * Get Google calendar data by request.
 * @param {String} url
 */
function getCalData(url) {
    var statusCode;
    $.getJSON(url, function (data) {
        if (!$.isEmptyObject(data)) {
            var events = parseCalData(data);
            var curReserv = getCurrentReservation(events);
            statusCode = getRoomStatusCode(curReserv);
        } else {
            statusCode = 'ERROR_DATA';
        }
        printRoomStatusToUI(statusCode, $('#output'));
    }).fail(function (r) { // HTTP communication error
        console.error(r);
    });
};

/*
 * Parse Google calendar data.
 * @param {Object} data
 * @return {Object} events
 */
function parseCalData(data) {
    var events;
    events = $.map(data.feed.entry, function (evt, i) {
        var dt = evt['gd$when'][0];
        return {
            start: new Date(dt.startTime),
            end: new Date(dt.endTime),
            title: evt.title.$t,
            summary: evt.content.$t
        };
    });
    if (events) {
        sortEvents(events); // Just in case
    }
    return events;
};

/*
 * Sort Google calendar events.
 * @param {Object} events
 */
function sortEvents(events) {
    events.sort(function (a, b) {
        return a.start - b.start;
    });
}

/*
 * Get/check for current reservation.
 * If current time falls between start and end of an event, 
 * mark it as a reservation currently in progress.
 * @param {Object} events
 * @return {int} curReserv
 */
function getCurrentReservation(events) {
    var curReserv;
    if (events) {
        var dtNow = new Date(); // Current datetime
        curReserv = -1; // No reservations
        for (var i in events) {
            var dtStart = events[i].start;
            var dtEnd = events[i].end;
            if (dtNow >= dtStart && dtNow <= dtEnd) {
                curReserv = i;
                break;
            }
        }
    }
    return curReserv;
};

/*
 * Get room availability statusCode.
 * @param {int} curReserv
 * @return {String} statusCode
 */
function getRoomStatusCode(curReserv) {
    var statusCode = 'ROOM_A';
    if (!curReserv) {
        statusCode = 'ERROR_PROCESS';
    } else if (curReserv && curReserv != -1) {
        statusCode = 'ROOM_O';
    }
    return statusCode;
};

/*
 * @private
 * Get room status text.
 * @param {String} statusCode
 * @return {String}
 */
function getRoomStatusText(statusCode) {
    return statusList[statusCode];
};

/*
 * @private
 * Check if statusCode is an ERROR one.
 * @param {String} statusCode
 * @return {Boolean}
 */
function isErrorStatus(statusCode) {
    return (statusCode.indexOf('ERROR') > -1);
};

/* 
 * Print room availability to UI.
 * @param {String} statusCode
 * @param {Object} elem
 */
function printRoomStatusToUI(statusCode, elem) {
    var statusText = getRoomStatusText(statusCode);
    var isError = isErrorStatus(statusCode);
    if (statusText && $.trim(statusText) != '') {
        if (!isError) {
            statusText = '<h1>Room is: ' + statusText + '</h1>';
        }
        elem.html(statusText);
    }
};

Outras dicas

You can quickly check what state a variable is by using:

console.log(variableName);

This will output the results of the variable in your browser console tab (in Developer Tools).

In your case, I did console.log(events); where the events were to be looped, and I discovered that events were not being set. After some debugging, I determined that the code was $.getJSON() function wasn't completing 100% before the code below it was running (most likely because the ajax request takes time).

To fix this, I've moved all of your code that parses the events within the $.getJSON() function so that the events are properly retrieved and set before parsing the data.

Your code will look like this now:

Working JSFiddle: http://jsfiddle.net/Mf8vb/4/

// Declare global variables
// Parse Google Calendar Public JSON Feed and store in the events global array

$(document).ready(function () {

    var events = [];
    var currentReservation = null;
    var nextReservation = null;
    var gclaData = 'http://www.google.com/calendar/feeds/4occ2bc4m626a3pgmirlm06q5s%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&singleevents=true&max-results=2&alt=json';

    $.getJSON(gclaData, function (data) {
        $.each(data.feed.entry, function (i, entry) {
            var dtStart = new Date(entry["gd$when"][0].startTime);
            var dtEnd = new Date(entry["gd$when"][0].endTime);
            var dtSummary = entry.content.$t;
            var dtTitle = entry.title.$t;
            events[i] = {
                'start': dtStart,
                'end': dtEnd,
                'title': dtTitle,
                'summary': dtSummary
            };
        });

        reservationInfo = '';

        // sort events just in case (JSON should be sorted anyways)    

        events.sort(function (a, b) {
            return a.start - b.start;
        });

        // current date

        var dtNow = new Date();

        // let's assume there are no current room reservations unless script detects otherwise.
        // No reservations indicated by -1
        currentReservation = -1;

        // loop through the events array and if current time falls between start and end of a element in the array the mark it as a reservation currently in progress 

        for (var i in events) {
            if (dtNow >= events[i].start && dtNow <= events[i].end)
                currentReservation = i;
        }

        // Print the result to a output div

        if (-1 == currentReservation) {

            reservationInfo = '<h1>ROOM AVAILABLE</h1>';
            $('#output').html(reservationInfo);

        } else {

            reservationInfo = '<h1>ROOM OCCUPIED</h1>';
            $('#output').html(reservationInfo);
        }      

    });   

});
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top