Something that
might be a fact


Jan. 2024
Personal project
I have developed a web page which appears to be informative, however, it is a blend of both speculation and facts. The main objective of this short project was to navigate through various directions by using APIs. I provided assumptions regarding the gender of the dogs(fact) in images based on the dog species. I also provided the probability of the guesses made. This approach was taken in order to highlight the possibility of any erroneous information that may have been provided.

< VScode, API >















Process documentation




1. Refresh each time you press a button



<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<header>
<button id="startButton">START!</button>
</header>
<main id="main"></main>

<script>
let startBTN = document.getElementById("startButton")
let mainELEM = document.getElementById("main")
let cocktailURL = "https://api.thedogapi.com/v1/images/search?limit=5&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi"

let fetchCocktailData = () => {
console.info("CLICKED!")
fetch(cocktailURL)
.then((response) => response.json())
.then((payload) => {
//Below is the code for refreshing
mainELEM.innerHTML = "";
appendCocktailData(payload);
});
}

let appendCocktailData = (data) => {
let drName = data[0].id
let drImg = data[0].url

let nameHeader = document.createElement('h3')
nameHeader.innerText = drName
mainELEM.appendChild(nameHeader)

let imageHolder = document.createElement('img')
imageHolder.src = drImg
mainELEM.appendChild(imageHolder)
}
startBTN.addEventListener("click", fetchCocktailData)
</script>

</body>
</html>







2. Failed to get the color palette from the dog image


let startBTN = document.getElementById("startButton");
let mainELEM = document.getElementById("main");
let dogAPIURL = "https://api.thedogapi.com/v1/images/search?limit=1&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi";
let colormindAPIURL = "http://colormind.io/api/";


--------------------------------------------------------------------------------

I tried to create a color palette with a picture of a dog using Colormind's API, but I failed.


I tried to connect a new URL and request additional keywords inside, but I wasn't sure if it would handle those requirements. In documentation said it would make a color palette according to the input, but when I put this in my code, I got a lot of errors. I admitted that I couldn't solve it by myself.


I tried because there seemed to be some errors that would be solved by connecting to my local server, but I didn't earn much. It's more important to practice it first, so I looked for another API.






3. Trials to put facts about dogs








I used the Dog API because I thought I could take the subject consistently if I put in news or facts related to dogs. When I followed what was shown in the document, there were no errors, but the letters did not come out. 

In addition, the cocktail names used in the example code in the last class were replaced with Dogs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<header>
<button id="startButton">START!</button>
</header>
<main id="main"></main>

<script>
let startBTN = document.getElementById("startButton")
let mainELEM = document.getElementById("main")
let DogURL = "https://api.thedogapi.com/v1/images/search?limit=5&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi"

let NewsURL = "https://newsapi.org/v2/everything?q=Dog&from=2024-01-01&sortBy=popularity&apiKey=fe5611a2b5fd493486b788a97cfcb33e"
// let NewsAPIkey = "fe5611a2b5fd493486b788a97cfcb33e"
// let NewsDate = "date=2024-01-01"

let fetchDogData = () => {
console.info("CLICKED!")
fetch(DogURL)
.then((response) => response.json())
.then((payload) => {
mainELEM.innerHTML = "";
appendDogData(payload);
});
}

let appendDogData = (data) => {
let dName = data[0].id
let dImg = data[0].url

let nameHeader = document.createElement('h3')
nameHeader.innerText = dName
mainELEM.appendChild(nameHeader)

let imageHolder = document.createElement('img')
imageHolder.src = dImg
mainELEM.appendChild(imageHolder)
}
startBTN.addEventListener("click", fetchDogData)
</script>

</body>
</html>







I thought, "Is it because I'm getting the data, but is it just invisible?" so I added some feature. And to see if it's because there's really no news, if there's no news to show, I made a "No news articles found." appear.

When I refreshed, I found that I didn't really have the news to show. But the site was still running, so I looked through it again and found that there were two versions: V2 was no longer running, and they moved to V1. (Yes, it's really important to read it carefully.🥲)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<header>
<button id="startButton">START!</button>
</header>
<main id="main"></main>

<script>
let startBTN = document.getElementById("startButton");
let mainELEM = document.getElementById("main");
let dogURL = "https://api.thedogapi.com/v1/images/search?limit=1&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi";
let newsURL = "https://newsapi.org/v2/everything?q=Dog&from=2024-01-01&sortBy=popularity&apiKey=fe5611a2b5fd493486b788a97cfcb33e";

let fetchDogAndNewsData = async () => {
console.info("CLICKED!");

try {
// Fetch dog data
const dogResponse = await fetch(dogURL);
const dogData = await dogResponse.json();

// Fetch news data
const newsResponse = await fetch(newsURL);
const newsData = await newsResponse.json();

// Clear existing content before appending new content
mainELEM.innerHTML = "";

// Append dog data
appendDogData(dogData);

// Append news data
appendNewsData(newsData);
} catch (error) {
console.error("Error fetching data:", error);
}
};

let appendDogData = (data) => {
let dName = data[0].id;
let dImg = data[0].url;

let nameHeader = document.createElement('h3');
nameHeader.innerText = dName;
mainELEM.appendChild(nameHeader);

let imageHolder = document.createElement('img');
imageHolder.src = dImg;
mainELEM.appendChild(imageHolder);
};

let appendNewsData = (data) => {
if (data.articles && data.articles.length > 0) {
let newsContainer = document.createElement('div');

data.articles.forEach((article) => {
let articleDiv = document.createElement('div');
articleDiv.innerHTML = `
<h4>${article.title}</h4>
<p>${article.description}</p>
<a href="${article.url}" target="_blank">Read more</a>
`;
newsContainer.appendChild(articleDiv);
});

mainELEM.appendChild(newsContainer);
} else {
let noNewsMessage = document.createElement('p');
noNewsMessage.innerText = "No news articles found.";
mainELEM.appendChild(noNewsMessage);
}
};

startBTN.addEventListener("click", fetchDogAndNewsData);
</script>
</body>
</html>



<script>
let startBTN = document.getElementById("startButton");
let mainELEM = document.getElementById("main");
let dogURL = "https://api.thedogapi.com/v1/images/search?limit=1&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi";
let newsURL = "https://dogapi.dog/api/v1/facts?number=1&raw=true";


Some parts had functions that changed as it changed to V2. First, I modified the most important URL and checked that the contents were visible under the picture.









4. Showing events related to dogs





Lastly, I thought it would be good to show dog-related events, so I searched for related APIs. Among them, I found a Ticketmaster API that can be used for free. And I succeeded in implementing the function by reading the provided document carefully. However, it seems that only related events can be searched using the Keyword function, so I added keyword= Dogs to the URL, but the event that came out did not seem to have much to do with dogs. I thought, should I use the filtering function rather than the search function? I'm rereading the document to see if this is possible.
<script>
let startBTN = document.getElementById("startButton");
let mainELEM = document.getElementById("main");
let dogURL = "https://api.thedogapi.com/v1/images/search?limit=1&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi";
let newsURL = "https://dogapi.dog/api/v1/facts?number=1&raw=true";
let eventURL = "https://app.ticketmaster.com/discovery/v2/events.json?size=1&keyword=Dogs&apikey=07SgF9aCMxWo5fDeVAtuUwy6Ws6HkGIG";


try {
// Fetch dog data
const dogResponse = await fetch(dogURL);
const dogData = await dogResponse.json();

// Fetch news data
const newsResponse = await fetch(newsURL);

// Separate fetching and processing news data
const newsText = await newsResponse.text();

// Fetch event data
const eventResponse = await fetch(eventURL);
const eventData = await eventResponse.json();

// Clear existing content before appending new content
mainELEM.innerHTML = "";

// Append dog data
appendDogData(dogData);

// Append news data
appendNewsData(newsText);


// Append event data
appendEventData(eventData);
} catch (error) {
console.error("Error fetching data:", error);
}
};

let appendEventData = (data) => {
let eventContainer = document.createElement('div');
let eventDiv = document.createElement('div');

if (data._embedded && data._embedded.events && data._embedded.events.length > 0) {
const event = data._embedded.events[0];
eventDiv.innerHTML = `
<h3>${event.name}</h3>
<p>${event.dates.start.localDate}</p>
<p>${event._embedded.venues[0].name}, ${event._embedded.venues[0].city.name}</p>
`;
} else {
eventDiv.innerHTML = `<p>No dog events found.</p>`;
}





5. Tiny visual adjustments




I was able to see the entire webpage thanks to the success of putting 3 APIs on it. I made a few changes to resize text and images, and I modified the code to make the ID of the image to be invisible because it doesn't need to be shown.
<style>
#main {
font-size: 10px; /* Set your desired font size in pixels */
}

p {
font-size: 4em; /* Set your desired font size using em units */
}

.event-info {
font-size: 2em;
/* Set the font size for event-related information */
}
</style>





6. Failed to get dog image that got Fav


let favURL = "https://api.thedogapi.com/v1/favourites?limit=5&sub_id=user-demo-0.00040560561710663&order=DESC&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi"

I modified the URL because I thought I had found the sub-id. I needed to use only pictures of puppies that received Fav. But it didn't work properly, maybe because it was a demo ID.






7. Using Alert


// Display breed namealert(`Breed: ${breedData.name}`);
} else {
// Handle the case where the breed information is not available
alert('Breed information not available.');
return;
}

Instead, I found a dog's species in the data I received from dogAPI and made it appear as a notification.





8. Linked Genderize.io API



<script>
let startBTN = document.getElementById("startButton");
let mainELEM = document.getElementById("main");
let dogURL = "https://api.thedogapi.com/v1/images/search?limit=1&api_key=live_FbJiRE07BFOn6pdKyPNjPsunZBwQQcT3JID6s1MmACb0DrTiEVsomB2xLZ3hSfKi";
let breedURL = "https://api.thedogapi.com/v1/breeds/";
let genderizeURL = "https://api.genderize.io?name=";
let eventURL = "https://app.ticketmaster.com/discovery/v2/events.json?size=1&keyword=Dogs&apikey=07SgF9aCMxWo5fDeVAtuUwy6Ws6HkGIG";




Then I discovered and put in an API that predicts gender according to the name of the species. It uses breed name to guess the gender.




// Map data between 1 and 10
const randomProbability = Math.floor(Math.random() * 10) + 1;


I then mapped the probability value between 1 and 10.





9. Troubleshooting NewsAPI



<Before>


<After>

// Fetch news data
const newsResponse = await fetch("https://dogapi.dog/api/v2/facts?limit=2");
const newsData = await newsResponse.json();

// Log the newsData to inspect its structure
console.log("News Data:", newsData);

let appendNewsData = (newsData) => {
let newsContainer = document.createElement('div');
let newsDiv = document.createElement('div');

// Check if newsData has the expected structure
if (newsData.data && Array.isArray(newsData.data) && newsData.data.length > 0) {
newsDiv.innerHTML = "<h3>News</h3>";
newsData.data.forEach(newsItem => {
const newsText = newsItem.attributes.body || "No news available.";
newsDiv.innerHTML += `<p>${newsText}</p>`;
});
} else {
newsDiv.innerHTML = `<p>No news available.</p>`;
}

newsContainer.appendChild(newsDiv);
mainELEM.appendChild(newsContainer);
};


During the work, I found that the factual part about the dog was missing and added it.






10. Adding CSS





if (newsData.data && Array.isArray(newsData.data) && newsData.data.length > 0) { newsDiv.innerHTML =
` <div class="text-info news-info">
<p class="text-label news-label">Maybe:</p>
<div class="text-container news-content">
<p class="text-content">${newsData.data[0].attributes.body}</p> </div> </div> `;


<CSS>
body { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; font-family: 'Inter', sans-serif; background: #fff; /* White background for the body */ }

    #main { display: flex; /* Use flexbox layout */ flex-direction: row; /* Arrange children in a row */ align-items: flex-start; /* Align items to the start of the cross axis */ justify-content: space-between; /* Distribute extra space evenly */ width: 80%; /* Adjust width to your preference */ max-width: 1000px; /* Maximum width of the main container */ margin: 20px; /* Margin around the main container */ }

    .image-placeholder { width: 300px; /* Width for the image placeholder */ height: 300px; /* Height for the image placeholder */ background-color: #ccc; /* Gray background for the image placeholder */ border-radius: 10px; /* Rounded corners for the image placeholder */ }

    .text-container { display: flex; /* Use flexbox layout for text content */ flex-direction: column; /* Arrange children in a column */ width: 100%; /* Take up remaining space */ padding-left: 20px; /* Padding between image and text */ }

    .text-info { display: flex; justify-content: flex-start; align-items: center; margin: 10px 0; /* Adjusted margin for spacing between text items */ }

    .text-label { color: #636363; /* Change color to match News */ font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0; width: 100px; }
   
    .text-content { color: #636363; font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0 10px; /* Adjusted margin for spacing between label and content */ }

    .text-info.news-info { margin: 10px 0; /* Adjusted margin for spacing between text items */ }

    .text-label.news-label { color: #636363; /* Change color to match News */ font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0; width: 100px; }

    .text-content.news-content { color: #636363; font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0 10px; /* Adjusted margin for spacing between label and content */ }  

    .news-section { display: flex; flex-direction: row; align-items: flex-start; /* Align items to the top */ margin: 10px 0; /* Adjusted margin for spacing between text items */ }

    .text-label.news-label { color: #636363; /* Change color to match News */ font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0; width: 100px; }

    .text-container.news-content { display: flex; flex-direction: column; margin-left: 10px; /* Adjusted margin for spacing between label and content */ }

    .text-info.news-info { margin: 10px 0; /* Adjusted margin for spacing between text items */ }

    #startButton { font-size: 1em; padding: 10px 20px; cursor: pointer; border: none; border-radius: 20px; background-color: #DE6161; color: white; outline: none; transition: background-color 0.3s ease; align-self: center; /* Align button to the center */ margin-top: 20px; }

    #startButton:hover { background-color: #c24e4e; }

    @media (max-width: 768px) { #main { flex-direction: column; } .image-placeholder { margin-bottom: 20px; }
    .text-container { padding-left: 0; /* Reset padding for small screens */ } }

    body { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; font-family: 'Inter', sans-serif; background: #fff; }

    #main { display: flex; flex-direction: column; /* Change to column layout */ align-items: center; /* Center align children */ width: 80%; max-width: 1000px; margin: 20px; }

    .image-placeholder { width: 300px; height: 300px; background-color: #ccc; border-radius: 10px; }

    .text-container { display: flex; flex-direction: column; width: 100%; padding-left: 20px; }

    .text-info { display: flex; justify-content: flex-start; align-items: center; margin: 10px 0; }

    .text-label { color: #636363; font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0; width: 100px; }

    .text-content { color: #636363; font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0 10px; }


    .text-info.news-info { margin: 10px 0; }

    .text-label.news-label { color: #636363; font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0; width: 100px; }

    .text-content.news-content { color: #636363; font-family: 'Inter', sans-serif; font-size: 16px; font-style: normal; font-weight: 400; margin: 0 10px; } 

    .news-section { display: flex; flex-direction: column; /* Change to column layout */ align-items: center; /* Center align children */ margin: 10px 0; } /* Rest of your CSS styles here */





Seoul, South Korea