From a7bed53c8fe4247d7ac977bb908a56b37d4ad90c Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Fri, 17 Feb 2023 18:06:18 +0000 Subject: [PATCH 1/4] Setting up GitHub Classroom Feedback From 1d689fcd79672def7d6def9849a3f48e99576a5f Mon Sep 17 00:00:00 2001 From: mironovisa Date: Sat, 18 Feb 2023 18:13:57 +0200 Subject: [PATCH 2/4] Milestones 1-4 --- company.html | 49 ++++++++++++++ css/style.css | 106 +++++++++++++++++++++++++++++++ favicon.png | Bin 0 -> 364 bytes images/logo.png | Bin 0 -> 27038 bytes index.html | 57 +++++++++++++++++ js/company.js | 99 +++++++++++++++++++++++++++++ js/script.js | 137 ++++++++++++++++++++++++++++++++++++++++ js/script_milestone1.js | 41 ++++++++++++ 8 files changed, 489 insertions(+) create mode 100644 company.html create mode 100644 css/style.css create mode 100644 favicon.png create mode 100644 images/logo.png create mode 100644 index.html create mode 100644 js/company.js create mode 100644 js/script.js create mode 100644 js/script_milestone1.js diff --git a/company.html b/company.html new file mode 100644 index 0000000..74d46be --- /dev/null +++ b/company.html @@ -0,0 +1,49 @@ + + + + + + + + + + Company Info + + + + +

+
+
+
+
+
+
+
+
+ +
+ + + diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..8a66f08 --- /dev/null +++ b/css/style.css @@ -0,0 +1,106 @@ +html { + font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; +} +body { + margin: 0px; + height: 1vh; + color: white; +} + +html { + background-color: #2b2b2b; + color: white; + border: none; +} +a, +li, +ul, +h1 { + color: white !important; + text-decoration: none !important; + font-weight: 400; +} + +input { + background-color: #2b2b2b; + color: white; + border: none; +} +button { + margin-top: 10px !important; + background-color: #2b2b2b; + border: none; + color: white; +} +p:not() { + color: white; + display: none; +} +#loading { +} +input { + border: 1px white solid; + border-radius: 10px; +} +#searchDiv { + background-color: #ffd829; + height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +.text-success:after { + content: ""; + display: inline-block; + width: 0; + height: 0; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 5px solid green; + margin-left: 5px; + transform: rotate(42deg); +} +.text-danger:after { + content: ""; + display: inline-block; + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 6px solid red; + margin-left: 5px; + transform: rotate(4deg); +} +#chartContainer { + height: 500px; + width: 500px; +} +.ticker-container { + overflow: hidden; + white-space: nowrap; + height: 15px; +} + +.ticker-list { + display: inline-block; + margin: 0; + padding: 0; + animation: ticker 10000s linear infinite; +} + +@keyframes ticker { + 0% { + transform: translateY(0); + } + 100% { + transform: translateY(-100%); + } +} + +@media (max-width: 767px) { + #searchDiv { + height: 10em; + } +} diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..27ac658321c02693418d405932d10da4703a6ab2 GIT binary patch literal 364 zcmV-y0h9iTP)Px$CP_p=R5(wqlf6qqVHAg-_a-GxX+wiUU_<886h?zXHAO8Efi*RRvxp%?i_pg+ zE;bbe>Co5*2rdx?EkQ%%6iMPgpbnylzHxaqF>j#P&V0^ue&?Lu5t8Er5c|Lg{Y4ez zp^%(ZOcb|TRds;uuW@I#F<@;9VoNHsAt6_SWCkwZ;a59jfNur@bKp;dCctHf@H}J- zuyGBw#*d7@0lTxXc-7WBYJqznq&^|?YyzN{EI8nH9VX&XSF`l4K+o2IauD3-kS&@3 z3<(98K7%hafaOU@tb*edntSYh1e+C}w&CIpqAvzZ9M&M@f%q$|IAPBNp$9d$Yh0c6 zF%LT_<&9>v71*ti-h{0?aE`%|x6??84BUKlnf70-Jm@nG_RimT(|28x37iK20000< KMNUMnLSTZ}Ym}=1 literal 0 HcmV?d00001 diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f87dcf6731bd19de8ff486530de0529fb8482a7c GIT binary patch literal 27038 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

xS!T}E;pgrUZaYWa>~g&$f*kFZAb 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

95bvS{wn+XDslz*kgyJ23=9#nG%W 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..b15715c --- /dev/null +++ b/index.html @@ -0,0 +1,57 @@ + + + + + + + + + + .dotstocks.com + + + +
+
+
+

.your_search_results:

+

loading...

+
+
+

.search_NASDAQ_stocks:

+ + +
+
+
+ +
+ + + + + diff --git a/js/company.js b/js/company.js new file mode 100644 index 0000000..12d496e --- /dev/null +++ b/js/company.js @@ -0,0 +1,99 @@ +const queryParamOfThePage = new URLSearchParams(window.location.search).get( + "symbol" +); +const endPointLink = `https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/company/profile/${queryParamOfThePage}`; +const chartEndPointLink = `https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/historical-price-full/${queryParamOfThePage}?serietype=line`; + +const infoDiv = document.getElementById("infoDiv"); +const companyNameDiv = document.getElementById("companyName"); +const companyUrlDiv = document.getElementById("companyUrl"); +const companyDescriptionDiv = document.getElementById("companyDescription"); +const companyPriceDiv = document.getElementById("companyPrice"); +const companyChangeDiv = document.getElementById("companyChanges"); +const chartDraw = document.getElementById("myChart").getContext("2d"); + +const h1 = document.getElementById("h1"); +h1.textContent = `Info about ${queryParamOfThePage}`; + +fetch(endPointLink) + .then((response) => response.json()) + .then((data) => { + let changesNegPoz = + data.profile.changesPercentage > 0 ? "text-success" : "text-danger"; + companyNameDiv.innerHTML = `Company Name: ${data.profile.companyName}`; + companyPriceDiv.innerHTML = `Price: ${data.profile.price}$`; + companyChangeDiv.innerHTML = `Latest Changes: ${data.profile.changesPercentage}`; + companyUrlDiv.innerHTML = `URL: ${data.profile.website}`; + companyDescriptionDiv.innerHTML = `Description: ${data.profile.description}`; + const logoImg = document.createElement("img"); + logoImg.src = `${data.profile.image}`; + logoImg.alt = "Company Logo"; + logoImg.width = 100; + logoImg.height = 100; + logoImg.style.float = "right"; + infoDiv.appendChild(logoImg); + }) + .catch((error) => console.error(error)); + +async function loadData() { + try { + const response = await fetch(chartEndPointLink); + const data = await response.json(); + const prices = data.historical.map((d) => d.close); + const dates = data.historical.map((d) => d.date); + const chart = new Chart(chartDraw, { + type: "bar", + data: { + labels: dates, + datasets: [ + { + label: "Close", + data: prices, + backgroundColor: "rgba(255,99,132,0.2)", + borderColor: "rgba(255,99,132,1)", + borderwidth: 0.5, + borderWidth: 1, + pointRadius: 2, + pointHoverRadius: 4, + }, + ], + }, + options: { + scales: { + y: { + beginAtZero: true, + }, + }, + }, + }); + } catch (error) { + console.error(error); + } +} + +loadData(); + +const tickerList = document.querySelector(".ticker-list"); +function MarqueeList() { + const tickerEndpoint = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/quotes/nyse?exchange=NASDAQ"; + fetch(tickerEndpoint) + .then((response) => response.json()) + .then((data) => { + data.forEach((item) => { + const changesNegPoz = + item.changesPercentage > 0 ? "text-success" : "text-danger"; + const listItem = document.createElement("li"); + listItem.innerHTML = ` + ${item.symbol}: ${item.price} (${item.changesPercentage}%) + + `; + tickerList.appendChild(listItem); + }); + }) + .catch((error) => { + console.error("Error fetching ticker data:", error); + }); +} + +MarqueeList(); diff --git a/js/script.js b/js/script.js new file mode 100644 index 0000000..1232342 --- /dev/null +++ b/js/script.js @@ -0,0 +1,137 @@ +let searchBoxValue = document.getElementById("searchBox"); +const searchButton = document.getElementById("searchButton"); +const resultsDiv = document.getElementById("resultsDiv"); +const loaderP = document.getElementById("loading"); + +document.addEventListener("DOMContentLoaded", function (event) { + document.querySelectorAll("img").forEach(function (img) { + img.onerror = function () { + this.style.display = "none"; + }; + }); +}); + +showLoader = () => { + loaderP.style.display = "unset"; +}; + +hideloader = () => { + loaderP.style.display = "none"; +}; +queryAdress = () => { + window.location.search = `query=${searchBoxValue.value}`; +}; +let timeout = 0; + +function getNameAndSymbol(name) { + let endpoint = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/search?query=" + + name + + "&limit=10&exchange=NASDAQ"; + resultsDiv.innerHTML = "

.your_search_results:

"; + return fetch(endpoint) + .then((response) => response.json()) + .then((data) => { + let promises = []; + for (let i = 0; i < 10; i++) { + let clearedsymbol; + let symbol = data[i].symbol; + let imageUrl = ""; + let promise = fetch( + `https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/company/profile/${data[i].symbol}` + ) + .then((response) => response.json()) + .then((data) => { + let changesNegPoz = + data.profile.changesPercentage > 0 + ? "text-success" + : "text-danger"; + const pEls = resultsDiv.querySelectorAll("div p"); + pEls[i].textContent = `Change: ${data.profile.changesPercentage}%`; + pEls[i].classList.add(changesNegPoz); + if (data.profile.changesPercentage > 0) { + pEls[i].innerHTML += ` `; + } else if (data.profile.changesPercentage < 0) { + pEls[i].innerHTML += ` `; + } + imageUrl = data.profile.image; + + const imgEl = resultsDiv.querySelector( + `img[data-symbol="${symbol}"]` + ); + if (imgEl) { + if (imageUrl) { + imgEl.src = imageUrl; + } else { + return; + } + } + const firstPEl = resultsDiv.querySelectorAll("p"); + if (firstPEl) { + firstPEl.textContent = `Changes Percentage: ${data.profile.changesPercentage}%`; + firstPEl.classList.add(changesNegPoz); + const triangleIcon = document.createElement("span"); + triangleIcon.classList.add("triangle"); + triangleIcon.classList.add( + data.profile.changesPercentage > 0 ? "positive" : "negative" + ); + firstPEl.appendChild(triangleIcon); + } + }) + .catch((error) => (imgEl.style.display = "none")); //how to bring it to work ); + promises.push(promise); + resultsDiv.innerHTML += ` + + `; + } + return Promise.all(promises); + }) + .catch((error) => console.log(error)); +} + +endpointFunction = () => { + clearTimeout(timeout); + timeout = setTimeout(async () => { + showLoader(); + await getNameAndSymbol(searchBoxValue.value); + hideloader(); + }, 500); +}; + +bothFunctions = () => { + endpointFunction(); +}; + +searchButton.addEventListener("click", endpointFunction, queryAdress); +searchBoxValue.addEventListener("keyup", endpointFunction); + +const tickerList = document.querySelector(".ticker-list"); +function MarqueeList() { + const tickerEndpoint = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/quotes/nyse?exchange=NASDAQ"; + fetch(tickerEndpoint) + .then((response) => response.json()) + .then((data) => { + data.forEach((item) => { + const changesNegPoz = + item.changesPercentage > 0 ? "text-success" : "text-danger"; + const listItem = document.createElement("li"); + listItem.innerHTML = ` + ${item.symbol}: ${item.price} (${item.changesPercentage}%) + + `; + tickerList.appendChild(listItem); + }); + }) + .catch((error) => { + console.error("Error fetching ticker data:", error); + }); +} + +MarqueeList(); diff --git a/js/script_milestone1.js b/js/script_milestone1.js new file mode 100644 index 0000000..c95185d --- /dev/null +++ b/js/script_milestone1.js @@ -0,0 +1,41 @@ +let searchBoxValue = document.getElementById("searchBox"); +const searchButton = document.getElementById("searchButton"); +const resultsDiv = document.getElementById("resultsDiv"); +showLoader = () => { + document.getElementById("loading").style.display = "unset"; +}; +hideloader = () => { + document.getElementById("loading").style.display = "none"; +}; +endpointFunction = () => { + showLoader(); + let endpoint = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/search?query=" + + searchBoxValue.value + + "&limit=10&exchange=NASDAQ"; + async function getNameAndSymbol() { + await fetch(endpoint) + .then((response) => response.json()) + .then((data) => { + console.log(data); + console.log(data.length); + resultsDiv.innerHTML = ""; + for (let i = 0; i < 10; i++) { + resultsDiv.innerHTML += `${data[i].name}, (${data[i].symbol})

`; + } + }) + .catch((error) => console.log("error")); + } + hideloader(); + getNameAndSymbol(); +}; + +searchButton.addEventListener("click", endpointFunction); + +/*Questions! +1. Why isn't searchButton.addEventListener working while being in the beginning of the page? +2. How can I make endpointFunction more lovely, what can I get rid of? +3. How to work with showLoader and hideloader functions in a better way? + + +*/ From 8ce529b2cd2239634e29ab92662e8e3270a3fdfc Mon Sep 17 00:00:00 2001 From: mironovisa Date: Tue, 7 Mar 2023 17:34:46 +0200 Subject: [PATCH 3/4] Milestones 5-7 --- index.html | 9 ++--- js/marquee.js | 24 +++++++++++++ js/script.js | 42 +++++----------------- js/searchForm.js | 32 +++++++++++++++++ js/searchResults.js | 86 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 39 deletions(-) create mode 100644 js/marquee.js create mode 100644 js/searchForm.js create mode 100644 js/searchResults.js diff --git a/index.html b/index.html index b15715c..5d7c18b 100644 --- a/index.html +++ b/index.html @@ -47,11 +47,8 @@

.search_NASDAQ_stocks:

- - + + + diff --git a/js/marquee.js b/js/marquee.js new file mode 100644 index 0000000..cf73348 --- /dev/null +++ b/js/marquee.js @@ -0,0 +1,24 @@ +const tickerList = document.querySelector(".ticker-list"); +function MarqueeList() { + const tickerEndpoint = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/quotes/nyse?exchange=NASDAQ"; + fetch(tickerEndpoint) + .then((response) => response.json()) + .then((data) => { + data.forEach((item) => { + const changesNegPoz = + item.changesPercentage > 0 ? "text-success" : "text-danger"; + const listItem = document.createElement("li"); + listItem.innerHTML = ` + ${item.symbol}: ${item.price} (${item.changesPercentage}%) + + `; + tickerList.appendChild(listItem); + }); + }) + .catch((error) => { + console.error("Error fetching ticker data:", error); + }); +} + +MarqueeList(); diff --git a/js/script.js b/js/script.js index 1232342..d589ddb 100644 --- a/js/script.js +++ b/js/script.js @@ -2,6 +2,8 @@ let searchBoxValue = document.getElementById("searchBox"); const searchButton = document.getElementById("searchButton"); const resultsDiv = document.getElementById("resultsDiv"); const loaderP = document.getElementById("loading"); +const baseUrl = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3"; document.addEventListener("DOMContentLoaded", function (event) { document.querySelectorAll("img").forEach(function (img) { @@ -15,10 +17,10 @@ showLoader = () => { loaderP.style.display = "unset"; }; -hideloader = () => { +hideLoader = () => { loaderP.style.display = "none"; }; -queryAdress = () => { +queryAddress = () => { window.location.search = `query=${searchBoxValue.value}`; }; let timeout = 0; @@ -34,7 +36,6 @@ function getNameAndSymbol(name) { .then((data) => { let promises = []; for (let i = 0; i < 10; i++) { - let clearedsymbol; let symbol = data[i].symbol; let imageUrl = ""; let promise = fetch( @@ -95,43 +96,18 @@ function getNameAndSymbol(name) { .catch((error) => console.log(error)); } -endpointFunction = () => { +autoSearchDebounce = () => { clearTimeout(timeout); timeout = setTimeout(async () => { showLoader(); await getNameAndSymbol(searchBoxValue.value); - hideloader(); + hideLoader(); }, 500); }; bothFunctions = () => { - endpointFunction(); + autoSearchDebounce(); }; -searchButton.addEventListener("click", endpointFunction, queryAdress); -searchBoxValue.addEventListener("keyup", endpointFunction); - -const tickerList = document.querySelector(".ticker-list"); -function MarqueeList() { - const tickerEndpoint = - "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/quotes/nyse?exchange=NASDAQ"; - fetch(tickerEndpoint) - .then((response) => response.json()) - .then((data) => { - data.forEach((item) => { - const changesNegPoz = - item.changesPercentage > 0 ? "text-success" : "text-danger"; - const listItem = document.createElement("li"); - listItem.innerHTML = ` - ${item.symbol}: ${item.price} (${item.changesPercentage}%) - - `; - tickerList.appendChild(listItem); - }); - }) - .catch((error) => { - console.error("Error fetching ticker data:", error); - }); -} - -MarqueeList(); +searchButton.addEventListener("click", autoSearchDebounce, queryAddress); +searchBoxValue.addEventListener("keyup", autoSearchDebounce); diff --git a/js/searchForm.js b/js/searchForm.js new file mode 100644 index 0000000..e83e255 --- /dev/null +++ b/js/searchForm.js @@ -0,0 +1,32 @@ +let searchBoxValue = document.getElementById("searchBox"); +const searchButton = document.getElementById("searchButton"); +const resultsDiv = document.getElementById("resultsDiv"); +const loaderP = document.getElementById("loading"); + +showLoader = () => { + loaderP.style.display = "unset"; +}; + +hideLoader = () => { + loaderP.style.display = "none"; +}; +queryAddress = () => { + window.location.search = `query=${searchBoxValue.value}`; +}; +let timeout = 0; + +autoSearchDebounce = () => { + clearTimeout(timeout); + timeout = setTimeout(async () => { + showLoader(); + await getNameAndSymbol(searchBoxValue.value); + hideLoader(); + }, 500); +}; + +bothFunctions = () => { + autoSearchDebounce(); +}; + +searchButton.addEventListener("click", autoSearchDebounce, queryAddress); +searchBoxValue.addEventListener("keyup", autoSearchDebounce); diff --git a/js/searchResults.js b/js/searchResults.js new file mode 100644 index 0000000..26fb88a --- /dev/null +++ b/js/searchResults.js @@ -0,0 +1,86 @@ +const baseUrl = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3"; + +function highlightText(text, searchTerm) { + const regex = new RegExp(searchTerm, "gi"); + return text.replace(regex, (match) => `${match}`); +} + +function getNameAndSymbol(name) { + let endpoint = `${baseUrl}/search?query=${name}&limit=10&exchange=NASDAQ`; + resultsDiv.innerHTML = "

.your_search_results:

"; + return fetch(endpoint) + .then((response) => response.json()) + .then((data) => { + let promises = []; + for (let i = 0; i < 10; i++) { + let symbol = data[i].symbol; + let imageUrl = ""; + let promise = fetch( + `https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/company/profile/${data[i].symbol}` + ) + .then((response) => response.json()) + .then((data) => { + let changesNegPoz = + data.profile.changesPercentage > 0 + ? "text-success" + : "text-danger"; + const pEls = resultsDiv.querySelectorAll("div p"); + pEls[i].textContent = `Change: ${data.profile.changesPercentage}%`; + pEls[i].classList.add(changesNegPoz); + if (data.profile.changesPercentage > 0) { + pEls[i].innerHTML += ` `; + } else if (data.profile.changesPercentage < 0) { + pEls[i].innerHTML += ` `; + } + imageUrl = data.profile.image; + + const imgEl = resultsDiv.querySelector( + `img[data-symbol="${symbol}"]` + ); + if (imgEl) { + if (imageUrl) { + imgEl.src = imageUrl; + } else { + return; + } + } + const firstPEl = resultsDiv.querySelectorAll("p")[0]; + if (firstPEl) { + firstPEl.innerHTML = `Changes Percentage: ${highlightText( + data.profile.changesPercentage + "%", + name + )}`; + firstPEl.classList.add(changesNegPoz); + const triangleIcon = document.createElement("span"); + triangleIcon.classList.add("triangle"); + triangleIcon.classList.add( + data.profile.changesPercentage > 0 ? "positive" : "negative" + ); + firstPEl.appendChild(triangleIcon); + } + const nameEl = resultsDiv.querySelectorAll("div a")[i]; + const nameText = nameEl.textContent; + nameEl.innerHTML = highlightText(nameText, name); + }) + .catch((error) => (imgEl.style.display = "none")); + promises.push(promise); + resultsDiv.innerHTML += ` + + `; + } + return Promise.all(promises); + }) + .catch((error) => console.log(error)); +} From 6a702fd062cd50b541c58b15fe81a3c631f19d44 Mon Sep 17 00:00:00 2001 From: mironovisa Date: Wed, 15 Mar 2023 13:45:10 +0200 Subject: [PATCH 4/4] Updated Milestones 5,6,7 --- js/marquee.js | 49 +++++++++------ js/searchForm.js | 65 +++++++++++-------- js/searchResults.js | 150 +++++++++++++++++++++----------------------- 3 files changed, 139 insertions(+), 125 deletions(-) diff --git a/js/marquee.js b/js/marquee.js index cf73348..127197f 100644 --- a/js/marquee.js +++ b/js/marquee.js @@ -1,24 +1,33 @@ -const tickerList = document.querySelector(".ticker-list"); -function MarqueeList() { - const tickerEndpoint = - "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/quotes/nyse?exchange=NASDAQ"; - fetch(tickerEndpoint) - .then((response) => response.json()) - .then((data) => { - data.forEach((item) => { - const changesNegPoz = - item.changesPercentage > 0 ? "text-success" : "text-danger"; - const listItem = document.createElement("li"); - listItem.innerHTML = ` - ${item.symbol}: ${item.price} (${item.changesPercentage}%) - - `; - tickerList.appendChild(listItem); +class MarqueeList { + constructor() { + this.tickerList = document.querySelector(".ticker-list"); + this.tickerEndpoint = + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/quotes/nyse?exchange=NASDAQ"; + this.fetchData(); + } + + fetchData() { + fetch(this.tickerEndpoint) + .then((response) => response.json()) + .then((data) => { + this.renderData(data); + }) + .catch((error) => { + console.error("Error fetching ticker data:", error); }); - }) - .catch((error) => { - console.error("Error fetching ticker data:", error); + } + + renderData(data) { + data.forEach((item) => { + const changesNegPoz = + item.changesPercentage > 0 ? "text-success" : "text-danger"; + const listItem = document.createElement("li"); + listItem.innerHTML = ` + ${item.symbol}: ${item.price} (${item.changesPercentage}%) + `; + this.tickerList.appendChild(listItem); }); + } } -MarqueeList(); +new MarqueeList(); diff --git a/js/searchForm.js b/js/searchForm.js index e83e255..998862a 100644 --- a/js/searchForm.js +++ b/js/searchForm.js @@ -1,32 +1,43 @@ -let searchBoxValue = document.getElementById("searchBox"); -const searchButton = document.getElementById("searchButton"); -const resultsDiv = document.getElementById("resultsDiv"); -const loaderP = document.getElementById("loading"); +class SearchForm { + constructor(searchBox, searchButton, loader) { + this.searchBox = searchBox; + this.searchButton = searchButton; + this.loader = loader; + this.timeout = 0; -showLoader = () => { - loaderP.style.display = "unset"; -}; + this.searchButton.addEventListener("click", () => { + this.autoSearchDebounce(); + this.queryAddress(); + }); + this.searchBox.addEventListener("keyup", () => this.autoSearchDebounce()); + } -hideLoader = () => { - loaderP.style.display = "none"; -}; -queryAddress = () => { - window.location.search = `query=${searchBoxValue.value}`; -}; -let timeout = 0; + showLoader() { + this.loader.style.display = "unset"; + } -autoSearchDebounce = () => { - clearTimeout(timeout); - timeout = setTimeout(async () => { - showLoader(); - await getNameAndSymbol(searchBoxValue.value); - hideLoader(); - }, 500); -}; + hideLoader() { + this.loader.style.display = "none"; + } -bothFunctions = () => { - autoSearchDebounce(); -}; + queryAddress() { + window.location.search = `query=${this.searchBox.value}`; + } -searchButton.addEventListener("click", autoSearchDebounce, queryAddress); -searchBoxValue.addEventListener("keyup", autoSearchDebounce); + autoSearchDebounce() { + clearTimeout(this.timeout); + this.timeout = setTimeout(async () => { + this.showLoader(); + await searchResults.getNameAndSymbol(this.searchBox.value); + this.hideLoader(); + }, 500); + } +} + +document.addEventListener("DOMContentLoaded", () => { + const searchBox = document.getElementById("searchBox"); + const searchButton = document.getElementById("searchButton"); + const loader = document.getElementById("loading"); + + new SearchForm(searchBox, searchButton, loader); +}); diff --git a/js/searchResults.js b/js/searchResults.js index 26fb88a..14a3dc2 100644 --- a/js/searchResults.js +++ b/js/searchResults.js @@ -1,86 +1,80 @@ -const baseUrl = - "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3"; +class SearchResults { + constructor(resultsDiv, baseUrl) { + this.resultsDiv = resultsDiv; + this.baseUrl = baseUrl; + } -function highlightText(text, searchTerm) { - const regex = new RegExp(searchTerm, "gi"); - return text.replace(regex, (match) => `${match}`); -} + highlightText(text, query) { + const regex = new RegExp(`(${query})`, "gi"); + return text.replace(regex, "$1"); + } -function getNameAndSymbol(name) { - let endpoint = `${baseUrl}/search?query=${name}&limit=10&exchange=NASDAQ`; - resultsDiv.innerHTML = "

.your_search_results:

"; - return fetch(endpoint) - .then((response) => response.json()) - .then((data) => { + async getNameAndSymbol(name) { + let endpoint = `${this.baseUrl}/search?query=${name}&limit=10&exchange=NASDAQ`; + this.resultsDiv.innerHTML = "

.your_search_results:

"; + try { + const response = await fetch(endpoint); + const data = await response.json(); let promises = []; for (let i = 0; i < 10; i++) { let symbol = data[i].symbol; - let imageUrl = ""; - let promise = fetch( - `https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3/company/profile/${data[i].symbol}` - ) - .then((response) => response.json()) - .then((data) => { - let changesNegPoz = - data.profile.changesPercentage > 0 - ? "text-success" - : "text-danger"; - const pEls = resultsDiv.querySelectorAll("div p"); - pEls[i].textContent = `Change: ${data.profile.changesPercentage}%`; - pEls[i].classList.add(changesNegPoz); - if (data.profile.changesPercentage > 0) { - pEls[i].innerHTML += ` `; - } else if (data.profile.changesPercentage < 0) { - pEls[i].innerHTML += ` `; - } - imageUrl = data.profile.image; + let highlightedName = this.highlightText(data[i].name, name); + let highlightedSymbol = this.highlightText(symbol, name); + promises.push(this.fetchSymbolData(symbol, i)); + this.resultsDiv.innerHTML += ` + + `; + } + await Promise.all(promises); + } catch (error) { + console.log(error); + } + } - const imgEl = resultsDiv.querySelector( - `img[data-symbol="${symbol}"]` - ); - if (imgEl) { - if (imageUrl) { - imgEl.src = imageUrl; - } else { - return; - } - } - const firstPEl = resultsDiv.querySelectorAll("p")[0]; - if (firstPEl) { - firstPEl.innerHTML = `Changes Percentage: ${highlightText( - data.profile.changesPercentage + "%", - name - )}`; - firstPEl.classList.add(changesNegPoz); - const triangleIcon = document.createElement("span"); - triangleIcon.classList.add("triangle"); - triangleIcon.classList.add( - data.profile.changesPercentage > 0 ? "positive" : "negative" - ); - firstPEl.appendChild(triangleIcon); - } - const nameEl = resultsDiv.querySelectorAll("div a")[i]; - const nameText = nameEl.textContent; - nameEl.innerHTML = highlightText(nameText, name); - }) - .catch((error) => (imgEl.style.display = "none")); - promises.push(promise); - resultsDiv.innerHTML += ` - - `; + async fetchSymbolData(symbol, index) { + try { + const response = await fetch(`${this.baseUrl}/company/profile/${symbol}`); + const data = await response.json(); + let changesNegPoz = + data.profile.changesPercentage > 0 ? "text-success" : "text-danger"; + const pEls = this.resultsDiv.querySelectorAll("div p"); + pEls[index].textContent = `Change: ${data.profile.changesPercentage}%`; + pEls[index].classList.add(changesNegPoz); + if (data.profile.changesPercentage > 0) { + pEls[index].innerHTML += ` `; + } else if (data.profile.changesPercentage < 0) { + pEls[index].innerHTML += ` `; + } + const imgEl = this.resultsDiv.querySelector( + `img[data-symbol="${symbol}"]` + ); + if (imgEl) { + imgEl.src = data.profile.image; } - return Promise.all(promises); - }) - .catch((error) => console.log(error)); + } catch (error) { + const imgEl = this.resultsDiv.querySelector( + `img[data-symbol="${symbol}"]` + ); + imgEl.style.display = "none"; + } + } } + +const searchResults = new SearchResults( + document.getElementById("resultsDiv"), + "https://stock-exchange-dot-full-stack-course-services.ew.r.appspot.com/api/v3" +); + +document.addEventListener("DOMContentLoaded", function (event) { + document.querySelectorAll("img").forEach(function (img) { + img.onerror = function () { + this.style.display = "none"; + }; + }); +});