This repository was archived by the owner on Oct 23, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscripts.js
More file actions
282 lines (240 loc) · 10.9 KB
/
scripts.js
File metadata and controls
282 lines (240 loc) · 10.9 KB
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
//hide content (headers) on load.
$("#auto-content").toggle(false);
//variable that decides whether you can change section tabs or not.
let dataGrabSuccess = false;
//definition for JSON functions to use, defined in outer-scope so that it can be access from any function.
let returnedJSON = null;
//auto-focus on the form
document.getElementById("search-query").focus();
//Variables for Section switching. Must be updated for every new section added to the interface, along with a function called in fillData()
//Format [[#ID_NAME_OF_SECTION],[NAV-LINK-ID]]
const sectionListAndLinkID = [["#section-price-history","price-history-link"],["#section-shipping","shipping-link"],["#section-seller-info","seller-info-link"],["#section-raw-json","raw-json-link"]];
//Stop the form submission from refreshing the page / redirecting, eats the request and calls functions for JSON requests instead.
(function() {
var form = document.getElementById("search-form");
console.log(form);
function handleForm(event) { event.preventDefault(); clearPreviousResult(); JSONFromInput(); }
form.addEventListener('submit', handleForm);
})();
//start tooltips
(function() {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
})
})();
//does as it says, clears the last result, doesnt let you change section, until new result is found.
function clearPreviousResult() {
$("#auto-content").toggle(false);
dataGrabSuccess = false;
}
// Gets Grailed JSON from an ID or URL
function JSONFromInput() {
console.log("Starting search")
setStatus("alert-primary","Starting Search...")
let input = document.getElementById("search-query").value.toString();
console.log("input: "+input);
//parse URL from ID
// Example URL: https://www.grailed.com/listings/15582671-kappa-x-vintage-need-gone-vintage-kappa-sidetape-light-jacket
// Example ID: 15582671
if (parseToID(input) !== 0) {
let listingID = parseToID(input)
//takes over fetch and propagation
fetchJSON(listingID);
} else {
//set status
setStatus("alert-danger","Failed! Invalid URL or ID.");
// return alert("Failed, Invalid URL or ID.")
}
}
//Parses the into to an ID, returns 0 if invalid.
function parseToID(input) {
if (isValidID(input)) {
return input;
} else if (isValidURL(input)) {
for (let i = 0; i < input.length; i++) { //i=1, to skip potential trailing backslashes
// if (/^\d+$/.test(input.charAt(input.length-i))) {
if (/^\/+$/.test(input.charAt(input.length-(i+2)))) { //input.length-(i+2), to go from back to front, and skip last item
console.log("There is a slash at pos "+i);
let lastSlash = input.length-(i+1);
console.log("last slash is at "+lastSlash);
for (let j = lastSlash; j < input.length; j++) { //from the lastSlash to end, look for '-', remove dash and everything after it.
if (/^-+$/.test(input.charAt(j))) {
let firstDash = j;
console.log("First dash is at "+firstDash);
console.log(input.slice(lastSlash,firstDash));
return input.slice(lastSlash,firstDash);
}
}
}
}
//parse URL into id
return input.replace(/\D/g,''); //keeping regex here in-case there are no dashes
// return input
} else {
console.log("This is not a valid URL or ID! " + input)
return 0;//TODO throw an exception?
}
}
//checks if arg only contains [0-9]
function isValidID(id) {
//regex for [0-9]
return /^\d+$/.test(id);
}
//checks if arg contains "grailed.com/listing"
function isValidURL(url) {
// console.log(url.contains("grailed.com.listing"))
return url.includes("grailed.com/listing");
}
//makes the request for the JSON, and callbacks fetchJSONCallback on completion.
/*TODO
* parse 404 and timed-out requests into a status
* maybe do this with by looking at JSON content for 404,
* or if returnedJSON is still null after x seconds set the error status*/
function fetchJSON(listing) {
setStatus("alert-secondary", "Fetching Data...")
$.getJSON("https://cors-anywhere.herokuapp.com/https://www.grailed.com/api/listings/"+listing, fetchJSONCallback);
}
//does the dirty work
function fetchJSONCallback(data) {
console.log(data);
//add success status
setStatus("alert-success", "Request Approved!");
dataGrabSuccess = true;
returnedJSON = data["data"];
//propagation of HTML page
fillData();
}
//fills the page with content parsed from JSON, each section has a helper function.
function fillData() {
//Data for
document.getElementById("listing-title").innerHTML = returnedJSON["title"];
//Get date and format
let dateUpdated = new Date(returnedJSON["price_updated_at"]);
console.log("Date Updated:\n",dateUpdated);
let [month, date, year] = (dateUpdated).toLocaleDateString().split("/")
//Create price history table
let priceHistory = returnedJSON["price_drops"]; //array of prices
//Empty the table body
document.getElementById("listing-info-table-body").innerHTML = "";
//Create table headers
document.getElementById("listing-info-table-head").innerHTML = "<tr>\n" +
" <th scope=\"col\">Price (USD)</th>\n" +
" <th scope=\"col\">Date</th>\n" +
" </tr>"
//For each priceHistory item add a row
for (let i = 0; i < priceHistory.length-1; i++) {
document.getElementById("listing-info-table-body").innerHTML = document.getElementById("listing-info-table-body").innerHTML + "<tr><td>$" + priceHistory[i] + "</td><td>--</td></tr>";
}
//adding most current info
document.getElementById("listing-info-table-body").innerHTML = document.getElementById("listing-info-table-body").innerHTML + "<tr><td>$" + returnedJSON['price'] + "</td><td>" + month+"/"+date+"/"+year + "</td></tr>";
// initializeCharts(priceHistory);
propagateChart(priceHistory);
//shipping table
fillShippingInfo();
//seller info
fillSellerInfo();
//Raw Json section
document.getElementById("raw-json-here").innerHTML = JSON.stringify(returnedJSON,undefined,2);
$("#auto-content").toggle(true);
}
function fillShippingInfo() {
let shippingInfo = returnedJSON["shipping"];
//Empty the table body
document.getElementById("shipping-table-body").innerHTML = "";
//Create table headers
document.getElementById("shipping-table-head").innerHTML = "<tr>\n" +
" <th scope=\"col\">Location</th>\n" +
" <th scope=\"col\">Amount</th>\n" +
" <th scope=\"col\">Enabled?</th>\n" +
" </tr>"
//Location Array
const location = ["us","ca","uk","eu","asia","au","other"];
//For each priceHistory item add a row
for (let i = 0; i < 7; i++) {
document.getElementById("shipping-table-body").innerHTML = document.getElementById("shipping-table-body").innerHTML + "<tr><td>" + location[i] + "</td><td>$ " + shippingInfo[location[i]]['amount'] + "</td><td>" + shippingInfo[location[i]]['enabled'] + "</td></tr>";
}
}
// Puts seller info on seller info section
function fillSellerInfo() {
let sellerInfo = returnedJSON["seller"];
document.getElementById("seller-score-sold_count").innerHTML = "<span class=\"font-italic\">Sold Count: </span><mark>" + sellerInfo["seller_score"]["sold_count"] + "</mark>";
document.getElementById("seller-score-rating_average").innerHTML = "<span class='font-italic'>Avg. Rating: </span>" + sellerInfo["seller_score"]["rating_average"];
document.getElementById("seller-score-rating_count").innerHTML = "<span class='font-italic'>Num. Ratings: </span>" + sellerInfo["seller_score"]["rating_count"];
document.getElementById("buyer-score-purchase_count").innerHTML = "<span class='font-italic'>Num. Purchases: </span><mark>" + sellerInfo["buyer_score"]["purchase_count"] + "</mark>";
document.getElementById("buyer-score-would_sell_to_again").innerHTML = "<span class='font-italic'>\"Would Sell to Again\" Count: </span><mark>" + sellerInfo["buyer_score"]["would_sell_to_again_count"] + "</mark>";
//Get date and format
let dateUpdated = new Date(sellerInfo["created_at"]);
console.log("Date Updated:\n",dateUpdated);
let [month, date, year] = (dateUpdated).toLocaleDateString().split("/")
document.getElementById("seller-created_at").innerHTML = "<span class='font-italic'>Account Creation Date: </span><mark>" + month + "/" + date + "/" + year + "</mark>";
document.getElementById("seller-username").innerHTML = "<span class='font-italic'>Username: </span>" + sellerInfo["username"];
}
/* Sets a status box on the page, new statuses override old. Statuses do not disappear.
* TODO
* add an 'x' button to statuses, or make they timeout on their own
* */
function setStatus(type, text) {
document.getElementById("statuses").innerHTML = "<div id=\"status-box\" class=\"alert "+type+" mt-3\" role=\"alert\">\n" +
text +
"</div>"
}
function propagateChart(inputDataPoints) {
'use strict'
feather.replace()
console.log("Input Data Points: ",inputDataPoints);
//make x-axis
let labels = [];
for (let i = 0; i < inputDataPoints.length; i++) {
labels.push("");
}
// Graphs
var ctx = document.getElementById('myChart')
// eslint-disable-next-line no-unused-vars
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
data: inputDataPoints,
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: false
}
}
})
}
function openSection(openMe) {
if (dataGrabSuccess) {
console.log("Opening",openMe);
closeOtherSections(openMe);
} else console.log("Failed to Open: ",openMe,"condition's not met");
}
function closeOtherSections(keepOpen) {
//close all sections & remove active status
for (let i = 0; i < sectionListAndLinkID.length; i++) {
$(sectionListAndLinkID[i][0]).toggle(false);
document.getElementById(sectionListAndLinkID[i][1]).classList.remove("active");
}
//open keepOpen
$(keepOpen[0]).toggle(true);
document.getElementById(keepOpen[1]).classList.add("active");
}
//set the default section view
(function(){
closeOtherSections(sectionListAndLinkID[0]);
})();