how to create multiple things saved in local storage - javascript

I have some code which allows me to get data from the user and gets saved locally but doesn't make a new item in local storage for each set of inputs.
It currently save s the data but only until you delete it or overwrites it
How do I make it so it creates a new storage item rather than overwriting it?
let reminders = [];
const addReminders = (ev) => {
ev.preventDefault();
let reminder = {
ReminderInput: document.getElementById('ReminderInput').value,
DateInput: document.getElementById('DateInput').value,
InfoInput: document.getElementById('InfoInput').value
}
const arr = [reminder.ReminderInput, reminder.DateInput, reminder.InfoInput]
localStorage.setItem('todoForm', JSON.stringify(arr))
localStorage.getItem('todoForm', JSON.parse(arr))
}
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn').addEventListener('click', addReminders);
});
<div class="container">
<!-- The above form looks like this -->
<div class="row">
<div class="six columns" style="margin-top: 20%">
<form id="todoForm">
<label for="ReminderInput">Reminder</label>
<input class="u-full-width" type="text" id="ReminderInput">
<label for="DateInput">Date</label>
<input class="u-full-width" type="datetime-local" id="DateInput">
<label for="InfoInput">Additional Information</label>
<textarea class="u-full-width" type="text" placeholder="Remember to..." id="InfoInput"></textarea>
<button type="button" id="btn" class="button-primary">Add Reminder</button>
</form>
</div>
</div>
</div>

In localstorage, the items are identified by their names. If you save two different objects with the same name, the last one will overwrite the first, as you've seen.
In this circumstance, it may be better to keep a list of all the reminders (or get it from the localstorage), add the new one to the list and save the whole list.
let reminders = JSON.parse(localStorage.getItem("reminders"));
// ...
reminders.push([reminder.ReminderInput, reminder.DateInput, reminder.InfoInput]);
localStorage.setItem("reminders", JSON.stringify(reminders));

You should store the object inside the array:
// getItem will return a string, so you have to parse in this way:
const storedJson = localStorage.getItem('todoForm');
const reminders = storedJson ? JSON.parse(storedJson) || [];
// into the array you should store object, not single data:
function addReminders(ev) {
ev.preventDefault();
const reminder = {
ReminderInput: document.getElementById('ReminderInput').value,
DateInput: document.getElementById('DateInput').value,
InfoInput: document.getElementById('InfoInput').value
};
reminders.push(reminder);
updateStorage();
}
function updateStorage() {
localStorage.setItem("reminders", JSON.stringify(reminders));
}
In this way the data will be more clear and you'll have an easier access to it.

Here is whole example you just need to oranize your data as you well.
Important this example dont work on code snippet becouse :
Failed to read the 'localStorage' property from 'Window': The
document is sandboxed and lacks the 'allow-same-origin' flag.
Test on : codepenio
/**
* LocalStorageMemory save and load js objects in localStorage.
*/
var localStorageMemory = {
localStorage: window.localStorage,
/**
* save Put the object into storage.
* #example Usage : save("MyObjectKey", myObject )
* #method save
* #param {String} Name Name of localstorage key
* #param {object} Value Any object we can store.
* #return {false | object} What ever we are stored intro localStorage.
*/
save: function(name, obj) {
try {
return localStorage.setItem(name, JSON.stringify(obj));
} catch (e) {
console.log("Something wrong in LocalStorageMemory class , method save! -> ", e);
return false;
}
},
/**
* Load saved object from storage. Retrieve the object from storage or
* return false.
* #example Usage : var giveMeMyObject = load("MyObjectKey")
* #function load
* #param {String} Name Name of localstorage key
* #return {false | object} What ever we are stored intro localStorage.
*/
load: function(name) {
if (localStorage.getItem(name) === "undefined" || localStorage.getItem(name) == null || localStorage.getItem(name) === "") {
console.warn("LocalStorageMemory method load return's: ", localStorage.getItem(name));
return false;
} else {
return JSON.parse(localStorage.getItem(name));
}
}
}
/**********CREATE INSTANCE***********/
var saveAnyDataObj = {
name: "wins",
numberOfWins: c++
};
localStorageMemory.save("MyObject1", saveAnyDataObj);
var getMyMemory = localStorageMemory.load("MyObject1");
console.log("MyObject1 = ", getMyMemory);
var c = 0;
setInterval(function() {
var saveAnyDataObj = {
name: "wins",
numberOfWins: c++
};
localStorageMemory.save("MyObject1", saveAnyDataObj);
getMyMemory = localStorageMemory.load("MyObject1");
document.getElementById("result").innerHTML = getMyMemory.numberOfWins;
}, 1000);

Do something like this :
let reminders = [];
let arr;
const addReminders = (ev) => {
ev.preventDefault();
let reminder = {
ReminderInput: document.getElementById('ReminderInput').value,
DateInput: document.getElementById('DateInput').value,
InfoInput: document.getElementById('InfoInput').value
}
if(localStorage.getItem("todoForm") === null){ //check if localstorage is empty
arr=[];
}else{
arr = JSON.parse(localStorage.getItem("todoForm");
//if it already has elements,it will set 'arr' to the elements of localStorage
})
arr.push(reminder.ReminderInput, reminder.DateInput, reminder.InfoInput); //push your new elements
localStorage.setItem('todoForm', JSON.stringify(arr))
localStorage.getItem('todoForm', JSON.parse(arr))
}
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn').addEventListener('click', addReminders);
}
For example if ur local storage consists of a array like this:
['todo1','todo2','todo3']; //array 1
when you are setting the localStorage with new todo items like
['todo4','todo5']
The previous wont get replaced because."array1" will be retrived to 'arr'.like this
arr = ['todo1','todo2','todo3']; //from localStorage;
later you push your new elements 'todo4','todo5';
the arr becomes
arr = ['todo1','todo2','todo3','todo4','todo5'];
It is basically retriving the elements from localStorage to an array and adding new elements to the array and set localStorage with the modified array,like this you wont overwrite your existing elements

Related

Problem with sessionStorage: I am not displaying the first item correctly

I am having a problem with sessionStorage; in particular, I want the id of the ads to be saved in the session where the user puts the like on that particular favorite article.
However, I note that the array of objects that is returned contains the ids starting with single quotes, as shown below:
['', '1', '7']
but I want '1' to be shown to me directly.
While if I go into the sessionStorage I notice that like is shown as:
,1,7
ie with the leading comma, but I want it to start with the number directly.
How can I fix this?
function likeAnnunci(){
let likeBtn = document.querySelectorAll('.like');
likeBtn.forEach(btn => {
btn.addEventListener('click', function(){
let id = btn.getAttribute('ann-id');
//sessionStorage.setItem('like', [])
let storage = sessionStorage.getItem('like').split(',');
//console.log(storage);
if(storage.includes(id)){
storage = storage.filter(id_a => id_a != id);
} else {
storage.push(id);
}
sessionStorage.setItem('like', storage)
console.log(sessionStorage.getItem('like').split(','));
btn.classList.toggle('fas');
btn.classList.toggle('far');
btn.classList.toggle('tx-main');
})
})
};
function setLike(id){
if(sessionStorage.getItem('like')){
let storage = sessionStorage.getItem('like').split(',');
if(storage.includes(id.toString())){
return `fas`
} else {
return `far`
}
} else {
sessionStorage.setItem('like', '');
return`far`;
}
}
The main issue you're having is that you're splitting on a , instead of using JSON.parse().
Also, you've got some other code issues and logical errors.
Solution:
function likeAnnunci() {
const likeBtn = document.querySelectorAll('.like');
likeBtn.forEach((btn) => {
btn.addEventListener('click', function () {
let id = btn.getAttribute('ann-id');
//sessionStorage.setItem('like', [])
let storage = JSON.parse(sessionStorage.getItem('like') || '[]');
//console.log(storage);
if (!storage.includes(id)) {
storage.push(id);
}
sessionStorage.setItem('like', JSON.stringify(storage));
console.log(JSON.parse(sessionStorage.getItem('like')));
btn.classList.toggle('fas');
btn.classList.toggle('far');
btn.classList.toggle('tx-main');
});
});
}
More modular and optimal solution:
const likeBtns = document.querySelectorAll('.like');
// If there is no previous array stored, initialize it as an empty array
const initLikesStore = () => {
if (!sessionStorage.getItem('likes')) sessionStorage.setItem('likes', JSON.stringify([]));
};
// Get the item from sessionStorage and parse it into an array
const grabLikesStore = () => JSON.parse(sessionStorage.getItem('likes'));
// Set a new value for the likesStore, automatically serializing the value into a string
const setLikesStore = (array) => sessionStorage.setItem('likes', JSON.stringify(array));
// Pass in a value.
const addToLikesStore = (value) => {
// Grab the current likes state
const pulled = grabStorage();
// If the value is already there, do nothing
if (pulled.includes(value)) return;
// Otherwise, add the value and set the new array
// of the likesStore
storage.push(value);
setLikesStore(pulled);
};
const likeAnnunci = (e) => {
// Grab the ID from the button clicked
const id = e.target.getAttribute('ann-id');
// Pass the ID to be handled by the logic in the
// function above.
addToLikesStore(id);
console.log(grabLikesStore());
btn.classList.toggle('fas');
btn.classList.toggle('far');
btn.classList.toggle('tx-main');
};
// When the dom content loads, initialize the likesStore and
// add all the button event listeners
window.addEventListener('DOMContentLoaded', () => {
initLikesStore();
likeBtns.forEach((btn) => btn.addEventListener('click', likeAnnunci));
});

how to store an array in local storage and then display it in dom

I am trying to save the score of a game in local storage and then access it to display the saved score on my page
I am trying this
const savedScores = [];
function saveRecord() {
localStorage.setItem('scores', JSON.stringify(timeTaken));
savedScores.unshift(JSON.parse(localStorage.getItem('scores')));
}
function veiwRecord() {
setBtnPopup((oldPopup) => !oldPopup);
console.log(savedScores);
return savedScores;
}
and then trying to display it like this
const scoreEl = savedSscores.map((score) => {
return <p> {score} </p>;
});
All localStorage values are in string format, you need to parse the string array into array.
function veiwRecord() {
setBtnPopup((oldPopup) => !oldPopup);
savedScores = JSON.parse(localStorage.getItem("scores"));
console.log(savedScores);
return savedScores;
}
You have to get the Item from localStorage as well in your veiwRecord method.
function set(){
var sendJSON = JSON.stringify(timeTaken);
localStorage.setItem('timeTaken',sendJSON)
}
function get(){
var getJSON = localStorage.getItem('timeTaken');
if (getJSON){
timeTaken = JSON.parse(getJSON)
}
}
You can store arrays and other object types in localStorage using "JSON.stringify", as strings are the only data types that localStorage accepts.
var names = [];
names[0] = prompt("New member name?");
localStorage.setItem("names", JSON.stringify(names));
//...
var storedNames = JSON.parse(localStorage.getItem("names"));
Then you can retrieve stored data with JSON.parse so you can use your array, object etc...

localStorage .parse .stringify

I need help with pushing 2 data values into localStorage. I know a little about the stringify and parse methods but cant grasp how to implement them.The 2 data values are from "Scores" and "saveName"(a username that is put into an input box).
var Score = (answeredCorrect * 20) + (timeleft);
var saveName = document.querySelector("#saveName");
function Storage() {
localStorage.setItem("User", JSON.stringify(saveName.value));
localStorage.setItem("Scores", JSON.stringify(Score));
var GetStorage = localStorage.getItem("User");
var GetStorage2 = localStorage.getItem("Scores");
return {
first:console.log("GetStorage: "+ GetStorage + GetStorage2),
second:GetStorage,
third:GetStorage2,
};
};
var values = Storage();
var first = values.first;
var second = values.second;
var third = values.third;
As mentioned in the comments you need to parse it once retrieved from storage with JSON.parse, also naming Storage should be avoided.
Since your making a wrapper for localstorage, it could be done like this:
const Store = {
set: (key, value) => localStorage[key] = JSON.stringify(value),
get: key => JSON.parse(localStorage[key])
}
Then you can simply call it like the following, with a set and get methods:
//
Store.set('Score', Score)
Score = Store.get('Score')
//
Store.set('User', saveName.value)
saveName = Store.get('User')
Though you only need to get() on page load as you already have the value in Score/saveName etc.

Problem with Google Apps Script maximum execution time

I'm new to coding and recently I've created a Google script (based on two other scripts) which does the following:
Searches for a Gmail draft by its subject line
Gets the Gmail draft and uses it as a template to create multiple drafts with unique attachments
Puts a confirmation phrase after drafts are created.
Here is the code:
//Change these to match the column names you are using for email recepient addresses and merge status column//
var RECIPIENT_COL = "Email";
var MERGE_STATUS_COL = "M";
//Creates the menu item "Mail Merge" for user to run scripts on drop-down//
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Mail Merge')
.addItem('📌 Create Drafts', 'createDrafts').addToUi();
}
function createDrafts() {
// search for the draft Gmail message to merge with by its subject line
var subjectLine = Browser.inputBox("Select draft " + "to merge with:", "Paste the subject line:", Browser.Buttons.OK_CANCEL);
if (subjectLine === "cancel" || subjectLine == ""){
// if no subject line finish up
return;
}
// get the draft Gmail message to use as a template
var emailTemplate = getGmailTemplateFromDrafts_(subjectLine);
emailTemplate.subject = subjectLine;
// get the data from the active sheet
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getDataRange();
// fetch values for each row in the Range.
var data = dataRange.getValues();
// assuming row 1 contains our column headings
var header = data.shift();
// get the index of column named 'M' (Assume header names are unique)
var draftCreatedColIdx = header.indexOf(MERGE_STATUS_COL);
var object = data.map(function(row) {
// create a new object for next row using the header as a key
var nextRowObject = header.reduce(function(accumulator, currentValue, currentIndex) {
accumulator[currentValue] = row[currentIndex];
return accumulator;
}, {}) // Use {} here rather than initialAccumulatorValue
return nextRowObject;
});
// loop through all the rows of data
object.forEach(function(row, rowIdx){
// only create drafts if mail merge status cell is blank
if (row[MERGE_STATUS_COL] === ''){
var msgObj = fillInTemplateFromObject_(emailTemplate, row);
var attachment_id = "File Name";
// split the values taken from cell into array
var pdfName = row[attachment_id].split(', ');
// initialize files as empty array
var files = [];
// run through cell values and perform search
for(var j in pdfName){
// perform the search,results is a FileIterator
var results = DriveApp.getFilesByName(pdfName[j]);
// interate through files found and add to attachment results
while(results.hasNext()) {
// add files to array
files.push(results.next());
}
}
// #see https://developers.google.com/apps-script/reference/gmail/gmail-app#sendemailrecipient-subject-body-options
GmailApp.createDraft(row[RECIPIENT_COL], msgObj.subject, msgObj.text, {htmlBody: msgObj.html, attachments: files});
// create a confirmation phrase in the first column
sheet.getRange("A" + (rowIdx + 2)).setValue("DRAFT");
}
});
}
/**
* Get a Gmail draft message by matching the subject line.
* #param {string} subject_line to search for draft message
* #return {object} containing the plain and html message body
*/
function getGmailTemplateFromDrafts_(subject_line) {
try {
// get drafts
var drafts = GmailApp.getDrafts();
// filter the drafts that match subject line
var draft = drafts.filter(subjectFilter_(subject_line))[0];
// get the message object
var msg = draft.getMessage();
return {text: msg.getPlainBody(), html:msg.getBody()};
} catch(e) {
throw new Error("Oops - can't find Gmail draft");
}
}
/**
* Filter draft objects with the matching subject linemessage by matching the subject line.
* #param {string} subject_line to search for draft message
* #return {object} GmailDraft object
*/
function subjectFilter_(subject_line){
return function(element) {
if (element.getMessage().getSubject() === subject_line) {
return element;
}
}
}
/**
* Fill HTML string with data object.
* #param {string} template string containing {{}} markers which are replaced with data
* #param {object} data object used to replace {{}} markers
* #return {object} message replaced with data
* H/T https://developers.google.com/apps-script/articles/mail_merge
*/
function fillInTemplateFromObject_(template, data) {
// convert object to string for simple find and replace
template = JSON.stringify(template);
// Search for all the variables to be replaced, for instance {{Column name}}
var templateVars = template.match(/{{([^}]+)}}/g);
// Replace variables from the template with the actual values from the data object.
// If no value is available, replace with the empty string.
for (var i = 0; i < templateVars.length; ++i) {
// strip out {{ }}
var variableData = data[templateVars[i].substring(2, templateVars[i].length - 2)];
template = template.replace(templateVars[i], variableData || "");
}
// convert back to object
return JSON.parse(template);
}
The script works as expected but when I'm trying to process too many rows with too many attachments it exceeds a 6-minute Google Script maximum execution time.
While trying to solve this problem I found a simple script that uses a continuationToken and by doing so never exceeds the limit. My goal is to try to use the same principle in my own script and to process rows by tens. Unfortunatelly, I haven't had any luck so far and need some help. Here's the code of the script that I found:
Code.gs
function onOpen() {
SpreadsheetApp.getUi().createMenu("List Drive files").addItem('Start', 'start').addToUi();
}
function start() {
var ui = HtmlService.createHtmlOutputFromFile('ui');
return SpreadsheetApp.getUi().showSidebar(ui);
}
function getDriveFiles(continuationToken) {
if(continuationToken) {
var files = DriveApp.continueFileIterator(continuationToken);
}
else {
var files = DriveApp.getFiles();
}
var i = 0;
while (files.hasNext() && i < 10) {
var file = files.next();
SpreadsheetApp.getActiveSheet().appendRow([file.getName(), file.getUrl()]);
i++;
if(i == 10) {
return files.getContinuationToken();
}
}
}
ui.html
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<div style="text-align:center; margin-top:10px">
<div>Files processed:</div>
<div id="nbOfFilesProcessed">0</div>
<br>
<button id="startButton" class="blue" onclick="start()">Start</button>
<div class="secondary">Close the sidebar to stop the script.</div>
</div>
<script>
function start() {
document.getElementById("startButton").disabled = true;
google.script.run.withSuccessHandler(onSuccess).getDriveFiles();
}
function onSuccess(continuationToken){
// If server function returned a continuationToken it means the task is not complete
// so ask the server to process a new batch.
if(continuationToken) {
var nbOfFilesProcessedEl = document.getElementById("nbOfFilesProcessed");
nbOfFilesProcessedEl.innerHTML = parseInt(nbOfFilesProcessedEl.innerHTML) + 10;
google.script.run.withSuccessHandler(onSuccess).getDriveFiles(continuationToken);
}
}
</script>
From what I see in the code you posted you will have to edit your createDrafts function in this way:
Edit how the function is triggered: you will have to use an HTML ui element to run javascript inside it.
Edit the while loop so that it has a return statement when you hit the limit of your batch.
Create a Javascript function in the HTML ui element that handles the success of the createDrafts function and recursively calls it in case that the continuationToken is returned.
Snippets
UI Component
You can keep your custom menu and on click add this HTML to a UI dialog.
- code.gs -
//Creates the menu item "Mail Merge" for user to run scripts on drop-down//
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Mail Merge')
.addItem('📌 Create Drafts', 'openDialog').addToUi();
}
function openDialog() {
// Display a modal dialog box with custom HtmlService content.
var htmlOutput = HtmlService
.createHtmlOutputFromFile('Dialog')
.setWidth(250)
.setHeight(300);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Create Drafts');
}
- Dialog.html -
<!-- The UI will be very similar to the one you found, I will keep only the strictly necessary statements for this example -->
<div>
<button id="startButton" onclick="startBatch()">Start</button>
</div>
<script>
function startBatch() {
google.script.run.withSuccessHandler(onSuccess).createDrafts();
}
function onSuccess(continuationToken){
// If server function returned a continuationToken it means the task is not complete
// so ask the server to process a new batch.
if(continuationToken) {
google.script.run.withSuccessHandler(onSuccess).createDrafts(continuationToken);
}
}
</script>
Apps Script Component
function createDrafts(continuationToken) {
var batchLimit = 10;
// ...
// run through cell values and perform search
for(var j in pdfName){
// perform the search,results is a FileIterator
if (continuationToken) {
var results = DriveApp.continueFileIterator(continuationToken);
} else {
var results = DriveApp.getFilesByName(pdfName[j]);
}
// interate through files found and add to attachment results
let i = 0;
while(results.hasNext() && i<batchLimit) {
// add files to array
files.push(results.next());
i++;
if (i === batchLimit) {
return results.getContinuationToken();
}
}
}
Final considerations
As an improvement to your batch operation, I would save all the user inputs so that you will be able to continue the script without prompting for it again. You can either pass these values to the return function on a javascript object or save them in the cache with the CacheService utility.
Moreover, try to find the correct trade off between execution time and batch limit: A small batch limit will never hit the time limit but will consume your quota very fast.
References:
Client Side API
Cache Service
Apps Script UI

Conference room availability in JavaScript

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>
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);
}
};
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);
}
});
});

Categories

Resources