-
Notifications
You must be signed in to change notification settings - Fork 1
/
app.js
151 lines (129 loc) · 3.43 KB
/
app.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
;(function() {
'use strict'
//
// Variables
//
const app = document.querySelector('#app')
const endpoint = 'https://vanillajsacademy.com/api/pirates.json'
const storageID = 'pirateCache'
const timestring = 1000 * 60 * 5 // expiration time: five minutes
//
// Helper functions
//
/*!
* Sanitize and encode all HTML in a user-submitted string
* (c) 2018 Chris Ferdinandi, MIT License, https://gomakethings.com
* @param {String} str The user-submitted string
* @return {String} str The sanitized string
*/
const sanitizeHTML = function(str) {
const temp = document.createElement('div')
temp.textContent = str
return temp.innerHTML
}
/**
* Check if the data is valid
* @param {Object} saved The data to validate
* @param {Number} goodFor How long the data is good for
* @return {Boolean} If true, data has not yet expired
*/
const isDataValid = function(saved, goodFor) {
// Check that there's data, and a timestamp key
if (!saved || !saved.data || !saved.timestamp) return
// Get timestamp from cache
const { timestamp } = JSON.parse(localStorage.getItem(storageID))
// Get the difference between the timestamp and current time
const difference = new Date().getTime() - timestamp
return difference < goodFor
}
/**
* Save article data to localStorage
* @param {Object} data The article data
*/
const saveDataToLocalStorage = data => {
// Create a cache object with a timestamp
const cache = {
data: data,
timestamp: new Date().getTime()
}
// Stringify it and save it to localStorage
localStorage.setItem(storageID, JSON.stringify(cache))
}
/**
* Render articles into the UI
* @param {Object} articles The API response object
*/
const renderNews = data => {
const { articles } = data
// If there are no articles, render a message into the UI
if (articles.length < 1) {
renderNoArticles()
return
}
// Otherwise, render the UI
return (app.innerHTML =
articles
.map(
article =>
`<article>
<h2>${sanitizeHTML(article.title)}</h2>
<p><em>By ${sanitizeHTML(article.author)} on ${sanitizeHTML(
article.pubdate
)} </em></p>
<p>${sanitizeHTML(article.article)}</p>
</article>`
)
.join('') +
`<p><em>Articles from <a href="${sanitizeHTML(
data.attribution.url
)}">${sanitizeHTML(data.attribution.name)}</a></em></p>`)
}
/**
* Render a message into the UI when there are no articles to share
*/
const renderNoArticles = function() {
app.innerHTML =
'<p>There be no pirate news afoot, matey. Check back later.</p>'
}
//
// Methods
//
/**
* Get articles from the API
*/
const fetchArticles = () => {
fetch(endpoint)
.then(response => {
if (response.ok) return response.json()
return Promise.reject(response)
})
.then(data => {
renderNews(data)
saveDataToLocalStorage(data)
})
.catch(error => {
console.log('Something went wrong:', error)
renderNoArticles()
})
}
//
// Inits
//
/**
* Get API data from localStorage
*/
const saved = JSON.parse(localStorage.getItem(storageID))
if (saved) {
// Check if it's been less than five minutes since the data was saved
if (isDataValid(saved, timestring)) {
// The data is still good, use it
console.log('loaded from cache')
const { data } = saved
renderNews(data)
return
}
}
// Get fresh data and use that instead
console.log('fetched from API')
fetchArticles()
})()