forked from erikdkennedy/new-tab-new-you
-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.js
372 lines (300 loc) · 12.2 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
$(document).ready(function() {
/*
Here is how this code is organized:
* INITIALIZATION STUFF
* WIDGET-DRAWING FUNCTIONS - The functions that draw the page based on localStorage data.
* DATA FUNCTIONS - The CRUD methods that interface with localStorage. Abstracted beyond individual widgets.
* LISTENERS - Everything that responds to a click or form submission on the page
* HELPERS - Functions that are called in different places but don't fit anywhere else
*/
//to store week that's being viewed currently
var viewingWeek = moment().day(0).format("M/D/YYYY"); //Sunday of the current week
//initialize widgets from localStorage
loadSiteKeywords();
drawWeeklyGoalsList(viewingWeek);
drawCarbsTracker();
//set focus to search box
$("#searchGoogleBox").focus();
//* * * * * WIDGET-DRAWING FUNCTIONS * * * * * * //
//Site keywords allow you to go to a site without typing in the URL-- this populates the list from localStorage
function loadSiteKeywords() {
//clear any children of the #siteKeywords that are already there
$("#siteKeywords").empty();
//populate #siteKeywords from localStorage
var siteKeywords = getLocalData("siteKeywords");
for (key in siteKeywords) {
var siteName = key;
var siteUrl = siteKeywords[siteName];
var siteKeywordAppendage = "<a href='" + siteUrl + "' title='" + siteUrl + "'>" + siteName + "</a> "
+ "<small>[<a href='#' class='deleteSiteKeyword' id='deleteSiteKeyword-" + siteName + "'>X</a>]</small> | ";
$("#siteKeywords").append(siteKeywordAppendage);
}
}
function drawWeeklyGoalsList(week) {
//change widget header to current week
$("#weeklyGoalsWeek").html(viewingWeek);
//clear any goals in #weeklyGoals already
$("#weeklyGoals").empty();
//populate #weeklyGoals for specified week from localStorage
var weeklyGoals = getLocalData("weeklyGoals");
var thisWeeksGoals = weeklyGoals[week];
if (thisWeeksGoals == undefined) { //if there are no goals for the week and never were...
$("#weeklyGoals").append("<li>There are no weekly goals yet. Add one below!</li>");
} else if (thisWeeksGoals.length == 0) { //if there were goals for the week but they were all deleted...
$("#weeklyGoals").append("<li>There are no weekly goals yet. Add one below!</li>");
} else { //if there are some goals for the week
var goals = "";
for (var i=0; i<thisWeeksGoals.length; i++) {
goals += "<li class='weeklyGoal'>";
goals += "<label for='checkboxForGoal-" + i + "'>";
goals += "<input type='checkbox' id='checkboxForGoal-" + i + "'";
goals += "class='checkboxForGoal' ";
goals += thisWeeksGoals[i][1] ? "checked='true'" : "";
goals += "/><span id='goal-" + i + "' class='weeklyGoalText";
goals += thisWeeksGoals[i][1] ? " goalAccomplished" : "";
goals += "'>"+ thisWeeksGoals[i][0] + "</span>";
goals += "</label>";
goals += " <small>[<a href='#' class='deleteWeeklyGoal' id='deleteWeeklyGoal-" + i + "'>Delete</a>]</small></li>"
}
$("#weeklyGoals").append(goals);
}
//disable "next" button if this is the current week
if (viewingWeek == moment().day(0).format("M/D/YYYY")) {
$("#viewNextWeek").attr("onclick", "")
$("#viewNextWeek").attr("class", "disabledLink");
} else {
$("#viewNextWeek").attr("onclick", "viewNextWeek()");
//TODO: Find way to remove entirely the class attribute in this case
$("#viewNextWeek").attr("class", "");
}
}
function drawCarbsTracker() {
//draw carbs chart
drawCarbsChart();
var today = moment(); //for use in date picker controls
//populate date picker - months
var months = "";
for (i=0; i<12; i++) {
months += "<option value='" + (i+1) +"'>" + (i+1) + "</option>"
}
$("#month").append(months).attr("value", today.month()+1);
//populate date picker - days
var days = "";
for (i=0; i<today.daysInMonth(); i++) {
days += "<option value='" + (i+1) +"'>" + (i+1) + "</option>"
}
$("#day").append(days).attr("value", today.date());
//populate date picker - years
var years = "";
for (i=2011; i<2022; i++) {
years += "<option value='" + (i+1) +"'>" + (i+1) + "</option>"
}
$("#year").append(years).attr("value", today.year());
}
//TODO: Change number of days shown in day picker when month is changed
//* * * * * * * *DATA FUNCTIONS * * * * * * * * //
function getLocalData(objName) {
//objNames so far include "siteKeywords", "carbs", and "weeklyGoals"
if (localStorage[objName] == undefined) {
localStorage[objName] = "{}";
} else {
return JSON.parse(localStorage[objName])
}
}
//sets a localStorage object (identified by objName) to a dictionary dict
function setLocalData(objName, dict) {
localStorage[objName] = JSON.stringify(dict);
}
//add a key-value pair (appendage) to one of the localStorage dictionaries (identified by objName)
//appendance should be a table with a single key and a single value
function appendLocalData(objName, appendage) {
//possible types are the same as listed for getLocalData(objName)
if (localStorage[objName] != undefined) {
var dict = getLocalData(objName);
dict[appendage[0]] = appendage[1];
setLocalData(objName, dict);
} else {
alert("You're attempting to store data somewhere that can't be found. There's an error.")
}
}
//localStorage has an object for every type of data we're storing. First parameter is the object name
//second parameter is the key
//third parameter is optional-- if the value at that key is an array, this is the index of the array
function deleteLocalData(objName, key, index) {
var dict = getLocalData(objName);
if (index === undefined) {
delete(dict[key])
} else {
dict[key].splice(index, index+1);
}
setLocalData(objName, dict);
}
//* * * * * * * * * LISTENERS * * * * * * * * * //
//SEARCH GOOGLE
//searches Google for whatever's in #searchGoogle input box
$("#searchGoogle").submit(function() {
var searchText = $("#searchGoogleBox").attr("value");
//if searchText is a site keyword, go directly to the site URL
var keywords = getLocalData("siteKeywords");
if (keywords[searchText] != undefined) {
window.location.href = keywords[searchText];
return false;
} else if (searchText.split(" ").length == 1 && searchText.indexOf(".") >= 0) {
//if searchText is a URL (one word, contains a period)
window.location.href = "http://" + searchText;
} else {
//if searchText is not a keyword, search it on Google
window.location.href = "http://www.google.com/search?q=" + searchText;
}
return false; //so form is not actually submitted
});
//ADD SITE KEYWORD
//adds a site keyword that you can go to by typing into the "Search Google" textbox
$("#addSiteKeyword").click(function() {
var defaultSiteUrl = "http://";
var siteUrl = "", siteName = "";
//prompt for site URL
siteUrl = prompt("What URL do you want to be able to access directly? (e.g. http://facebook.com)", defaultSiteUrl);
//if user filled our URL, prompt for site name
if (siteUrl != "" && siteUrl != defaultSiteUrl) {
siteName = prompt("What should you call the link to go there? (e.g. 'facebook')");
//if both prompt boxes are filled out...
if (siteName.length>1) {
appendLocalData("siteKeywords", [siteName, siteUrl])
//now refresh the list of site keywords
loadSiteKeywords();
}
}
});
//DELETE SITE KEYWORD
$(".deleteSiteKeyword").live("click", function() {
//get side name (part of element ID after the first dash)
var siteName = this.id.substring(this.id.indexOf("-")+1);
//remove site keyword from localStorage
deleteLocalData("siteKeywords", siteName);
//now refresh the list of site keywords
loadSiteKeywords();
});
//CHECK OR UNCHECK WEEKLY GOAL
//checking or unchecking a weekly goal as completed
$(".checkboxForGoal").live("click", function() {
var goalIndex = this.id.substring(this.id.indexOf("-")+1);
//switch completed bit in weeklyGoals
var weeklyGoals = getLocalData("weeklyGoals");
weeklyGoals[viewingWeek][goalIndex][1] = !weeklyGoals[viewingWeek][goalIndex][1];
//change HTML class of goal text to cross it off if accomplished
var classString = weeklyGoals[viewingWeek][goalIndex][1] ? "weeklyGoalText goalAccomplished" : "weeklyGoalText";
$("#goal-" + goalIndex).attr("class", classString);
//save back localStorage goals data
setLocalData("weeklyGoals", weeklyGoals);
});
//DELETE WEEKLY GOAL
$(".deleteWeeklyGoal").live("click", function() {
//get goalIndex (part of ID after the first dash)
var goalIndex = this.id.substring(this.id.indexOf("-")+1);
//remove particular goal from localStorage of particular week (viewingWeek)
deleteLocalData("weeklyGoals", viewingWeek, goalIndex);
//now redraw the list of goals-- without the deleted goal this time
drawWeeklyGoalsList(viewingWeek);
});
//CREATE WEEKLY GOAL
//Create new weekly goal based on what's in the #newWeeklyGoalBox text box
$("#newWeeklyGoal").submit(function() {
//set the initial variables defining the goal
var goal = $("#newWeeklyGoalBox").attr("value");
var dateString = viewingWeek;
var isAccomplished = false;
//Ensure textbox is filled in
if (goal.length == 0) {
alert("Enter a goal to add.");
return;
}
//Save data
var weeklyGoals = getLocalData("weeklyGoals");
if (weeklyGoals[dateString] == undefined) {
//no goals for that week yet
weeklyGoals[dateString] = [[goal, isAccomplished]];
} else {
weeklyGoals[dateString].push([goal, isAccomplished]);
}
setLocalData("weeklyGoals", weeklyGoals);
//now redraw list of viewingWeek's goals
drawWeeklyGoalsList(viewingWeek);
//Empty textbox
$("#newWeeklyGoalBox").attr("value", "");
return false; //so form submit doesn't trigger anything
});
//VIEW PREVIOUS WEEK'S GOALS
$("#viewPrevWeek").click(function() {
viewingWeek = moment(viewingWeek).subtract("days", 7).format("M/D/YYYY");
drawWeeklyGoalsList(viewingWeek);
});
//VIEW NEXT WEEK'S GOALS
$("#viewNextWeek").click(function() {
viewingWeek = moment(viewingWeek).add("days", 7).format("M/D/YYYY");
drawWeeklyGoalsList(viewingWeek);
});
//ADD NEW CARBS DATA
$("#newCarbsData").submit(function() {
var userInput = $("#carbsTextBox").attr("value");
if (isNaN(parseInt(userInput))) {
alert("Must enter an integer.")
return
} else {
var selectedDate = $("#month").attr("value") + "/" + $("#day").attr("value") + "/" + $("#year").attr("value");
//if entered date is real
if (moment(selectedDate).isValid()) {
//add date-carbs pair to localStorage
appendLocalData("carbs", [selectedDate, parseInt(userInput)]);
//refresh #carbsChart with new data
drawCarbsChart();
} else { //if entered date is NOT real...
alert("Must enter a valid date.");
}
}
});
//* * * * * * * * * * HELPERS * * * * * * * * * //
function drawCarbsChart() {
var carbsDict = getLocalData("carbs");
//Grab lifetime data; calculate average
var lifetimeAverage = calculateAverageOfValues(carbsDict);
//Narrow data to last two weeks; calculate that average
var fortnightCarbsDict = {};
for (i=-14; i<1; i++) {
var date = moment().add("days",i).format("M/D/YYYY");
fortnightCarbsDict[date] = carbsDict[date];
}
var fortnightAverage = calculateAverageOfValues(fortnightCarbsDict);
//Draw line chart
drawLineChart($("#carbsChart"), fortnightCarbsDict);
//write averages
var c = $("#carbsChart")[0].getContext("2d");
var yPos = 14;
c.font = "14px Helvetica, Arial, sans-serif";
c.fillStyle = "#666";
c.textAlign = "end";
var canvasWidth = $("#carbsChart").attr("width");
var canvasHeight = $("#carbsChart").attr("height");
c.fillText("2-WEEK", canvasWidth - 5, yPos);
c.fillText("LIFETIME", canvasWidth - 5, yPos+40);
c.font = "bold 21px Helvetica";
c.fillText(fortnightAverage,canvasWidth - 5, yPos+20);
c.fillText(lifetimeAverage, canvasWidth - 5, yPos+60);
//empty carbs textbox
$("#carbsTextBox").attr("value", "");
}
function calculateAverageOfValues(dict) {
var total = 0;
var count = 0;
//cycle through days
for (key in dict) {
//if a day has carbs entered for it...
if (dict[key] != undefined) {
total += dict[key];
count += 1;
}
}
//return average carbs per day over dict's timeframe
return (total/count).toFixed(2);
}
});